From 2c4a1330ce754797cde552b5dd4beee7fe886f91 Mon Sep 17 00:00:00 2001 From: Littlegnal <8847263+littleGnAl@users.noreply.github.com> Date: Mon, 21 Feb 2022 22:30:17 +0800 Subject: [PATCH] feat: Support flutter desktop (#600) --- .github/workflows/build.yml | 128 +- .gitmodules | 6 + .metadata | 4 +- .pubignore | 1 + CHANGELOG.md | 34 + CONTRIBUTING.md | 18 +- README.md | 175 +- README.zh.md | 127 +- analysis_options.yaml | 2 + android/build.gradle | 14 +- android/gradle.properties | 1 - .../main/java/io/agora/rtc/base/.gitignore | 1 - .../java/io/agora/rtc/base/Annotations.java | 991 -- .../java/io/agora/rtc/base/BeanCovertor.kt | 271 - .../main/java/io/agora/rtc/base/Callback.kt | 41 - .../java/io/agora/rtc/base/EnumCovertor.kt | 97 - .../main/java/io/agora/rtc/base/Extensions.kt | 172 - .../java/io/agora/rtc/base/MediaObserver.kt | 40 - .../main/java/io/agora/rtc/base/RtcChannel.kt | 486 - .../java/io/agora/rtc/base/RtcChannelEvent.kt | 443 - .../main/java/io/agora/rtc/base/RtcEngine.kt | 1379 -- .../java/io/agora/rtc/base/RtcEngineEvent.kt | 718 - .../java/io/agora/rtc/base/RtcSurfaceView.kt | 112 - .../java/io/agora/rtc/base/RtcTextureView.kt | 86 - .../agora_rtc_engine/AgoraPlatformView.kt | 82 + .../agora_rtc_engine/AgoraRtcChannelPlugin.kt | 71 +- .../agora_rtc_engine/AgoraRtcEnginePlugin.kt | 185 +- .../AgoraSurfaceViewFactory.kt | 111 +- .../AgoraTextureViewFactory.kt | 87 +- .../agora/agora_rtc_engine/ResultCallback.kt | 16 - ci/run_flutter_integration_test.sh | 15 + ci/run_flutter_macos_integration_test.sh | 22 + example/.gitignore | 6 +- example/.metadata | 4 +- example/README.md | 32 +- example/README.zh.md | 17 +- example/android/.gitignore | 4 + example/android/app/build.gradle | 8 +- .../android/app/src/main/AndroidManifest.xml | 4 +- .../app/src/main/res/values/styles.xml | 10 +- .../RtcEnginePluginTest.kt | 168 +- example/android/build.gradle | 4 +- example/android/gradle.properties | 1 - .../gradle/wrapper/gradle-wrapper.properties | 2 +- example/android/settings.gradle | 4 - .../audio_mixing/Agora.io-Interactions.mp3 | Bin 0 -> 2437297 bytes example/ios/Podfile | 2 + example/ios/Runner.xcodeproj/project.pbxproj | 109 +- .../xcshareddata/xcschemes/Runner.xcscheme | 2 +- example/ios/Runner/AppDelegate.swift | 1 + .../RunnerTests/FakeAgoraRtcEngineKit.swift | 3 - example/ios/RunnerTests/RunnerTests.swift | 177 +- example/lib/config/agora.config.dart | 23 +- .../advanced/audio_mixing/audio_mixing.dart | 262 + .../channel_media_relay.dart | 176 +- .../device_manager/device_manager.dart | 207 + example/lib/examples/advanced/index.dart | 34 +- .../join_multiple_channel.dart | 133 +- .../rtmp_streaming/rtmp_streaming.dart | 266 + .../screen_sharing/screen_sharing.dart | 251 + .../set_encryption/set_encryption.dart | 199 + .../set_video_encoder_configuration.dart | 241 + .../stream_message/stream_message.dart | 123 +- .../advanced/voice_changer/voice_changer.dart | 699 +- .../join_channel_audio.dart | 136 +- .../join_channel_video.dart | 99 +- .../examples/basic/string_uid/string_uid.dart | 43 +- example/lib/examples/log_sink.dart | 164 + example/lib/main.dart | 11 +- example/linux/flutter/CMakeLists.txt | 3 + example/macos/Flutter/Flutter-Debug.xcconfig | 2 +- .../macos/Flutter/Flutter-Release.xcconfig | 2 +- .../Flutter/GeneratedPluginRegistrant.swift | 2 + example/macos/Podfile | 2 + .../macos/Runner.xcodeproj/project.pbxproj | 68 +- .../xcshareddata/xcschemes/Runner.xcscheme | 14 +- .../xcshareddata/WorkspaceSettings.xcsettings | 8 + example/macos/Runner/Configs/AppInfo.xcconfig | 2 +- .../macos/Runner/DebugProfile.entitlements | 10 + example/macos/Runner/Info.plist | 4 + example/macos/Runner/Release.entitlements | 12 + ...agora_rtc_engine_exampleDebug.entitlements | 0 .../custom_capture_audio_api.dart | 0 example/pubspec.yaml | 3 +- example/web/AgoraRtcWrapper.bundle.js | 2 + example/web/index.html | 1 + example/windows/flutter/CMakeLists.txt | 2 + .../flutter/generated_plugin_registrant.cc | 3 + .../windows/flutter/generated_plugins.cmake | 1 + example/windows/runner/Runner.rc | 2 +- integration_test_app/.gitignore | 46 + integration_test_app/.metadata | 10 + integration_test_app/README.md | 16 + integration_test_app/analysis_options.yaml | 29 + integration_test_app/android/.gitignore | 14 + integration_test_app/android/app/build.gradle | 83 + .../android/app/src/debug/AndroidManifest.xml | 7 + .../android/app/src/main/AndroidManifest.xml | 42 + .../integration_test_app/MainActivity.kt | 12 + .../TestRtcEnginePlugin.kt | 63 + .../res/drawable-v21/launch_background.xml | 12 + .../main/res/drawable/launch_background.xml | 12 + .../src/main/res/mipmap-hdpi/ic_launcher.png | Bin 0 -> 544 bytes .../src/main/res/mipmap-mdpi/ic_launcher.png | Bin 0 -> 442 bytes .../src/main/res/mipmap-xhdpi/ic_launcher.png | Bin 0 -> 721 bytes .../main/res/mipmap-xxhdpi/ic_launcher.png | Bin 0 -> 1031 bytes .../main/res/mipmap-xxxhdpi/ic_launcher.png | Bin 0 -> 1443 bytes .../app/src/main/res/values-night/styles.xml | 18 + .../app/src/main/res/values/styles.xml | 18 + .../app/src/profile/AndroidManifest.xml | 7 + integration_test_app/android/build.gradle | 29 + .../android/gradle.properties | 3 + .../gradle/wrapper/gradle-wrapper.properties | 6 + .../android/libs/x86_64/libAgoraRtcWrapper.so | Bin 0 -> 2788008 bytes integration_test_app/android/settings.gradle | 11 + .../agora_render_view_smoke_test.dart | 444 + .../agora_rtc_channel_api_test.dart | 901 ++ ...ra_rtc_channel_event_handler_api_test.dart | 993 ++ ..._rtc_channel_event_handler_smoke_test.dart | 9 + ...el_event_handler_smoke_test.generated.dart | 853 ++ ...ora_rtc_device_manager_api_smoke_test.dart | 41 + ...vice_manager_api_smoke_test.generated.dart | 662 + .../agora_rtc_engine_api_smoke_test.dart | 231 + .../agora_rtc_engine_api_test.dart | 3279 +++++ ...ora_rtc_engine_event_handler_api_test.dart | 1773 +++ ...a_rtc_engine_event_handler_smoke_test.dart | 10 + ...ne_event_handler_smoke_test.generated.dart | 2326 ++++ ..._rtc_engine_subprocess_api_smoke_test.dart | 10 + ...e_subprocess_api_smoke_test.generated.dart | 4244 ++++++ .../rtc_engine_plugin_test.dart | 86 + integration_test_app/ios/.gitignore | 33 + .../ios/Flutter/AppFrameworkInfo.plist | 26 + .../ios/Flutter/Debug.xcconfig | 2 + .../ios/Flutter/Release.xcconfig | 2 + integration_test_app/ios/Podfile | 51 + .../ios/Runner.xcodeproj/project.pbxproj | 557 + .../contents.xcworkspacedata | 7 + .../xcshareddata/IDEWorkspaceChecks.plist | 8 + .../xcshareddata/WorkspaceSettings.xcsettings | 8 + .../xcshareddata/xcschemes/Runner.xcscheme | 91 + .../contents.xcworkspacedata | 10 + .../xcshareddata/IDEWorkspaceChecks.plist | 8 + .../xcshareddata/WorkspaceSettings.xcsettings | 8 + .../ios/Runner/AppDelegate.swift | 16 + .../AppIcon.appiconset/Contents.json | 122 + .../Icon-App-1024x1024@1x.png | Bin 0 -> 10932 bytes .../AppIcon.appiconset/Icon-App-20x20@1x.png | Bin 0 -> 564 bytes .../AppIcon.appiconset/Icon-App-20x20@2x.png | Bin 0 -> 1283 bytes .../AppIcon.appiconset/Icon-App-20x20@3x.png | Bin 0 -> 1588 bytes .../AppIcon.appiconset/Icon-App-29x29@1x.png | Bin 0 -> 1025 bytes .../AppIcon.appiconset/Icon-App-29x29@2x.png | Bin 0 -> 1716 bytes .../AppIcon.appiconset/Icon-App-29x29@3x.png | Bin 0 -> 1920 bytes .../AppIcon.appiconset/Icon-App-40x40@1x.png | Bin 0 -> 1283 bytes .../AppIcon.appiconset/Icon-App-40x40@2x.png | Bin 0 -> 1895 bytes .../AppIcon.appiconset/Icon-App-40x40@3x.png | Bin 0 -> 2665 bytes .../AppIcon.appiconset/Icon-App-60x60@2x.png | Bin 0 -> 2665 bytes .../AppIcon.appiconset/Icon-App-60x60@3x.png | Bin 0 -> 3831 bytes .../AppIcon.appiconset/Icon-App-76x76@1x.png | Bin 0 -> 1888 bytes .../AppIcon.appiconset/Icon-App-76x76@2x.png | Bin 0 -> 3294 bytes .../Icon-App-83.5x83.5@2x.png | Bin 0 -> 3612 bytes .../LaunchImage.imageset/Contents.json | 23 + .../LaunchImage.imageset/LaunchImage.png | Bin 0 -> 68 bytes .../LaunchImage.imageset/LaunchImage@2x.png | Bin 0 -> 68 bytes .../LaunchImage.imageset/LaunchImage@3x.png | Bin 0 -> 68 bytes .../LaunchImage.imageset/README.md | 5 + .../Runner/Base.lproj/LaunchScreen.storyboard | 37 + .../ios/Runner/Base.lproj/Main.storyboard | 26 + integration_test_app/ios/Runner/Info.plist | 45 + .../ios/Runner/Runner-Bridging-Header.h | 10 + .../ios/Runner/TestRtcEnginePlugin.h | 11 + .../ios/Runner/TestRtcEnginePlugin.m | 57 + .../Info.plist | Bin 0 -> 720 bytes .../Resources/Info.plist | 44 + .../Versions/A/Resources/Info.plist | 44 + .../Versions/A/_CodeSignature/CodeResources | 128 + .../Versions/A/iris_integration_test | Bin 0 -> 332096 bytes .../Versions/Current/Resources/Info.plist | 44 + .../Current/_CodeSignature/CodeResources | 128 + .../Versions/Current/iris_integration_test | Bin 0 -> 332096 bytes .../iris_integration_test | Bin 0 -> 318800 bytes .../ios/Runner/iris_integration_test.podspec | 17 + .../iris_integration_test/.gitignore | 1 + .../iris_integration_test/.gitmodules | 3 + .../iris_integration_test/CMakeLists.txt | 123 + .../iris_integration_test/README.md | 2 + .../iris_integration_test/build-android.sh | 40 + .../iris_integration_test/build-ios.sh | 30 + .../iris_integration_test/build-macos.sh | 26 + .../iris_integration_test/ios.toolchain.cmake | 927 ++ .../src/fake_rtc_engine.h | 83 + .../src/fake_rtc_engine_internal.h | 575 + .../src/iris_rtc_engine_call_api_recorder.cc | 114 + .../src/iris_rtc_engine_call_api_recorder.h | 84 + ...is_rtc_engine_integration_test_delegate.cc | 221 + ...ris_rtc_engine_integration_test_delegate.h | 94 + ...is_rtc_engine_integration_test_helplers.cc | 114 + ...ris_rtc_engine_integration_test_helplers.h | 111 + .../src/rtc_event_handler_test.cc | 623 + .../src/rtc_event_handler_test.h | 25 + .../agora/rtc/include/AgoraAudioFrame.h | 276 + .../third_party/agora/rtc/include/AgoraBase.h | 805 ++ .../agora/rtc/include/AgoraConstants.h | 91 + .../agora/rtc/include/AgoraEnumerates.h | 2354 ++++ .../agora/rtc/include/AgoraLogWriter.h | 33 + .../agora/rtc/include/AgoraMediaIO.h | 301 + .../agora/rtc/include/AgoraMediaMetadata.h | 68 + .../agora/rtc/include/AgoraObjects.h | 1947 +++ .../agora/rtc/include/AgoraRtcChannel.h | 1604 +++ .../agora/rtc/include/AgoraRtcEngineKit.h | 6727 +++++++++ .../agora/rtc/include/AgoraVideoFrame.h | 280 + .../third_party/agora/rtc/include/IAgoraLog.h | 34 + .../agora/rtc/include/IAgoraMediaEngine.h | 1042 ++ .../agora/rtc/include/IAgoraRtcChannel.h | 1686 +++ .../agora/rtc/include/IAgoraRtcEngine.h | 11354 ++++++++++++++++ .../agora/rtc/include/IAgoraRtcEngine2.h | 52 + .../agora/rtc/include/IAgoraService.h | 73 + .../third_party/googletest | 1 + .../third_party/iris/iris_audio_processor.h | 30 + .../third_party/iris/iris_base.h | 140 + .../third_party/iris/iris_delegate.h | 33 + .../third_party/iris/iris_event_handler.h | 44 + .../third_party/iris/iris_media_base.h | 198 + .../third_party/iris/iris_rtc_base.h | 323 + .../third_party/iris/iris_rtc_c_api.h | 161 + .../third_party/iris/iris_rtc_channel.h | 76 + .../iris/iris_rtc_device_manager.h | 78 + .../third_party/iris/iris_rtc_engine.h | 78 + .../third_party/iris/iris_rtc_raw_data.h | 98 + .../iris/iris_rtc_raw_data_plugin.h | 90 + .../iris/iris_rtc_raw_data_plugin_manager.h | 52 + .../third_party/iris/iris_video_processor.h | 171 + .../unittest/CMakeLists.txt | 32 + ...ngine_integration_test_helpers_unittest.cc | 726 + .../iris_integration_test/unittest/main.cc | 6 + integration_test_app/lib/main.dart | 115 + integration_test_app/lib/src/configs.dart | 14 + .../lib/src/event_handler_tester.dart | 40 + .../lib/src/fake_iris_rtc_engine.dart | 630 + integration_test_app/macos/.gitignore | 6 + .../macos/Flutter/Flutter-Debug.xcconfig | 2 + .../macos/Flutter/Flutter-Release.xcconfig | 2 + .../Flutter/GeneratedPluginRegistrant.swift | 12 + integration_test_app/macos/Podfile | 44 + .../macos/Runner.xcodeproj/project.pbxproj | 619 + .../xcshareddata/IDEWorkspaceChecks.plist | 8 + .../xcshareddata/xcschemes/Runner.xcscheme | 89 + .../contents.xcworkspacedata | 10 + .../xcshareddata/IDEWorkspaceChecks.plist | 8 + .../macos/Runner/AppDelegate.swift | 9 + .../AppIcon.appiconset/Contents.json | 68 + .../AppIcon.appiconset/app_icon_1024.png | Bin 0 -> 46993 bytes .../AppIcon.appiconset/app_icon_128.png | Bin 0 -> 3276 bytes .../AppIcon.appiconset/app_icon_16.png | Bin 0 -> 1429 bytes .../AppIcon.appiconset/app_icon_256.png | Bin 0 -> 5933 bytes .../AppIcon.appiconset/app_icon_32.png | Bin 0 -> 1243 bytes .../AppIcon.appiconset/app_icon_512.png | Bin 0 -> 14800 bytes .../AppIcon.appiconset/app_icon_64.png | Bin 0 -> 1874 bytes .../macos/Runner/Base.lproj/MainMenu.xib | 339 + .../macos/Runner/Configs/AppInfo.xcconfig | 14 + .../macos/Runner/Configs/Debug.xcconfig | 2 + .../macos/Runner/Configs/Release.xcconfig | 2 + .../macos/Runner/Configs/Warnings.xcconfig | 13 + .../macos/Runner/DebugProfile.entitlements | 20 + integration_test_app/macos/Runner/Info.plist | 36 + .../macos/Runner/MainFlutterWindow.swift | 15 + .../macos/Runner/Release.entitlements | 18 + .../Resources/Info.plist | 44 + .../Versions/A/Resources/Info.plist | 44 + .../Versions/A/_CodeSignature/CodeResources | 128 + .../Versions/A/iris_integration_test | Bin 0 -> 338416 bytes .../Versions/Current/Resources/Info.plist | 44 + .../Current/_CodeSignature/CodeResources | 128 + .../Versions/Current/iris_integration_test | Bin 0 -> 338416 bytes .../iris_integration_test | Bin 0 -> 338416 bytes .../Runner/iris_integration_test.podspec | 17 + integration_test_app/macos/Runner/src | 1 + integration_test_app/pubspec.yaml | 92 + integration_test_app/test/widget_test.dart | 30 + .../integration_test_cases_generator.dart | 1337 ++ integration_test_app/windows/.gitignore | 17 + integration_test_app/windows/CMakeLists.txt | 100 + .../windows/flutter/CMakeLists.txt | 103 + .../flutter/generated_plugin_registrant.cc | 14 + .../flutter/generated_plugin_registrant.h | 15 + .../windows/flutter/generated_plugins.cmake | 16 + .../windows/runner/CMakeLists.txt | 18 + integration_test_app/windows/runner/Runner.rc | 121 + .../windows/runner/flutter_window.cpp | 61 + .../windows/runner/flutter_window.h | 33 + integration_test_app/windows/runner/main.cpp | 43 + .../windows/runner/resource.h | 16 + .../windows/runner/resources/app_icon.ico | Bin 0 -> 33772 bytes .../windows/runner/runner.exe.manifest | 20 + integration_test_app/windows/runner/utils.cpp | 64 + integration_test_app/windows/runner/utils.h | 19 + .../windows/runner/win32_window.cpp | 245 + .../windows/runner/win32_window.h | 98 + ios/Classes/AgoraRtcChannelPlugin.h | 10 + ios/Classes/AgoraRtcChannelPlugin.mm | 64 + ios/Classes/AgoraRtcChannelPlugin.swift | 89 - ios/Classes/AgoraRtcEnginePlugin.h | 2 +- ios/Classes/AgoraRtcEnginePlugin.m | 15 - ios/Classes/AgoraRtcEnginePlugin.mm | 120 + ios/Classes/AgoraSurfaceViewFactory.h | 14 + ios/Classes/AgoraSurfaceViewFactory.mm | 187 + ios/Classes/AgoraSurfaceViewFactory.swift | 105 - ios/Classes/AgoraTextureViewFactory.h | 14 + ios/Classes/AgoraTextureViewFactory.mm | 192 + ios/Classes/Base/.gitignore | 1 - ios/Classes/Base/AgoraRtcEngineKit.h | 119 - ios/Classes/Base/BeanCovertor.swift | 456 - ios/Classes/Base/Callback.swift | 41 - ios/Classes/Base/Extensions.swift | 208 - ios/Classes/Base/MediaObserver.swift | 49 - ios/Classes/Base/RtcChannel.swift | 403 - ios/Classes/Base/RtcChannelEvent.swift | 249 - ios/Classes/Base/RtcEngine.swift | 1228 -- ios/Classes/Base/RtcEngineEvent.swift | 536 - ios/Classes/Base/RtcEnginePlugin.h | 2 +- ios/Classes/Base/RtcEnginePluginRegistrant.h | 25 + ios/Classes/Base/RtcEnginePluginRegistrant.mm | 15 + .../Base/RtcEnginePluginRegistrant.swift | 22 - ios/Classes/Base/RtcEngineRegistry.h | 24 + ios/Classes/Base/RtcEngineRegistry.mm | 53 + ios/Classes/Base/RtcEngineRegistry.swift | 61 - ios/Classes/Base/RtcSurfaceView.swift | 98 - ios/Classes/CallApiMethodCallHandler.h | 24 + ios/Classes/CallApiMethodCallHandler.mm | 104 + ios/Classes/FlutterIrisEventHandler.h | 20 + ios/Classes/FlutterIrisEventHandler.mm | 130 + ios/Classes/ResultCallback.swift | 25 - ios/Classes/SwiftAgoraRtcEnginePlugin.swift | 99 - ios/agora_rtc_engine.podspec | 9 +- lib/agora_rtc_engine_web.dart | 225 +- lib/agora_rtc_engine_web.ng.dart | 1122 ++ lib/rtc_engine.dart | 3 +- lib/rtc_local_view.dart | 38 + lib/rtc_remote_view.dart | 10 +- lib/src/agora_media_recorder.dart | 124 + lib/src/api_types.dart | 256 + lib/src/classes.dart | 1589 ++- lib/src/classes.g.dart | 121 +- lib/src/enum_converter.dart | 39 +- lib/src/enum_converter.g.dart | 73 +- lib/src/enums.dart | 2671 ++-- lib/src/events.dart | 2414 ++-- lib/src/rtc_channel.dart | 1340 +- lib/src/rtc_device_manager.dart | 437 + lib/src/rtc_engine.dart | 4321 +++--- lib/src/rtc_engine_extension.dart | 176 +- lib/src/rtc_engine_extension_web.dart | 23 + lib/src/rtc_render_view.dart | 443 +- macos/Classes/AgoraRtcChannelPlugin.h | 7 + macos/Classes/AgoraRtcChannelPlugin.mm | 43 + macos/Classes/AgoraRtcDeviceManagerPlugin.h | 10 + macos/Classes/AgoraRtcDeviceManagerPlugin.mm | 54 + macos/Classes/AgoraRtcEnginePlugin.h | 4 + macos/Classes/AgoraRtcEnginePlugin.mm | 152 + macos/Classes/AgoraRtcEnginePlugin.swift | 19 - macos/Classes/AgoraTextureViewFactory.h | 9 + macos/Classes/AgoraTextureViewFactory.mm | 185 + macos/Classes/CallApiMethodCallHandler.h | 34 + macos/Classes/CallApiMethodCallHandler.mm | 133 + macos/Classes/File.swift | 2 + macos/Classes/FlutterIrisEventHandler.h | 20 + macos/Classes/FlutterIrisEventHandler.mm | 147 + macos/agora_rtc_engine.podspec | 24 +- pubspec.yaml | 17 +- scripts/build-internal-testing-macos.sh | 17 + scripts/build-internal-testing.sh | 23 + scripts/build-iris-all.sh | 14 + scripts/build-iris-android.sh | 21 + scripts/build-iris-ios.sh | 26 + scripts/build-iris-macos.sh | 21 + scripts/build-iris-windows.sh | 29 + web | 1 + windows/.gitignore | 3 + windows/CMakeLists.txt | 39 +- windows/PluginInfo.props | 14 - windows/agora_rtc_channel_plugin.cc | 164 + windows/agora_rtc_device_manager_plugin.cc | 134 + windows/agora_rtc_engine_plugin.cc | 257 + windows/agora_rtc_engine_plugin.cpp | 89 - windows/agora_rtc_engine_plugin.h | 23 - windows/agora_texture_view_factory.cc | 177 + windows/call_api_method_call_handler.cc | 114 + windows/cmake/DownloadSDK.cmake | 32 + .../agora_rtc_channel_plugin.h | 12 + .../agora_rtc_device_manager_plugin.h | 12 + .../agora_texture_view_factory.h | 67 + .../call_api_method_call_handler.h | 25 + windows/plugin.vcxproj | 247 - windows/plugin.vcxproj.filters | 45 - 393 files changed, 74521 insertions(+), 15018 deletions(-) create mode 100644 .gitmodules create mode 100644 .pubignore delete mode 100644 android/src/main/java/io/agora/rtc/base/.gitignore delete mode 100644 android/src/main/java/io/agora/rtc/base/Annotations.java delete mode 100644 android/src/main/java/io/agora/rtc/base/BeanCovertor.kt delete mode 100644 android/src/main/java/io/agora/rtc/base/Callback.kt delete mode 100644 android/src/main/java/io/agora/rtc/base/EnumCovertor.kt delete mode 100644 android/src/main/java/io/agora/rtc/base/Extensions.kt delete mode 100644 android/src/main/java/io/agora/rtc/base/MediaObserver.kt delete mode 100644 android/src/main/java/io/agora/rtc/base/RtcChannel.kt delete mode 100644 android/src/main/java/io/agora/rtc/base/RtcChannelEvent.kt delete mode 100644 android/src/main/java/io/agora/rtc/base/RtcEngine.kt delete mode 100644 android/src/main/java/io/agora/rtc/base/RtcEngineEvent.kt delete mode 100644 android/src/main/java/io/agora/rtc/base/RtcSurfaceView.kt delete mode 100644 android/src/main/java/io/agora/rtc/base/RtcTextureView.kt create mode 100644 android/src/main/kotlin/io/agora/agora_rtc_engine/AgoraPlatformView.kt delete mode 100644 android/src/main/kotlin/io/agora/agora_rtc_engine/ResultCallback.kt create mode 100644 ci/run_flutter_integration_test.sh create mode 100644 ci/run_flutter_macos_integration_test.sh create mode 100644 example/assets/audio_mixing/Agora.io-Interactions.mp3 create mode 100644 example/lib/examples/advanced/audio_mixing/audio_mixing.dart create mode 100644 example/lib/examples/advanced/device_manager/device_manager.dart create mode 100644 example/lib/examples/advanced/rtmp_streaming/rtmp_streaming.dart create mode 100644 example/lib/examples/advanced/screen_sharing/screen_sharing.dart create mode 100644 example/lib/examples/advanced/set_encryption/set_encryption.dart create mode 100644 example/lib/examples/advanced/set_video_encoder_configuration/set_video_encoder_configuration.dart create mode 100644 example/lib/examples/log_sink.dart create mode 100644 example/macos/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings create mode 100644 example/macos/Runner/agora_rtc_engine_exampleDebug.entitlements rename example/{lib/examples/advanced => pigeons}/custom_capture_audio/custom_capture_audio_api.dart (100%) create mode 100644 example/web/AgoraRtcWrapper.bundle.js create mode 100644 integration_test_app/.gitignore create mode 100644 integration_test_app/.metadata create mode 100644 integration_test_app/README.md create mode 100644 integration_test_app/analysis_options.yaml create mode 100644 integration_test_app/android/.gitignore create mode 100644 integration_test_app/android/app/build.gradle create mode 100644 integration_test_app/android/app/src/debug/AndroidManifest.xml create mode 100644 integration_test_app/android/app/src/main/AndroidManifest.xml create mode 100644 integration_test_app/android/app/src/main/kotlin/io/agora/integration_test_app/integration_test_app/MainActivity.kt create mode 100644 integration_test_app/android/app/src/main/kotlin/io/agora/integration_test_app/integration_test_app/TestRtcEnginePlugin.kt create mode 100644 integration_test_app/android/app/src/main/res/drawable-v21/launch_background.xml create mode 100644 integration_test_app/android/app/src/main/res/drawable/launch_background.xml create mode 100644 integration_test_app/android/app/src/main/res/mipmap-hdpi/ic_launcher.png create mode 100644 integration_test_app/android/app/src/main/res/mipmap-mdpi/ic_launcher.png create mode 100644 integration_test_app/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png create mode 100644 integration_test_app/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png create mode 100644 integration_test_app/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png create mode 100644 integration_test_app/android/app/src/main/res/values-night/styles.xml create mode 100644 integration_test_app/android/app/src/main/res/values/styles.xml create mode 100644 integration_test_app/android/app/src/profile/AndroidManifest.xml create mode 100644 integration_test_app/android/build.gradle create mode 100644 integration_test_app/android/gradle.properties create mode 100644 integration_test_app/android/gradle/wrapper/gradle-wrapper.properties create mode 100644 integration_test_app/android/libs/x86_64/libAgoraRtcWrapper.so create mode 100644 integration_test_app/android/settings.gradle create mode 100644 integration_test_app/integration_test/agora_render_view_smoke_test.dart create mode 100644 integration_test_app/integration_test/agora_rtc_channel_api_test.dart create mode 100644 integration_test_app/integration_test/agora_rtc_channel_event_handler_api_test.dart create mode 100644 integration_test_app/integration_test/agora_rtc_channel_event_handler_smoke_test.dart create mode 100644 integration_test_app/integration_test/agora_rtc_channel_event_handler_smoke_test.generated.dart create mode 100644 integration_test_app/integration_test/agora_rtc_device_manager_api_smoke_test.dart create mode 100644 integration_test_app/integration_test/agora_rtc_device_manager_api_smoke_test.generated.dart create mode 100644 integration_test_app/integration_test/agora_rtc_engine_api_smoke_test.dart create mode 100644 integration_test_app/integration_test/agora_rtc_engine_api_test.dart create mode 100644 integration_test_app/integration_test/agora_rtc_engine_event_handler_api_test.dart create mode 100644 integration_test_app/integration_test/agora_rtc_engine_event_handler_smoke_test.dart create mode 100644 integration_test_app/integration_test/agora_rtc_engine_event_handler_smoke_test.generated.dart create mode 100644 integration_test_app/integration_test/agora_rtc_engine_subprocess_api_smoke_test.dart create mode 100644 integration_test_app/integration_test/agora_rtc_engine_subprocess_api_smoke_test.generated.dart create mode 100644 integration_test_app/integration_test/rtc_engine_plugin_test.dart create mode 100644 integration_test_app/ios/.gitignore create mode 100644 integration_test_app/ios/Flutter/AppFrameworkInfo.plist create mode 100644 integration_test_app/ios/Flutter/Debug.xcconfig create mode 100644 integration_test_app/ios/Flutter/Release.xcconfig create mode 100644 integration_test_app/ios/Podfile create mode 100644 integration_test_app/ios/Runner.xcodeproj/project.pbxproj create mode 100644 integration_test_app/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata create mode 100644 integration_test_app/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist create mode 100644 integration_test_app/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings create mode 100644 integration_test_app/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme create mode 100644 integration_test_app/ios/Runner.xcworkspace/contents.xcworkspacedata create mode 100644 integration_test_app/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist create mode 100644 integration_test_app/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings create mode 100644 integration_test_app/ios/Runner/AppDelegate.swift create mode 100644 integration_test_app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json create mode 100644 integration_test_app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png create mode 100644 integration_test_app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png create mode 100644 integration_test_app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png create mode 100644 integration_test_app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png create mode 100644 integration_test_app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png create mode 100644 integration_test_app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png create mode 100644 integration_test_app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png create mode 100644 integration_test_app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png create mode 100644 integration_test_app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png create mode 100644 integration_test_app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png create mode 100644 integration_test_app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png create mode 100644 integration_test_app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png create mode 100644 integration_test_app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png create mode 100644 integration_test_app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png create mode 100644 integration_test_app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png create mode 100644 integration_test_app/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json create mode 100644 integration_test_app/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png create mode 100644 integration_test_app/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png create mode 100644 integration_test_app/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png create mode 100644 integration_test_app/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md create mode 100644 integration_test_app/ios/Runner/Base.lproj/LaunchScreen.storyboard create mode 100644 integration_test_app/ios/Runner/Base.lproj/Main.storyboard create mode 100644 integration_test_app/ios/Runner/Info.plist create mode 100644 integration_test_app/ios/Runner/Runner-Bridging-Header.h create mode 100644 integration_test_app/ios/Runner/TestRtcEnginePlugin.h create mode 100644 integration_test_app/ios/Runner/TestRtcEnginePlugin.m create mode 100644 integration_test_app/ios/Runner/iris_integration_test.framework/Info.plist create mode 100644 integration_test_app/ios/Runner/iris_integration_test.framework/Resources/Info.plist create mode 100644 integration_test_app/ios/Runner/iris_integration_test.framework/Versions/A/Resources/Info.plist create mode 100644 integration_test_app/ios/Runner/iris_integration_test.framework/Versions/A/_CodeSignature/CodeResources create mode 100755 integration_test_app/ios/Runner/iris_integration_test.framework/Versions/A/iris_integration_test create mode 100644 integration_test_app/ios/Runner/iris_integration_test.framework/Versions/Current/Resources/Info.plist create mode 100644 integration_test_app/ios/Runner/iris_integration_test.framework/Versions/Current/_CodeSignature/CodeResources create mode 100755 integration_test_app/ios/Runner/iris_integration_test.framework/Versions/Current/iris_integration_test create mode 100755 integration_test_app/ios/Runner/iris_integration_test.framework/iris_integration_test create mode 100644 integration_test_app/ios/Runner/iris_integration_test.podspec create mode 100644 integration_test_app/iris_integration_test/.gitignore create mode 100644 integration_test_app/iris_integration_test/.gitmodules create mode 100644 integration_test_app/iris_integration_test/CMakeLists.txt create mode 100644 integration_test_app/iris_integration_test/README.md create mode 100644 integration_test_app/iris_integration_test/build-android.sh create mode 100644 integration_test_app/iris_integration_test/build-ios.sh create mode 100644 integration_test_app/iris_integration_test/build-macos.sh create mode 100644 integration_test_app/iris_integration_test/ios.toolchain.cmake create mode 100644 integration_test_app/iris_integration_test/src/fake_rtc_engine.h create mode 100644 integration_test_app/iris_integration_test/src/fake_rtc_engine_internal.h create mode 100644 integration_test_app/iris_integration_test/src/iris_rtc_engine_call_api_recorder.cc create mode 100644 integration_test_app/iris_integration_test/src/iris_rtc_engine_call_api_recorder.h create mode 100644 integration_test_app/iris_integration_test/src/iris_rtc_engine_integration_test_delegate.cc create mode 100644 integration_test_app/iris_integration_test/src/iris_rtc_engine_integration_test_delegate.h create mode 100644 integration_test_app/iris_integration_test/src/iris_rtc_engine_integration_test_helplers.cc create mode 100644 integration_test_app/iris_integration_test/src/iris_rtc_engine_integration_test_helplers.h create mode 100644 integration_test_app/iris_integration_test/src/rtc_event_handler_test.cc create mode 100644 integration_test_app/iris_integration_test/src/rtc_event_handler_test.h create mode 100644 integration_test_app/iris_integration_test/third_party/agora/rtc/include/AgoraAudioFrame.h create mode 100644 integration_test_app/iris_integration_test/third_party/agora/rtc/include/AgoraBase.h create mode 100644 integration_test_app/iris_integration_test/third_party/agora/rtc/include/AgoraConstants.h create mode 100644 integration_test_app/iris_integration_test/third_party/agora/rtc/include/AgoraEnumerates.h create mode 100644 integration_test_app/iris_integration_test/third_party/agora/rtc/include/AgoraLogWriter.h create mode 100644 integration_test_app/iris_integration_test/third_party/agora/rtc/include/AgoraMediaIO.h create mode 100644 integration_test_app/iris_integration_test/third_party/agora/rtc/include/AgoraMediaMetadata.h create mode 100644 integration_test_app/iris_integration_test/third_party/agora/rtc/include/AgoraObjects.h create mode 100644 integration_test_app/iris_integration_test/third_party/agora/rtc/include/AgoraRtcChannel.h create mode 100644 integration_test_app/iris_integration_test/third_party/agora/rtc/include/AgoraRtcEngineKit.h create mode 100644 integration_test_app/iris_integration_test/third_party/agora/rtc/include/AgoraVideoFrame.h create mode 100644 integration_test_app/iris_integration_test/third_party/agora/rtc/include/IAgoraLog.h create mode 100644 integration_test_app/iris_integration_test/third_party/agora/rtc/include/IAgoraMediaEngine.h create mode 100644 integration_test_app/iris_integration_test/third_party/agora/rtc/include/IAgoraRtcChannel.h create mode 100644 integration_test_app/iris_integration_test/third_party/agora/rtc/include/IAgoraRtcEngine.h create mode 100755 integration_test_app/iris_integration_test/third_party/agora/rtc/include/IAgoraRtcEngine2.h create mode 100644 integration_test_app/iris_integration_test/third_party/agora/rtc/include/IAgoraService.h create mode 160000 integration_test_app/iris_integration_test/third_party/googletest create mode 100644 integration_test_app/iris_integration_test/third_party/iris/iris_audio_processor.h create mode 100644 integration_test_app/iris_integration_test/third_party/iris/iris_base.h create mode 100644 integration_test_app/iris_integration_test/third_party/iris/iris_delegate.h create mode 100644 integration_test_app/iris_integration_test/third_party/iris/iris_event_handler.h create mode 100644 integration_test_app/iris_integration_test/third_party/iris/iris_media_base.h create mode 100644 integration_test_app/iris_integration_test/third_party/iris/iris_rtc_base.h create mode 100644 integration_test_app/iris_integration_test/third_party/iris/iris_rtc_c_api.h create mode 100644 integration_test_app/iris_integration_test/third_party/iris/iris_rtc_channel.h create mode 100644 integration_test_app/iris_integration_test/third_party/iris/iris_rtc_device_manager.h create mode 100644 integration_test_app/iris_integration_test/third_party/iris/iris_rtc_engine.h create mode 100644 integration_test_app/iris_integration_test/third_party/iris/iris_rtc_raw_data.h create mode 100644 integration_test_app/iris_integration_test/third_party/iris/iris_rtc_raw_data_plugin.h create mode 100644 integration_test_app/iris_integration_test/third_party/iris/iris_rtc_raw_data_plugin_manager.h create mode 100644 integration_test_app/iris_integration_test/third_party/iris/iris_video_processor.h create mode 100644 integration_test_app/iris_integration_test/unittest/CMakeLists.txt create mode 100644 integration_test_app/iris_integration_test/unittest/iris_rtc_engine_integration_test_helpers_unittest.cc create mode 100644 integration_test_app/iris_integration_test/unittest/main.cc create mode 100644 integration_test_app/lib/main.dart create mode 100644 integration_test_app/lib/src/configs.dart create mode 100644 integration_test_app/lib/src/event_handler_tester.dart create mode 100644 integration_test_app/lib/src/fake_iris_rtc_engine.dart create mode 100644 integration_test_app/macos/.gitignore create mode 100644 integration_test_app/macos/Flutter/Flutter-Debug.xcconfig create mode 100644 integration_test_app/macos/Flutter/Flutter-Release.xcconfig create mode 100644 integration_test_app/macos/Flutter/GeneratedPluginRegistrant.swift create mode 100644 integration_test_app/macos/Podfile create mode 100644 integration_test_app/macos/Runner.xcodeproj/project.pbxproj create mode 100644 integration_test_app/macos/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist create mode 100644 integration_test_app/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme create mode 100644 integration_test_app/macos/Runner.xcworkspace/contents.xcworkspacedata create mode 100644 integration_test_app/macos/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist create mode 100644 integration_test_app/macos/Runner/AppDelegate.swift create mode 100644 integration_test_app/macos/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json create mode 100644 integration_test_app/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_1024.png create mode 100644 integration_test_app/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_128.png create mode 100644 integration_test_app/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_16.png create mode 100644 integration_test_app/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_256.png create mode 100644 integration_test_app/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_32.png create mode 100644 integration_test_app/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_512.png create mode 100644 integration_test_app/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_64.png create mode 100644 integration_test_app/macos/Runner/Base.lproj/MainMenu.xib create mode 100644 integration_test_app/macos/Runner/Configs/AppInfo.xcconfig create mode 100644 integration_test_app/macos/Runner/Configs/Debug.xcconfig create mode 100644 integration_test_app/macos/Runner/Configs/Release.xcconfig create mode 100644 integration_test_app/macos/Runner/Configs/Warnings.xcconfig create mode 100644 integration_test_app/macos/Runner/DebugProfile.entitlements create mode 100644 integration_test_app/macos/Runner/Info.plist create mode 100644 integration_test_app/macos/Runner/MainFlutterWindow.swift create mode 100644 integration_test_app/macos/Runner/Release.entitlements create mode 100644 integration_test_app/macos/Runner/iris_integration_test.framework/Resources/Info.plist create mode 100644 integration_test_app/macos/Runner/iris_integration_test.framework/Versions/A/Resources/Info.plist create mode 100644 integration_test_app/macos/Runner/iris_integration_test.framework/Versions/A/_CodeSignature/CodeResources create mode 100755 integration_test_app/macos/Runner/iris_integration_test.framework/Versions/A/iris_integration_test create mode 100644 integration_test_app/macos/Runner/iris_integration_test.framework/Versions/Current/Resources/Info.plist create mode 100644 integration_test_app/macos/Runner/iris_integration_test.framework/Versions/Current/_CodeSignature/CodeResources create mode 100755 integration_test_app/macos/Runner/iris_integration_test.framework/Versions/Current/iris_integration_test create mode 100755 integration_test_app/macos/Runner/iris_integration_test.framework/iris_integration_test create mode 100644 integration_test_app/macos/Runner/iris_integration_test.podspec create mode 120000 integration_test_app/macos/Runner/src create mode 100644 integration_test_app/pubspec.yaml create mode 100644 integration_test_app/test/widget_test.dart create mode 100644 integration_test_app/tools/integration_test_cases_generator.dart create mode 100644 integration_test_app/windows/.gitignore create mode 100644 integration_test_app/windows/CMakeLists.txt create mode 100644 integration_test_app/windows/flutter/CMakeLists.txt create mode 100644 integration_test_app/windows/flutter/generated_plugin_registrant.cc create mode 100644 integration_test_app/windows/flutter/generated_plugin_registrant.h create mode 100644 integration_test_app/windows/flutter/generated_plugins.cmake create mode 100644 integration_test_app/windows/runner/CMakeLists.txt create mode 100644 integration_test_app/windows/runner/Runner.rc create mode 100644 integration_test_app/windows/runner/flutter_window.cpp create mode 100644 integration_test_app/windows/runner/flutter_window.h create mode 100644 integration_test_app/windows/runner/main.cpp create mode 100644 integration_test_app/windows/runner/resource.h create mode 100644 integration_test_app/windows/runner/resources/app_icon.ico create mode 100644 integration_test_app/windows/runner/runner.exe.manifest create mode 100644 integration_test_app/windows/runner/utils.cpp create mode 100644 integration_test_app/windows/runner/utils.h create mode 100644 integration_test_app/windows/runner/win32_window.cpp create mode 100644 integration_test_app/windows/runner/win32_window.h create mode 100644 ios/Classes/AgoraRtcChannelPlugin.h create mode 100644 ios/Classes/AgoraRtcChannelPlugin.mm delete mode 100644 ios/Classes/AgoraRtcChannelPlugin.swift delete mode 100644 ios/Classes/AgoraRtcEnginePlugin.m create mode 100644 ios/Classes/AgoraRtcEnginePlugin.mm create mode 100644 ios/Classes/AgoraSurfaceViewFactory.h create mode 100644 ios/Classes/AgoraSurfaceViewFactory.mm delete mode 100644 ios/Classes/AgoraSurfaceViewFactory.swift create mode 100644 ios/Classes/AgoraTextureViewFactory.h create mode 100644 ios/Classes/AgoraTextureViewFactory.mm delete mode 100644 ios/Classes/Base/.gitignore delete mode 100644 ios/Classes/Base/AgoraRtcEngineKit.h delete mode 100644 ios/Classes/Base/BeanCovertor.swift delete mode 100644 ios/Classes/Base/Callback.swift delete mode 100644 ios/Classes/Base/Extensions.swift delete mode 100644 ios/Classes/Base/MediaObserver.swift delete mode 100644 ios/Classes/Base/RtcChannel.swift delete mode 100644 ios/Classes/Base/RtcChannelEvent.swift delete mode 100644 ios/Classes/Base/RtcEngine.swift delete mode 100644 ios/Classes/Base/RtcEngineEvent.swift create mode 100644 ios/Classes/Base/RtcEnginePluginRegistrant.h create mode 100644 ios/Classes/Base/RtcEnginePluginRegistrant.mm delete mode 100644 ios/Classes/Base/RtcEnginePluginRegistrant.swift create mode 100644 ios/Classes/Base/RtcEngineRegistry.h create mode 100644 ios/Classes/Base/RtcEngineRegistry.mm delete mode 100644 ios/Classes/Base/RtcEngineRegistry.swift delete mode 100644 ios/Classes/Base/RtcSurfaceView.swift create mode 100644 ios/Classes/CallApiMethodCallHandler.h create mode 100644 ios/Classes/CallApiMethodCallHandler.mm create mode 100644 ios/Classes/FlutterIrisEventHandler.h create mode 100644 ios/Classes/FlutterIrisEventHandler.mm delete mode 100644 ios/Classes/ResultCallback.swift delete mode 100644 ios/Classes/SwiftAgoraRtcEnginePlugin.swift create mode 100644 lib/agora_rtc_engine_web.ng.dart create mode 100644 lib/src/agora_media_recorder.dart create mode 100644 lib/src/api_types.dart create mode 100644 lib/src/rtc_device_manager.dart create mode 100644 lib/src/rtc_engine_extension_web.dart create mode 100644 macos/Classes/AgoraRtcChannelPlugin.h create mode 100644 macos/Classes/AgoraRtcChannelPlugin.mm create mode 100644 macos/Classes/AgoraRtcDeviceManagerPlugin.h create mode 100644 macos/Classes/AgoraRtcDeviceManagerPlugin.mm create mode 100644 macos/Classes/AgoraRtcEnginePlugin.h create mode 100644 macos/Classes/AgoraRtcEnginePlugin.mm delete mode 100644 macos/Classes/AgoraRtcEnginePlugin.swift create mode 100644 macos/Classes/AgoraTextureViewFactory.h create mode 100644 macos/Classes/AgoraTextureViewFactory.mm create mode 100644 macos/Classes/CallApiMethodCallHandler.h create mode 100644 macos/Classes/CallApiMethodCallHandler.mm create mode 100644 macos/Classes/File.swift create mode 100644 macos/Classes/FlutterIrisEventHandler.h create mode 100644 macos/Classes/FlutterIrisEventHandler.mm create mode 100644 scripts/build-internal-testing-macos.sh create mode 100644 scripts/build-internal-testing.sh create mode 100644 scripts/build-iris-all.sh create mode 100644 scripts/build-iris-android.sh create mode 100644 scripts/build-iris-ios.sh create mode 100644 scripts/build-iris-macos.sh create mode 100644 scripts/build-iris-windows.sh create mode 160000 web delete mode 100644 windows/PluginInfo.props create mode 100644 windows/agora_rtc_channel_plugin.cc create mode 100644 windows/agora_rtc_device_manager_plugin.cc create mode 100644 windows/agora_rtc_engine_plugin.cc delete mode 100644 windows/agora_rtc_engine_plugin.cpp delete mode 100644 windows/agora_rtc_engine_plugin.h create mode 100644 windows/agora_texture_view_factory.cc create mode 100644 windows/call_api_method_call_handler.cc create mode 100644 windows/cmake/DownloadSDK.cmake create mode 100644 windows/include/agora_rtc_engine/agora_rtc_channel_plugin.h create mode 100644 windows/include/agora_rtc_engine/agora_rtc_device_manager_plugin.h create mode 100644 windows/include/agora_rtc_engine/agora_texture_view_factory.h create mode 100644 windows/include/agora_rtc_engine/call_api_method_call_handler.h delete mode 100644 windows/plugin.vcxproj delete mode 100644 windows/plugin.vcxproj.filters diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 9aae8be88..05a2e36da 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -1,10 +1,23 @@ name: CI on: + # pull_request_target: + # types: [opened, synchronize] + # branches: + # - master + # # Temporarily allow check on dev/flutter2-iris branch + # - 'dev/flutter2-iris' + push: - branches: [ master ] + branches: + - master + # Temporarily allow check on dev/flutter2-iris branch + - 'dev/flutter2-iris' pull_request: - branches: [ master ] + branches: + - master + # Temporarily allow check on dev/flutter2-iris branch + - 'dev/flutter2-iris' jobs: # DO NOT run flutter test as this time, because the unit test is broken, will re-enable it @@ -19,13 +32,80 @@ jobs: # java-version: '11' # - uses: subosito/flutter-action@v1 # with: - # flutter-version: '2.5.3' + # flutter-version: '2.10.0' # - run: flutter pub get # - run: flutter test + integration_test_android: + name: Run Flutter Android Integration Tests + runs-on: macos-11 + timeout-minutes: 60 + env: + TEST_APP_ID: ${{ secrets.MY_APP_ID }} + steps: + - uses: actions/checkout@v1 + - uses: actions/setup-java@v1 + with: + java-version: '11' + - uses: subosito/flutter-action@v1 + with: + flutter-version: '2.10.0' + - name: run flutter android integration tests + uses: reactivecircus/android-emulator-runner@v2.21.0 + with: + api-level: 31 + arch: x86_64 + profile: Nexus 6 + script: bash ci/run_flutter_integration_test.sh + + integration_test_ios: + name: Run Flutter iOS Integration Tests + runs-on: macos-11 + timeout-minutes: 60 + env: + TEST_APP_ID: ${{ secrets.MY_APP_ID }} + steps: + - uses: actions/checkout@v1 + - uses: subosito/flutter-action@v1 + with: + flutter-version: '2.10.0' + - uses: futureware-tech/simulator-action@v1 + with: + model: 'iPhone 13 Pro Max' + - run: bash ci/run_flutter_integration_test.sh + + integration_test_macos: + name: Run Flutter macOS Integration Tests + runs-on: macos-11 + timeout-minutes: 60 + env: + TEST_APP_ID: ${{ secrets.MY_APP_ID }} + steps: + - uses: actions/checkout@v1 + - uses: subosito/flutter-action@v1 + with: + flutter-version: '2.10.0' + - run: flutter config --enable-macos-desktop + - run: bash ci/run_flutter_macos_integration_test.sh + + integration_test_windows: + name: Run Flutter Windows Integration Tests + runs-on: windows-2019 + timeout-minutes: 60 + env: + TEST_APP_ID: ${{ secrets.MY_APP_ID }} + steps: + - uses: actions/checkout@v1 + - uses: subosito/flutter-action@v1 + with: + flutter-version: '2.10.0' + - run: flutter config --enable-windows-desktop + - run: bash ci/run_flutter_macos_integration_test.sh + unittest_android: name: Run Android Unit Test runs-on: ubuntu-latest + timeout-minutes: 60 steps: - uses: actions/checkout@v1 - uses: actions/setup-java@v1 @@ -33,47 +113,47 @@ jobs: java-version: '11' - uses: subosito/flutter-action@v1 with: - flutter-version: '2.5.3' + flutter-version: '2.10.0' - run: flutter pub get - run: bash ci/run_android_test.sh unittest_ios: name: Run iOS Unit Test runs-on: macos-11 + timeout-minutes: 60 steps: - uses: actions/checkout@v1 - uses: subosito/flutter-action@v1 with: - flutter-version: '2.5.3' + flutter-version: '2.10.0' - run: flutter pub get - run: bash ci/run_ios_test.sh - # Temporay disable the android build since it will fail cause by - # "No toolchains found in the NDK toolchains folder for ABI with prefix: arm-linux-androideabi" error on ci. - # This issue can be refer: https://github.com/gradle/gradle/issues/12440#issuecomment-606188282 - # TODO(littlegnal): Upgrade the AGP version to solve this issue, and re-enable this build. - # build_android: - # name: Build Android - # runs-on: ubuntu-latest - # steps: - # - uses: actions/checkout@v1 - # - uses: actions/setup-java@v1 - # with: - # java-version: '11' - # with: - # flutter-version: '2.5.3' - # - run: flutter pub get - # - name: Run flutter build apk - # run: flutter build apk - # working-directory: example + + build_android: + name: Build Android + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v1 + - uses: actions/setup-java@v1 + with: + java-version: '11' + - uses: subosito/flutter-action@v1 + with: + flutter-version: '2.10.0' + - run: flutter pub get + - name: Run flutter build apk + run: flutter build apk + working-directory: example build_ios: name: Build iOS runs-on: macos-11 + timeout-minutes: 60 steps: - uses: actions/checkout@v1 - uses: subosito/flutter-action@v1 with: - flutter-version: '2.5.3' + flutter-version: '2.10.0' - run: flutter pub get - name: Run flutter build ios --no-codesign run: flutter build ios --no-codesign diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 000000000..f143fb338 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,6 @@ +[submodule "web"] + path = web + url = https://github.com/AgoraIO-Community/Iris-Rtc-Web.git +[submodule "integration_test_app/iris_integration_test/third_party/googletest"] + path = integration_test_app/iris_integration_test/third_party/googletest + url = https://github.com/google/googletest.git diff --git a/.metadata b/.metadata index fbc1f3952..4d5f4ab5f 100644 --- a/.metadata +++ b/.metadata @@ -4,7 +4,7 @@ # This file should be version controlled and should not be manually edited. version: - revision: 5391447fae6209bb21a89e6a5a6583cac1af9b4b - channel: beta + revision: c5a4b4029c0798f37c4a39b479d7cb75daa7b05c + channel: stable project_type: plugin diff --git a/.pubignore b/.pubignore new file mode 100644 index 000000000..8afce0990 --- /dev/null +++ b/.pubignore @@ -0,0 +1 @@ +integration_test_app/ \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index 5d67f6253..2283f7d4d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -75,6 +75,20 @@ * add RtcEngineContext instead of RtcEngineConfig ([5dd294f](https://github.com/AgoraIO/Flutter-SDK/commit/5dd294fa95799dcc19d69775c19a13aeed61e2a2)) * support native SDK 3.4.5 ([d1d8433](https://github.com/AgoraIO/Flutter-SDK/commit/d1d84330c9fcc1367cfe8160fe8c6d593c7bac9c)) +# [4.1.0-alpha.2](https://github.com/AgoraIO/Flutter-SDK/compare/v4.1.0-alpha.1...v4.1.0-alpha.2) (2021-06-16) + + +### Bug Fixes + +* web build error ([8c57eae](https://github.com/AgoraIO/Flutter-SDK/commit/8c57eae792e3d02cedeb52b87c5350e65a6be7f9)) + +# [4.1.0-alpha.1](https://github.com/AgoraIO/Flutter-SDK/compare/v4.1.0-alpha.0...v4.1.0-alpha.1) (2021-06-16) + + +### Features + +* support screen share for desktop + ## [4.0.2](https://github.com/AgoraIO/Flutter-SDK/compare/v4.0.1...v4.0.2) (2021-06-09) @@ -83,6 +97,26 @@ * Android build error ([3af4476](https://github.com/AgoraIO/Flutter-SDK/commit/3af44762ad765cde99024e2b080d4c88f34cfc09)) * enum type cast bug, close [#345](https://github.com/AgoraIO/Flutter-SDK/issues/345) ([85d720d](https://github.com/AgoraIO/Flutter-SDK/commit/85d720d1f13a7ff340419135a9d397be798b750f)) +# [4.1.0-alpha.0](https://github.com/AgoraIO/Flutter-SDK/compare/v4.0.1...v4.1.0-alpha.0) (2021-06-04) + + +### Bug Fixes + +* Android build error ([3af4476](https://github.com/AgoraIO/Flutter-SDK/commit/3af44762ad765cde99024e2b080d4c88f34cfc09)) +* build error ([8c80c1e](https://github.com/AgoraIO/Flutter-SDK/commit/8c80c1e43f86de3d62b281473f92f217513e139a)) +* mac render crash ([dee5ab9](https://github.com/AgoraIO/Flutter-SDK/commit/dee5ab9d0245859113b3411adfab60baad6ac7b4)) +* mobile `RtcStats` key error ([70cb58e](https://github.com/AgoraIO/Flutter-SDK/commit/70cb58efcfce21352f3f77076abe8c3f62998d6c)) +* remove unless import ([668650f](https://github.com/AgoraIO/Flutter-SDK/commit/668650f95fc052089f37898e6a7b5a735f08a3b5)) +* render error ([f409099](https://github.com/AgoraIO/Flutter-SDK/commit/f409099398f8d7d51c449bba00a0128fde90b113)) +* Web call `Platform` API error ([d760093](https://github.com/AgoraIO/Flutter-SDK/commit/d760093a5e3368108e54f9995c1956d9caaa8460)) + + +### Features + +* add `rtc_device_manager.dart` ([94e27c9](https://github.com/AgoraIO/Flutter-SDK/commit/94e27c91fb2efe630751551d1cfddc1ba657a735)) +* add device manager for Web ([18b5d90](https://github.com/AgoraIO/Flutter-SDK/commit/18b5d90ec320bff090dcb01cc8717c0781dd5a38)) +* add DeviceManager for windows ([dcf5630](https://github.com/AgoraIO/Flutter-SDK/commit/dcf56308c04b9d6da0aba31b5a3c04b4087db388)) + ## [4.0.1](https://github.com/AgoraIO/Flutter-SDK/compare/v4.0.0...v4.0.1) (2021-05-19) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index c1dbe8761..ee1c08495 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,18 +1,18 @@ # Contribute your code -We are glad you are here! Everyone is welcome to contribute code -via pull requests, to help people asking for -help, to add to our documentation, or to help out in any other way. +We are glad you are here! Everyone is welcome to contribute code via pull requests, to help people who ask for help, to add to our documentation, or to help out in any other way. -This document briefly describes some guidance on how you can contribute -to this repository. +This document briefly describes some guidance on how you can contribute to this repository. ## Source code structures -1. **[lib/rtc_engine.dart](lib/rtc_engine.dart)**: Dart APIs wrapper, api message channels to native modules. -2. **[example](example)**: Example demo for quick start/showcase. -3. **[ios/Classes/AgoraRtcEnginePlugin.m](ios/Classes/AgoraRtcEnginePlugin.m)**: iOS native implementation to handle dart message channel api calls. -4. **[android/src/main/kotlin/io/agora/agora_rtc_engine/AgoraRtcEnginePlugin.kt](android/src/main/kotlin/io/agora/agora_rtc_engine/AgoraRtcEnginePlugin.kt)**: Android native implementation to handle dart message channel api calls. +1. **[lib/rtc_engine.dart](lib/rtc_engine.dart)**: The entry of Dart API. +2. **[example](example)**: API Examples. +3. **[android](android)**: Android native implementation. +4. **[ios](ios)**: iOS native implementation. +5. **[macos](macos)**: Mac native implementation. +6. **[windows](windows)**: Windows native implementation. +7. **[web](lib/agora_rtc_engine_web.dart)**: Web implementation. While creating PR, below materials could be helpful: diff --git a/README.md b/README.md index 5600dbd70..745d1eba7 100644 --- a/README.md +++ b/README.md @@ -3,57 +3,125 @@ ![pub package](https://img.shields.io/pub/v/agora_rtc_engine.svg?include_prereleases) [中文](README.zh.md) -[日本語](README.jp.md) -This Flutter plugin is a wrapper for [Agora Video SDK](https://docs.agora.io/en/Interactive%20Broadcast/product_live?platform=All%20Platforms). +This Flutter plugin is a wrapper +for [Agora Video SDK](https://docs.agora.io/en/Interactive%20Broadcast/product_live?platform=All%20Platforms) +. -Agora.io provides building blocks for you to add real-time voice and video communications through a simple and powerful SDK. You can integrate the Agora SDK to enable real-time communications in your own application quickly. +Agora.io provides building blocks for you to add real-time voice and video communications through a +simple and powerful SDK. You can integrate the Agora SDK to enable real-time communications in your +own application quickly. ## Usage -To use this plugin, add `agora_rtc_engine` as a dependency in your [pubspec.yaml](https://flutter.dev/docs/development/packages-and-plugins/using-packages) file. +To use this plugin, please add `agora_rtc_engine` as a dependency to +your [pubspec.yaml](https://flutter.dev/docs/development/packages-and-plugins/using-packages) file. ## Getting Started -* See the [example](example) directory for a sample about one to one video chat app which using `agora_rtc_engine`. -* Or checkout this [Tutorial](https://github.com/AgoraIO-Community/Agora-Flutter-Quickstart) for a sample about live broadcasting app which using `agora_rtc_engine`. +* Get some basic and advanced examples from the [example](example/lib/examples) folder. -## Device Permission +### Privacy Permission -Agora Video SDK requires `camera` and `microphone` permission to start video call. +Agora Video SDK requires `Camera` and `Microphone` permission to start a video call. -### Android +#### Android -Open the `AndroidManifest.xml` file and add the required device permissions to the file. +See the required device permissions from +the [AndroidManifest.xml](android/src/main/AndroidManifest.xml) file. ```xml + - ... - - - - - - - - - - ... + ... + + + + + + + + + + + + ... ``` -### iOS +#### iOS & macOS Open the `Info.plist` and add: -- `Privacy - Microphone Usage Description`, and add a note in the Value column. -- `Privacy - Camera Usage Description`, and add a note in the Value column. +- `Privacy - Microphone Usage Description`,and add some description into the `Value` column. +- `Privacy - Camera Usage Description`, and add some description into the `Value` column. + +## Flutter2 support + +### Null Safety + +We have supported null safety at +the [4.0.1](https://pub.dev/packages/agora_rtc_engine/versions/4.0.1) version already. This version +is not downward compatible, your project needs to be migrated to null safety, please refer +to [Migrating to null safety](https://dart.dev/null-safety/migration-guide). + +### Multiple Platforms + +#### Linux + +Not support yet. + +#### macOS -Your application can still run the voice call when it is switched to the background if the background mode is enabled. Select the app target in Xcode, click the **Capabilities** tab, enable **Background Modes**, and check **Audio, AirPlay, and Picture in Picture**. +You can get more info from the [agora_rtc_engine.podspec](macos/agora_rtc_engine.podspec) file, such +as dependency Libraries on macOS. + +#### Windows + +You can get more info from the [CMakeLists.text](windows/CMakeLists.txt) file, such as dependency +Libraries on Windows. + +#### Web + +We use the [js](https://pub.dev/packages/js) library to call JavaScript from the dart layer. + +We have a wrapper library named [AgoraRtcWrapper.bundle.js](example/web/AgoraRtcWrapper.bundle.js) +for the Web SDK, so you should add it to your `index.html`, you can refer +to [example/web/index.html](example/web/index.html). + +```html + + +``` + +This wrapper library is the output of the open-source +repository [Iris-Rtc-Web](https://github.com/AgoraIO-Community/Iris-Rtc-Web). The repository attempt +to mapping the API from Web SDK as Native SDK, we make it open-source to help developer positioning +and troubleshooting. + +We have imported it as a Git submodule, you can find it in the [web](web) folder. ## Interact with RtcEngine/AgoraRtcEngineKit on Android/iOS -`agora_rtc_engine` has not implemented all the features of agora native (Android/iOS) sdk, due to performance reasons, such as [Custom Audio Source and Renderer](https://docs.agora.io/en/Video/custom_audio_android?platform=Android), [Custom Video Source and Renderer](https://docs.agora.io/en/Video/custom_video_android?platform=Android), [Raw Audio Data](https://docs.agora.io/en/Video/raw_data_audio_android?platform=Android), etc. `agora_rtc_engine` provides [RtcEnginePlugin](https://github.com/AgoraIO/Agora-Flutter-SDK/blob/master/android/src/main/java/io/agora/rtc/base/RtcEnginePlugin.kt)/[RtcEnginePlugin](https://github.com/AgoraIO/Agora-Flutter-SDK/blob/master/ios/Classes/Base/RtcEnginePlugin.h), allowing you to to interact with the [RtcEngine](https://github.com/AgoraIO/Agora-Flutter-SDK/blob/master/lib/src/rtc_engine.dart) created on the Flutter side in the Android/iOS code, you can implement your own plugin by inheriting [RtcEnginePlugin](https://github.com/AgoraIO/Agora-Flutter-SDK/blob/master/android/src/main/java/io/agora/rtc/base/RtcEnginePlugin.kt)/[RtcEnginePlugin](https://github.com/AgoraIO/Agora-Flutter-SDK/blob/master/ios/Classes/Base/RtcEnginePlugin.h), and get the [RtcEngine](https://docs.agora.io/en/Video/API%20Reference/java/classio_1_1agora_1_1rtc_1_1_rtc_engine.html)/[AgoraRtcEngineKit](https://docs.agora.io/en/Video/API%20Reference/oc/Classes/AgoraRtcEngineKit.html) in the `onRtcEngineCreated` callback. Please note that you should not call the [RtcEngine.destroy](https://docs.agora.io/en/Video/API%20Reference/java/classio_1_1agora_1_1rtc_1_1_rtc_engine.html#afb808cdc9025a77af7dd2bce98311bfe)/[AgoraRtcEngineKit.destroy](https://docs.agora.io/en/Video/API%20Reference/oc/Classes/AgoraRtcEngineKit.html#//api/name/destroy) function on Android/iOS code, because it will affect the [RtcEngine](https://github.com/AgoraIO/Agora-Flutter-SDK/blob/master/lib/src/rtc_engine.dart) on the Flutter side. To see how to use `RtcEnginePlugin`, please check the custom audio source example: +`agora_rtc_engine` has not implemented all the features of agora native (Android/iOS) sdk, due to +performance reasons, such +as [Custom Audio Source and Renderer](https://docs.agora.io/en/Video/custom_audio_android?platform=Android) +, [Custom Video Source and Renderer](https://docs.agora.io/en/Video/custom_video_android?platform=Android) +, [Raw Audio Data](https://docs.agora.io/en/Video/raw_data_audio_android?platform=Android), +etc. `agora_rtc_engine` +provides [RtcEnginePlugin](https://github.com/AgoraIO/Agora-Flutter-SDK/blob/master/android/src/main/java/io/agora/rtc/base/RtcEnginePlugin.kt)/[RtcEnginePlugin](https://github.com/AgoraIO/Agora-Flutter-SDK/blob/master/ios/Classes/Base/RtcEnginePlugin.h) +, allowing you to to interact with +the [RtcEngine](https://github.com/AgoraIO/Agora-Flutter-SDK/blob/master/lib/src/rtc_engine.dart) +created on the Flutter side in the Android/iOS code, you can implement your own plugin by +inheriting [RtcEnginePlugin](https://github.com/AgoraIO/Agora-Flutter-SDK/blob/master/android/src/main/java/io/agora/rtc/base/RtcEnginePlugin.kt)/[RtcEnginePlugin](https://github.com/AgoraIO/Agora-Flutter-SDK/blob/master/ios/Classes/Base/RtcEnginePlugin.h) +, and get +the [RtcEngine](https://docs.agora.io/en/Video/API%20Reference/java/classio_1_1agora_1_1rtc_1_1_rtc_engine.html)/[AgoraRtcEngineKit](https://docs.agora.io/en/Video/API%20Reference/oc/Classes/AgoraRtcEngineKit.html) +in the `onRtcEngineCreated` callback. Please note that you should not call +the [RtcEngine.destroy](https://docs.agora.io/en/Video/API%20Reference/java/classio_1_1agora_1_1rtc_1_1_rtc_engine.html#afb808cdc9025a77af7dd2bce98311bfe)/[AgoraRtcEngineKit.destroy](https://docs.agora.io/en/Video/API%20Reference/oc/Classes/AgoraRtcEngineKit.html#//api/name/destroy) +function on Android/iOS code, because it will affect +the [RtcEngine](https://github.com/AgoraIO/Agora-Flutter-SDK/blob/master/lib/src/rtc_engine.dart) on +the Flutter side. To see how to use `RtcEnginePlugin`, please check the custom audio source example: Android:[CustomAudioPlugin.kt](https://github.com/AgoraIO/Agora-Flutter-SDK/blob/master/example/android/app/src/main/kotlin/io/agora/agora_rtc_engine_example/custom_audio_source/CustomAudioPlugin.kt) @@ -61,34 +129,67 @@ iOS:[CustmoAudioSourcePlugin.swift](https://github.com/AgoraIO/Agora-Flutter-S ## Error handling -### Android build error +Please check **Pinned issues** and search +in [Issues](https://github.com/AgoraIO/Agora-Flutter-SDK/issues) first. + +### [Background mode #28](https://github.com/AgoraIO/Agora-Flutter-SDK/issues/28) + +#### Android + +[Android 9.0 Background Capture](https://docs.agora.io/en/Interactive%20Broadcast/faq/android_background?platform=Android) + +#### iOS + +Select your **TARGET** in Xcode, and click the `Signing & Capabilities` tab, then +enable `Background Modes` and check `Audio, AirPlay, and Picture in Picture`. + +### [RawData #183](https://github.com/AgoraIO/Agora-Flutter-SDK/issues/183) + +Only support Android and iOS yet. + +### [Using flutter assets #181](https://github.com/AgoraIO/Agora-Flutter-SDK/issues/181) + +### Screen Sharing + +Only support Web, macOS and Windows yet, not support for Android and iOS. + +**Important** -The error log like `Could not find com.github.agorabuilder:native-full-sdk:3.4.2.` +You should set `AppGroup` on macOS and set as parameter before calling `getScreenShareHelper`. -pls refer to https://github.com/AgoraIO/Agora-Flutter-SDK/issues/321#issuecomment-843913064 +You can refer +to [screen_sharing.dart](example/lib/examples/advanced/screen_sharing/screen_sharing.dart) +and [Apple doc](https://developer.apple.com/library/archive/documentation/Security/Conceptual/AppSandboxDesignGuide/AppSandboxInDepth/AppSandboxInDepth.html#//apple_ref/doc/uid/TP40011183-CH3-SW21) ## API -* [Flutter API](https://docs.agora.io/en/All/api-ref?platform=Flutter) +* [Flutter API](https://docs.agora.io/en/Video/API%20Reference/flutter/index.html) * [Android API](https://docs.agora.io/en/Video/API%20Reference/java/index.html) -* [iOS API](https://docs.agora.io/en/Video/API%20Reference/oc/docs/headers/Agora-Objective-C-API-Overview.html) +* [iOS/Mac API](https://docs.agora.io/en/Video/API%20Reference/oc/docs/headers/Agora-Objective-C-API-Overview.html) +* [Windows API](https://docs.agora.io/en/Video/API%20Reference/cpp/index.html) +* [Web API](https://docs.agora.io/en/Video/API%20Reference/web_ng/index.html) ## Feedback -If you have any problems or suggestions regarding the sample projects, feel free to file an [issue](https://github.com/AgoraIO/Agora-Flutter-SDK/issues). +If you have any problems or suggestions regarding the sample projects, feel free to file +an [issue](https://github.com/AgoraIO/Agora-Flutter-SDK/issues). ## How to contribute -To help work on this sdk, see our [contributor guide](https://github.com/AgoraIO/Flutter-SDK/blob/master/CONTRIBUTING.md). +To help work on this sdk, please refer +to [CONTRIBUTING.md](https://github.com/AgoraIO/Flutter-SDK/blob/master/CONTRIBUTING.md). ## Related resources - Check our [FAQ](https://docs.agora.io/en/faq) to see if your issue has been recorded. - Dive into [Agora SDK Samples](https://github.com/AgoraIO) to see more tutorials -- Take a look at [Agora Use Case](https://github.com/AgoraIO-usecase) for more complicated real use case -- Repositories managed by developer communities can be found at [Agora Community](https://github.com/AgoraIO-Community) -- If you encounter problems during integration, feel free to ask questions in [Stack Overflow](https://stackoverflow.com/questions/tagged/agora.io) +- Take a look at [Agora Use Case](https://github.com/AgoraIO-usecase) for more complicated real use + case +- Repositories managed by developer communities can be found + at [Agora Community](https://github.com/AgoraIO-Community) +- If you encounter problems during integration, feel free to ask questions + in [Stack Overflow](https://stackoverflow.com/questions/tagged/agora.io) ## License -The sample projects are under the MIT license. \ No newline at end of file +The sample projects are under the MIT license. diff --git a/README.zh.md b/README.zh.md index 62e12d795..db24f8774 100644 --- a/README.zh.md +++ b/README.zh.md @@ -3,57 +3,100 @@ ![pub package](https://img.shields.io/pub/v/agora_rtc_engine.svg?include_prereleases) [English](README.md) -[日本語](README.jp.md) -此 Flutter 插件 是对 [Agora 视频 SDK](https://docs.agora.io/cn/Interactive%20Broadcast/product_live?platform=All%20Platforms) 的包装。 +此 Flutter 插件 +是对 [Agora 视频 SDK](https://docs.agora.io/cn/Interactive%20Broadcast/product_live?platform=All%20Platforms) +的包装。 Agora.io 通过一个简单而强大的 SDK 为您提供了添加实时语音和视频通信的构建块。您可以集成此 SDK 以便在您自己的应用程序中快速实现实时通信。 ## 如何使用 -为了使用此插件, 添加 `agora_rtc_engine` 到您的 [pubspec.yaml](https://flutter.dev/docs/development/packages-and-plugins/using-packages) 文件中。 +为了使用此插件, 请添加 `agora_rtc_engine` +到您的 [pubspec.yaml](https://flutter.dev/docs/development/packages-and-plugins/using-packages) 文件中。 ## 快速开始 -* 参阅 [example](example) 目录,这是一个一对一视频聊天的示例。 -* 或者检出 [Tutorial](https://github.com/AgoraIO-Community/Agora-Flutter-Quickstart) ,这是一个直播场景的示例. +* 从 [example](example/lib/examples) 目录获取一些基础和高阶的参考示例。 -## 设备权限 +### 隐私权限 Agora 视频 SDK 需要 `摄像头` 和 `麦克风` 权限来开始视频通话。 -### Android +#### Android -打开 `AndroidManifest.xml` 文件并且添加必备的权限到此文件中. +查看 [AndroidManifest.xml](android/src/main/AndroidManifest.xml) 文件中已声明的权限。 ```xml + - ... - - - - - - - - - - ... + ... + + + + + + + + + + + + ... ``` -### iOS +#### iOS 和 macOS -打开 `info.plist` 文件并且添加: +打开 `Info.plist` 文件并且添加: - `Privacy - Microphone Usage Description`,并且在 `Value` 列中添加描述。 - `Privacy - Camera Usage Description`, 并且在 `Value` 列中添加描述。 -您的程序可以在后台运行音视频通话,前提是您开启了后台模式。在 Xcode 中选择您的 app target,点击 **Capabilities** 标签,开启 **Background Modes**,并且检查 **Audio、AirPlay 和 Picture in Picture**。 +## Flutter2 支持 + +### 空安全 + +我们在 [4.0.1](https://pub.dev/packages/agora_rtc_engine/versions/4.0.1) 版本已经正式支持了空安全。 +此版本不向下兼容,需要您的工程迁移至空安全,具体参考 [迁移至空安全](https://dart.cn/null-safety/migration-guide) 。 + +### 多平台 + +#### Linux + +暂不支持。 + +#### macOS + +您可以从 [agora_rtc_engine.podspec](macOS/agora_rtc_engine.podspec) 文件中获取更多信息, 比如在 macOS 上的依赖库。 + +#### Windows + +您可以从 [CMakeLists.text](windows/CMakeLists.txt) 文件中获取更多信息, 比如在 Windows 上的依赖库。 + +#### Web + +我们使用 [js](https://pub.dev/packages/js) 库实现 dart 对 JavaScript 的调用。 + +我们针对 Web SDK 有一个 [AgoraRtcWrapper.bundle.js](example/web/AgoraRtcWrapper.bundle.js) +包装库,所以需要在您的 `index.html` 中添加引用,可以参考 [example/web/index.html](example/web/index.html) 。 + +```html + + +``` + +此包装库是 [Iris-Rtc-Web](https://github.com/AgoraIO-Community/Iris-Rtc-Web) 开源库的编译产物,它尝试将 Web SDK 接口映射成 +Native SDK 接口,我们将其开源以便开发者定位和排查问题。 + +我们已将其作为 Git Submodule 导入到工程中,您可以在 [web](web) 目录中找到它。 ## 在Android/iOS中与[RtcEngine](https://docs.agora.io/cn/Video/API%20Reference/java/classio_1_1agora_1_1rtc_1_1_rtc_engine.html)/[AgoraRtcEngineKit](https://docs.agora.io/cn/Video/API%20Reference/oc/Classes/AgoraRtcEngineKit.html)交互 -由于性能原因,`agora_rtc_engine`暂时没有实现agora native(Android/iOS) sdk的所有功能,如[自定义音频采集和渲染](hhttps://docs.agora.io/cn/Video/custom_audio_android?platform=Android),[自定义视频采集和渲染](https://docs.agora.io/cn/Video/custom_video_android?platform=Android),[原始音频数据](https://docs.agora.io/cn/Video/raw_data_audio_android?platform=Android)等功能,`agora_rtc_engine`提供[RtcEnginePlugin](https://github.com/AgoraIO/Agora-Flutter-SDK/blob/master/android/src/main/java/io/agora/rtc/base/RtcEnginePlugin.kt)/[RtcEnginePlugin](https://github.com/AgoraIO/Agora-Flutter-SDK/blob/master/ios/Classes/Base/RtcEnginePlugin.h),允许你在Android/iOS代码中与Flutter端创建的[RtcEngine](https://github.com/AgoraIO/Agora-Flutter-SDK/blob/master/lib/src/rtc_engine.dart)交互,你可以继承[RtcEnginePlugin](https://github.com/AgoraIO/Agora-Flutter-SDK/blob/master/android/src/main/java/io/agora/rtc/base/RtcEnginePlugin.kt)/[RtcEnginePlugin](https://github.com/AgoraIO/Agora-Flutter-SDK/blob/master/ios/Classes/Base/RtcEnginePlugin.h)实现自己的插件,在`onRtcEngineCreated`回调中获取[RtcEngine](https://docs.agora.io/cn/Video/API%20Reference/java/classio_1_1agora_1_1rtc_1_1_rtc_engine.html)/[AgoraRtcEngineKit](https://docs.agora.io/cn/Video/API%20Reference/oc/Classes/AgoraRtcEngineKit.html),请注意不要在Android/iOS中调用[RtcEngine.destroy](https://docs.agora.io/cn/Video/API%20Reference/java/classio_1_1agora_1_1rtc_1_1_rtc_engine.html#afb808cdc9025a77af7dd2bce98311bfe)/[AgoraRtcEngineKit.destroy](https://docs.agora.io/cn/Video/API%20Reference/oc/Classes/AgoraRtcEngineKit.html#//api/name/destroy)方法,因为这会影响Flutter端的[RtcEngine](https://github.com/AgoraIO/Agora-Flutter-SDK/blob/master/lib/src/rtc_engine.dart)功能。如何使用`RtcEnginePlugin`,请查看我们提供的音频自采集demo: +由于性能原因,`agora_rtc_engine`暂时没有实现agora native(Android/iOS) +sdk的所有功能,如[自定义音频采集和渲染](hhttps://docs.agora.io/cn/Video/custom_audio_android?platform=Android) +,[自定义视频采集和渲染](https://docs.agora.io/cn/Video/custom_video_android?platform=Android),[原始音频数据](https://docs.agora.io/cn/Video/raw_data_audio_android?platform=Android)等功能,`agora_rtc_engine`提供[RtcEnginePlugin](https://github.com/AgoraIO/Agora-Flutter-SDK/blob/master/android/src/main/java/io/agora/rtc/base/RtcEnginePlugin.kt)/[RtcEnginePlugin](https://github.com/AgoraIO/Agora-Flutter-SDK/blob/master/ios/Classes/Base/RtcEnginePlugin.h),允许你在Android/iOS代码中与Flutter端创建的[RtcEngine](https://github.com/AgoraIO/Agora-Flutter-SDK/blob/master/lib/src/rtc_engine.dart)交互,你可以继承[RtcEnginePlugin](https://github.com/AgoraIO/Agora-Flutter-SDK/blob/master/android/src/main/java/io/agora/rtc/base/RtcEnginePlugin.kt)/[RtcEnginePlugin](https://github.com/AgoraIO/Agora-Flutter-SDK/blob/master/ios/Classes/Base/RtcEnginePlugin.h)实现自己的插件,在`onRtcEngineCreated`回调中获取[RtcEngine](https://docs.agora.io/cn/Video/API%20Reference/java/classio_1_1agora_1_1rtc_1_1_rtc_engine.html)/[AgoraRtcEngineKit](https://docs.agora.io/cn/Video/API%20Reference/oc/Classes/AgoraRtcEngineKit.html),请注意不要在Android/iOS中调用[RtcEngine.destroy](https://docs.agora.io/cn/Video/API%20Reference/java/classio_1_1agora_1_1rtc_1_1_rtc_engine.html#afb808cdc9025a77af7dd2bce98311bfe)/[AgoraRtcEngineKit.destroy](https://docs.agora.io/cn/Video/API%20Reference/oc/Classes/AgoraRtcEngineKit.html#//api/name/destroy)方法,因为这会影响Flutter端的[RtcEngine](https://github.com/AgoraIO/Agora-Flutter-SDK/blob/master/lib/src/rtc_engine.dart)功能。如何使用`RtcEnginePlugin`,请查看我们提供的音频自采集demo: Android:[CustomAudioPlugin.kt](https://github.com/AgoraIO/Agora-Flutter-SDK/blob/master/example/android/app/src/main/kotlin/io/agora/agora_rtc_engine_example/custom_audio_source/CustomAudioPlugin.kt) @@ -61,21 +104,43 @@ iOS:[CustmoAudioSourcePlugin.swift](https://github.com/AgoraIO/Agora-Flutter-S ## 常见问题 -### iOS 无法显示视频(Android 是好的) +请优先查看 **Pinned issues** 和在 [Issues](https://github.com/AgoraIO/Agora-Flutter-SDK/issues) 中搜索。 + +### [后台采集](https://github.com/AgoraIO/Agora-Flutter-SDK/issues/28) + +#### Android + +[Android 9.0 后台采集无效](https://docs.agora.io/cn/Interactive%20Broadcast/faq/android_background?platform=Android) + +#### iOS + +在 Xcode 中选择您的 **TARGET**,点击 `Signing & Capabilities` 标签,开启 `Background Modes` +,并且勾选 `Audio, AirPlay, and Picture in Picture`。 + +### [获取裸数据](https://github.com/AgoraIO/Agora-Flutter-SDK/issues/183) + +目前仅支持 Android 和 iOS。 + +### [使用 flutter assets 作为路径](https://github.com/AgoraIO/Agora-Flutter-SDK/issues/181) + +### 屏幕共享 -我们的 SDK 使用 `PlatformView`,您需要设置 `io.flutter.embedded_views_preview` 为 `YES` 在您的 **info.plist** 中。 +目前仅支持 Web、macOS 和 Windows,暂不支持 Android 和 iOS。 -### iOS 内存泄漏 +**重要信息** -如果您使用 `stable` 版本的 `flutter`,`PlatformView` 会导致内存泄漏,您可以运行 `flutter channel beta` +在 macOS 平台上你需要设置 `AppGroup` 并且作为参数在你调用 `getScreenShareHelper` 之前。 -您可以参考这个 [pull request](https://github.com/flutter/engine/pull/14326) +你可以参考 [screen_sharing.dart](example/lib/examples/advanced/screen_sharing/screen_sharing.dart) +和 [Apple doc](https://developer.apple.com/library/archive/documentation/Security/Conceptual/AppSandboxDesignGuide/AppSandboxInDepth/AppSandboxInDepth.html#//apple_ref/doc/uid/TP40011183-CH3-SW21) ## API -* [Flutter API](https://docs.agora.io/cn/All/api-ref?platform=Flutter) -* [Android API](https://docs.agora.io/en/Video/API%20Reference/java/index.html) -* [iOS API](https://docs.agora.io/en/Video/API%20Reference/oc/docs/headers/Agora-Objective-C-API-Overview.html) +* [Flutter API](https://docs.agora.io/cn/Video/API%20Reference/flutter/index.html) +* [Android API](https://docs.agora.io/cn/Video/API%20Reference/java/index.html) +* [iOS/Mac API](https://docs.agora.io/cn/Video/API%20Reference/oc/docs/headers/Agora-Objective-C-API-Overview.html) +* [Windows API](https://docs.agora.io/cn/Video/API%20Reference/cpp/index.html) +* [Web API](https://docs.agora.io/cn/Video/API%20Reference/web_ng/index.html) ## 反馈 diff --git a/analysis_options.yaml b/analysis_options.yaml index 3a657c0e2..ae7d15e9c 100644 --- a/analysis_options.yaml +++ b/analysis_options.yaml @@ -4,6 +4,8 @@ analyzer: # Ignore generated files - '**/*.g.dart' - 'lib/src/generated/*.dart' + errors: + undefined_prefixed_name: ignore linter: rules: - public_member_api_docs diff --git a/android/build.gradle b/android/build.gradle index b1691be3f..f97e66d8f 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -6,7 +6,8 @@ def safeExtGet(prop, fallback) { } buildscript { - def kotlin_version = rootProject.ext.has('kotlin_version') ? rootProject.ext.get('kotlin_version') : '1.3.72' + ext.agora_rtc_engine_kt_version = '1.5.31' + def kotlin_version = rootProject.ext.has('kotlin_version') ? rootProject.ext.get('kotlin_version') : "$agora_rtc_engine_kt_version" repositories { mavenCentral() @@ -30,12 +31,12 @@ apply plugin: 'com.android.library' apply plugin: 'kotlin-android' android { - compileSdkVersion safeExtGet('compileSdkVersion', 28) - buildToolsVersion safeExtGet('buildToolsVersion', '28.0.3') + compileSdkVersion safeExtGet('compileSdkVersion', 31) + buildToolsVersion safeExtGet('buildToolsVersion', '31.0.0') defaultConfig { minSdkVersion safeExtGet('minSdkVersion', 16) - targetSdkVersion safeExtGet('targetSdkVersion', 28) + targetSdkVersion safeExtGet('targetSdkVersion', 31) consumerProguardFiles 'consumer-rules.pro' } @@ -50,7 +51,6 @@ android { } dependencies { - api 'com.github.agorabuilder:native-full-sdk:3.5.2' - - implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:${safeExtGet('kotlin_version', '1.3.72')}" + api 'com.github.agorabuilder:iris-rtc:3.5.2' + implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:${safeExtGet('kotlin_version', "$agora_rtc_engine_kt_version")}" } diff --git a/android/gradle.properties b/android/gradle.properties index 38c8d4544..94adc3a3f 100644 --- a/android/gradle.properties +++ b/android/gradle.properties @@ -1,4 +1,3 @@ org.gradle.jvmargs=-Xmx1536M -android.enableR8=true android.useAndroidX=true android.enableJetifier=true diff --git a/android/src/main/java/io/agora/rtc/base/.gitignore b/android/src/main/java/io/agora/rtc/base/.gitignore deleted file mode 100644 index 9f11b755a..000000000 --- a/android/src/main/java/io/agora/rtc/base/.gitignore +++ /dev/null @@ -1 +0,0 @@ -.idea/ diff --git a/android/src/main/java/io/agora/rtc/base/Annotations.java b/android/src/main/java/io/agora/rtc/base/Annotations.java deleted file mode 100644 index a4fc0fbba..000000000 --- a/android/src/main/java/io/agora/rtc/base/Annotations.java +++ /dev/null @@ -1,991 +0,0 @@ -package io.agora.rtc.base; - -import androidx.annotation.IntDef; - -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; - -import io.agora.rtc.Constants; -import io.agora.rtc.IRtcEngineEventHandler; -import io.agora.rtc.RtcEngineConfig; -import io.agora.rtc.video.BeautyOptions; -import io.agora.rtc.video.VideoCanvas; -import io.agora.rtc.video.VirtualBackgroundSource; - -@SuppressWarnings("deprecation") -public class Annotations { - @IntDef({ - AgoraRtcAppType.NATIVE, - AgoraRtcAppType.COCOS, - AgoraRtcAppType.UNITY, - AgoraRtcAppType.ELECTRON, - AgoraRtcAppType.FLUTTER, - AgoraRtcAppType.UNREAL, - AgoraRtcAppType.XAMARIN, - AgoraRtcAppType.API_CLOUD, - AgoraRtcAppType.REACT_NATIVE, - AgoraRtcAppType.PYTHON, - AgoraRtcAppType.COCOS_CREATOR, - AgoraRtcAppType.RUST, - AgoraRtcAppType.C_SHARP, - AgoraRtcAppType.CEF, - AgoraRtcAppType.UNI_APP, - }) - @Retention(RetentionPolicy.SOURCE) - public @interface AgoraRtcAppType { - int NATIVE = 0; - int COCOS = 1; - int UNITY = 2; - int ELECTRON = 3; - int FLUTTER = 4; - int UNREAL = 5; - int XAMARIN = 6; - int API_CLOUD = 7; - int REACT_NATIVE = 8; - int PYTHON = 9; - int COCOS_CREATOR = 10; - int RUST = 11; - int C_SHARP = 12; - int CEF = 13; - int UNI_APP = 14; - } - - @IntDef({ - AgoraAudioCodecProfileType.LC_AAC, - AgoraAudioCodecProfileType.HE_AAC, - }) - @Retention(RetentionPolicy.SOURCE) - public @interface AgoraAudioCodecProfileType { - int LC_AAC = 0; - int HE_AAC = 1; - } - - @IntDef({ - Constants.AUDIO_EQUALIZATION_BAND_31, - Constants.AUDIO_EQUALIZATION_BAND_62, - Constants.AUDIO_EQUALIZATION_BAND_125, - Constants.AUDIO_EQUALIZATION_BAND_250, - Constants.AUDIO_EQUALIZATION_BAND_500, - Constants.AUDIO_EQUALIZATION_BAND_1K, - Constants.AUDIO_EQUALIZATION_BAND_2K, - Constants.AUDIO_EQUALIZATION_BAND_4K, - Constants.AUDIO_EQUALIZATION_BAND_8K, - Constants.AUDIO_EQUALIZATION_BAND_16K, - }) - @Retention(RetentionPolicy.SOURCE) - public @interface AgoraAudioEqualizationBandFrequency { - } - - @IntDef({ - Constants.LOCAL_AUDIO_STREAM_ERROR_OK, - Constants.LOCAL_AUDIO_STREAM_ERROR_FAILURE, - Constants.LOCAL_AUDIO_STREAM_ERROR_DEVICE_NO_PERMISSION, - Constants.LOCAL_AUDIO_STREAM_ERROR_DEVICE_BUSY, - Constants.LOCAL_AUDIO_STREAM_ERROR_CAPTURE_FAILURE, - Constants.LOCAL_AUDIO_STREAM_ERROR_ENCODE_FAILURE, - Constants.LOCAL_AUDIO_STREAM_ERROR_INTERRUPTED, - }) - @Retention(RetentionPolicy.SOURCE) - public @interface AgoraAudioLocalError { - } - - @IntDef({ - Constants.LOCAL_AUDIO_STREAM_STATE_STOPPED, - Constants.LOCAL_AUDIO_STREAM_STATE_CAPTURING, - Constants.LOCAL_AUDIO_STREAM_STATE_ENCODING, - Constants.LOCAL_AUDIO_STREAM_STATE_FAILED, - }) - @Retention(RetentionPolicy.SOURCE) - public @interface AgoraAudioLocalState { - } - - @IntDef({ - Constants.AUDIO_MIXING_REASON_CAN_NOT_OPEN, - Constants.AUDIO_MIXING_REASON_TOO_FREQUENT_CALL, - Constants.AUDIO_MIXING_REASON_INTERRUPTED_EOF, - Constants.AUDIO_MIXING_REASON_STARTED_BY_USER, - Constants.AUDIO_MIXING_REASON_ONE_LOOP_COMPLETED, - Constants.AUDIO_MIXING_REASON_START_NEW_LOOP, - Constants.AUDIO_MIXING_REASON_ALL_LOOPS_COMPLETED, - Constants.AUDIO_MIXING_REASON_STOPPED_BY_USER, - Constants.AUDIO_MIXING_REASON_PAUSED_BY_USER, - Constants.AUDIO_MIXING_REASON_RESUMED_BY_USER, - AgoraAudioMixingReason.MEDIA_ENGINE_AUDIO_ERROR_OK, - }) - @Retention(RetentionPolicy.SOURCE) - public @interface AgoraAudioMixingReason { - int MEDIA_ENGINE_AUDIO_ERROR_OK = 0; - } - - @IntDef({ - Constants.MEDIA_ENGINE_AUDIO_EVENT_MIXING_PLAY, - Constants.MEDIA_ENGINE_AUDIO_EVENT_MIXING_PAUSED, - Constants.MEDIA_ENGINE_AUDIO_EVENT_MIXING_RESTART, - Constants.MEDIA_ENGINE_AUDIO_EVENT_MIXING_STOPPED, - Constants.MEDIA_ENGINE_AUDIO_EVENT_MIXING_ERROR, - }) - @Retention(RetentionPolicy.SOURCE) - public @interface AgoraAudioMixingStateCode { - } - - @IntDef({ - Constants.AUDIO_ROUTE_DEFAULT, - Constants.AUDIO_ROUTE_HEADSET, - Constants.AUDIO_ROUTE_EARPIECE, - Constants.AUDIO_ROUTE_HEADSETNOMIC, - Constants.AUDIO_ROUTE_SPEAKERPHONE, - Constants.AUDIO_ROUTE_LOUDSPEAKER, - Constants.AUDIO_ROUTE_HEADSETBLUETOOTH, - }) - @Retention(RetentionPolicy.SOURCE) - public @interface AgoraAudioOutputRouting { - } - - @IntDef({ - Constants.AUDIO_PROFILE_DEFAULT, - Constants.AUDIO_PROFILE_SPEECH_STANDARD, - Constants.AUDIO_PROFILE_MUSIC_STANDARD, - Constants.AUDIO_PROFILE_MUSIC_STANDARD_STEREO, - Constants.AUDIO_PROFILE_MUSIC_HIGH_QUALITY, - Constants.AUDIO_PROFILE_MUSIC_HIGH_QUALITY_STEREO, - }) - @Retention(RetentionPolicy.SOURCE) - public @interface AgoraAudioProfile { - } - - @IntDef({ - Constants.AUDIO_RECORDING_QUALITY_LOW, - Constants.AUDIO_RECORDING_QUALITY_MEDIUM, - Constants.AUDIO_RECORDING_QUALITY_HIGH, - }) - @Retention(RetentionPolicy.SOURCE) - public @interface AgoraAudioRecordingQuality { - } - - @IntDef({ - Constants.REMOTE_AUDIO_STATE_STOPPED, - Constants.REMOTE_AUDIO_STATE_STARTING, - Constants.REMOTE_AUDIO_STATE_DECODING, - Constants.REMOTE_AUDIO_STATE_FROZEN, - Constants.REMOTE_AUDIO_STATE_FAILED, - }) - @Retention(RetentionPolicy.SOURCE) - public @interface AgoraAudioRemoteState { - } - - @IntDef({ - Constants.REMOTE_AUDIO_REASON_INTERNAL, - Constants.REMOTE_AUDIO_REASON_NETWORK_CONGESTION, - Constants.REMOTE_AUDIO_REASON_NETWORK_RECOVERY, - Constants.REMOTE_AUDIO_REASON_LOCAL_MUTED, - Constants.REMOTE_AUDIO_REASON_LOCAL_UNMUTED, - Constants.REMOTE_AUDIO_REASON_REMOTE_MUTED, - Constants.REMOTE_AUDIO_REASON_REMOTE_UNMUTED, - Constants.REMOTE_AUDIO_REASON_REMOTE_OFFLINE, - }) - @Retention(RetentionPolicy.SOURCE) - public @interface AgoraAudioRemoteStateReason { - } - - @IntDef({ - Constants.AUDIO_REVERB_OFF, - Constants.AUDIO_REVERB_POPULAR, - Constants.AUDIO_REVERB_RNB, - Constants.AUDIO_REVERB_ROCK, - Constants.AUDIO_REVERB_HIPHOP, - Constants.AUDIO_REVERB_VOCAL_CONCERT, - Constants.AUDIO_REVERB_KTV, - Constants.AUDIO_REVERB_STUDIO, - Constants.AUDIO_REVERB_FX_KTV, - Constants.AUDIO_REVERB_FX_VOCAL_CONCERT, - Constants.AUDIO_REVERB_FX_UNCLE, - Constants.AUDIO_REVERB_FX_SISTER, - Constants.AUDIO_REVERB_FX_STUDIO, - Constants.AUDIO_REVERB_FX_POPULAR, - Constants.AUDIO_REVERB_FX_RNB, - Constants.AUDIO_REVERB_FX_PHONOGRAPH, - Constants.AUDIO_VIRTUAL_STEREO, - }) - @Retention(RetentionPolicy.SOURCE) - public @interface AgoraAudioReverbPreset { - } - - @IntDef({ - Constants.AUDIO_REVERB_DRY_LEVEL, - Constants.AUDIO_REVERB_WET_LEVEL, - Constants.AUDIO_REVERB_ROOM_SIZE, - Constants.AUDIO_REVERB_WET_DELAY, - Constants.AUDIO_REVERB_STRENGTH, - }) - @Retention(RetentionPolicy.SOURCE) - public @interface AgoraAudioReverbType { - } - - @IntDef({ - AgoraAudioSampleRateType.TYPE_32000, - AgoraAudioSampleRateType.TYPE_44100, - AgoraAudioSampleRateType.TYPE_48000, - }) - @Retention(RetentionPolicy.SOURCE) - public @interface AgoraAudioSampleRateType { - int TYPE_32000 = 32000; - int TYPE_44100 = 44100; - int TYPE_48000 = 48000; - } - - @IntDef({ - Constants.AUDIO_SCENARIO_DEFAULT, - Constants.AUDIO_SCENARIO_CHATROOM_ENTERTAINMENT, - Constants.AUDIO_SCENARIO_EDUCATION, - Constants.AUDIO_SCENARIO_GAME_STREAMING, - Constants.AUDIO_SCENARIO_SHOWROOM, - Constants.AUDIO_SCENARIO_CHATROOM_GAMING, - Constants.AUDIO_SCENARIO_IOT, - Constants.AUDIO_SCENARIO_MEETING, - }) - @Retention(RetentionPolicy.SOURCE) - public @interface AgoraAudioScenario { - } - - @IntDef({ - Constants.VOICE_CHANGER_OFF, - Constants.VOICE_CHANGER_OLDMAN, - Constants.VOICE_CHANGER_BABYBOY, - Constants.VOICE_CHANGER_BABYGIRL, - Constants.VOICE_CHANGER_ZHUBAJIE, - Constants.VOICE_CHANGER_ETHEREAL, - Constants.VOICE_CHANGER_HULK, - Constants.VOICE_BEAUTY_VIGOROUS, - Constants.VOICE_BEAUTY_DEEP, - Constants.VOICE_BEAUTY_MELLOW, - Constants.VOICE_BEAUTY_FALSETTO, - Constants.VOICE_BEAUTY_FULL, - Constants.VOICE_BEAUTY_CLEAR, - Constants.VOICE_BEAUTY_RESOUNDING, - Constants.VOICE_BEAUTY_RINGING, - Constants.VOICE_BEAUTY_SPACIAL, - Constants.GENERAL_BEAUTY_VOICE_MALE_MAGNETIC, - Constants.GENERAL_BEAUTY_VOICE_FEMALE_FRESH, - Constants.GENERAL_BEAUTY_VOICE_FEMALE_VITALITY, - }) - @Retention(RetentionPolicy.SOURCE) - public @interface AgoraAudioVoiceChanger { - } - - @IntDef({ - AgoraCameraCaptureOutputPreference.CAPTURER_OUTPUT_PREFERENCE_AUTO, - AgoraCameraCaptureOutputPreference.CAPTURER_OUTPUT_PREFERENCE_PERFORMANCE, - AgoraCameraCaptureOutputPreference.CAPTURER_OUTPUT_PREFERENCE_PREVIEW, - AgoraCameraCaptureOutputPreference.CAPTURER_OUTPUT_PREFERENCE_MANUAL, - }) - @Retention(RetentionPolicy.SOURCE) - public @interface AgoraCameraCaptureOutputPreference { - int CAPTURER_OUTPUT_PREFERENCE_AUTO = 0; - int CAPTURER_OUTPUT_PREFERENCE_PERFORMANCE = 1; - int CAPTURER_OUTPUT_PREFERENCE_PREVIEW = 2; - int CAPTURER_OUTPUT_PREFERENCE_MANUAL = 3; - } - - @IntDef({ - AgoraCameraDirection.CAMERA_REAR, - AgoraCameraDirection.CAMERA_FRONT, - }) - @Retention(RetentionPolicy.SOURCE) - public @interface AgoraCameraDirection { - int CAMERA_REAR = 0; - int CAMERA_FRONT = 1; - } - - @IntDef({ - Constants.RELAY_OK, - Constants.RELAY_ERROR_SERVER_ERROR_RESPONSE, - Constants.RELAY_ERROR_SERVER_NO_RESPONSE, - Constants.RELAY_ERROR_NO_RESOURCE_AVAILABLE, - Constants.RELAY_ERROR_FAILED_JOIN_SRC, - Constants.RELAY_ERROR_FAILED_JOIN_DEST, - Constants.RELAY_ERROR_FAILED_PACKET_RECEIVED_FROM_SRC, - Constants.RELAY_ERROR_FAILED_PACKET_SENT_TO_DEST, - Constants.RELAY_ERROR_SERVER_CONNECTION_LOST, - Constants.RELAY_ERROR_INTERNAL_ERROR, - Constants.RELAY_ERROR_SRC_TOKEN_EXPIRED, - Constants.RELAY_ERROR_DEST_TOKEN_EXPIRED, - }) - @Retention(RetentionPolicy.SOURCE) - public @interface AgoraChannelMediaRelayError { - } - - @IntDef({ - Constants.RELAY_EVENT_NETWORK_DISCONNECTED, - Constants.RELAY_EVENT_NETWORK_CONNECTED, - Constants.RELAY_EVENT_PACKET_JOINED_SRC_CHANNEL, - Constants.RELAY_EVENT_PACKET_JOINED_DEST_CHANNEL, - Constants.RELAY_EVENT_PACKET_SENT_TO_DEST_CHANNEL, - Constants.RELAY_EVENT_PACKET_RECEIVED_VIDEO_FROM_SRC, - Constants.RELAY_EVENT_PACKET_RECEIVED_AUDIO_FROM_SRC, - Constants.RELAY_EVENT_PACKET_UPDATE_DEST_CHANNEL, - Constants.RELAY_EVENT_PACKET_UPDATE_DEST_CHANNEL_REFUSED, - Constants.RELAY_EVENT_PACKET_UPDATE_DEST_CHANNEL_NOT_CHANGE, - Constants.RELAY_EVENT_PACKET_UPDATE_DEST_CHANNEL_IS_NULL, - Constants.RELAY_EVENT_VIDEO_PROFILE_UPDATE, - Constants.RELAY_EVENT_PAUSE_SEND_PACKET_TO_DEST_CHANNEL_SUCCESS, - Constants.RELAY_EVENT_PAUSE_SEND_PACKET_TO_DEST_CHANNEL_FAILED, - Constants.RELAY_EVENT_RESUME_SEND_PACKET_TO_DEST_CHANNEL_SUCCESS, - Constants.RELAY_EVENT_RESUME_SEND_PACKET_TO_DEST_CHANNEL_FAILED, - }) - @Retention(RetentionPolicy.SOURCE) - public @interface AgoraChannelMediaRelayEvent { - } - - @IntDef({ - Constants.RELAY_STATE_IDLE, - Constants.RELAY_STATE_CONNECTING, - Constants.RELAY_STATE_RUNNING, - Constants.RELAY_STATE_FAILURE, - }) - @Retention(RetentionPolicy.SOURCE) - public @interface AgoraChannelMediaRelayState { - } - - @IntDef({ - Constants.CHANNEL_PROFILE_COMMUNICATION, - Constants.CHANNEL_PROFILE_LIVE_BROADCASTING, - Constants.CHANNEL_PROFILE_GAME, - }) - @Retention(RetentionPolicy.SOURCE) - public @interface AgoraChannelProfile { - } - - @IntDef({ - Constants.CLIENT_ROLE_BROADCASTER, - Constants.CLIENT_ROLE_AUDIENCE, - }) - @Retention(RetentionPolicy.SOURCE) - public @interface AgoraClientRole { - } - - @IntDef({ - Constants.CONNECTION_CHANGED_CONNECTING, - Constants.CONNECTION_CHANGED_JOIN_SUCCESS, - Constants.CONNECTION_CHANGED_INTERRUPTED, - Constants.CONNECTION_CHANGED_BANNED_BY_SERVER, - Constants.CONNECTION_CHANGED_JOIN_FAILED, - Constants.CONNECTION_CHANGED_LEAVE_CHANNEL, - Constants.CONNECTION_CHANGED_INVALID_APP_ID, - Constants.CONNECTION_CHANGED_INVALID_CHANNEL_NAME, - Constants.CONNECTION_CHANGED_INVALID_TOKEN, - Constants.CONNECTION_CHANGED_TOKEN_EXPIRED, - Constants.CONNECTION_CHANGED_REJECTED_BY_SERVER, - Constants.CONNECTION_CHANGED_SETTING_PROXY_SERVER, - Constants.CONNECTION_CHANGED_RENEW_TOKEN, - Constants.CONNECTION_CHANGED_CLIENT_IP_ADDRESS_CHANGED, - Constants.CONNECTION_CHANGED_KEEP_ALIVE_TIMEOUT, - Constants.CONNECTION_CHANGED_PROXY_SERVER_INTERRUPTED, - }) - @Retention(RetentionPolicy.SOURCE) - public @interface AgoraConnectionChangedReason { - } - - @IntDef({ - Constants.CONNECTION_STATE_DISCONNECTED, - Constants.CONNECTION_STATE_CONNECTING, - Constants.CONNECTION_STATE_CONNECTED, - Constants.CONNECTION_STATE_RECONNECTING, - Constants.CONNECTION_STATE_FAILED, - }) - @Retention(RetentionPolicy.SOURCE) - public @interface AgoraConnectionStateType { - } - - @IntDef({ - AgoraDegradationPreference.MAINTAIN_QUALITY, - AgoraDegradationPreference.MAINTAIN_FRAMERATE, - AgoraDegradationPreference.MAINTAIN_BALANCED, - }) - @Retention(RetentionPolicy.SOURCE) - public @interface AgoraDegradationPreference { - int MAINTAIN_QUALITY = 0; - int MAINTAIN_FRAMERATE = 1; - int MAINTAIN_BALANCED = 2; - } - - @IntDef({ - AgoraEncryptionMode.NONE, - AgoraEncryptionMode.AES128XTS, - AgoraEncryptionMode.AES128ECB, - AgoraEncryptionMode.AES256XTS, - AgoraEncryptionMode.SM4128ECB, - AgoraEncryptionMode.AES128GCM, - AgoraEncryptionMode.AES256GCM, - AgoraEncryptionMode.AES128GCM2, - AgoraEncryptionMode.AES256GCM2, - }) - @Retention(RetentionPolicy.SOURCE) - public @interface AgoraEncryptionMode { - int NONE = 0; - int AES128XTS = 1; - int AES128ECB = 2; - int AES256XTS = 3; - int SM4128ECB = 4; - int AES128GCM = 5; - int AES256GCM = 6; - int AES128GCM2 = 7; - int AES256GCM2 = 8; - } - - @IntDef({ - Constants.ERR_OK, - Constants.ERR_FAILED, - Constants.ERR_INVALID_ARGUMENT, - Constants.ERR_NOT_READY, - Constants.ERR_NOT_SUPPORTED, - Constants.ERR_REFUSED, - Constants.ERR_BUFFER_TOO_SMALL, - Constants.ERR_NOT_INITIALIZED, - Constants.ERR_NO_PERMISSION, - Constants.ERR_TIMEDOUT, - Constants.ERR_CANCELED, - Constants.ERR_TOO_OFTEN, - Constants.ERR_BIND_SOCKET, - Constants.ERR_NET_DOWN, - Constants.ERR_NET_NOBUFS, - Constants.ERR_JOIN_CHANNEL_REJECTED, - Constants.ERR_LEAVE_CHANNEL_REJECTED, - Constants.ERR_ALREADY_IN_USE, - Constants.ERR_INVALID_APP_ID, - Constants.ERR_INVALID_CHANNEL_NAME, - Constants.ERR_NO_SERVER_RESOURCES, - Constants.ERR_TOKEN_EXPIRED, - Constants.ERR_INVALID_TOKEN, - Constants.ERR_CONNECTION_INTERRUPTED, - Constants.ERR_CONNECTION_LOST, - Constants.ERR_NOT_IN_CHANNEL, - Constants.ERR_SIZE_TOO_LARGE, - Constants.ERR_BITRATE_LIMIT, - Constants.ERR_TOO_MANY_DATA_STREAMS, - Constants.ERR_DECRYPTION_FAILED, - Constants.ERR_CLIENT_IS_BANNED_BY_SERVER, - Constants.ERR_WATERMARK_PARAM, - Constants.ERR_WATERMARK_PATH, - Constants.ERR_WATERMARK_PNG, - Constants.ERR_WATERMARKR_INFO, - Constants.ERR_WATERMARK_ARGB, - Constants.ERR_WATERMARK_READ, - Constants.ERR_ENCRYPTED_STREAM_NOT_ALLOWED_PUBLISHED, - Constants.ERR_INVALID_USER_ACCOUNT, - Constants.ERR_PUBLISH_STREAM_CDN_ERROR, - Constants.ERR_PUBLISH_STREAM_NUM_REACH_LIMIT, - Constants.ERR_PUBLISH_STREAM_NOT_AUTHORIZED, - Constants.ERR_PUBLISH_STREAM_INTERNAL_SERVER_ERROR, - Constants.ERR_PUBLISH_STREAM_NOT_FOUND, - Constants.ERR_PUBLISH_STREAM_FORMAT_NOT_SUPPORTED, - Constants.ERR_MODULE_NOT_FOUND, - Constants.ERR_ALREADY_IN_RECORDING, - Constants.ERR_LOAD_MEDIA_ENGINE, - Constants.ERR_START_CALL, - Constants.ERR_START_CAMERA, - Constants.ERR_START_VIDEO_RENDER, - Constants.ERR_ADM_GENERAL_ERROR, - Constants.ERR_ADM_JAVA_RESOURCE, - Constants.ERR_ADM_SAMPLE_RATE, - Constants.ERR_ADM_INIT_PLAYOUT, - Constants.ERR_ADM_START_PLAYOUT, - Constants.ERR_ADM_STOP_PLAYOUT, - Constants.ERR_ADM_INIT_RECORDING, - Constants.ERR_ADM_START_RECORDING, - Constants.ERR_ADM_STOP_RECORDING, - Constants.ERR_ADM_RUNTIME_PLAYOUT_ERROR, - Constants.ERR_ADM_RUNTIME_RECORDING_ERROR, - Constants.ERR_ADM_RECORD_AUDIO_FAILED, - Constants.ERR_ADM_INIT_LOOPBACK, - Constants.ERR_ADM_START_LOOPBACK, - Constants.ERR_AUDIO_BT_SCO_FAILED, - Constants.ERR_ADM_NO_RECORDING_DEVICE, - Constants.ERR_ADM_NO_PLAYOUT_DEVICE, - Constants.ERR_VDM_CAMERA_NOT_AUTHORIZED, - Constants.ERR_VCM_UNKNOWN_ERROR, - Constants.ERR_VCM_ENCODER_INIT_ERROR, - Constants.ERR_VCM_ENCODER_ENCODE_ERROR, - Constants.ERR_VCM_ENCODER_SET_ERROR, - }) - @Retention(RetentionPolicy.SOURCE) - public @interface AgoraErrorCode { - } - - @IntDef({ - Constants.INJECT_STREAM_STATUS_START_SUCCESS, - Constants.INJECT_STREAM_STATUS_START_ALREADY_EXISTS, - Constants.INJECT_STREAM_STATUS_START_UNAUTHORIZED, - Constants.INJECT_STREAM_STATUS_START_TIMEDOUT, - Constants.INJECT_STREAM_STATUS_START_FAILED, - Constants.INJECT_STREAM_STATUS_STOP_SUCCESS, - Constants.INJECT_STREAM_STATUS_STOP_NOT_FOUND, - Constants.INJECT_STREAM_STATUS_STOP_UNAUTHORIZED, - Constants.INJECT_STREAM_STATUS_STOP_TIMEDOUT, - Constants.INJECT_STREAM_STATUS_STOP_FAILED, - Constants.INJECT_STREAM_STATUS_BROKEN, - }) - @Retention(RetentionPolicy.SOURCE) - public @interface AgoraInjectStreamStatus { - } - - @IntDef({ - Constants.LASTMILE_PROBE_RESULT_COMPLETE, - Constants.LASTMILE_PROBE_RESULT_INCOMPLETE_NO_BWE, - Constants.LASTMILE_PROBE_RESULT_UNAVAILABLE, - }) - @Retention(RetentionPolicy.SOURCE) - public @interface AgoraLastmileProbeResultState { - } - - @IntDef({ - BeautyOptions.LIGHTENING_CONTRAST_LOW, - BeautyOptions.LIGHTENING_CONTRAST_NORMAL, - BeautyOptions.LIGHTENING_CONTRAST_HIGH, - }) - @Retention(RetentionPolicy.SOURCE) - public @interface AgoraLighteningContrastLevel { - } - - @IntDef({ - Constants.LOCAL_VIDEO_STREAM_ERROR_OK, - Constants.LOCAL_VIDEO_STREAM_ERROR_FAILURE, - Constants.LOCAL_VIDEO_STREAM_ERROR_DEVICE_NO_PERMISSION, - Constants.LOCAL_VIDEO_STREAM_ERROR_DEVICE_BUSY, - Constants.LOCAL_VIDEO_STREAM_ERROR_CAPTURE_FAILURE, - Constants.LOCAL_VIDEO_STREAM_ERROR_ENCODE_FAILURE, - Constants.LOCAL_VIDEO_STREAM_ERROR_DEVICE_NOT_FOUND - }) - @Retention(RetentionPolicy.SOURCE) - public @interface AgoraLocalVideoStreamError { - } - - @IntDef({ - Constants.LOCAL_VIDEO_STREAM_STATE_STOPPED, - Constants.LOCAL_VIDEO_STREAM_STATE_CAPTURING, - Constants.LOCAL_VIDEO_STREAM_STATE_ENCODING, - Constants.LOCAL_VIDEO_STREAM_STATE_FAILED, - }) - @Retention(RetentionPolicy.SOURCE) - public @interface AgoraLocalVideoStreamState { - } - - @IntDef({ - Constants.LOG_FILTER_OFF, - Constants.LOG_FILTER_DEBUG, - Constants.LOG_FILTER_INFO, - Constants.LOG_FILTER_WARNING, - Constants.LOG_FILTER_ERROR, - Constants.LOG_FILTER_CRITICAL, - }) - @Retention(RetentionPolicy.SOURCE) - public @interface AgoraLogFilter { - } - - @IntDef({ - Constants.QUALITY_UNKNOWN, - Constants.QUALITY_EXCELLENT, - Constants.QUALITY_GOOD, - Constants.QUALITY_POOR, - Constants.QUALITY_BAD, - Constants.QUALITY_VBAD, - Constants.QUALITY_DOWN, - Constants.QUALITY_UNSUPPORTED, - Constants.QUALITY_DETECTING, - }) - @Retention(RetentionPolicy.SOURCE) - public @interface AgoraNetworkQuality { - } - - @IntDef({ - Constants.NETWORK_TYPE_UNKNOWN, - Constants.NETWORK_TYPE_DISCONNECTED, - Constants.NETWORK_TYPE_LAN, - Constants.NETWORK_TYPE_WIFI, - Constants.NETWORK_TYPE_MOBILE_2G, - Constants.NETWORK_TYPE_MOBILE_3G, - Constants.NETWORK_TYPE_MOBILE_4G, - }) - @Retention(RetentionPolicy.SOURCE) - public @interface AgoraNetworkType { - } - - @IntDef({ - Constants.RTMP_STREAM_PUBLISH_ERROR_OK, - Constants.RTMP_STREAM_PUBLISH_ERROR_INVALID_ARGUMENT, - Constants.RTMP_STREAM_PUBLISH_ERROR_ENCRYPTED_STREAM_NOT_ALLOWED, - Constants.RTMP_STREAM_PUBLISH_ERROR_CONNECTION_TIMEOUT, - Constants.RTMP_STREAM_PUBLISH_ERROR_INTERNAL_SERVER_ERROR, - Constants.RTMP_STREAM_PUBLISH_ERROR_RTMP_SERVER_ERROR, - Constants.RTMP_STREAM_PUBLISH_ERROR_TOO_OFTEN, - Constants.RTMP_STREAM_PUBLISH_ERROR_REACH_LIMIT, - Constants.RTMP_STREAM_PUBLISH_ERROR_NOT_AUTHORIZED, - Constants.RTMP_STREAM_PUBLISH_ERROR_STREAM_NOT_FOUND, - Constants.RTMP_STREAM_PUBLISH_ERROR_FORMAT_NOT_SUPPORTED, - Constants.RTMP_STREAM_UNPUBLISH_ERROR_OK, - }) - @Retention(RetentionPolicy.SOURCE) - public @interface AgoraRtmpStreamingErrorCode { - } - - @IntDef({ - Constants.RTMP_STREAM_PUBLISH_STATE_IDLE, - Constants.RTMP_STREAM_PUBLISH_STATE_CONNECTING, - Constants.RTMP_STREAM_PUBLISH_STATE_RUNNING, - Constants.RTMP_STREAM_PUBLISH_STATE_RECOVERING, - Constants.RTMP_STREAM_PUBLISH_STATE_FAILURE, - }) - @Retention(RetentionPolicy.SOURCE) - public @interface AgoraRtmpStreamingState { - } - - @IntDef({ - Constants.STREAM_FALLBACK_OPTION_DISABLED, - Constants.STREAM_FALLBACK_OPTION_VIDEO_STREAM_LOW, - Constants.STREAM_FALLBACK_OPTION_AUDIO_ONLY, - }) - @Retention(RetentionPolicy.SOURCE) - public @interface AgoraStreamFallbackOptions { - } - - @IntDef({ - Constants.USER_OFFLINE_QUIT, - Constants.USER_OFFLINE_DROPPED, - Constants.USER_OFFLINE_BECOME_AUDIENCE, - }) - @Retention(RetentionPolicy.SOURCE) - public @interface AgoraUserOfflineReason { - } - - @IntDef({ - Constants.USER_PRIORITY_HIGH, - Constants.USER_PRIORITY_NORMAL, - }) - @Retention(RetentionPolicy.SOURCE) - public @interface AgoraUserPriority { - } - - @IntDef({ - AgoraVideoCodecProfileType.BASELINE, - AgoraVideoCodecProfileType.MAIN, - AgoraVideoCodecProfileType.HIGH, - }) - @Retention(RetentionPolicy.SOURCE) - public @interface AgoraVideoCodecProfileType { - int BASELINE = 66; - int MAIN = 77; - int HIGH = 100; - } - - @IntDef({ - AgoraVideoFrameRate.FRAME_RATE_FPS_1, - AgoraVideoFrameRate.FRAME_RATE_FPS_7, - AgoraVideoFrameRate.FRAME_RATE_FPS_10, - AgoraVideoFrameRate.FRAME_RATE_FPS_15, - AgoraVideoFrameRate.FRAME_RATE_FPS_24, - AgoraVideoFrameRate.FRAME_RATE_FPS_30, - }) - @Retention(RetentionPolicy.SOURCE) - public @interface AgoraVideoFrameRate { - int FRAME_RATE_FPS_1 = 1; - int FRAME_RATE_FPS_7 = 7; - int FRAME_RATE_FPS_10 = 10; - int FRAME_RATE_FPS_15 = 15; - int FRAME_RATE_FPS_24 = 24; - int FRAME_RATE_FPS_30 = 30; - } - - @IntDef({ - Constants.VIDEO_MIRROR_MODE_AUTO, - Constants.VIDEO_MIRROR_MODE_ENABLED, - Constants.VIDEO_MIRROR_MODE_DISABLED, - }) - @Retention(RetentionPolicy.SOURCE) - public @interface AgoraVideoMirrorMode { - } - - @IntDef({ - AgoraVideoOutputOrientationMode.ORIENTATION_MODE_ADAPTIVE, - AgoraVideoOutputOrientationMode.ORIENTATION_MODE_FIXED_LANDSCAPE, - AgoraVideoOutputOrientationMode.ORIENTATION_MODE_FIXED_PORTRAIT, - }) - @Retention(RetentionPolicy.SOURCE) - public @interface AgoraVideoOutputOrientationMode { - int ORIENTATION_MODE_ADAPTIVE = 0; - int ORIENTATION_MODE_FIXED_LANDSCAPE = 1; - int ORIENTATION_MODE_FIXED_PORTRAIT = 2; - } - - @IntDef({ - Constants.ADAPT_NONE, - Constants.ADAPT_UP_BANDWIDTH, - Constants.ADAPT_DOWN_BANDWIDTH, - }) - @Retention(RetentionPolicy.SOURCE) - public @interface AgoraVideoQualityAdaptIndication { - } - - @IntDef({ - Constants.REMOTE_VIDEO_STATE_STOPPED, - Constants.REMOTE_VIDEO_STATE_STARTING, - Constants.REMOTE_VIDEO_STATE_DECODING, - Constants.REMOTE_VIDEO_STATE_FROZEN, - Constants.REMOTE_VIDEO_STATE_FAILED, - }) - @Retention(RetentionPolicy.SOURCE) - public @interface AgoraVideoRemoteState { - } - - @IntDef({ - Constants.REMOTE_VIDEO_STATE_REASON_INTERNAL, - Constants.REMOTE_VIDEO_STATE_REASON_NETWORK_CONGESTION, - Constants.REMOTE_VIDEO_STATE_REASON_NETWORK_RECOVERY, - Constants.REMOTE_VIDEO_STATE_REASON_LOCAL_MUTED, - Constants.REMOTE_VIDEO_STATE_REASON_LOCAL_UNMUTED, - Constants.REMOTE_VIDEO_STATE_REASON_REMOTE_MUTED, - Constants.REMOTE_VIDEO_STATE_REASON_REMOTE_UNMUTED, - Constants.REMOTE_VIDEO_STATE_REASON_REMOTE_OFFLINE, - Constants.REMOTE_VIDEO_STATE_REASON_AUDIO_FALLBACK, - Constants.REMOTE_VIDEO_STATE_REASON_AUDIO_FALLBACK_RECOVERY, - }) - @Retention(RetentionPolicy.SOURCE) - public @interface AgoraVideoRemoteStateReason { - } - - @IntDef({ - VideoCanvas.RENDER_MODE_HIDDEN, - VideoCanvas.RENDER_MODE_FIT, - VideoCanvas.RENDER_MODE_ADAPTIVE, - VideoCanvas.RENDER_MODE_FILL, - }) - @Retention(RetentionPolicy.SOURCE) - public @interface AgoraVideoRenderMode { - } - - @IntDef({ - Constants.VIDEO_STREAM_HIGH, - Constants.VIDEO_STREAM_LOW, - }) - @Retention(RetentionPolicy.SOURCE) - public @interface AgoraVideoStreamType { - } - - @IntDef({ - Constants.WARN_INVALID_VIEW, - Constants.WARN_INIT_VIDEO, - Constants.WARN_PENDING, - Constants.WARN_NO_AVAILABLE_CHANNEL, - Constants.WARN_LOOKUP_CHANNEL_TIMEOUT, - Constants.WARN_LOOKUP_CHANNEL_REJECTED, - Constants.WARN_OPEN_CHANNEL_TIMEOUT, - Constants.WARN_OPEN_CHANNEL_REJECTED, - Constants.WARN_SWITCH_LIVE_VIDEO_TIMEOUT, - Constants.WARN_SET_CLIENT_ROLE_TIMEOUT, - Constants.WARN_SET_CLIENT_ROLE_NOT_AUTHORIZED, - Constants.WARN_OPEN_CHANNEL_INVALID_TICKET, - Constants.WARN_OPEN_CHANNEL_TRY_NEXT_VOS, - Constants.WARN_AUDIO_MIXING_OPEN_ERROR, - Constants.WARN_ADM_RUNTIME_PLAYOUT_WARNING, - Constants.WARN_ADM_RUNTIME_RECORDING_WARNING, - Constants.WARN_ADM_RECORD_AUDIO_SILENCE, - Constants.WARN_ADM_PLAYOUT_ABNORMAL_FREQUENCY, - Constants.WARN_ADM_RECORD_ABNORMAL_FREQUENCY, - Constants.WARN_ADM_CALL_INTERRUPTION, - Constants.WARN_ADM_RECORD_AUDIO_LOWLEVEL, - Constants.WARN_ADM_PLAYOUT_AUDIO_LOWLEVEL, - Constants.WARN_ADM_RECORD_IS_OCCUPIED, - Constants.WARN_APM_HOWLING, - Constants.WARN_ADM_GLITCH_STATE, - Constants.WARN_APM_RESIDUAL_ECHO, - Constants.WARN_SUPER_RESOLUTION_STREAM_OVER_LIMITATION, - Constants.WARN_SUPER_RESOLUTION_USER_COUNT_OVER_LIMITATION, - Constants.WARN_SUPER_RESOLUTION_DEVICE_NOT_SUPPORTED, - }) - @Retention(RetentionPolicy.SOURCE) - public @interface AgoraWarningCode { - } - - @IntDef({ - RtcEngineConfig.AreaCode.AREA_CODE_CN, - RtcEngineConfig.AreaCode.AREA_CODE_NA, - RtcEngineConfig.AreaCode.AREA_CODE_EU, - RtcEngineConfig.AreaCode.AREA_CODE_AS, - RtcEngineConfig.AreaCode.AREA_CODE_JP, - RtcEngineConfig.AreaCode.AREA_CODE_IN, - RtcEngineConfig.AreaCode.AREA_CODE_GLOB, - }) - @Retention(RetentionPolicy.SOURCE) - public @interface AgoraAreaCode { - } - - @IntDef({ - Constants.SUB_STATE_IDLE, - Constants.SUB_STATE_NO_SUBSCRIBED, - Constants.SUB_STATE_SUBSCRIBING, - Constants.SUB_STATE_SUBSCRIBED, - }) - @Retention(RetentionPolicy.SOURCE) - public @interface AgoraStreamSubscribeState { - } - - @IntDef({ - Constants.PUB_STATE_IDLE, - Constants.PUB_STATE_NO_PUBLISHED, - Constants.PUB_STATE_PUBLISHING, - Constants.PUB_STATE_PUBLISHED, - }) - @Retention(RetentionPolicy.SOURCE) - public @interface AgoraStreamPublishState { - } - - @IntDef({ - Constants.RTMP_STREAMING_EVENT_FAILED_LOAD_IMAGE, - Constants.RTMP_STREAMING_EVENT_URL_ALREADY_IN_USE, - }) - @Retention(RetentionPolicy.SOURCE) - public @interface AgoraRtmpStreamingEvent { - } - - @IntDef({ - Constants.AUDIO_EFFECT_OFF, - Constants.ROOM_ACOUSTICS_KTV, - Constants.ROOM_ACOUSTICS_VOCAL_CONCERT, - Constants.ROOM_ACOUSTICS_STUDIO, - Constants.ROOM_ACOUSTICS_PHONOGRAPH, - Constants.ROOM_ACOUSTICS_VIRTUAL_STEREO, - Constants.ROOM_ACOUSTICS_SPACIAL, - Constants.ROOM_ACOUSTICS_ETHEREAL, - Constants.ROOM_ACOUSTICS_3D_VOICE, - Constants.VOICE_CHANGER_EFFECT_UNCLE, - Constants.VOICE_CHANGER_EFFECT_OLDMAN, - Constants.VOICE_CHANGER_EFFECT_BOY, - Constants.VOICE_CHANGER_EFFECT_SISTER, - Constants.VOICE_CHANGER_EFFECT_GIRL, - Constants.VOICE_CHANGER_EFFECT_PIGKING, - Constants.VOICE_CHANGER_EFFECT_HULK, - Constants.STYLE_TRANSFORMATION_RNB, - Constants.STYLE_TRANSFORMATION_POPULAR, - Constants.PITCH_CORRECTION, - }) - @Retention(RetentionPolicy.SOURCE) - public @interface AgoraAudioEffectPreset { - } - - @IntDef({ - Constants.VOICE_BEAUTIFIER_OFF, - Constants.CHAT_BEAUTIFIER_MAGNETIC, - Constants.CHAT_BEAUTIFIER_FRESH, - Constants.CHAT_BEAUTIFIER_VITALITY, - Constants.SINGING_BEAUTIFIER, - Constants.TIMBRE_TRANSFORMATION_VIGOROUS, - Constants.TIMBRE_TRANSFORMATION_DEEP, - Constants.TIMBRE_TRANSFORMATION_MELLOW, - Constants.TIMBRE_TRANSFORMATION_FALSETTO, - Constants.TIMBRE_TRANSFORMATION_FULL, - Constants.TIMBRE_TRANSFORMATION_CLEAR, - Constants.TIMBRE_TRANSFORMATION_RESOUNDING, - Constants.TIMBRE_TRANSFORMATION_RINGING, - }) - @Retention(RetentionPolicy.SOURCE) - public @interface AgoraVoiceBeautifierPreset { - } - - @IntDef({ - Constants.AUDIENCE_LATENCY_LEVEL_LOW_LATENCY, - Constants.AUDIENCE_LATENCY_LEVEL_ULTRA_LOW_LATENCY, - }) - @Retention(RetentionPolicy.SOURCE) - public @interface AgoraAudienceLatencyLevelType { - } - - @IntDef({ - Constants.TRANSPORT_TYPE_NONE_PROXY, - Constants.TRANSPORT_TYPE_UDP_PROXY, - Constants.TRANSPORT_TYPE_TCP_PROXY, - }) - @Retention(RetentionPolicy.SOURCE) - public @interface AgoraCloudProxyType { - } - - @IntDef({ - AgoraLogLevel.LOG_LEVEL_NONE, - AgoraLogLevel.LOG_LEVEL_INFO, - AgoraLogLevel.LOG_LEVEL_WARN, - AgoraLogLevel.LOG_LEVEL_ERROR, - AgoraLogLevel.LOG_LEVEL_FATAL, - }) - @Retention(RetentionPolicy.SOURCE) - public @interface AgoraLogLevel { - int LOG_LEVEL_NONE = 0; - int LOG_LEVEL_INFO = 1; - int LOG_LEVEL_WARN = 2; - int LOG_LEVEL_ERROR = 4; - int LOG_LEVEL_FATAL = 8; - } - - @IntDef({ - Constants.CAPTURE_BRIGHTNESS_LEVEL_INVALID, - Constants.CAPTURE_BRIGHTNESS_LEVEL_NORMAL, - Constants.CAPTURE_BRIGHTNESS_LEVEL_BRIGHT, - Constants.CAPTURE_BRIGHTNESS_LEVEL_DARK, - }) - @Retention(RetentionPolicy.SOURCE) - public @interface AgoraCaptureBrightnessLevelType { - } - - @IntDef({ - IRtcEngineEventHandler.UploadErrorReason.UPLOAD_SUCCESS, - IRtcEngineEventHandler.UploadErrorReason.UPLOAD_NET_ERROR, - IRtcEngineEventHandler.UploadErrorReason.UPLOAD_SERVER_ERROR, - }) - @Retention(RetentionPolicy.SOURCE) - public @interface AgoraUploadErrorReason { - } - - @IntDef({ - IRtcEngineEventHandler.ExperienceQuality.EXPERIENCE_GOOD, - IRtcEngineEventHandler.ExperienceQuality.EXPERIENCE_BAD, - }) - @Retention(RetentionPolicy.SOURCE) - public @interface AgoraExperienceQualityType { - } - - @IntDef({ - IRtcEngineEventHandler.ExperiencePoorReason.EXPERIENCE_REASON_NONE, - IRtcEngineEventHandler.ExperiencePoorReason.REMOTE_NETWORK_QUALITY_POOR, - IRtcEngineEventHandler.ExperiencePoorReason.LOCAL_NETWORK_QUALITY_POOR, - IRtcEngineEventHandler.ExperiencePoorReason.WIRELESS_SIGNAL_POOR, - IRtcEngineEventHandler.ExperiencePoorReason.WIFI_BLUETOOTH_COEXIST, - }) - @Retention(RetentionPolicy.SOURCE) - public @interface AgoraExperiencePoorReason { - } - - @IntDef({ - Constants.SR_STATE_REASON_SUCCESS, - Constants.SR_STATE_REASON_STREAM_OVER_LIMITATION, - Constants.SR_STATE_REASON_USER_COUNT_OVER_LIMITATION, - Constants.SR_STATE_REASON_DEVICE_NOT_SUPPORTED, - }) - @Retention(RetentionPolicy.SOURCE) - public @interface AgoraSuperResolutionStateReason { - } - - @IntDef({ - VirtualBackgroundSource.BACKGROUND_COLOR, - VirtualBackgroundSource.BACKGROUND_IMG, - VirtualBackgroundSource.BACKGROUND_BLUR, - }) - @Retention(RetentionPolicy.SOURCE) - public @interface AgoraVirtualBackgroundSourceType { - } - - @IntDef({ - Constants.VBS_STATE_REASON_SUCCESS, - Constants.VBS_STATE_REASON_IMAGE_NOT_EXIST, - Constants.VBS_STATE_REASON_COLOR_FORMAT_NOT_SUPPORTED, - Constants.VBS_STATE_REASON_DEVICE_NOT_SUPPORTED, - }) - @Retention(RetentionPolicy.SOURCE) - public @interface AgoraVirtualBackgroundSourceStateReason { - } -} diff --git a/android/src/main/java/io/agora/rtc/base/BeanCovertor.kt b/android/src/main/java/io/agora/rtc/base/BeanCovertor.kt deleted file mode 100644 index f72b2b3dd..000000000 --- a/android/src/main/java/io/agora/rtc/base/BeanCovertor.kt +++ /dev/null @@ -1,271 +0,0 @@ -package io.agora.rtc.base - -import io.agora.rtc.RtcEngineConfig -import io.agora.rtc.audio.AgoraRhythmPlayerConfig -import io.agora.rtc.audio.AudioRecordingConfiguration -import io.agora.rtc.internal.EncryptionConfig -import io.agora.rtc.internal.LastmileProbeConfig -import io.agora.rtc.live.LiveInjectStreamConfig -import io.agora.rtc.live.LiveTranscoding -import io.agora.rtc.live.LiveTranscoding.TranscodingUser -import io.agora.rtc.models.ChannelMediaOptions -import io.agora.rtc.models.ClientRoleOptions -import io.agora.rtc.models.DataStreamConfig -import io.agora.rtc.models.EchoTestConfiguration -import io.agora.rtc.video.* - -fun mapToVideoDimensions(map: Map<*, *>): VideoEncoderConfiguration.VideoDimensions { - return VideoEncoderConfiguration.VideoDimensions().apply { - (map["width"] as? Number)?.let { width = it.toInt() } - (map["height"] as? Number)?.let { height = it.toInt() } - } -} - -fun mapToVideoEncoderConfiguration(map: Map<*, *>): VideoEncoderConfiguration { - return VideoEncoderConfiguration().apply { - (map["dimensions"] as? Map<*, *>)?.let { dimensions = mapToVideoDimensions(it) } - (map["frameRate"] as? Number)?.let { frameRate = it.toInt() } - (map["minFrameRate"] as? Number)?.let { minFrameRate = it.toInt() } - (map["bitrate"] as? Number)?.let { bitrate = it.toInt() } - (map["minBitrate"] as? Number)?.let { minBitrate = it.toInt() } - (map["orientationMode"] as? Number)?.let { orientationMode = intToOrientationMode(it.toInt()) } - (map["degradationPrefer"] as? Number)?.let { - degradationPrefer = intToDegradationPreference(it.toInt()) - } - (map["mirrorMode"] as? Number)?.let { mirrorMode = it.toInt() } - } -} - -fun mapToBeautyOptions(map: Map<*, *>): BeautyOptions { - return BeautyOptions().apply { - (map["lighteningContrastLevel"] as? Number)?.let { lighteningContrastLevel = it.toInt() } - (map["lighteningLevel"] as? Number)?.let { lighteningLevel = it.toFloat() } - (map["smoothnessLevel"] as? Number)?.let { smoothnessLevel = it.toFloat() } - (map["rednessLevel"] as? Number)?.let { rednessLevel = it.toFloat() } - } -} - -fun mapToAgoraImage(map: Map<*, *>): AgoraImage { - return AgoraImage().apply { - (map["url"] as? String)?.let { url = it } - (map["x"] as? Number)?.let { x = it.toInt() } - (map["y"] as? Number)?.let { y = it.toInt() } - (map["width"] as? Number)?.let { width = it.toInt() } - (map["height"] as? Number)?.let { height = it.toInt() } - } -} - -fun mapToTranscodingUser(map: Map<*, *>): TranscodingUser { - return TranscodingUser().apply { - (map["uid"] as? Number)?.let { uid = it.toNativeUInt() } - (map["x"] as? Number)?.let { x = it.toInt() } - (map["y"] as? Number)?.let { y = it.toInt() } - (map["width"] as? Number)?.let { width = it.toInt() } - (map["height"] as? Number)?.let { height = it.toInt() } - (map["zOrder"] as? Number)?.let { zOrder = it.toInt() } - (map["alpha"] as? Number)?.let { alpha = it.toFloat() } - (map["audioChannel"] as? Number)?.let { audioChannel = it.toInt() } - } -} - -fun mapToColor(map: Map<*, *>): Int { - return ((map["red"] as Number).toInt() shl 16) + ((map["green"] as Number).toInt() shl 8) + (map["blue"] as Number).toInt() -} - -fun mapToLiveTranscoding(map: Map<*, *>): LiveTranscoding { - return LiveTranscoding().apply { - (map["width"] as? Number)?.let { width = it.toInt() } - (map["height"] as? Number)?.let { height = it.toInt() } - (map["videoBitrate"] as? Number)?.let { videoBitrate = it.toInt() } - (map["videoFramerate"] as? Number)?.let { videoFramerate = it.toInt() } - (map["lowLatency"] as? Boolean)?.let { lowLatency = it } - (map["videoGop"] as? Number)?.let { videoGop = it.toInt() } - (map["watermark"] as? Map<*, *>)?.let { watermark = mapToAgoraImage(it) } - (map["backgroundImage"] as? Map<*, *>)?.let { backgroundImage = mapToAgoraImage(it) } - (map["audioSampleRate"] as? Number)?.let { - audioSampleRate = intToLiveTranscodingAudioSampleRate(it.toInt()) - } - (map["audioBitrate"] as? Number)?.let { audioBitrate = it.toInt() } - (map["audioChannels"] as? Number)?.let { audioChannels = it.toInt() } - (map["audioCodecProfile"] as? Number)?.let { - audioCodecProfile = intToAudioCodecProfile(it.toInt()) - } - (map["videoCodecProfile"] as? Number)?.let { - videoCodecProfile = intToVideoCodecProfile(it.toInt()) - } - (map["backgroundColor"] as? Map<*, *>)?.let { backgroundColor = mapToColor(it) } - (map["userConfigExtraInfo"] as? String)?.let { userConfigExtraInfo = it } - (map["transcodingUsers"] as? List<*>)?.let { list -> - list.forEach { item -> - (item as? Map<*, *>)?.let { - addUser(mapToTranscodingUser(it)) - } - } - } - } -} - -fun mapToChannelMediaInfo(map: Map<*, *>): ChannelMediaInfo { - return ChannelMediaInfo( - map["channelName"] as? String, - map["token"] as? String, - (map["uid"] as Number).toNativeUInt() - ) -} - -fun mapToChannelMediaRelayConfiguration(map: Map<*, *>): ChannelMediaRelayConfiguration { - return ChannelMediaRelayConfiguration().apply { - (map["srcInfo"] as? Map<*, *>)?.let { setSrcChannelInfo(mapToChannelMediaInfo(it)) } - (map["destInfos"] as? List<*>)?.let { list -> - list.forEach { item -> - (item as? Map<*, *>)?.let { - val info = mapToChannelMediaInfo(it) - setDestChannelInfo(info.channelName, info) - } - } - } - } -} - -fun mapToLastmileProbeConfig(map: Map<*, *>): LastmileProbeConfig { - return LastmileProbeConfig().apply { - (map["probeUplink"] as? Boolean)?.let { probeUplink = it } - (map["probeDownlink"] as? Boolean)?.let { probeDownlink = it } - (map["expectedUplinkBitrate"] as? Number)?.let { expectedUplinkBitrate = it.toInt() } - (map["expectedDownlinkBitrate"] as? Number)?.let { expectedUplinkBitrate = it.toInt() } - } -} - -fun mapToRectangle(map: Map<*, *>): WatermarkOptions.Rectangle { - return WatermarkOptions.Rectangle().apply { - (map["x"] as? Number)?.let { x = it.toInt() } - (map["y"] as? Number)?.let { y = it.toInt() } - (map["width"] as? Number)?.let { width = it.toInt() } - (map["height"] as? Number)?.let { height = it.toInt() } - } -} - -fun mapToWatermarkOptions(map: Map<*, *>): WatermarkOptions { - return WatermarkOptions().apply { - (map["visibleInPreview"] as? Boolean)?.let { visibleInPreview = it } - (map["positionInLandscapeMode"] as? Map<*, *>)?.let { - positionInLandscapeMode = mapToRectangle(it) - } - (map["positionInPortraitMode"] as? Map<*, *>)?.let { - positionInPortraitMode = mapToRectangle(it) - } - } -} - -fun mapToLiveInjectStreamConfig(map: Map<*, *>): LiveInjectStreamConfig { - return LiveInjectStreamConfig().apply { - (map["width"] as? Number)?.let { width = it.toInt() } - (map["height"] as? Number)?.let { height = it.toInt() } - (map["videoGop"] as? Number)?.let { videoGop = it.toInt() } - (map["videoFramerate"] as? Number)?.let { videoFramerate = it.toInt() } - (map["videoBitrate"] as? Number)?.let { videoBitrate = it.toInt() } - (map["audioSampleRate"] as? Number)?.let { - audioSampleRate = intToLiveInjectStreamConfigAudioSampleRate(it.toInt()) - } - (map["audioBitrate"] as? Number)?.let { audioBitrate = it.toInt() } - (map["audioChannels"] as? Number)?.let { audioChannels = it.toInt() } - } -} - -fun mapToRhythmPlayerConfig(map: Map<*, *>): AgoraRhythmPlayerConfig { - return AgoraRhythmPlayerConfig().apply { - (map["beatsPerMeasure"] as? Number)?.let { beatsPerMeasure = it.toInt() } - (map["beatsPerMinute"] as? Number)?.let { beatsPerMinute = it.toInt() } - (map["publish"] as? Boolean)?.let { publish = it } - } -} - -fun mapToCameraCapturerConfiguration(map: Map<*, *>): CameraCapturerConfiguration { - return CameraCapturerConfiguration( - intToCapturerOutputPreference((map["preference"] as Number).toInt()), - intToCameraDirection((map["cameraDirection"] as Number).toInt()) - ).apply { - dimensions = CameraCapturerConfiguration.CaptureDimensions() - (map["captureWidth"] as? Number)?.toInt()?.let { dimensions.width = it } - (map["captureHeight"] as? Number)?.toInt()?.let { dimensions.height = it } - } -} - -fun mapToChannelMediaOptions(map: Map<*, *>): ChannelMediaOptions { - return ChannelMediaOptions().apply { - (map["autoSubscribeAudio"] as? Boolean)?.let { autoSubscribeAudio = it } - (map["autoSubscribeVideo"] as? Boolean)?.let { autoSubscribeVideo = it } - (map["publishLocalAudio"] as? Boolean)?.let { publishLocalAudio = it } - (map["publishLocalVideo"] as? Boolean)?.let { publishLocalVideo = it } - } -} - -fun mapToRtcEngineConfig(map: Map<*, *>): RtcEngineConfig { - return RtcEngineConfig().apply { - mAppId = map["appId"] as String - (map["areaCode"] as? Number)?.toInt()?.let { mAreaCode = it } - (map["logConfig"] as? Map<*, *>)?.let { mLogConfig = mapToLogConfig(it) } - } -} - -fun mapToAudioRecordingConfiguration(map: Map<*, *>): AudioRecordingConfiguration { - return AudioRecordingConfiguration().apply { - (map["filePath"] as? String)?.let { filePath = it } - (map["recordingQuality"] as? Number)?.let { recordingQuality = it.toInt() } - (map["recordingPosition"] as? Number)?.let { recordingPosition = it.toInt() } - (map["recordingSampleRate"] as? Number)?.let { recordingSampleRate = it.toInt() } - } -} - -fun mapToEncryptionConfig(map: Map<*, *>): EncryptionConfig { - return EncryptionConfig().apply { - (map["encryptionMode"] as? Number)?.let { encryptionMode = intToEncryptionMode(it.toInt()) } - (map["encryptionKey"] as? String)?.let { encryptionKey = it } - (map["encryptionKdfSalt"] as? List<*>)?.let { list -> - for (i in list.indices) { - (list[i] as? Number)?.let { - encryptionKdfSalt[i] = it.toByte() - } - } - } - } -} - -fun mapToClientRoleOptions(map: Map<*, *>): ClientRoleOptions { - return ClientRoleOptions().apply { - (map["audienceLatencyLevel"] as? Number)?.let { audienceLatencyLevel = it.toInt() } - } -} - -fun mapToLogConfig(map: Map<*, *>): RtcEngineConfig.LogConfig { - return RtcEngineConfig.LogConfig().apply { - (map["filePath"] as? String)?.let { filePath = it } - (map["fileSize"] as? Number)?.let { fileSize = it.toInt() } - (map["level"] as? Number)?.let { level = it.toInt() } - } -} - -fun mapToDataStreamConfig(map: Map<*, *>): DataStreamConfig { - return DataStreamConfig().apply { - (map["syncWithAudio"] as? Boolean)?.let { syncWithAudio = it } - (map["ordered"] as? Boolean)?.let { ordered = it } - } -} - -fun mapToVirtualBackgroundSource(map: Map<*, *>): VirtualBackgroundSource { - return VirtualBackgroundSource().apply { - (map["backgroundSourceType"] as? Number)?.let { backgroundSourceType = it.toInt() } - (map["color"] as? Map<*, *>)?.let { color = mapToColor(it) } - (map["source"] as? String)?.let { source = it } - (map["blur_degree"] as? Int)?.let { blur_degree = it } - } -} - -fun mapToEchoTestConfiguration(map: Map<*, *>): EchoTestConfiguration { - return EchoTestConfiguration().apply { - (map["enableAudio"] as? Boolean)?.let { enableAudio = it } - (map["enableVideo"] as? Boolean)?.let { enableVideo = it } - (map["token"] as? String)?.let { token = it } - (map["channelId"] as? String)?.let { channelId = it } - } -} diff --git a/android/src/main/java/io/agora/rtc/base/Callback.kt b/android/src/main/java/io/agora/rtc/base/Callback.kt deleted file mode 100644 index 0d9b69378..000000000 --- a/android/src/main/java/io/agora/rtc/base/Callback.kt +++ /dev/null @@ -1,41 +0,0 @@ -package io.agora.rtc.base - -import io.agora.rtc.Constants -import io.agora.rtc.RtcEngine -import kotlin.math.abs - -abstract class Callback { - fun code(code: Int?, runnable: ((Int?) -> Any?)? = null) { - if (code == null || code < 0) { - val newCode = abs(code ?: Constants.ERR_NOT_INITIALIZED) - failure(newCode.toString(), RtcEngine.getErrorDescription(newCode)) - return - } - - val res = if (runnable != null) runnable(code) else Unit - if (res is Unit) { - success(null) - } else { - success(res) - } - } - - fun resolve(source: T?, runnable: (T) -> Any?) { - if (source == null) { - val code = Constants.ERR_NOT_INITIALIZED - failure(code.toString(), RtcEngine.getErrorDescription(code)) - return - } - - val res = runnable(source) - if (res is Unit) { - success(null) - } else { - success(res) - } - } - - abstract fun success(data: Any?) - - abstract fun failure(code: String, message: String) -} diff --git a/android/src/main/java/io/agora/rtc/base/EnumCovertor.kt b/android/src/main/java/io/agora/rtc/base/EnumCovertor.kt deleted file mode 100644 index ea423ce69..000000000 --- a/android/src/main/java/io/agora/rtc/base/EnumCovertor.kt +++ /dev/null @@ -1,97 +0,0 @@ -package io.agora.rtc.base - -import io.agora.rtc.internal.EncryptionConfig -import io.agora.rtc.live.LiveInjectStreamConfig -import io.agora.rtc.live.LiveTranscoding -import io.agora.rtc.video.CameraCapturerConfiguration -import io.agora.rtc.video.VideoEncoderConfiguration - -fun intToFrameRate(@Annotations.AgoraVideoFrameRate intValue: Int): VideoEncoderConfiguration.FRAME_RATE { - for (value in VideoEncoderConfiguration.FRAME_RATE.values()) { - if (value.value == intValue) { - return value - } - } - throw RuntimeException("VideoEncoderConfiguration.FRAME_RATE not contains $intValue") -} - -fun intToOrientationMode(@Annotations.AgoraVideoOutputOrientationMode intValue: Int): VideoEncoderConfiguration.ORIENTATION_MODE { - for (value in VideoEncoderConfiguration.ORIENTATION_MODE.values()) { - if (value.value == intValue) { - return value - } - } - throw RuntimeException("VideoEncoderConfiguration.ORIENTATION_MODE not contains $intValue") -} - -fun intToDegradationPreference(@Annotations.AgoraDegradationPreference intValue: Int): VideoEncoderConfiguration.DEGRADATION_PREFERENCE { - for (value in VideoEncoderConfiguration.DEGRADATION_PREFERENCE.values()) { - if (value.value == intValue) { - return value - } - } - throw RuntimeException("VideoEncoderConfiguration.DEGRADATION_PREFERENCE not contains $intValue") -} - -fun intToLiveTranscodingAudioSampleRate(@Annotations.AgoraAudioSampleRateType intValue: Int): LiveTranscoding.AudioSampleRateType { - for (value in LiveTranscoding.AudioSampleRateType.values()) { - if (LiveTranscoding.AudioSampleRateType.getValue(value) == intValue) { - return value - } - } - throw RuntimeException("LiveTranscoding.AudioSampleRateType not contains $intValue") -} - -fun intToLiveInjectStreamConfigAudioSampleRate(@Annotations.AgoraAudioSampleRateType intValue: Int): LiveInjectStreamConfig.AudioSampleRateType { - for (value in LiveInjectStreamConfig.AudioSampleRateType.values()) { - if (LiveInjectStreamConfig.AudioSampleRateType.getValue(value) == intValue) { - return value - } - } - throw RuntimeException("LiveInjectStreamConfig.AudioSampleRateType not contains $intValue") -} - -fun intToAudioCodecProfile(@Annotations.AgoraAudioCodecProfileType intValue: Int): LiveTranscoding.AudioCodecProfileType { - for (value in LiveTranscoding.AudioCodecProfileType.values()) { - if (LiveTranscoding.AudioCodecProfileType.getValue(value) == intValue) { - return value - } - } - throw RuntimeException("LiveTranscoding.AudioCodecProfileType not contains $intValue") -} - -fun intToVideoCodecProfile(@Annotations.AgoraVideoCodecProfileType intValue: Int): LiveTranscoding.VideoCodecProfileType { - for (value in LiveTranscoding.VideoCodecProfileType.values()) { - if (LiveTranscoding.VideoCodecProfileType.getValue(value) == intValue) { - return value - } - } - throw RuntimeException("LiveTranscoding.VideoCodecProfileType not contains $intValue") -} - -fun intToCapturerOutputPreference(@Annotations.AgoraCameraCaptureOutputPreference intValue: Int): CameraCapturerConfiguration.CAPTURER_OUTPUT_PREFERENCE { - for (value in CameraCapturerConfiguration.CAPTURER_OUTPUT_PREFERENCE.values()) { - if (value.value == intValue) { - return value - } - } - throw RuntimeException("CameraCapturerConfiguration.CAPTURER_OUTPUT_PREFERENCE not contains $intValue") -} - -fun intToCameraDirection(@Annotations.AgoraCameraDirection intValue: Int): CameraCapturerConfiguration.CAMERA_DIRECTION { - for (value in CameraCapturerConfiguration.CAMERA_DIRECTION.values()) { - if (value.value == intValue) { - return value - } - } - throw RuntimeException("CameraCapturerConfiguration.CAMERA_DIRECTION not contains $intValue") -} - -fun intToEncryptionMode(@Annotations.AgoraEncryptionMode intValue: Int): EncryptionConfig.EncryptionMode { - for (value in EncryptionConfig.EncryptionMode.values()) { - if (value.value == intValue) { - return value - } - } - throw RuntimeException("EncryptionConfig.EncryptionMode not contains $intValue") -} diff --git a/android/src/main/java/io/agora/rtc/base/Extensions.kt b/android/src/main/java/io/agora/rtc/base/Extensions.kt deleted file mode 100644 index cb24c448c..000000000 --- a/android/src/main/java/io/agora/rtc/base/Extensions.kt +++ /dev/null @@ -1,172 +0,0 @@ -package io.agora.rtc.base - -import android.graphics.Rect -import io.agora.rtc.IRtcEngineEventHandler.* -import io.agora.rtc.models.UserInfo - -fun UserInfo.toMap(): Map { - return hashMapOf( - "uid" to uid.toUInt().toLong(), - "userAccount" to userAccount - ) -} - -fun LocalAudioStats.toMap(): Map { - return hashMapOf( - "numChannels" to numChannels, - "sentSampleRate" to sentSampleRate, - "sentBitrate" to sentBitrate, - "txPacketLossRate" to txPacketLossRate - ) -} - -fun RtcStats.toMap(): Map { - return hashMapOf( - "duration" to totalDuration, - "txBytes" to txBytes, - "rxBytes" to rxBytes, - "txAudioBytes" to txAudioBytes, - "txVideoBytes" to txVideoBytes, - "rxAudioBytes" to rxAudioBytes, - "rxVideoBytes" to rxVideoBytes, - "txKBitRate" to txKBitRate, - "rxKBitRate" to rxKBitRate, - "txAudioKBitRate" to txAudioKBitRate, - "rxAudioKBitRate" to rxAudioKBitRate, - "txVideoKBitRate" to txVideoKBitRate, - "rxVideoKBitRate" to rxVideoKBitRate, - "userCount" to users, - "lastmileDelay" to lastmileDelay, - "txPacketLossRate" to txPacketLossRate, - "rxPacketLossRate" to rxPacketLossRate, - "cpuTotalUsage" to cpuTotalUsage, - "cpuAppUsage" to cpuAppUsage, - "gatewayRtt" to gatewayRtt, - "memoryAppUsageRatio" to memoryAppUsageRatio, - "memoryTotalUsageRatio" to memoryTotalUsageRatio, - "memoryAppUsageInKbytes" to memoryAppUsageInKbytes - ) -} - -fun Rect.toMap(): Map { - return hashMapOf( - "left" to left, - "top" to top, - "right" to right, - "bottom" to bottom - ) -} - -fun RemoteAudioStats.toMap(): Map { - return hashMapOf( - "uid" to uid.toUInt().toLong(), - "quality" to quality, - "networkTransportDelay" to networkTransportDelay, - "jitterBufferDelay" to jitterBufferDelay, - "audioLossRate" to audioLossRate, - "numChannels" to numChannels, - "receivedSampleRate" to receivedSampleRate, - "receivedBitrate" to receivedBitrate, - "totalFrozenTime" to totalFrozenTime, - "frozenRate" to frozenRate, - "totalActiveTime" to totalActiveTime, - "publishDuration" to publishDuration, - "qoeQuality" to qoeQuality, - "qualityChangedReason" to qualityChangedReason, - "mosValue" to mosValue - ) -} - -fun LocalVideoStats.toMap(): Map { - return hashMapOf( - "sentBitrate" to sentBitrate, - "sentFrameRate" to sentFrameRate, - "encoderOutputFrameRate" to encoderOutputFrameRate, - "rendererOutputFrameRate" to rendererOutputFrameRate, - "targetBitrate" to targetBitrate, - "targetFrameRate" to targetFrameRate, - "qualityAdaptIndication" to qualityAdaptIndication, - "encodedBitrate" to encodedBitrate, - "encodedFrameWidth" to encodedFrameWidth, - "encodedFrameHeight" to encodedFrameHeight, - "encodedFrameCount" to encodedFrameCount, - "codecType" to codecType, - "txPacketLossRate" to txPacketLossRate, - "captureFrameRate" to captureFrameRate, - "captureBrightnessLevel" to captureBrightnessLevel - ) -} - -fun RemoteVideoStats.toMap(): Map { - return hashMapOf( - "uid" to uid.toUInt().toLong(), - "delay" to delay, - "width" to width, - "height" to height, - "receivedBitrate" to receivedBitrate, - "decoderOutputFrameRate" to decoderOutputFrameRate, - "rendererOutputFrameRate" to rendererOutputFrameRate, - "packetLossRate" to packetLossRate, - "rxStreamType" to rxStreamType, - "totalFrozenTime" to totalFrozenTime, - "frozenRate" to frozenRate, - "totalActiveTime" to totalActiveTime, - "publishDuration" to publishDuration - ) -} - -fun AudioVolumeInfo.toMap(): Map { - return hashMapOf( - "uid" to uid.toUInt().toLong(), - "volume" to volume, - "vad" to vad, - "channelId" to channelId - ) -} - -fun Array.toMapList(): List> { - return List(size) { this[it].toMap() } -} - -fun LastmileProbeResult.LastmileProbeOneWayResult.toMap(): Map { - return hashMapOf( - "packetLossRate" to packetLossRate, - "jitter" to jitter, - "availableBandwidth" to availableBandwidth - ) -} - -fun LastmileProbeResult.toMap(): Map { - return hashMapOf( - "state" to state, - "rtt" to rtt, - "uplinkReport" to uplinkReport.toMap(), - "downlinkReport" to downlinkReport.toMap() - ) -} - -fun AgoraFacePositionInfo.toMap(): Map { - return hashMapOf( - "x" to x, - "y" to y, - "width" to width, - "height" to height, - "distance" to distance - ) -} - -fun AudioFileInfo.toMap(): Map { - return hashMapOf( - "filePath" to filePath, - "durationMs" to durationMs - ) -} - -fun Array.toMapList(): List> { - return List(size) { this[it].toMap() } -} - -@ExperimentalUnsignedTypes -internal fun Number.toNativeUInt(): Int { - return toLong().toUInt().toInt() -} diff --git a/android/src/main/java/io/agora/rtc/base/MediaObserver.kt b/android/src/main/java/io/agora/rtc/base/MediaObserver.kt deleted file mode 100644 index b763cedeb..000000000 --- a/android/src/main/java/io/agora/rtc/base/MediaObserver.kt +++ /dev/null @@ -1,40 +0,0 @@ -package io.agora.rtc.base - -import androidx.annotation.IntRange -import io.agora.rtc.IMetadataObserver -import java.util.* -import java.util.concurrent.atomic.AtomicInteger - -class MediaObserver( - private val emit: (data: Map?) -> Unit -) : IMetadataObserver { - private var maxMetadataSize = AtomicInteger(1024) - private var metadataList = Collections.synchronizedList(mutableListOf()) - - fun addMetadata(metadata: String) { - metadataList.add(metadata) - } - - fun setMaxMetadataSize(@IntRange(from = 0, to = 1024) size: Int) { - maxMetadataSize.set(size) - } - - override fun onReadyToSendMetadata(timeStampMs: Long): ByteArray? { - if (metadataList.size > 0) { - return metadataList.removeAt(0).toByteArray() - } - return null - } - - override fun getMaxMetadataSize(): Int { - return maxMetadataSize.get() - } - - override fun onMetadataReceived(buffer: ByteArray, uid: Int, timeStampMs: Long) { - emit( - hashMapOf( - "data" to arrayListOf(String(buffer), uid.toUInt().toLong(), timeStampMs) - ) - ) - } -} diff --git a/android/src/main/java/io/agora/rtc/base/RtcChannel.kt b/android/src/main/java/io/agora/rtc/base/RtcChannel.kt deleted file mode 100644 index 48621739b..000000000 --- a/android/src/main/java/io/agora/rtc/base/RtcChannel.kt +++ /dev/null @@ -1,486 +0,0 @@ -package io.agora.rtc.base - -import io.agora.rtc.Constants -import io.agora.rtc.IMetadataObserver -import io.agora.rtc.RtcChannel -import io.agora.rtc.RtcEngine -import io.agora.rtc.internal.EncryptionConfig -import java.util.* - -class IRtcChannel { - interface RtcChannelInterface : RtcAudioInterface, RtcVideoInterface, RtcVoicePositionInterface, - RtcPublishStreamInterface, RtcMediaRelayInterface, RtcDualStreamInterface, - RtcFallbackInterface, RtcMediaMetadataInterface, RtcEncryptionInterface, - RtcInjectStreamInterface, RtcStreamMessageInterface { - fun create(params: Map, callback: Callback) - - fun destroy(params: Map, callback: Callback) - - fun setClientRole(params: Map, callback: Callback) - - fun joinChannel(params: Map, callback: Callback) - - fun joinChannelWithUserAccount(params: Map, callback: Callback) - - fun leaveChannel(params: Map, callback: Callback) - - fun renewToken(params: Map, callback: Callback) - - fun getConnectionState(params: Map, callback: Callback) - - @Deprecated("") - fun publish(params: Map, callback: Callback) - - @Deprecated("") - fun unpublish(params: Map, callback: Callback) - - fun getCallId(params: Map, callback: Callback) - } - - interface RtcAudioInterface { - fun adjustUserPlaybackSignalVolume(params: Map, callback: Callback) - - fun muteLocalAudioStream(params: Map, callback: Callback) - - fun muteRemoteAudioStream(params: Map, callback: Callback) - - fun muteAllRemoteAudioStreams(params: Map, callback: Callback) - - @Deprecated("") - fun setDefaultMuteAllRemoteAudioStreams(params: Map, callback: Callback) - } - - interface RtcVideoInterface { - fun muteLocalVideoStream(params: Map, callback: Callback) - - fun muteRemoteVideoStream(params: Map, callback: Callback) - - fun muteAllRemoteVideoStreams(params: Map, callback: Callback) - - @Deprecated("") - fun setDefaultMuteAllRemoteVideoStreams(params: Map, callback: Callback) - - fun enableRemoteSuperResolution(params: Map, callback: Callback) - } - - interface RtcVoicePositionInterface { - fun setRemoteVoicePosition(params: Map, callback: Callback) - } - - interface RtcPublishStreamInterface { - fun setLiveTranscoding(params: Map, callback: Callback) - - fun addPublishStreamUrl(params: Map, callback: Callback) - - fun removePublishStreamUrl(params: Map, callback: Callback) - } - - interface RtcMediaRelayInterface { - fun startChannelMediaRelay(params: Map, callback: Callback) - - fun updateChannelMediaRelay(params: Map, callback: Callback) - - fun stopChannelMediaRelay(params: Map, callback: Callback) - - fun pauseAllChannelMediaRelay(params: Map, callback: Callback) - - fun resumeAllChannelMediaRelay(params: Map, callback: Callback) - } - - interface RtcDualStreamInterface { - fun setRemoteVideoStreamType(params: Map, callback: Callback) - - fun setRemoteDefaultVideoStreamType(params: Map, callback: Callback) - } - - interface RtcFallbackInterface { - fun setRemoteUserPriority(params: Map, callback: Callback) - } - - interface RtcMediaMetadataInterface { - fun registerMediaMetadataObserver(params: Map, callback: Callback) - - fun unregisterMediaMetadataObserver(params: Map, callback: Callback) - - fun setMaxMetadataSize(params: Map, callback: Callback) - - fun sendMetadata(params: Map, callback: Callback) - } - - interface RtcEncryptionInterface { - @Deprecated("") - fun setEncryptionSecret(params: Map, callback: Callback) - - @Deprecated("") - fun setEncryptionMode(params: Map, callback: Callback) - - fun enableEncryption(params: Map, callback: Callback) - } - - interface RtcInjectStreamInterface { - fun addInjectStreamUrl(params: Map, callback: Callback) - - fun removeInjectStreamUrl(params: Map, callback: Callback) - } - - interface RtcStreamMessageInterface { - fun createDataStream(params: Map, callback: Callback) - - fun sendStreamMessage(params: Map, callback: Callback) - } -} - -class RtcChannelManager( - private val emit: (methodName: String, data: Map?) -> Unit -) : IRtcChannel.RtcChannelInterface { - private val rtcChannelMap = Collections.synchronizedMap(mutableMapOf()) - private val mediaObserverMap = Collections.synchronizedMap(mutableMapOf()) - - fun release() { - rtcChannelMap.forEach { it.value.destroy() } - rtcChannelMap.clear() - mediaObserverMap.clear() - } - - operator fun get(channelId: String): RtcChannel? { - return rtcChannelMap[channelId] - } - - override fun create(params: Map, callback: Callback) { - callback.resolve(params["engine"] as RtcEngine) { e -> - e.createRtcChannel(params["channelId"] as String)?.let { - it.setRtcChannelEventHandler(RtcChannelEventHandler { methodName, data -> - emit( - methodName, - data - ) - }) - rtcChannelMap[it.channelId()] = it - } - Unit - } - } - - override fun destroy(params: Map, callback: Callback) { - callback.code(rtcChannelMap.remove(params["channelId"] as String)?.destroy()) - } - - override fun setClientRole(params: Map, callback: Callback) { - val role = (params["role"] as Number).toInt() - (params["options"] as? Map<*, *>)?.let { - callback.code( - this[params["channelId"] as String]?.setClientRole( - role, - mapToClientRoleOptions(it) - ) - ) - return@setClientRole - } - callback.code(this[params["channelId"] as String]?.setClientRole(role)) - } - - override fun joinChannel(params: Map, callback: Callback) { - callback.code( - this[params["channelId"] as String]?.joinChannel( - params["token"] as? String, - params["optionalInfo"] as? String, - (params["optionalUid"] as Number).toNativeUInt(), - mapToChannelMediaOptions(params["options"] as Map<*, *>) - ) - ) - } - - override fun joinChannelWithUserAccount(params: Map, callback: Callback) { - callback.code( - this[params["channelId"] as String]?.joinChannelWithUserAccount( - params["token"] as? String, - params["userAccount"] as String, - mapToChannelMediaOptions(params["options"] as Map<*, *>) - ) - ) - } - - override fun leaveChannel(params: Map, callback: Callback) { - callback.code(this[params["channelId"] as String]?.leaveChannel()) - } - - override fun renewToken(params: Map, callback: Callback) { - callback.code(this[params["channelId"] as String]?.renewToken(params["token"] as String)) - } - - override fun getConnectionState(params: Map, callback: Callback) { - callback.resolve(this[params["channelId"] as String]) { it.connectionState } - } - - override fun publish(params: Map, callback: Callback) { - callback.code(this[params["channelId"] as String]?.publish()) - } - - override fun unpublish(params: Map, callback: Callback) { - callback.code(this[params["channelId"] as String]?.unpublish()) - } - - override fun getCallId(params: Map, callback: Callback) { - callback.resolve(this[params["channelId"] as String]) { it.callId } - } - - override fun adjustUserPlaybackSignalVolume(params: Map, callback: Callback) { - callback.code( - this[params["channelId"] as String]?.adjustUserPlaybackSignalVolume( - (params["uid"] as Number).toNativeUInt(), - (params["volume"] as Number).toInt() - ) - ) - } - - override fun muteLocalAudioStream(params: Map, callback: Callback) { - callback.code( - this[params["channelId"] as String]?.muteLocalAudioStream( - params["muted"] as Boolean - ) - ) - } - - override fun muteRemoteAudioStream(params: Map, callback: Callback) { - callback.code( - this[params["channelId"] as String]?.muteRemoteAudioStream( - (params["uid"] as Number).toNativeUInt(), - params["muted"] as Boolean - ) - ) - } - - override fun muteAllRemoteAudioStreams(params: Map, callback: Callback) { - callback.code(this[params["channelId"] as String]?.muteAllRemoteAudioStreams(params["muted"] as Boolean)) - } - - override fun setDefaultMuteAllRemoteAudioStreams(params: Map, callback: Callback) { - callback.code(this[params["channelId"] as String]?.setDefaultMuteAllRemoteAudioStreams(params["muted"] as Boolean)) - } - - override fun muteLocalVideoStream(params: Map, callback: Callback) { - callback.code( - this[params["channelId"] as String]?.muteLocalVideoStream( - params["muted"] as Boolean - ) - ) - } - - override fun muteRemoteVideoStream(params: Map, callback: Callback) { - callback.code( - this[params["channelId"] as String]?.muteRemoteVideoStream( - (params["uid"] as Number).toNativeUInt(), - params["muted"] as Boolean - ) - ) - } - - override fun muteAllRemoteVideoStreams(params: Map, callback: Callback) { - callback.code(this[params["channelId"] as String]?.muteAllRemoteVideoStreams(params["muted"] as Boolean)) - } - - override fun setDefaultMuteAllRemoteVideoStreams(params: Map, callback: Callback) { - callback.code(this[params["channelId"] as String]?.setDefaultMuteAllRemoteVideoStreams(params["muted"] as Boolean)) - } - - override fun enableRemoteSuperResolution(params: Map, callback: Callback) { - callback.code( - this[params["channelId"] as String]?.enableRemoteSuperResolution( - (params["uid"] as Number).toNativeUInt(), - params["enabled"] as Boolean - ) - ) - } - - override fun setRemoteVoicePosition(params: Map, callback: Callback) { - callback.code( - this[params["channelId"] as String]?.setRemoteVoicePosition( - (params["uid"] as Number).toNativeUInt(), - (params["pan"] as Number).toDouble(), - (params["gain"] as Number).toDouble() - ) - ) - } - - override fun setLiveTranscoding(params: Map, callback: Callback) { - callback.code( - this[params["channelId"] as String]?.setLiveTranscoding( - mapToLiveTranscoding( - params["transcoding"] as Map<*, *> - ) - ) - ) - } - - override fun addPublishStreamUrl(params: Map, callback: Callback) { - callback.code( - this[params["channelId"] as String]?.addPublishStreamUrl( - params["url"] as String, - params["transcodingEnabled"] as Boolean - ) - ) - } - - override fun removePublishStreamUrl(params: Map, callback: Callback) { - callback.code(this[params["channelId"] as String]?.removePublishStreamUrl(params["url"] as String)) - } - - override fun startChannelMediaRelay(params: Map, callback: Callback) { - callback.code( - this[params["channelId"] as String]?.startChannelMediaRelay( - mapToChannelMediaRelayConfiguration(params["channelMediaRelayConfiguration"] as Map<*, *>) - ) - ) - } - - override fun updateChannelMediaRelay(params: Map, callback: Callback) { - callback.code( - this[params["channelId"] as String]?.updateChannelMediaRelay( - mapToChannelMediaRelayConfiguration(params["channelMediaRelayConfiguration"] as Map<*, *>) - ) - ) - } - - override fun stopChannelMediaRelay(params: Map, callback: Callback) { - callback.code(this[params["channelId"] as String]?.stopChannelMediaRelay()) - } - - override fun pauseAllChannelMediaRelay(params: Map, callback: Callback) { - callback.code(-Constants.ERR_NOT_SUPPORTED) -// callback.code(this[params["channelId"] as String]?.pauseAllChannelMediaRelay()) - } - - override fun resumeAllChannelMediaRelay(params: Map, callback: Callback) { - callback.code(-Constants.ERR_NOT_SUPPORTED) -// callback.code(this[params["channelId"] as String]?.resumeAllChannelMediaRelay()) - } - - override fun setRemoteVideoStreamType(params: Map, callback: Callback) { - callback.code( - this[params["channelId"] as String]?.setRemoteVideoStreamType( - (params["uid"] as Number).toNativeUInt(), - (params["streamType"] as Number).toInt() - ) - ) - } - - override fun setRemoteDefaultVideoStreamType(params: Map, callback: Callback) { - callback.code(this[params["channelId"] as String]?.setRemoteDefaultVideoStreamType((params["streamType"] as Number).toInt())) - } - - override fun setRemoteUserPriority(params: Map, callback: Callback) { - callback.code( - this[params["channelId"] as String]?.setRemoteUserPriority( - (params["uid"] as Number).toNativeUInt(), - (params["userPriority"] as Number).toInt() - ) - ) - } - - override fun registerMediaMetadataObserver(params: Map, callback: Callback) { - val channelId = params["channelId"] as String - val mediaObserver = MediaObserver { data -> - emit( - RtcChannelEvents.MetadataReceived, - data?.toMutableMap()?.apply { put("channelId", channelId) }) - } - callback.code( - this[channelId]?.registerMediaMetadataObserver( - mediaObserver, - IMetadataObserver.VIDEO_METADATA - ) - ) { - mediaObserverMap[channelId] = mediaObserver - Unit - } - } - - override fun unregisterMediaMetadataObserver(params: Map, callback: Callback) { - val channelId = params["channelId"] as String - callback.code( - this[channelId]?.registerMediaMetadataObserver( - null, - IMetadataObserver.VIDEO_METADATA - ) - ) { - mediaObserverMap.remove(channelId) - Unit - } - } - - override fun setMaxMetadataSize(params: Map, callback: Callback) { - callback.resolve(mediaObserverMap[params["channelId"] as String]) { - it.maxMetadataSize = (params["size"] as Number).toInt() - Unit - } - } - - override fun sendMetadata(params: Map, callback: Callback) { - callback.resolve(mediaObserverMap[params["channelId"] as String]) { - it.addMetadata(params["metadata"] as String) - Unit - } - } - - override fun setEncryptionSecret(params: Map, callback: Callback) { - callback.code(this[params["channelId"] as String]?.setEncryptionSecret(params["secret"] as String)) - } - - override fun setEncryptionMode(params: Map, callback: Callback) { - callback.code( - this[params["channelId"] as String]?.setEncryptionMode( - when ((params["encryptionMode"] as Number).toInt()) { - EncryptionConfig.EncryptionMode.AES_128_XTS.value -> "aes-128-xts" - EncryptionConfig.EncryptionMode.AES_128_ECB.value -> "aes-128-ecb" - EncryptionConfig.EncryptionMode.AES_256_XTS.value -> "aes-256-xts" - else -> "" - } - ) - ) - } - - override fun enableEncryption(params: Map, callback: Callback) { - callback.code( - this[params["channelId"] as String]?.enableEncryption( - params["enabled"] as Boolean, - mapToEncryptionConfig(params["config"] as Map<*, *>) - ) - ) - } - - override fun addInjectStreamUrl(params: Map, callback: Callback) { - callback.code( - this[params["channelId"] as String]?.addInjectStreamUrl( - params["url"] as String, - mapToLiveInjectStreamConfig(params["config"] as Map<*, *>) - ) - ) - } - - override fun removeInjectStreamUrl(params: Map, callback: Callback) { - callback.code(this[params["channelId"] as String]?.removeInjectStreamUrl(params["url"] as String)) - } - - override fun createDataStream(params: Map, callback: Callback) { - val channel = this[params["channelId"] as String] - (params["config"] as? Map<*, *>)?.let { config -> - callback.code(channel?.createDataStream(mapToDataStreamConfig(config))) { it } - return@createDataStream - } - callback.code( - channel?.createDataStream( - params["reliable"] as Boolean, - params["ordered"] as Boolean - ) - ) { it } - } - - override fun sendStreamMessage(params: Map, callback: Callback) { - callback.code( - this[params["channelId"] as String]?.sendStreamMessage( - (params["streamId"] as Number).toInt(), - (params["message"] as String).toByteArray() - ) - ) - } -} diff --git a/android/src/main/java/io/agora/rtc/base/RtcChannelEvent.kt b/android/src/main/java/io/agora/rtc/base/RtcChannelEvent.kt deleted file mode 100644 index 83bc3990c..000000000 --- a/android/src/main/java/io/agora/rtc/base/RtcChannelEvent.kt +++ /dev/null @@ -1,443 +0,0 @@ -package io.agora.rtc.base - -import androidx.annotation.IntRange -import io.agora.rtc.IRtcChannelEventHandler -import io.agora.rtc.IRtcEngineEventHandler -import io.agora.rtc.RtcChannel - -class RtcChannelEvents { - companion object { - const val Warning = "Warning" - const val Error = "Error" - const val JoinChannelSuccess = "JoinChannelSuccess" - const val RejoinChannelSuccess = "RejoinChannelSuccess" - const val LeaveChannel = "LeaveChannel" - const val ClientRoleChanged = "ClientRoleChanged" - const val UserJoined = "UserJoined" - const val UserOffline = "UserOffline" - const val ConnectionStateChanged = "ConnectionStateChanged" - const val ConnectionLost = "ConnectionLost" - const val TokenPrivilegeWillExpire = "TokenPrivilegeWillExpire" - const val RequestToken = "RequestToken" - const val ActiveSpeaker = "ActiveSpeaker" - const val VideoSizeChanged = "VideoSizeChanged" - const val RemoteVideoStateChanged = "RemoteVideoStateChanged" - const val RemoteAudioStateChanged = "RemoteAudioStateChanged" - const val LocalPublishFallbackToAudioOnly = "LocalPublishFallbackToAudioOnly" - const val RemoteSubscribeFallbackToAudioOnly = "RemoteSubscribeFallbackToAudioOnly" - const val RtcStats = "RtcStats" - const val NetworkQuality = "NetworkQuality" - const val RemoteVideoStats = "RemoteVideoStats" - const val RemoteAudioStats = "RemoteAudioStats" - const val RtmpStreamingStateChanged = "RtmpStreamingStateChanged" - const val TranscodingUpdated = "TranscodingUpdated" - const val StreamInjectedStatus = "StreamInjectedStatus" - const val StreamMessage = "StreamMessage" - const val StreamMessageError = "StreamMessageError" - const val ChannelMediaRelayStateChanged = "ChannelMediaRelayStateChanged" - const val ChannelMediaRelayEvent = "ChannelMediaRelayEvent" - const val MetadataReceived = "MetadataReceived" - const val AudioPublishStateChanged = "AudioPublishStateChanged" - const val VideoPublishStateChanged = "VideoPublishStateChanged" - const val AudioSubscribeStateChanged = "AudioSubscribeStateChanged" - const val VideoSubscribeStateChanged = "VideoSubscribeStateChanged" - const val RtmpStreamingEvent = "RtmpStreamingEvent" - const val UserSuperResolutionEnabled = "UserSuperResolutionEnabled" - - fun toMap(): Map { - return hashMapOf( - "Warning" to Warning, - "Error" to Error, - "JoinChannelSuccess" to JoinChannelSuccess, - "RejoinChannelSuccess" to RejoinChannelSuccess, - "LeaveChannel" to LeaveChannel, - "ClientRoleChanged" to ClientRoleChanged, - "UserJoined" to UserJoined, - "UserOffline" to UserOffline, - "ConnectionStateChanged" to ConnectionStateChanged, - "ConnectionLost" to ConnectionLost, - "TokenPrivilegeWillExpire" to TokenPrivilegeWillExpire, - "RequestToken" to RequestToken, - "ActiveSpeaker" to ActiveSpeaker, - "VideoSizeChanged" to VideoSizeChanged, - "RemoteVideoStateChanged" to RemoteVideoStateChanged, - "RemoteAudioStateChanged" to RemoteAudioStateChanged, - "LocalPublishFallbackToAudioOnly" to LocalPublishFallbackToAudioOnly, - "RemoteSubscribeFallbackToAudioOnly" to RemoteSubscribeFallbackToAudioOnly, - "RtcStats" to RtcStats, - "NetworkQuality" to NetworkQuality, - "RemoteVideoStats" to RemoteVideoStats, - "RemoteAudioStats" to RemoteAudioStats, - "RtmpStreamingStateChanged" to RtmpStreamingStateChanged, - "TranscodingUpdated" to TranscodingUpdated, - "StreamInjectedStatus" to StreamInjectedStatus, - "StreamMessage" to StreamMessage, - "StreamMessageError" to StreamMessageError, - "ChannelMediaRelayStateChanged" to ChannelMediaRelayStateChanged, - "ChannelMediaRelayEvent" to ChannelMediaRelayEvent, - "MetadataReceived" to MetadataReceived, - "AudioPublishStateChanged" to AudioPublishStateChanged, - "VideoPublishStateChanged" to VideoPublishStateChanged, - "AudioSubscribeStateChanged" to AudioSubscribeStateChanged, - "VideoSubscribeStateChanged" to VideoSubscribeStateChanged, - "RtmpStreamingEvent" to RtmpStreamingEvent, - "UserSuperResolutionEnabled" to UserSuperResolutionEnabled - ) - } - } -} - -class RtcChannelEventHandler( - private val emitter: (methodName: String, data: Map?) -> Unit -) : IRtcChannelEventHandler() { - companion object { - const val PREFIX = "io.agora.rtc." - } - - private fun callback(methodName: String, channel: RtcChannel?, vararg data: Any?) { - channel?.let { - emitter( - methodName, hashMapOf( - "channelId" to it.channelId(), - "data" to data.toList() - ) - ) - } - } - - override fun onChannelWarning(rtcChannel: RtcChannel?, @Annotations.AgoraWarningCode warn: Int) { - callback(RtcChannelEvents.Warning, rtcChannel, warn) - } - - override fun onChannelError(rtcChannel: RtcChannel?, @Annotations.AgoraErrorCode err: Int) { - callback(RtcChannelEvents.Error, rtcChannel, err) - } - - override fun onJoinChannelSuccess(rtcChannel: RtcChannel?, uid: Int, elapsed: Int) { - callback( - RtcChannelEvents.JoinChannelSuccess, - rtcChannel, - rtcChannel?.channelId(), - uid.toUInt().toLong(), - elapsed - ) - } - - override fun onRejoinChannelSuccess(rtcChannel: RtcChannel?, uid: Int, elapsed: Int) { - callback( - RtcChannelEvents.RejoinChannelSuccess, - rtcChannel, - rtcChannel?.channelId(), - uid.toUInt().toLong(), - elapsed - ) - } - - override fun onLeaveChannel(rtcChannel: RtcChannel?, stats: IRtcEngineEventHandler.RtcStats?) { - callback(RtcChannelEvents.LeaveChannel, rtcChannel, stats?.toMap()) - } - - override fun onClientRoleChanged( - rtcChannel: RtcChannel?, - @Annotations.AgoraClientRole oldRole: Int, - @Annotations.AgoraClientRole newRole: Int - ) { - callback(RtcChannelEvents.ClientRoleChanged, rtcChannel, oldRole, newRole) - } - - override fun onUserJoined(rtcChannel: RtcChannel?, uid: Int, elapsed: Int) { - callback(RtcChannelEvents.UserJoined, rtcChannel, uid.toUInt().toLong(), elapsed) - } - - override fun onUserOffline( - rtcChannel: RtcChannel?, - uid: Int, - @Annotations.AgoraUserOfflineReason reason: Int - ) { - callback(RtcChannelEvents.UserOffline, rtcChannel, uid.toUInt().toLong(), reason) - } - - override fun onConnectionStateChanged( - rtcChannel: RtcChannel?, - @Annotations.AgoraConnectionStateType state: Int, - @Annotations.AgoraConnectionChangedReason reason: Int - ) { - callback(RtcChannelEvents.ConnectionStateChanged, rtcChannel, state, reason) - } - - override fun onConnectionLost(rtcChannel: RtcChannel?) { - callback(RtcChannelEvents.ConnectionLost, rtcChannel) - } - - override fun onTokenPrivilegeWillExpire(rtcChannel: RtcChannel?, token: String?) { - callback(RtcChannelEvents.TokenPrivilegeWillExpire, rtcChannel, token) - } - - override fun onRequestToken(rtcChannel: RtcChannel?) { - callback(RtcChannelEvents.RequestToken, rtcChannel) - } - - override fun onActiveSpeaker(rtcChannel: RtcChannel?, uid: Int) { - callback(RtcChannelEvents.ActiveSpeaker, rtcChannel, uid.toUInt().toLong()) - } - - override fun onVideoSizeChanged( - rtcChannel: RtcChannel?, - uid: Int, - width: Int, - height: Int, - @IntRange(from = 0, to = 360) rotation: Int - ) { - callback( - RtcChannelEvents.VideoSizeChanged, - rtcChannel, - uid.toUInt().toLong(), - width, - height, - rotation - ) - } - - override fun onRemoteVideoStateChanged( - rtcChannel: RtcChannel?, - uid: Int, - @Annotations.AgoraVideoRemoteState state: Int, - @Annotations.AgoraVideoRemoteStateReason reason: Int, - elapsed: Int - ) { - callback( - RtcChannelEvents.RemoteVideoStateChanged, - rtcChannel, - uid.toUInt().toLong(), - state, - reason, - elapsed - ) - } - - override fun onRemoteAudioStateChanged( - rtcChannel: RtcChannel?, - uid: Int, - @Annotations.AgoraAudioRemoteState state: Int, - @Annotations.AgoraAudioRemoteStateReason reason: Int, - elapsed: Int - ) { - callback( - RtcChannelEvents.RemoteAudioStateChanged, - rtcChannel, - uid.toUInt().toLong(), - state, - reason, - elapsed - ) - } - - override fun onLocalPublishFallbackToAudioOnly( - rtcChannel: RtcChannel?, - isFallbackOrRecover: Boolean - ) { - callback(RtcChannelEvents.LocalPublishFallbackToAudioOnly, rtcChannel, isFallbackOrRecover) - } - - override fun onRemoteSubscribeFallbackToAudioOnly( - rtcChannel: RtcChannel?, - uid: Int, - isFallbackOrRecover: Boolean - ) { - callback( - RtcChannelEvents.RemoteSubscribeFallbackToAudioOnly, - rtcChannel, - uid.toUInt().toLong(), - isFallbackOrRecover - ) - } - - override fun onRtcStats(rtcChannel: RtcChannel?, stats: IRtcEngineEventHandler.RtcStats?) { - callback(RtcChannelEvents.RtcStats, rtcChannel, stats?.toMap()) - } - - override fun onNetworkQuality( - rtcChannel: RtcChannel?, - uid: Int, - @Annotations.AgoraNetworkQuality txQuality: Int, - @Annotations.AgoraNetworkQuality rxQuality: Int - ) { - callback( - RtcChannelEvents.NetworkQuality, - rtcChannel, - uid.toUInt().toLong(), - txQuality, - rxQuality - ) - } - - override fun onRemoteVideoStats( - rtcChannel: RtcChannel?, - stats: IRtcEngineEventHandler.RemoteVideoStats? - ) { - callback(RtcChannelEvents.RemoteVideoStats, rtcChannel, stats?.toMap()) - } - - override fun onRemoteAudioStats( - rtcChannel: RtcChannel?, - stats: IRtcEngineEventHandler.RemoteAudioStats? - ) { - callback(RtcChannelEvents.RemoteAudioStats, rtcChannel, stats?.toMap()) - } - - override fun onRtmpStreamingStateChanged( - rtcChannel: RtcChannel?, - url: String?, - @Annotations.AgoraRtmpStreamingState state: Int, - @Annotations.AgoraRtmpStreamingErrorCode errCode: Int - ) { - callback(RtcChannelEvents.RtmpStreamingStateChanged, rtcChannel, url, state, errCode) - } - - override fun onTranscodingUpdated(rtcChannel: RtcChannel?) { - callback(RtcChannelEvents.TranscodingUpdated, rtcChannel) - } - - override fun onStreamInjectedStatus( - rtcChannel: RtcChannel?, - url: String?, - uid: Int, - @Annotations.AgoraInjectStreamStatus status: Int - ) { - callback(RtcChannelEvents.StreamInjectedStatus, rtcChannel, url, uid.toUInt().toLong(), status) - } - - override fun onStreamMessage(rtcChannel: RtcChannel?, uid: Int, streamId: Int, data: ByteArray?) { - callback( - RtcChannelEvents.StreamMessage, - rtcChannel, - uid.toUInt().toLong(), - streamId, - data?.let { String(it, Charsets.UTF_8) }) - } - - override fun onStreamMessageError( - rtcChannel: RtcChannel?, - uid: Int, - streamId: Int, - @Annotations.AgoraErrorCode error: Int, - missed: Int, - cached: Int - ) { - callback( - RtcChannelEvents.StreamMessageError, - rtcChannel, - uid.toUInt().toLong(), - streamId, - error, - missed, - cached - ) - } - - override fun onChannelMediaRelayStateChanged( - rtcChannel: RtcChannel?, - @Annotations.AgoraChannelMediaRelayState state: Int, - @Annotations.AgoraChannelMediaRelayError code: Int - ) { - callback(RtcChannelEvents.ChannelMediaRelayStateChanged, rtcChannel, state, code) - } - - override fun onChannelMediaRelayEvent( - rtcChannel: RtcChannel?, - @Annotations.AgoraChannelMediaRelayEvent code: Int - ) { - callback(RtcChannelEvents.ChannelMediaRelayEvent, rtcChannel, code) - } - - override fun onAudioPublishStateChanged( - rtcChannel: RtcChannel?, - @Annotations.AgoraStreamPublishState oldState: Int, - @Annotations.AgoraStreamPublishState newState: Int, - elapseSinceLastState: Int - ) { - callback( - RtcChannelEvents.AudioPublishStateChanged, - rtcChannel, - rtcChannel?.channelId(), - oldState, - newState, - elapseSinceLastState - ) - } - - override fun onVideoPublishStateChanged( - rtcChannel: RtcChannel?, - @Annotations.AgoraStreamPublishState oldState: Int, - @Annotations.AgoraStreamPublishState newState: Int, - elapseSinceLastState: Int - ) { - callback( - RtcChannelEvents.VideoPublishStateChanged, - rtcChannel, - rtcChannel?.channelId(), - oldState, - newState, - elapseSinceLastState - ) - } - - override fun onAudioSubscribeStateChanged( - rtcChannel: RtcChannel?, - uid: Int, - @Annotations.AgoraStreamSubscribeState oldState: Int, - @Annotations.AgoraStreamSubscribeState newState: Int, - elapseSinceLastState: Int - ) { - callback( - RtcChannelEvents.AudioSubscribeStateChanged, - rtcChannel, - rtcChannel?.channelId(), - uid.toUInt().toLong(), - oldState, - newState, - elapseSinceLastState - ) - } - - override fun onVideoSubscribeStateChanged( - rtcChannel: RtcChannel?, - uid: Int, - @Annotations.AgoraStreamSubscribeState oldState: Int, - @Annotations.AgoraStreamSubscribeState newState: Int, - elapseSinceLastState: Int - ) { - callback( - RtcChannelEvents.VideoSubscribeStateChanged, - rtcChannel, - rtcChannel?.channelId(), - uid.toUInt().toLong(), - oldState, - newState, - elapseSinceLastState - ) - } - - override fun onRtmpStreamingEvent( - rtcChannel: RtcChannel?, - url: String?, - @Annotations.AgoraRtmpStreamingEvent errCode: Int - ) { - callback(RtcChannelEvents.RtmpStreamingEvent, rtcChannel, url, errCode) - } - - override fun onUserSuperResolutionEnabled( - rtcChannel: RtcChannel?, - uid: Int, - enabled: Boolean, - @Annotations.AgoraSuperResolutionStateReason reason: Int - ) { - callback( - RtcChannelEvents.UserSuperResolutionEnabled, - rtcChannel, - uid.toUInt().toLong(), - enabled, - reason - ) - } -} diff --git a/android/src/main/java/io/agora/rtc/base/RtcEngine.kt b/android/src/main/java/io/agora/rtc/base/RtcEngine.kt deleted file mode 100644 index 9b2566076..000000000 --- a/android/src/main/java/io/agora/rtc/base/RtcEngine.kt +++ /dev/null @@ -1,1379 +0,0 @@ -package io.agora.rtc.base - -import android.content.Context -import io.agora.rtc.* -import io.agora.rtc.internal.EncryptionConfig -import io.agora.rtc.models.UserInfo - -class IRtcEngine { - interface RtcEngineInterface : RtcUserInfoInterface, RtcAudioInterface, RtcVideoInterface, - RtcAudioMixingInterface, RtcAudioEffectInterface, RtcVoiceChangerInterface, - RtcVoicePositionInterface, RtcPublishStreamInterface, RtcMediaRelayInterface, - RtcAudioRouteInterface, RtcEarMonitoringInterface, RtcDualStreamInterface, - RtcFallbackInterface, RtcTestInterface, RtcMediaMetadataInterface, - RtcWatermarkInterface, RtcEncryptionInterface, RtcAudioRecorderInterface, - RtcInjectStreamInterface, RtcCameraInterface, RtcStreamMessageInterface { - fun create(params: Map, callback: Callback) - - fun destroy(callback: Callback) - - fun setChannelProfile(params: Map, callback: Callback) - - fun setClientRole(params: Map, callback: Callback) - - fun joinChannel(params: Map, callback: Callback) - - fun switchChannel(params: Map, callback: Callback) - - fun leaveChannel(callback: Callback) - - fun renewToken(params: Map, callback: Callback) - - @Deprecated("") - fun enableWebSdkInteroperability(params: Map, callback: Callback) - - fun getConnectionState(callback: Callback) - - fun sendCustomReportMessage(params: Map, callback: Callback) - - fun getCallId(callback: Callback) - - fun rate(params: Map, callback: Callback) - - fun complain(params: Map, callback: Callback) - - @Deprecated("") - fun setLogFile(params: Map, callback: Callback) - - @Deprecated("") - fun setLogFilter(params: Map, callback: Callback) - - @Deprecated("") - fun setLogFileSize(params: Map, callback: Callback) - - fun setParameters(params: Map, callback: Callback) - - fun getSdkVersion(callback: Callback) - - fun getErrorDescription(params: Map, callback: Callback) - - fun getNativeHandle(callback: Callback) - - fun enableDeepLearningDenoise(params: Map, callback: Callback) - - fun setCloudProxy(params: Map, callback: Callback) - - fun uploadLogFile(callback: Callback) - - fun setLocalAccessPoint(params: Map, callback: Callback) - - fun enableVirtualBackground(params: Map, callback: Callback) - - fun takeSnapshot(params: Map, callback: Callback) - } - - interface RtcUserInfoInterface { - fun registerLocalUserAccount(params: Map, callback: Callback) - - fun joinChannelWithUserAccount(params: Map, callback: Callback) - - fun getUserInfoByUserAccount(params: Map, callback: Callback) - - fun getUserInfoByUid(params: Map, callback: Callback) - } - - interface RtcAudioInterface { - fun enableAudio(callback: Callback) - - fun disableAudio(callback: Callback) - - fun setAudioProfile(params: Map, callback: Callback) - - fun adjustRecordingSignalVolume(params: Map, callback: Callback) - - fun adjustUserPlaybackSignalVolume(params: Map, callback: Callback) - - fun adjustPlaybackSignalVolume(params: Map, callback: Callback) - - fun enableLocalAudio(params: Map, callback: Callback) - - fun muteLocalAudioStream(params: Map, callback: Callback) - - fun muteRemoteAudioStream(params: Map, callback: Callback) - - fun muteAllRemoteAudioStreams(params: Map, callback: Callback) - - @Deprecated("") - fun setDefaultMuteAllRemoteAudioStreams(params: Map, callback: Callback) - - fun enableAudioVolumeIndication(params: Map, callback: Callback) - - fun startRhythmPlayer(params: Map, callback: Callback) - - fun stopRhythmPlayer(callback: Callback) - - fun configRhythmPlayer(params: Map, callback: Callback) - } - - interface RtcVideoInterface { - fun enableVideo(callback: Callback) - - fun disableVideo(callback: Callback) - - fun setVideoEncoderConfiguration(params: Map, callback: Callback) - - fun startPreview(callback: Callback) - - fun stopPreview(callback: Callback) - - fun enableLocalVideo(params: Map, callback: Callback) - - fun muteLocalVideoStream(params: Map, callback: Callback) - - fun muteRemoteVideoStream(params: Map, callback: Callback) - - fun muteAllRemoteVideoStreams(params: Map, callback: Callback) - - @Deprecated("") - fun setDefaultMuteAllRemoteVideoStreams(params: Map, callback: Callback) - - fun setBeautyEffectOptions(params: Map, callback: Callback) - - fun enableRemoteSuperResolution(params: Map, callback: Callback) - } - - interface RtcAudioMixingInterface { - fun startAudioMixing(params: Map, callback: Callback) - - fun stopAudioMixing(callback: Callback) - - fun pauseAudioMixing(callback: Callback) - - fun resumeAudioMixing(callback: Callback) - - fun adjustAudioMixingVolume(params: Map, callback: Callback) - - fun adjustAudioMixingPlayoutVolume(params: Map, callback: Callback) - - fun adjustAudioMixingPublishVolume(params: Map, callback: Callback) - - fun getAudioMixingPlayoutVolume(callback: Callback) - - fun getAudioMixingPublishVolume(callback: Callback) - - fun getAudioMixingDuration(params: Map, callback: Callback) - - fun getAudioFileInfo(params: Map, callback: Callback) - - fun getAudioMixingCurrentPosition(callback: Callback) - - fun setAudioMixingPosition(params: Map, callback: Callback) - - fun setAudioMixingPitch(params: Map, callback: Callback) - - fun setAudioMixingPlaybackSpeed(params: Map, callback: Callback) - - fun getAudioTrackCount(callback: Callback) - - fun selectAudioTrack(params: Map, callback: Callback) - - fun setAudioMixingDualMonoMode(params: Map, callback: Callback) - } - - interface RtcAudioEffectInterface { - fun getEffectsVolume(callback: Callback) - - fun setEffectsVolume(params: Map, callback: Callback) - - fun setVolumeOfEffect(params: Map, callback: Callback) - - fun playEffect(params: Map, callback: Callback) - - fun setEffectPosition(params: Map, callback: Callback) - - fun getEffectDuration(params: Map, callback: Callback) - - fun getEffectCurrentPosition(params: Map, callback: Callback) - - fun stopEffect(params: Map, callback: Callback) - - fun stopAllEffects(callback: Callback) - - fun preloadEffect(params: Map, callback: Callback) - - fun unloadEffect(params: Map, callback: Callback) - - fun pauseEffect(params: Map, callback: Callback) - - fun pauseAllEffects(callback: Callback) - - fun resumeEffect(params: Map, callback: Callback) - - fun resumeAllEffects(callback: Callback) - - fun setAudioSessionOperationRestriction(params: Map, callback: Callback) - } - - interface RtcVoiceChangerInterface { - @Deprecated("") - fun setLocalVoiceChanger(params: Map, callback: Callback) - - @Deprecated("") - fun setLocalVoiceReverbPreset(params: Map, callback: Callback) - - fun setLocalVoicePitch(params: Map, callback: Callback) - - fun setLocalVoiceEqualization(params: Map, callback: Callback) - - fun setLocalVoiceReverb(params: Map, callback: Callback) - - fun setAudioEffectPreset(params: Map, callback: Callback) - - fun setVoiceBeautifierPreset(params: Map, callback: Callback) - - fun setVoiceConversionPreset(params: Map, callback: Callback) - - fun setAudioEffectParameters(params: Map, callback: Callback) - - fun setVoiceBeautifierParameters(params: Map, callback: Callback) - } - - interface RtcVoicePositionInterface { - fun enableSoundPositionIndication(params: Map, callback: Callback) - - fun setRemoteVoicePosition(params: Map, callback: Callback) - } - - interface RtcPublishStreamInterface { - fun setLiveTranscoding(params: Map, callback: Callback) - - fun addPublishStreamUrl(params: Map, callback: Callback) - - fun removePublishStreamUrl(params: Map, callback: Callback) - } - - interface RtcMediaRelayInterface { - fun startChannelMediaRelay(params: Map, callback: Callback) - - fun updateChannelMediaRelay(params: Map, callback: Callback) - - fun stopChannelMediaRelay(callback: Callback) - - fun pauseAllChannelMediaRelay(callback: Callback) - - fun resumeAllChannelMediaRelay(callback: Callback) - } - - interface RtcAudioRouteInterface { - fun setDefaultAudioRoutetoSpeakerphone(params: Map, callback: Callback) - - fun setEnableSpeakerphone(params: Map, callback: Callback) - - fun isSpeakerphoneEnabled(callback: Callback) - } - - interface RtcEarMonitoringInterface { - fun enableInEarMonitoring(params: Map, callback: Callback) - - fun setInEarMonitoringVolume(params: Map, callback: Callback) - } - - interface RtcDualStreamInterface { - fun enableDualStreamMode(params: Map, callback: Callback) - - fun setRemoteVideoStreamType(params: Map, callback: Callback) - - fun setRemoteDefaultVideoStreamType(params: Map, callback: Callback) - } - - interface RtcFallbackInterface { - fun setLocalPublishFallbackOption(params: Map, callback: Callback) - - fun setRemoteSubscribeFallbackOption(params: Map, callback: Callback) - - fun setRemoteUserPriority(params: Map, callback: Callback) - } - - interface RtcTestInterface { - fun startEchoTest(params: Map, callback: Callback) - - fun stopEchoTest(callback: Callback) - - fun enableLastmileTest(callback: Callback) - - fun disableLastmileTest(callback: Callback) - - fun startLastmileProbeTest(params: Map, callback: Callback) - - fun stopLastmileProbeTest(callback: Callback) - } - - interface RtcMediaMetadataInterface { - fun registerMediaMetadataObserver(callback: Callback) - - fun unregisterMediaMetadataObserver(callback: Callback) - - fun setMaxMetadataSize(params: Map, callback: Callback) - - fun sendMetadata(params: Map, callback: Callback) - } - - interface RtcWatermarkInterface { - fun addVideoWatermark(params: Map, callback: Callback) - - fun clearVideoWatermarks(callback: Callback) - } - - interface RtcEncryptionInterface { - @Deprecated("") - fun setEncryptionSecret(params: Map, callback: Callback) - - @Deprecated("") - fun setEncryptionMode(params: Map, callback: Callback) - - fun enableEncryption(params: Map, callback: Callback) - } - - interface RtcAudioRecorderInterface { - fun startAudioRecording(params: Map, callback: Callback) - - fun stopAudioRecording(callback: Callback) - } - - interface RtcInjectStreamInterface { - fun addInjectStreamUrl(params: Map, callback: Callback) - - fun removeInjectStreamUrl(params: Map, callback: Callback) - } - - interface RtcCameraInterface { - fun switchCamera(callback: Callback) - - fun isCameraZoomSupported(callback: Callback) - - fun isCameraTorchSupported(callback: Callback) - - fun isCameraFocusSupported(callback: Callback) - - fun isCameraExposurePositionSupported(callback: Callback) - - fun isCameraAutoFocusFaceModeSupported(callback: Callback) - - fun setCameraZoomFactor(params: Map, callback: Callback) - - fun getCameraMaxZoomFactor(callback: Callback) - - fun setCameraFocusPositionInPreview(params: Map, callback: Callback) - - fun setCameraExposurePosition(params: Map, callback: Callback) - - fun enableFaceDetection(params: Map, callback: Callback) - - fun setCameraTorchOn(params: Map, callback: Callback) - - fun setCameraAutoFocusFaceModeEnabled(params: Map, callback: Callback) - - fun setCameraCapturerConfiguration(params: Map, callback: Callback) - } - - interface RtcStreamMessageInterface { - fun createDataStream(params: Map, callback: Callback) - - fun sendStreamMessage(params: Map, callback: Callback) - } -} - -open class RtcEngineFactory { - open fun create( - params: Map, - rtcEngineEventHandler: RtcEngineEventHandler - ): RtcEngine? { - val engine = RtcEngineEx.create(mapToRtcEngineConfig(params["config"] as Map<*, *>).apply { - mContext = params["context"] as Context - mEventHandler = rtcEngineEventHandler - }) - - return engine - } -} - -open class RtcEngineManager( - private val emit: (methodName: String, data: Map?) -> Unit, - private val rtcEngineFactory: RtcEngineFactory = RtcEngineFactory() -) : IRtcEngine.RtcEngineInterface { - var engine: RtcEngine? = null - private set - private var mediaObserver: MediaObserver? = null - - fun release() { - if (engine != null) { - RtcEngine.destroy() - engine = null - } - mediaObserver = null - } - - override fun create(params: Map, callback: Callback) { - engine = rtcEngineFactory.create(params, RtcEngineEventHandler { methodName, data -> - emit(methodName, data) - }) - callback.code((engine as RtcEngineEx).setAppType((params["appType"] as Number).toInt())) { - RtcEngineRegistry.instance.onRtcEngineCreated(engine) - it - } - } - - override fun destroy(callback: Callback) { - callback.resolve(engine) { - release() - RtcEngineRegistry.instance.onRtcEngineDestroyed() - } - } - - override fun setChannelProfile(params: Map, callback: Callback) { - callback.code(engine?.setChannelProfile((params["profile"] as Number).toInt())) - } - - override fun setClientRole(params: Map, callback: Callback) { - val role = (params["role"] as Number).toInt() - (params["options"] as? Map<*, *>)?.let { - callback.code(engine?.setClientRole(role, mapToClientRoleOptions(it))) - return@setClientRole - } - callback.code(engine?.setClientRole(role)) - } - - override fun joinChannel(params: Map, callback: Callback) { - val token = params["token"] as? String - val channelName = params["channelName"] as String - val optionalInfo = params["optionalInfo"] as? String - val optionalUid = (params["optionalUid"] as Number).toNativeUInt() - (params["options"] as? Map<*, *>)?.let { - callback.code( - engine?.joinChannel( - token, - channelName, - optionalInfo, - optionalUid, - mapToChannelMediaOptions(it) - ) - ) - return@joinChannel - } - callback.code(engine?.joinChannel(token, channelName, optionalInfo, optionalUid)) - } - - override fun switchChannel(params: Map, callback: Callback) { - val token = params["token"] as? String - val channelName = params["channelName"] as String - (params["options"] as? Map<*, *>)?.let { - callback.code(engine?.switchChannel(token, channelName, mapToChannelMediaOptions(it))) - return@switchChannel - } - callback.code(engine?.switchChannel(token, channelName)) - } - - override fun leaveChannel(callback: Callback) { - callback.code(engine?.leaveChannel()) - } - - override fun renewToken(params: Map, callback: Callback) { - callback.code(engine?.renewToken(params["token"] as String)) - } - - override fun enableWebSdkInteroperability(params: Map, callback: Callback) { - callback.code(engine?.enableWebSdkInteroperability(params["enabled"] as Boolean)) - } - - override fun getConnectionState(callback: Callback) { - callback.resolve(engine) { it.connectionState } - } - - override fun sendCustomReportMessage(params: Map, callback: Callback) { - callback.code( - engine?.sendCustomReportMessage( - params["id"] as String, - params["category"] as String, - params["event"] as String, - params["label"] as String, - (params["value"] as Number).toInt() - ) - ) - } - - override fun getCallId(callback: Callback) { - callback.resolve(engine) { it.callId } - } - - override fun rate(params: Map, callback: Callback) { - callback.code( - engine?.rate( - params["callId"] as String, - (params["rating"] as Number).toInt(), - params["description"] as? String - ) - ) - } - - override fun complain(params: Map, callback: Callback) { - callback.code(engine?.complain(params["callId"] as String, params["description"] as String)) - } - - override fun setLogFile(params: Map, callback: Callback) { - callback.code(engine?.setLogFile(params["filePath"] as String)) - } - - override fun setLogFilter(params: Map, callback: Callback) { - callback.code(engine?.setLogFilter((params["filter"] as Number).toInt())) - } - - override fun setLogFileSize(params: Map, callback: Callback) { - callback.code(engine?.setLogFileSize((params["fileSizeInKBytes"] as Number).toInt())) - } - - override fun setParameters(params: Map, callback: Callback) { - callback.code(engine?.setParameters(params["parameters"] as String)) - } - - override fun getSdkVersion(callback: Callback) { - callback.success(RtcEngine.getSdkVersion()) - } - - override fun getErrorDescription(params: Map, callback: Callback) { - callback.success(RtcEngine.getErrorDescription((params["error"] as Number).toInt())) - } - - override fun getNativeHandle(callback: Callback) { - callback.resolve(engine) { it.nativeHandle } - } - - override fun enableDeepLearningDenoise(params: Map, callback: Callback) { - callback.code(engine?.enableDeepLearningDenoise(params["enabled"] as Boolean)) - } - - override fun setCloudProxy(params: Map, callback: Callback) { - callback.code(engine?.setCloudProxy((params["proxyType"] as Number).toInt())) - } - - override fun uploadLogFile(callback: Callback) { - callback.resolve(engine) { it.uploadLogFile() } - } - - override fun setLocalAccessPoint(params: Map, callback: Callback) { - callback.code( - engine?.setLocalAccessPoint( - arrayListOf().apply { - (params["ips"] as? List<*>)?.let { list -> - list.forEach { item -> - (item as? String)?.let { - add(it) - } - } - } - }, - params["domain"] as String - ) - ) - } - - override fun enableVirtualBackground(params: Map, callback: Callback) { - callback.code( - engine?.enableVirtualBackground( - params["enabled"] as Boolean, - mapToVirtualBackgroundSource(params["backgroundSource"] as Map<*, *>) - ) - ) - } - - override fun takeSnapshot(params: Map, callback: Callback) { - callback.code( - engine?.takeSnapshot( - params["channel"] as String, - (params["uid"] as Number).toNativeUInt(), - params["filePath"] as String - ) - ) - } - - override fun registerLocalUserAccount(params: Map, callback: Callback) { - callback.code( - engine?.registerLocalUserAccount( - params["appId"] as String, - params["userAccount"] as String - ) - ) - } - - override fun joinChannelWithUserAccount(params: Map, callback: Callback) { - val token = params["token"] as? String - val channelName = params["channelName"] as String - val userAccount = params["userAccount"] as String - (params["options"] as? Map<*, *>)?.let { - callback.code( - engine?.joinChannelWithUserAccount( - token, - channelName, - userAccount, - mapToChannelMediaOptions(it) - ) - ) - return@joinChannelWithUserAccount - } - callback.code(engine?.joinChannelWithUserAccount(token, channelName, userAccount)) - } - - override fun getUserInfoByUserAccount(params: Map, callback: Callback) { - callback.resolve(engine) { - val userInfo = UserInfo() - it.getUserInfoByUserAccount(params["userAccount"] as String, userInfo) - userInfo.toMap() - } - } - - override fun getUserInfoByUid(params: Map, callback: Callback) { - callback.resolve(engine) { - val userInfo = UserInfo() - it.getUserInfoByUid((params["uid"] as Number).toNativeUInt(), userInfo) - userInfo.toMap() - } - } - - override fun enableAudio(callback: Callback) { - callback.code(engine?.enableAudio()) - } - - override fun disableAudio(callback: Callback) { - callback.code(engine?.disableAudio()) - } - - override fun setAudioProfile(params: Map, callback: Callback) { - callback.code( - engine?.setAudioProfile( - (params["profile"] as Number).toInt(), - (params["scenario"] as Number).toInt() - ) - ) - } - - override fun adjustRecordingSignalVolume(params: Map, callback: Callback) { - callback.code(engine?.adjustRecordingSignalVolume((params["volume"] as Number).toInt())) - } - - override fun adjustUserPlaybackSignalVolume(params: Map, callback: Callback) { - callback.code( - engine?.adjustUserPlaybackSignalVolume( - (params["uid"] as Number).toNativeUInt(), - (params["volume"] as Number).toInt() - ) - ) - } - - override fun adjustPlaybackSignalVolume(params: Map, callback: Callback) { - callback.code(engine?.adjustPlaybackSignalVolume((params["volume"] as Number).toInt())) - } - - override fun enableLocalAudio(params: Map, callback: Callback) { - callback.code(engine?.enableLocalAudio(params["enabled"] as Boolean)) - } - - override fun muteLocalAudioStream(params: Map, callback: Callback) { - callback.code(engine?.muteLocalAudioStream(params["muted"] as Boolean)) - } - - override fun muteRemoteAudioStream(params: Map, callback: Callback) { - callback.code( - engine?.muteRemoteAudioStream( - (params["uid"] as Number).toNativeUInt(), - params["muted"] as Boolean - ) - ) - } - - override fun muteAllRemoteAudioStreams(params: Map, callback: Callback) { - callback.code(engine?.muteAllRemoteAudioStreams(params["muted"] as Boolean)) - } - - override fun setDefaultMuteAllRemoteAudioStreams(params: Map, callback: Callback) { - callback.code(engine?.setDefaultMuteAllRemoteAudioStreams(params["muted"] as Boolean)) - } - - override fun enableAudioVolumeIndication(params: Map, callback: Callback) { - callback.code( - engine?.enableAudioVolumeIndication( - (params["interval"] as Number).toInt(), - (params["smooth"] as Number).toInt(), - params["report_vad"] as Boolean - ) - ) - } - - override fun startRhythmPlayer(params: Map, callback: Callback) { - callback.code( - engine?.audioEffectManager?.startRhythmPlayer( - params["sound1"] as String, - params["sound2"] as String, - mapToRhythmPlayerConfig(params["config"] as Map<*, *>) - ) - ) - } - - override fun stopRhythmPlayer(callback: Callback) { - callback.code(engine?.audioEffectManager?.stopRhythmPlayer()) - } - - override fun configRhythmPlayer(params: Map, callback: Callback) { - callback.code(engine?.audioEffectManager?.configRhythmPlayer(mapToRhythmPlayerConfig(params as Map<*, *>))) - } - - override fun enableVideo(callback: Callback) { - callback.code(engine?.enableVideo()) - } - - override fun disableVideo(callback: Callback) { - callback.code(engine?.disableVideo()) - } - - override fun setVideoEncoderConfiguration(params: Map, callback: Callback) { - callback.code(engine?.setVideoEncoderConfiguration(mapToVideoEncoderConfiguration(params["config"] as Map<*, *>))) - } - - override fun startPreview(callback: Callback) { - callback.code(engine?.startPreview()) - } - - override fun stopPreview(callback: Callback) { - callback.code(engine?.stopPreview()) - } - - override fun enableLocalVideo(params: Map, callback: Callback) { - callback.code(engine?.enableLocalVideo(params["enabled"] as Boolean)) - } - - override fun muteLocalVideoStream(params: Map, callback: Callback) { - callback.code(engine?.muteLocalVideoStream(params["muted"] as Boolean)) - } - - override fun muteRemoteVideoStream(params: Map, callback: Callback) { - callback.code( - engine?.muteRemoteVideoStream( - (params["uid"] as Number).toNativeUInt(), - params["muted"] as Boolean - ) - ) - } - - override fun muteAllRemoteVideoStreams(params: Map, callback: Callback) { - callback.code(engine?.muteAllRemoteVideoStreams(params["muted"] as Boolean)) - } - - override fun setDefaultMuteAllRemoteVideoStreams(params: Map, callback: Callback) { - callback.code(engine?.setDefaultMuteAllRemoteVideoStreams(params["muted"] as Boolean)) - } - - override fun setBeautyEffectOptions(params: Map, callback: Callback) { - callback.code( - engine?.setBeautyEffectOptions( - params["enabled"] as Boolean, - mapToBeautyOptions(params["options"] as Map<*, *>) - ) - ) - } - - override fun enableRemoteSuperResolution(params: Map, callback: Callback) { - callback.code( - engine?.enableRemoteSuperResolution( - (params["uid"] as Number).toNativeUInt(), - params["enabled"] as Boolean - ) - ) - } - - override fun startAudioMixing(params: Map, callback: Callback) { - (params["startPos"] as? Number)?.let { startPos -> - callback.code( - engine?.startAudioMixing( - params["filePath"] as String, - params["loopback"] as Boolean, - params["replace"] as Boolean, - (params["cycle"] as Number).toInt(), - startPos.toInt() - ) - ) - return@startAudioMixing - } - callback.code( - engine?.startAudioMixing( - params["filePath"] as String, - params["loopback"] as Boolean, - params["replace"] as Boolean, - (params["cycle"] as Number).toInt() - ) - ) - } - - override fun stopAudioMixing(callback: Callback) { - callback.code(engine?.stopAudioMixing()) - } - - override fun pauseAudioMixing(callback: Callback) { - callback.code(engine?.pauseAudioMixing()) - } - - override fun resumeAudioMixing(callback: Callback) { - callback.code(engine?.resumeAudioMixing()) - } - - override fun adjustAudioMixingVolume(params: Map, callback: Callback) { - callback.code(engine?.adjustAudioMixingVolume((params["volume"] as Number).toInt())) - } - - override fun adjustAudioMixingPlayoutVolume(params: Map, callback: Callback) { - callback.code(engine?.adjustAudioMixingPlayoutVolume((params["volume"] as Number).toInt())) - } - - override fun adjustAudioMixingPublishVolume(params: Map, callback: Callback) { - callback.code(engine?.adjustAudioMixingPublishVolume((params["volume"] as Number).toInt())) - } - - override fun getAudioMixingPlayoutVolume(callback: Callback) { - callback.code(engine?.audioMixingPlayoutVolume) { it } - } - - override fun getAudioMixingPublishVolume(callback: Callback) { - callback.code(engine?.audioMixingPublishVolume) { it } - } - - override fun getAudioMixingDuration(params: Map, callback: Callback) { - callback.code(engine?.audioMixingDuration) { it } - } - - override fun getAudioFileInfo(params: Map, callback: Callback) { - callback.code(engine?.getAudioFileInfo(params["filePath"] as String)) - } - - override fun getAudioMixingCurrentPosition(callback: Callback) { - callback.code(engine?.audioMixingCurrentPosition) { it } - } - - override fun setAudioMixingPosition(params: Map, callback: Callback) { - callback.code(engine?.setAudioMixingPosition((params["pos"] as Number).toInt())) - } - - override fun setAudioMixingPitch(params: Map, callback: Callback) { - callback.code(engine?.setAudioMixingPitch((params["pitch"] as Number).toInt())) - } - - override fun setAudioMixingPlaybackSpeed(params: Map, callback: Callback) { - callback.code(engine?.setAudioMixingPlaybackSpeed((params["speed"] as Number).toInt())) - } - - override fun getAudioTrackCount(callback: Callback) { - callback.code(engine?.audioTrackCount) { it } - } - - override fun selectAudioTrack(params: Map, callback: Callback) { - callback.code(engine?.selectAudioTrack((params["index"] as Number).toInt())) - } - - override fun setAudioMixingDualMonoMode(params: Map, callback: Callback) { - callback.code(engine?.setAudioMixingDualMonoMode((params["mode"] as Number).toInt())) - } - - override fun getEffectsVolume(callback: Callback) { - callback.resolve(engine) { it.audioEffectManager.effectsVolume } - } - - override fun setEffectsVolume(params: Map, callback: Callback) { - callback.code(engine?.audioEffectManager?.setEffectsVolume((params["volume"] as Number).toDouble())) - } - - override fun setVolumeOfEffect(params: Map, callback: Callback) { - callback.code( - engine?.audioEffectManager?.setVolumeOfEffect( - (params["soundId"] as Number).toInt(), - (params["volume"] as Number).toDouble() - ) - ) - } - - override fun playEffect(params: Map, callback: Callback) { - (params["startPos"] as? Number)?.let { startPos -> - callback.code( - engine?.audioEffectManager?.playEffect( - (params["soundId"] as Number).toInt(), - params["filePath"] as String, - (params["loopCount"] as Number).toInt(), - (params["pitch"] as Number).toDouble(), - (params["pan"] as Number).toDouble(), - (params["gain"] as Number).toDouble(), - params["publish"] as Boolean, - startPos.toInt() - ) - ) - return@playEffect - } - callback.code( - engine?.audioEffectManager?.playEffect( - (params["soundId"] as Number).toInt(), - params["filePath"] as String, - (params["loopCount"] as Number).toInt(), - (params["pitch"] as Number).toDouble(), - (params["pan"] as Number).toDouble(), - (params["gain"] as Number).toDouble(), - params["publish"] as Boolean - ) - ) - } - - override fun setEffectPosition(params: Map, callback: Callback) { - callback.code( - engine?.audioEffectManager?.setEffectPosition( - (params["soundId"] as Number).toInt(), - (params["pos"] as Number).toInt() - ) - ) - } - - override fun getEffectDuration(params: Map, callback: Callback) { - callback.code(engine?.audioEffectManager?.getEffectDuration(params["filePath"] as String)) { - it - } - } - - override fun getEffectCurrentPosition(params: Map, callback: Callback) { - callback.code(engine?.audioEffectManager?.getEffectCurrentPosition((params["soundId"] as Number).toInt())) { it } - } - - override fun stopEffect(params: Map, callback: Callback) { - callback.code(engine?.audioEffectManager?.stopEffect((params["soundId"] as Number).toInt())) - } - - override fun stopAllEffects(callback: Callback) { - callback.code(engine?.audioEffectManager?.stopAllEffects()) - } - - override fun preloadEffect(params: Map, callback: Callback) { - callback.code( - engine?.audioEffectManager?.preloadEffect( - (params["soundId"] as Number).toInt(), - params["filePath"] as String - ) - ) - } - - override fun unloadEffect(params: Map, callback: Callback) { - callback.code(engine?.audioEffectManager?.unloadEffect((params["soundId"] as Number).toInt())) - } - - override fun pauseEffect(params: Map, callback: Callback) { - callback.code(engine?.audioEffectManager?.pauseEffect((params["soundId"] as Number).toInt())) - } - - override fun pauseAllEffects(callback: Callback) { - callback.code(engine?.audioEffectManager?.pauseAllEffects()) - } - - override fun resumeEffect(params: Map, callback: Callback) { - callback.code(engine?.audioEffectManager?.resumeEffect((params["soundId"] as Number).toInt())) - } - - override fun resumeAllEffects(callback: Callback) { - callback.code(engine?.audioEffectManager?.resumeAllEffects()) - } - - override fun setAudioSessionOperationRestriction(params: Map, callback: Callback) { - callback.code(-Constants.ERR_NOT_SUPPORTED) - } - - override fun setLocalVoiceChanger(params: Map, callback: Callback) { - callback.code(engine?.setLocalVoiceChanger((params["voiceChanger"] as Number).toInt())) - } - - override fun setLocalVoiceReverbPreset(params: Map, callback: Callback) { - callback.code(engine?.setLocalVoiceReverbPreset((params["preset"] as Number).toInt())) - } - - override fun setLocalVoicePitch(params: Map, callback: Callback) { - callback.code(engine?.setLocalVoicePitch((params["pitch"] as Number).toDouble())) - } - - override fun setLocalVoiceEqualization(params: Map, callback: Callback) { - callback.code( - engine?.setLocalVoiceEqualization( - (params["bandFrequency"] as Number).toInt(), - (params["bandGain"] as Number).toInt() - ) - ) - } - - override fun setLocalVoiceReverb(params: Map, callback: Callback) { - callback.code( - engine?.setLocalVoiceReverb( - (params["reverbKey"] as Number).toInt(), - (params["value"] as Number).toInt() - ) - ) - } - - override fun setAudioEffectPreset(params: Map, callback: Callback) { - callback.code(engine?.setAudioEffectPreset((params["preset"] as Number).toInt())) - } - - override fun setVoiceBeautifierPreset(params: Map, callback: Callback) { - callback.code(engine?.setVoiceBeautifierPreset((params["preset"] as Number).toInt())) - } - - override fun setVoiceConversionPreset(params: Map, callback: Callback) { - callback.code(engine?.setVoiceConversionPreset((params["preset"] as Number).toInt())) - } - - override fun setAudioEffectParameters(params: Map, callback: Callback) { - callback.code( - engine?.setAudioEffectParameters( - (params["preset"] as Number).toInt(), - (params["param1"] as Number).toInt(), - (params["param2"] as Number).toInt() - ) - ) - } - - override fun setVoiceBeautifierParameters(params: Map, callback: Callback) { - callback.code( - engine?.setVoiceBeautifierParameters( - (params["preset"] as Number).toInt(), - (params["param1"] as Number).toInt(), - (params["param2"] as Number).toInt() - ) - ) - } - - override fun enableSoundPositionIndication(params: Map, callback: Callback) { - callback.code(engine?.enableSoundPositionIndication(params["enabled"] as Boolean)) - } - - override fun setRemoteVoicePosition(params: Map, callback: Callback) { - callback.code( - engine?.setRemoteVoicePosition( - (params["uid"] as Number).toNativeUInt(), - (params["pan"] as Number).toDouble(), - (params["gain"] as Number).toDouble() - ) - ) - } - - override fun setLiveTranscoding(params: Map, callback: Callback) { - callback.code(engine?.setLiveTranscoding(mapToLiveTranscoding(params["transcoding"] as Map<*, *>))) - } - - override fun addPublishStreamUrl(params: Map, callback: Callback) { - callback.code( - engine?.addPublishStreamUrl( - params["url"] as String, - params["transcodingEnabled"] as Boolean - ) - ) - } - - override fun removePublishStreamUrl(params: Map, callback: Callback) { - callback.code(engine?.removePublishStreamUrl(params["url"] as String)) - } - - override fun startChannelMediaRelay(params: Map, callback: Callback) { - callback.code(engine?.startChannelMediaRelay(mapToChannelMediaRelayConfiguration(params["channelMediaRelayConfiguration"] as Map<*, *>))) - } - - override fun updateChannelMediaRelay(params: Map, callback: Callback) { - callback.code(engine?.updateChannelMediaRelay(mapToChannelMediaRelayConfiguration(params["channelMediaRelayConfiguration"] as Map<*, *>))) - } - - override fun stopChannelMediaRelay(callback: Callback) { - callback.code(engine?.stopChannelMediaRelay()) - } - - override fun pauseAllChannelMediaRelay(callback: Callback) { - callback.code(engine?.pauseAllChannelMediaRelay()) - } - - override fun resumeAllChannelMediaRelay(callback: Callback) { - callback.code(engine?.resumeAllChannelMediaRelay()) - } - - override fun setDefaultAudioRoutetoSpeakerphone(params: Map, callback: Callback) { - callback.code(engine?.setDefaultAudioRoutetoSpeakerphone(params["defaultToSpeaker"] as Boolean)) - } - - override fun setEnableSpeakerphone(params: Map, callback: Callback) { - callback.code(engine?.setEnableSpeakerphone(params["enabled"] as Boolean)) - } - - override fun isSpeakerphoneEnabled(callback: Callback) { - callback.resolve(engine) { it.isSpeakerphoneEnabled } - } - - override fun enableInEarMonitoring(params: Map, callback: Callback) { - callback.code(engine?.enableInEarMonitoring(params["enabled"] as Boolean)) - } - - override fun setInEarMonitoringVolume(params: Map, callback: Callback) { - callback.code(engine?.setInEarMonitoringVolume((params["volume"] as Number).toInt())) - } - - override fun enableDualStreamMode(params: Map, callback: Callback) { - callback.code(engine?.enableDualStreamMode(params["enabled"] as Boolean)) - } - - override fun setRemoteVideoStreamType(params: Map, callback: Callback) { - callback.code( - engine?.setRemoteVideoStreamType( - (params["uid"] as Number).toNativeUInt(), - (params["streamType"] as Number).toInt() - ) - ) - } - - override fun setRemoteDefaultVideoStreamType(params: Map, callback: Callback) { - callback.code(engine?.setRemoteDefaultVideoStreamType((params["streamType"] as Number).toInt())) - } - - override fun setLocalPublishFallbackOption(params: Map, callback: Callback) { - callback.code(engine?.setLocalPublishFallbackOption((params["option"] as Number).toInt())) - } - - override fun setRemoteSubscribeFallbackOption(params: Map, callback: Callback) { - callback.code(engine?.setRemoteSubscribeFallbackOption((params["option"] as Number).toInt())) - } - - override fun setRemoteUserPriority(params: Map, callback: Callback) { - callback.code( - engine?.setRemoteUserPriority( - (params["uid"] as Number).toNativeUInt(), - (params["userPriority"] as Number).toInt() - ) - ) - } - - override fun startEchoTest(params: Map, callback: Callback) { - (params["intervalInSeconds"] as? Number)?.let { intervalInSeconds -> - callback.code(engine?.startEchoTest(intervalInSeconds.toInt())) - return@startEchoTest - } - (params["config"] as? Map<*, *>)?.let { config -> - callback.code(engine?.startEchoTest(mapToEchoTestConfiguration(config))) - return@startEchoTest - } - callback.code(engine?.startEchoTest()) - } - - override fun stopEchoTest(callback: Callback) { - callback.code(engine?.stopEchoTest()) - } - - override fun enableLastmileTest(callback: Callback) { - callback.code(engine?.enableLastmileTest()) - } - - override fun disableLastmileTest(callback: Callback) { - callback.code(engine?.disableLastmileTest()) - } - - override fun startLastmileProbeTest(params: Map, callback: Callback) { - callback.code(engine?.startLastmileProbeTest(mapToLastmileProbeConfig(params["config"] as Map<*, *>))) - } - - override fun stopLastmileProbeTest(callback: Callback) { - callback.code(engine?.stopLastmileProbeTest()) - } - - override fun registerMediaMetadataObserver(callback: Callback) { - val mediaObserver = MediaObserver { data -> - emit(RtcEngineEvents.MetadataReceived, data) - } - callback.code( - engine?.registerMediaMetadataObserver( - mediaObserver, - IMetadataObserver.VIDEO_METADATA - ) - ) { - this.mediaObserver = mediaObserver - Unit - } - } - - override fun unregisterMediaMetadataObserver(callback: Callback) { - callback.code(engine?.registerMediaMetadataObserver(null, IMetadataObserver.VIDEO_METADATA)) { - mediaObserver = null - Unit - } - } - - override fun setMaxMetadataSize(params: Map, callback: Callback) { - callback.resolve(mediaObserver) { - it.maxMetadataSize = (params["size"] as Number).toInt() - Unit - } - } - - override fun sendMetadata(params: Map, callback: Callback) { - callback.resolve(mediaObserver) { - it.addMetadata(params["metadata"] as String) - } - } - - override fun addVideoWatermark(params: Map, callback: Callback) { - callback.code( - engine?.addVideoWatermark( - params["watermarkUrl"] as String, - mapToWatermarkOptions(params["options"] as Map<*, *>) - ) - ) - } - - override fun clearVideoWatermarks(callback: Callback) { - callback.code(engine?.clearVideoWatermarks()) - } - - override fun setEncryptionSecret(params: Map, callback: Callback) { - callback.code(engine?.setEncryptionSecret(params["secret"] as String)) - } - - override fun setEncryptionMode(params: Map, callback: Callback) { - callback.code( - engine?.setEncryptionMode( - when ((params["encryptionMode"] as Number).toInt()) { - EncryptionConfig.EncryptionMode.AES_128_XTS.value -> "aes-128-xts" - EncryptionConfig.EncryptionMode.AES_128_ECB.value -> "aes-128-ecb" - EncryptionConfig.EncryptionMode.AES_256_XTS.value -> "aes-256-xts" - else -> "" - } - ) - ) - } - - override fun enableEncryption(params: Map, callback: Callback) { - callback.code( - engine?.enableEncryption( - params["enabled"] as Boolean, - mapToEncryptionConfig(params["config"] as Map<*, *>) - ) - ) - } - - override fun startAudioRecording(params: Map, callback: Callback) { - (params["config"] as? Map<*, *>)?.let { - callback.code(engine?.startAudioRecording(mapToAudioRecordingConfiguration(it))) - return@startAudioRecording - } - callback.code( - engine?.startAudioRecording( - params["filePath"] as String, - (params["sampleRate"] as Number).toInt(), - (params["quality"] as Number).toInt() - ) - ) - } - - override fun stopAudioRecording(callback: Callback) { - callback.code(engine?.stopAudioRecording()) - } - - override fun addInjectStreamUrl(params: Map, callback: Callback) { - callback.code( - engine?.addInjectStreamUrl( - params["url"] as String, - mapToLiveInjectStreamConfig(params["config"] as Map<*, *>) - ) - ) - } - - override fun removeInjectStreamUrl(params: Map, callback: Callback) { - callback.code(engine?.removeInjectStreamUrl(params["url"] as String)) - } - - override fun switchCamera(callback: Callback) { - callback.code(engine?.switchCamera()) - } - - override fun isCameraZoomSupported(callback: Callback) { - callback.resolve(engine) { it.isCameraZoomSupported } - } - - override fun isCameraTorchSupported(callback: Callback) { - callback.resolve(engine) { it.isCameraTorchSupported } - } - - override fun isCameraFocusSupported(callback: Callback) { - callback.resolve(engine) { it.isCameraFocusSupported } - } - - override fun isCameraExposurePositionSupported(callback: Callback) { - callback.resolve(engine) { it.isCameraExposurePositionSupported } - } - - override fun isCameraAutoFocusFaceModeSupported(callback: Callback) { - callback.resolve(engine) { it.isCameraAutoFocusFaceModeSupported } - } - - override fun setCameraZoomFactor(params: Map, callback: Callback) { - callback.code(engine?.setCameraZoomFactor((params["factor"] as Number).toFloat())) - } - - override fun getCameraMaxZoomFactor(callback: Callback) { - callback.resolve(engine) { it.cameraMaxZoomFactor } - } - - override fun setCameraFocusPositionInPreview(params: Map, callback: Callback) { - callback.code( - engine?.setCameraFocusPositionInPreview( - (params["positionX"] as Number).toFloat(), - (params["positionY"] as Number).toFloat() - ) - ) - } - - override fun setCameraExposurePosition(params: Map, callback: Callback) { - callback.code( - engine?.setCameraExposurePosition( - (params["positionXinView"] as Number).toFloat(), - (params["positionYinView"] as Number).toFloat() - ) - ) - } - - override fun enableFaceDetection(params: Map, callback: Callback) { - callback.code(engine?.enableFaceDetection(params["enabled"] as Boolean)) - } - - override fun setCameraTorchOn(params: Map, callback: Callback) { - callback.code(engine?.setCameraTorchOn(params["isOn"] as Boolean)) - } - - override fun setCameraAutoFocusFaceModeEnabled(params: Map, callback: Callback) { - callback.code(engine?.setCameraAutoFocusFaceModeEnabled(params["enabled"] as Boolean)) - } - - override fun setCameraCapturerConfiguration(params: Map, callback: Callback) { - callback.code(engine?.setCameraCapturerConfiguration(mapToCameraCapturerConfiguration(params["config"] as Map<*, *>))) - } - - override fun createDataStream(params: Map, callback: Callback) { - (params["config"] as? Map<*, *>)?.let { config -> - callback.code(engine?.createDataStream(mapToDataStreamConfig(config))) { it } - return@createDataStream - } - callback.code( - engine?.createDataStream( - params["reliable"] as Boolean, - params["ordered"] as Boolean - ) - ) { it } - } - - override fun sendStreamMessage(params: Map, callback: Callback) { - callback.code( - engine?.sendStreamMessage( - (params["streamId"] as Number).toInt(), - (params["message"] as String).toByteArray() - ) - ) - } -} diff --git a/android/src/main/java/io/agora/rtc/base/RtcEngineEvent.kt b/android/src/main/java/io/agora/rtc/base/RtcEngineEvent.kt deleted file mode 100644 index 15ac9c19d..000000000 --- a/android/src/main/java/io/agora/rtc/base/RtcEngineEvent.kt +++ /dev/null @@ -1,718 +0,0 @@ -package io.agora.rtc.base - -import android.graphics.Rect -import androidx.annotation.IntRange -import io.agora.rtc.IRtcEngineEventHandler -import io.agora.rtc.models.UserInfo - -class RtcEngineEvents { - companion object { - const val Warning = "Warning" - const val Error = "Error" - const val ApiCallExecuted = "ApiCallExecuted" - const val JoinChannelSuccess = "JoinChannelSuccess" - const val RejoinChannelSuccess = "RejoinChannelSuccess" - const val LeaveChannel = "LeaveChannel" - const val LocalUserRegistered = "LocalUserRegistered" - const val UserInfoUpdated = "UserInfoUpdated" - const val ClientRoleChanged = "ClientRoleChanged" - const val UserJoined = "UserJoined" - const val UserOffline = "UserOffline" - const val ConnectionStateChanged = "ConnectionStateChanged" - const val NetworkTypeChanged = "NetworkTypeChanged" - const val ConnectionLost = "ConnectionLost" - const val TokenPrivilegeWillExpire = "TokenPrivilegeWillExpire" - const val RequestToken = "RequestToken" - const val AudioVolumeIndication = "AudioVolumeIndication" - const val ActiveSpeaker = "ActiveSpeaker" - const val FirstLocalAudioFrame = "FirstLocalAudioFrame" - const val FirstLocalVideoFrame = "FirstLocalVideoFrame" - const val UserMuteVideo = "UserMuteVideo" - const val VideoSizeChanged = "VideoSizeChanged" - const val RemoteVideoStateChanged = "RemoteVideoStateChanged" - const val LocalVideoStateChanged = "LocalVideoStateChanged" - const val RemoteAudioStateChanged = "RemoteAudioStateChanged" - const val LocalAudioStateChanged = "LocalAudioStateChanged" - const val RequestAudioFileInfo = "RequestAudioFileInfo" - const val LocalPublishFallbackToAudioOnly = "LocalPublishFallbackToAudioOnly" - const val RemoteSubscribeFallbackToAudioOnly = "RemoteSubscribeFallbackToAudioOnly" - const val AudioRouteChanged = "AudioRouteChanged" - const val CameraFocusAreaChanged = "CameraFocusAreaChanged" - const val CameraExposureAreaChanged = "CameraExposureAreaChanged" - const val FacePositionChanged = "FacePositionChanged" - const val RtcStats = "RtcStats" - const val LastmileQuality = "LastmileQuality" - const val NetworkQuality = "NetworkQuality" - const val LastmileProbeResult = "LastmileProbeResult" - const val LocalVideoStats = "LocalVideoStats" - const val LocalAudioStats = "LocalAudioStats" - const val RemoteVideoStats = "RemoteVideoStats" - const val RemoteAudioStats = "RemoteAudioStats" - const val AudioMixingFinished = "AudioMixingFinished" - const val AudioMixingStateChanged = "AudioMixingStateChanged" - const val AudioEffectFinished = "AudioEffectFinished" - const val RtmpStreamingStateChanged = "RtmpStreamingStateChanged" - const val TranscodingUpdated = "TranscodingUpdated" - const val StreamInjectedStatus = "StreamInjectedStatus" - const val StreamMessage = "StreamMessage" - const val StreamMessageError = "StreamMessageError" - const val MediaEngineLoadSuccess = "MediaEngineLoadSuccess" - const val MediaEngineStartCallSuccess = "MediaEngineStartCallSuccess" - const val ChannelMediaRelayStateChanged = "ChannelMediaRelayStateChanged" - const val ChannelMediaRelayEvent = "ChannelMediaRelayEvent" - const val FirstRemoteVideoFrame = "FirstRemoteVideoFrame" - const val FirstRemoteAudioFrame = "FirstRemoteAudioFrame" - const val FirstRemoteAudioDecoded = "FirstRemoteAudioDecoded" - const val UserMuteAudio = "UserMuteAudio" - const val StreamPublished = "StreamPublished" - const val StreamUnpublished = "StreamUnpublished" - const val RemoteAudioTransportStats = "RemoteAudioTransportStats" - const val RemoteVideoTransportStats = "RemoteVideoTransportStats" - const val UserEnableVideo = "UserEnableVideo" - const val UserEnableLocalVideo = "UserEnableLocalVideo" - const val FirstRemoteVideoDecoded = "FirstRemoteVideoDecoded" - const val MicrophoneEnabled = "MicrophoneEnabled" - const val ConnectionInterrupted = "ConnectionInterrupted" - const val ConnectionBanned = "ConnectionBanned" - const val AudioQuality = "AudioQuality" - const val CameraReady = "CameraReady" - const val VideoStopped = "VideoStopped" - const val MetadataReceived = "MetadataReceived" - const val FirstLocalAudioFramePublished = "FirstLocalAudioFramePublished" - const val FirstLocalVideoFramePublished = "FirstLocalVideoFramePublished" - const val AudioPublishStateChanged = "AudioPublishStateChanged" - const val VideoPublishStateChanged = "VideoPublishStateChanged" - const val AudioSubscribeStateChanged = "AudioSubscribeStateChanged" - const val VideoSubscribeStateChanged = "VideoSubscribeStateChanged" - const val RtmpStreamingEvent = "RtmpStreamingEvent" - const val UserSuperResolutionEnabled = "UserSuperResolutionEnabled" - const val UploadLogResult = "UploadLogResult" - const val VirtualBackgroundSourceEnabled = "VirtualBackgroundSourceEnabled" - const val SnapshotTaken = "SnapshotTaken" - - fun toMap(): Map { - return hashMapOf( - "Warning" to Warning, - "Error" to Error, - "ApiCallExecuted" to ApiCallExecuted, - "JoinChannelSuccess" to JoinChannelSuccess, - "RejoinChannelSuccess" to RejoinChannelSuccess, - "LeaveChannel" to LeaveChannel, - "LocalUserRegistered" to LocalUserRegistered, - "UserInfoUpdated" to UserInfoUpdated, - "ClientRoleChanged" to ClientRoleChanged, - "UserJoined" to UserJoined, - "UserOffline" to UserOffline, - "ConnectionStateChanged" to ConnectionStateChanged, - "NetworkTypeChanged" to NetworkTypeChanged, - "ConnectionLost" to ConnectionLost, - "TokenPrivilegeWillExpire" to TokenPrivilegeWillExpire, - "RequestToken" to RequestToken, - "AudioVolumeIndication" to AudioVolumeIndication, - "ActiveSpeaker" to ActiveSpeaker, - "FirstLocalAudioFrame" to FirstLocalAudioFrame, - "FirstLocalVideoFrame" to FirstLocalVideoFrame, - "UserMuteVideo" to UserMuteVideo, - "VideoSizeChanged" to VideoSizeChanged, - "RemoteVideoStateChanged" to RemoteVideoStateChanged, - "LocalVideoStateChanged" to LocalVideoStateChanged, - "RemoteAudioStateChanged" to RemoteAudioStateChanged, - "LocalAudioStateChanged" to LocalAudioStateChanged, - "RequestAudioFileInfo" to RequestAudioFileInfo, - "LocalPublishFallbackToAudioOnly" to LocalPublishFallbackToAudioOnly, - "RemoteSubscribeFallbackToAudioOnly" to RemoteSubscribeFallbackToAudioOnly, - "AudioRouteChanged" to AudioRouteChanged, - "CameraFocusAreaChanged" to CameraFocusAreaChanged, - "CameraExposureAreaChanged" to CameraExposureAreaChanged, - "FacePositionChanged" to FacePositionChanged, - "RtcStats" to RtcStats, - "LastmileQuality" to LastmileQuality, - "NetworkQuality" to NetworkQuality, - "LastmileProbeResult" to LastmileProbeResult, - "LocalVideoStats" to LocalVideoStats, - "LocalAudioStats" to LocalAudioStats, - "RemoteVideoStats" to RemoteVideoStats, - "RemoteAudioStats" to RemoteAudioStats, - "AudioMixingFinished" to AudioMixingFinished, - "AudioMixingStateChanged" to AudioMixingStateChanged, - "AudioEffectFinished" to AudioEffectFinished, - "RtmpStreamingStateChanged" to RtmpStreamingStateChanged, - "TranscodingUpdated" to TranscodingUpdated, - "StreamInjectedStatus" to StreamInjectedStatus, - "StreamMessage" to StreamMessage, - "StreamMessageError" to StreamMessageError, - "MediaEngineLoadSuccess" to MediaEngineLoadSuccess, - "MediaEngineStartCallSuccess" to MediaEngineStartCallSuccess, - "ChannelMediaRelayStateChanged" to ChannelMediaRelayStateChanged, - "ChannelMediaRelayEvent" to ChannelMediaRelayEvent, - "FirstRemoteVideoFrame" to FirstRemoteVideoFrame, - "FirstRemoteAudioFrame" to FirstRemoteAudioFrame, - "FirstRemoteAudioDecoded" to FirstRemoteAudioDecoded, - "UserMuteAudio" to UserMuteAudio, - "StreamPublished" to StreamPublished, - "StreamUnpublished" to StreamUnpublished, - "RemoteAudioTransportStats" to RemoteAudioTransportStats, - "RemoteVideoTransportStats" to RemoteVideoTransportStats, - "UserEnableVideo" to UserEnableVideo, - "UserEnableLocalVideo" to UserEnableLocalVideo, - "FirstRemoteVideoDecoded" to FirstRemoteVideoDecoded, - "MicrophoneEnabled" to MicrophoneEnabled, - "ConnectionInterrupted" to ConnectionInterrupted, - "ConnectionBanned" to ConnectionBanned, - "AudioQuality" to AudioQuality, - "CameraReady" to CameraReady, - "VideoStopped" to VideoStopped, - "MetadataReceived" to MetadataReceived, - "FirstLocalAudioFramePublished" to FirstLocalAudioFramePublished, - "FirstLocalVideoFramePublished" to FirstLocalVideoFramePublished, - "AudioPublishStateChanged" to AudioPublishStateChanged, - "VideoPublishStateChanged" to VideoPublishStateChanged, - "AudioSubscribeStateChanged" to AudioSubscribeStateChanged, - "VideoSubscribeStateChanged" to VideoSubscribeStateChanged, - "RtmpStreamingEvent" to RtmpStreamingEvent, - "UserSuperResolutionEnabled" to UserSuperResolutionEnabled, - "UploadLogResult" to UploadLogResult, - "VirtualBackgroundSourceEnabled" to VirtualBackgroundSourceEnabled, - "SnapshotTaken" to SnapshotTaken - ) - } - } -} - -class RtcEngineEventHandler( - private val emitter: (methodName: String, data: Map?) -> Unit -) : IRtcEngineEventHandler() { - companion object { - const val PREFIX = "io.agora.rtc." - } - - private fun callback(methodName: String, vararg data: Any?) { - emitter(methodName, hashMapOf("data" to data.toList())) - } - - override fun onWarning(@Annotations.AgoraWarningCode warn: Int) { - callback(RtcEngineEvents.Warning, warn) - } - - override fun onError(@Annotations.AgoraErrorCode err: Int) { - callback(RtcEngineEvents.Error, err) - } - - override fun onApiCallExecuted( - @Annotations.AgoraErrorCode error: Int, - api: String?, - result: String? - ) { - callback(RtcEngineEvents.ApiCallExecuted, error, api, result) - } - - override fun onJoinChannelSuccess(channel: String?, uid: Int, elapsed: Int) { - callback(RtcEngineEvents.JoinChannelSuccess, channel, uid.toUInt().toLong(), elapsed) - } - - override fun onRejoinChannelSuccess(channel: String?, uid: Int, elapsed: Int) { - callback(RtcEngineEvents.RejoinChannelSuccess, channel, uid.toUInt().toLong(), elapsed) - } - - override fun onLeaveChannel(stats: RtcStats?) { - callback(RtcEngineEvents.LeaveChannel, stats?.toMap()) - } - - override fun onLocalUserRegistered(uid: Int, userAccount: String?) { - callback(RtcEngineEvents.LocalUserRegistered, uid.toUInt().toLong(), userAccount) - } - - override fun onUserInfoUpdated(uid: Int, userInfo: UserInfo?) { - callback(RtcEngineEvents.UserInfoUpdated, uid.toUInt().toLong(), userInfo?.toMap()) - } - - override fun onClientRoleChanged( - @Annotations.AgoraClientRole oldRole: Int, - @Annotations.AgoraClientRole newRole: Int - ) { - callback(RtcEngineEvents.ClientRoleChanged, oldRole, newRole) - } - - override fun onUserJoined(uid: Int, elapsed: Int) { - callback(RtcEngineEvents.UserJoined, uid.toUInt().toLong(), elapsed) - } - - override fun onUserOffline(uid: Int, @Annotations.AgoraUserOfflineReason reason: Int) { - callback(RtcEngineEvents.UserOffline, uid.toUInt().toLong(), reason) - } - - override fun onConnectionStateChanged( - @Annotations.AgoraConnectionStateType state: Int, - @Annotations.AgoraConnectionChangedReason reason: Int - ) { - callback(RtcEngineEvents.ConnectionStateChanged, state, reason) - } - - override fun onNetworkTypeChanged(@Annotations.AgoraNetworkType type: Int) { - callback(RtcEngineEvents.NetworkTypeChanged, type) - } - - override fun onConnectionLost() { - callback(RtcEngineEvents.ConnectionLost) - } - - override fun onTokenPrivilegeWillExpire(token: String?) { - callback(RtcEngineEvents.TokenPrivilegeWillExpire, token) - } - - override fun onRequestToken() { - callback(RtcEngineEvents.RequestToken) - } - - override fun onAudioVolumeIndication( - speakers: Array?, - @IntRange(from = 0, to = 255) totalVolume: Int - ) { - callback(RtcEngineEvents.AudioVolumeIndication, speakers?.toMapList(), totalVolume) - } - - override fun onActiveSpeaker(uid: Int) { - callback(RtcEngineEvents.ActiveSpeaker, uid.toUInt().toLong()) - } - - override fun onFirstLocalAudioFrame(elapsed: Int) { - callback(RtcEngineEvents.FirstLocalAudioFrame, elapsed) - } - - override fun onFirstLocalVideoFrame(width: Int, height: Int, elapsed: Int) { - callback(RtcEngineEvents.FirstLocalVideoFrame, width, height, elapsed) - } - - @Deprecated("", ReplaceWith("onRemoteVideoStateChanged")) - override fun onUserMuteVideo(uid: Int, muted: Boolean) { - callback(RtcEngineEvents.UserMuteVideo, uid.toUInt().toLong(), muted) - } - - override fun onVideoSizeChanged( - uid: Int, - width: Int, - height: Int, - @IntRange(from = 0, to = 360) rotation: Int - ) { - callback(RtcEngineEvents.VideoSizeChanged, uid.toUInt().toLong(), width, height, rotation) - } - - override fun onRemoteVideoStateChanged( - uid: Int, - @Annotations.AgoraVideoRemoteState state: Int, - @Annotations.AgoraVideoRemoteStateReason reason: Int, - elapsed: Int - ) { - callback(RtcEngineEvents.RemoteVideoStateChanged, uid.toUInt().toLong(), state, reason, elapsed) - } - - override fun onLocalVideoStateChanged( - @Annotations.AgoraLocalVideoStreamState localVideoState: Int, - @Annotations.AgoraLocalVideoStreamError error: Int - ) { - callback(RtcEngineEvents.LocalVideoStateChanged, localVideoState, error) - } - - override fun onRemoteAudioStateChanged( - uid: Int, - @Annotations.AgoraAudioRemoteState state: Int, - @Annotations.AgoraAudioRemoteStateReason reason: Int, - elapsed: Int - ) { - callback(RtcEngineEvents.RemoteAudioStateChanged, uid.toUInt().toLong(), state, reason, elapsed) - } - - override fun onLocalAudioStateChanged( - @Annotations.AgoraAudioLocalState state: Int, - @Annotations.AgoraAudioLocalError error: Int - ) { - callback(RtcEngineEvents.LocalAudioStateChanged, state, error) - } - - override fun onRequestAudioFileInfo(info: AudioFileInfo?, error: Int) { - callback(RtcEngineEvents.RequestAudioFileInfo, info?.toMap(), error) - } - - override fun onLocalPublishFallbackToAudioOnly(isFallbackOrRecover: Boolean) { - callback(RtcEngineEvents.LocalPublishFallbackToAudioOnly, isFallbackOrRecover) - } - - override fun onRemoteSubscribeFallbackToAudioOnly(uid: Int, isFallbackOrRecover: Boolean) { - callback( - RtcEngineEvents.RemoteSubscribeFallbackToAudioOnly, - uid.toUInt().toLong(), - isFallbackOrRecover - ) - } - - override fun onAudioRouteChanged(@Annotations.AgoraAudioOutputRouting routing: Int) { - callback(RtcEngineEvents.AudioRouteChanged, routing) - } - - override fun onCameraFocusAreaChanged(rect: Rect?) { - callback(RtcEngineEvents.CameraFocusAreaChanged, rect?.toMap()) - } - - override fun onCameraExposureAreaChanged(rect: Rect?) { - callback(RtcEngineEvents.CameraExposureAreaChanged, rect?.toMap()) - } - - override fun onFacePositionChanged( - imageWidth: Int, - imageHeight: Int, - faces: Array? - ) { - callback(RtcEngineEvents.FacePositionChanged, imageWidth, imageHeight, faces?.toMapList()) - } - - override fun onRtcStats(stats: RtcStats?) { - callback(RtcEngineEvents.RtcStats, stats?.toMap()) - } - - override fun onLastmileQuality(@Annotations.AgoraNetworkQuality quality: Int) { - callback(RtcEngineEvents.LastmileQuality, quality) - } - - override fun onNetworkQuality( - uid: Int, - @Annotations.AgoraNetworkQuality txQuality: Int, - @Annotations.AgoraNetworkQuality rxQuality: Int - ) { - callback(RtcEngineEvents.NetworkQuality, uid.toUInt().toLong(), txQuality, rxQuality) - } - - override fun onLastmileProbeResult(result: LastmileProbeResult?) { - callback(RtcEngineEvents.LastmileProbeResult, result?.toMap()) - } - - @Deprecated("", ReplaceWith("onLocalVideoStats")) - override fun onLocalVideoStat(sentBitrate: Int, sentFrameRate: Int) { - // TODO Not in iOS - } - - override fun onLocalVideoStats(stats: LocalVideoStats?) { - callback(RtcEngineEvents.LocalVideoStats, stats?.toMap()) - } - - override fun onLocalAudioStats(stats: LocalAudioStats?) { - callback(RtcEngineEvents.LocalAudioStats, stats?.toMap()) - } - - @Deprecated("", ReplaceWith("onRemoteVideoStats")) - override fun onRemoteVideoStat( - uid: Int, - delay: Int, - receivedBitrate: Int, - receivedFrameRate: Int - ) { - // TODO Not in iOS - } - - override fun onRemoteVideoStats(stats: RemoteVideoStats?) { - callback(RtcEngineEvents.RemoteVideoStats, stats?.toMap()) - } - - override fun onRemoteAudioStats(stats: RemoteAudioStats?) { - callback(RtcEngineEvents.RemoteAudioStats, stats?.toMap()) - } - - @Deprecated("", ReplaceWith("onAudioMixingStateChanged")) - override fun onAudioMixingFinished() { - callback(RtcEngineEvents.AudioMixingFinished) - } - - override fun onAudioMixingStateChanged( - @Annotations.AgoraAudioMixingStateCode state: Int, - @Annotations.AgoraAudioMixingReason reason: Int - ) { - callback(RtcEngineEvents.AudioMixingStateChanged, state, reason) - } - - override fun onAudioEffectFinished(soundId: Int) { - callback(RtcEngineEvents.AudioEffectFinished, soundId) - } - - override fun onRtmpStreamingStateChanged( - url: String?, - @Annotations.AgoraRtmpStreamingState state: Int, - @Annotations.AgoraRtmpStreamingErrorCode errCode: Int - ) { - callback(RtcEngineEvents.RtmpStreamingStateChanged, url, state, errCode) - } - - override fun onTranscodingUpdated() { - callback(RtcEngineEvents.TranscodingUpdated) - } - - override fun onStreamInjectedStatus( - url: String?, - uid: Int, - @Annotations.AgoraInjectStreamStatus status: Int - ) { - callback(RtcEngineEvents.StreamInjectedStatus, url, uid.toUInt().toLong(), status) - } - - override fun onStreamMessage(uid: Int, streamId: Int, data: ByteArray?) { - callback( - RtcEngineEvents.StreamMessage, - uid.toUInt().toLong(), - streamId, - data?.let { String(it, Charsets.UTF_8) }) - } - - override fun onStreamMessageError( - uid: Int, - streamId: Int, - @Annotations.AgoraErrorCode error: Int, - missed: Int, - cached: Int - ) { - callback( - RtcEngineEvents.StreamMessageError, - uid.toUInt().toLong(), - streamId, - error, - missed, - cached - ) - } - - override fun onMediaEngineLoadSuccess() { - callback(RtcEngineEvents.MediaEngineLoadSuccess) - } - - override fun onMediaEngineStartCallSuccess() { - callback(RtcEngineEvents.MediaEngineStartCallSuccess) - } - - override fun onChannelMediaRelayStateChanged( - @Annotations.AgoraChannelMediaRelayState state: Int, - @Annotations.AgoraChannelMediaRelayError code: Int - ) { - callback(RtcEngineEvents.ChannelMediaRelayStateChanged, state, code) - } - - override fun onChannelMediaRelayEvent(@Annotations.AgoraChannelMediaRelayEvent code: Int) { - callback(RtcEngineEvents.ChannelMediaRelayEvent, code) - } - - @Deprecated("", ReplaceWith("onRemoteVideoStateChanged")) - override fun onFirstRemoteVideoFrame(uid: Int, width: Int, height: Int, elapsed: Int) { - callback(RtcEngineEvents.FirstRemoteVideoFrame, uid.toUInt().toLong(), width, height, elapsed) - } - - @Deprecated("", ReplaceWith("onRemoteAudioStateChanged")) - override fun onFirstRemoteAudioFrame(uid: Int, elapsed: Int) { - callback(RtcEngineEvents.FirstRemoteAudioFrame, uid.toUInt().toLong(), elapsed) - } - - @Deprecated("", ReplaceWith("onRemoteAudioStateChanged")) - override fun onFirstRemoteAudioDecoded(uid: Int, elapsed: Int) { - callback(RtcEngineEvents.FirstRemoteAudioDecoded, uid.toUInt().toLong(), elapsed) - } - - @Deprecated("", ReplaceWith("onRemoteAudioStateChanged")) - override fun onUserMuteAudio(uid: Int, muted: Boolean) { - callback(RtcEngineEvents.UserMuteAudio, uid.toUInt().toLong(), muted) - } - - @Deprecated("", ReplaceWith("onRtmpStreamingStateChanged")) - override fun onStreamPublished(url: String?, @Annotations.AgoraErrorCode error: Int) { - callback(RtcEngineEvents.StreamPublished, url, error) - } - - @Deprecated("", ReplaceWith("onRtmpStreamingStateChanged")) - override fun onStreamUnpublished(url: String?) { - callback(RtcEngineEvents.StreamUnpublished, url) - } - - @Deprecated("", ReplaceWith("onRemoteAudioStats")) - override fun onRemoteAudioTransportStats(uid: Int, delay: Int, lost: Int, rxKBitRate: Int) { - callback( - RtcEngineEvents.RemoteAudioTransportStats, - uid.toUInt().toLong(), - delay, - lost, - rxKBitRate - ) - } - - @Deprecated("", ReplaceWith("onRemoteVideoStats")) - override fun onRemoteVideoTransportStats(uid: Int, delay: Int, lost: Int, rxKBitRate: Int) { - callback( - RtcEngineEvents.RemoteVideoTransportStats, - uid.toUInt().toLong(), - delay, - lost, - rxKBitRate - ) - } - - @Deprecated("", ReplaceWith("onRemoteVideoStateChanged")) - override fun onUserEnableVideo(uid: Int, enabled: Boolean) { - callback(RtcEngineEvents.UserEnableVideo, uid.toUInt().toLong(), enabled) - } - - @Deprecated("", ReplaceWith("onRemoteVideoStateChanged")) - override fun onUserEnableLocalVideo(uid: Int, enabled: Boolean) { - callback(RtcEngineEvents.UserEnableLocalVideo, uid.toUInt().toLong(), enabled) - } - - @Deprecated("", ReplaceWith("onRemoteVideoStateChanged")) - override fun onFirstRemoteVideoDecoded(uid: Int, width: Int, height: Int, elapsed: Int) { - callback(RtcEngineEvents.FirstRemoteVideoDecoded, uid.toUInt().toLong(), width, height, elapsed) - } - - @Deprecated("", ReplaceWith("onLocalAudioStateChanged")) - override fun onMicrophoneEnabled(enabled: Boolean) { - callback(RtcEngineEvents.MicrophoneEnabled, enabled) - } - - @Deprecated("", ReplaceWith("onConnectionStateChanged")) - override fun onConnectionInterrupted() { - callback(RtcEngineEvents.ConnectionInterrupted) - } - - @Deprecated("", ReplaceWith("onConnectionStateChanged")) - override fun onConnectionBanned() { - callback(RtcEngineEvents.ConnectionBanned) - } - - @Deprecated("", ReplaceWith("onRemoteAudioStats")) - override fun onAudioQuality( - uid: Int, - @Annotations.AgoraNetworkQuality quality: Int, - delay: Short, - lost: Short - ) { - callback(RtcEngineEvents.AudioQuality, uid.toUInt().toLong(), quality, delay, lost) - } - - @Deprecated("", ReplaceWith("onLocalVideoStateChanged")) - override fun onCameraReady() { - callback(RtcEngineEvents.CameraReady) - } - - @Deprecated("", ReplaceWith("onLocalVideoStateChanged")) - override fun onVideoStopped() { - callback(RtcEngineEvents.VideoStopped) - } - - override fun onFirstLocalAudioFramePublished(elapsed: Int) { - callback(RtcEngineEvents.FirstLocalAudioFramePublished, elapsed) - } - - override fun onFirstLocalVideoFramePublished(elapsed: Int) { - callback(RtcEngineEvents.FirstLocalVideoFramePublished, elapsed) - } - - override fun onAudioPublishStateChanged( - channel: String?, - @Annotations.AgoraStreamPublishState oldState: Int, - @Annotations.AgoraStreamPublishState newState: Int, - elapseSinceLastState: Int - ) { - callback( - RtcEngineEvents.AudioPublishStateChanged, - channel, - oldState, - newState, - elapseSinceLastState - ) - } - - override fun onVideoPublishStateChanged( - channel: String?, - @Annotations.AgoraStreamPublishState oldState: Int, - @Annotations.AgoraStreamPublishState newState: Int, - elapseSinceLastState: Int - ) { - callback( - RtcEngineEvents.VideoPublishStateChanged, - channel, - oldState, - newState, - elapseSinceLastState - ) - } - - override fun onAudioSubscribeStateChanged( - channel: String?, - uid: Int, - @Annotations.AgoraStreamSubscribeState oldState: Int, - @Annotations.AgoraStreamSubscribeState newState: Int, - elapseSinceLastState: Int - ) { - callback( - RtcEngineEvents.AudioSubscribeStateChanged, - channel, - uid.toUInt().toLong(), - oldState, - newState, - elapseSinceLastState - ) - } - - override fun onVideoSubscribeStateChanged( - channel: String?, - uid: Int, - @Annotations.AgoraStreamSubscribeState oldState: Int, - @Annotations.AgoraStreamSubscribeState newState: Int, - elapseSinceLastState: Int - ) { - callback( - RtcEngineEvents.VideoSubscribeStateChanged, - channel, - uid.toUInt().toLong(), - oldState, - newState, - elapseSinceLastState - ) - } - - override fun onRtmpStreamingEvent(url: String?, @Annotations.AgoraRtmpStreamingEvent error: Int) { - callback(RtcEngineEvents.RtmpStreamingEvent, url, error) - } - - override fun onUserSuperResolutionEnabled( - uid: Int, - enabled: Boolean, - @Annotations.AgoraSuperResolutionStateReason reason: Int - ) { - callback(RtcEngineEvents.UserSuperResolutionEnabled, uid.toUInt().toLong(), enabled, reason) - } - - override fun onUploadLogResult( - requestId: String?, - success: Boolean, - @Annotations.AgoraUploadErrorReason reason: Int - ) { - callback(RtcEngineEvents.UploadLogResult, requestId, success, reason) - } - - override fun onVirtualBackgroundSourceEnabled( - enabled: Boolean, - @Annotations.AgoraVirtualBackgroundSourceStateReason reason: Int - ) { - callback(RtcEngineEvents.VirtualBackgroundSourceEnabled, enabled, reason) - } - - override fun onSnapshotTaken( - channel: String?, - uid: Int, - filePath: String?, - width: Int, - height: Int, - errCode: Int - ) { - callback( - RtcEngineEvents.SnapshotTaken, - channel, - uid.toUInt().toLong(), - filePath, - width, - height, - errCode - ) - } -} diff --git a/android/src/main/java/io/agora/rtc/base/RtcSurfaceView.kt b/android/src/main/java/io/agora/rtc/base/RtcSurfaceView.kt deleted file mode 100644 index ff31727f6..000000000 --- a/android/src/main/java/io/agora/rtc/base/RtcSurfaceView.kt +++ /dev/null @@ -1,112 +0,0 @@ -package io.agora.rtc.base - -import android.content.Context -import android.view.SurfaceView -import android.widget.FrameLayout -import io.agora.rtc.RtcChannel -import io.agora.rtc.RtcEngine -import io.agora.rtc.video.VideoCanvas -import java.lang.ref.WeakReference - -class RtcSurfaceView( - context: Context -) : FrameLayout(context) { - private var surface: SurfaceView - private var canvas: VideoCanvas - private var isMediaOverlay = false - private var onTop = false - private var channel: WeakReference? = null - - init { - try { - surface = RtcEngine.CreateRendererView(context) - } catch (e: UnsatisfiedLinkError) { - throw RuntimeException("Please init RtcEngine first!") - } - canvas = VideoCanvas(surface) - addView(surface) - } - - fun setZOrderMediaOverlay(isMediaOverlay: Boolean) { - this.isMediaOverlay = isMediaOverlay - try { - removeView(surface) - surface.setZOrderMediaOverlay(isMediaOverlay) - addView(surface) - } catch (e: Exception) { - e.printStackTrace() - } - } - - fun setZOrderOnTop(onTop: Boolean) { - this.onTop = onTop - try { - removeView(surface) - surface.setZOrderOnTop(onTop) - addView(surface) - } catch (e: Exception) { - e.printStackTrace() - } - } - - fun setData(engine: RtcEngine, channel: RtcChannel?, uid: Number) { - this.channel = if (channel != null) WeakReference(channel) else null - canvas.channelId = this.channel?.get()?.channelId() - canvas.uid = uid.toNativeUInt() - setupVideoCanvas(engine) - } - - fun resetVideoCanvas(engine: RtcEngine) { - val canvas = - VideoCanvas(null, canvas.renderMode, canvas.channelId, canvas.uid, canvas.mirrorMode) - if (canvas.uid == 0) { - engine.setupLocalVideo(canvas) - } else { - engine.setupRemoteVideo(canvas) - } - } - - private fun setupVideoCanvas(engine: RtcEngine) { - removeAllViews() - surface = RtcEngine.CreateRendererView(context.applicationContext) - surface.setZOrderMediaOverlay(isMediaOverlay) - surface.setZOrderOnTop(onTop) - addView(surface) - surface.layout(0, 0, width, height) - canvas.view = surface - if (canvas.uid == 0) { - engine.setupLocalVideo(canvas) - } else { - engine.setupRemoteVideo(canvas) - } - } - - fun setRenderMode(engine: RtcEngine, @Annotations.AgoraVideoRenderMode renderMode: Int) { - canvas.renderMode = renderMode - setupRenderMode(engine) - } - - fun setMirrorMode(engine: RtcEngine, @Annotations.AgoraVideoMirrorMode mirrorMode: Int) { - canvas.mirrorMode = mirrorMode - setupRenderMode(engine) - } - - private fun setupRenderMode(engine: RtcEngine) { - if (canvas.uid == 0) { - engine.setLocalRenderMode(canvas.renderMode, canvas.mirrorMode) - } else { - channel?.get()?.let { - it.setRemoteRenderMode(canvas.uid, canvas.renderMode, canvas.mirrorMode) - return@setupRenderMode - } - engine.setRemoteRenderMode(canvas.uid, canvas.renderMode, canvas.mirrorMode) - } - } - - override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) { - val width: Int = MeasureSpec.getSize(widthMeasureSpec) - val height: Int = MeasureSpec.getSize(heightMeasureSpec) - surface.layout(0, 0, width, height) - super.onMeasure(widthMeasureSpec, heightMeasureSpec) - } -} diff --git a/android/src/main/java/io/agora/rtc/base/RtcTextureView.kt b/android/src/main/java/io/agora/rtc/base/RtcTextureView.kt deleted file mode 100644 index 795f7af44..000000000 --- a/android/src/main/java/io/agora/rtc/base/RtcTextureView.kt +++ /dev/null @@ -1,86 +0,0 @@ -package io.agora.rtc.base - -import android.content.Context -import android.view.TextureView -import android.widget.FrameLayout -import io.agora.rtc.RtcChannel -import io.agora.rtc.RtcEngine -import io.agora.rtc.video.VideoCanvas -import java.lang.ref.WeakReference - -class RtcTextureView( - context: Context -) : FrameLayout(context) { - private var texture: TextureView - private var canvas: VideoCanvas - private var channel: WeakReference? = null - - init { - try { - texture = RtcEngine.CreateTextureView(context) - } catch (e: UnsatisfiedLinkError) { - throw RuntimeException("Please init RtcEngine first!") - } - canvas = VideoCanvas(texture) - addView(texture) - } - - fun setData(engine: RtcEngine, channel: RtcChannel?, uid: Number) { - this.channel = if (channel != null) WeakReference(channel) else null - canvas.channelId = this.channel?.get()?.channelId() - canvas.uid = uid.toNativeUInt() - setupVideoCanvas(engine) - } - - fun resetVideoCanvas(engine: RtcEngine) { - val canvas = - VideoCanvas(null, canvas.renderMode, canvas.channelId, canvas.uid, canvas.mirrorMode) - if (canvas.uid == 0) { - engine.setupLocalVideo(canvas) - } else { - engine.setupRemoteVideo(canvas) - } - } - - private fun setupVideoCanvas(engine: RtcEngine) { - removeAllViews() - texture = RtcEngine.CreateTextureView(context.applicationContext) - addView(texture) - texture.layout(0, 0, width, height) - canvas.view = texture - if (canvas.uid == 0) { - engine.setupLocalVideo(canvas) - } else { - engine.setupRemoteVideo(canvas) - } - } - - fun setRenderMode(engine: RtcEngine, @Annotations.AgoraVideoRenderMode renderMode: Int) { - canvas.renderMode = renderMode - setupRenderMode(engine) - } - - fun setMirrorMode(engine: RtcEngine, @Annotations.AgoraVideoMirrorMode mirrorMode: Int) { - canvas.mirrorMode = mirrorMode - setupRenderMode(engine) - } - - private fun setupRenderMode(engine: RtcEngine) { - if (canvas.uid == 0) { - engine.setLocalRenderMode(canvas.renderMode, canvas.mirrorMode) - } else { - channel?.get()?.let { - it.setRemoteRenderMode(canvas.uid, canvas.renderMode, canvas.mirrorMode) - return@setupRenderMode - } - engine.setRemoteRenderMode(canvas.uid, canvas.renderMode, canvas.mirrorMode) - } - } - - override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) { - val width: Int = MeasureSpec.getSize(widthMeasureSpec) - val height: Int = MeasureSpec.getSize(heightMeasureSpec) - texture.layout(0, 0, width, height) - super.onMeasure(widthMeasureSpec, heightMeasureSpec) - } -} diff --git a/android/src/main/kotlin/io/agora/agora_rtc_engine/AgoraPlatformView.kt b/android/src/main/kotlin/io/agora/agora_rtc_engine/AgoraPlatformView.kt new file mode 100644 index 000000000..633dfe51a --- /dev/null +++ b/android/src/main/kotlin/io/agora/agora_rtc_engine/AgoraPlatformView.kt @@ -0,0 +1,82 @@ +package io.agora.agora_rtc_engine + +import android.content.Context +import android.view.View +import android.widget.FrameLayout +import io.agora.iris.rtc.IrisRtcEngine +import io.agora.iris.rtc.base.ApiTypeEngine +import io.flutter.plugin.common.BinaryMessenger +import io.flutter.plugin.common.ErrorLogResult +import io.flutter.plugin.common.MethodCall +import io.flutter.plugin.common.MethodChannel +import io.flutter.plugin.platform.PlatformView + +private class PlatformViewApiTypeCallApiMethodCallHandler( + irisRtcEngine: IrisRtcEngine, + private val platformView: AgoraPlatformView +) : CallApiMethodCallHandler(irisRtcEngine) { + override fun callApi(apiType: Int, params: String?, sb: StringBuffer): Int { + platformView.updateView() + return irisRtcEngine.callApi(ApiTypeEngine.fromInt(apiType), params, platformView.getIrisRenderView(), sb) + } +} + +// We should ensure not doing some leak in constructor +@Suppress("LeakingThis") +abstract class AgoraPlatformView( + private val context: Context, + messenger: BinaryMessenger, + viewId: Int, + args: Map<*, *>?, + private val irisRtcEngine: IrisRtcEngine +) : PlatformView, MethodChannel.MethodCallHandler { + + private val parentView: FrameLayout = FrameLayout(context) + + private var platformView: View + + private val channel: MethodChannel + + private val callApiMethodCallHandler: CallApiMethodCallHandler = + PlatformViewApiTypeCallApiMethodCallHandler(irisRtcEngine, this) + + init { + platformView = createView(context.applicationContext) + parentView.addView(platformView) + + channel = MethodChannel(messenger, "${channelName}_$viewId") + channel.setMethodCallHandler(this) + + args?.apply { + for ((key, value) in entries) { + onMethodCall(MethodCall(key as String, value), ErrorLogResult("")) + } + } + } + + fun updateView() { + parentView.removeAllViews() + platformView = createView(context.applicationContext) + parentView.addView(platformView) + } + + abstract fun createView(context: Context): View + + protected abstract val channelName: String + + fun getIrisRenderView(): View { + return platformView + } + + override fun getView(): View { + return parentView + } + + override fun dispose() { + channel.setMethodCallHandler(null) + } + + override fun onMethodCall(call: MethodCall, result: MethodChannel.Result) { + callApiMethodCallHandler.onMethodCall(call, result) + } +} diff --git a/android/src/main/kotlin/io/agora/agora_rtc_engine/AgoraRtcChannelPlugin.kt b/android/src/main/kotlin/io/agora/agora_rtc_engine/AgoraRtcChannelPlugin.kt index e6bd0a04c..ae6535513 100644 --- a/android/src/main/kotlin/io/agora/agora_rtc_engine/AgoraRtcChannelPlugin.kt +++ b/android/src/main/kotlin/io/agora/agora_rtc_engine/AgoraRtcChannelPlugin.kt @@ -2,10 +2,10 @@ package io.agora.agora_rtc_engine import android.os.Handler import android.os.Looper +import android.util.Log import androidx.annotation.NonNull -import io.agora.rtc.RtcChannel -import io.agora.rtc.RtcEngine -import io.agora.rtc.base.RtcChannelManager +import io.agora.iris.rtc.IrisRtcEngine +import io.agora.iris.rtc.base.ApiTypeChannel import io.flutter.embedding.engine.plugins.FlutterPlugin import io.flutter.plugin.common.BinaryMessenger import io.flutter.plugin.common.EventChannel @@ -14,9 +14,22 @@ import io.flutter.plugin.common.MethodChannel import io.flutter.plugin.common.MethodChannel.MethodCallHandler import io.flutter.plugin.common.MethodChannel.Result +private class ApiTypeChannelCallApiMethodCallHandler( + irisRtcEngine: IrisRtcEngine +) : CallApiMethodCallHandler(irisRtcEngine) { + override fun callApi(apiType: Int, params: String?, sb: StringBuffer): Int { + return irisRtcEngine.channel.callApi(ApiTypeChannel.fromInt(apiType), params, sb) + } + + override fun callApiWithBuffer(apiType: Int, params: String?, buffer: ByteArray?, sb: StringBuffer): Int { + return irisRtcEngine.channel.callApi(ApiTypeChannel.fromInt(apiType), params, buffer, sb) + } +} + /** AgoraRtcChannelPlugin */ class AgoraRtcChannelPlugin( - private val rtcEnginePlugin: AgoraRtcEnginePlugin +// private val rtcEnginePlugin: AgoraRtcEnginePlugin + private val irisRtcEngine: IrisRtcEngine ) : FlutterPlugin, MethodCallHandler, EventChannel.StreamHandler { /// The MethodChannel that will the communication between Flutter and native Android /// @@ -25,14 +38,20 @@ class AgoraRtcChannelPlugin( private lateinit var methodChannel: MethodChannel private lateinit var eventChannel: EventChannel private var eventSink: EventChannel.EventSink? = null - private val manager = RtcChannelManager { methodName, data -> emit(methodName, data) } +// private val manager = RtcChannelManager { methodName, data -> emit(methodName, data) } private val handler = Handler(Looper.getMainLooper()) + private lateinit var callApiMethodCallHandler: CallApiMethodCallHandler + fun initPlugin(binaryMessenger: BinaryMessenger) { methodChannel = MethodChannel(binaryMessenger, "agora_rtc_channel") methodChannel.setMethodCallHandler(this) eventChannel = EventChannel(binaryMessenger, "agora_rtc_channel/events") eventChannel.setStreamHandler(this) + + callApiMethodCallHandler = ApiTypeChannelCallApiMethodCallHandler(irisRtcEngine) + + } override fun onAttachedToEngine(binding: FlutterPlugin.FlutterPluginBinding) { @@ -42,51 +61,23 @@ class AgoraRtcChannelPlugin( override fun onDetachedFromEngine(binding: FlutterPlugin.FlutterPluginBinding) { methodChannel.setMethodCallHandler(null) eventChannel.setStreamHandler(null) - manager.release() } override fun onListen(arguments: Any?, events: EventChannel.EventSink?) { + eventSink = events + + irisRtcEngine.channel.setEventHandler(EventHandler(eventSink)) + Log.e("MainActivity", "channel onListen: $eventSink") } override fun onCancel(arguments: Any?) { + irisRtcEngine.channel.setEventHandler(null) eventSink = null } - private fun emit(methodName: String, data: Map?) { - handler.post { - val event: MutableMap = mutableMapOf("methodName" to methodName) - data?.let { event.putAll(it) } - eventSink?.success(event) - } - } - - private fun engine(): RtcEngine? { - return rtcEnginePlugin.engine() - } - - fun channel(channelId: String): RtcChannel? { - return manager[channelId] - } - override fun onMethodCall(@NonNull call: MethodCall, @NonNull result: Result) { - manager.javaClass.declaredMethods.find { it.name == call.method }?.let { function -> - function.let { method -> - try { - val parameters = mutableListOf() - call.arguments>()?.toMutableMap()?.let { - if (call.method == "create") { - it["engine"] = engine() - } - parameters.add(it) - } - method.invoke(manager, *parameters.toTypedArray(), ResultCallback(result)) - return@onMethodCall - } catch (e: Exception) { - e.printStackTrace() - } - } - } - result.notImplemented() + // Iris supported + callApiMethodCallHandler.onMethodCall(call, result) } } diff --git a/android/src/main/kotlin/io/agora/agora_rtc_engine/AgoraRtcEnginePlugin.kt b/android/src/main/kotlin/io/agora/agora_rtc_engine/AgoraRtcEnginePlugin.kt index f4995837d..1f2eb6d34 100644 --- a/android/src/main/kotlin/io/agora/agora_rtc_engine/AgoraRtcEnginePlugin.kt +++ b/android/src/main/kotlin/io/agora/agora_rtc_engine/AgoraRtcEnginePlugin.kt @@ -3,16 +3,113 @@ package io.agora.agora_rtc_engine import android.content.Context import android.os.Handler import android.os.Looper +import android.util.Log import androidx.annotation.NonNull +import io.agora.iris.base.IrisEventHandler +import io.agora.iris.rtc.IrisRtcEngine +import io.agora.iris.rtc.base.ApiTypeEngine import io.agora.rtc.RtcEngine -import io.agora.rtc.base.RtcEngineManager import io.agora.rtc.base.RtcEngineRegistry +import io.flutter.BuildConfig import io.flutter.embedding.engine.plugins.FlutterPlugin import io.flutter.plugin.common.* import io.flutter.plugin.common.MethodChannel.MethodCallHandler import io.flutter.plugin.common.MethodChannel.Result import io.flutter.plugin.common.PluginRegistry.Registrar import io.flutter.plugin.platform.PlatformViewRegistry +import kotlin.math.abs + +internal class EventHandler(private val eventSink: EventChannel.EventSink?) : IrisEventHandler { + private val handler = Handler(Looper.getMainLooper()) + override fun OnEvent(event: String?, data: String?) { + handler.post { + eventSink?.success(mapOf("methodName" to event, "data" to data)) + } + } + + override fun OnEvent(event: String?, data: String?, buffer: ByteArray?) { + handler.post { + eventSink?.success(mapOf("methodName" to event, "data" to data, "buffer" to buffer)) + } + } +} + +open class CallApiMethodCallHandler( + protected val irisRtcEngine: IrisRtcEngine +) : MethodCallHandler { + + protected open fun callApi(apiType: Int, params: String?, sb: StringBuffer): Int { + val type = ApiTypeEngine.fromInt(apiType) + val ret = irisRtcEngine.callApi(type, params, sb) + if (type == ApiTypeEngine.kEngineInitialize) { + RtcEngineRegistry.instance.onRtcEngineCreated(irisRtcEngine.rtcEngine as RtcEngine?) + } + if (type == ApiTypeEngine.kEngineRelease) { + RtcEngineRegistry.instance.onRtcEngineDestroyed() + } + + return ret + } + + protected open fun callApiWithBuffer( + apiType: Int, + params: String?, + buffer: ByteArray?, + sb: StringBuffer): Int { + return irisRtcEngine.callApi(ApiTypeEngine.fromInt(apiType), params, buffer, sb) + } + + protected open fun callApiError(ret: Int): String { + val description = StringBuffer() + irisRtcEngine.callApi( + ApiTypeEngine.kEngineGetErrorDescription, + "{\"code\":" + abs(ret) + "}", + description + ) + return description.toString() + } + + override fun onMethodCall(call: MethodCall, result: Result) { + val apiType = call.argument("apiType") + val params = call.argument("params") + val sb = StringBuffer() + + if (BuildConfig.DEBUG && "getIrisRtcEngineIntPtr" == call.method) { + result.success(irisRtcEngine.nativeHandle) + return + } + try { + val ret = when (call.method) { + "callApi" -> { + callApi(apiType!!, params, sb) + } + "callApiWithBuffer" -> { + val buffer = call.argument("buffer") + callApiWithBuffer(apiType!!, params, buffer, sb) + } + else -> { + // This should not occur + -1 + } + } + + if (ret == 0) { + if (sb.isEmpty()) { + result.success(null) + } else { + result.success(sb.toString()) + } + } else if (ret > 0) { + result.success(ret) + } else { + val errorMsg = callApiError(ret) + result.error(ret.toString(), errorMsg, null) + } + } catch (e: Exception) { + result.error("", e.message ?: "", null) + } + } +} /** AgoraRtcEnginePlugin */ class AgoraRtcEnginePlugin : FlutterPlugin, MethodCallHandler, EventChannel.StreamHandler { @@ -20,6 +117,8 @@ class AgoraRtcEnginePlugin : FlutterPlugin, MethodCallHandler, EventChannel.Stre private var binding: FlutterPlugin.FlutterPluginBinding? = null private lateinit var applicationContext: Context + private lateinit var irisRtcEngine: IrisRtcEngine + /// The MethodChannel that will the communication between Flutter and native Android /// /// This local reference serves to register the plugin with the Flutter Engine and unregister it @@ -28,9 +127,10 @@ class AgoraRtcEnginePlugin : FlutterPlugin, MethodCallHandler, EventChannel.Stre private lateinit var eventChannel: EventChannel private var eventSink: EventChannel.EventSink? = null - private val manager = RtcEngineManager(emit = { methodName, data -> emit(methodName, data) }) +// private val managerAgoraTextureView = RtcEngineManager { methodName, data -> emit(methodName, data) } private val handler = Handler(Looper.getMainLooper()) - private val rtcChannelPlugin = AgoraRtcChannelPlugin(this) + private lateinit var rtcChannelPlugin: AgoraRtcChannelPlugin;// = AgoraRtcChannelPlugin(irisRtcEngine) + private lateinit var callApiMethodCallHandler: CallApiMethodCallHandler // This static function is optional and equivalent to onAttachedToEngine. It supports the old // pre-Flutter-1.12 Android projects. You are encouraged to continue supporting @@ -46,7 +146,7 @@ class AgoraRtcEnginePlugin : FlutterPlugin, MethodCallHandler, EventChannel.Stre fun registerWith(registrar: Registrar) { AgoraRtcEnginePlugin().apply { this.registrar = registrar - rtcChannelPlugin.initPlugin(registrar.messenger()) + initPlugin(registrar.context(), registrar.messenger(), registrar.platformViewRegistry()) } } @@ -58,24 +158,30 @@ class AgoraRtcEnginePlugin : FlutterPlugin, MethodCallHandler, EventChannel.Stre platformViewRegistry: PlatformViewRegistry ) { applicationContext = context.applicationContext + irisRtcEngine = IrisRtcEngine(applicationContext) methodChannel = MethodChannel(binaryMessenger, "agora_rtc_engine") methodChannel.setMethodCallHandler(this) eventChannel = EventChannel(binaryMessenger, "agora_rtc_engine/events") eventChannel.setStreamHandler(this) + callApiMethodCallHandler = CallApiMethodCallHandler(irisRtcEngine) + platformViewRegistry.registerViewFactory( "AgoraSurfaceView", - AgoraSurfaceViewFactory(binaryMessenger, this, rtcChannelPlugin) + AgoraSurfaceViewFactory(binaryMessenger, irisRtcEngine) ) platformViewRegistry.registerViewFactory( "AgoraTextureView", - AgoraTextureViewFactory(binaryMessenger, this, rtcChannelPlugin) + AgoraTextureViewFactory(binaryMessenger, irisRtcEngine) ) + + rtcChannelPlugin = AgoraRtcChannelPlugin(irisRtcEngine) + rtcChannelPlugin.initPlugin(binaryMessenger) } override fun onAttachedToEngine(@NonNull binding: FlutterPlugin.FlutterPluginBinding) { this.binding = binding - rtcChannelPlugin.onAttachedToEngine(binding) +// rtcChannelPlugin.onAttachedToEngine(binding) initPlugin(binding.applicationContext, binding.binaryMessenger, binding.platformViewRegistry) } @@ -83,52 +189,53 @@ class AgoraRtcEnginePlugin : FlutterPlugin, MethodCallHandler, EventChannel.Stre rtcChannelPlugin.onDetachedFromEngine(binding) methodChannel.setMethodCallHandler(null) eventChannel.setStreamHandler(null) - manager.release() + + irisRtcEngine.destroy() } override fun onListen(arguments: Any?, events: EventChannel.EventSink?) { + eventSink = events + irisRtcEngine.setEventHandler(EventHandler(eventSink)) + Log.e("MainActivity", "eventSink: $eventSink") } override fun onCancel(arguments: Any?) { + irisRtcEngine.setEventHandler(null) eventSink = null } - private fun emit(methodName: String, data: Map?) { - handler.post { - val event: MutableMap = mutableMapOf("methodName" to methodName) - data?.let { event.putAll(it) } - eventSink?.success(event) - } - } - - fun engine(): RtcEngine? { - return manager.engine - } +// private fun emit(methodName: String, data: Map?) { +// handler.post { +// val event: MutableMap = mutableMapOf("methodName" to methodName) +// data?.let { event.putAll(it) } +// eventSink?.success(event) +// } +// } override fun onMethodCall(@NonNull call: MethodCall, @NonNull result: Result) { - if (call.method == "getAssetAbsolutePath") { - getAssetAbsolutePath(call, result) - return - } - manager.javaClass.declaredMethods.find { it.name == call.method }?.let { function -> - function.let { method -> - try { - val parameters = mutableListOf() - call.arguments>()?.toMutableMap()?.let { - if (call.method == "create") { - it["context"] = applicationContext - } - parameters.add(it) - } - method.invoke(manager, *parameters.toTypedArray(), ResultCallback(result)) - return@onMethodCall - } catch (e: Exception) { - e.printStackTrace() +// val textureRegistry = registrar?.textures() ?: binding?.textureRegistry +// val messenger = registrar?.messenger() ?: binding?.binaryMessenger + + // Iris supported + when (call.method) { + "createTextureRender" -> { + result.notImplemented() + return + } + "destroyTextureRender" -> { + result.notImplemented() + return + } + "getAssetAbsolutePath" -> { + getAssetAbsolutePath(call, result) + return + } + else -> { + callApiMethodCallHandler.onMethodCall(call, result) } - } } - result.notImplemented() + } private fun getAssetAbsolutePath(call: MethodCall, result: Result) { diff --git a/android/src/main/kotlin/io/agora/agora_rtc_engine/AgoraSurfaceViewFactory.kt b/android/src/main/kotlin/io/agora/agora_rtc_engine/AgoraSurfaceViewFactory.kt index e7e6ed7ec..093885fe2 100644 --- a/android/src/main/kotlin/io/agora/agora_rtc_engine/AgoraSurfaceViewFactory.kt +++ b/android/src/main/kotlin/io/agora/agora_rtc_engine/AgoraSurfaceViewFactory.kt @@ -1,10 +1,11 @@ package io.agora.agora_rtc_engine import android.content.Context +import android.view.SurfaceView import android.view.View -import io.agora.rtc.RtcChannel +import android.widget.FrameLayout +import io.agora.iris.rtc.IrisRtcEngine import io.agora.rtc.RtcEngine -import io.agora.rtc.base.RtcSurfaceView import io.flutter.plugin.common.BinaryMessenger import io.flutter.plugin.common.MethodCall import io.flutter.plugin.common.MethodChannel @@ -14,99 +15,53 @@ import io.flutter.plugin.platform.PlatformViewFactory class AgoraSurfaceViewFactory( private val messenger: BinaryMessenger, - private val rtcEnginePlugin: AgoraRtcEnginePlugin, - private val rtcChannelPlugin: AgoraRtcChannelPlugin +private val irisRtcEngine: IrisRtcEngine ) : PlatformViewFactory(StandardMessageCodec.INSTANCE) { override fun create(context: Context, viewId: Int, args: Any?): PlatformView { - return AgoraSurfaceView( + return AgoraPlatformViewSurface( context.applicationContext, messenger, viewId, args as? Map<*, *>, - rtcEnginePlugin, - rtcChannelPlugin + irisRtcEngine ) } } -internal class AgoraSurfaceView( +class AgoraPlatformViewSurface( context: Context, messenger: BinaryMessenger, - viewId: Int, - args: Map<*, *>?, - private val rtcEnginePlugin: AgoraRtcEnginePlugin, - private val rtcChannelPlugin: AgoraRtcChannelPlugin -) : PlatformView, MethodChannel.MethodCallHandler { - private val view = RtcSurfaceView(context) - private val channel = MethodChannel(messenger, "agora_rtc_engine/surface_view_$viewId") - - init { - args?.let { map -> - (map["data"] as? Map<*, *>)?.let { setData(it) } - (map["renderMode"] as? Number)?.let { setRenderMode(it.toInt()) } - (map["mirrorMode"] as? Number)?.let { setMirrorMode(it.toInt()) } - (map["zOrderOnTop"] as? Boolean)?.let { setZOrderOnTop(it) } - (map["zOrderMediaOverlay"] as? Boolean)?.let { setZOrderMediaOverlay(it) } - } - channel.setMethodCallHandler(this) - } - - override fun getView(): View { - return view + viewId: Int, args: Map<*, *>?, + irisRtcEngine: IrisRtcEngine +) : AgoraPlatformView(context, messenger, viewId, args, irisRtcEngine) { + override fun createView(context: Context): View { + return RtcEngine.CreateRendererView(context) } - override fun dispose() { - channel.setMethodCallHandler(null) - } + override val channelName: String + get() = "agora_rtc_engine/surface_view" override fun onMethodCall(call: MethodCall, result: MethodChannel.Result) { - this.javaClass.declaredMethods.find { it.name == call.method }?.let { function -> - function.let { method -> - val parameters = mutableListOf() - call.arguments>()?.let { args -> - args.values.forEach { - parameters.add(it) - } - } - try { - method.invoke(this, *parameters.toTypedArray()) - result.success(null) - return@onMethodCall - } catch (e: Exception) { - e.printStackTrace() - result.error(e.toString(), null, null) - } + when (call.method) { + "setZOrderOnTop" -> { + val surfaceView = getIrisRenderView() as SurfaceView + val parentView = view as FrameLayout + parentView.removeView(surfaceView) + surfaceView.setZOrderOnTop((call.argument("onTop"))!!) + parentView.addView(surfaceView) + result.success(null) + } + "setZOrderMediaOverlay" -> { + val surfaceView = getIrisRenderView() as SurfaceView + val parentView = view as FrameLayout + parentView.removeView(surfaceView) + surfaceView.setZOrderMediaOverlay((call.argument("isMediaOverlay"))!!) + parentView.addView(surfaceView) + result.success(null) + } + else -> { + super.onMethodCall(call, result) } } - result.notImplemented() - } - - private fun setData(data: Map<*, *>) { - val channel = (data["channelId"] as? String)?.let { getChannel(it) } - getEngine()?.let { view.setData(it, channel, (data["uid"] as Number).toInt()) } - } - - private fun setRenderMode(renderMode: Int) { - getEngine()?.let { view.setRenderMode(it, renderMode) } - } - - private fun setMirrorMode(mirrorMode: Int) { - getEngine()?.let { view.setMirrorMode(it, mirrorMode) } - } - - private fun setZOrderOnTop(onTop: Boolean) { - view.setZOrderOnTop(onTop) - } - - private fun setZOrderMediaOverlay(isMediaOverlay: Boolean) { - view.setZOrderMediaOverlay(isMediaOverlay) - } - - private fun getEngine(): RtcEngine? { - return rtcEnginePlugin.engine() - } - - private fun getChannel(channelId: String): RtcChannel? { - return rtcChannelPlugin.channel(channelId) } } diff --git a/android/src/main/kotlin/io/agora/agora_rtc_engine/AgoraTextureViewFactory.kt b/android/src/main/kotlin/io/agora/agora_rtc_engine/AgoraTextureViewFactory.kt index 0e70f2913..83afca3a4 100644 --- a/android/src/main/kotlin/io/agora/agora_rtc_engine/AgoraTextureViewFactory.kt +++ b/android/src/main/kotlin/io/agora/agora_rtc_engine/AgoraTextureViewFactory.kt @@ -2,101 +2,40 @@ package io.agora.agora_rtc_engine import android.content.Context import android.view.View -import io.agora.rtc.RtcChannel +import io.agora.iris.rtc.IrisRtcEngine import io.agora.rtc.RtcEngine -import io.agora.rtc.base.RtcTextureView import io.flutter.plugin.common.BinaryMessenger -import io.flutter.plugin.common.MethodCall -import io.flutter.plugin.common.MethodChannel import io.flutter.plugin.common.StandardMessageCodec import io.flutter.plugin.platform.PlatformView import io.flutter.plugin.platform.PlatformViewFactory class AgoraTextureViewFactory( private val messenger: BinaryMessenger, - private val rtcEnginePlugin: AgoraRtcEnginePlugin, - private val rtcChannelPlugin: AgoraRtcChannelPlugin + private val irisRtcEngine: IrisRtcEngine ) : PlatformViewFactory(StandardMessageCodec.INSTANCE) { + override fun create(context: Context, viewId: Int, args: Any?): PlatformView { - return AgoraTextureView( + return AgoraPlatformViewTexture( context.applicationContext, messenger, viewId, args as? Map<*, *>, - rtcEnginePlugin, - rtcChannelPlugin + irisRtcEngine ) } } -class AgoraTextureView( +class AgoraPlatformViewTexture( context: Context, messenger: BinaryMessenger, - viewId: Int, - args: Map<*, *>?, - private val rtcEnginePlugin: AgoraRtcEnginePlugin, - private val rtcChannelPlugin: AgoraRtcChannelPlugin -) : PlatformView, MethodChannel.MethodCallHandler { - private val view = RtcTextureView(context) - private val channel = MethodChannel(messenger, "agora_rtc_engine/texture_view_$viewId") - - init { - args?.let { map -> - (map["data"] as? Map<*, *>)?.let { setData(it) } - (map["renderMode"] as? Number)?.let { setRenderMode(it.toInt()) } - (map["mirrorMode"] as? Number)?.let { setMirrorMode(it.toInt()) } - } - channel.setMethodCallHandler(this) - } - - override fun getView(): View { - return view - } - - override fun dispose() { - channel.setMethodCallHandler(null) - } - - override fun onMethodCall(call: MethodCall, result: MethodChannel.Result) { - this.javaClass.declaredMethods.find { it.name == call.method }?.let { function -> - function.let { method -> - val parameters = mutableListOf() - call.arguments>()?.let { args -> - args.values.forEach { - parameters.add(it) - } - } - try { - method.invoke(this, *parameters.toTypedArray()) - result.success(null) - return@onMethodCall - } catch (e: Exception) { - e.printStackTrace() - result.error(e.toString(), null, null) - } - } - } - result.notImplemented() - } - - private fun setData(data: Map<*, *>) { - val channel = (data["channelId"] as? String)?.let { getChannel(it) } - getEngine()?.let { view.setData(it, channel, (data["uid"] as Number).toInt()) } - } - - private fun setRenderMode(renderMode: Int) { - getEngine()?.let { view.setRenderMode(it, renderMode) } - } - - private fun setMirrorMode(mirrorMode: Int) { - getEngine()?.let { view.setMirrorMode(it, mirrorMode) } - } + viewId: Int, args: Map<*, *>?, + irisRtcEngine: IrisRtcEngine +) : AgoraPlatformView(context, messenger, viewId, args, irisRtcEngine) { + override fun createView(context: Context): View { - private fun getEngine(): RtcEngine? { - return rtcEnginePlugin.engine() + return RtcEngine.CreateTextureView(context) } - private fun getChannel(channelId: String): RtcChannel? { - return rtcChannelPlugin.channel(channelId) - } + override val channelName: String + get() = "agora_rtc_engine/texture_view" } diff --git a/android/src/main/kotlin/io/agora/agora_rtc_engine/ResultCallback.kt b/android/src/main/kotlin/io/agora/agora_rtc_engine/ResultCallback.kt deleted file mode 100644 index f3adf3689..000000000 --- a/android/src/main/kotlin/io/agora/agora_rtc_engine/ResultCallback.kt +++ /dev/null @@ -1,16 +0,0 @@ -package io.agora.agora_rtc_engine - -import io.agora.rtc.base.Callback -import io.flutter.plugin.common.MethodChannel.Result - -class ResultCallback( - private val result: Result? -) : Callback() { - override fun success(data: Any?) { - result?.success(data) - } - - override fun failure(code: String, message: String) { - result?.error(code, message, null) - } -} diff --git a/ci/run_flutter_integration_test.sh b/ci/run_flutter_integration_test.sh new file mode 100644 index 000000000..c92e59f2c --- /dev/null +++ b/ci/run_flutter_integration_test.sh @@ -0,0 +1,15 @@ +#!/usr/bin/env bash + +set -e +set -x + +flutter packages get + +cd integration_test_app + +pushd iris_integration_test +git submodule update +popd + +flutter packages get +flutter test integration_test --dart-define=TEST_APP_ID="${TEST_APP_ID}" \ No newline at end of file diff --git a/ci/run_flutter_macos_integration_test.sh b/ci/run_flutter_macos_integration_test.sh new file mode 100644 index 000000000..d71cfe16f --- /dev/null +++ b/ci/run_flutter_macos_integration_test.sh @@ -0,0 +1,22 @@ +#!/usr/bin/env bash + +set -e +set -x + +flutter packages get + +cd integration_test_app + +pushd iris_integration_test +git submodule update +popd + +flutter packages get + +# It's a little tricky that you should run integration test one by one on flutter macOS/Windows +for filename in integration_test/*.dart; do + if [[ "$filename" == *.generated.dart ]]; then + continue + fi + flutter test $filename --dart-define=TEST_APP_ID="${TEST_APP_ID}" +done \ No newline at end of file diff --git a/example/.gitignore b/example/.gitignore index f3c205341..0fa6b675c 100644 --- a/example/.gitignore +++ b/example/.gitignore @@ -40,5 +40,7 @@ app.*.symbols # Obfuscation related app.*.map.json -# Exceptions to above rules. -!/packages/flutter_tools/test/data/dart_dependencies_test/**/.packages +# Android Studio will place build artifacts here +/android/app/debug +/android/app/profile +/android/app/release diff --git a/example/.metadata b/example/.metadata index a505a25d3..80206eb5a 100644 --- a/example/.metadata +++ b/example/.metadata @@ -4,7 +4,7 @@ # This file should be version controlled and should not be manually edited. version: - revision: 9a99403ad262cc4ead21e01d130d77f3a49f3de4 - channel: master + revision: c5a4b4029c0798f37c4a39b479d7cb75daa7b05c + channel: stable project_type: app diff --git a/example/README.md b/example/README.md index 7bbd18297..5043aa14d 100644 --- a/example/README.md +++ b/example/README.md @@ -16,19 +16,24 @@ Any scene of this project can run successfully alone. | Demo | Description | APIs | | ------------------------------------------------------------ | -------------------------------------------------- | ------------------------------------------------------------ | -| [JoinChannelAudio](./lib/examples/basic/join_channel_audio) | Audio live streaming | GetEngine, JoinChannelByKey, LeaveChannel | -| [JoinChannelVideo](./lib/examples/basic/join_channel_video) | Video live streaming | SetChannelProfile,SetClientRole,EnableVideo,EnableVideoObserver, JoinChannelByKey, VideoSurface | -| [StringUid](./lib/examples/basic/string_uid) | String user ID | SetChannelProfile,SetClientRole,EnableVideo,EnableVideoObserver, JoinChannelByKey, VideoSurface | +| [JoinChannelAudio](./lib/examples/basic/join_channel_audio) | Audio live streaming | | +| [JoinChannelVideo](./lib/examples/basic/join_channel_video) | Video live streaming | | +| [StringUid](./lib/examples/basic/string_uid) | String user ID | | * **Advanced demos:** | Demo | Description | APIs | | ------------------------------------------------------------ | ------------------------------------------------------------ | ------------------------------------------------------------ | -| [JoinMultipleChannel](./lib/examples/advanced/join_multiple_channel) | Join multiple channels | CreateChannel, SetClientRole, EnableEncryption, LeaveChannel, ReleaseChannel | -| [VoiceChanger](./lib/examples/advanced/voice_changer) | Voice effects | CreateChannel, SetClientRole, EnableEncryption, LeaveChannel, ReleaseChannel | -| [ChannelMediaRelay](./lib/examples/advanced/channel_media_relay) | Channel media relay | CreateChannel, SetClientRole, EnableEncryption, LeaveChannel, ReleaseChannel | -| [StreamMessage](./lib/examples/advanced/stream_message) | Send data stream | CreateChannel, SetClientRole, EnableEncryption, LeaveChannel, ReleaseChannel | +| [AudioMixing](./lib/examples/advanced/audio_mixing) | Audio mixing | +| [ChannelMediaRelay](./lib/examples/advanced/channel_media_relay) | Channel media relay | | | [CustomCaptureAudio](./lib/examples/advanced/custom_capture_audio)| Custom audio capture | | +| [JoinMultipleChannel](./lib/examples/advanced/join_multiple_channel) | Join multiple channels | | +| [RTMPStreaming](./lib/examples/advanced/rtmp_streaming)| RTMP streaming | | +| [ScreenSharing](./lib/examples/advanced/screen_sharing)| Screen sharing | | +| [SetEncryption](./lib/examples/advanced/set_encryption)| Set encryption | | +| [SetVideoEncoderConfiguration](./lib/examples/advanced/set_video_encoder_configuration)| Set video encoder configuration | | +| [StreamMessage](./lib/examples/advanced/stream_message) | Send data stream | | +| [VoiceChanger](./lib/examples/advanced/voice_changer) | Voice effects | | ## How to run the sample project @@ -54,8 +59,8 @@ Any scene of this project can run successfully alone. 4. Make the project and run the app in the simulator or connected physical device. -You are all set! Feel free to play with this sample project and explore features of the Agora RTC SDK. - +You are all set! Feel free to play with this sample project and explore features of the Agora RTC +SDK. ## Feedback @@ -70,9 +75,12 @@ If you have any problems or suggestions regarding the sample projects, feel free - Check our [FAQ](https://docs.agora.io/en/faq) to see if your issue has been recorded. - Dive into [Agora SDK Samples](https://github.com/AgoraIO) to see more tutorials -- Take a look at [Agora Use Case](https://github.com/AgoraIO-usecase) for more complicated real use case -- Repositories managed by developer communities can be found at [Agora Community](https://github.com/AgoraIO-Community) -- If you encounter problems during integration, feel free to ask questions in [Stack Overflow](https://stackoverflow.com/questions/tagged/agora.io) +- Take a look at [Agora Use Case](https://github.com/AgoraIO-usecase) for more complicated real use + case +- Repositories managed by developer communities can be found + at [Agora Community](https://github.com/AgoraIO-Community) +- If you encounter problems during integration, feel free to ask questions + in [Stack Overflow](https://stackoverflow.com/questions/tagged/agora.io) ## License diff --git a/example/README.zh.md b/example/README.zh.md index b1aeca178..6867455b4 100644 --- a/example/README.zh.md +++ b/example/README.zh.md @@ -16,19 +16,22 @@ | Demo | Description | APIs | | ------------------------------------------------------------ | -------------------------------------------------- | ------------------------------------------------------------ | -| [JoinChannelAudio](./lib/examples/basic/join_channel_audio) | 音频直播 | GetEngine, JoinChannelByKey, LeaveChannel | -| [JoinChannelVideo](./lib/examples/basic/join_channel_video) | 视频直播 | SetChannelProfile,SetClientRole,EnableVideo,EnableVideoObserver, JoinChannelByKey, VideoSurface | -| [StringUid](./lib/examples/basic/string_uid) | 字符串用户ID | SetChannelProfile,SetClientRole,EnableVideo,EnableVideoObserver, JoinChannelByKey, VideoSurface | +| [JoinChannelAudio](./lib/examples/basic/join_channel_audio) | 音频直播 | | +| [JoinChannelVideo](./lib/examples/basic/join_channel_video) | 视频直播 | | +| [StringUid](./lib/examples/basic/string_uid) | 字符串用户ID | | * **进阶案例:** | Demo | Description | APIs | | ------------------------------------------------------------ | ------------------------------------------------------------ | ------------------------------------------------------------ | -| [JoinMultipleChannel](./lib/examples/advanced/join_multiple_channel) | 加入多频道 | CreateChannel, SetClientRole, EnableEncryption, LeaveChannel, ReleaseChannel | -| [VoiceChanger](./lib/examples/advanced/voice_changer) | 音频效果 | SetOnCaptureVideoFrameCallback, SetOnRenderVideoFrameCallback, OnRenderVideoFrameHandler, OnCaptureVideoFrameHandler | -| [ChannelMediaRelay](./lib/examples/advanced/channel_media_relay) | 频道媒体流转发 | RegisterAudioRawDataObserver, SetOnPlaybackAudioFrameCallback, OnPlaybackAudioFrameHandler | -| [StreamMessage](./lib/examples/advanced/stream_message) | 发送数据流 | SetVideoEncoderConfiguration, SetLiveTranscoding, AddPublishStreamUrl, RemovePublishStreamUrl | +| [AudioMixing](./lib/examples/advanced/audio_mixing) | 混音 | | +| [ChannelMediaRelay](./lib/examples/advanced/channel_media_relay) | 频道媒体流转发 | | | [CustomCaptureAudio](./lib/examples/advanced/custom_capture_audio)| 音频自采集 | | +| [JoinMultipleChannel](./lib/examples/advanced/join_multiple_channel) | 加入多频道 | | +| [RTMPStreaming](./lib/examples/advanced/rtmp_streaming)| RTMP推流 | | +| [ScreenSharing](./lib/examples/advanced/screen_sharing)| 屏幕共享 | | +| [SetEncryption](./lib/examples/advanced/set_encryption)| 开启加密 | | +| [SetVideoEncoderConfiguration](./lib/examples/advanced/set_video_encoder_configuration)| 设置视频编码参数 | | ## 如何运行示例程序 diff --git a/example/android/.gitignore b/example/android/.gitignore index 5da0a3e6c..26bd9ae37 100644 --- a/example/android/.gitignore +++ b/example/android/.gitignore @@ -2,3 +2,7 @@ /captures/ /local.properties GeneratedPluginRegistrant.java + +# Remember to never publicly share your keystore. +# See https://flutter.dev/docs/deployment/android#reference-the-keystore-from-the-app +key.properties diff --git a/example/android/app/build.gradle b/example/android/app/build.gradle index 6dea3dfea..6611f2f4d 100644 --- a/example/android/app/build.gradle +++ b/example/android/app/build.gradle @@ -26,7 +26,7 @@ apply plugin: 'kotlin-android' apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle" android { - compileSdkVersion 28 + compileSdkVersion 31 compileOptions { sourceCompatibility JavaVersion.VERSION_1_8 @@ -42,15 +42,11 @@ android { test.java.srcDirs += 'src/test/kotlin' } - lintOptions { - disable 'InvalidPackage' - } - defaultConfig { // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). applicationId "io.agora.agora_rtc_engine_example" minSdkVersion 16 - targetSdkVersion 28 + targetSdkVersion 31 versionCode flutterVersionCode.toInteger() versionName flutterVersionName diff --git a/example/android/app/src/main/AndroidManifest.xml b/example/android/app/src/main/AndroidManifest.xml index 69a600f8d..fcfc998f7 100644 --- a/example/android/app/src/main/AndroidManifest.xml +++ b/example/android/app/src/main/AndroidManifest.xml @@ -8,7 +8,6 @@ additional functionality it is fine to subclass or reimplement FlutterApplication and put your custom class here. --> + android:windowSoftInputMode="adjustResize" + android:exported="true"> - diff --git a/example/android/app/src/test/kotlin/io/agora/agora_rtc_engine_example/RtcEnginePluginTest.kt b/example/android/app/src/test/kotlin/io/agora/agora_rtc_engine_example/RtcEnginePluginTest.kt index d0c6408b2..958ccc9eb 100644 --- a/example/android/app/src/test/kotlin/io/agora/agora_rtc_engine_example/RtcEnginePluginTest.kt +++ b/example/android/app/src/test/kotlin/io/agora/agora_rtc_engine_example/RtcEnginePluginTest.kt @@ -1,86 +1,82 @@ -package io.agora.agora_rtc_engine_example - -import io.agora.agora_rtc_engine.ResultCallback -import io.agora.rtc.RtcEngine -import io.agora.rtc.base.* -import org.junit.Assert -import org.junit.Before -import org.junit.Test - -class FakeRtcEngineFactory(private val engine: RtcEngine) : RtcEngineFactory() { - override fun create( - params: Map, - rtcEngineEventHandler: RtcEngineEventHandler - ): RtcEngine? { - return engine - } -} - -class RtcEnginePluginTest { - private lateinit var rtcChannelManager: RtcEngineManager - private lateinit var rtcEngine: RtcEngine - - @Before - fun setUp() { - rtcEngine = FakeRtcEngine() - rtcChannelManager = RtcEngineManager( - emit = { _: String, _: Map? -> }, - rtcEngineFactory = FakeRtcEngineFactory(rtcEngine) - ) - } - - @Test - fun shouldCallPluginCallback() { - var onRtcEngineCreated = false - var onRtcEngineDestroyed = false - var engine: RtcEngine? = null - val plugin = object : RtcEnginePlugin { - - override fun onRtcEngineCreated(rtcEngine: RtcEngine?) { - onRtcEngineCreated = true - engine = rtcEngine - } - - override fun onRtcEngineDestroyed() { - onRtcEngineDestroyed = true - } - } - - RtcEnginePlugin.register(plugin) - - rtcChannelManager.create(mutableMapOf("appType" to 0), ResultCallback(null)) - Assert.assertTrue(onRtcEngineCreated) - Assert.assertEquals(rtcEngine, engine) - - rtcChannelManager.destroy(ResultCallback(null)) - Assert.assertTrue(onRtcEngineDestroyed) - Assert.assertNull(rtcChannelManager.engine) - - RtcEnginePlugin.unregister(plugin) - } - - @Test - fun shouldNotCallPluginCallbackAfterUnregister() { - var onRtcEngineCreated = false - var onRtcEngineDestroyed = false - val plugin = object : RtcEnginePlugin { - - override fun onRtcEngineCreated(rtcEngine: RtcEngine?) { - onRtcEngineCreated = true - } - - override fun onRtcEngineDestroyed() { - onRtcEngineDestroyed = true - } - } - - RtcEnginePlugin.register(plugin) - RtcEnginePlugin.unregister(plugin) - - rtcChannelManager.create(mutableMapOf("appType" to 0), ResultCallback(null)) - rtcChannelManager.destroy(ResultCallback(null)) - - Assert.assertFalse(onRtcEngineCreated) - Assert.assertFalse(onRtcEngineDestroyed) - } -} +// TODO(littlegnal): Re-enable test after MS-88689 done +//package io.agora.agora_rtc_engine_example +// +//import io.agora.rtc.RtcEngine +//import io.agora.rtc.base.* +//import org.junit.Assert +//import org.junit.Before +//import org.junit.Test +// +//class FakeRtcEngineFactory(private val engine: RtcEngine) : RtcEngineFactory() { +// override fun create(params: Map, rtcEngineEventHandler: RtcEngineEventHandler): RtcEngine? { +// return engine +// } +//} +// +//class RtcEnginePluginTest { +// private lateinit var rtcChannelManager: RtcEngineManager +// private lateinit var rtcEngine: RtcEngine +// +// @Before +// fun setUp() { +// rtcEngine = FakeRtcEngine() +// rtcChannelManager = RtcEngineManager( +// emit = {_: String, _: Map? -> }, +// rtcEngineFactory = FakeRtcEngineFactory(rtcEngine)) +// } +// +// @Test +// fun shouldCallPluginCallback() { +// var onRtcEngineCreated = false +// var onRtcEngineDestroyed = false +// var engine: RtcEngine? = null +// val plugin = object : RtcEnginePlugin { +// +// override fun onRtcEngineCreated(rtcEngine: RtcEngine?) { +// onRtcEngineCreated = true +// engine = rtcEngine +// } +// +// override fun onRtcEngineDestroyed() { +// onRtcEngineDestroyed = true +// } +// } +// +// RtcEnginePlugin.register(plugin) +// +// rtcChannelManager.create(mutableMapOf("appType" to 0), ResultCallback(null)) +// Assert.assertTrue(onRtcEngineCreated) +// Assert.assertEquals(rtcEngine, engine) +// +// rtcChannelManager.destroy(ResultCallback(null)) +// Assert.assertTrue(onRtcEngineDestroyed) +// Assert.assertNull(rtcChannelManager.engine) +// +// RtcEnginePlugin.unregister(plugin) +// } +// +// @Test +// fun shouldNotCallPluginCallbackAfterUnregister() { +// var onRtcEngineCreated = false +// var onRtcEngineDestroyed = false +// val plugin = object : RtcEnginePlugin { +// +// override fun onRtcEngineCreated(rtcEngine: RtcEngine?) { +// onRtcEngineCreated = true +// } +// +// override fun onRtcEngineDestroyed() { +// onRtcEngineDestroyed = true +// } +// } +// +// RtcEnginePlugin.register(plugin) +// RtcEnginePlugin.unregister(plugin) +// +// rtcChannelManager.create(mutableMapOf("appType" to 0), ResultCallback(null)) +// rtcChannelManager.destroy(ResultCallback(null)) +// +// Assert.assertFalse(onRtcEngineCreated) +// Assert.assertFalse(onRtcEngineDestroyed) +// } +//} diff --git a/example/android/build.gradle b/example/android/build.gradle index 8cca02ee4..c04784b5d 100644 --- a/example/android/build.gradle +++ b/example/android/build.gradle @@ -1,12 +1,12 @@ buildscript { - ext.kotlin_version = '1.3.72' + ext.kotlin_version = '1.5.31' repositories { google() jcenter() } dependencies { - classpath 'com.android.tools.build:gradle:3.5.0' + classpath 'com.android.tools.build:gradle:4.1.0' classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" } } diff --git a/example/android/gradle.properties b/example/android/gradle.properties index 38c8d4544..94adc3a3f 100644 --- a/example/android/gradle.properties +++ b/example/android/gradle.properties @@ -1,4 +1,3 @@ org.gradle.jvmargs=-Xmx1536M -android.enableR8=true android.useAndroidX=true android.enableJetifier=true diff --git a/example/android/gradle/wrapper/gradle-wrapper.properties b/example/android/gradle/wrapper/gradle-wrapper.properties index 296b146b7..bc6a58afd 100644 --- a/example/android/gradle/wrapper/gradle-wrapper.properties +++ b/example/android/gradle/wrapper/gradle-wrapper.properties @@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-5.6.2-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-6.7-all.zip diff --git a/example/android/settings.gradle b/example/android/settings.gradle index d3b6a4013..44e62bcf0 100644 --- a/example/android/settings.gradle +++ b/example/android/settings.gradle @@ -1,7 +1,3 @@ -// Copyright 2014 The Flutter Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - include ':app' def localPropertiesFile = new File(rootProject.projectDir, "local.properties") diff --git a/example/assets/audio_mixing/Agora.io-Interactions.mp3 b/example/assets/audio_mixing/Agora.io-Interactions.mp3 new file mode 100644 index 0000000000000000000000000000000000000000..337cdeb17727878ab11973778c129db339ca402c GIT binary patch literal 2437297 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%0D^6qKfV$GWL65*`ab1>PICJ63KFUGv1L*R=_APZ zD^o*o^`d&(2gR3y+CCvUTfml$Ux@W-nM?Oa0VxcweY(o{)#J>Tdw;CA&MI8D>wEv> zs6r~axdpWI=ugS0V&a!)H< z!N5RB5by;BHl$_%&_)jONL4F3gU?eM#jQ{ODJbAIhV=z}%sAPHNq$dmr|G`Iar!W? z!JDw8BPJ;apvjcOQLU6I@4@NEZzMA+h7oi}RK^*d#_8JSDL!z=7*I36e*&uvM?1(u##+U;uV)}j!oIrYDiU8$J zzVJa;IikU!!U_9)OE?8onWp8Q!Wu`wguYdrG_JL(+AG4|XXggekz8!|uU3bM+Qw6Z zbP=~wiM#TI*P8#8DgA)(U;Q}#9vboO%76_}2B5+wLY=8G~WEerMmbk4p4zq%Ey0?sq_O5XZZW zqwnF@6^`zxYd>+{zOE0Ar2}9h0EmO=cwsugZ2Tty@nd+%LGOLyF~-hOE@X*ydAHhj z?Ec;Gm3-gf$DMZ$y6=VF9)9{$pZO`G0GJ1wg!)@2;XM{kjYAt75tJ}&a^lm-SWX;DP-%su@}4L@ zJ4j+(gmd%th1Y2oR-R+kJv!85fx9Shoo>eC%Jm*8l#MQ4(n8wlqo)=U0wi&MRPH+- zWgmcAr&G?i{Asm+3*qx_%Gen1jzy_sb<>Dex=RWO-(Ch|`%jXq?=gthd&aM*K85up zrpo%_t&5%lC$uJ|>z^Jbns;>lj1!bb2&(y=yY>4u?0)*`u>f{+yTu5bm(Zu~?q`L_ zmWza$h+^B+8D2OBtUV4O#Q*gTH0Q-t;=cphIq_lkui_018Bvc5kB{lJzAHzaTiV16 zUd!wE)fd!*7cf^YUSwDyx{6>j&;7VkRU#>~xHh!ZRZ-fXgnC$|Y8)^Rwr)kvf@7td zio>3Ay>)C8k@NmDF)HJDV6Uxfq4JP*K8^Eyf>d!s;mqQ}k@me)J2AO?-N-M-y*Ptk zY^9!$^+9gJC`zlMhG|xwqGhX3WzY(_8JiA3*&L`D-MApM?Lf6QW9?30JRsBmH`NbX_y3! zZ!x_^f-rH2PSH+Xz`&neJ?`3G$)1-b>ikYC%D=T`G~Plu!=#*7=StTSt%MDl>tlvR zOgaXlT}4}rz}wN^Ozx%~Oq zzPqQN9!%x=_24{c@4i$+CtJ5|+erFElJVZER+yiI!n^{a>x&bvJiYgYr@?}ApKqti z|AJ%u^q$H-6@Xten+uU+{9LybPM46Y_mNrE2*Zv=URQV`TQJ=$cYohk=(=bfT_a4rQ$i_#kX;braXNfm0_T%#*p9-&ewz`Rw5_b zu8ZGM$Z|cctM?K)cY0zbqgPE1F#)&z1v}H43Ej$d@x90>_sy;}O1|b<=xLy@Us+() zq`DO}>wKm3HqY;H+j|`k6J_r1OtfZem`)~aw=jnqW}{E+o$cCp3lX?iq1tb%@}3zt zlUnvcem%s_vd#LAu-#l)Tb?rQ#C|%?6c2R}!*_u80T2}O!>M}ENJ`ZI4}&41pv(Em zSmuTTP5-ei-+?+8d%{AhQoj-uTz?63xgJmtqV!3RVNingUQ!`Dsd$f&*>BFfTaJ-f z*9@&QnL4L@B~x`@`84C()-F!>z;*w&wkc&y8=gawM$AxEY1=_D{bzlKV-y z>AkBq)!0am&P~?yj6XM+r}o%87utHt0-PsWPL|9DHy{mb1e2XgH4&IC;2keTS5+>0 zz8TbT$oQ)>!U$(lm;QLwo;HOw+)e=gnD^T)N%w8N%=n)j?neNQV-{@GuQ+1Kr*8-? zgRnnSnVGP$d?V3M3sbAQ*CDDRz4lDcJ^?DQA%P)5oo(!x8}LQG3@zjG=)&T&0VrN5 zo#&m~(1#2OnY-d6giIbZ|2wniUnv99=JqKnr@!psY98<8x$Y>XxMa^o*=ZjkztiTr zd|VbJqSoH+(In5^mc-3xAi?CnX)tqG^82GxBk8ch!+g_u4~L#d%zHOu%V0?`TVGAA z+PcKvae^nQ>g=DdLr+>5e_6uT$Bj#F0*7$80py+)=7|SdIAxm3ju_#?rLcmP#yF{7 zLw22oM%0V*-_9h6sNHy_>(3(P`yufuskQVr{bJMm(`TI;tE8SjAotzP^Q_&pGP)}H zbUEyqrltB*uBU~sw$om=JI)4LM8XBW8oY$4dIXzV8NcA=1bi}sq>BUoEBCbbNqaUf zLTXA4t}o+be>Te(WQQ3sxi^%MEVb=Y;CrvrO3UlL{ZMi9OA9WC?N+pQ7SiaAtl}-C zQR!Na;rtV7?>ERy1kYxzxv%5SW@kU+R4tMjHRBa;zIfYI@Z5#n$vyeW0Pe46{x)e9 zS`&_EFi$dM-0iv6XKV*3%@-_3DtPAl0mSAqaAcY>kj*QWV7YYg;Oxo6KE1*%s}7~( zGH3O#UebR1;lkd)#s%5llBxx!x((z=k*%n^BJgH>VWY&OC`B^;pCbrwz6a5Lh^YE?)W}! zOfosJGsYIt_vVzso3J+->Y3M&7X{XXGFHk=-^R@<79*{djTBq8Fqp@1-#eGBcS8;_ z{811<_Nre_$I127%*e1cuyHTTOulDW+c7LrE>NGGj29OKZ#FBxkNfSjZ4=xpnqDn# zmDzBP@pDu!a{2+1UA=Dhb>bxxSVZ!*-nX$GUo#`8cAo{;_quAzHZz<=`&0q;^JG-W zdW>%6{7K~}=THy~cH$N@CS(ySmZU?*lfX$sRUAn$IjAG&+boI_RCfw#SRw+f`NSiS z>8Wp-Zp_l`VTnHJVOU!csQ{U?5w!$M>sI?kXmH|POuj_40L zV>BlJTM?T=zC%IqM5k>p#nsC>CmL>=IN~c(bbmE%XVu#u-`LkR@i(1s$}4k$^OHhL zphCD9*;&&hP2=mFM321HFPthK&hk*X0uk9O1N}D`uG$*QL>KbwwsX~6q)y(A#VPNL zjLphb8GSYBb4&5-u*MPqjF5ijLi~bXgW$km2ouk$zd?cDB3lKS_%(0Hq2vR$zBzcL z>a;zOUtLm?QtK@_qE+5g&$&B_SGda^>@R1mEyPiqJRuExFl7bh|2W;Eo!U22qM8;J zcE+{}-8kHojf$w7%k5suS&**IwCQ)TT#XV^c^u+*PRv3)nxoL?BVNC&@Cpz6si(4# z-_jP5QoNd+;=~m1iQC>OauzAh0r^U=t*SdXa`HNFrg!?0i{_PY)9u#okQa8+&1b)JW1f==ZKjEG@^$`U^$oCtLBxjh?*&@x^H*nfnzDlY!U{)o zy}cW=woQKv3@}OPz8&)+`srL}*yO`R3eDAHEbQ18#qhPzNPi!)=t4e`>#Z*+t09r| z^`lIy0lsZZI9(ySb5z3eO=e)#RT=855Ufq-^7_!12^;a}?I&r%t{FwzW>@!C7DgdW z+}#|%hC&~FdCT&jSaUm5BtSf9O}_Bawbk-Jet$>2r&8W5ye`IIZ+*Y@IUthp2p7uV zs@a4nxOvf10rBd%IQNAS+7SBw{9Q6jSph{Re}8EE2D*S(Y^-Y|H>&ng;j6lU+xR+B z3q$QejRjfM`mZ1v(8Y+$MW-6al^5GSg<`&Q-Fa}zc3^bN_6mJuQZqQSWhV4sup~F0 zEyGW9OOD%H%fXZ-v&Z)283QYgfV%-%(dKmf<7tl}5Y~Td2c~%z;4u?)nfxoNQRbXS zYPt}ArU6sW)FXpO=0TZ+ZP!}W8~@bV1aUu(9M1SVdSwcv;KZj^(VZV|MZ3IyQ(8Jb zW?r|X2Cl{#gma#n^Nq7;kmwjA@r`&tfB)Q2Z@;%wCe^MK&U`~QD?)uE_OaoCLliW1V#A6>PoBm{T7sAe6 z#@Q`EQyToOC3o^nGB%z$W+<}Fu`5C1*g9U5q^(N1yS{M&6`?BmYI>8wR<~HBVS2|P zPfZQ-`KGz*OXVEK*TyZAq@9+|eZTv*T&wwPF-J~`r13(D6Mwtr;ZA%+Ah#P!<6B)? zuGvjqHBfK2UbtaI?BTGq%QVrYrr}9tzm$d2l_e6V-XN=v2>eY)4(yX*68C0v-DQPv z_Q8F1_ktP@mp6TCZ=IEvRx9Uym-wqIcQ2m!5Ek2+sDF)5e>>Dv+JyWL*N&3h;9=41 z4$^w&5XPtMshRqdRXwey+*o{bU}gT{y(Cw@}bE$YL5Y9z(CrO4%p}z9Rk8=7#-3vx|A+a zM%PHG(MTg8C8#LU-6aAlEvbYkBFekp`{8}>zu@_Bp6fpMIamDb6#}Ue$yaVpitp?^M%P&&|S6e8!w{CS+j(nv(g9=punrJI5_2cUA&{edC;eOM7 z$T2SRi_d*7KF=9x#D`Q)hmR7g{;U~r(-#m&+vz&ZMwm8+(uw+?I#(!kP`R)(M+q*&Jn577P!n^b+o3xssA~Ci$ZsX)7rytjEiv13p zo9I)Qs8IP3wI96pirvKsZ73wH5DcJMqcHu(bZ!bg}*sBO-*-A^k%Q_g09X53oHb>h$d*74G+%fKN#wr{BNNnYdy$Ei(* zHnB^*IqGgLozyJrj|um622|2Bt>g;kfKM>GZ7|$|#^n_kzk+G@Kw||j_jBL{oYFN4 z+n1e!@O6>dV1yt1#`l#jC5RurpMTl*TsVIHszvvR))A)7XoZFsR;H*vbo>C^b?)!m z;|pH)&+sD=rU-CYv_*o@}$&Wz=H#qMG{XPgsh3kF!-Q46qKM zb&NHi+SH8=EV9@YGdN?g+a_TyAyJEN@%`g=R0_G3J$RRx6Fp88_0~gXf2#Jwd{$i{Vl~?r zowzD8+Mf4x4E;kPEO}eko$0m02SKaHzwc|QX&|_wR)-RGcp16G>?zdlNko3oV!!zp zo@4Hva=9Br{V(!&BVjZ3?^NUO^_h^25HHQ(C%eO&f0iPPH#hJp&L9P@U_=9FonX)l zd4TiJqyIY7BLL_w#yCJIQcIOQG8ZpX$yiH6Sq;u*~M=aQ@u3p{SjwFqwar$e3d6aeUyzVJg#kL}NY zM`qvbu<_npD&3(E&UZ7FjPgHBVB9(KoPUC{aD}yz>p$5g*i|Ts2qCbo2`H7Xn~UE z1YrDr1lRr`PIk%gwsIe^j?{q<;N_aP^|3lij%9lVqb~Eyw(U}A=b!UlmsjP=+(d>g za>2jOZ*G35q>nU|wBEMGaFtz?iGGBRy{+CY zq&M`YPe=GANSX8oYwFZU7sA;-#5;(<7m}4GgKQ} z8AECuzd4y7))CU$GvMk{-+hU9wX`-9e!TT@)v>p*4|jT2mxOAs2w$1JOE0+8QA_c$ z>+BK##(&r9B$o6$!DbX~bE30pmCh=}3jG~&@1hgS#faxuBBW=Llyd4Hqa$zr+}!9j zus6FzN+ws;Qn)O*EUn*{Ti_XH+R>=FZ;Na)=oG89u_)_RwdH)+UIvdCkwbLc9Di0_ zROja9k-JAwn@v@RP1@g7|KwJUH1g7IW_wWvj0?{j0y|St7n#^+=JG z@!?t!NWz)XOrOxvE`38Xag^3{d^GuPcCwq8=8uV(rqu>2%;Iy7AJ8`5XHs}q`FoI3 zYE5A7-US(9QkcXYVgCvkbd?3T_eCAsV+yyR6?CoHawhP5W1abWFwG5^%s!`ez-{1! zErasFXdZl|XUgHE9wY03>49LhvOpZ@J7g08>O8-6;IsHXqCz-1%TlZ}uoptp=IzL4 zd>lX&-QWzT0_e{s6K*m+WU=GYA9;Uqjwdf~_pT(&OJJqXu zkU}gp@;~4KwG0WUSQ80?5`>S1jxNjWbw^XhW#bWt%#(FT+9<>)kvTMU*4xAL?Hm)^ z+oz-|4nJWx5@ABND?VQN&FaTKg;6ndJ5WP{I(`R`H-j~P?JA<%MkKOyEA_XH(s5fd zCGFP+Srf%n;h(KER59|6*At3IotyL|4h9_aZ=d4}>vY!+r@wrT-2Z?O{iCIg zAPO$m)=$&I)r**U3yc@0$mMD@Ow7F!uX(`U3ZTduiUx3jNwi`YxjI7p-g-OroTt5{ z!p(?9n_7yqJr>tqn+9$f6iw`DkT9nTpv94r{SNbV)v77q-NVDO+e@p2qh%Xm}!52qv6cLGZeQ$0RCOSU0Vva6U;>--uD?w_V^k9_RZP1S*T}q4**%0Ih>s{0 z6+>9FtNjB|@VZQW3sECdLch5+<(|RBpQ8OY7r=EX#`mlBgj7!juVgS!XOP40a?JT7 zo^whKUqv(LY-+TS#6ta!eouf0Xf5~>D^JDPk=iRFTwC>usL2dNv!jimrI*wSnhTS& zw33Bco7g-MXl;qNyLxr}+ywXXgDXqllZHthyAAEXyN`doa4p;LfW_%pt-cyFF9Tm! z3%~R+3$5>$;%_jEw*FZAw-{U0C6@sPWMyy4YWPt)*aLCsezY%+thbH?SYKHta4}cz z`37v#e}V-K_;>Xy5M!8qwYkevsOIWm1sxMEj|z(O3>Z{8MN2Vxul6yR99^Tr_EQ8k zeV>3d-pAQI`P+-MA?R?4CQ2o0;IG#=6Mot&+0~}2+2gi0nL9q=p~3fGeKqNrM;E=A z3n{N@5B)59pXt-%?>=qU-66Y|O;Xtv-tT|dA8~SsI)xku{jy)L-y*Ev0I&Nl(tcvR z`$3svloD8E9O`5f$P8u1AW_b=r;g@PPLdOJt|#xlPdW0Dta$3Yf8(Z2X(eW zEgOf6T*8mL1)4zFx}D2yy5h%8lCI{jKR{CTJ3~9dZ$c9{;=$Q932Pjl1qJRw4Hns< z|Fopux*d6S$ov?T{09l%x1<@)4&6w9@#tQpcYlfNho>&r8H?c`l7MiE;WL$~)#~@D ziRs5wjU|eAK9gwOb(r}4;r^#f&kMkBdKkg*Xv&?B()-ywGd&vqiJ}O@;2^|?WmsUg zaKmMi*IHHEGCJ?0c95a8sl3s)iYGSrkoEf9IuBiKnch=(WORNimiCI-qPg>CfA{sr@L~M`-+k5NH$$ zF?tX98^EJ_kxyFbOnAHJ$(3bzIn)!1>>Nvq7kCP!@t}+rS5eM4!tSq(AEeiR_?ZDsaeZH^b_|=#r)bx#sR=xULVDTND({F1N6KUeQ zE4a_T^7)0s(&<%;tObnI_bDz9pK2c_^A)tWcXkL1l-)Uc!L$RbZ8J`#u~?X*8k0)= zielM)ZKWktm6E01>2|vET3~ihYL1m^(6mHBzYRet%~6<2v{cSms$`59V3W~q@42K#`v;041i#Frm&(JK<9gw zN%#%?e}kB7EZG!hhA^DH{DZS%ce`cJNLaHUwTMN}hzUHd=8?o6hIrDyd}78=p+t;fd|UyFO_0djVihqkcaeJt;r>CFVIGlh7X>8E`k;;9tK5KZ!s&5t z7FXRTL&ED^z)56co=LVB_llS)!$O%xRz+<>T#a(d5aFP!_Uya0d%YkNS%i~UI!Ws* zz7bfUQN+_*vjiQoKrRd|$Gf*5Mk_(9A^DkLcz@)l=Hd>)c!i zm)QA78OYVHH%zn6R65JAq|fWR0!zdrxall;G>k}$#M@b>J$}RAu2`GFh7u?`8uD}! z;j=7W#rvUp-S>@sbeamqKku0=xC-4cKym<=x-&jK!2K3bTiG_l5VuhY+#?%j{U9CjFO4=@%?E`;QB#&)syE! z)fx3(Y=O-OvUvj!C)9k%2Wia;;0}zmYr88lj}?t2kMp^>WH#={lGSjT0L_fJ^VY7y zkO%uCSH`HM1DJE}k{2C4)_Mokp*I{1$us{e!LkBMg*>z8cR){^cq|R z98uZ~m?@x1hz9W6x35EGYP%Xo<&BvGk^0hK4^&Q}x_6m!Q?%*YEqvWQRQUAwBTjZ` zoretc3z7|I$z7R@w;oERnW-6EtlihQ3_6kwugcZe1sj-oTXc+l_(W>7Fq2EmmE>LG zIJiC+!eu}cHCg|+|Gt#rR5<)XH!BYoxTi0UcCWtFxYyIjozBoznYkxIE=q^+W>r9= zz~sUV*PwhNqyGL!fP1E?>*89Oq>vPV)0^QRlBeI+A)oP(Vm({Dj!){cxi>Ih2vA-tbe zjeeQQBy@~w>sSQRVg8Shq-VVlOQcJDx|v6m!I7fKv&Lrrzu5&ppca3G4qf&H3hrom zJXy0$+TO5rm07iVGq)V7W*6M>NxcvuX2$SQult?-i*6%-prt6&1Iv(3zQ;kJY2-v5Ylp~4YRsE8bGpO%Mah~33?)cWpxP2yivb8gu z?yx@|oj5Ycm6X{*&{G92FLxr$D!}Fn7L|D(eEGMUt+en8Z?lWof_R0-R;&caI9PpU zpNpDE(Mi)g-ZyUV?ueu08Z<);=I5?`)=2U(UN%48u5{Sm#=1V;zU=?F*LX|>=F$>7 zOKR#Ab>TaxDQBrq3=soRAnszLQcV3=WS92_DC8EE=&xH0St+q3v6B;v{68-NL6nTqgS`~|+C1u6U?%~!ZsPMBv7(obz#q8rgU6rEY3EV z9`J7iKn$%LDrsIX<4+1mMHQtj}v`RHs$8C%BlmzH4R2MVjTIjum6} z1eS(Kz>mSfG|TkME4BSlTALhLG^(713tkbinBgK-aP~8`t0k9+F-Ov+$NwsbW<~*q z&yTI;zRU}yj0Y+@QL9TTDk>L!66jcbZVKhVDJBZN~8i<<{iO&e)X#v&zFSa6gKNG_;@n#vAr?8x1|JUnvN3QBx>&d0ex}xNrV^R?;jlhZm2A zuj;-d6Xb86cjx!aHx~l}0IvtA81GAJQmG9J<>IPelVyIS-Ctv8$k8Kx{S`emXv8WzH;Fc`$JFb{u!j$C@&gSr+PfG2uw;SiFh>T>+9rZR z&M&h{2r1dkYCiy^0=9FHAiB$SF={$wxy_YAbIG-ORyd8q>T>WnJ0EVW z80~2>q^offDdXPIiC>I=reBVoyfiMjQ;(~R@MV2(FMl~3a@k0GN$|p}aCy!qboVx2 zPchw*WRTM3)=%M?)Rx<7@w&xC*WJom(kG{$oeo)*;eei~L`c+>mrcq<1I6P&j61W&=B9;0 z+%?F;JhayG;&b`tYCn3*|I>J@2dw4cL;B`tIPz)<$llXdcl=OJngxU2rriw=%3RL3=NIVIX!SEtp6-P5r~p}a zii`h*z5y_G4kjrpvlEdg$55ODrqdx ze@pX>FXKNj9S4v)+RXlu)ef)m3O8_xFEy)rr1~G2J{NU=R}8;~b+}*}g>>lB)M6Xc zlORG5Fxt|L+_YF2A}0p}t0z@>tErtS6cLNBE7#*eXm3%}@Q==m<6Tm?HQ7yLbJj^& z(LZC=Dn$@eh4fk4BA>D@mNe@|vpa88XL4>1(Dx!j-i55#ol5V_`AMpG)%{n@pS>lm zo3&JO3N=|V%)ww9abq;izz0O|Yad^|_-Q~A2iquC~5hu@#q@qI7ikqq2SEKX6(*Oa*rMYd=n{|N7lWZc?7OR#y{}d>2a*cwe(LS=Ka_GpXewl4BJ#R6z6`~qBBu9!-@LtE+llw zMx{oD<_bcOJE7c0nksUp;LPd{%QqzvvX_1;^V3fkRbN{(hfd#W%HebSF*7Ll<>#o! zb1m4jmFpcu;{7~{%^xSfm{H%^ZqbU2VPHU&kX-aMK>h%dXae;ZmdzM4Rk|xFTZwd} z0H=JzTU4%U(s zf+;g<*~YBr*#v4-ml|vc_dEQ~k;(W4o!F2)U3!{JmoQQ8nJ-~-Sx&rFo-X0JQrShZ z@bJ{Qo4aq)sB-3A#BT~0!pCxg<<56xXkLi85%ksmwYJ9U%pB}ARB#pJGvJVKOZF2d z6AqVnQ!Oum2KfPw8N_K5m$=f5nU}V_)>?r`IW+e~$fFWr+rtX$PF5Ko-rM zqv^^aDJ*lY>zsK)53-9<&ixaHs?_jT)Au zgMfRE<(jH@{hM$Pj5bAc1~-@%HQO}|V{sT@Gr-GG{MF)IqQUEZMy($`vana>kZZmwpnVY&zn8ZiRI1Ci&nCWPL988lhT=;s5Rj~Gn}5eY`!w0RDcT)A`9`mSk%EdkQa-N6MBWmF;_n+l3!iYk zBq=u}CyhSg`a((1!OFqxVa^dw_qyu+YF)iYprqGXn)?s+n}3=6Z}MV@42R)w$MchW zdp6^BV9MQwTprcD9BQsSB9~>mRSwyUMFrV+p6DVhd!1^Z94a4c_e1-?_q;%6@3P-@on>(@7<%C_xZ?KXgoWg zN7iru;fa~LIkzg2#P9W;hRi{&4$9zmUypUBdja+_RYlAFWx#C&*(O*{CZ0?#CwKdT}rWOl9RF9vgt{>H_% zT$`{{_(TPny1yt@)ns{q7U)>~T6Z3C=!;@wM>okm57cSNtSdG&uCzF_~$sdWcsyVejY#h7YhOa^ug2>V1=hRf}NRe%^CU|g4!1I0PLmy2k6Vi~m<*SR>0Ivl>9KsQYczFhZ?w})W5U*-LM zfA;46zoI(C+N4g@Yv&GqFIP^QikBjH&18eQ8~SM^h)GpgJRMx3qvD-}q~v-zCFv{B z7RH&zpv0{wo^@YoXScft_I(qiko9X8toL<()#r|8#0S)c+JT-^(lJ0KoN_g3+{4># ztY~qe?g*lO|BWK`s_`m*Nl+3EwwgmM*-}z~nhcj~nlB8_mJCm$+iL9cz`OVj23>TI z6VGIv{6MyhdQcz{Pl=_42=r=FSf){DBb;ULw>_qrO-%~(Vs-`o}52F zo^_cm&wPAhNF921w|K?nn{!ic*YrXJgY8gkZNLe}AuL zsxL@XmSM}48R5A*f_zUzBT3#uG-G5=%zPeEE{+-|9x*g>CD#jsF>%vBT%KgyTLtJQ z$mNZ(DT`3#jCax(>rx)5V(wlkiMXb9`ZwdK^ImJ0JDoxZ*Ofo4Qb$~Z8L7!a9KblH zud6s2#qBr>AS4Xhx>|@7JXJGPUf1QVs5ExMybUbHS| zuBN(#ky<%NhuP~1k^CYdIn?s5<#-a1wsuA`J+Hw;PSlS$X z6|tW5+-^kJlsha#ir8%4w@oN3vw!9x4l^K1FcsGjx1vscD-77UH9w(VGE#8MVUB}p z0!U*GTT0JSYGxDAx!y^EPhTHNZ|dvEPub+<|3{&X%M2~-w!t=F79 z3S?xdzor{_Y0bK~ z!%TPe@n;IIa{gcVXIB?tmaG>Znu?L9F{vlt=M{c;pGv&NL>RA}?@_(Lc#<#r==ev} zZB8zS{_mC@%S2~q@<$dka&N0X-Er5+;vz-&*kz;aCuRNP1iUazo?U}X?vaaGg_hyd zT+CRJn+2W110kMloGP8?xlpAB@m8^#6K%rNLW*(IeNQ+(DMSodV3d=}6@a|{$Y^vz z;@E>}V-qaI<<~_qNO7qXRSg*8!7UE6J{=_WKAtT#D$}AdFU(~m-DQsF7X_bf2ep)@ z?1gm~V}s31w7%Yb>hwYSrzb|ckl@F8*lyzK+|^Z|{ZBPNBj%l~2#Cdci_BjUqRvSv z%Kfu#X8pTgbQ2$x|wjv8$`Vky-4Wbi35#pnoHUSvqzf^>asKoEB4Tkaw)ZL^UmFQ z;LG*6#`2ktO^-?xAW6fe;T>15=gNeV^DTOku$vcx;_nWuN?8^x)P6!dmj=gn5EXZB z&Jz(eg^7mJg+5i$FCldjOv^fWO-X5~Vj>OUk1GMj1+*JIMpm{rgL|wTl1a5HR>0eh#^P+NA|`j?r5TorauRGGxbNMMZT7CKkQ_Wa z=aL10N7IeiCdO|uGfOA;5Avp)b;RxX?}tK~@Pb`;E%EqbVNM+cGZIXSVIB=Ve&p%; zZozkQ^FQoa#e%{xbAK$uLN&Lp>>ZPWpcg3y$1ZW}8|fZ@Gw|DYpT3iw?QNi@8C9~} z-z3xVz?b^1CjztOUE1lR3(lTD5TvGJ)q;nLJXe#WW%wdQBpB~d-5Oc~nG0_BWPh`F zwO!%ZkPLfq&Mu>t0S4N+z^s`Az z_&S-rn2X-XtRtuy_<@!Y>DUuRd2L+rr;5^DHm-wweT^$Q?WxKa5ut<;r=wWGyrr7*e)?Kq)kR56)EB2xS$v(w8`@ z6wrcv!@MVEVjQi`ITfoS_E~6}hf@+*VVd`|I<#yd0e+Augn!)`T~ zL1$p3`(~*p8*y{Q=)c*mu3i1m8DXZlEd~ z%mKqUuB?{`7E?EIMb4MON7Zw@vW$nV=^(de=6Pt#0lDSVg^ULb@ceq}%B`<2jC5o& z^lrz!#vbbwrDt3`y5!5=KZqO*NT)-j)#Vo^ZQq6i;cD}jrarUL?Pe)N`_@gKi=(c)5!1VW8I^68 zH+2-#oX@TgMyZAI;nr zFBt`-m#iE|+?#RVJqH6U&(`|U#>P##6=c|j&sGkE!c=)m(7%-6M+aZIFo%&e{W!~sR`H<{<=MAHTEjn@PfSc!)&0)xuSs%wSrZ=|KQDu_ z!DSsy{D(bXu%J5_vqz%nOLeEKFU}ru(4+(c*DI+`D9z(>5nOVlM3aemO+zp@J6$>S zZ;(ff4u(cNTMIxEHiInwwAGd3$;G#L5i>KUW-4?>&%j>L!!u0J%!i8i_TC`bkK1k$ z%hW33=Yo<)mMNgMD|?27OqsGC-CX#ngTn|r5}rb%!JefAK%p`0xrW6Epq9s|%E5J( zQh-zrxd9>ahc$);bgQB4aElV2B|;dOqRRdxg-wB>+Q~yP)$oZ(5vb95iB2HAWaLF) zW0&Q1KZ^}ICq7=m$F{U~?5(_QA8z@lAU{*0sQ`Y{;6frM>)jbAZ07e-gs2FckPb_2 zySLJB_SWg*1f@s9)-gkrvitj7m-FRnb17-e1fh1>0ecl8bWp(ex>4bvl%)07?|L6Y zCMjByoj8}ur=Gz0f)ED)*F7vRKg}Bb4Ki(HB+>xITq4&mL+_|R7YYrvwbdD;b#DD@UKl2>Q0O&$Fc*(70%Zuj zTx-|87-GfaH{03@1L$(3XEmqBwq}3wY#t6T?BnsPlCK@EU1b~W_CGOkiPp0LHfb)6 zil+teE+=naWc_?Y8-P1;U{qb6Gw??{$07@<*_;{0wC=NH*Xbq!+Zc`Gt%9T0Js0Ue zR$BdsJy!rGC}#eVfla6y@ru2JM*>taiBNF~Wuk{MtVnv`h=A+2+^qqf0LY(%(x}yXFhN`Sh9jk-v?>R{hSn*o#vrTlLx%H&fZu zEzVw43d6IO*~{f%bGA}Gj^9rXT&i47vkemZUkTd9J!iDP82FU1e&5#6R^+y~?aj?z zI*+cOpUg{3J<}V`Q`-|1Q|*AC7^fea)d zZXDtZ*_%SmRtEM|Z5o29k$5>e21S~vXPunuOYDvrwom#ktzwpZY6CeQ42x)mj|Aij zXTgki5VZ&STfU9@2k#F-dBbtaBqk!(6NhbCFhIsvIG{;lPoEjkydG1nC+C4{apVCQ z0>{{PeCurBu@;g)E&Xc?D$E<6dsT^DD=FAzZ4ngaz07i^(R#FVicd}f2HdRjL0{2% z_BvLg((y?Pp%G@{TQNIFn!JGvPb~CPq~@{MMV)o7$GcpLq7}t#+FQawNZ3!iG60k# zA(+RTzqZlcZ>`A}fb>ACN6sPpZ6z)d*jJH)JLkRnIwRoVL2GBcJBp&Qf* z14HwT^X(Yo z#2ybl71tKEXs)UxgS-&#|G_gArsenm;_StiRi`Ok+#DX z{H1YtN=*GH55L*ywx7}c=eR+G(qyva+HcuQ=TZW2av}L7Eg>_%ltCWqX(%j{M4VgQ zEjEAtIZ71qxLW~FIEAZT=e*{!?3D4SL*6^PzL%G=0c{dyFFtdA`k8d-QdPrmB_(Sm)UtIG?0S}!{w|rDKaAe80Nlqkt$&}mTcWcikq8*#+%T#u`o{hta`<$YBrG%v%R4OpF*-~{;rGB8_kQG z49mAr3VJ^9iQ9dQ%K6hVmg!kS%rEqy25lz2UyVUBb$)r&JFdUg#xa)?MbG-Ps2U99 z7DC}4sd)p8bxs7ZqaNDK(P-4D-&?ui#1_g&))T6xwNB~Ae3(9# zQ?hFFs@80zN|5qr{zo@_c6Vty7mumew?z^x#m^Z)q-BhVn_F|ua}W!03=>`<{Av_| zjAB9pqDyz40A=#US{6*m`uLwA%l&!{UsWlT+A$tm{_buZe;$-u_muKNmRb-&aC>|I z=sP@CK`NeJ2Qmf*d4O2jHK=7JIeQZBn2@-LsA25CuT_PJdI(T2I~r<#Jv-nz&~;w%IYv&`5PA@l&&e} z*R>RzoBAUmUaiJA_n>D55obyhvRy{(pCRAO0PP0zgHoY5OA`%N88;JJ2K0CKp8Lp> z#>i{i!(L;e+5KaToK8n)(rPkzckHuVH^oeQTiWch;4G@T6JH_nSBKlP`~Z z`{LX3$u-<*p6&`f%!ylJ&Wu+c&0+zIVCf02*SHMf3wpIzLSS~&?Ku6o%1<4)Tdva; zFm<<6<`>p4Xq-N~#Vgd4Qj}}8Kg^R|kQT5=?0DwG)T1M=CL8Y7-^oMH^hm|xI4$2Oj7hq3{LyMzodAdK@Hlfncy`%J^_S?Go?3DC!Bn{_kgU$rZj-(IVfk1}R6 zE#0nQA0DUHJX{9>E8g; zW2lLB@rEkY11N0FVux(mo^#ANxR0Ky{ZX}x&qv!1vNZFnyT&}PZtQZ^Sk9lCDdW|i z@Lo-j_Puk!PN45(H%0i{?OVa)g@v^`(@kETuJS=u)j}8@?Vj)?K8L^Mvd}YjH{^Ao zBN($8p6L;5B{Qqstt*cnW)*n`egO~PUHHTFjBdA5n>kJ73R$2#v|#J+@4=aTP>W20 z{8w?`u%KHGvwsY9SKM}W?s-8Jp^Zr@$6~T|<;;AKb9rn`WKG*73HixCoPGE1f}2il zhp`BkE|%g>`yK{~g`ewClFuX(XJX2l9DTQ6^WV2Zyz;7Edwo?Fpa1uj)IZ0pdS3I} zJw_gjssRBO2HA-Z60|2+#G}q86@vU-_Fum%=bD_1qZjdryQNz88K}XhyjtLJo~P1r zAgP-}oV1b<64}{tII%DB#G%JT2>(*)-Nc(*2XScTXdKvKD3wIHHF{(Szjti`GJI2% z6pagJbZ+1D5f8qI_*^u9Z)RAZaya#BZpWn7EjzFxkSWk*!ANMmT$R=2wSUQ%KjKQx z7sub0nR&)9J%3zr1R}#)BBrUIsu%EZXmhQymq?2%7%JzUay<~-&pB&F+IEMnogRi; zZejc~i%TRyBQ(sGyh++HwIrL-WZADGfoZ)&-OLZ==YK`~w0{0^^~+o5`{f5OAD1X3 zNe>7reJi%V*F z9MytTdu6JMj9?Y>c12cFNjQuku|GhP60p(N(7tHmviW$%=Chq8KP_e&kgy;?x(~v< zyVjp(ZB!s4IDQEJ{zL<8fg;|^l@Y1N&}(lw*HK%-_stHC zGG(1m+2wUj+v4|)HElw5q#D$*ei@*?!nW>z&fPh0HOM1`fT#L-%wHY|Wf~*Jf7M(3 z2znW(OJBF(X~@DSJ>B;xw@>I3v&6pn=V~ zRvD`lNaN^3fW7UB0w}*h!^9HeGHV`Sop@v0}< zkb)uQK;RigfI=DAIBl;f6*Atj^a@Mhf(;D~Dcwn+2V?n+CBa}CIsTQoNw}U^xo^KR zshrrTyQ~HiFFuS2(O-imb438=4>gK|0{8XFMK;7? zG{7FjRb@&(n*#tK8!E{si_3RMMIfvgs!j|g_NXEF3Zf-ra^0F+6`o{06PbCU!)k^k z9*)_JpAtSnF~aw5el-24_FTHd-!;}I0N_oD4RCb|;!hu)U+;mDtc7jhU{UVV>OK=8 zMC)^EA0b9q+!V|RZQ6G|Wnn%cn}{9E2*G8l+4O_CAnLJ+1A#(l&c5y5OVtSp<+bGj zG&rJ{2FEZn$cSE08)JYJDG!)Hl7!%f?*NM?%G?t4#FBR;`nII3B%)0aJc6WjZpMP` zGqEbf@g;QJlw#}6?pQeo)4CBF!0kj*4aa`KMw=j%QUI!qoplgE*ZK+op*#*M@cPjt9lQyzYvPF;ZeDz`Ei(e zT-&uR?TEUnq3Qf~hC*_t^t|oV%UgQNNIGCP$t(Vm(Ry*b2Gysfw7cno4z45J?>UFs z;$x#2%K3ZMFv!4e^LIha-Mi2d5WZQO^(9Hcl^+}x53m=G%}o?n-EC}G-BMjk;zgPALxffx4~XezY$|JAuW-~cJh>x zh&q>46PuxDRS@$#XQV)8I4S88{KZhzfc&^20DNdj9G<0?0fr%oByOXTvz!hRH2er6 zVk#)sREq@+RqIWr)l4QMM?oNLp+hkwK!DR0B}8b&Sdz4)6dn!Y0+o%F#0^2H9UNV? z7)rH(#GsDXPg=hA`V-ne2h#`usKeDnO`Sga@mOP{cp_{DNjzZ(2<&Zs-cKAmk^K-t z4`A!bP(n)r`38CdCcud&y=ZluP>(~88tnuFz@d+Xae_qUsK1O7LZu9|Xoj&ZQbHmu z*wip;)eInv${BZrs<^4C4;f1;Gt*@+V20!z?$Mi90GKVH&o9qk&ww-ZD4QoAJ2)$k zz8U~%t(OH5(=kwqt(&)R4Xo|5RU9MIgt(=(#LCv)EmM;7++`X1hCexCvj>Duuu^xJ zW&<3cP+6m7K@V(9G%*ATeGhX^;3J!PI?=``d z@3L!_lR_|N-seKCV~bK$mS$221drLb8Dm)*;%SitSlEMKxnBsxC7EGpiKl`#J7jRvcU(2{?wdMD9WcUxBzQ6HB*3Qa zlC_=0e|{kUf7T=jyP^L(f7+y2Qhfp7g)}Xjs98o`4mg2YM0{V8j$Rh*&E7MioFAcHVsq=zJ|qJDTfLMlz-+`9LMG(2|If zo9_ZcX6@IXkMm5m&HyYk>)5rnLHK@yNnjK}E;cr>FQ%;ssP8Au6f2K{ z(HQZqLt8K-4}oRX`8G~Ox=08dMn*@HT&74hssaHd4gw%BXdi%uC?+mXA(2Fgf{_Yo zh=|pqgZa{+T#W<_#ZVBU&EF_pb$WQU?X*^X2p5`mrpa+x%|xGkn0bIhOET;cs`Q-i>nC z?&${ZjC^fa?F4AB4nMf%20s1twWRQE$%RM!Q-Z}V`*0LDRni~(<5J_4)_)4g#qaZ- zGbwCH2tuYP?6>PdX-{hiua#1NAI94-t|NRjv*`lWHpZv^5h=QY?U zmJim7cEIju5>-)E5M#3<+*t;6kBG=D4BhjMHit-jTTZsIy&4P{8h(>GsFApJ-yi;0 z%|^bHIhTm8GQ2AIt?cdXX+Dq4VR;z=1wWKXAFojm3D0DAkrHPy1FovUVlHIe%q4v ztxnZ#nzuS$vHoZ^jyE4G32rd=|0nma^XBHwvQ0%_R(#2Q)Db$O`&ak{G+NGC>zcjkHRppr^l{36;r1Ze(VeF z@99rN3gG(e37m4ar+@w!Ed`l;9qN&l&QMw3h;Vw8rTS0n>Ua6JUHbOE{mYNDJK+OG z`C?pvs3%QA?sj(=oHEjg{YO|^cuC*#XnCYjJ_qCjI;izPA6On1F(9d3!pg{5m{%UA zB8s0ZNrk16f%|tQ91JNfGroDtodnt1f%YrmK`rCIHzn2ph8@Oc0yG;2w)T?9)idh zKG67LeB#6XMbFdv&4?g_y5Aw7c_1JWxL`gk4^n2@9_ia!OZ2>QY! zS{@@DzG>E<7#b2>(g1>jAT8{xEoV!M0eV8Gay|e1kYwzD742bI`%8bi000m00003P zDT7_@J(b{W0A_R$00bC^Q;eQDEKea8zHyeq!jnjgY6j1j?f&31_y|JmxFLp{l1XK4 zR@%jXW#AgPA9ibKp!D0003fCi2KJ0-?e< zY!0*#0Cr-)qhl+{J=5f+1pm}Whsr3&_1pfrJ~sx4C&R5wUSAM%c>3SQvbbl~i{+H{ zG?sS&%@E3D1v=wzt1*hg7!x3Hu<$XHv=2oJg%}Z_BnXNJMTm1q=Yj$TG+F+E8xvAw zkmF#08qa1Ubdopar9-n6)!Mb#tSV+|CUH^xLrCwX9)q){3dQyko;q-Hz?F0M4WEtz z{~KD6ynw~l9}WWQG>#GAnE~0ix`eri$HM8Fv>`2DSN+v=TONZ)&qjEdezZ?QaK#?B z%g`(-{KlRyt5Ln_s`#E_dC?Z(IgC$fdFEBrhYLaf`=Dgr00sYF)@wL=xR#VRcO+-5g^QcM`7sn{rE`al2X_ki<$?J#6d_G6JP-l7gNId+*JUGM| z0AS-*l(nWr$lxS127qIUpvhq9tdz6u$qA-3I6yU^&L4<`2NvA)rTc4do0gXH)$gnE z()P#HJd_g?YA%wGih>jrk&jz~ ztw6C6JctV}CIhdjIRopB%?ZMJva_^{%PYwU&z9J|3fEmBFF!8X!gB6dSX8lm1rr%2 zSsCWnm!(5#NgU$(oV0Lmf_%b+UtOZsSoF)-hPOp2Sk$Vxi%Q0__NUqEZx;k&T?9=? zdkN;pAtMk(kJB&!c#r}LqVLzg-?<4E6EK0p;GsA-BMhknk(qM9fGVD}?e^-*azg() zyzT!xi7Aen2-vtXBpi>&o;%0wjd3v*ZOGE(HirjT;U*?nB{#qJ;R!QZu#n-uG98H= z!)LRVfHZ&xk01cMCP*@xsZtYC^|>t=E$eR5$7NK8N|_U=90JIU)Rm@UF^Rf$tkfhB zQ?C2NG5ljPNoG2>;YrY?-<_{|%abdL<=aO_hd(rn3;+ADWYYi#bYfQfOnzmDF>ZAksqrGX%OFO|>!XENwiq#2j~BP2x{whRnf zV|ENSa%%aG3o|3BE+DHI000E|0kFPJwihgG>~VmG{lMNHs-4$IDV?le{JA()@Pr?K z3bA;!xBj?ekG8x;)#mIt)D`EpeRovuU#D3dU@~2KnO$YgQ;K*}hZ*;(WW$PCgau~% zNlfFwDH8}}?ZgvC6KL#1CM3uLmW}yyCSDpSD=j+!LM1Jvxdb1hxCt`E+yOBaWz`_B zhJzxQP><#T8XBxDD1|IUC7xtbHdIMOjs*bG6=A^mYS=JEx$YMfm>j1yMDs^fM|~2M zojz7PsX;k(j>5LrxFHn+QF$!}{N}No{8DwcI>*6L2%eZJq?;%T#V>;rI?%wQrU&sC z`>MnFIo5f#ibQ87XIx)b@;i3vF_Fx3IWDT9sE~XJI2NTN3*LFwsw_ZY34nkA9eU7) zs%+hQ=iyUbFPnw5g9C_nl_h{!m|-||H1X&z7PsT#NyvqVjQtp(+JQ8hT^@Gr7fDcv zN6s`cstu0XzlwMe=*IpWw+Bu@fTW%`<`>!jpLg{xK#MD`z)I#(3*S*=w(#M!~ZKE0GcNkFUv zQB8b2!>v~P6BAy6n#vL-*R0Izh~2czxpYoMc=C+A7bTW#>46v>Ud5{~LE@(oc{D&9 zcgu0n)BYc8R4mh8YeFG{DDNm^=oJD7%&&rgrQh${`3m3YEY$zHvB)t+up-JA83YoW zeCH_;T5_okolaN(qCt~*nP5XCawkI0fU+Ek^D|5tVC|A*v0>SxAT$P}iz(B87Am+{ z>iJm{HU4&{A7~1a0edebE{G^D+A%~0Q7(v1!V*#;KwW0fvaxb{G%m=6fbnT)Zb7}( z2|4J=X-0U%D9KdjcTv7CN=l}}Mg*%Qi_08KpH;m>EdfmUN=Z^g2K9y^@eWB6)i|>c zQdZZL8mj)`Zr_~}5~o>uO&ndOjFAbn$)vI}-svDo#lxtowWi8}Zh+)LDL6UCTOG1Y zl|)1EC64$q6qra;8b}uM{E4GAkXS-!3l|On5QR!(BOo|GD=;h^5{$>SNGB#i=#(S` z=0;@e`Z!ot*B;UauK7Id{?>91roQ{mdVVk^2JV?McTB~p1Bj7KdeNygZ+)9g-Czi5 z?9B9Fexw`Z`Z%awNto3!jn}{ThgSDvjd3cYG^5uP-a6tm3w1cRu^4zWc%?3O4O$977vmIsyIYnQ$q~yV(DcMZiX}0GI5KKmR6mSi& zBT!Ti!$`&;vI`(t<;@>w>^+#ILr-Aq_@oC31cK59-clcq=ZgfT{6G*1)_lIc&9YGF z%CM)>DXy+2+d^ifAwoLK%p)g7AyGSVNu(*#@F>X@zHHkYD6x+w=$?+;fykhiTHU2t zGmu3Xku-=z(+ed%seg4Qa$8iQCTH4~)p*pB-{TS`)m93@EM^q6&;_1EmC5$9GM#8d2z8#vV4!Sgy z%Ecl>i64F(+|n2XI7LE zD^;=27)5O~Z3q&ROlT%sPC58?@DXDbSmPQf78!jEM3T704NQ|X5-MI+Tgs~KGd0}~ zKJiETRIDycMXf!Ns_(5@kyzZ09F)&O`)Vf7BQ;_&S;@<_(yXe;PPIK(u0J?HEu$}( zof*7@xrdn<2`nC?d54=nxgg=zo|knti?Gtlq`qR0V9v?vp=ZZhRKrl4nBASW!qb}= zg#$A%Sz=-lh@C1$1E^xE`{uLOhTnpD>0~=8y=IGz5k!b}Api*|r;JNLRvk$z@e%Hb zAi(H=N*9Q^1IZx!pbQ0C*GiQ?j9xEF@V@fMe4K9Ft&9^RI8LCJW=)BSEfE>;A`FEK zGU%Y!s=%!vP0Vz)o{gxs;w4nr$Cd}J82S-#i^a^~VwKOGXa*z5CaTJk7 zZ4^&fl9MWJy;E;@jN76G?|mr(G~g(7^W_p{hh`xHiX^MRj)ypPB)!6omXru^lR^+c zq9q74SRE0Pg~(2JB^-F)79vwz4;~#+32n)(wpU3}0c!E6ro4c$Y1-LkJSp(7*?S;q z)b*;v2Fs8wnC|Ol>@99i-EIXBdguQ=d>Ko>x$Z+S_)%d(=)vxkwrP$uT9!(Laz80X zwNFqV83=&MMvW8M0ts$z(96)kB$`Og$0$9(yTI%TYYjM> zbX)Av9>8R0qbFr)tlgR12)O&xRe+R7!e}{ zNI@}KF%x5ASEt`;3!Z%ZFISbcG`5L;wH^ zVM_8!8`)%rtf-B4y_oAtw!^A#k0uhy==`B%0z`tc)mlfO!#JotA07q&X_q zRSVNE9G}TO^;WzlfS_wEfVu|adZ5laUSB$fotWQAszy~2!gUzg%l|yvt4lgpHZLJ9 z@P*R0fxA62nUWy}R_NYh_(;bZbJAuUGOWU46c8DJVFdutl3j+f1_Y=j%JDNi3{))k zV0gH3dT=U~^T2?{qevYJ>D5R~EbY@%%u9>KPaRAtS1H#H-{I?x?HbV;TH4t#_RQ)> zG&xG3%X*Zt4LKW7Oq7QKT>^@o5e#V~0$u)ZUk&b}i-nfASDZZO zt+(^K{Y?^-nmyyg4-XG-`$UvLCGLi1FP=tNX_gCA(O7XahXh`RIJ4WsS=!2+Dn?0( ztW&i-U!iIGI|mwZK||%8POnT$4icTQrP5YaL>SImivl)cwKhJUu&Ui1Lx|c}O5-i9 z_VW!kk3KgQ%XOM+zuWCw4t9HmYcmYHz4J`LR`2cn1!WnutzFX)8vQ9Gwa&K(7PBkZ zy0dF5bCs=qVifm>sE{b)>XrZ6*~Pbt*HnoE6HOj?@WaE^03?}7G-pU)RS^i5raaWh z;n5VVr7>tKNuy#0aNw|X7cgX+Fx*@*6nZdVdND*D1scW_gl0Dfh8+neACzVkg2C7b zj*)gOC_1-}lhfwh)0P%On1?BFD_A7>DG`(sodZG!s)C7yh?0#(v0-Gv$B34Q3>;7y zg#@0Bq`8)oho8Z)H|pg%3*6zX6ud|>SHo!**pRTd5tyo01DFp8FMFu`q!95yAXQ5? zv{nYQwq4>-@Di6s zX;{mk{aLgB`~UvHaCm1>WRq3{gCRvNE`THxNv@o1svN6zDj5h0VGyy8frbJNJYj+( zOashx0}LyJ2UPE%5Lv_$1zbYtQc&qKX{HExbEAF@1CH7>s~rdm1~LMp*)1YQJODx< z!5<3*GXRq*^IVWimR~lsljXHAh6#lrJ)=Qy(>Yc*t-HOlc8t#0V#Q->TE_qT&}8ob z3Y=z7{&z$G&FBh0&S;PtDT_<}r+^7il_`Igzyz2Lsz`*oKWMm2iJ+tdzVbIlw=Yn6#p$P&8l=qh*BU-Vt&XE@qK|L6a~?bzBxKV+MhRu>k&BI*d^Hl$??ffjJsU zW10aevMl{LjpXtYa51P`+~7osI_gSpvbeZ1D{GhQ&J|a?xzb0rjyU!qrVtCNr*emj`8mP}W^7i;-m{%83|eMkbD8W98>c(r6`Srw(PK zsdNxHVgyD=9APAZP&GO+fZz}lH;uG5F8#W#DeZ%x>E>59%c?HMv3^$+w+G5B?wXp! z+y5hFG|v<3OB;rwQ*DP;r$RX5^#TxjXQK0>-B&{#~7qzDXSdrBZB zC0I-$CUx(mwN{vcA$B|wlKmMfa#~@((F&xLQ1Xi|Hf8N0M13S{m0eakB}gY3TU%Au z7bIh9S4*dFRjw<@S`!&s!iBIQ(Xb&C5w6bLZLR=LeJY?xG-`W$-Gt#sk0i{<#Uj%N zMP(FK5H1`(3J8IPQ31t;mQkSypn@(47&9>VwUD2QfU6#h;Ds6C5L7|_?j1leML2Uv zow1WlelIYvSP&EvK>-A!2)HUXiKGTHfe4I4@|7zCT5T#0#dDjYB;y!C5~ZD%%b6Po zlsaunFscE@RA3M!3RdQI@0S-I?U9#b6Yx?mc3k=9}?FoLI@1WL>5^+L^zi9 z0J_c3nIZ?k)b={=H3y!w+-OG+lTTK!JuV${($luO**)aTn4y$K6X98H#qGfK%>Vna zWZM7+S7OoYX@1a5B?`|S>2n#ijZf}niJ>}_DLfakkiyy9^%B>`Ri-K7gB{62c;--( zGaNk2=QLbDhzDvA?u7bf24tsDTa&Qidgk1!1i_^%D5&jV0AUOmW(Sve-vo1skuNdE z@nAQ<7+msICodM3iA1z$&*Bx04q;TxugtPNx6I@tXMBHm5acsa&qU9BGH==Kc zFuT=403>*ZYqsA<%#<@gNX2FvpQ9vLTXXPWlQgoxv(q4>!WkMc%nER!EJe8%mAJr6 z-d4P2(r9JQd_v+>j%{unlpS$4%|tkyylV)=b>)XA6?-n8wRf)En<)N`?CS}~_gu<{ z!H>SVh_$71#PwIQIIGyCcaP*zKXbGh_Q599k7JLdim^EgE&lviHDGlu@aqDbTFZp^O7XLy(l&84X}WT$M5_ zP%uJ4hYM^r_}rdC(f+#iU@bB)xR~(?k?PdAREinydSc+Mzc;N3T-V zWpwgo1JzO`lW65rlG8N#QJv}qW3@G`tAybGDvHaW?LBw@tIXm%16oFA9cC17{4Vjb zb{afzU{|C|Ymyqo`glG%xoL!z9U{DG6>Tt+@fK51ApigW|Ns9MyDN5>_y5CmR|abT z`>{cZ$b;ZK8Vpp?sRnP#0E8t9 zK9xuz!G5NC!XxWSjY`-xJP^NXI>SnCrMlsA8e?7L11yVEMWsxVYDFrS@<7-|NsAMj0+1b{nM5@i%tv6O@IIZ zCK!aKoB$8;1eG7ANk}kB09^x~c~Ls8|IN2v9*3(iLXK!+ z_hf9!8YX6hfw3+WG-ZGz)NMCcE7r1Pan#X~M$q2ev`8)c6twpy^43+Y$6h7NS^cqx zW0q}0Bmg%_5UG-6!8{$JUVRjQ|E5zmC6Jl4 zm*kU70018f;04Df0DtCLv6yPJu^oyltYZw zssH<+Wd48#3SiUwOkT)O208x$=~NeWe^2c(yD3tds5}>?wbN)rLXC6Z2mLA>kCcEs z&IfTD50Y+#HQIdXuhI~5i+X~ zG~!N~G#R9YrXhlZ2^s){#-Ftr8Vr}guT#RirC1vI9 zG__T{M9f=Vsm(G{8q98tw)xGaDyG`@hRmjKV$wCqm3IpX$^4E=zyI}Xo$WQ#w@|Aa zCR&A`n%?&Ji)iv9k_dXWopADN&q;F$i6FX%7}FQ37GXj$38@c45fHb!Z(sla|1aE^ zl#zSgb`A3&007ki04Rd^0N!U?aW|1>-CO0c#6vA36avQdN^opUNEINPGD37zghY!E zY_^uYT3^6QW3K{2%YKC+sM>&T4`&CA2|qX{D%{fm06PLr7XT9qA`8M`hgqILq5uJj zXvU5YFtZRDjdT!La~30w9svUZ2SO=^kOm|Uh6Er6OoSAq05wLY0>da=)LW|wCR90e z-31)ZanA8{bhsmlYdb?)8x2UFRcF4<@s^=xLQ+haqtE02|Ni^p+OBxdMfmIsJHOhq z|NqwH(~J!KxU$7zz7KQcY2 znVL+>6shFyBTVHwPC$&waPKloMg&3kcl}2sId|275X0*J05cs7HV_jCp%)5t#(9oN zeRvp|P`%-W1Q_Y@&`IE8I+mLNzb}XupK=i@%nk&eQFn#!v5hP{Nbf^5vY3qSa_UGO z^Jz{Edkm_AExT|u99{QK+~k(zPC2-8$7QtBQtH(ya>KOw z_xJz*|NODIe$BfR7k*y?Ml3{OP;7e4_1YOMYP^dk$t+upq1BKyxnwI-)AaO|*J?l1 zPBRIH%d7!udH~HCBPn0(4pSPLq@4f%|Nqsmt$+USHE9WB`os*aWxyC20yrflH#NlN z^Xjc038@FA=p!Y|taORf7eD5Af7ZYM8GcIAq>eqB@`5KDhy%a=ouBfHU;u(b+pfS4 zXG3OIAOwjEm==`9+>f=~Sh%$&w(ekICJKIa#U~m|6*SX13{Z4A8sN9URFKVqm_(=m zFlm_0x{Whfzt%fFUY<87qM3E2@fDE#K$2gCH)h@^4`(Z;j7g>~ya1@fq#1>|yDNs~ zJM?1%AA;p(OTMFhmf}qgIy#>}|L^yCo1|^a*RWo$COTlP9f+mVG)L;jWf{!(EJC5B zREfHr#D=9}OFz_X#@rXSW+x{pGZG?eBINxu<%s70e_mHRVOI7l4RZa(`@;YM1G}=% z`DP%61poV>WcL6DmR(WPe8Px6MVcQ4h@~1yb4RV^?dcbv==>#?j5L21Ts)7JO zAbGCj3}qt52zUkw0e%E58EEO6Mlwe5!i>#CHA4(75FWPG<%R$Xo^Y~ICMN9&M388~yhl*?sE77ozhp4fnt^ml62 zgX3tbz9#(s29mn+vO!F=4G`xhXRm7A))1;*flgirsm?H{_R?kW6_3Y2JQj-73W{fg zQgo0mOKjZ!$)7VRg5nr{cvCQ}4j!*+Cd4qUebU2m;7dP;KfT950B-B~f@*I72NHpJ zmMl99Lu4fp?EnA&>&3M!fEg!o0)FSL?!pMt zK{;iN2+x2;X@9BQdRrANCN$u9&f*mS00;FG5Fl_Vi=>#?LBqzCmzZ#gp3faX;vyJ; zSj=G(>4$`ZhYai`GNs_8AW%5qQHqKQ7$h;3Ok%;QQ2>%6X%MCJCV|P5#1VAF5L9C& zgN2V70v0i`K|%zfn7|_dh(L!17!rVT=O-u-gDqRd%hnd;7Od`@m$?02VS{(`#>J$XDhnA06qGAQ^i{P3iICEhK3C+!}RI35rLnw@9NK z3Is4?!~hs8p8VHbEbzbOq*v?Jf4N4jBe}g|_+@iLlczGv6_ieOhtl*$YTbUe!JS;~M&Q4DTMav=7uG+QoxrqEb3-Y+{L_>z; z%>L1~02kjuq&8QC026?65y#UbY8SWqy0N!}H#Dkgyt-Dq(7@@la3QBL^MG7sGG(-F zg&NUO33BL~x6{mHm02Bokn-$+=a)(n(;*fa)BxOEC;hpW?Fq$VRBC;6EVgW^0-;uC zrhhtv!!Ls_3?duA0@TmH_RmVWa_J1{TV8Sk9F1Z7#MxtHG`r zv8Xs6e24?IE6m!5AQImkfqn|NrvUy;ltu zN#dDEr8|CLM|Sbf*4cAUD%i|~EVwCM)!|K`1uU-rfsMG?pim$*g9_7xL17~%lTSXE zVuCf|j!M$^=2t$O?&4$PwqG*6Sd6B+WcA1v;|ayHp>WFgI5T~dd-|lOMV20#uPnV2Oddm!%Uq$Q zoj)~o)kaFFqP73~uw>f+1{_{h>r8%FS!QZ~Ff1(>`FU5ZG5cW+7-_wLpuDx2Vsamu z`RSZqe#>r&r=@~c7NQ+0ePPC{#51vm5|vw6iYfi3(G3O12e2ZNih$pd5g?-0-Vj;R z{zs6_;v^LZ49B*HiDz(mn91)CggACa7 zFcZzlvHr$f=*o;toust}s-10}KM0?+r`%UeEo@1;yS!L%Zcj(9IfhQK!&N2z)pS1~ob6{ztEyu=X3+I&pwK(DWlsXmgCPX7>4#Mr4AT z2aWTX3oLQvw}o0wzX6r&0}`CJrA-qebn)hR(iX?TV$)i%$Ae4W3wGp06d3F=0000y z0ZPc6OexwdA)c+j^X4AMP6Ada=YiqD!3qr-Ce_2m*3ZbkrTHh%_VX)0w2tptCw^B2 zf9$6X7J3H?ASyY1ZF41T6iN#)Di8VfIR-8>wai^aqc8h9k=O)Bw?H+ zfIx{0cY4<%sYxF8V0gmqhou}m{&@aua}lZH^^BewAE`@Q$&2Xc(ONRWjZ+z&#WORj zYVs4vYI~`NzUsHOWo&nIHp7C$qEVTaDlC%ET4!tz5Bm*oI?t>HLYF)JNCi#+MTdIQ zYgTUTmPU|_bDvxF|NEe1@&E=}TvTgWdzeCH3GZYnJr|{GQ>{Ig;Kh_^{PKwWv5hcE zLzE3$Gw9r*P-++YKcMC)F*knoRZMY&CMM_2&LA=|VBrX1jfk4K@r-KQK$GHhao+EU*IqyGDlro_$tW-X;F+#Pn7?OF2m-t!wz?$(&aAeFvTH6lSkt#&+0vUVWxv@FNZCC~yy@GX17QQlQw|NsB` zL>ibiqyP+b00M6SBtZZBpk(HN7Diaq>u+VaFy!gqJjWjyrHe_fVKJbjlcza=oMaJB zszGeZnH?q(fAr7$#9}885(lmSg~idR6%xPy%`}WPBqaz51vNkuxu?unEYihHC?Lv; z4Fw=*fZ9w39S`MPXhlybPbIx=B-ak_l zbCE#WqhVlEC>Yc;tK28=b&I`ET4^QPsq>nudbY%}Wt_MuPot$)?=jdG+vComz9)2k zu2@=;1ZZ0jil@~~Obe(rPQ|XiH|@9^`}?!+|HQz&9iZ5O!_EK%&;g19fxrL*5daoe zSQe;{|9oXdDv&HLpZh6o{}`#^Tps@z;NgxFDK}YMz|;(=n28(+dSEuCoiUJrvw$$9 z>Qw`+8g(#;kjW8FJTSn+Ou(2JBB50JlL!K9YZ!1E0L^pw1yr5M13g)$1SXJjhW1?O zywF!7+I~!?R;FnkD5zSkt27!a(&^zJ9c&EJZr}g^_)NfaFRdVf|Bp(I@ zOgGBZ;dFD8oLgyJtYJJ5_^@W&`iR`tuWOP6xgc$y42&a48ziX04>F12^qjQQDoHQ@ z|Nq80nBp#rGT|7Na07Rn|NEe1;eZyWV$=I?J@_UAnV(=S9~hO3O|8ATV0wtByzr!a z!4Mq)CSZqea8{j2$r8+L0HqIR@MZZwFA+&q76}ChM0lN@slXy)#USNFOCK=>uyc4~ zfwzgEh{LMJ4@?vx>0m|%j0_MAMGFr!60m9rMAu1xZ?)BZFqmyhysB7}?QPDZZ-WV+ zom7uDep!{Wm2qZQI~})AZkv;x?((wN9H*@gP~9cI|NsC0$`M$WK|nJOmX%P>ksr~9 z;hw&IJslAl9o3lKMSG?t63d8d$5bxM9Tn3qQ|Ii}9a<{!={zrEyx7c;EY7(uOAmkl z|NE(wb!O$kq`HuI4B!a$n;-%>0002t8-#pUahN%ufDmDfp(ZE@unSgW$`Bt05U}78 zErr?2Jl9MCTN3O=%&^pd7+@n)tcZ!0-ct?oiK(a=aFoZNLLlyIN>e2HPK9)(OZ}}f z=O#A}yApeDlao8}mo&W#;#JUom zc!frOdB%M+JA?TYpI_qozwi?g9Zfs!MXb;knGp-9IM45tP*qJzWpcgAhGR)qMwJ7M zC&r_I+$VQ3MM=Y?2s2ncT?64(E#0%eLM>@X!N!h)t$@*86= zYO(Gt2f?!D7XI4$S&qsNlNtZ}pk(C$77Jojdu(s0BZ4XKJSiO);fqbJJ-J|?aq_8umx@8~^`IaUDD{MmW+h2H=f_yiLY{S@$)w^*o^a{{!xlGrh+2A}``{`Yx@lk5Ng z|6lrk)}?F1I$1Pd0;XkjXUZ*rH0M+*KOqrtj8dUnW#{50ofo6ZDe|FUI*}@K6i!5N zgP4Tugg=)wqRPFW^a>t!aVj)$|NEe1@_-fCV$y4GZdf=&*`Hu68yB66P3>jpAjuCX zJco&-RJX}D(7I_ShKMv~#G}E+oWOG6#&8aV#F;RNgXoz%q6`pPMC+tp?y4gyC512x zv5vdg=r+sih1QylcG=PcjUM9hIfu_DxPC4#A>BdX9@kERsjEVF?l5%~qe3u?CS*iJ@# zKzQrTcFpa*-)x4jL(AEq#7;@9RP;ZHzstY>%+$K&*8l%BnhXbRR*e?cg7wsM5mz$0 zJIM_vE$6O zlqdZ57G#I=MVN543BwL2Bnah`z^w$Pr0BP&B83pEaDbO+`5?YBw0|*C5XMK0p*^K=Nvc?h?2uL&RlCa@z;Q%?YSPWC_C4vkDxFjTy7NteuEZY-j zOu=cj7#)1O3aJdaulm6Ovs0RfH+R--WcRv(X!@X*ke2g9xsj-~5cdQ#1Wy>D&9YW1 zDiu#4IZTSg#UqGQ3e`^QmYlZO@akhy{-SxtN~yYV^VXJ|($mp1wUyBldJsWH(;u00 z#51I^XI1L#)uvxQmfA8BR^n&=X79$qm`q-*^T$F;mBr$n2bSGqrmcXH5LCh>Z%zOU z&A)qRwT2qQzii4R;}FXLXfq;spa8-0KGpG%EGXgRySjCaeTva#G>HaCN~nJelCrr% zrOhcbPz6A#iV48MrijoHD=#J02Bl{J!Ng(R8qM~$V_j@HThL%_3$G$f19D`Nm=?$h z7PauK&7@l4*Q$xBdhIhP+gYZRwANCzU>R0!wF;7)CENPzOY2fDZBmmH!rN6+IvJo$ zXileXk`YCGXZl*hC~9v(=yRW$aX^Am>*mqNA&mi!v*|NF3H+5iR-Vo-Z|VdzyPna^eEcNeXTKkZ?O zVM&sxJoK8)E1ZPoF^a;`HV>IAo!I4L2YI$raAIn3aIj8MHFqagco`82#4GFnpa7sR z;xefBhm7VE#z?4W>H^sRB&4y(eluwld>g2-h?gD) z=-~l`LQy7`EY!$N1!_#31Y;%y2Q!9riTD3q%`IROfD&`0q|(3^MhZe_;}Qcfg-U%) ziUUYXVr8$IH2rS3c)!4;ywJpvl!Sb9}y zYVRkPAbd}4^R?y24~Zq?Q>R!*8dAtl7`BVpW)y4*aG@w>zcSG>&OCUi%I2nxt%@Y4 z6xwH6*p)n-Y1GB59hY8XHZwvh>e-{dYqspHLqcVbEjI*ml^XU+s!8uQTVWBT1@g!e z7?S%A#Iy;b&Hw`dnNw}I`~U?{Y+I%bEcEvPmj=M_1Qu!R&>OAd${Zw=H9%SMOXalV zp!$4W56Z`dCP#8f>H1;R&gjk#3eTRGiN%J;p)GSuPUAX1ESN4<(TN=tOPz+`Z7yug z%{ANod6K#ij2g7UqcO4!f}+|QGzR2@Y*#lC@=O5x1C1r2QCD@yhLeH7CN+;CK!jI2 zI)KoWuv|Kl4@^u}56jC33notETI~w&2!+T|<18Lgi(UWKgHQZ_ZJAPBom z76CUS z^xA7a**&{mdNT(Evo&$TOFy+HVzZQ9e)T!C_d1nr`B>!b?`4U>x$rkPICXf?6IPms zM!)^Q0|!FT$T@Og6+VZg%omw_84B)*$>QvCB(c8a2!s_j22SBrV!`Fnm>d;|T)KU= z!jWKgYbw&j1`K3g`O>(n_In=jqRpI2h{`bpedXBJBbQUV`2;HJDzxd1f0_SXT`>Bb%!LO?2G{eJX?tX^;X`N(lt9 zCm<#MDp*3lTdu?a&74&YUrPY?zwXpKc0%jB|NF3H_W%Y=VNd&6Vfs;o+7BlQM`Tfz zIjwU5pye2+v=xcv1=ol`k_I(N5l>cKBGif+f3(Qk$bE;&S7Ri3Y(VjO*o=~ycE72f zt&C|5p@76C5-XwvG)W@5Ca4lG9XkqR;PRa z^*IbUxT-P+2t8w-qp^gyDP}t2O&FL9dwWCKyHc&kZ2LL3ok}$XTme7eH0AT}|>Y8Gz zBH}AaZP7RCIN(08GgyM-RIw;R!aH^8C+l07jJl1@?sqD~^Q^xcG*C8iIARE( zeP-5*TS|g}sk9oo)Y1HK-uNA%q#|KAHfYpUU3CBZuw>$Z2Fzhndu)B$F5`M#1qK}; zX@yJeZy@O)k!W!<{uytnV)z(>Arv-7M%jwkyFh| zD6q4CI(z>+GWD=V4(`F2$t8~4p!mb~Z{2`i+0NO_UKYV?3dp0kH~p-dOlK>v4Uf&g zngI!FQoV1$0y+aSspP~mLt2?kRxmJ_z|H}5xdjuEI+x_e#6kkXz(tsgl7TT)LSe!% zVZg9SX{Lx6FwwCigh3eCX|5m`FmaVb2{@RUd6J8q8K@Y5P&@`Wwc!^`N6sJ?G727Q8ZdAwQe@$9#*iT}FkldUZOhED+q?wr>ngK#}aF(I@gJ&gv&4n~m-26{Y zSy9l`R3MVesG@w%4)djXTvH2)nlr|* zu#QHxp<-b;48#%}g6ywL7krfHdkH#HA%r}dnr-Rh9dl*OAFg<%yOnB-&yJd-ixkCT zu;OS~H;Cf(UsVDFfZ~&R%S(v;fumEZsjehr$CLKvCU~x_Z;l#dG00BkXH&ip|2Mi!tg%}7L zsEd#yB!MQx0dRtQHsMZ+W{nxyWI<;au$4b530hKlyS#S#Nd8JSP1Z@#{)}EcHJ>5p zYh$Jtl&3!GFeQDMRV5p4H4Q}oc?hx%dO9gUyG#^D%R~&I*#&rxmLxcckVyo58@m7a_96^p?7^m= zLk}Sg9Lj4@+R7F<*mYQ_O+ex@rc9GkNYyg4!xDw9*<_}Aw2nn4JR=m2VLxqpRYUuxrX?iAvGr+TTE5c*;OinyPaVYu3k!7=|?wmLhMUEF-o>^aissBGs@0bi;~v z%Y>Q&0ZDG3Fxv}LYG!=NSR345imxJ(uM=Y3iRF|Q{5OrGvoCVi%{(-zoR{*=4IJ(` z+QHdzN-~Cco$W##|;71ac8emM(nFX_q7rr}P?J3jW)RgOc|w;$Yk$)L0rCk7 zm4l}wd;rGbGZ4lzTXwe^2Lyyd>xS7U`IDkn){GdG3NcGXQjI%gZ$cE$Dw}x@D?3n! zhyx)-qXB_rs>`s{u#vP~X@~%L>L-hYqeT(wG)O zE36-4iQ?34G=@GBgroL&rnO-#$jE<9&!AmwePvWz&lhd*;O-8=Ex5b8ySr1QP^=}m zTX2fIySqCSFH+nJlmZ2QErm8O{jay)r#ByxmE60sa%aw*Idf*8y-`dZYJTvjEx$1R zTfVm;sLpnuLo~vAtWns0+g>M^WRzEsC* zHHT&HNjhmc&qslNu*q2wxr1i&vP=iVC`l$H-&j9exk=d$>Wd1Osi-6P$}MCf-bf?y ze)$m#{sb=Gng`1@cq>2<`{Q%(p0JFx)hJaPse}rGc{v>ST~;G(UOcE@B-LL9L1ocJQ;w+A~Av@FtNKCXRbtx=*%-h?to^ z?{=rh>jwu3=Lt=tg{v9$t}_pz%_-pzC=8p3UkCNwf2?36H{V-^!H=$bl$-)~=B8te z5l=0kD?nF%CCVv+hHd>NY(K0W8;scx0P3c?Y(1iMJi|GeWC$7xIeMopS1Rlma|V!5 z4HSzcdkA?HN7S=N+hko`(s=RP65Ib&7RB{9^)%v`MRct1p7=^P!K zVB7?x_+dLx0c;`n%nol75hwZe6;y~&3dum459bKN6%Kf5@A0l!>C-BE?s6wWvASL& zrQ<$u;o|D#$argV;WPkII-SXk=&M+&boeFvtnkxlMUpvL<-zwq+<*mAmvq^Qj&?uX zOg4@rI$91cXfu;7XD&=HjK$Lz+S4UEexqKQ)@5pR-pdTm4+Xaj-E4;Jaerad>-79* zafc9+H+EYgCc!2KPVAo)Im1j8;q}YBPe&T$^{=EAd$mJJec@T%*6@TdEaYgejudsu z^}^V3dc<5352HNDx(1YJv&+k?6y3d!EuZ1zVc1|C2%i1=D~hQ~8aDnl5Rn5%hTT&Z zZv?S(!iSS1au!JeH33ggg@~Z+>rQkoxZzKJxAc=jZFHKpBxkAt{imw1uv9HKAF{w8 zI@hM`*-xlQEkHIKumYL=G1b#2^h)MW7^UHfJICWu%+@MGI%DOOer$3hoAqBI`p5|O zApQd~Gdub^F1oa|JX>TLYAs9@MFxH=<-r{>bghqXK2cfgAFtf}@!O;wG*98~BA0Ox zWQbn9w3t;-Ws+0z!Tj%UN_2p+gx3?X*&hc(&c3(Rsaahol}swe^>bO4zNftBOd4tV z#Ms#>`%Z<*2H)Qd|Ld8qqt*HGzc1w%BqFo^=4+N#HExzd8mH0=`v`b*3jjW|)1P9u zg)gy{Dr%GpXD5e#m&UNV-(tp`1Lf0g1qP;ak1lqtE>Rj>#YKTIggYpxkcGLF=o4|1 zKb1%<0a^}IRS{lR0#$yt4l>S%4+n@rf*+e`rE|jmlEK9*u8^?^%IFrb1$I5hgYiyV z1uCLza`29wrF6nq7k-qq=(sStp+90_fD(S^P8E_wYZwA5s&s?%g2BH6NO`EEI%<+# z!|5_F^IP}qsPK)r|GWBtVDIr=zlPV+>AN6_8ZdtHA%=;-AO@ueIvRQ1rlb`|^$n_z zs9R3FYUZ-Ev`WN~H`U%uAKQY7UBO*)Vkr4R*3{sv91+|r1BU33Vc|vOa}aeg8sEY} z11%2M5L9J5!xxSBfsRf)&0I0nWK4;=H@t%M&G~Mjv6WbPu)iGTmuvkLJfa1U=p^{ti zioPfHK0~(Eek{#a@WwU$k!;m&^r)QB!l8cFp^=`70C`@thzdKDcoo`5yb9On);`$`fwXhjoxhThc8wD{LOdB0<@Co^f`!8mrCSz(N zKn(d+hT>EU*%t|f;HYnhCa(rgY;e1ihCRjm_+XOJpQ8dW6$rJg`aym2d=D>b(5b;M?(I%!SK z1Et1*$pgDcjBnPSUC*`=gL=K5X~dCgJ0pR63!}jeeZ@zk8&0!DGMzH)_xrX9;}87H z^0LP|m}N(qqk12lQb?c&}=9swR7(p@a{kLYK`lCcuz`^QJq+)Ulek#5sRroMoTGO&r*G@ zcnBq--KAo$u5z#;1fu8_? zTsuCJKY1>~YLC}4lAs07y^LASjeyDk$-6n!O^J&{LxHoVcH@erIjbBc#50^qxQJ(R z^@;amU#DglmmjOf{ggOo2}FyTBi7Vh&KL-FT!a{cIMP%XMT0yx^X^Tq7M;?kj056A zhiDWvhq8?Wq!iIB19rtva@Wvb+^T=VVnL?KEe-GKU{%WRd!7IOX1#slPJLIA=$JI1 z5${pefx+ZzixrMca3S$kBa(^_q=3VMkez|9>jN(aLB(I}L(EbCI!;ujNbeTUgUqIL zc-ZSx=;}K+QD_#r@LY(kB&yn@$^P|Emy>eCeVJrRV>al|7_x;_GH7sm#6FdT@-^sZ zATFD`HsXD|$6k@(*#uDMP$Ilf;fwkAmoIE}ecQ#sL-uLoPIS}@Ju=7yI2+A?BJ)Bod`gn8S?Y|XS z8Qb$L1sOaUu7_rop%@7fn>B7Y69W>nfV><55dt^4Ol!$F;^vq;eK5zwTO0(2Wo>)D zHBUZ?1Q&T9w{nK~9Z1x2owaA?cXkj7rdlasViP`54qU!h!iG^EVFl`zMm!=-vYeVS zV=;t$$7xV2MzrCl={k?Qxmd3;uRYN5%=aewIU+T;xw)(N+}*!P+9g{k`6<2?Q9j_%)8D9K#Nh7)7K2M0KJjwFvw+Zr#wvkywZ5 zq+xJ0IWx$OFSzLR=_4J|%QV+_m87a*VOqe$&`uct-?ElPdUQuxt4 z?X_m^rON`f_bTw^UUOVw{YLR?h6#^D)gg6KK*^fYF_khq>w9EPz_aorN(v(6c^Hb{1w~}WWf{>iwBHPg7%l^%JnT`U zLW2~PLIZ6voD5`aF&O9N*5Ituk_^n6y#9V7WD&}c^u2G~yy;k!;&AL;0tML}0K7Gy znrSkQqzqY8C4xRXVgYjL%yxK3S8G(Gv&m#lbpElK{(@lKM$Z5BlR-jOt-W3HKxDH` zH-BEl1H7WJhk?Oyx}{Px|1Ia(xpV=EOh9y!ygT0adB74IGpTMnfbe~jn8)I4kbYLY zSkf3qc-;ynQ6!x4Rifmm9x-A*V%tH@sk{L{+$wpfX?LQjfOu!qwr1121|h%lr8M)U znW(C2?;k|y;Yw5e1+E&=nx*D7q+n@iHbK$Ot`3clW$Nz3)I~^Bdf+A7Dsnic$0wQt z^3&x5#@q3sF{x2g@|+N?Lqf1g<|IU(6=IqoM<#qse{S;}gKD>!Gy&k{(*wvxR6^vl z?pn*7$~oj~a-Swv~!?>eEd0h|`@jV z=bVhfm7$%Wa?YwMwb^FkYi8^AA7|L#Om6i?>HCVhf{?Qy8Jzm?@k+ui<~}OY7-Rro zEzjoCvZvxmK_dX)8_)$<7(YJx?WpLTun)q**xsH*O%w)+!FYz692fON-qw#oAZ}9 z46#wO5P$aZakLF_lL-8Yo8zK(BaZ&mSQu&+W(=)4QDTWj_#55B&YVgp13*wye+K~2 zm$FALI=jg9tt@3*TN#M}rJk7?N*|Uy(T#oz{^Vh%R?&!xS>xSI9zlv(i1JoavOyyN zy1mIp9YRB`#>FWxjl0Sr#f~ULY)TT*UPBI_9vk(jqB3v+l;|TrDy{;3gU7=M(N$)@ z<+kg+F!K^xx?QK7(WEFkI=)rDZaGWMLTPJEQy9~&XPHA+a#Wn2tPWYDs?W>cOr>Qc zHFPWB$XXM7-V%EMMq}Zy=yYM>ybn8I%D{k3x2!K%<78>!v6OrDr^dpAW)FV2CToN+Jxe;c3fJ@5!YRiKbWkYM&d~75=Avu6= zVd&eK>=M{!J~kN?Hz(XBV1hfSqqHQ4Fh-7v|Bs3hF2`eT{W;9_5CF32<@yFeAdL<& zzHy8kiHl@>N;-_Tn@B+Tp=OO(T38DtJPn@dD9Hi+nv?wWU}zE~FrrdzohE!Gz>B8^ zUEZlEm6qByIqIs<^Wz)(8pF14I|TDgxM*?o&~Gcq@fx*r(#w#)FZHU=&D-#S!=m;G z7d*^nyX+lX*;i~ipF+R7us;X9ZQNT_ z=}p-?`}Df&Y~wRG>%g?Tlq-4}I64pkiBLZhgT&U=iL9y1(P=D>aI>92N%n|O_rI}{ zQCX#ma6BXjc6*7yu|i}hA9G?LKJ|h2p)S*TW6DR~oB?Qz0@+z>Yn?y24@hx3WMVK32a71Ct6^+)5%!tqGwrvfx#u=ZgX%ygN#SYZ`SHv5ZRp8W6UU7P#! z+~I&p?3z(M`f|{oL_#_8Xaqy!LIMzjM~3BpNUs%$kg%;mNKoJip-esw8Ul)mV6^^? zB>#v?1al9G4N8sckpUa~W{R-3x@&KxzYe8;vcQCsmgvb4o|Us)43ks1^Bihvq<&+I ztFw!&EP$@u>>CZ$Bn<#<;p7iKaFQoR4?!baEIY9k$!>!t`!UZ}cnw_<;kZGKw_%dI zNiC1OblWJnh?A#~LH#rkUPRTy5v@jxWSML=H8x=1me!dO&hE)gs5hYvckZu3+(Zdc zr`os5D--FLf8S4S4&TCAUtuVdrYJH$h|J}}aJtPuPjB8M8iLwo-~CPw`12@mHAo%W zU6-QtS)yz+cSeH0(KsK85Nmx9PMnMo#g5(L2@GL*j!wUW>C(l^?P2>2aWO6MR|(zt3v`=w4C}jdUU$rRJrU%P$@-CfMt~WHe*C0v&k^9 ztcJuyRRfQ3HF9J&s_JIk0B~>AD!J{XQIwdleV)mWxWHrjDLEbwJ z2|O$gUC9$n(`?4X4w(4(sbWVr!X~l%89RxUA?D53^UkgqVkD$I593kgf&Cf`28H9KALJ3!3hC0u#b#B<>@DpJ%R z8!DFATshaOyj=;vBQ+D4cuU?5Z`4Z9|D8H40)*J$c^FfhJ4X6iH;Fes6!`ImH-lM# zh{*cDoKqBMtuyiuEwA4=7IpOcEV;Ro&uZtRVqU#jIcQ5Hm1+*Y|JFoOB0>tTF(LfT zl(zO+rsj}5BMm zLQ6}$Wmc9IiVL*glHuW}4oy?%CWfY%W*vP% zxN_vbN?9qnY$aJM{Ama6<@}qc+mDY!Bw3Dzfv!YoOX(1F;*_b_8g?>fd$eP#*J9ye z;3?oT+PdbRiOY_v3c)v{w!yag&u4wvGV%S#r5cR!YCiF5RRbheB`^`PtAUr^7|GY+ z5~h-9v;bi6`gd)@=Q)3>C5hO-vTriq{rDJln+Yq<2|OGPyn~CED)O~;;{)57#GIGwsfU_%e4q}>yRq3EyaMdiA+QXYfQV@y9`YZF9T|3AEe1#o1krvWJvmysQ+y+ z8Sn?CPUIELxv((4Ci026cp~(>**UMwY{I-G-$s~G(Zxb5rrv+BW0UxqKWmB}Q8Vny zOhLF5`dqwV;4LtI8Ip<-y12|o{y>r=i)fC5Z!Nwg+S2Z8icH8Q8?OAzWrTIjc=j+n6zMsHI3(bL-O@uygL55lMCP%NrAD>NH5;+)&C! zK8?$}R7g3oC$pxN+u}2ZeQl>}zz6C1#qw+3)qGE2_ zD%UJY2x5gCPmwzP;nxZs64z1NXFP~LFP)6M2@~pTI>WT6ZP3>*FJah;YGjr*;VH+2 z2}2%}n7>nDGq!z+#^ghR7uSD;HcJfxDKNgn6jKXfD~8$}uxqiFl`KFR8GiqV#yUEo zJfM?}tWPU83l1welbZuqCSd}Bg!q_Y!5D=|tolwRGqSos9x);cxEO%QkU~Mhj)Fm| zYN+#pC^K%BSgq{?s|Kp0s<&+IF~Miz1!DUs62c}VJwwmvP3y!oUwVf|f&PMa-7>ue z*I(*iEg0EsUx9EkaTU+`c`wC#MdvlwI@+?q@xO&hQElZ}B$9$(|KtCCLIJxy@KugE zQc$wksi{>Y$0!`rXrf9Ti+<^Fc>28m^Nr;{i@O7$ZrN>yywUh2Uw)M;!RAkikf{6J z_3ZF61zxI{JMj9QvgkhE|LhC9N-flX7t3Deo1^7KTOZJkxs>xB&&Po+4QDsU7iv4)77CF_W8yxgBH-s5{F@@93us_ zDOcJgaHbmpK#;*A6c_?ET6l&dA|qz)7>GF>GIN!e2@x&F@&zEl5zJIxUC`{KE0&yY zCUP-Zko+lg`Yn2>c(M{wmaT6CO2{v+pJkn|pUOpgRb!c}PJZPNGqakOy%B9nTb$ct z7s5(=Z@Bcaz+$6vBuetlEr%-6eepTZpX94nm71|ZWeoQhWBA&<|EuWPJHF}(zmaO* zKJ8RPj{l&B=%Ucp>`mSv*PqTa-3sD3GBy9^95f1Opc@j=oa6?wM7=OB!a!>$0Fezs z0{~#XV)dxh;eXD^_$XnObuX$jT6wQd?=LtcMD0@3(_sI%yMlN3ZwPE7KKP4a{0bKX z!185(U!W}cdc?K82(S^&iyclf2Ot?(mq*bfcw{KuPflsWIY(s&Sa+OrLUU)Frs#Og z3k+q+Sd`?=Gruh|e?Ltp2X`#B^FeydHC4R5lZNyzY;`9BHlxQrln37j3Dk0quB+bF zy2H$#|6+0Mo^br`KlZku(YomQ)=JDIxLsfH*Q+WMU(2F6PJJ@ZA6~3+fA6yXrTDFn z-ngZ_3JWb)n>-5(#cWxaXw%8`bMbKFk^RIM@%CB7oxiu=U2@g~&+(5Z`iv>x;G^u@ z@CT2e-2+fY094LL<<;+)bQFHL70cMaz5Q!A_HVU=vyaT$8@LAt{o*grgW0f9Qv@Yi z-Z)+#CTG?R+{Ib+lfq!NtvIsYK$8qS?Eg@(kk>@K{VyS`5mo-Z?ZBTi8d*`eOhDI5 zzMs+jXpA&mc-k5>DENeW>#u-jo=kGSME0Lqxca?*SMA+P)Iup}7zN2cQRbvQ*S2fz z2+qz+Dha!InlzCiU~;~e{fjssf7o5KFys?9dpu3VUsd({BW&WTD*iu!c8^<__>M8< zLORc%VHhmw*5_TK{&}I<@j!;!ltQ%)?Rn(7_aATLiR$QvCbGKjhG8fb>)t0=VUv-q z5ntXBijyw0ebtu}2;(9^cxvN201bf;No%z)8HFaJ>kXV2c$WnRBa6b~#>^}c z&8Uz=RC~^tQiT9jOvqd!qW~@Iuc+E2nIs<^)e_N&^seUPge0f4#kg%x)DR&M3m-)C zflyhU1o;SrIIMm3Z26(FVhL{T)sza*mES}mxTCC4MyteQ-jpmQcdq=SbBSWIa=Yxm zz#2Ao=X)Akpj4LxE2Jo}%qUNTiF72I!FX&oH@j|B;N=IfyOzn1N}GZtoFYx1S$G$o zjfpEIrW9$g&N*gseuXqwQG7P7q`3UC0y-E?uPpWP$N1=aJ_F?m}*X=C_w1>2M3;$;gSCH0qnI#sO6s}+(J-w?Ka>7=D%1_C}<_vQOMa6O>b;( z=!%J)-a~3EGl6OweB+Vtq5uYMs&m*21Dtgdjwp7>_N-L`X3Dct@N9bdBbnsxq>`m=0}ePokAV566-o zTjA2Cbly=*Dd&|4e1PF?l6Ej@W@yTZV11x@qgq|eFzAEC+W)Rp!(ZnGglceeu&s3u zRATB$6l?Op9Aqi<#FAJYYM5+|p{fmLg00udvWZ7M;Kjd=HlETN8@dev(9^tQbz6Kd z09G?9t_^?+03fd#P2`{%tckPLD&_r`J~YcNVl-ey?&{KVkAtEnQntic=0&X9G)827 zL_2S!<5=G%#-N1A%10dGC*OonKOt$O-}|#Ax}wD-as#G0X6Fo1KS0->K?ywm_VW4~ zaVozQMEMyBtHEw23x=eVZdU$=Ny3t0SqqsURKGy{Im{ASH=u*e4c% z9ZHf|GOW|q75UN@tJb*xZBgz4B>M1GC@AO`r7U@|jVBVRZ7f{a!RKo*vVCVxE{ecx z3jZf9WSfa3fx(96z{cu1KtKl00AH=)UQLip{;9~V9EUD)=1h?-u!I0#*@v~N1Y~0Y zMDkV7*pc7JkeWa-O=i525!`sX(07!1)^NM5Z$(nX=N!T& z5tIIyPucOV!p>Eeg#^PPd|3hq^-%`Tm4^-YR4tOV9{y9Z#OLRitLqerevKS0QHdkC z{}Kt-A~pPrDBF`JTUm}rqfGuO_IPhG8qcXiCErK1WZ)CgBo{`@SvMnk|vohiS zGpb4>#jvcQ5~Xs{O^-ZhG7PsdJMSC^;f{)OK`vVOe}lIsHUc4<+c3hw?!jv`tqKp{ zfI4mVLn@T@1(4%6??T06#w~8wSSz@n|MTPPs;77pPNYMFt$>kWMo zeq~$K%nLzC<-e)=3F80F?(>U=WiH-`>UW6|1k&_)>l?P;HuT|af#m>{(X@rrsN6+a zM^scBhlFYZM9BIfVmz5hu&FGgEica1jf1BdNmi@P3I24g zrsfaZGusj_)){wq{KjE>5csGmwTLzck-c2`D}Fd9WA=u~A*~5u@$xasVlc8m5~22U z=OYbvG8dyU=nxE~tGE(V9a+Y2)1|GDRt8QgIK_XF=;X~VTFpr`$HQp6n6UPSWUZtZ{^4Q)WTK=8T9u!6q)SK&q69@bDv-7(jZ6FVCD%^Xl)Ut7fxgY z>jb}n{UzO4!k+aAyFUW+n_E*Z7E^y6&sX8jsz*ie6)3tJTI!_Z)R8sm=xCE1v`Jd`9hRs$me z^r?UnXTyI}^%q2N&ua6!!F#_Z%D7kj9XYpT#4TXsPJ;J@3`D){W+oWxH{6`LWC_rv`+!yE5jH&t^yw`kx;3-W|M>u2uf0grFfaN{CJ9uZTPfh+gMrN7tYu-f~b;_m2#piNxZR ztzt5LuVY1_9q|(jn2t){W*0@O&17!Y^GfC|FO#nR#rIe&wcXU&bqBHnfj$b(+V?bs zdkfWQ;FJQnYj*=}55wWOE2M!0N%mwhHJ6j7cl6lAZR~57U-2y~{G0-4swoiyG#^z4|3#)b%)Bb#7pl zlMV^#LM5g^G7$hY5Y$H_%K`Yb4GT6JP6{sIWBLEuD>`{^E&?PiCdGRT4}Q}0 zuOX=0`%rEOACjOU7wWqgIUe1*Zbk@>p9|Q@vOaTxu=AbK=(eM#9)?ZxD{pzo+boF9aT4_7brjRT1SxV#P0ggtvbba2QJTN=xOpdKz$j~%E2G8!pzKBsp}3WBfo zI+ToTAK|BLJS+G_rficAf39hZZf-1o5AR6^rFA+9)l53q)y{D#Tk=IY0V4*WU9_O`s{^Y@+Di7y zRsaej=jL`=A9i3m)nfAzRYvZ`m8(MUDVKMWyunIR;?Jw60q};LmsEwq4<)~6hX-X$ zIY*G1E?%}dCRk}Aa7DcYd-4c%2LBr#qHd4EsDi>3*X&z@1i8Na{G|`f|1543Ko(}V z4s)ji;M-8(96}JRW}~fdqzPRNQO+I-u@tKED-6|6y#>vMXo=8DgI$Ea7tsGyaWo{S z^G)oL?u>ik4(v!!OV^6HzU7^N+CqGv-@%2ihZLM?DMgm>(>ISjmM`at+i|y6QxmHx z2Jgizb4vGV%qQRAyC9cWBgh_T=+U&gx_V*!V%h)^*Ks-o+)Nx|4Y=8(GFSVV}C-n$bw4#z|d}=w26iraBjn65e9Pc+xg~>L2hhN-k z#}oEo+N*%KoX@=))pSP|jiT|ta=E3<_WI^%s^w_(jn>sy6AL-HidYu&vUb_rs?=*2 z37>G3Tc|42*dr>upneN?hArLToYK|zN^1d&CwXuFv~PbyKo^@Q*twaJ_NvA1o+Iauv%31%{WLUe6hE`zp44VDgi!g_#@i$c8Li7 z$YQ!sxI6;^iL30S%oGB%?pH*>U<{Csow4OhI%hveZ5!Bl6lY1Zn|#7BFEa4E0-s`x zFB8>P2u35wK|-^=)PC7=9;%3Iv_ZS4Ek2#Fsu#o9je#|JdEC#Dm8(y>)h0}>9@l)JcJasIHP8Mdkgeh#NiPPuXWqxv4zQP^NNW5TkYUUraisE7Iq8dW49w zDQ&KLhp^5?y*>X%Fv)q7q9aAFV-eTzbHhj2rR*^5Mnry#<1!3R^8kZ+81pvnHF5i6 z;+`*-Sq=Zk8kjUrDh(6=w)ACxyozNvDZ{1$nXQZbgJo^WDC7L#mN7Cp1R(wPzwsuN zn#~1W4a9H+M$wEIle;e#GbKG(Mv76qqKJ`-m{B;o9Zbw6GPrXA{;w~L@)LYOYyY(H z*5P&cl3ZV#x|pq8Ia$SJn~|}(@LaOiQ@ItYZdEdK#kjT|q)VS()vb%bQ_mDmQbX>A3@@}H?GaXN&b;fyW%L|NQIt9sapsME-ix84<@ymX~h#2Ic|<}}3|@l2Rh z5NQ0S73|kL&m3#qxhS!){&NOOVq7qWsFk^SW5XX!A!*phS;og=a7V{rIajl#t-}66 zb6)@CJ7fN^Z)+J3!TMTI=XV3uTV};P^zo!BRa1nMZ`@LI@VQxz7yxMN|9sCC096HU z2|+==qNR1i&ZaVC+ll&%ybs~d(7N{x*r$42X(n!Cg+3$ECwfbv_!X`xL}XY*4iJ{w zWCEY1Xe|l`*+Qe|;WpFI59@6r|B1}fO=N!QcYU#HSFh#Fn!0U`0~(C1ZLJ;U)o%ad zKf6+J?aopVT1$#hD=qwn8fw#^z*~a8pc}K5Ii=`idt6REQbxayVaHmQDDV@dxCSIu zThLlI4Q|0H#70^%A!5Qn!6~UFNqsXmXyz*#zn#g%Vl|~VB%U>$g<{@ynFo|MlOWa? z2o1)o!)MJLMnXF~)};@8?FeBm!2E9A{pN3Z9$Zeo(&N=?`$!F(>BqLwO{i5Mz3URU z%zST(r{f(*ZKB|DX(3O!HFHWjoacH2E|*e4t1Qc$nV_GrMOYG3abVTR;9gpAY3&#R zcwvEkM%RFic`K+u3WOOPO9oH6{x8XByrlGiD|-YmQGn&8TyC8nmGaRay)!|5p-F1@ zA60J0I5ZG$H67O0w;BmwN|@ialgznzJx&cKcs~pv@soWi9}r_Fe|p8Q9&#e2!c#SH z+{V@v7{>y5JH>cV>6dM-+I74QqjB@0Z@=eO=>)u2SJ}-;PXm+n)fomca`Y10<>+&9 zr1!q3abHZuDt=4Jbd`HM8l8U#X-Yyf= zoF-qW5p~QU&)e=c_0c3{!oP)MEhnj=(%}8WpUD#=JPOA{u6iTr$VkH%Hl~a9W)f2N(dA z#ZLc)Q{&Eh!Ys@kT?!s)YcJYfjK0Np`%}Pc3&7o|SHq?h!X%LJ)^*p`!YZ8#9RUc@ zAW8F)l`zWdS1Gf*qI`sq6jG+a+Wqd#${vn#13)Bt@irbcZl%EcYc6RMeW!wS-Q$_B zi=Tyd9fz(Ai>^%SV&5^4Wb1+r;22OojRu^{@L32d>M1GJMlJ?@9|e*^Ee}68FOqR; z{;+l8zyi0;DUgq%N4F(U16O^XlKw5vjU3)_tnCPr!S)r%t2u8F0SeOuI$-F{groUjpy0ytGSaC#6>1W1thgcF773ZynzKseFe%I_i3} zF@MtloQjgn-14+yX#_sz-4k$&FCu{2OXA?M%m}TILz504J*3dJpqJStu01VHuo3}; zL>Xqv`zB|?5bWUDAeG1YA6012?hte)DjzB}q6d^8sdZa+G2qESEQLPk{`!lW6G!ix zyKeHj;xkiBxvCLDLpJ{G|J;@0=A6*LiZNFps_c5Bv54hDut8l^B}z1`Bs9@3HX49LC3v zO>I===#r~^csQIa#B(tPZ2W`_5COJp`La`uyeG_nqa#$Vs9yB(2^n5z^{SRpSrIk- zNaX7k42&pztUi-*{*5=?a_FAHt5MWB`NP=eD&0O=3HQ> zE%y}!LtCS&bM@$>DX191WOwshON|SQ>I<0^oOr9Exkg1UL?va6+2QM+1kcl_Oj&IN z02d}SjOjEloL+K6dv?9N_{njiFSEqQvL<}=$;>Q`O1q|4m`&0;zozKVT$!ddEH&|K z1AU?jR>>2Pm>p!f)-JxL{?xYfci)eB(i`lM%E;a9R7(2Tyn${ol4JJ!KX*ifj=I*Y zlz9gHJ`jlETT@EsmwD}Ol?O2aQ++}tu2k|#iOjnX<=@wAq|V`c5*$=~mVBBx1D20? zXQ~y)Q;st=u7rAb!t*W>JW5iLiYxxy5y&KITBK*>LelCrW-D^16Jd0@NoOIxgRv}m zJr(8_LY6`ljadSh1QRN_zspW)%4qqpQ-f&|jbOZ|ZqGeQ0*Azr<0Emc) z>ZGZ%t|;HLwba7X=H$O0y4y)b=$0JDNxlQ5z<_&sj%pKo^!HG`uk#5BWxDsH>`ZkG zJo#>RL7_R!6&scReJ*!v<`j{#>WFL9=9?q;iJVaJO2Ac}o|JobncQ5;EE?JPXK@!0 zR4lu-lR!I};Hf?|$;&W`yhPn5$M~cE{HxdL$_9OLJv9;SBPpqXDE=wZWg-nnG zw7=9B<0Jza`J8O@d{gHjT)82kp~bOMU%xHi33o6zC+I*R64l_012dsh-qFU@QJ6Y~ zlXt*Oxm|g);XbbB5Xt8b9a=M?MRd7(E~9BMfqJUfX)#Xisn07J9NXinPd0<{MFR`8 z!$-D2o+o;bgckXAL!%Y{zp*M1P^0j41~0kyg`85e-K2co^1E&+PhMWCpB&UF494%n zM(3n2m*J(FRERZ+J&$`7`PG*?Nw6hSn3*3#mth?PYYtV19}87OL^lWtp_^Fiw&MvQ z2b@XBUh1fx%$dcvJr+45$}p|9xWz%FJ)fwvra5~Vs4OSzNrZ3lj*B8Z!Y`3dO)>2)RhAu!Qv*n~n4XW~a&LfL!#HDz@he-D~cY}ZGOUL2hqs?S}W&1Rc? z$-Jx`q4IhJg+T2>K8EQmgW3-b4CZDW*7@}6Z9N6SHx%-mzGQd(7NR8eg2^KrQD^I` znwxvp?6R2eZ$ zd!Y6qX0zBBi9V%~HPp$^zJoCs8S-}Kkfv#T|3{7-o1UtN&FzZ#Jx z2&$3YMo6%oiTn9ZGx?=6`AQ-jS$NH$!tVU|AML_J+jwk_u!v5frD1nVyAWlyyK#Bb z*woBeNm74A>_7wBGK0bbtDE!UuSAr_U49%x%g5bGo-o*7SEr}YrapgcGa4~xvt9j2 z+pmk2Axae!vF<5bMW2$JOMPxRo(hG=H8&+U*I94Eg&=Tm0Fbz@JXmTh4729A7Rnj@ z@}3kLH60a_GWKgI6eM@YCpU+$;waofRbHcn&X=y`UR>QDfTLjXzVxvn79Z8pah9eW z5-jVpM9laES1C5Of-GkVz+`64tj>*bvG>8)U!maG|VT0veLEh72CM%yW) zxKur8PACdev>swo0m6D0H!7$cIVPLQS51JZT2imarY<^QOsB=;;KNw|r0&YOh*i#g zSKlUmtEblcap}o;vtF01t09is>Uh)gU+f-jBW2KcoU#MxHC^NK&p+7mIigrtgkCtR zet9_VnH_t+o#~c(deO`W*ZUm6j@Mv?ZS9na^53}2D7;TvS)IH-YSX)MYJ%*{vb|Hq zO`k~&8E&|$vZn@*iN#YE++jL8IAUMwgV?kE6B%Y_UqdqVi@A4V70BWo{WsY-{o|;` z6tukGoA?8NEjtAEwc&=LZ}YjkV?k#W_6wJuS}-u}BZ8keyU>?8R8JSj$iCZs)I4|t z`!jr7rm=-gG+Cdr%fjmvsSqb%RFV+G?Ft%$pt4uF+b4rt7z7?5wXEo}5fIIl1S}f7 z4iP*Je5-5}s?^v>C^}XMs?0W>-LVNarmz5Z`jnPuS9V?o0|I_7bpXvs)_EclsJt;P zeuj>94~j5GY$9RS` z4?xv}A9w}_saV9i4Wq<_kTb;^-?TnlmQ%9@zNu+RFMvk45M3_*OqfxcLDD5-Nzufs|-e6P)|>bwn!7 zqy6R#-M8k-Ln1n@uT8X&mBfhgk3*+Y4}T*{^3`D68Kx+k{yPFw z%ZK2{9YDFd9tcc!6|CK@TuedwCbD!W4&#c@_RP9_O2#g?ti2>9X8q z!k^Oguh%CsKSBZ5s_vd_XeR&%(XM!1k1zrS#`Q~kBcGH~Yg*BVQ*Oi8jh;Rk6SNU} zk5DP5Lh3F@QT)w})#Bls;SVOTsr;ssW?}nR*fs2Bw?}i1ZaqW3@RXTSwmbcy>#I+> zF?OeA+eA$7OGOZa6~0Ruk=0*Tq|Xk6+sIPS>3L!NlBLr`KUF1Yr({h|Rd_9uCzx~? zwY90g$NQorjy}I|pzRDM(s&VHyEr1v=UD`pL`$gUsn3cFlziv34)gp^oD;$hDo!o? z5A9M9&Im}IstuhR*AIKG{viDHUz?3$P6bqxCyOfRT(?K$HEkP`lN)gK(Z&`%-2rTx z0_fe5g&^TbCngea*4U@T*yGYq>bH{Ny_Mu{B+o^3Zi+*ZD=E?;5@0H(K@U{9*dq93 zM!*_GF{8|lJKMr!(;!QM{A2S3ZzImC9{rQL^1`rMt05%U0WW!JLOH<|N|zij$C~ud znQlQ)o~(@AH9~)R#Hux8e@iFh4S_R}KV9Lo)V&%Pg;EuA=o|-IeoAn1rf)YgSGrbv zd+;LtcYFhlpn)GvABkde%WiM_jj^Cx-$Rn2TK}73sio`V9gIK{k+%MD;Pyd zEO>;Lsqcqj=lQ1?(=F!5bIUSg001VJA5O)BkQeyN$dp_eA*)D?&B%5#2D1u%b4g1U z&RG@#dn`)M$PBNV5&2&$H=Pcz@wNtrmfkvN8a7&k6^bOrr1GOYg+s{BL)Qkek-!jQ zJ8L|nfnUftJ~`IPy1>P{h41M6mJXz2E>d40jUe)*J1LuH@2Y^9o@mj2MHBgq#EtK2 z>;l-(0pZ%!d4v~W~Bd&dco&o8j|Nof7FrbTi>B{h{YlC9PI$fuDgEiw_8 z1c(b~J!{WEh*NxHeL%V=0n8s>-F&g=PxZ^~XRy-KwCf=mYv)(_RH#~Zy`Zk9@P;9@ zjnT6VSdNFTlujHkL`j!ERNqpeqLPI7bH<=IQ@k1PBR#z*;`CvG%h7*~>7D6Rj*18h z?@bPVhso!M7pW)ClF&q;M1ujy(28>_Ix=9I8zp%@A_IbGQ@kt_mTzQAd^a^G9u=!; z$VC281Zqnn#!GW%sD(a~ohw$M?dz|C2Rwn6F($%$kE$hxds|iBcl0@c*%(yw6_SwzV*c zY8!j+J)0OYYExA;VsEv@ti35p(NcTwS)*DMHM?|atG>M7^Cu+dxu5%-b6vlyN!={^ z*@uzcwNGU#?Gqg9pE?yk{ECTZW@;~KoLjXS_fTTc0YtqmKI&UXH&HwtFJ29}e=p7P zL|oo~24kJf##DTiee;ELWr+TNhv^>z`7v(6G(~^>f%b;iE#4-$U!roedn~RWj_mDh z@x1v^RfZA3XrgC3y<$ZNay+8q_S{$NQq?q;*5qa|XVnliIhp=rY4z9Tz435+3^x=y$HArH<$8*LG)a;bXpA zis2PX`ie{n76x1ZKeZ?wbO22~bX7_Lqc({>r)5ahvgV~`Q6ZGSuuN1?$R%8iCq>#E z3z2mSD~DUP;wFlw3MUj(Nzo%O6OmqCLt47p67eFmquaq<@|;gb<&&bn7?%%xfk?Gx ziODMQIk(__Z#dxN;!gEPb(ms!F+W0%7j#A^tIslG;)%g)ktP$N{nO*GzGq(New&33 zooC?9OLpJC*qo^j!goiw9E>*zFXcac<2RYZDX|ig^x)CAfbIP#<#L$|lK}jBr{nDc zeu*^dW&jzuAIwX!EdpavkA4ziIHTpOVrp26IBWpojmXH=rL_VwX(q--LqY~lJy^`6 zhv0ElVui63p3N^kJoX~bl}&Y;@2fhyCk;l0&QjNX|J_gxwN zQv;a0K&ah?x)YbG^+k#_iX3_T;*u$z(i4l&SR-7bGD%3MC=p@{2cwpfeP0)%=i+y@ z{YO@={cfSi?WFL&9JCPYzIu393#2z!KZ4bIxOp#=I3yg-kG9OU48e0`Eh+~r9?J!> zT=)5~%iP+n&UNVj*3#Qx6uGnh!s~~)p(4IA`Eg@XC7Fb4+NuF(wV_0QK}iQ!hg6)& zUwMZa@ZaYGcZ1rlhQhYOaHOnHQpJ5FP#8MSEfF2vocFs)fXsN#;#B31X#kILZr!Vv zesJZaIxJzBt0yA#li=>c#SwWIBfi7hIec%g{4K-FD?|Tw^)9`jp64Uhq2;HxpUg|+ zywy(M9I{7llqGdYhXO5Tx!&GsY$p@39O0KrJB__^jEkk<_Bn zF01ak^3Wu?KqTua2S0=C5Lbekm;}4r>ku+sH8W?;N2 zLMDR(z*DZu#*gHN)}FYOtAGdf9Vgp0JvcKouv9kh?$K3Vu9g2N%w}sPzsc!aulXj? zENF?6P%rO!+gjYOINs62%L~(3R)ih{wg)XL595vqQ^KD@Y!$yMRW;F3yJ!^=JY5z) zefyxh`}J8Yi|NBKaFVVz7!LsWq5$-T-aeV-k1>$tF!Y|9CWu1asmR8Iyg@|>Gq=h~2dfl}H zN8v!a!HMrNG_?){6!U*buN?yQI~Vn*|F?~g32u5W}pfHp->VgdmC*KLOU@?+uhb?w3 zAD6dK+t^a^!zvgD|H{poV#B7y*mEdNwSZvL*aFUbYdz*^8ZBRbXzZ%HzF)iDq`_Ak6+?k!69=fkyPV#0W}d2>C9BYu#S5m)k0`5wa?=X)WEc}oM0#aD&Jed@H6 z54dAz#>I5e#Sc%7mVS7jh2VX=Hx~cmQ?~lcWN@6Dw zbzt*%ahp)-LplFnbZi3Yn8%7&>=Ediybq81oRk#r{@Z$GYzmaF7n6&5b_}5D!2kPq z_JzGer6rsyvP(nFE0fIf>U{3XIwR_)>pPNK2xjfH@HjY;maQUzFqK@f!oB zykN|gyaOx^Wn-(!p3m%r`}zOWh+0f}+s?Ad6Ku(mm@HPFQ=f}>sqwhmRnRMwkR4g2 zwwlK}G-7gCE`Lq`^`YL_%cWKccP<8*n)*L;9Ma~2S+^tN$xoUWmWG{{{NZ1|iZkn9 zgz3K2Y344UkbEd{=&>=wXd4x9v+bG=ob=%mGg6qWD^rNyhb1ACPtq;XZQ}cr+MQ=U zM?Hq@9|h)tlmrN=(*;IpP)UWK_iXCOUTm9rHLNwx?FzLqzrz~0@}OsMUxvF)PVX>* z`&soo-u>FHJl~JpbA?U7tjNI9Dr3|mM*T-BGAin`1c3l13HL238luod=zSP+f~rhJ znnIT0yMqE`CPh8Hm4UA!+FZ_#(F`GP-vs6|z+af4eye}GQcE_e(*`4MEA{!uRfu!t z8oydZZqwZsXVMw!_h<9^!G-ko+NudonKpT zmdi1PW`B|Tw>QuKrQYBD@6cWYP;@w%{jmxm8mLW#V~;AW1$;=5lZ!G??BT8SZL@k& zu2pug!TQU0|v-*b2L+WhnBp4%EpIkFc64->nLLy&qX;f-Q^>OJDvHq!M(C2=FW9z6B z6H`;ZNe-ja%!t)x+=I+p4q@aDh00>jl-pfJ=HgzC=R6`BmJB_kbWE*j!H!^bWMq|b8*xPZ0xB)O6G|DN5(TSd zX$cwU`nXNLvgQ80)%EkgiX)9oRY{N&ALn3`y$v6%XC8avW9_qEsU26QI;F2|oI3Lq ziE;e}b#qE=K&k;p<9WCA;wYTxazCZ2T!JL^r>ZUf-A}Lojs!$~a{$(ZYXh2-6PJ0& z;CAFu{j02U#dZ$_N{6MJ(K!KbVT{`e_lepbtGe$n97 zFycXkf1A8-L+l29W)7$I`RXd;E&fFIj7I0~8bZJT~U z?ekhBhl%lz>Wb-gbVtbr@6ZSrLnU8KsW@pmI*w~>y3uMTA>y<(;(u_rC1_plpOmNk z%11Gwguik*t*5aLWFRlo+N2*AZr3f=^E~1uS^WuVy}Y5fq^69SS0!V(DMkwjOiX%BZr=4c+bwB)N=lp_8{79QUHBzzJ<--v$tFA|g z_$`&yz<|3z^Yu(;Pngfp);5o*R*=+B+fO#n`))hD9ku$c@~+|iE!hE=x4h=WnXlAA zvWp0-c;$ch&^7Ug1?vLry)AzWu2pxS)0hnYxP^KhPVq)3Acx}JBh@owP0zOl#igfd zr)K>DpjauCB$N8PX=*E(7SGe)6+D0eQ76TyX=)18MeWEA86$OEBIGNUL{D?r!SH_b z6#qtNE!`Vd=y8*g5SnX0bK@6nlD3&mF()*Q>Zn6A3l&oAXdxY$txyUU4OX*Rl71$TwT>V7BF@vB5; z*`4g>)lu|ZF=L&Le3SMT}3 zQGG|q_ZN($F{yANEbhDV>|;Yo5&qr{IJ*GK=m(r!cw2wVT!>C7UDgY`pM_*17ho=;cdJ=a0ejUQB;y`^Ou7R9C$R1FGMx z*Vz|%1K%r7Tz_cq!n)C@Xv-80}DN&*?Pzj>$eSd=+Gx>w`r5Z>Vv zL#a@XXKmiKHmROU!4-+~pTwH;4)@Q_Qd{BmT36rsQ_>xDsusfrIu%lue`mbcxEJ1k z)j9HAyPml4EAYpi%^$xc2PN=l#TzHJ0NMu;y$@(x`59s|M22$-oP33HGVfn84YpY) zk8dO)Ld|?mz3cJChs0e5&TdIT4vI9l!65kr`MH&>R%#$o`^() zCZM^2E#!%?OdEd4kZKIOd3CmEI*fA;N)fH~pix8`?0(JC2*m?f+=91glNo725bOaN zzKKRgDr6a+oC40Qy+Hcu)b}@< z7=PzxKj6-CcU>L1A|vC=KIhef2gm06}oc>b%!& zNOQqhaTTdMZXGydl}__wl?{!4*}|W!XHsf%;*;?A^xk*mf4iUXtB7p(+ulnCf}h2- ztJ$fHAXQXAV4OHCe_Ce~1gh2~CxT7HX#IyVWPlU~KW8pLIGsK_tdbl+K2(lC#W1JW zE&;0*OSqZ7r4aK#WpcF)|dG%OKH`V$I>nEG>C` z)ZUb2t%78Quv|{J^z6 z!ljMaeWT$|kkJ~m743$5AuO!YCkhVHF4@gxB10TT@keF4)|GLnsii0x{`;>3Jz`@d zDfhF*j%>ehCEuR^TlTWEF~@sID*M^zH}vEUZ7Wq)Rxl#%>v+YJrb2#^EU)|_KcgRR z1#aZYy)S=(KsO3D9u;W`|59VorD!g!Hv$ky?K$BX8yNK35i7fz4LWM(RkH__2i5mc`r zM&cVk)(S_Tb5985Pu;(-DqN|@WnjrV3?MmS?=K&jiQ)1nuQBanG?L}GaOQo9&l-X~ zw981glo$^Tdr?sk>}Q62n)#3;Mpo{#f4!-Z(iTiwf4ciU3}TTLs#3c+9HsG{nNB`O zaf)5}34V5KEj8av`ZB1&+8y$D)@($FJ>Z$mJM>8tOHP7Lp~Cx8t>T~@dnp=&$Aeal z{z$Q83M~7SH`|06nec8&R zgBZSb_X9^lvEA>FpKPp;Hm1+b?6SX0VG~X?O@?!}nk)uGh|_f4zgc#pnPZt}VtN2P zKlP9MeOn|d$#%nQ!e~O(a_?#Z7<)uYW5t>cyaWa179Tx{1sw1@f>;4?vXtmp!2IYM zrf?ddPNH(KYtebK=T&)he*qu=(XN_FB;+83)n5T`=vT2X3+!GGi3X~xJDt^# z0C=vn6-qPZI1R`QMgK>gm=eQT%Kz>Op9$o@?f)~Qgj~a}{{zxM*uBE!&-N2{C{hpF zZ&o&5`C(L%J(qx&;V;+&+Z^z`D63^(Cu>;$1aCPOm#mt?sUgG44MA8}@FxFIQ#W?_ zyhnG?vu`xiIFl#;MI(T%?W&A7hMx#*IoO#H(^8a^ zmK7{Tl*lEs=F*b>!y*p{z5Q>MhVqJ!7%Gq9jp8@+dyX}D?Ye~oZy5ufFUN>6-|EJi zj6X2v=VR&&7CB5k_E;RcO}214U3u@=6>Tb?m>p_34NYZyMDz1$b%;*UJVg=8dxoc9 zz1;=?tYR@Vz8Pg&ttr82vauOy#e(Hn=@wvQ_yLic#H6?+3;cMLr z%F;<9Myi6c{=NTuf&eOK98f2O_^(GHnSIr82KR`L!P?I3eM)*c@YH0*rv2Ds^`{@g z@{*K3th~*V!*^4bLsxd~`&YOV3a+)r%ZP51H|RSy)rnpwcaR*b3^tY|^ZMv92C?3< z<~Xek-uu$~MApr9dGl8)=;>ZEHQmZd!Yi6z+T(nsoh6!T{I<`jY$z_&q$nF_RZRy0 z)IoF*t(NFF$>k{&@fxfeFpAX8E5oYSS63e$t)BHXXVXKU=m3`AtIPMUD&eBF7u*k? zT!+6&^28v)2?`fz?d6!j90XwSF?_s$4iX*hgoy?N)s-CyDJ{Ne(`3M8oOoRpt4i>K zC_^np93`bYg=ere#7c#k_>a=qZ$No0zaUA-%sRtT3f~?3}Qvp4Gol+wUsg28oDbB5(EmepM71MPY!q16A-OQssj6 zjC^TXJ$5MU3`((;Oc7$}15+1HPER>9a)Y}v#yDMw3aw9%*4N4LI5s(Fc7hUitY*^+ zuQEQZY$}mH6Ac8)iVa2q|HBsU5@>EY>w5)YXsk~YpEex=MY{8qFJ>4)SDYWNe(b9@6C=D!NztP`OL#F_}X385q zjdTK}AA)X=N8i0xQD&{N<_57IiSiof+Ntn|)-R#g7MP^=^ah93rSA>%q^udm2!^$Q zs0uiJwK&Um%~Nemx<0_3hXjPX4AnS>;SW^9H^KPXA?tXmXLl##mwgx7% zm5GED!Yc%salxsubE}lG1g&ipYj(@gc-$U_=^#YlrZ#veRsM3aneBA4W~YE!^v7=g z2ZySYH=iVebYU<4c1|-iy~?8X+D_LHbak>`Zwi+J^tU!xPx|IqcJu=zu^|9SUJy)M zLYyU&ivB2V=c6o!dnKvoi?&-9QOoQyZxA`{uMq4$7FL-R#FUAEFCAO71#(aw>Bj! ztSXdE&T&o4dKc!-8O2P|qqEA%qsAlJTRgOD1WgEJKmeQWO)LP$08F9*ug|?)jp(Vd;#dAlPG)uXf`FcIeED#5#o6q! zBGdwaa-FJ1uG$_Dx&-i z3qf%Rke!A{#D5f65XhPzFsudufmAi@NXsG6G#Z4?-yX!AQ-c=}qv`Lhn4r{b>Lz7> zIc~~N%JmCovDQKHT&&j7=?E-2hdQ>R?!|gkRmpWi5lDm!{#lHrvJsSFeE&rZCQ8@H zM&>7_b_IIhAOS+F9P^Wf*=!q0MPfX&)4ad&${GVnx@!Zn8;EW|tE!)&63ra~Osehu zIU8zr*+tS2%~R4%ZwJg| zOC7aG$2%W6%D?a`#afbq4<#0|W7Zm_!Qu$!b&S3itzFFncF`x(Wc`u{cNA}}RKpu3 z)5B5`U_H+PYO!P`AUSTBH|vG8xddmsi19igo)zt^!p~gyO(lnlk&LdIanE9j+05tu@SXPc|;M3!R_$+YMz1&>QA zeNrC9e`kUZfV$nqn1nKgVVy+o%p9h3DW{rWP6H5Y2?F#T1TYn0=6&kchtY~(tc(*J zzvVEW3Xd;Uia&Hr9H)x;Vd;J)I1VRF@y%@pUn;IRiH)d;cG?7sl=oSFW>Ul_1v6?{ zQFm0I3yGg|y75s?UvuOq-$>nPf0JuB<@f49WxL8dT``$5;xZBnj4+CIy0tj&zU2a2 z)RdM6MGu8j^s7^TQ3a8@6aejA=65D~q3paVD5khjm@9Jp)DF-J%L)$U7*+5!MZy$+ zI^{^*e=BvHc}iKHmzu<1pg7IZ@#^odbd*`l7E>w=NRX`|J&C0MP|Vx`S7EPE~}_VrZ*}k zy)}bEZv5FwHuKxax2T@|aaaDO?`6$#oau(5+`HFqp65A!lcuiCCwCeQ9Z>(K(c{h1 z^EX7txjx{bS&NE>E6L{GIFa}!XHw=f@To#@Lb1xYDJ($7ytRxUEImNZ4C7SZk5B~* zwB)Y#h`7g>p{mmSpYfJrCv*nN=W+o6^*AR08J1;&F+UprI+&E!9lb!L&~}dQfHGmL9P5#8@coDvCG^*sVo5mB+^6pwmyqXe@kl-KnknW6NhZ044mxdU$BOfIneG z&rt8iQCN=Zbr=7bV`sb0vWcIo(Na*)lYN6NUMAZJ${P%|Io44`ebnsWkHZ*EO_y{1 zPpRR3A$U&8MkDh{iRZn2#77!kL$6o=KBnK_xHEr6TdYfe~k4Zx|F#R^Em>5`;ANv^GGmPgo%F}+SB8l8g zRe}vQ5@*jX3LVI~Dw<**zPQ*172H^~y9wpS|e2_{5@f zkazFS75?WlVf3rU$%cqeuezKJzD+)i7R>20FlHo{zS-xA?_Oi@~fi-dp)Vn+S+1OWASi=)Hz z<%I`a&DyXMgsD`SKmX>iC5d^$^p)mzlz|WHAx6~Hl1PE?@}>4|SxNVBPGFRJM&5r4 z&tXzp8sP|!!Dfk+PE?*Rh|GcIZEKWHzhB?DR$s3`V6*c&I4Y{wbqDc&#zrxUOHazDt0kkE@mNXH4J)hnJ z4({nH{?|k<5h%DxR6I|IaY3NS zaMxU!-J-!C!+ORZm8!v;299UsE2A#wkfcfzz6N{ogds!Jx>iUrm1&Z(*yOw5XH;ka z-jtL#9mH*(TE(ghJCLwFtj0Rhwbl) z)xWjp5zXkeSHT(kN9f6xy0j^+lN#?py92?iH|$j*8>B#i7TY&r0e!g;nYXt>L)AQu zhC(731E86PPp?K~NQjp2ru#OG6OF=mYj58#-k}d&Ahy1#Xm@d;eRsbVpg{T^WI!5K zQxT7s`&5+8L+zqqbscLDwQAWh63Yn+0n51;OyMIxYOeN>w{NdZ+ZYZ=iz03;;lY%4O%5jj#(s;A~mRHkf zt&yfnV*9!m9dK>dl|6db1PhjOF38;fZ)~qy+ZeoS2ILO0n&v3`?T-RLxwiMV6R;5!H4kdK^rp4m~ z`25R`sbuHqB6L5Z_Y1FEj0`TSs0GS=$0qYF8+Ke>G5_klbH$Nw5#K(xYFAMk@q0Kx z9Qk|~o4|Cw(`u{Gke z3{xoS*7hdDloe5rU~|lAjpLGJ-vOw^JAu=Jh4sp&Zf?#9^0N{0a(3ZSzKkm9aK8t5 zWHgm0eGY*GLn`%_MFi&PU zg%hW<6h+4aR;Hq*lEO66+*L!_51)Sko>Iya-Rk@eMw7IbCH{C91pr+iP1(%66D_-A z(Nde^+xPBjznuBr;scl&nP&lbMMWTcz|-m2o>nJXkYSv^)MDyGW1 za(L&zirXSkymT=CWA*5_%R&7etRYE0l4yJ85?|IxMD}pKGm zW@_8jdOa{TUtII`]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 <69>{7l*LfQM03_Qylr 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%0A+=yt zfmDf*_bW*ho{ObXX>7gXi!Bw3S~zGBQ1)L%;M>T+x{gKPr%;Q&0SVEWXC}-1Pn%V_ zs)b9TtA#_)L280e)33!!(h?S% zeHqjup^+}p`0@NTo4Ne=Ir6`)9dCfKvGF-%CA?`~>5wgwMT~c6J{HM+|Mgt62#Kx# z62C|9RqgTg+=(SWrTRY4p+qvz3MsTPhSxJt2%s%R$q~AseIW^BNV(oa@{tJUNRomRl*47Ady@U{f zxVR=0puYj|DW0ouQZK?mlNh96BQ*kYd=@Yj`IaUbM!pysx}T&jI}X2|{@3o9tcKK7 z-FYF0A6E{MbH)i@>hoeOQMJbm8Uac*m%+B|p&dUGULO(p*HKkQ^uTQ{@bK9%N{!JEW1U4)b-J`#;roj6nKe}Z8s|M3 zs$w5!M-$QdaL)X8cSc#AG(Txd6BD}`eAmxqf+ehb#|=_%gbS2iXpy%xBuUV{lcJn^ zmP#-wMB~RFGYlT7u$w65oq8L&pQ)eiSoZq&wS+)dApz~y3b|=A{tUdve3qmZ%c@d` zlg@@}^I}z*H1Wnt(8SPgsu&G2sdkK}gR|=kq%D;Zc`mZ{uyuk38aZVvQf$!T;^I?F zd8q1@0^DKE6<0C8{Js@!?i%XkQ)kV+L{g;^KRp}qe2ED_?+u*m>lmr{81aAYC4y21 zX7 zPB)J_Ns^-l~Q?a%hQx5{IDCq$l z-jqQ%D);{2XG$UL+l2OOhi6fuht*F>b&AKx)}!saM|2~R5$tAKCZ^@GiV@L*v*R#9 z8Q^XdguFm1nbHVUde}^?>as=ess7T33y(}nAyqozYDd8aZx^Y?oWw3;d1yi1&Hjtu z$lzUkbYy_288e+y{=j3Dn)2=uY$=Bt5|m`y{j21$`Io&yv9vIVf%0oRPw=(W%*4k; z`?JF8>&tPL=Bc;oPj{($ZqnO-^iYG}xw#f~H@BY&aDjLA3`T-hPPps2{~^;Y1SJSn z2?CBjN~3ORu1A(MLNTyQxs(VRBG;$5+HEjD&AVKaUaPKB3bZIg5fS0}Y74*c)spO5 zoroRgJ?J7<+`4WD0H7@mIAnDhQLypCrRCrtSGZkHO}6HBz;lf^%cw|zgySh*yv(k3 zI3$|H?R!u{V>58UCQ@l>&r%9?d-_{r zjfK~TH#6h6;I|rS%bo)N6;GFxPDuL{ zuSjIEq!1XoA!?1E!+}v#7tg{00IZ^-T~pqRhLm(GV*4F4x&alyORVGQ`b2g*Niyb{ zSMax7H<-^gK5+kOtK4^LWg^n@P=K^>;1rjic^x?>N&E|UXyfl~)`VZNURMe-N2-FR zq!=~rf%JwjMRXE7qlD$?vXh80)#0HKl2*SDR2*WJu8+rKnI1MeWjao)lV|ZA?{lv2 zTga$$uEn#0**L zt$phpFq-mXE^sU8CpVF&PYprMo{`AQAJwVzWo=|p4bAV8As%$C{T`l
  • -ItJ4&y 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

    3VQ9v5yaO+c{ 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�*xi~@6Pp! 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�I7G^USWjNliG&D6G%WNyocfaFj^C*9h}L<& ztr@3KkX}(1dP+K+>wv9U{Rs#EMh_O*jC$2*b3w0&Uyp4dc9s#IQT`ign9c)KmRgmI!s;Mi-S z{{EZD=Fot45)P^EB&h*a=Qqyb_q~`N77eFyn%WcelW!2q4W_lntGnU9g7E|r=< zp&fQO!!g7_W;)3L4iH(}g5&%*B`@4Fks6%Z;T||YT-voOGy$Lqa=_8W-IB~3Jn_J? z$H$NiLXa#x0!Fm2^1xtIF2uCya~ya9rJq;Vp%JyTXdR*s$=g>Zr}{X{Rp6Gj+3GD6 z*z1@TY`r`;1n?vV%aQ%-F|Q?Q3;2|Pb^AIpuiiVJWtd9>Df5cfs;bNEK+>{W)?OK) z2PZ3O${iCVy%L6k1!)TxSO4gj@Gu#0gRN7F0JYE&Q}z_De2oiynKZE2l_=U2*^Mm#z$mmKB?XFZ`x`^F|D{*Mzq7e_v4+jN6zB$suk<0WEdjF zsKQ?aluK0NS=WpaIl5LVa0`tgzo!jg1DMW&rhl1!Xc{ietlt~VAQJ|WXGEnSrY+&> zU>8tBBo2`Ze#QOSA8Vhl`uid0X~jx7qi{1>9=}mieiYq5Cm=5X5nmHU{?$rtSm)rs ze$N~LQsk`P^Jel7y$TZ*;y%QVGF9u&IoAf;ra0yzT%y@ZWkyW%vsB~P z&*8~@{}%gL9z)}F7xDOy4w4)T*Tk^%hvb>}ex>GK#(@{R`gL1rR|?#xK;$3CA82a0 z2x)zbPH#E8`*gVPv}~`)Ny#!n?pt6T9e;qsD38#{0p@XER3xpe$w?o6$7FXuve+gK zl_fGmv+41M^`2SUuZ4l@C*m!q%(3KKUB5zjDKsDvayEWIQ$V801`iI9yFD@Pl1}+q zke&*8tf`ORl&iGGpE|xE#B&u)!hxM9Q3eJk$bD=RL63o5O;92^()ib%>;sUxykKmCaNVue4-fVQRf)OR7Yd zy4n5NA*u6@H0JDB^~Pzl=pD|dmTQ%Lzskox5^QPjn+3UO7*}lDp9*Nv#dufVe{q#8 zGbO(0aHT_E@i{1I#_9g1hk>`}T8Nv0;@0aabyq(JEwU0DHXysw?bsHH;S5@S8W7lH zi8x-LJ`L}Q24UK~fWHki3A8^lub=m1mMNF3^5TDjB`%l#gvee{69_a>q@cNFZCMul zN4Y2Xqt%X&_=!IJBn%*hBh({OabT9N!5(912i8Y#+H&< zPOwOSLo&En4H(Zy=VpZNn!O;ysFIb@O_bKQ7d)xM@5}N%XPR5lIj}2LgFRcTGjjf& zn7H_n`q1|}e4q!~Xpk*sqxX_;%E!v>efzhXltC2(npqW7(uWV_b-*X3Z%lfkIr68z z-o^iHLGxLxc<#bgP4Azcp^Lt(cHm`4@iFfNes$N;^95W7j72PQ5OxhW%eU6uhXl`n z5|=*!5@koTM}`)%QfdO!05=v^nnbl%pH4rK(ePiRpT)!>MsOqyAB5giW};*V8lw2F z#PV4cf@;S5{aH0467&)=3d+G(V-#SG1m#m@y~xJBIwt^-j_@?es2ne7lEX zW|c#}swFeK65FL%X=YR_W2hy%f1F;kjsM-S-jO$-6N4m=dAMfY@pt&?*7|+ojL`N_ zSBD*M*@Mr+P!<+eTKy92sqq;UO`WTY1K%bfp1fbjJPJhk8c)kEHGRBJCn+IDM&3A(1HN~rRaBnh1td+%qS%hF(##dSFVN} zyiAakw@HANr+7fw%5R{745UfVbuKa}#tsO{q5@d*g zzxj>mt#Ku-xd;0<8J$7wk9=RTyijX!A8lo-H8bX4JU{%7&+!Z8Tz{`Q_6EUj9{XP( zW&@x(?`Y_q9~NSnyn!bhOSYm>dT+nSq83>Z>W=^MQTpqL7LFW&Di1HQS<#OFiZ6brQG*BiltZcu z$M*pTfWp={Ue>&`uC!f?*QTh3=mOz&ms?fZv3lOziJ1oMISD#AT2pj(seDqGiQD#K zbIl%K4x}g3@{WMr@7_JFowVz?lNh0mVn*`ke0J8Y5hylz zJR{YLLLHxze<^3c^b{NDOFHXU#+i=9x_Z0U8pR^6v^9b`6h7p<8{WR6UB`Ki>9J4N z@HC(5P1>dD2K0&v;JT6Pp49dk)4B>HzuS~j{M!}I?g3qMQ=r-5Z>$!Mn25f8I;)XPWXKSz11 z$;To}QT(_5;c8x7x8f_JG=a~`0btJ;JEo9m(#p|PT((y=xqJ6e)MDfr48;;(uJve( zUDZ3YEEA-4eae4wCS4y!@%OlOxTY#t`(@n2&8mM{u4Li_t&?DZq^e#QpPBhbefVHJ z)42o_@%(B>fxn-QtcXr%A$(q}e$M~cMk6BsyY`D+-cY2=Nf0B*>!jzy_usEx`LwIf zzFYrc%5QRH^KmikgetJ!{nHnVsu)M3gcmaMK{lU@w4(pJ)oYm(4FRTnk%^H1a?d6} z+T3aWG%xIz$N=OCRF0UDKpbmu{Ip|8bkqrZqn8u`G_`5!2MeSu?Pdel9bzAti&A4z z6b}fg+Go-+65v2K?6mUTu`|YuT91SYv7Vr;OedkDkbb8E@#hPFA$B@y8G#0}=cG~NMjnvK;Ruy(f zO<@Bm!~f zcvN?$l#uA>B=%ITuvbDQ+TenS$ooi6az!FPJfPP01!;1=qK+UlE34Ov2?5-;_AlLG zf|hPS$E3?o_#sM&kXt~u1~ZO84h3j8PNjqSm=6Fh0RZS}f2VTi!INc$4W;|XfvhA_ z>~41=c__(uFzEwm>?p3O9{?US;v3(=z$v)+_{2D1y-a^BX(9@Z$^4I|X7?4SpvCCFLwjg`>5N1U+xBf1n!D@r|K*-zfONOx zoOf5~A4c5oVz3;Y+nr>&_ICi3R`gzGC4e}3uFK1Ak5?9sFcnJ&vmkn5-jBOP=9H2j zgJ98Syyun(E`CYtrFAqr#sbvf+Rk{{DqA7Yg%8_FZesrF1R6yjiXR z@{0pF2XK$Or*RAz)(buT;U9cb0ATwthJXzEpn<~CN~r&SClBe@CAR;GNArCJO zIypP=xQU}35Y`Ts;VxESXPQBI=R6*7Bo!$_ohJ_}gd|9vzz4OUriuemDZ{Yg*g1JP zg33wTjj!9CQ`dAPGICV4MstP3sdQAw!P%{HtlVXo2jO8G&Bo}z+%%*L62YkpT1&N63){%$ZAXYYpm%UES{_`jKu&Jc4#;YSk-k(xFcsUkf zrZU)uQS!aqiKRquhiD(Mwm3R*aAfMcpnb;_jGLn^zRVjS@tDE zI)D~Y!2tsRC`o_xW5K3SmZn4*Q84;(VqJb!~z|7&1f;mA{57VibS;K%{U zfPMf#peRG*_h+0=tps<6AQnpm2C{qBQILs?EkqMjJt|Ry0Eu9u4iK|e1`6?Sf#W|q zVV=p^z{Wgbg&Tc+-`0{I6#%$)H7lm+|K(Owb~=*~Tf{pO((8`V&iv+S87 z1ZC8*izKUI{}e-Zn~a~`Nnc6WSfgJ4UW)3Qtt)}t;Oo8%dhfUw2LI%oKj6RN(mOe* zeQA#IN+)f5Dt>J?T!2IjA+Q0!Wf9EUVLWb}6Q;=dNP8XxE%D5p^~k$L-bu=l^r(Mc z%|TpSQJCoZ)823RzZoKQe*Y{lS^`l{DQN>%dy3bF@(|NC`QpIJK!7NID4U2nS`C?; z0>nioQrP2vAy7~NCQ_Xo2DdRhdARK zNMJxHcxZ<<5{5+egZuyjf$vw5zlbc$@pC_V_TWPK+}Hh zX{%{UVkDr6ld->&j;YY^xuXkB7vxYjgO&-2+D&>&raevpFjE1>$xA!AfJvjH`c*D< z?}+WNXPHQGOWFF-U}O`RSR^~Ch+Rp(lcf(t5A~0LDly_C>|Ok5Fx5MwZ(tY|9Th)} zfF#fJlL|3@I~{qbJ`W4^WBg2XA0R_KI)?1$BadQ=+gK_aUWhQMXSPF;u!B^XepdJw zxKf!m2@66oSKcju6`S4p8=AFZe@49fv1qzCnw2kV!8zP|RN`K-?6zoSs?qmA_s^dh zAxewhhkQP_Je7B!@k_21BS#%?FTN1#m*Fo{_OsFMTgdUhh^Lgh|IY4e;}!nk?98fJ zL05p=T+L`R;_S&w>xXaBxF(Y%*WAkKm8lXONC0iMv1SX6 zsrWM|d%kF0=>8ms42Nna&%8?2s{u{3l1>gw(4-R4J4y_!Xc^bUI~XOEZVZhzzy4@d z;$0N;Bw&DDn~#(V06j%aKVcY(bc`Hlk%^9+)3-K?6|Bf(?lQf}Hpm9KO-6qT(x1 z8(u$blLxw+;RoLOka;Ajo-Ual8(<=th!NL6s5by(k+l+wA&OltdsXx{D0R(Uc+!OX zY5PeSE$U{qwHTiPx*$_^!SxYB5}(%c-@3X;OeMhZ;!ps%g8}kDLBQk|Yc(L|C2$~6 zSM=b?;dxJA?kIJs?RH%q*P8=fv)SQ4*9`hHp9B@eYp?GB{uc?g%O=*m%d zWzjXvsv3E3duH9+UZNVE$j+N9p=o0M=yne+%b&0%%8_o0QE!b{u^TGApS3IALQI42 zq^X!w_uvJ`?RoW~%DJw_En2Zp^F2E>|nHDY=9)o*La|QoqXg za81c;CBEwOXS??DhMD^AuRjuPUrzXbHxF(AYQ+Yz1B{KwW`bV&1W=+WW%J~UXdM7~ zWIQQoBiVE{a)5Sz3>eHa4UAg9D0xF^#3M+*&o?SXy*hlAQ}?YU=3U~Z-%{OFu6vq# zdo#Ja!{ZZy*t-lCe_UOYrQeBMQjy0=hRlXWePH?`T%Ao$Pm_PG|G9Z?P9$6Zfqk>$ z<9Ent@dh}ojyf=HgNdl(^LV9e(KG0R-|*kycNs;`Q$sQUsJ^pp%t_s%nzm?JnsfKA0h_S)GDcck-b#I+3Eo)s0URS%`jMK&nkH5+Q@I456Xe0qf zw~U8}iIS90&G`8r{}2E=ZB(lBgmELSn7kv6iq=T5{3J4ZC?EwO~aWSbml z)HoD95*%H3+{*zw5jI*6H<0|T8JQwR>La)h}M?_1vc{Ke$N0v zWra1$GG!S0RaWKY>el*>{m)2x>q(Q=;~XKT?e%?KD*{@i@}aq-2E!n91GwPlToliYXL|D9U2#vMP^fjKt`Yx?x_Z4^S@8kMThDc3jYl8c>Mk z(l|REQY$AmAWzIA0hEX1Z*d`;y6+MTQpc4b|2&Q&F4IL!h3vsf5;lc$h1wDhOVKAl zZ0@i9XL{|0uVrj!BTq-Uztpvwh+g+Gh%BwJnrqH}k=6Ht&m8Vy?Uessw?vfik3ZR8 z`+I&u(c*oMma}aqa!Yg<2bcRxPUDs|VeBkjuozXonXb3?E!rcyoqSOXs6+kU7*Ir03WC>aQGSzw+C>{CmT0p4MqAPK?viu3ZO z*nTk>vcZNRe~kuZNF@30K(_3TljZHbKnV5s_DGQ=t-T&PTb+BSYTsD7RLQ)dnW}rL zqGLi+8{wBRCu)Mt+hvUc1@5%@zp3XY*gChqpZEE4EH^M$pNNl6A8YR>5oogPB$MwM z?Y7UfQtuUgbXeqh!uQ^yVh4c10Qsv0A?kw3XirRs49cM>>%qsT z)2%n|!3Fd2tZWLPjP+hIM@BrqGP>s-%Vj=XrAr#1AWUq>bj>7PkR0y}DB>znX`)2# zV_6=tXPdjGP>GvNFFT{( z#>EAQnOCT8nI$qD#NdWg9O!!d0Fnd>b%gkrSh)D0eJx*n$#=tc-~&#;P{?|KZDD>P z2OkN{ij4f%DtGr^kGhC9v$yXnET{kVMDkq$04bpl3nj<6B#u;@Q`Wyd>wmpK&gH{GJL(5oY(eGIBz2!+}t@_&A_K~Y>V znom0sm2hZUn#7s8b+!8DXT-DWxwFx8%>=>hkK<9%Dan+kcUDBV4aBE+VwvnnI$&ib zQ9vrK{^{;FdZO^f=Yh|Py$;MBe(;?30+*YnP8LgZpPEnB3TQT69@*;lMybw?m%rt0 z;(@L{Qm|yarD5HQS{TmjbxR31FGCge^20+e$@d$Nw*XJjdotmR-k%!T76#ag# zxn>e)$y?Hcz@#`N3G;!8T(Dr8tI%Kc1{g`V#Oe$ zYx|hpdO6Kqb9WZK{(QBkZWZfilC}+2sAjzy$pagyIvQ;s8^*zZcPD6`O;$?G@vPO9 zFDcj_EXM0=HRX4YtDg^EKO!-UWDCH@qj)3<9hUY?TwkNhTn3$ zvY|WC(qs1=OKYeSv$}{;PHn{JXr{kc?(n@gL_3?vR++CC1pvr{d->uf(LE0C$~waX zl+O1{bKJ=&fuwVc+7X+k?Y$rHpRCrt%Px;miStuCbFR1WV21KN;@7G8Z|lR}6RF2o zir|oDT10OSK4}CCxeRbu0Hcb8yrQsW<`SjnUPUTZ42G3uql04NKZJFp)K>ZDOf%&e zY^Rta$hCwmrf6FPneFn!U(|4pCX5E~&7*aiDMTs1xF_X(eZ2j#P`mhLe-HDWL8sR* zMfaYmYK%}nP))NK%3C%5AmAS!OEB1Ma#@IEI3bKYtwKC_ROIcHp}frW@%98Y(~@z> z@l9^x@@k2+O5Ho9XmU+kHIrLMV(%YydZxbro*?p3nBVq$;poJM*-%n<6-}6_#2aNA zs$2h7OCAxx1$`!f%HCn7JQip{&M{lWy4WW$>~}+R`L>k12ArOQ{ztEbWG5?3Kl8`A z=L3esVhB!-*vzf(-FCd~6BIyo6ihiiX+q|~w0t5hubpZGFm`530H=RsP!ZeL%8nKi zArgPlRu_@U;TTTAu&LOb5@-X9P7m0o&1+O%@zT}~H#xqRrD`oURr0fe^k4cpe6!2H zpA{d*q(`I}ZTGVP&DQ-)^VpY$rR;TaqPZ;Z}tzoO%tMSP-WjlhFHIb<7#u zN!u?b2%b{F59!mrXPiK4#V*9d>Z@@n+AHnt#o`Ua@J!Z085sKt1&~^5HWx zHIhQ{f94uF&g1cE_+L75ABJ!c3r0ioY5?;q1<$ESXd#u0!7u86LqrUUv!t?4`la*L zL)wZu-^MdcX8{s)XM(he1x~9Qe z$s}+H5}aaO+zkwANkPgrL#DOf&Ce*ahxFS7dFbaSerDMCy)7o)G7W(ig)X)xQ^D3P z;vik*$wmx1O*K)A#wL=?SC#D>MHvbmmA=36#|7ecUBn!JtE<|gfFtR)8F#m5|_lB@Ku?9!Y zBzFKx=hBP1tN{px%pN}GpTd<2K4Nd54VzAH96XkdTgatru&ce2?*ZqL?^&7S?>oP= zGHa5DQxh<9%*aC8{uJWNE279Q#MwgDHy@T~q-EC5rP_s@g0!<5VnxVx({MWiQ~J*H z;{BF~H%nn=D+}~kzCo~edY);mWKjOLh@wTxLpQ^U8g;W8tcO9(MU}-U!#E@0zvht0 zHP9;j;pbdXlD4lQef zTDnpeENE4eoU0lPtDHYn6Nao&G1L2J%9ERaJXV*onXC|J+T4-Xd|mp0qo&+cA(G~H zjkBBbk~$*bjmqr%>L(0b(^KD;d31Kw8&q?5UNi2$Gfuo;dObSA1f?f$kHukx6co%I;V5r^E zPpP@d&G(^B?c?&~T@8N9XcX`x%+B0;a;nF7N^xx zZm^X~zgzdBZl^d=q1F2BQdfj+FKuL+$q$Rd1H9bX(aK+C{6AjKgg_HC+^kVL1@uxc zi7p1k^l?pDB09a(5}4*;D?#ql!DlSl9vp=$p&X=ui3;$FOE+B&7;KBt+;^CW|KVf^ zPvcZ5lT6Keo}$T}$ooG45kc<0XC$F4^xdL**n}ZGL}6;~GG37J1=E0-b}1dNJ6O2% z;;kf>ONh$K*--{vApUxAJ1;D_^hQ`!EUgC5vdXp0AzT{uO2$iawDz8M81^^JM5nIN zQF)`yAG-4?Q6ERrxa8&MjFE^cY*}qoT}oKyiiJx};`g&#-8WZGl)7S3&!Btn%E)H6 zIMbi>-B)!*Yy)OkfXyfZfPm14*?KFbQY8rrA~ZA00LxLle3&>6gOQBd?A9`JB^8I+Gx6=_*q8!6baloUg_ha26_8~tSc59E0yY+Fmd!K>`KARV7>CA_*W*} z*ySO@y4?)n2j0k7Z1*dewBd3TEk6~WEj1gm*`HMZ`@m%500x9&((_Dx@L$AR4`t|i z7`cm4?O}&vJ)|jpoFwp)ng0t)fYiZhQ3jOPIO+LIj$i(uj?G?$r^t+j-1 z42e1%OK?Ldfn}{?h=fE81%ZnpU_>Pb(3P>9!2uBiWmAHadguHLv%Q7nNRP1(-1=pC zs;i}JyQrP7(%x{f2!j+cD{T;B%M+gSMsAdh%_H++jZvTIor8tEl#g;=xBvg~Bf_;6 zn1*OD0ucZw48sse!vd(4smDARi1$3il*$Cu)XH@hKq3{ITJRE}R?HxiNkH65!y=pj z*l<27itLa8%cfxv>Ow6RpB|PZCsd|f@yM2T00a2`w0#=Vo(@VjGV;a+>EA%B2WALP zA9IKYu))yl>R|TG-(7D+m2(d~%r56f(iM>Eb@anRN}CxNK6~(0BaoFBU&fruIC8_d#alXjQ}O%dhhq&( zrBnfsv`JcW+1w({4P+R4R{x^WSH=UX`YPsfqWA`nJq zNmq~k{Hl}W`ybBb`YV{>*$)5z>ZMLMVi?F8EVQLI@C{&kA}GREQFPixIAaV|GVFwD z-~|XUfJ3D-a()}T5{0gL`ZcEIr8H?Of|v*a>nI1=2Iy-_Qb>HwiE`yDS;cr-WMWGe zEz^a{N=zm=QSL{2l^k-AojyrqoeL(#G!nrWy7kb_o{2GScd;GSm2wKV19ygnNw%gk zX(RS)7gnD-vldyUOsw2YzKT|~J5>DSopp#t!R;J4fwceouw?sy22Em8`&nUFg(*sZ zWrM32U5ioeVTWPzBkFmiihYkMg%-ec-dOSDw^o#oQjUQzidqL%EKEEbcs^CbvmrHC z$L$10tQnSsp9w>W>;@trh#6*)}XS;-ya{oq|!AB*rl0Gs%32d z{Bv`Vq6Cq6WVZ@IOsX+eikCwG+?Rcfa?>0H$EgyA1~6mbpDUP69s!ut2w*u=Le>Hy zTzKgEm@1q8;Ua@9M-hTjZKftWr4Cete^rH)X8_@N#Q4~ALO+1Svg%h;Qh9<=`)9~% z9&zkh=@QN8t8 zQ==j|^2nfXOs|@_P9N}hvzpV@qnB8cS-ePbo(PDv&io;WcoGy7ofwnHLsI!31(aJ# zAuQuF6MrFMh_-eFS}2G!-cIucfjcrX0RUdX%aydpH8goxE6!ciQbp)}W;Hgu1J*f& z;OJZ?2q=eUti)Q<6DO6CEkTq6p^`(f)Ca5&+!{-upv^K>-ecc*pQR&WJPmFC#ce#Q zNIaPD;xEwRjd2XXO_t?%7}=l-EYK8;OqdnSc@u^g1aD?0MA~Iw2BCuhrl^`&I*u-o zNEmwcFo+pySaDpz1P&2^Sz!l)zygBku@B)Yj|REaRG5)NF{siOv>KKBZtIv9Q!Fl) z6Gmd;f;0HiC0lT^w%L8PFh_&9@0=ep!hCbyI;IrYbl(YB|NFpX+W-bYV$}OtVQ^^X zx{qOommH;wSMA~HVRD>nJQt+o#`z49-*9HjHeX8>v6Y5MtC*O!=kro&|AzW{$x7nv zFV3Y}?CN^Cs_n74NU(>UXY!qJ>7mjbnQT3k1BK!S2z&yxk^nRxj3ak$`a1$JsU<{!`oox_&7SnWyFHp@v=1PfqV94jp^{R`{a)iPJ z1nPl?liIay6AwO0RdcYt>&v8>Fi(V3lCKHIfcZ zP;Cz}DximC$wK1E)dbD8p?zPk zg-iAW!ezESLv#I3+2KOnGpN_x2MPSD$+Gp0vEt><>A1^=C@gI1gTHSe*DWxU)qmIz z=4acG?j(z)6DrHtP<&k1d4&rtPItBxu=_KmAq0U*b(9U0)tD~-`=Dg~00u;2*ZWUn z*i%Q!9$|%US`mp=?P2R72$ZY5u$i2r^#CZohy#Hb{JkSLt*(pu0w^2eQ?z70A?(|jwG#&*-GoheJOqhLV`6^bZTD6}mMe6B4B zIlP7%XLbdG4^_s635_KqYE}Ax(|CuM;?YLtbiPZN2!?Y`3fdg6gB4KV**j7p9Mdy1 z6bV|~R&=}H>Ez@16ku@h@r}WsU-tC=W?;Ma%(|sD*%;ig%S|)P@q(<*OP7k)H+RaN z)L8G7imRyOZOJBXzHCN0rN8_CdC&4qBqz(Y%?;XV2nOA)d<_=#7iQhlM4#j80;zVo6n~jhC)S9VlB<#p;b>vPQmdCpF&1fB*ZyWY~ZPqG8qh zczSACC2HRz2~8O3iCOJoiDA|rE4&>rq!n}6ho)j}cky}i*BQjd3(&b}kYt2^c1agZ zxsx!U8lwitY)cA`i!S<;C5GiPpxH@Wq-=xrnVHX-^u?seMPdQTfdJR-N&w4l{(t}j z8%lOuBV!O49NC*KKm;1Mj{=A__2vr7xi_v-{UH$`vQVPwk|6gGklLloP8F32g3;O7 z)V`_Mol@&|I#8KG+5Bx9pO+BPwP~JKIulNdCuj6L*v}s%A~%_t!L4#Bnb+o8a7!$m zEXdU|M4Xo}8!q4b-LrN;Je)|zz#3o(6m5gI130kWkuZe7LI^;X3BHNUUMTcU`7V~4 zrgs!(aw~TG?zk_!uuHYE>dpqF5@>!wjFMY*E2z%hBsR)(gx8X4QL=`ym@QG#>;U(0X;@?E|HmHeE;?!7h6 zLO8e^W7&jP0!S+ZK?pKEG53soQn9Kn2DI(zLSs^ENaV11^9Q#%Go*zlrxy~k=)pzO zf;g3+1i2LD|DgL6(SuDZHEm64*3N(ag-?IeWBIVs6fw{GPcTHAbpT5*+g;4G0SJ>| zQI?pPrvM3yFm_LrlL-!L#fTas3qCLbpV5F&#dd||P;PRLP39C83?j1DcilD${!nrM zc7`(xb}g-#++boy+S>mqBKhyYu+|e9cxPmx_+CjbWM9iuGQdL|?<(0)blEcnJhF zM6ehX31}^IZSuLk@nP*t8yAV=f3N??fQK$(OvC^p5^4Z#7TjDPB;hj8|NEe1{(uGC zVpn@iP1tIO>fd4MX&D`fSM4$Pp;eM;{Pr4z;9B+JA^@eV^@N;dHzc;LZ~i48C~JYx z4t2z%XbEtaa;Vyn&F1vqM(04qhmuLgoMh#z#}PORu0&4czp?N z+6i255m=RAYZ&yj;rbtuLqYHepA!iToU5RbqqGmKJ3~i~%xot*KPN7^Y1i8-R8B&v z;`QcjpjdfWCof?3aS0(Pcm}G@3%N~5y1y_%zcJ2y&hKmQyDD$cQTNbmh-;dlynzNR zbXh$hN9mN_k7;1{w|kt;Dz*AWsSQ&fDz@|ShMqpL|M+TiR6;yeQvetwIRmYd`||_& znOLluk+aqx@TyEuLJmbWQuVZ)YpBOWz^ahw$)_KUI;NQ}#VgNz!rqlLHN4r&V{5R` z&|F$RB#$+J?7vHYveC&M5flIU6d2b)3U5w z21#PodrW~MTeOgNr_RdW$EEe8>xJT7Mz$Q361(QciOhHc(Zs-aX$RN%NAd~ z(tYj&b7Ga16>;AL)HE##q3h;HN3uFRct~uJwf_JA*4BKqu$+L(smjca*#H0jq)}7= z0fhu)B#n5;1%W6s0)i&jmWP6%LGP#6`EKUiL=QmuWG6W!tUec<8(0b+7IeN&T4z#G zS%x8xq3uG7%mBwi6t3UQZ}tEE97w%EXaDsU3#C9&X?73`FWcL}iH!UsT*de?#Y5Gs zgVd4Xg4!P?1GXYsBxIQkCt(m&>+?3iJQPrf=Ky5c*yKC0V=_@n=A!}e_<8aiv_XKC zC&8ChJQl`1tJ#aN@+U>y{t(f8YOg`X{Vfq(lbTw-h|i_F9e4Wyqg66#pUa*c3@o)IaTC)dZHTn9)(fI$Ip4);vQn!Gz!yPe;{ zQ2WjE?pJsuAY=dU=IW_P;?L6y2g)tHg{Hc(l;*7HZOY~1Nf?a~84O`lDL?=J|Dfk$ z^<;nl|MXD-5h9BY9z_E=g>w;VU$&UVf&*PQqo}|MgOLoIHYbf*6M{q{Yr?hX3(E%x z!zwwYV}Ouh=7LZ)$s9hS5ZMsC2ThFTh;b~vw*A8@-bW&-5(YQky(%NMt#a7SUE;RG zBn1;A6s}c~;-~ey<*S!-S-Yadld?DK7TKhyVj@ZK8vVpggKLwUFsEK%9IIf_1}_ zKs2!G1c2U8;ucW(*V#bWTls(0zF|d-3W}f8botN!$ZpeiK|ms#WkCej)7eZhvl^@q zQJ@7~A|P0}4Pl}faH5(4hM6kgkd~@QFafMTXu1;SCnb&1GltOx6sK*KAYN>?b8 zN5sOTvf_i!F&_ilp`eo%yZ=s^r%hSgZ*X_7O!vGopX~Mz8iI$_h_02B1dz>u~9# zc39-0XhxI>wo!ox5D3yxYGVp0!HpspD+3*csksoDYkOg6zO6BO!400%J$0vA1k2+$ zLhJ4V>=Prs2TX&DC4(-JOl4min3+sui=WOdstM6A%xqm5WF$n>8HJ$`$}E%$8UO$w06#zg1`W2==%q;?t6Bg1 zuw?Ln23}!RdrW^yJEIDpCE`UG^?O(CJv!;;C9TCJwh0}lkxsrw5hYFJYZYn@FxrkLV7uLzZDa5dtrV+A7 zY@}1solaxI41XR>EPbgUc#!CUb6TwGn!f5NLsraEMq93MC(Xi^3kOf5n~Yr^k)%|? z09!HfHh0;r$4^xog&vjmaf_`+e+BFMwnd8?8ysB{Wu!T+7OzC!>Q{$V2pX}i zWyPN3IW5v^OFFUtZ6a9Nd4*~Ok}-jDnrRd67x6J-TBA{2tc9i`P_oP`UVj>Oc(td) zgY`~D(R{@SsOTU8bN~Us0003*rP>Bn*EO+#ixnrS;}9f~gb0?1{RJ%3Z`S7a?0^0y ze?GsZ|Ne|nafWXDVJl_#T%IhJsx?UsJsnuVLz!t#WjH@XBT|Ce98zf639Y9)<(IQWNnKY$Y|JcItwX1h1UhHWta}d zI?XddK_sL8#mEIXtRc;l+I zET5xcmdWdaLZH^Ha1s#?1Lz-4+w}|mWU3$`nuR713$3NhSTj2K^qPr^L}!S164YV= z8agGEGY5&23k-1Db1qY;Y2~0}&zx=yUJoZE7aIg)t~~?sg9>%x&5BapVYsUPh_^_^ z-s>y1jF&FjSyJu&w=FnBWlK?+9G6rsjdf2JTIz{)ExdG<4@<>0r2-1_!ka*dzF6zb z{O(jy3GCXn%G~BliF~~&4^*96>=+op;lg#Z`Bw_IvE;Vux{lEn2l2V9x;Do9wG;+> z2Y6~A05n^NB>}@^03{0I5zc?=3Sfo>pK7lQhJPw?K&wtaQazj4@V6`8U{F#1zy3$& z)>VpPBfyOIgL@u8CEa<6C3OBj8V@>yU+)qDO36IS2!tW0KqQ_fDrgX>GEyisV#H<; zI5a>IAW#O}3>*d80)wo}FPg%-&^DT#Gb@NEvtx}ow&B?m5^0NQE(os~D@?4}B#R2; zMwXk;Gb^RF@syraaT^7E?#R>;gf}@8v7s+KOd?-lDY{8AX!$A8vcXvPT{l!%I4(6C zkMdML`b^HV5O7?MXRnqqh`|Xl%GHWsS!IipB|}`LNu!?={GlR7Swl*AsN}GEC@z;e zI|2X>3eoW^|M}zhCzWsuX?6er93lV#bCr=kp7>T+@d?cI#3FHzB{>MEjO8hEjA9ox zy+Qx`pk(*}1<+YldrW@VM&%lBV62x|^@~xhv0Gsbl<2*KrR?x5FY4d?ZT*AB=MfB5 z6y%7dw^$X9(-T6f@l`NnoSB6t=kd4A7$as>+NYKdyDO-s0ryN`q1XZgMg(bv28tm7 z0YZiXkp){xOsWtn*Q7;CSH?od9(v3g)iXksx_8)^@z@ol#o+il0bLHuOk8-%D&b=6 zuAU5gTN_Y_L&D?uQ9LPX0wYmt?eIVC34MB&N>MN?5}hJZ?~O&|WE z#GG3I0IC8G0000~d3Ic=w|Ad)i^RD`jFAd1NLm@@@ma#kndpQ;X?Nct!&x;0Q3=&T zl`ZBBcXet>CHc8Ij$%z5%q)ULIzZe>L^ew{RxsfKKt@?Zt$>7LR8YJzTI+4=nR%`~FVmb1-XEWlq`Zb!AAZ&!foi z9Njl6UZ@fW9O!MmAxFHBXu$8VsM+2kQqI-!=BlK*VgyHzDUJXC|JA)}31;QE;06Rw zW&n8W|NEe1S?y)z;NOtxeUh>400bq7-~ZiD)_km> zPSRh9#04fMNSMNAAN3Cd8MpquzYF34nP?ayLSGvGG9Vk~)i6MZm{BI2i5EeXj~_!j z^|~01<+)R^5@RkbDAZZ%KN%3>OMt^mbTS#psJ|LOpf~4gItYIrDpFe(WMrk)3{SBp z3lx1R9x9?4s)Ia)r`cXXblRPbbvfQ>#ng)F_M&oo8D9Gn=SmgI8!q26L#$GIO2qmj z6Fs7+7*9=9t8IEE1oA-Yq^@TIhIeW>I~H#~Q(@)Bw~%gi18$r{qHfVu`F2dcsoV(ucR$MdaYaYGc&umIHxawV{{^Qz#!s4Vt_aRC3A|-r)|`f z$SpJh9!pzhP{UN=)LKG-T#R`lNrT_)5FuF5RBRJD-}_DwDkuj-mH(k(c?7icUG}w; z57sj=LNpKMkf6_*cFxvM?7NxN=445&IK|9_K)}R_S12JVkvL4mKnyTq0V=I>@gNnO z&@>|dFJ=76ANO_Ro|HQErrfxkLO%mS9Jm3dNt}o|<7MvT%>5(o|J}}Q+-uFjiahe? zR?l}5GD0RqUZHizqezWlgGT7MynREbg5o;Cx`Wuxt&Ojx*o}GPvQ?AC<;z|n!)o3B zHwz3cLT&&1uw>eR7J6e-drxF|Or)v3VQhODiHlY3F&!xf5~sbE9o!{N3Wbp=b#cX2%Sfj_}0;B#8fY>m(!kv^g_Zhb#3!=*O*KvabE&QF|#&a+5FNt8Qt5gc=V5U`v^>VB^BVBZ5Q(0cUI{4_oyIOII_* zQp<{%r&Owvn5(sfEj*GTWXV?MWT9f(T||k*gIM@tZckADPdz(Ph*OK`l&lBqYDI-= zswzDj8Y(oCrAeV#P(v^|iXt&tNVV;G8$ zmQRx5?IU;XTSThoMcOw_W0pGe(MHufpLL=b;j8GM#tmGh_7iC?L0Sf|W7o6#H!1BWl9l>)&rAR@rH6#m*qXUzMP|`0E zOT|$p#Gxr(tyG2{>9I6(qD6=mKt$wlw59b+2uqEKfYD+73?oxiqtT-A!Xrz#4GEgd zNmnc;0rnO1Wku(t^dRnv#lO{90!n~(zfCBih+UUOsVw&U@ejYsz_S+H#F&f~p@{%v zo?$dfpk5J`|NF3H?0`1JW7K<3WNJhtdGBR{g&_5pN$oQ=sVfrZ5rvA(5fx*#pkc-U zKtb55WeyI?NVpmlX+%jy5#kkHADPgwWq{hdn5Kon11L>;R)ayEG67Pf4C5RFRAV_1 z5GF~$Wzq%7UD10M?rh1x1sI415xA=&TL-_3QIsx=4Mp-1+c37Ovk+0FZQ{pauq^vt zd7-9}GiA6e2B|b zz*A`WI6?-lDhQQ9OuPk+uMpsn-~nQ`SjmE+2r97BHU7&BTHgwxWZ8} z6eWuQt`pn}Fi_f1DD2%M**e3lIvcw0X;`= zB3S|}5#X9h6s+-3_MynBJqej|ITQuOM-xGS1mS=H0pI`(slo&l9XcP?AR%nSL7EuU zh=LT{PzmxJKrGc%gp6(gZY!C?W~}K@OWZit4zkfqM74Ys8|fET8YB4LJW%mh z5&9yOy=3z{J5=p{i2wn;;mS#?D43^T4czZA9Fdxly8x3V*ermJKwYeuXkq{uj7fGp ztF*CF#kfDsC=&7M7vTA7M1^6^omviMM6>D{>!3NiJ!Sl=6C9 zwvjG?nZxMUW6=Nmz+~J27t3Q(dw6{EQUfVXXAfH=J&jN7<@M;?38y`*B^)aMO$97Q zc1{U21u>*yXv6^km>_V#3{mrh(;}z%@f2C{8cHNhjy?7=8mRS%<1xS{q(`zvHwH9UZM|yHE1S7=~ zwjE%b2_RNSMW~$9tix#l4>L{)enL>TMCg)=0`OlYLt0jfCUr69}qt^@O z`X%WEItBuvB@$)8B;p-Zhy%rXDre-wZd_1nBM=WYL=|2fo=@tmffQOG)!I_n^9ykBjL5v$*RgcR1`fjW-Hw zl87PCYq+}c*akatFII`zbXx;JXEaHMUe&Ic>jF3hH)Si}0Wwk}aFN@HP~yc-g@a0_ za`S{BM+H|R(nP1za$zDvk}i^fg$~@*Q6AtC=nkL-Fi97y!EPHd1&1eUbpc5Zx$kwC zN?}@|r=h-OF+}QknG08A$QgsIi;7|9dz!%0uz-4q8??IrXl!YY)$i1ELjucFBF(v8n{o6vk?3!k&uo=f`;pH5UJzGyJEFm zc(oZN;U?aGE72N&a~q+;GzS?i3V}XDO~rKRNQEfaixbsk6k#twp(c=;mjVu5Qe@^S zx;n&2bF`DxAoLi>qW}A_Wa$AIVPjSMdBG?v!ikMwDT5p_by@9Y;pmkFqxFp7L|&FI zD&0Oys83>MCIWg(1od4S6zSHPdn^a$j8f)+8LR5|JTX3AJk{fl@u!0{yPq*3Ss~!O zWs?z^s?~+V+1H(AYVAIx;2;13?f?M@G7;M{L>%BBG7ErE{7WC(u-i))dR?*11sLlv zD6Lic%D6L1m;eG!QNR=v&P3s?si`=VMmvXM#7r0ptl+{+gokv3LbSSAcpe`n7?}^l z3WkAGbmS*VlEk?sK%^_&n4vq2h9RcQAaRYvs$PniYL-tI4Bx5|_1nD0Hd9krz(ZACE2sG|&H zz)naDw*CMB4pYM)j5}vUnvP%qm?#9nYrv5h0kwNv8ncX{SQD52<&Xx8xn=}Sr)DIs zUcC17cwd658*o-w zS0-Aa0Bb6S>^g^mJ**>w0zrCLUwwM;EG9Q91eX zkEDm2J>6~xF`?x(wo@Gw1eZ#NOP3xripiBSNv=<3CNTh3uW&FFz_1G16~%hXu+mZJ;{Hg`vR|DiqrV3qVWYaHMSr0<1CG&>IOY z>p66qyAWj2+9`BL45z!slCx>3<2SC%WrSt&ccZ+OKU6f`>%{jgEFA+zW7E&=Lv<~p zu<{_24T?o`k|6BM?HdgPS>Tebae>%^S&1oK5@(q@ONmeyF1EE96>;#Ci6J=7CK-f! zSdES8#*UWsy$cA*Ac?W9j;_M>C1ww{v+U8LOhln7GwGI?8cXWMuscfECv<~LSJ(Qf zR#55m8Mi;0glY5u0Am(1Z8bqZNl6k(^CYoOCS0ECf7T(42S z2_r+~0({$1Rj~{#*4Z4OUqaN_a5JP6>Z5@mcrF*{VEzZ?6{P_Nh2@1K=m%1f>T$)( zmRt&urYoTvoi6WmLl{Z+E;O>DDs$y5Hd$J7;v@>XogpOmU`StFUM)U2ov|J*KQ1{l zGd(iTTI{S_1&e}N$~;|BD$6*2Tuwc&QY4yc;Qk>C%3=v<$ZIU6C>{<9<$BtmRpnS> zde?zg&DA=@`wjlIvD&yv694<4Wbl9%e_~L3On*Q#VtPMk15+8@i#P5)k0AMvD7~f$ z=W6V11}x%j}t0#&@LX(Sss!=6cAH%R8z)WE}PJ$OTvTa_-OKEK~&-^TI& zo3wttVuKQ;>s2ytX-ejALRU=70YryBNjy-W(y*_5cdlbIEhh{=c;6fW`;0)itJRE@M~@SNAVV(F!A zm~_gloDH@sL?uRiqX5E(&0(iU|b!@_u(HM?$*mgi_gIf2eQZmW>e^C1ig(EsLp8iDyT!L_rsiGlm5^77lH*wo}mZ9ecAgJ^9nk^knpQwd)MxSi0L0g2x6y2TJ ziC_fHan z5aLb{l}Xn4#zPkgNfHbyDVR{?G8$T}=HjBx3Ut$H{<(goEsHSHN9qZc7NUfOt5*+8 zn|dxXfndQ^snurUf$}2rq7R~W#{~-?g@Dy$Hx&uS6?12CX>2{zui!s4Qq68maT(V{ zyzfyEiA9)A2^ggwZlDqXAQs5#w;;f0krpMyAyBV>tQ@9UUC<8nK?J^0BnwFd^>Px9 z^{0uqoRH5Z0!g4E6qe|6ZA|Q{;-OuFY8jX? z;zP?m9JM-3a?zEQVl|fF?XaMRq)O{xbL!s@N8fe6%qQ6uMd19hM#&dM=3;~EmA7R~ zt%5yI9BNrDpZ4t}Z+Qr=)f1A@od5fFmZSeC)>&GRJ#iDvQt+|t4e4dSxWIkTzJX*lh`L4 zGPW86P_gvoNvgyn7HD#PR5VmEiDhC~nGIrDKB3~8%aA^zHsFRtbQEWbBP&9sXzWiy z8J3}u6wF|S!h$G5#g602sR$zK)nJO+o$68)W33ZuZbG-=GhQ;j)sg_~QcMB@1HlTh zhab~fXc;a0Jq*_Wy09U}VH6NP#f$VpUgWw8wyhkEH@ zx3a<9RYWzkL4wkhRHGmDA~5D)QQ6u(^VwDt&IXekYzU5-SL3ePBkRxKWtJRd!v<+A zbh{1UV!c^KZPaS#7f&j=XJnElH67$dW6VQmfWYLWLlCr5QRFn!R7R(<8EN2#7jUy#G0soVM4ERIt$VKJHDMonA*fB*{o2<_mrcL)Ta z69oVU6l!E!-801PihP}#(DBMU?W zVW2UD1ZFG>7$ihsQ;CBjreidL6Gmbr1_d;RjG@8MCC?xXX$2G{9W(?GSrZ6Y$V38J zJ4X(IA<_Z?h6oy4m{GzqU>9eqxiw<{`@m$;00#16QR{hm%0@#8&jsTxB-xQm?{i4u zG?eMQfSSxCY1+%y9KwZPvUOln)Sv=Ov` zl>GK}<*_;E_L;BCA9~S=>PJQUnO4Us$fk|gp`PE*U!B4s6?&QcS>uyZP-85lfMB*S zd8N!S$s?;8kLMVkqj4aq_&!S+u~)R0J92OFrNaDMwIh0N5BxhOjYX-VG8fWvGfB9+ zkj^6$m{L+l-+034b}Ty*+WgMPDj|SWK*E6?AHKWYg*e=K6?G_yN?CIc6_6zWI9!nF z^l+1UH{@g8>o`r=w4k~t&%3v%9RXm$1e_o&F#r55|NdxOrAhfim_7(7T?#Nom{dk~ z^!_J|U=aikL}`&=iHFl>)g&0~W@uW8!-nQn2_6WEffX1igfd_t4UL%t0?d3s#lQ?K zcmyhD(Z+Db1~M`vGjO9*z=%qKg-~RQksU>WFzrcrXb4JAvJ};UP?|6p31fh>Wiv3P zBo;J6Bkqa_@{%HeAa-FHXJywhkXWW< zLcp&y;u$1z024{pX%r;9Q3ghiE=-KX5hRI_Nu;S!m2aeE4@8~(l|f9+F_`NxYm8Zx zIL~Y!EQ`ZYmRDN)@S=`wI@5tGOW{&TA!uIBxFPI zlnA&2AOQXEzs~m<*?_`k0uLLB>Tlj5?XKcMC~#042Qv1M{J!d7+A=5PvJGi;yXD&| z3d|%NA^}9*UwCWKRShmMj|-`gg!?06?bpP*ucrFus~aTe zHUvv*7N!XB)k(xa@`Viuq>tEG+DsUXYlU<4G9qmd;{?uTPOzbtZYIu^s7hs0N>nf> zeGKY;TM+b`q5DigM3}N#+Cg_FNGk(`L2&13NKQ5P>dngf6)`2XBx;Iq;r>nbu7!3=(lBu9T(Wqs^hDZg7%7zNCy(*%!GJ*gJTkjD9HmF!t zBdE0=uyzoz_#X&Z>P8WBR+n8Ymq+Sw;S2hoPzGk`|M{K#F|+ zjs-n@7RJ>gd5K#F@L3&VC&Dpn=Gu^=JCzK|*R+hdboowjqtvPv$P4UHntAB3`M*xr z_b5GPGO2j1NwdP^B~&~)KrtkklS#r+TK4qcNG`c^Ftv53OKf6$pJG%AALtnmON&ho znoAkcl?TWOv%whvBpv~~!oVQ3=S$#If(T4uE(8l|iI_Vq&CGNXk`@BN+XXbriARz1 zoq3h#izPVAh(I~=Var!(GZ$9zq2z!6|NT$@{lJYC46J0Eku@>OG;G)GwE$hsQv$*Y zZg{+8nD3i{shBx6#`4u%!k{k7WCJd??F>R7Da#UCNB;?2Ga!=3+JtT;AAsz^t%Ij3 z7UJc`LUV1_@+Q)q}x{jmEstT$|P7OwP%sJWGS z2}!a-NWB^I|9`Sm&2=-3xNAOy*@77IF)ADm0APMBrdYLs+18Mv*PMxRS7TT!AK3`>&+Eg}gmPXGI`Wc7dsfnwHsFJ$^lLn?m{EIAp0 zi&N~e`Js}PDm|PfH0(;!Z*Y!(sM^Q0WkVBU>OL0Yl!6Kr3Kp=j7$0)yHzriNA}`Gk zT|P2ro(+sh+2z-EvJA5g8q7gR+M~!5$YFsH$}8j%CLudwr7QSU8zOWbletHKKOyBl zPw6l6AL;~FhlVgBk}bJR@pD3W<%Bb(&lo{_nQa9bJ_uvaxLnIkzDvqWY}mw3qTH;vyn zxk+OWwo_j81@gOx1MBJ|!3Hrb-3r907Cd<3cgQz8e;{13pStP}a~p>Umak?fB7M~T zYx}EV(p&UeIu59%agq~Pf1+#WD)&P>HK$nO*FBck!+O1Tl@CVDzFrg{suPPr_kv9| zN?Fz^|nP*eOGR0PaS13`crr5EsB=aV`eLln=8EGQVOqKa(QT zx7MvOJ%N;WR{U%J>sLC-k!=wpO?8-293G_mw5=Ihto(1#xYWAh&WN^NtvtAYXq~z9 zU0CME$kHzakjqaLfd&zmD7f^em%eknxw&?298A{#`>2|XA(h0Ud zNC9yoi^Y?12pk#-afD!#6bf+AFjd2{X%JXCmD3fZ;S91)0*G}&9aauSoA{J!Cn-=_ z(JaLx;)%NF>$EbYyH@Jyxj24F-wTM?M4E^qfXmJVK|Uf-VgGK~a8xASjFV9ydIzX|%%6g6t)h}P?L=e-G{%7jEI}Lyu3TSgD1w32@KoMtssuh|qA;!-GWs0(9cC0Lf z>LY@Y5!Gm@=!Fzi#3h0@6(mNHH(vTaASQZgpC3NjbcMGg-H{gdX{uu+h3%(%g*8-r zc*Thk6v&BCg5eUTUb0k;>XvIIDM`4&POd`OdFM3=rs$SJ`7wjQBh)>l#H!B-g<~STB0?p^qcVa?5aY>=q)(*vb)Yq|Ab#6Mr5Yxlr!rbSEgDHA zffey~a^l=4%a9>x>_P{Xnid&RIYjO+W{wQBY*w3y-?o7#HE=?`;jew$Yc;8+So_;f zDJ7`n=^}@XHBf>@=Q))oPt7;&;s(q~2eMHr;#Qgo6k9EnU1BQPeT?hsCTWRD3s9PF z!4L&}i8z=JT>hBQg3{iccN@!soe*v z0%l$|oJuCK=*7ImKYy`#bf>28wGv>*)lW(bo_vI%h+|tC;|Z@i^!dYgiqGV;YDKU` z2BjF^U~r{IAZ4Byd52~Y5C{PqjRD7)G2#V?WR4OjD04Yc8zAGufDwk@s%1*km#Q*Q zJ#jY85ulPwA*t7*p43)nIG#625VSP9qX-2imwGZYgzSWM1Z1(4aONYSOo|vZbe&}p z$<33rkt#VWHgWAGRK#5|lWypaN@lqGJz73^0q{~&et3j0nmhtA6P);gH z695=oxhaoAc`5apQgu%ntO?#^;9l_PxSQ>B;DMZStx z%bG)tSPGOk}1U7VwD?*v- z%bVw}mKoCWGj0FW2lj!jM}+F}PHaSFj)%(cY|5N1$u#PyY9|UTH`ng0Gk@`Kzy2X> zHoiZXAC@csE&u$m3q(Papr{&{p>zfUC6gq^w11U|Om{>x*wn-evn-Vj)|N5Iw8yHW zWX4S3PBFm{!$Bh_5DXMFFyMH@CKDu=jmOhYJj@9K2st23|NGEn&j1FhV^jTU;0kbo|gCU_rBmqDKg$@@rpaf+{s2WlOi%Ya2a2PDZlv#+b zksu@nDS$CpI?@0Uh-kVHB$$veP!Z4$Ie``}JUFShJ^&tIm>>!FQLz|8>a)ghzyya@ zTJ97!jW9w$mV`(;^$>)8mTJ{vDCFrdB}T!JlO-e!Vuctm!bU?2mpuduqS`eG4mAzH z4O$lOp`wDYM}7o>q37wDiUU|BX(9+T9TORYDP@hMsdTFg3{w&y44J0Dab{NhrVAZr z<*Ek)bKWR+MqQ_Mi?z65zG;Ta8JnWmnR4;Lue?s&rJpS&f>^FA<$sXkUNHBSpu-Qd zN-BY15Yo59v;Kl`F;U>^2&IMNLjw9aDo_aszZpA!YzJ)jN?tM59M8qprFe#*X~?)V z1!J9MQMkj9A{ZJOi2|>a2Xi&qlRnZmz~td+W<*G1r(z+)1Qi7-8~Opa&YG1`j|d1s zOmINRMFf(-1_{jxT%sTn&6p^0F>r98@!()umnl-fvszNX!gQTiR8wED#!o5%0)*Zn zgx*8wh!O~$fHaXNhTfIlEQH>BZyJy;AWZ~pp;wVEDk{=MKm`=V%FX|-`+Cn~*2>G7 z*|YbVJ>Tym;6_Pu=eU`{uzKrL1sBEp=Yr;Lu=bXMzT?BJqOInn;{#N_``AJqNoxm< z4k2jx=wpX3*N%9Co1TX2Y(%uZyxSJL%Sdbbo&IPz9t*%Rg`OV$j=y(OS&K4>(4cDg zpZ@#}d=Lyl=tqR1y+oA!FbG7U0crbd;lykJ?Vz40hST)t0%vl8$l#9jK|sSz$%+$u zoeqm+72%u~XHOJ~OCf6}isON}a$6#YCtIJgPZk^ANmLv4mP@TJbD%w9d$#b7Gng4S zz?!szvd5Z?FoDx}b>JRHWjwhOC^C;;yOfwzKUF&ESl%iL?kz1O@711G&b3@uz#JUH zHOXX-wh_}sG}<|?az3&Tco}QSjB+bFyh(bL09R-?PT|FPoTsleMQPhN_t*P2S`W=# zs(yIzO(W;fe`2@L812Q#$2Cx=&?g0#>lgf%totCzx;WhaeG}pQo1L#|=qw%jB;@%? z;l{K7e9x~Jss0>KD1yFo$sOvYSkXnFBH`_*HH1E{ZNNat=xkWLZr!!MS|Ts4{KT2H zV8Ge?=Kn3BDl$W@=ls7&Jjzs`;qo&MF#-A&e@~3Zb(LPyqe92dT-ll!*W;#aoqBdu-R!|%0xH+%*Am}Kvmw>+49 zS8`?Epq7(l@}YVvjlj(DOz4YQU%&mP*ZtRDx;sTzBXiV$UKRRLq_9=_Ed5aW_k|We zMQ^#5BPSafK9jSV9g`Q&oLgA$inyQ6{b`I(0H(G*a8=Yj{^WG^2Bxs6uH#Jp)2BQg z53ip-h{V;iDOCcvs}*)gF$tFOEocHE5lMIYywd9VvT$|!-TM-#&-W+YQw3}!xqwuw z-pq)>r1>(5fgljqpiCC0v2+}!b1pY0_~cb=$~+fi_iiF6MMTBjLMklXL+1RzE4nRq zLN6nB+#4N=x9Zs7k9ZVQ)dWjeoF}|;=)_~0!@wrC8zzGe?G)+=!Lmio(Qy-f~MJ z6Sy>7VtwukgTY&qlVic;Db`h=&O!2va@`c6_QJeNxWIa2zF(p>Y{h`}3c!EXWhxwQ zx7*KKIoxB$eg5oU7woX^s%6dRgu z#5OH60B4C86M`l>kZK?%Mk(!F1t=^993KyQVzv}g9fe4MMha_l4$9vfCYs)FY4iM1 znT?BB{IA9M27u?fzX>vwN`oL{iAtavWfdSrM~# zqI-TO=iNE{@MhM;P+*0}NaBKajwPAK(PY5VgyZ^r*}JrXTAf(o?_2@2T$$dcv_?~i{pHqxjh|DrmM6|Q|3EabJNWR#iuBP z8YZkETIt>Uh_HZq3U=uH-HSeu2ALO<^=Z-;a&6zkPQS{QSMN3b5zmt3%|4?nTNJt{ zljQyO@c198(Mh1S2;B56z9SU=?)3ESJDu|9E=HMYL4HP(Wp~{8B6v%E#aZ{{4!OG? zKe-0JnttK_pJ?7fc?-Fp`Ql1C0g3}-uq8RoycLH^gOOGz223IaRR6bH~W!U@0L;9ud7~fPwtu!OL!8gi6`hsk# z@!^q26(O*m9oOF%)9Q98^GuLMTxF>JpDji83_AJih}RkD zsDs9XWt&190(v&Tz0=wSx4iATLfo8w)uY)KE9TtW9Hdc{So23ZUtSWP(EA5SflOUh zi}~5DaDQTNoi=*j?(r6YTe;d@r5&)&>hGRzw19YC(sa^i^F(k3jVj+67X1X9ML*Fe)o?6_{e3zk?|MHXN%K-4k2gz|(T8z% zdu{YZt8yu#M!41=XSlI6dXb$T%%=)z&E?K+=*V$>;!L8ao?H-6tZ(|0B)OD1J;{0*pniIOa$!X-xInw{d4l-vd}`SW+@1?zbe zqRMq$ang_U8!us8{N1B4S8`wfB0VtosY=@Nd7Nrti{2~IKRm{8o$Tslo0+W*e~Td0 zu{61~6zSU}?1xP5v@dO)Z*O`$|(4_G{^f^ZZtQKvmBbXAyLt zbl9U;;bq?5tAVi(0+LD{m@Ns3>SfVp98Qz`SI}TW${ldmZy#`Q=YZ;Q*Et*G>(=tX zMoJI;r0_S&t*@yyc98$36Mm54d~UY>G)9BYM*4GY>2RJ;G)BYO99P8>nd`$@$44sz zCzCs@#z6<|)N>kj^8 z)UGHP+cD11n!JEpcrZ0Lo0z~}1S=3}1c0T{k$TghR1DlC8z3l!O z23~sHW$CUJ7dT#;^DIRMWGwGAUhTmjB+>^P_2LaC*`w zy?B0^A>4UwvU{z?xvL%5)e2BPY2A}_htGDp?!LIIP^$9A^3}c@OW;Pay{C7Tso~$h zmLfT51o0xzj)O2Sd$RP3m*0Q2=N$l7rcErJclXirFum<5dYLaT?fm}ZBGLy|>Bo7z zg&`57UBZ~Vr+4MzakrMdNBP0}MNY06{{_Z$Th2?@G6SEz1WX#_*H~6#&Xw!NV61pQ z5%xLn%skYiwCr37Y0t4HbMMtfWQ-2C^Nf0iaLD_IGt|)r z4}}MgLB4Y0CSe3ldmmM!7#!}iY&^R`_LgCqbAhap^bOhBA${}3=gdidEhF0Is#-T# zu4ff)Vh8_bP038*r03G0w`++I!~w!6|`A)d!MoOQE~kTx@yv;i^M#U7z&uFCK)RffE;b z^@cZ4pg&7p1M_`$kLkb7OV}iwnu6YN)TM9r}kBBEhAv}fdQqJ@gbd$HaHZ=(`nu;bR#wTi&d<8+a9O$Qojw}@ z7oSLO+~m9A^1wT*zJp}%;T41`_^9 zkSa%X(*yFZ19S}qw=v~=A5>v@(nyxB-J_dD{~B&rFCM-A#ed}UMzz!Fl!mkzXH$u2 z4CO#Am=qB|+IWU--NRCiOmdvDazxUG@t)K+bwu_J0GiXGZXiMSkgu)6Zi z?h3)~<=&mf&*zvC=`znWUDG_mgfZb`1u8M`gUoy~Cr?tNMn!7R+P=7_mHKI=>y<(5 z{%=R^qS?1eZrhmU=dKE3tU2j5j(r8~0nU~J#odR$cqoml+!B;_VQ(gGCYpLhCv#FX z?R!o{ypOc+!rSP$Dn}tCKvD!4dq&hQC1i76<08%S7fOME+zWT)QCx7kYKAAaM;p+w z3d7Ugtc1hJr8Gu=+KZVp8GDa+TqCy1=}Ao{VO|H}>PJS{Z9(6)W~X_`oFa!3vlDwO zfpNu&u9YOi+8v($ulBqq)A+e_zlk?zbtKYR+~{0+N7Bqbxn{&&DHnfM z=C(OKRG{_glA(!YcHZr@;OZMw)akb9S7xkCqR#W+@FwDFuvzit=8Q=WJM(boE$cq% z?0PIP%0|bXq67*xZ6r?_y1lLC)2uVehA_D?P8c0DzS#OZ;9u(+CC=gmgT`01^r=sP ziH{zBJN;Vo9BDUgg)&wXx`X`#=)+&}He99M$a&G{EhJf|ZgTO#td?LUO&9cVn<3Kr z7@{AkkHBENCa5$)2;*$}E3v_qxv!tj7{~1|#|m)Amo=69#gEFQ8(2?N%ZD2J(}@#4 zYHi%{uJa6MF#3==W<7pryWX3PaemCo^kD02eX-@2I$MUV;G27s+hC`9=@3W)EY*K% zD|FkYC16r*X1R6Hvi%9ohIvG9-Z}P0QSjr`&MM7?!l_PE^n^U#rT6$$@Uq}QdC2La zIX$bS5R?kRq_0hDd7RR2*K!>BQvyR(KGjbx97vkj^*s(lNMZN%0r2O#Ppo=;z-6VEpj^_yiRJ?4-lro)IV zJ%4(MS8K}hC+AqDZ3kSlp8Vf#XX$49+uqeuZ#(9^>j!V{kreaky0SQdvWEMGO^d#S zyygNqUQt_@vU55FvF`wajsytgM#qgPxeLK+$7e&(RQ49OxZ1{~gZ4>y;%v~`f#73n zkMp*vRd^o?G*P|clwt+GmGL#tyg8PJ3m+A$Z{~`MP9{jy`H-penOe#g9?XF02_TYw z6B__$ovQ?6Rg8&o0WC>EPM+aF8k=kK!)eV|{!Gi4lywF3&g?hkuO$IHOv~aLF)M%wROch8=GfPcWy176J=h_{l5#kZun$`$(5hA(g+ zMm=4h343(^k*X(U<4j#{pF02&0bmUQfFI8c9Ffd;gT)+3q9C10qL?T{sqs;tN3g|W z#aAWGclFP=`90^%uj`Acsw!WL)}>lq@jjyE%;_G1uJU5r=ao6 zxuGi~aZ?*7=T=?MV}XXz@xUO9$e}p)!rqyXtLhQj!^XxJOV&$uY<4?QDOwiVh7X8J z&v5f+*xolGB^_05g0VhQZzh*yc3WhQzy4G2>OMCa9;R|<AFJUs~VFDaZP$1F;hKj@c}lYa0at_dI`oZPV3uWg_Sb|ADq_;xtU-UPO(WGbb=Yq zi=$4h=hJ3H_rA;O(Wh8ShYe}Q=M0B_ZP(%GFXf<!XSUSF_22)u zj*t^3mp=RbuYJGBu&h4{r?wH8I9*HN@7-w@TJ=gp%s#Bo3%Vc5fgCBvqAOWN*2x3a z_L{)3&%O|5RinV@C?Gtm^C)rct#Pfh!wh4Gfcvr5!3P5w#>PS;O!P{!QPFjP+M&fJ zg2}GzPOL0!p%;)W(bLu|uNzx6D#Wny@xUJ=vI_YZs>@voVXrtZgLP5%w(EUqtYWEU zVN%M2B~@3yW$RkoA=8KCM%*{oyDP+#Qu#F!L2?uIvFXj^4RWx(D4BQ1xYQ&ADdR{-X0w*h^l4nbVT`I9%aD6e zZSBPBV_3Sv%Q0@+7eY}fF@6B~tSq7~vy#!T8`78s%GdkJCiJo`UZwb_}oRyx3jd|VvF#oHzeHDy&Gz=T&cOeSkU-$)Tba@R~ z=uH&l#);g`6&)l$s=>ayPgRu&&&#GK;S{r*ozo1MGdfwE3Oq0+5XJTwtu{IfKh60(;sr?Y8&! zm9YMC%9s=zGk72vaF3A&mN-~YE+bvaO-Q4UF|{Cw(+`E@^&L&RDonmN4v=fF>6O_| zo~*m$=Fs{JU0$*?d8aAsNN6dAyLm_BYR@Y>&go08u_yUcW}W*ADC^dTdN#y9j-F47 zC6Unu+%AsYoOTcRUO%%g$$FU{c%UvUD^!I4R+44c8gXZSYg_?l{N|_4BOBpMKw^q5 z%{mVapmNb7D{){N&K6l~s1!Wi{Or1Pu9A-y#-x2v3EdrgN|k{V2=6zId7|0Y=^}(T zdP$|()pv3xrc&-5b8>xlo}X40p%*NtdL3wj@YPr>mIP$rMdL9La_(HTI+`T$IRqIx z-kTP$*|KVQ`;`h&Zv)dD-osDf|Ha>E@KZ0OTE3lg7VU=-xLltDDq^~v6FwQibm2vw z)0g@W&u=S9Sr$#55moxrY{yn)zCIuI{J28lPK;i};@iVZ8C@nycvS z^ksu5MRxha^N(^Z`Oiz21N>v_%g|k0`}0fvY{CyR0OwAOeQ>sW-g=Pj#F@5zTXqgQMwRdoGk6Zm<2V zz~Sb#KfxbPTaSter;#ZpCiBuNoM%o?k2?6K^=AvZhId;Y66FT>#cJO0p4WKX?2(?@ zOlvj*psMC3UNwn0Ai=--Dwd7ioh|<_))jASOkx1ah*DI~jLHJ#{l`W9$;)fl$ z1I{jnAX)4n>kxdFNoh}rov->XwhBWqge7Q07d)&AbeIUwW895}m7#-J>@om`SuQZq zCGZZmg8{d83^Q$l4VoDY)5ZHrXIESas1wNm2rJEEru>{G%HzsTBJjx3gWsFjseJkL zA8(1K9L1Ok9tWXJ$@=C7Pyjcv7MV5z*6FGK0WBa1LTU!5a z`a_xjbDvu#BW2yEuUxAIC&M-0P5Y3s{VcK$pUGg`(ydr^n&qVWhGsg^&ALk;H8Pm zA#8h_bIQ@M*^%MOBN@K-FRMB~$13jRzgGQt1y5uBoZ&Fm`icizWl1NLPN#Q}@sD}t zpm{ZGcgk)s_{P;hctW6Q1;$Q1Ps#MD8frY9EEEmP_`wJg4`h>I?b;%sPnq%j4ZX@R z?mDqTY68cmL`AxZd91XzQt$!8lnW)IO=;ALBJdmvK|;X`a^?~Sq7X1BnUbq9fK_r$ zk7G@Y%fokS%M~{cw!79))&&~vj_5K0%wV%`0bss{f?JUAY_4bw3OshlA6*E!*!nxP zcNxhAN20+698?N#xo*-k^9$s}%Q-8zywbw4ZwO?yBfIpEx0(QeHA1o;QUT3! zFnP@waa)Q`UaRA2Mqa+zw$6XYpa19CHh^LC+&!SB-@mm3+No=o&nCU0?fTlbq{Nj-=KG1mT=*x${x>k9x#5`Jq|@<7*MK+<@=?)sQV z#AA4Pn6Z>R7{Zs?lSf9MbrsvKuOuhT3nf01n7h#0G)GR8C^^*R*nS(Y_mX#S#m@$oXE(K$$%V=;{z@-t;gR+xcQ7DEwWJ3u*t?LUQheWH9i$0P2DmSEzkeX_5K7wqJsqU-?@#HH zoe0;Kn(j!c+`D}GRXp}D2@pcX?-1RD20*s+v&#pvL0NYK5^V6Fga)CLj4l`un zFN=39Bp$K0YCB4y1;)MEqV03HGC(0ZW#24q z>_hti8HG=>dom@ir~h2}R5fNZI_Pwc`UTteSNcb605quhGJ9vAW2cP{=vl7nS;PI0 zl0y%bGYL{kuSh52geo59_GXo=*;TzRwRB_>x9SOYd^VJ);~8>F87i#2VxsoaRr9)` z64P~6WQLM$Eq0$F+`Jr(v_jcx4C8%9u}yhxWD=LdEVYFVT&jiOvFFQS@^gcNrk=Q> z7?>Fb0Msnk8*zN@?BHzeAcd+yXD`YC4uwDp=o3}HO)bt+DJU?gc6zr9fe+3Nqhb+Q z0qd=`1~MQWKcJyOA9*ofhLwhLn4)Yx3K%9AMS63Shc?Cgf`25K_2AW|U!yg|+jhD%7J~z|6i7WmvsmZVQ<^IhUxD}Gx4e-30 z!*|m!WU@!A6R);yA8~3=re@org8m7D;tM|T2&XmT@cGmIvI4`PhXy5cD4JK&#OtHohbqZPGxOAGe0b(Nz0yG< zI8&@%DoTYYh@uRBYakX+00VM~nZxtgIiGwa-@xi3W{U`s8oFr z89 zElA?OZMB5VLi8}RyEcqc6P*yGY6Gel@}z!#0RSgJJdzdyFu}Dwh4CQBjR*7v0LmFE(ljv& zWDQdpRG@BT3z7hsdCKiF%3Rd+GM)kw0|wDRF2T|;;piRVLW;OC=;Z`E5YcRq$I;502|1Rn&Qa}TL?p4pvwW4WFMa1CPd*rp z1|#35_D%)Z>jJhOrF`{5)t01nx*2J56hjg|bpQ(?G6GVAXj!BT7>`y#at@-XaxBvT z^}r`Ilb?DpfC5ho;9CYPp-2c&I;g@zWYZNGRDqDuw@6P=^(Ya2k{>9UtvZS%14@SB zMVT6%=xk+tnvifj5sP9I@Bs$!h(;nEK%{EWBT@J$84x`b4!G?y0a|~9+4@99WFJw{ z5D*@lKpVJ0FoTBIunof z)uWzb2~{77byMD-_Eq*pu4SElclxuQ`B#G`IS5eZaw%4Q|1b9RZgFjDA{Bf0&CUWY zvNC{73oC?-4f`*=0OWM>Q!wjAvrh3+K=jJu{{31&>8i4_=74~zsCt6L+tf^c-g?MJWLsH|Qa7krD2i(vd)E=P8DP;Yh$sK0$x5IvHJ^h&KI-Z8wvk zA4(xG#H$FfL8l$SQ*B}>(G4-IGXnca8@uR?wd4hXeN3>H99TR9wp5%8KmuSS9V}x! zp44tjk`f^0GK0Cvc*i+f8e=ohKA;v0}D~3>DC8OyRK=knxY|tYt z3`7ngN%_FBBsen{Q4&Bx|EmeN0j9qm<4>+pXz!H?O$7ki;1YtvvwVOA_&lWj#$W=n z3^FBQ?HE8raYS-_0R!3E(kF}?ixS3S>C?G`7(j}iZ%F`{w8Dj8w6>zDbVS1PXcXw9 zNE0nPRIlZG6fk=kyx-MeAdp{m?v+`~+P%R>xQo~RbDEg#Bk~{Z+bwPE(&lK&?d4yA z^?G%yr$2i`gcbTLI_!tt=yP7K0dN4=_L#Tdw{{NLR9Z3gy2T=>z3Vy$Y8v($g$aIZ z^Z~ygo7lEfXY`D-v|+CxYS1g2LKntD{H#)HZWp#QAm4B^Lr;D*Fd-_JQ!JaXGg6kC zmFsVx;TIXu8eDD(I{}s&3^0r_7A1=2P+DM@^#)-J5Gu*DDcM z`l{<000b^*h=T>GjIqXvxWjm_QcAnniXUfw7w{n9nFUY-RS({$%v+Y`^8K(5h<@pB zu&(Em3c{BA-W40n_Kz6V}>Ol6CHL)-8GW^fDVql++g zk*vw@sm8ZEou=4qfawCreHDBm;w7sREK>=kyx@$dl9^KlIJIUeL5!6jEyc~kifa2S zW*UJY`0^EYSgvUDL&7SA4%0@QskZ#2 z7u+=~dqzXHdvYU0Z}63`wtb}_%T!Xy(OS7ton08=Ro??E_P6Dok9WyXIKOzF|FCM~By_{-BI``(!S(#m*+uuITOImZe6#1#JtE$W zdHqHZmf2x%9Pz&iXjfJdcREpxb85*!UEOOfFoASz!vIMU?g^(nte~pUFSp z1$OZU^fHKmyuyfH1JaqsSYH$B=7J1|($El1q%Hu#qtz&>%>qtDFji{D#!hDTpW=|z zS8=I2$6q`N=Zy%q8j{k4Pi4g9`+XW!2D{p3)~EFF0%-Z@D)(&g<5+l6%ui?%>X9|4tI`B*B%I`O~IvdLDCGTanHZ5*B zJ4MsD<<+lpiqzazrR-uF<8R&IKK-%(vrTqa!7Ob#>XG9O+c$my>X8g2$;|1rht_yHLWBZ~}@0lJK`ZlAJ8 zth@k}6A{BFOEUQ}Nrk`E9YYGCKkm7;_T zew_Efay^#qCn{-d4`%1Z?(Q5sBRX0%coJ`M>qbg{g~Q$!H=418aPhWXxYktWR-vgF z5P7lbtzdr~wNQ18MEnJKhXw6h*VaduQ9mZ{>KyU@02S(6Hx1M*YYbO$R)`MWbGB2Z zeRdo-**^SxU{Gq~oNim2_qL?x#K{;ylkxv+jtBs;AFm5d{tB@Kk^fbY**cVgCcs4a z9d&{WB~ZW{H+}jY6R;`p?)2MoWv=4W(|@*#eQ`8V04Di14L_dodAF3C7xRJE#@PQQ z@pa^fHT(8|yXq8~{+%cBN+dr1^8Q2&brvdLbz7Ncl@4L+^f^_=Thade&jaAd+|mc8 z$K&h>VD9v#p%xM`9jYEMyy%m_-)ND%qiR~aFc2yLnPjcsg_RN~-E==DLX2pB!p3hs zIyw^5x1Z5de71ROWO<$$FeYm1F-6%Zq=KPSSsDi*X`%@PYdprFDlwf~T|;euKQ~rW z%06}MITyyy_4V0e69LRvi`*ukPm1I_qb%5_4_(eqJV*5@W(M(CBR zNL2fdxt=vfp3nGuow?8@WPQG+B<48erS-K%Pem}7q=(PSj(zWXL=d9n4p=19ur?s@1a)>cQ92QLO zbmfUK^yi=2Az^)=j=Vi8Db*7`;LU@#wR;+)AvQo~yI3Ir$1#A%f$7`e8R{4x$bdxB ze+}Ox_Z|iy;XpGUp+W0v3f!vK1ExSYJd+rbl1Bw6kgG|?voL-B3%2#fZTjP^Wi^$t z#%auid!0V5?C#KI6~;D`iaeO&)%?UV2Nf|_ZheY0_+&?PyuCYRHS+V@rTQyr!};My zGS)JhQ9to56HjOFeYE=J@-H44&k(Y~?hTOvg9{pRJvgf|(meBq_XTI4F%Wb)GXvhr z(GmT`Z)CRNa6H(#R7fx{IUy(r^$A{ZJ!6`zu6(dLN3~(UWn7EIYrx1z_R{x7s&px1 zOlZC+cRZN6k_aCv%{Hl$!Q-P{Q-On2J=r=z)&v2DWeLD&ETtje83HH|kVckGmMHmh zQW_}T6WG~lv?vG2Ps^ZD1|-Hjk%@(aQS>4ux>pP1{bejI6S;k^=w>juQZpc)scct$ zgy9L&9^${OzWcq#MqXeN?>jqV!1(}FteV`;46UB#)MxzDS&7^1EzA;Gj(`2pX%x)t zsPY1Yw0?FbI3{vps=;oe_-0D@c}`!NaeVfgCj+=9^sp&ByACM~*YE-!N(|@_p3EHbVy zz)AU=a{T%ddn>qh%g({UwDD3W-ckzh3X&ce@uIzGw3_>@Qr46gNKJs7qPi(!l2=Bp z8?>GDyG`9pHkLw9aCQ;p6w+PZ@QF6D`W|u_4oPgx;yzL=4Y~SX*yc++bUp1t{Z|uK z$qfFU*8f8F!GAN;Z_oIU9h0)oziA-L+*I<5?VN=XF1P=9PGH-%7}Pm#+v}g)GO1mZ zFAsloxcorjrqjyfa=R@Z=y=_cpJX;}6R-TeD}wFuyO8z1(C~LZ1IkXWTsc;p?P>Q4 z!c9L_%+>l{D3~_)u%xzC3)=og`NNH$cOh3^zrgrZx|`T;UE3>;Uigr5MzMBN=ls>% z1wXk4i{3Qv>D50`H$Oexi|}(86ST4Ck+^G`ipQAVA~{v4!tLW86$h}C;fD>0zM@z} z**N-V2DtfdBSIfwvc_`7<;Syp{q|n{;#Ay2P_m)&FFN@Q$%hkWhf#sX+?)PdZJ$#0 zT}H}zWC|Rz_*yT9?eZMa&mV>RJ@J!&Vl6yla&qV(VsdT7{bSPgdxfUUmn18nFL8(; zulC>R@eF-2o?5k+ED{?Ka}~AJhRi&`Jes~cA;okg{=Q4JdiwE z&$UrUPz@{0Ncrs6f!knKYVezSXVedyrV^vBy>zm2>IH(tYcky^hX(wC@KxSn@xMrt zp-FGLrIKOk%!Rb}k{yoseEex>3+Sp~b+|CCmoc8GG_WeUQEJT3J_gpaAdxsjl{T>m z?&pn>1yjQq;_y?qrE;{3vMZTK^doyp+MJ>SpO}R^11F{bTVY+Omed`Czs(-Pr+))_ zYU{(=GOSG`@134r@Tpm}G7-x+nQ*tpN9RNP=kz1H{Zu@AJd{AiSLvcOcF9FBJWm|v z0{sKnK&l0w(slyhl^$-TCS>>pIJi`tG=**U01JJCt(v3muB~ zA(~BsIV!29$LcPJ>s|eNLwRSzQ);)07k79;pBBwxD2>8&3ApwfAkX{`xw$W$gdg;? z0;mc75B6-+4FAR)wL`!6Z#M6LQq>NKV#{&xI5)=6C=?Zj z)YtFliAC2larv?<2sA@eY77$`5WTO`TQGcF(~OMedP_6ILH&|`q1&*dg_bA7mkz=% zeq8N(9=87c#@LoS%+;%;q_Nuhlbb+8YJQm?QWp-=F#5}I`gcCGGGo?(13GegT2A(0 z5sf`9m8Q~8zP7uQU{+}U$F4jIx-}U+GK9S)YtV5w`j0Uq^<#d3Kw-0Q!kE3-J?7lQ z4ErH>dZu(wr8Y*J{eNDG$uj0X1?5OXh*or*%XhE!Urje3-njHYCoL+owWY~%^3X-y ztwYx7T6)_(9+wOEwU+CzM6J}96`K#1ZOAGWuWVsL_GxJw=;U+J&@=zchi{|r2eZCt z=kb&NQ*Rsta6h-jPY9KpPF%$t$VUBjYFVT) z@NwcnQMLg7=MDk}5!D+_Su)IiT=rP5wr=hIQ1{8u-(hvzuWp?%d#97}7^w(px@RY{ zu}50BQZB9yeyBYCBm+L(7H?*_{CNV6(6}3lf>P5pk}M_k4qud#-j_<+^DOWb0O;_~ z9|uiJ^HpnOL`0&4Zzp1II=NB4p^EdkAn#XP90ao5#NWGK+vu;T^)~I6ZE)ofW5{PQ zz15uEK)CE0()n3YQ_EU6>iYV?VOT9kt8;0mt&V*0w6xx%d?qI5gboqi^__*1D?<~P z2zTJ0?l~{_v0eR^kRFziultlmIBkNPYq=>dNhU{XKiqZKD<UuZ#SZj{{rWgI{dT zM0L03)>qrgaBxL|mR!-}WGF~;Q1X5=7)ws=-_*C78>*MTmb~IdCsRKNdP7Y+dAQs~ zj2H0ej}lBVT)dCKoeMz0JusXe{Xj=znHFQI<)JOit`fd2o1r*=aNt#8XJa$nnWH~~ z4r%^jXG4F#%6iAL+Eeqih-k*uni%^V-T^jH0V|zE#Y{}A90DO`D%ifKr@!*`nokyM z44@SickStymmra4MRYMN0QGF?8zz=@k%6cDk@knm*9|EIi|OLmE@dx(wb z{Ol6DKXRwf?6Q6I+=9xDkK)Hma>u(R2A&tgLU7mrn5w$OMAI-amV6B|H8RCqkE$N% z<^8#(kzeY9X-cyy-`caVd(6PQc=c}fzJP!Y`#ewn<$}2ckGqktG`i(=EDV5FF=(#X z!b~w?XGZD2)cyy+)!gPc97reG(x#U^Wn1}R8Rnmqe#ZZ8m%N|SeEmxPd)Mn$t??=o zGmRB;O(S-3_EU|Pd*GE%jFUsOJ;KZ^-T3rEU*T_nvHZV}yP$aij$!%cpoTEtYS!F8 z1ww=C40y+lWc{`G%1b1hkI9L{qIThp4zBqkALdFwiN$6Zx1vAx7+yH`6W}%&pV33u zNL}FH30{+GzI*eoOp!#0xm{SvsDHmwDU#DcLWONCq1NgQjxDEndg#si+0>4i)Jx)3 z()MeO;f+$?l>_^yda91yWxE*!nI5}>ctV#Iv<>*RWBmFv85&!d>Pwk0QYgb3x!!cn zB%{;Cug}9yf8XsAaK5qxHugzC<8%QSaVhg-QkP)+s~eYj+~O-WE#-rIuClM38{AsaPrV+_ ze5&xgs(rlmfGbD{WU&Iai0bcA1LbBlrHb>tjAB8~ z{A?=W-! zWtUrka*T{oXyO2>#|JQ+;5L6v?#4-4ljBw2q#T+rvdMmjiW`@Z^x2ZSRaVD<~Bu(#?H^ShOpA(Lw-&0`*M-$UsF zf^C{QD*zEOw+A_rlsLvci1`RE6}qYqarHZC%OJob5l%kN6hIXkm#_7YEO>Y|qoZ>i zpMXljY`FYFN2N^`;_~m>9%3m>Or1@g?0%^vE2Rjd;Tgk_Ok8hPw~gxa`i@0p_uS~Z zw&-eNHjCPH(3Ic4YX22^JDu04i>C`;Z8D)A{}%lJ1aW*7{N)8RCiA%h%_S1=@j#tC3tAl^csX>*m3_qAr`NVX% zHm1STFY}*@B>X}1iQr>p*xt7HWHOKZ9OvJp3>&R$cGu6v%$=?AbKa0^QQ#R$c%B|D zR{KvbHfrviKr0JRa1xt9zQ}@x?uM+qBZhtuQ`E#y)i~0_mc(SJm6kx&it8QVRm%6;1evre zQ6@@N9)7CGng@LZ35Y4$lwZxUOol0se{E1_#ZR_&ArH$gqP@iLCnek>Uo zbf^NRDk<|&x+S})^MC^@f*VO?ZK2>tG=E-aeB1=TXy|p0Jh`0K!X|}?oVr-qd^TkIE##aKFWvY<943Xpa%7hQj>eS zX~{D$iREDY$xo?8mP6PUE+f*hC+$dYzi z+E-=iKN>rV&d_3HVt#(Vywy8DHTZp?u&-@@;Ey1Vlo$CR?J@S=w>O>y}0 z#%21P5@+jW3bbuMvnI@xJi8svR+e>?1f{!eUR^7AbnVXbi9%Lxj~RM%f!t+l7@16v z(7=1RZIbuKt5J{Q#z2YVgUMT!+SpJoHkBh~VU(*Em>Fd+CUr^wf&gG)m?#P{to;&0 zNU%dB!YBp>FpRL5LVGi`q-i&A3(t9Tc(;8kAk_9*{6iECL-75LqSY;_6ns#CS|tkV z1}AlneH8et9p?8&uvXt&kL~jiJy4ymv4@GMj9B^{=@tZOB0juT^764OdmDdOed;(y zj;a0r54*+i`_a`?mTtP(3Hg=jex9@!iAw69u10Kre)q@6MQV5Y3ag3t!q_eQLOQtL zE#_p7Z_r66r|X5YBiACzE%($X_6MwwpWXgb)6;i+6FcYLQhrhPskrlX|M!imAs0hI zw00Py-0S=e)~p$-lg3)udNM&2lJ%!dP2cuKu8j!O|B!T+aZUbTAK%940i#EcZWu69 zlp0;52h!b*QtIf@-Jo=fw4fq28l*wMpi40jR1oFf?|<*XUf1L6b*}S0=X*Zq^L|5( zqy*pzvjR_BjLZD@IKa>f!IW_bAX5WN|Lnv>B%J^urXGUlG84}zL+L1r5UeEN%F#S9 z1VRneasedMlZ|a{V{J;PLD0vx^9=wA2;w)g2<6C48w)rhHDquzs)42hM`MLJK}0=r z3!9Q470Fd`iiqt7GYg5$*54Hss_&PGfa9vd%lYX*k&RJ$kXLF%Y94UAPtQ`{4(aP2 z)P|LQhY06WC5F()#Kb}Yfk3-%RZn7#Mezq6@rDkyBhP5Yf!GfM zSqUJ7$Zq#1XBlQQN@=`c(<{5TPI@^Gb9R*f_4y50N)m#pK}bAyLsx`q_A?!aTC&;S zdMx>82KVRPSa9;ht68=%1ymSR7#jNF@>UF*9sAIS|m%zp2^ zbA;)4i*!G^`TA?%rnCHAqlD?k&8o$Hec2}ee|Gis$~^KfW_sfl`CJ*Pgn2OxZ#1QO zG+J}XWDcjr;>Lt|v{MD4)FfFHvE~_|sKgrZH(zclZ^j6Tcz@xKog6fjuGwoMwKm*8 zqBhks?lpa^-gjt5y04w#hlBF{6yD8Yk`I|k!6&E1pF)|m==1wgZK*l##FSp!=Hiz6 z5zz(#ccMQ&O8kkuqx{th zy>vJgU3fd7Sm22fPgWiBwoZkWAe+(I!$+N*v^zrv8Ro1V()T3b;=I+$=FFo(XNK?0 z>Re3Quw~zYRzv}CLW#-_R15Rb%P@rp?~>V8G@!|weNpTY6JYs*Muvz@vl^iv& zzLHS&n*BHbnw__gU?5Jt&Op=s?vvi%68x(ZY`jUgoMK-3F8?AK7FtdhCA;+h*NqX-SDw-s#+s@R^M5$ZkZe|APvxdjD#{%xN zKk*<^2x`BBjGBuYhY5;WIW&i(Bp)7sMt@;>v`as4pa*-%J)WPVFRA@WE*tmmeFJ9= z7erEiXisueCei#&HqvsKS+!XSP9c-=+D_|z)6lbqhm?r&;WE` zG#Za)mUH}P#Xr1r5RuP+@c!LqlFt`7U{)c9MK!WACegkzM$1vhAK_yQW+w@B_J|tm z;ssXO@HWaTvgL!QOK@s+VL1gRV=6jox1#+s7ty&|iVCe+OXc#-0#w6?}Ue@*Da z(#BQLUo=HkXC?_tCVXGBdAQ z;~SYRpVmoMg~f|^tcL;ZXV-gLIBS$0`t;6gpWB?5LEU&u3kQ`&6`L~=Yr;?hY@1(y z#$NRRu^{1K{sIOK`>XFl(#VqN%MsHCdj+I4U~wLD9I7J*HwhI=ai|JV<-3bWqB~Xo z#lqK9RPLQLJdJ+$@nxa@KSx2TWK9EPkc=Pd2b0XXX}pmezC>!B>ZxfA?p_g@5a>(S zNczqwqFs=$j-ymW6u8&{+5vo?bKL{D`k{2efv-=%UWzN0huMM-4Zp|Az== zPe%OLlI0ni$G0C~+Sfnw^Y*TDbDTd6Z6MvbBNBP5!3QS-mb*pyC0oK*8%RL}xFZ-V zO!$WXXzWaeIZPG{%|pnzH{K0)KD#j@I$`qE!)b(9x<9&#&ke!u00bF(e zqGxKs4bo~O6s&PojbQ&bEquz*OtHnye7Oi{idv9R9v?KPZ<9PD`pdw9nkLoMMc=zT z_pp!ABM-g-7@QqI8D+?WGDH)-4s35#<_Oi?%J&06gLWZNXcA+Gu_Cdq!dJf3p)!nK z=>_~>Mji-xAZFQhdmi~rx7$b^QDl-;=X}|vOGbzZoNQCy{Pnn!6smd#eE4W4aBNjx zrcVYuy@O!B8}|pae6JkWU*ctM@jhTl89u|oWzpR#xoTP+B)e^w+CVf;hjIPqI+@a_ zgVqY-qY#ucqo57HM3*rALOoi&mzZ>?9I{DK_ZzH>TcSUl{|K|v@{Mw0R~n_<`NtDMD@?S zFM9L}02udZ3vmYw5piiL!QNO9!DSLq+>hZRL=<9haCRNcT+2Yl0ymO!_rcu~vzcsk zE8X@TTF1)3Q1gnS`7})2SZ*HWulzR}YAm(%GMYN*CDKCssj!V7V99W!hX&t9h1lI+ zzkR&wIOyE|5+?CeIT6s(X=X{wB1U@|2hUe>APZ(FL0@I!^PvkSmxlB`Zg=b+$j`M% zHd#=F4cw6T5#)(5#;3Ooa&Llga-u(9{(AX);oZGjS^oR~yg!&BI8r~}{M~O5(Rlgs z@86GEOGXBx(v-AVf`U+Ii-n5^Xtc)h*-v<*uIk~8i^!f!PWLlC~lFoh7f8MO>bM%JVX zAB%D`D4OWeW~;>)2;#rrSEv5`*-%`(VLtCAkLJaq-xRTPIqRf|Nf7a*LXMl|N}=^5 z^2g@YF29YRQF^a^3w$IsW`P6Rx56jgc`m0XN`;r3aj2F9Jr30;(AZ&p&C$V^GO3X* zGtjf>sambN⋼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

    UZtnvjURG4I2&%5QD+|W6AM>aT7*5+xEkuk}j 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

    &*vb?PIqaW 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%0ASTqPhNJL?rM+KybZLqLUSrj-p0 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

    Nojo}0ETT#m{P;wL)o-w(GK2f5qX;L&n%DjU2 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

    xttpdn7V%XxNYJKkeB9U{l*Kc|3EF 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

    F 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%0D(diirZ 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

      4SWpgCkyzH4 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

      Jnljt1Fx{ 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

        CA7+A7Ub8 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%0A_-G$sgk=|m*=0(UeJot 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≧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 tL*V~!fs{S{9~c File.join('.symlinks', 'plugins', 'agora_rtc_engine', 'ios') end post_install do |installer| diff --git a/example/ios/Runner.xcodeproj/project.pbxproj b/example/ios/Runner.xcodeproj/project.pbxproj index de127bc17..52069fb8c 100644 --- a/example/ios/Runner.xcodeproj/project.pbxproj +++ b/example/ios/Runner.xcodeproj/project.pbxproj @@ -9,7 +9,6 @@ /* Begin PBXBuildFile section */ 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; }; 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; }; - 5E9D826C4B1F29399F8A7742 /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 28CEF344452C45083E367B0C /* Pods_Runner.framework */; }; 6D48449932DC5CD432350C00 /* Pods_RunnerTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 43CA39DDEDE840FF44D1F750 /* Pods_RunnerTests.framework */; }; 711018242727DE9A003816A9 /* ExternalAudio.mm in Sources */ = {isa = PBXBuildFile; fileRef = 7110181E2727DE9A003816A9 /* ExternalAudio.mm */; }; 711018252727DE9A003816A9 /* AudioWriteToFile.m in Sources */ = {isa = PBXBuildFile; fileRef = 711018222727DE9A003816A9 /* AudioWriteToFile.m */; }; @@ -20,9 +19,11 @@ 71E2A2A32722C75F00C7B7BC /* FakeAgoraRtcEngineKit.swift in Sources */ = {isa = PBXBuildFile; fileRef = 71E2A2A02722C75F00C7B7BC /* FakeAgoraRtcEngineKit.swift */; }; 71E2A2A52722C80800C7B7BC /* RunnerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 71E2A2A42722C80800C7B7BC /* RunnerTests.swift */; }; 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; }; + 8ED9C0F130785918FB2F9BDF /* Pods_RunnerTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B024101BDAB90E5F0DAD65EB /* Pods_RunnerTests.framework */; }; 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; }; 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; }; 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; }; + 9CC1AE658CEAEC376753F939 /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0D63EBE14FBAC09B68B4589D /* Pods_Runner.framework */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -36,6 +37,16 @@ /* End PBXContainerItemProxy section */ /* Begin PBXCopyFilesBuildPhase section */ + 71BE5485275F3E23001A34FA /* Embed App Extensions */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = ""; + dstSubfolderSpec = 13; + files = ( + ); + name = "Embed App Extensions"; + runOnlyForDeploymentPostprocessing = 0; + }; 9705A1C41CF9048500538489 /* Embed Frameworks */ = { isa = PBXCopyFilesBuildPhase; buildActionMask = 2147483647; @@ -49,10 +60,11 @@ /* End PBXCopyFilesBuildPhase section */ /* Begin PBXFileReference section */ + 0D63EBE14FBAC09B68B4589D /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = ""; }; 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = ""; }; 1A91074EB53F0A7683F35F2E /* Pods-RunnerTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.debug.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.debug.xcconfig"; sourceTree = ""; }; - 28CEF344452C45083E367B0C /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 1B1F7CB3BFED3AD00E90B883 /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = ""; }; 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = ""; }; 43CA39DDEDE840FF44D1F750 /* Pods_RunnerTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_RunnerTests.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 592BF9E1006B18851CF75B6B /* Pods-RunnerTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.release.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.release.xcconfig"; sourceTree = ""; }; @@ -66,6 +78,7 @@ 711018272727E05A003816A9 /* CustomCaptureAudioPlugin.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CustomCaptureAudioPlugin.swift; sourceTree = ""; }; 715C8389273012A30080FA35 /* CustomCaptureAudio.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CustomCaptureAudio.m; sourceTree = ""; }; 715C838A273012A30080FA35 /* CustomCaptureAudio.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CustomCaptureAudio.h; sourceTree = ""; }; + 71BE5478275F3E23001A34FA /* AuthenticationServices.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AuthenticationServices.framework; path = System/Library/Frameworks/AuthenticationServices.framework; sourceTree = SDKROOT; }; 71E2A2932722C73000C7B7BC /* RunnerTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RunnerTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 71E2A29E2722C75F00C7B7BC /* OCTestRtcEnginePlugin.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OCTestRtcEnginePlugin.m; sourceTree = ""; }; 71E2A29F2722C75F00C7B7BC /* OCTestRtcEnginePlugin.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OCTestRtcEnginePlugin.h; sourceTree = ""; }; @@ -74,7 +87,6 @@ 71E2A2A42722C80800C7B7BC /* RunnerTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RunnerTests.swift; sourceTree = ""; }; 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = ""; }; 74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; - 79D5929EA4BAFFBDCB2B85F3 /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = ""; }; 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = ""; }; 87354120531BDA009F6E9C5B /* Pods-RunnerTests.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.profile.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.profile.xcconfig"; sourceTree = ""; }; 8C103D1D59FED56CD8C8069D /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = ""; }; @@ -85,7 +97,8 @@ 97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - E5064CBFB9AE669943232E3B /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = ""; }; + B024101BDAB90E5F0DAD65EB /* Pods_RunnerTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_RunnerTests.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + C34F4431D4464E5FF8C2CC66 /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -94,6 +107,7 @@ buildActionMask = 2147483647; files = ( 6D48449932DC5CD432350C00 /* Pods_RunnerTests.framework in Frameworks */, + 8ED9C0F130785918FB2F9BDF /* Pods_RunnerTests.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -101,7 +115,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - 5E9D826C4B1F29399F8A7742 /* Pods_Runner.framework in Frameworks */, + 9CC1AE658CEAEC376753F939 /* Pods_Runner.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -111,25 +125,16 @@ 274CC1CD2893CBA2D325BCDE /* Pods */ = { isa = PBXGroup; children = ( - 79D5929EA4BAFFBDCB2B85F3 /* Pods-Runner.debug.xcconfig */, 8C103D1D59FED56CD8C8069D /* Pods-Runner.release.xcconfig */, - E5064CBFB9AE669943232E3B /* Pods-Runner.profile.xcconfig */, 1A91074EB53F0A7683F35F2E /* Pods-RunnerTests.debug.xcconfig */, 592BF9E1006B18851CF75B6B /* Pods-RunnerTests.release.xcconfig */, 87354120531BDA009F6E9C5B /* Pods-RunnerTests.profile.xcconfig */, + C34F4431D4464E5FF8C2CC66 /* Pods-Runner.debug.xcconfig */, + 1B1F7CB3BFED3AD00E90B883 /* Pods-Runner.profile.xcconfig */, ); path = Pods; sourceTree = ""; }; - 55FF16860C15246CB811C77E /* Frameworks */ = { - isa = PBXGroup; - children = ( - 28CEF344452C45083E367B0C /* Pods_Runner.framework */, - 43CA39DDEDE840FF44D1F750 /* Pods_RunnerTests.framework */, - ); - name = Frameworks; - sourceTree = ""; - }; 711018292727FFF1003816A9 /* CustomCaptureAudio */ = { isa = PBXGroup; children = ( @@ -147,6 +152,14 @@ path = CustomCaptureAudio; sourceTree = ""; }; + 71BE544627561088001A34FA /* Recovered References */ = { + isa = PBXGroup; + children = ( + 43CA39DDEDE840FF44D1F750 /* Pods_RunnerTests.framework */, + ); + name = "Recovered References"; + sourceTree = ""; + }; 71E2A2942722C73000C7B7BC /* RunnerTests */ = { isa = PBXGroup; children = ( @@ -177,8 +190,9 @@ 97C146F01CF9000F007C117D /* Runner */, 71E2A2942722C73000C7B7BC /* RunnerTests */, 97C146EF1CF9000F007C117D /* Products */, - 55FF16860C15246CB811C77E /* Frameworks */, 274CC1CD2893CBA2D325BCDE /* Pods */, + 9DAFBFA0C30EA956162CE1B1 /* Frameworks */, + 71BE544627561088001A34FA /* Recovered References */, ); sourceTree = ""; }; @@ -215,6 +229,16 @@ name = "Supporting Files"; sourceTree = ""; }; + 9DAFBFA0C30EA956162CE1B1 /* Frameworks */ = { + isa = PBXGroup; + children = ( + 0D63EBE14FBAC09B68B4589D /* Pods_Runner.framework */, + B024101BDAB90E5F0DAD65EB /* Pods_RunnerTests.framework */, + 71BE5478275F3E23001A34FA /* AuthenticationServices.framework */, + ); + name = Frameworks; + sourceTree = ""; + }; /* End PBXGroup section */ /* Begin PBXNativeTarget section */ @@ -241,14 +265,15 @@ isa = PBXNativeTarget; buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */; buildPhases = ( - F05343AA277E4D9546495707 /* [CP] Check Pods Manifest.lock */, + E683325EB86E5F0243098C77 /* [CP] Check Pods Manifest.lock */, 9740EEB61CF901F6004384FC /* Run Script */, 97C146EA1CF9000F007C117D /* Sources */, 97C146EB1CF9000F007C117D /* Frameworks */, 97C146EC1CF9000F007C117D /* Resources */, 9705A1C41CF9048500538489 /* Embed Frameworks */, 3B06AD1E1E4923F5004D2608 /* Thin Binary */, - 91AF94D509E70D21F3F5445F /* [CP] Embed Pods Frameworks */, + C9AA703A6D4BE4F427A8671B /* [CP] Embed Pods Frameworks */, + 71BE5485275F3E23001A34FA /* Embed App Extensions */, ); buildRules = ( ); @@ -266,7 +291,7 @@ isa = PBXProject; attributes = { LastSwiftUpdateCheck = 1300; - LastUpgradeCheck = 1020; + LastUpgradeCheck = 1300; ORGANIZATIONNAME = ""; TargetAttributes = { 71E2A2922722C73000C7B7BC = { @@ -335,36 +360,36 @@ shellPath = /bin/sh; shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" embed_and_thin"; }; - 91AF94D509E70D21F3F5445F /* [CP] Embed Pods Frameworks */ = { + 9740EEB61CF901F6004384FC /* Run Script */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); - inputFileListPaths = ( - "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-input-files.xcfilelist", + inputPaths = ( ); - name = "[CP] Embed Pods Frameworks"; - outputFileListPaths = ( - "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-output-files.xcfilelist", + name = "Run Script"; + outputPaths = ( ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n"; - showEnvVarsInLog = 0; + shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build"; }; - 9740EEB61CF901F6004384FC /* Run Script */ = { + C9AA703A6D4BE4F427A8671B /* [CP] Embed Pods Frameworks */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); - inputPaths = ( + inputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-input-files.xcfilelist", ); - name = "Run Script"; - outputPaths = ( + name = "[CP] Embed Pods Frameworks"; + outputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-output-files.xcfilelist", ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build"; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n"; + showEnvVarsInLog = 0; }; E1E7D4EFC06175BC6CE45386 /* [CP] Check Pods Manifest.lock */ = { isa = PBXShellScriptBuildPhase; @@ -388,7 +413,7 @@ shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; showEnvVarsInLog = 0; }; - F05343AA277E4D9546495707 /* [CP] Check Pods Manifest.lock */ = { + E683325EB86E5F0243098C77 /* [CP] Check Pods Manifest.lock */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( @@ -564,8 +589,10 @@ CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_STYLE = Automatic; CURRENT_PROJECT_VERSION = 1; + DEVELOPMENT_TEAM = ""; GCC_C_LANGUAGE_STANDARD = gnu11; GENERATE_INFOPLIST_FILE = YES; IPHONEOS_DEPLOYMENT_TARGET = 15.0; @@ -577,8 +604,9 @@ MARKETING_VERSION = 1.0; MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; MTL_FAST_MATH = YES; - PRODUCT_BUNDLE_IDENTIFIER = io.agora.RunnerTests; + PRODUCT_BUNDLE_IDENTIFIER = io.agora.agoraRtcEngineExample; PRODUCT_NAME = "$(TARGET_NAME)"; + PROVISIONING_PROFILE_SPECIFIER = ""; SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; SWIFT_EMIT_LOC_STRINGS = NO; SWIFT_OBJC_BRIDGING_HEADER = "RunnerTests/RunnerTests-Bridging-Header.h"; @@ -601,8 +629,10 @@ CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_STYLE = Automatic; CURRENT_PROJECT_VERSION = 1; + DEVELOPMENT_TEAM = ""; GCC_C_LANGUAGE_STANDARD = gnu11; GENERATE_INFOPLIST_FILE = YES; IPHONEOS_DEPLOYMENT_TARGET = 15.0; @@ -613,8 +643,9 @@ ); MARKETING_VERSION = 1.0; MTL_FAST_MATH = YES; - PRODUCT_BUNDLE_IDENTIFIER = io.agora.RunnerTests; + PRODUCT_BUNDLE_IDENTIFIER = io.agora.agoraRtcEngineExample; PRODUCT_NAME = "$(TARGET_NAME)"; + PROVISIONING_PROFILE_SPECIFIER = ""; SWIFT_EMIT_LOC_STRINGS = NO; SWIFT_OBJC_BRIDGING_HEADER = "RunnerTests/RunnerTests-Bridging-Header.h"; SWIFT_VERSION = 5.0; @@ -635,8 +666,10 @@ CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_STYLE = Automatic; CURRENT_PROJECT_VERSION = 1; + DEVELOPMENT_TEAM = ""; GCC_C_LANGUAGE_STANDARD = gnu11; GENERATE_INFOPLIST_FILE = YES; IPHONEOS_DEPLOYMENT_TARGET = 15.0; @@ -647,8 +680,9 @@ ); MARKETING_VERSION = 1.0; MTL_FAST_MATH = YES; - PRODUCT_BUNDLE_IDENTIFIER = io.agora.RunnerTests; + PRODUCT_BUNDLE_IDENTIFIER = io.agora.agoraRtcEngineExample; PRODUCT_NAME = "$(TARGET_NAME)"; + PROVISIONING_PROFILE_SPECIFIER = ""; SWIFT_EMIT_LOC_STRINGS = NO; SWIFT_OBJC_BRIDGING_HEADER = "RunnerTests/RunnerTests-Bridging-Header.h"; SWIFT_VERSION = 5.0; @@ -774,6 +808,7 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_ENABLE_MODULES = YES; CODE_SIGN_IDENTITY = "Apple Development"; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "Apple Development"; CODE_SIGN_STYLE = Automatic; CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; DEVELOPMENT_TEAM = ""; diff --git a/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme index 640bba534..486d0d017 100644 --- a/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme +++ b/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme @@ -1,6 +1,6 @@ Int32 { - return 0 - } } diff --git a/example/ios/RunnerTests/RunnerTests.swift b/example/ios/RunnerTests/RunnerTests.swift index db425fb87..b36a91009 100644 --- a/example/ios/RunnerTests/RunnerTests.swift +++ b/example/ios/RunnerTests/RunnerTests.swift @@ -1,91 +1,92 @@ import XCTest @testable import agora_rtc_engine -class FakeAgoraRtcEngineKitFactory : AgoraRtcEngineKitFactory { - private var rtcEngineKit: AgoraRtcEngineKit! - - init(_ rtcEngineKit: AgoraRtcEngineKit) { - self.rtcEngineKit = rtcEngineKit - } - override func create(_ params: NSDictionary, _ delegate: RtcEngineEventHandler) -> AgoraRtcEngineKit? { - return self.rtcEngineKit - } -} - -class TestRtcEnginePlugin : NSObject, RtcEnginePlugin { - var engine: AgoraRtcEngineKit? = nil - var isRtcEngineCreated: Bool = false - var isRtcEngineDestroyed: Bool = false - - func onRtcEngineCreated(_ rtcEngine: AgoraRtcEngineKit?) { - engine = rtcEngine - isRtcEngineCreated = true - } - - func onRtcEngineDestroyed() { - isRtcEngineDestroyed = true - } -} - -class RunnerTests: XCTestCase { - - private var rtcEngineKit: AgoraRtcEngineKit! - private var rtcEngineManager: RtcEngineManager! - - override func setUpWithError() throws { - rtcEngineKit = FakeAgoraRtcEngineKit() - rtcEngineManager = RtcEngineManager( - {(_, _) -> Void in }, - FakeAgoraRtcEngineKitFactory(rtcEngineKit)) - } - - override func tearDownWithError() throws { - // Put teardown code here. This method is called after the invocation of each test method in the class. - } - - func testShouldCallPluginCallback() { - let plugin = TestRtcEnginePlugin() - - RtcEnginePluginRegistrant.register(plugin) - - - rtcEngineManager.create(["appType": 0], ResultCallback()) - XCTAssertTrue(plugin.isRtcEngineCreated) - XCTAssertEqual(rtcEngineKit, plugin.engine) - - rtcEngineManager.destroy(ResultCallback()) - XCTAssertTrue(plugin.isRtcEngineDestroyed) - XCTAssertNil(rtcEngineManager.engine) - - RtcEnginePluginRegistrant.unregister(plugin) - } - - func testShouldCallOCPluginCallback() { - let plugin = OCTestRtcEnginePlugin() - - plugin.registerSelf() - - rtcEngineManager.create(["appType": 0], ResultCallback()) - XCTAssertTrue(plugin.isRtcEngineCreated) - - rtcEngineManager.destroy(ResultCallback()) - XCTAssertTrue(plugin.isRtcEngineDestroyed) - XCTAssertNil(rtcEngineManager.engine) - - plugin.unregisterSelf() - } - - func testShouldNotCallPluginCallbackAfterUnregister() { - let plugin = TestRtcEnginePlugin() - - RtcEnginePluginRegistrant.register(plugin) - RtcEnginePluginRegistrant.unregister(plugin) - - rtcEngineManager.create(["appType": 0], ResultCallback()) - rtcEngineManager.destroy(ResultCallback()) - - XCTAssertFalse(plugin.isRtcEngineCreated) - XCTAssertFalse(plugin.isRtcEngineDestroyed) - } - -} +// TODO(littlegnal): Re-enable test after MS-88689 done +//class FakeAgoraRtcEngineKitFactory : AgoraRtcEngineKitFactory { +// private var rtcEngineKit: AgoraRtcEngineKit! +// +// init(_ rtcEngineKit: AgoraRtcEngineKit) { +// self.rtcEngineKit = rtcEngineKit +// } +// override func create(_ params: NSDictionary, _ delegate: RtcEngineEventHandler) -> AgoraRtcEngineKit? { +// return self.rtcEngineKit +// } +//} +// +//class TestRtcEnginePlugin : NSObject, RtcEnginePlugin { +// var engine: AgoraRtcEngineKit? = nil +// var isRtcEngineCreated: Bool = false +// var isRtcEngineDestroyed: Bool = false +// +// func onRtcEngineCreated(_ rtcEngine: AgoraRtcEngineKit?) { +// engine = rtcEngine +// isRtcEngineCreated = true +// } +// +// func onRtcEngineDestroyed() { +// isRtcEngineDestroyed = true +// } +//} +// +//class RunnerTests: XCTestCase { +// +// private var rtcEngineKit: AgoraRtcEngineKit! +// private var rtcEngineManager: RtcEngineManager! +// +// override func setUpWithError() throws { +// rtcEngineKit = FakeAgoraRtcEngineKit() +// rtcEngineManager = RtcEngineManager( +// {(_, _) -> Void in }, +// FakeAgoraRtcEngineKitFactory(rtcEngineKit)) +// } +// +// override func tearDownWithError() throws { +// // Put teardown code here. This method is called after the invocation of each test method in the class. +// } +// +// func testShouldCallPluginCallback() { +// let plugin = TestRtcEnginePlugin() +// +// RtcEnginePluginRegistrant.register(plugin) +// +// +// rtcEngineManager.create(["appType": 0], ResultCallback()) +// XCTAssertTrue(plugin.isRtcEngineCreated) +// XCTAssertEqual(rtcEngineKit, plugin.engine) +// +// rtcEngineManager.destroy(ResultCallback()) +// XCTAssertTrue(plugin.isRtcEngineDestroyed) +// XCTAssertNil(rtcEngineManager.engine) +// +// RtcEnginePluginRegistrant.unregister(plugin) +// } +// +// func testShouldCallOCPluginCallback() { +// let plugin = OCTestRtcEnginePlugin() +// +// plugin.registerSelf() +// +// rtcEngineManager.create(["appType": 0], ResultCallback()) +// XCTAssertTrue(plugin.isRtcEngineCreated) +// +// rtcEngineManager.destroy(ResultCallback()) +// XCTAssertTrue(plugin.isRtcEngineDestroyed) +// XCTAssertNil(rtcEngineManager.engine) +// +// plugin.unregisterSelf() +// } +// +// func testShouldNotCallPluginCallbackAfterUnregister() { +// let plugin = TestRtcEnginePlugin() +// +// RtcEnginePluginRegistrant.register(plugin) +// RtcEnginePluginRegistrant.unregister(plugin) +// +// rtcEngineManager.create(["appType": 0], ResultCallback()) +// rtcEngineManager.destroy(ResultCallback()) +// +// XCTAssertFalse(plugin.isRtcEngineCreated) +// XCTAssertFalse(plugin.isRtcEngineDestroyed) +// } +// +//} diff --git a/example/lib/config/agora.config.dart b/example/lib/config/agora.config.dart index 5cc0eeb40..036bf511b 100644 --- a/example/lib/config/agora.config.dart +++ b/example/lib/config/agora.config.dart @@ -1,14 +1,31 @@ /// Get your own App ID at https://dashboard.agora.io/ -const String appId = ''; +String get appId { + // Allow pass an `appId` as an environment variable with name `TEST_APP_ID` by using --dart-define + return const String.fromEnvironment('TEST_APP_ID', + defaultValue: ''); +} /// Please refer to https://docs.agora.io/en/Agora%20Platform/token -const String token = ''; +String get token { + // Allow pass a `token` as an environment variable with name `TEST_TOEKN` by using --dart-define + return const String.fromEnvironment('TEST_TOEKN', + defaultValue: ''); +} /// Your channel ID -const String channelId = ''; +String get channelId { + // Allow pass a `channelId` as an environment variable with name `TEST_CHANNEL_ID` by using --dart-define + return const String.fromEnvironment( + 'TEST_CHANNEL_ID', + defaultValue: '', + ); +} /// Your int user ID const int uid = 0; +/// Your user ID for the screen sharing +const int screenSharingUid = 10; + /// Your string user ID const String stringUid = '0'; diff --git a/example/lib/examples/advanced/audio_mixing/audio_mixing.dart b/example/lib/examples/advanced/audio_mixing/audio_mixing.dart new file mode 100644 index 000000000..1e969d4dd --- /dev/null +++ b/example/lib/examples/advanced/audio_mixing/audio_mixing.dart @@ -0,0 +1,262 @@ +import 'dart:async'; + +import 'package:agora_rtc_engine/rtc_engine.dart'; +import 'package:agora_rtc_engine_example/config/agora.config.dart' as config; +import 'package:agora_rtc_engine_example/examples/log_sink.dart'; +import 'package:flutter/cupertino.dart'; +import 'package:flutter/foundation.dart'; +import 'package:flutter/material.dart'; +import 'package:permission_handler/permission_handler.dart'; + +/// AudioMixing Example +class AudioMixing extends StatefulWidget { + @override + State createState() => _AudioMixingState(); +} + +class _AudioMixingState extends State { + late final RtcEngine _engine; + String channelId = config.channelId; + bool isJoined = false, + openMicrophone = true, + enableSpeakerphone = true, + playEffect = false; + TextEditingController? _controller; + + bool _isStartedAudioMixing = false; + bool _loopback = false; + bool _replace = false; + double _cycle = 1.0; + double _startPos = 1000; + + @override + void initState() { + super.initState(); + _controller = TextEditingController(text: channelId); + _initEngine(); + } + + @override + void reassemble() { + super.reassemble(); + _destroy(); + } + + @override + void dispose() { + super.dispose(); + _destroy(); + } + + Future _initEngine() async { + _engine = await RtcEngine.createWithContext(RtcEngineContext(config.appId)); + this._addListeners(); + + await _engine.enableAudio(); + await _engine.setChannelProfile(ChannelProfile.LiveBroadcasting); + await _engine.setClientRole(ClientRole.Broadcaster); + } + + void _addListeners() { + _engine.setEventHandler(RtcEngineEventHandler( + warning: (warningCode) { + logSink.log('warning ${warningCode}'); + }, + error: (errorCode) { + logSink.log('error ${errorCode}'); + }, + joinChannelSuccess: (channel, uid, elapsed) { + logSink.log( + 'joinChannelSuccess channel: ${channel}, uid: ${uid}, elapsed: ${elapsed}'); + setState(() { + isJoined = true; + }); + }, + leaveChannel: (stats) async { + logSink.log('leaveChannel ${stats.toJson()}'); + setState(() { + isJoined = false; + }); + }, + audioMixingFinished: () { + logSink.log('audioMixingFinished'); + }, + audioMixingStateChanged: ( + AudioMixingStateCode state, + AudioMixingReason reason, + ) { + logSink.log( + 'audioMixingStateChanged state:${state.toString()}, reason: ${reason.toString()}}'); + }, + remoteAudioMixingBegin: () { + logSink.log('remoteAudioMixingBegin'); + }, + remoteAudioMixingEnd: () { + logSink.log('remoteAudioMixingEnd'); + }, + )); + } + + Future _destroy() async { + await _engine.leaveChannel(); + await _engine.destroy(); + } + + Future _joinChannel() async { + if (defaultTargetPlatform == TargetPlatform.android) { + await Permission.microphone.request(); + } + + await _engine + .joinChannel(config.token, config.channelId, null, config.uid) + .catchError((onError) { + logSink.log('error ${onError.toString()}'); + }); + } + + Future _leaveChannel() async { + await _stopAudioMixing(); + _isStartedAudioMixing = false; + _loopback = false; + _replace = false; + _cycle = 1.0; + _startPos = 0; + await _engine.leaveChannel(); + } + + Future _startAudioMixing() async { + final filePath = await _engine + .getAssetAbsolutePath('assets/audio_mixing/Agora.io-Interactions.mp3'); + await _engine.startAudioMixing( + filePath!, + _loopback, + _replace, + _cycle.toInt(), + _startPos.toInt(), + ); + setState(() { + _isStartedAudioMixing = true; + }); + } + + Future _stopAudioMixing() async { + await _engine.stopAudioMixing(); + setState(() { + _isStartedAudioMixing = false; + }); + } + + @override + Widget build(BuildContext context) { + return Column( + children: [ + TextField( + controller: _controller, + decoration: InputDecoration(hintText: 'Channel ID'), + onChanged: (text) { + setState(() { + channelId = text; + }); + }, + ), + Row( + children: [ + Expanded( + flex: 1, + child: ElevatedButton( + onPressed: isJoined ? this._leaveChannel : this._joinChannel, + child: Text('${isJoined ? 'Leave' : 'Join'} channel'), + ), + ) + ], + ), + if (isJoined) + Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row(mainAxisSize: MainAxisSize.min, children: [ + Text('loopback: '), + Switch( + value: _loopback, + onChanged: _isStartedAudioMixing + ? null + : (changed) { + setState(() { + _loopback = changed; + }); + }, + activeTrackColor: Colors.grey[350], + activeColor: Colors.white, + ) + ]), + Row(mainAxisSize: MainAxisSize.min, children: [ + Text('replace: '), + Switch( + value: _replace, + onChanged: _isStartedAudioMixing + ? null + : (changed) { + setState(() { + _replace = changed; + }); + }, + activeTrackColor: Colors.grey[350], + activeColor: Colors.white, + ) + ]), + Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + Text('cycle:'), + Slider( + value: _cycle, + min: 0.0, + max: 10.0, + divisions: 10, + label: 'cycle value ${_cycle.toInt()}', + onChanged: _isStartedAudioMixing + ? null + : (double value) { + setState(() { + _cycle = value; + }); + }, + ) + ], + ), + Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + Text('startPos:'), + Slider( + value: _startPos, + min: 1000, + max: 5000, + divisions: 100, + label: 'startPos value ${_startPos / 1000.0}s', + onChanged: (double value) { + setState(() { + _startPos = value; + }); + + if (_isStartedAudioMixing) { + _engine.setAudioMixingPosition(_startPos.toInt()); + } + }, + ) + ], + ), + ElevatedButton( + onPressed: !_isStartedAudioMixing + ? this._startAudioMixing + : this._stopAudioMixing, + child: Text( + '${_isStartedAudioMixing ? 'Stop' : 'Start'} Audio Mixing'), + ), + ], + ), + ], + ); + } +} diff --git a/example/lib/examples/advanced/channel_media_relay/channel_media_relay.dart b/example/lib/examples/advanced/channel_media_relay/channel_media_relay.dart index 2b0b4db2a..549c3c8b3 100644 --- a/example/lib/examples/advanced/channel_media_relay/channel_media_relay.dart +++ b/example/lib/examples/advanced/channel_media_relay/channel_media_relay.dart @@ -1,10 +1,8 @@ -import 'dart:developer'; - import 'package:agora_rtc_engine/rtc_engine.dart'; import 'package:agora_rtc_engine/rtc_local_view.dart' as RtcLocalView; import 'package:agora_rtc_engine/rtc_remote_view.dart' as RtcRemoteView; import 'package:agora_rtc_engine_example/config/agora.config.dart' as config; -import 'package:flutter/cupertino.dart'; +import 'package:agora_rtc_engine_example/examples/log_sink.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:permission_handler/permission_handler.dart'; @@ -20,9 +18,13 @@ class _State extends State { bool isJoined = false; int? remoteUid; bool isRelaying = false; + late final TextEditingController _channelMediaRelayController; + late final TextEditingController _channelController; @override void initState() { + _channelMediaRelayController = TextEditingController(); + _channelController = TextEditingController(text: config.channelId); super.initState(); } @@ -46,68 +48,72 @@ class _State extends State { await _engine.setChannelProfile(ChannelProfile.LiveBroadcasting); await _engine.setClientRole(ClientRole.Broadcaster); - // Set audio route to speaker - await _engine.setDefaultAudioRoutetoSpeakerphone(true); - // start joining channel // 1. Users can only see each other after they join the // same channel successfully using the same app id. // 2. If app certificate is turned on at dashboard, token is needed // when joining channel. The channel name and uid used to calculate // the token has to match the ones used for channel join - await _engine.joinChannel(config.token, config.channelId, null, 0, null); + await _engine.joinChannel( + config.token, _channelController.text, null, 0, null); } _addListener() { - _engine.setEventHandler(RtcEngineEventHandler(warning: (warningCode) { - log('Warning ${warningCode}'); - }, error: (errorCode) { - log('Warning ${errorCode}'); - }, joinChannelSuccess: (channel, uid, elapsed) { - log('joinChannelSuccess ${channel} ${uid} ${elapsed}'); - ; - setState(() { - isJoined = true; - }); - }, userJoined: (uid, elapsed) { - log('userJoined $uid $elapsed'); - this.setState(() { - remoteUid = uid; - }); - }, userOffline: (uid, reason) { - log('userOffline $uid $reason'); - this.setState(() { - remoteUid = null; - }); - }, channelMediaRelayStateChanged: - (ChannelMediaRelayState state, ChannelMediaRelayError code) { - switch (state) { - case ChannelMediaRelayState.Idle: - log('ChannelMediaRelayState.Idle $code'); - this.setState(() { - isRelaying = false; - }); - break; - case ChannelMediaRelayState.Connecting: - log('ChannelMediaRelayState.Connecting $code)'); - break; - case ChannelMediaRelayState.Running: - log('ChannelMediaRelayState.Running $code)'); - this.setState(() { - isRelaying = true; - }); - break; - case ChannelMediaRelayState.Failure: - log('ChannelMediaRelayState.Failure $code)'); - this.setState(() { - isRelaying = false; - }); - break; - default: - log('default $code)'); - break; - } - })); + _engine.setEventHandler(RtcEngineEventHandler( + warning: (warningCode) { + logSink.log('warning ${warningCode}'); + }, + error: (errorCode) { + logSink.log('error ${errorCode}'); + }, + joinChannelSuccess: (channel, uid, elapsed) { + logSink.log('joinChannelSuccess ${channel} ${uid} ${elapsed}'); + setState(() { + isJoined = true; + }); + }, + userJoined: (uid, elapsed) { + logSink.log('userJoined $uid $elapsed'); + this.setState(() { + remoteUid = uid; + }); + }, + userOffline: (uid, reason) { + logSink.log('userOffline $uid $reason'); + this.setState(() { + remoteUid = null; + }); + }, + channelMediaRelayStateChanged: + (ChannelMediaRelayState state, ChannelMediaRelayError code) { + switch (state) { + case ChannelMediaRelayState.Idle: + logSink.log('ChannelMediaRelayState.Idle $code'); + this.setState(() { + isRelaying = false; + }); + break; + case ChannelMediaRelayState.Connecting: + logSink.log('ChannelMediaRelayState.Connecting $code)'); + break; + case ChannelMediaRelayState.Running: + logSink.log('ChannelMediaRelayState.Running $code)'); + this.setState(() { + isRelaying = true; + }); + break; + case ChannelMediaRelayState.Failure: + logSink.log('ChannelMediaRelayState.Failure $code)'); + this.setState(() { + isRelaying = false; + }); + break; + default: + logSink.log('default $code)'); + break; + } + }, + )); } _onPressRelayOrStop() async { @@ -115,19 +121,15 @@ class _State extends State { await _engine.stopChannelMediaRelay(); return; } - if (_controller.text.length == 0) { + if (_channelMediaRelayController.text.length == 0) { return; } await _engine.startChannelMediaRelay(ChannelMediaRelayConfiguration( - ChannelMediaInfo(config.channelId, 0, token: config.token), - [ChannelMediaInfo('', 0, token: '')])); - - _controller.clear(); + ChannelMediaInfo(_channelController.text, 0, token: config.token), + [ChannelMediaInfo(_channelMediaRelayController.text, 0, token: '')])); } - final TextEditingController _controller = TextEditingController(); - @override Widget build(BuildContext context) { return Stack( @@ -135,15 +137,23 @@ class _State extends State { Column( children: [ !isJoined - ? Row( + ? Column( children: [ - Expanded( - flex: 1, - child: ElevatedButton( - onPressed: _initEngine, - child: Text('Join channel'), - ), - ) + TextField( + controller: _channelController, + readOnly: isJoined, + ), + Row( + children: [ + Expanded( + flex: 1, + child: ElevatedButton( + onPressed: _initEngine, + child: Text('Join channel'), + ), + ) + ], + ), ], ) : _renderVideo(), @@ -153,7 +163,7 @@ class _State extends State { children: [ Expanded( child: TextField( - controller: _controller, + controller: _channelMediaRelayController, decoration: InputDecoration( hintText: 'Enter target relay channel name', ))), @@ -172,17 +182,25 @@ class _State extends State { _renderVideo() { return Row(children: [ Expanded( - child: AspectRatio( - aspectRatio: 1, - child: RtcLocalView.SurfaceView(), - )), + child: AspectRatio( + aspectRatio: 1, + child: + kIsWeb ? RtcLocalView.SurfaceView() : RtcLocalView.TextureView(), + ), + ), Expanded( child: AspectRatio( aspectRatio: 1, child: remoteUid != null - ? RtcRemoteView.SurfaceView( - uid: remoteUid!, - ) + ? (kIsWeb + ? RtcRemoteView.SurfaceView( + uid: remoteUid!, + channelId: _channelController.text, + ) + : RtcRemoteView.TextureView( + uid: remoteUid!, + channelId: _channelController.text, + )) : Container( color: Colors.grey[200], ), diff --git a/example/lib/examples/advanced/device_manager/device_manager.dart b/example/lib/examples/advanced/device_manager/device_manager.dart new file mode 100644 index 000000000..320f070f9 --- /dev/null +++ b/example/lib/examples/advanced/device_manager/device_manager.dart @@ -0,0 +1,207 @@ +import 'dart:convert'; +import 'dart:io'; + +import 'package:agora_rtc_engine/rtc_engine.dart'; +import 'package:agora_rtc_engine/rtc_local_view.dart' as RtcLocalView; +import 'package:agora_rtc_engine/rtc_remote_view.dart' as RtcRemoteView; +import 'package:agora_rtc_engine_example/config/agora.config.dart' as config; +import 'package:agora_rtc_engine_example/examples/log_sink.dart'; +import 'package:flutter/cupertino.dart'; +import 'package:flutter/foundation.dart'; +import 'package:flutter/material.dart'; +import 'package:permission_handler/permission_handler.dart'; + +/// DeviceManager Example +class DeviceManager extends StatefulWidget { + @override + State createState() => _State(); +} + +class _State extends State { + late final RtcEngine _engine; + String channelId = config.channelId; + bool isJoined = false; + List remoteUid = []; + List devices = []; + TextEditingController? _controller; + + @override + void initState() { + super.initState(); + _controller = TextEditingController(text: channelId); + _initEngine(); + } + + @override + void dispose() { + super.dispose(); + _engine.destroy(); + } + + _initEngine() async { + _engine = await RtcEngine.createWithContext(RtcEngineContext(config.appId)); + _addListeners(); + + await _engine.enableVideo(); + await _engine.startPreview(); + await _engine.setChannelProfile(ChannelProfile.LiveBroadcasting); + await _engine.setClientRole(ClientRole.Broadcaster); + } + + _addListeners() { + _engine.setEventHandler(RtcEngineEventHandler( + warning: (warningCode) { + logSink.log('warning ${warningCode}'); + }, + error: (errorCode) { + logSink.log('error ${errorCode}'); + }, + joinChannelSuccess: (channel, uid, elapsed) { + logSink.log('joinChannelSuccess ${channel} ${uid} ${elapsed}'); + setState(() { + isJoined = true; + }); + }, + userJoined: (uid, elapsed) { + logSink.log('userJoined ${uid} ${elapsed}'); + if (uid == config.screenSharingUid) { + return; + } + setState(() { + remoteUid.add(uid); + }); + }, + userOffline: (uid, reason) { + logSink.log('userOffline ${uid} ${reason}'); + setState(() { + remoteUid.removeWhere((element) => element == uid); + }); + }, + leaveChannel: (stats) { + logSink.log('leaveChannel ${stats.toJson()}'); + setState(() { + isJoined = false; + remoteUid.clear(); + }); + }, + )); + } + + _joinChannel() async { + if (defaultTargetPlatform == TargetPlatform.android) { + await [Permission.microphone, Permission.camera].request(); + } + await _engine.joinChannel(config.token, channelId, null, config.uid); + } + + _leaveChannel() async { + await _engine.leaveChannel(); + } + + _enumerateVideoDevices() async { + var devices = await _engine.deviceManager.enumerateVideoDevices(); + logSink.log('_enumerateVideoDevices $devices'); + ScaffoldMessenger.of(context).showSnackBar(SnackBar( + content: Text('_enumerateVideoDevices ${jsonEncode(devices)}'), + )); + setState(() { + this.devices = devices; + }); + } + + _setVideoDevice() async { + if (devices.isNotEmpty) { + await _engine.deviceManager.setVideoDevice(devices.last.deviceId); + } + } + + @override + Widget build(BuildContext context) { + return Stack( + children: [ + Column( + children: [ + TextField( + controller: _controller, + decoration: InputDecoration(hintText: 'Channel ID'), + onChanged: (text) { + setState(() { + channelId = text; + }); + }, + ), + Row( + children: [ + Expanded( + flex: 1, + child: ElevatedButton( + onPressed: isJoined ? _leaveChannel : _joinChannel, + child: Text('${isJoined ? 'Leave' : 'Join'} channel'), + ), + ) + ], + ), + _renderVideo(), + ], + ), + if (kIsWeb || (Platform.isWindows || Platform.isMacOS)) + Align( + alignment: Alignment.bottomRight, + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + ElevatedButton( + onPressed: _enumerateVideoDevices, + child: Text('Enumerate video devices'), + ), + ElevatedButton( + onPressed: _setVideoDevice, + child: Text('Set video device'), + ), + ], + ), + ) + ], + ); + } + + _renderVideo() { + return Expanded( + child: Stack( + children: [ + Row( + children: [ + Expanded( + flex: 1, + child: kIsWeb + ? RtcLocalView.SurfaceView() + : RtcLocalView.TextureView()), + ], + ), + Align( + alignment: Alignment.topLeft, + child: SingleChildScrollView( + scrollDirection: Axis.horizontal, + child: Row( + children: List.of(remoteUid.map( + (e) => Container( + width: 120, + height: 120, + child: kIsWeb + ? RtcRemoteView.SurfaceView( + uid: e, + channelId: channelId, + ) + : RtcRemoteView.TextureView( + uid: e, + channelId: channelId, + ), + ), + )), + ), + ), + ) + ], + )); + } +} diff --git a/example/lib/examples/advanced/index.dart b/example/lib/examples/advanced/index.dart index b9a572226..d2b854d45 100644 --- a/example/lib/examples/advanced/index.dart +++ b/example/lib/examples/advanced/index.dart @@ -1,22 +1,36 @@ -import 'package:agora_rtc_engine_example/examples/advanced/stream_message/stream_message.dart'; +import 'dart:io'; + +import 'package:agora_rtc_engine_example/examples/advanced/audio_mixing/audio_mixing.dart'; import 'package:agora_rtc_engine_example/examples/advanced/channel_media_relay/channel_media_relay.dart'; +import 'package:agora_rtc_engine_example/examples/advanced/custom_capture_audio/custom_capture_audio.dart'; +import 'package:agora_rtc_engine_example/examples/advanced/device_manager/device_manager.dart'; import 'package:agora_rtc_engine_example/examples/advanced/join_multiple_channel/join_multiple_channel.dart'; +import 'package:agora_rtc_engine_example/examples/advanced/rtmp_streaming/rtmp_streaming.dart'; +import 'package:agora_rtc_engine_example/examples/advanced/screen_sharing/screen_sharing.dart'; +import 'package:agora_rtc_engine_example/examples/advanced/set_encryption/set_encryption.dart'; +import 'package:agora_rtc_engine_example/examples/advanced/set_video_encoder_configuration/set_video_encoder_configuration.dart'; +import 'package:agora_rtc_engine_example/examples/advanced/stream_message/stream_message.dart'; import 'package:agora_rtc_engine_example/examples/advanced/voice_changer/voice_changer.dart'; - -import 'custom_capture_audio/custom_capture_audio.dart'; +import 'package:flutter/foundation.dart'; /// Data source for advanced examples final Advanced = [ {'name': 'Advanced'}, + {'name': 'AudioMixing', 'widget': AudioMixing()}, + {'name': 'ChannelMediaRelay', 'widget': ChannelMediaRelay()}, + if (!kIsWeb && (Platform.isAndroid || Platform.isIOS)) + {'name': 'CustomCaptureAudio', 'widget': CustomCaptureAudio()}, + if (kIsWeb || !(Platform.isAndroid || Platform.isIOS)) + {'name': 'DeviceManager', 'widget': DeviceManager()}, {'name': 'JoinMultipleChannel', 'widget': JoinMultipleChannel()}, + {'name': 'RtmpStreaming', 'widget': RtmpStreaming()}, + if (kIsWeb || !(Platform.isAndroid || Platform.isIOS)) + {'name': 'ScreenSharing', 'widget': ScreenSharing()}, + {'name': 'SetEncryption', 'widget': SetEncryption()}, { - 'name': 'StreamMessage', - 'widget': StreamMessage(), - }, - { - 'name': 'ChannelMediaRelay', - 'widget': ChannelMediaRelay(), + 'name': 'SetVideoEncoderConfiguration', + 'widget': SetVideoEncoderConfiguration() }, + {'name': 'StreamMessage', 'widget': StreamMessage()}, {'name': 'VoiceChanger', 'widget': VoiceChanger()}, - {'name': 'CustomCaptureAudio', 'widget': CustomCaptureAudio()}, ]; diff --git a/example/lib/examples/advanced/join_multiple_channel/join_multiple_channel.dart b/example/lib/examples/advanced/join_multiple_channel/join_multiple_channel.dart index 3f94863e5..33e289188 100644 --- a/example/lib/examples/advanced/join_multiple_channel/join_multiple_channel.dart +++ b/example/lib/examples/advanced/join_multiple_channel/join_multiple_channel.dart @@ -1,10 +1,9 @@ -import 'dart:developer'; - import 'package:agora_rtc_engine/rtc_channel.dart'; import 'package:agora_rtc_engine/rtc_engine.dart'; import 'package:agora_rtc_engine/rtc_local_view.dart' as RtcLocalView; import 'package:agora_rtc_engine/rtc_remote_view.dart' as RtcRemoteView; import 'package:agora_rtc_engine_example/config/agora.config.dart' as config; +import 'package:agora_rtc_engine_example/examples/log_sink.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; @@ -45,6 +44,12 @@ class _State extends State { await _engine.startPreview(); await _engine.setChannelProfile(ChannelProfile.LiveBroadcasting); await _engine.setClientRole(ClientRole.Broadcaster); + + _channel0 = await RtcChannel.create(_channelId0); + this._addListener(_channel0); + + _channel1 = await RtcChannel.create(_channelId1); + this._addListener(_channel1); } _joinChannel0() async { @@ -52,9 +57,6 @@ class _State extends State { await [Permission.microphone, Permission.camera].request(); } - _channel0 = await RtcChannel.create(_channelId0); - this._addListener(_channel0); - await _channel0.setClientRole(ClientRole.Broadcaster); await _channel0.joinChannel( null, @@ -71,9 +73,6 @@ class _State extends State { await [Permission.microphone, Permission.camera].request(); } - _channel1 = await RtcChannel.create(_channelId1); - this._addListener(_channel1); - await _channel1.setClientRole(ClientRole.Broadcaster); await _channel1.joinChannel( null, @@ -87,38 +86,27 @@ class _State extends State { _addListener(RtcChannel channel) { String channelId = channel.channelId; - channel.setEventHandler( - RtcChannelEventHandler(joinChannelSuccess: (channel, uid, elapsed) { - log('joinChannelSuccess ${channel} ${uid} ${elapsed}'); - if (channelId == _channelId0) { - setState(() { - isJoined0 = true; - }); - } else if (channelId == _channelId1) { - setState(() { - isJoined1 = true; - }); - } - }, userJoined: (uid, elapsed) { - log('userJoined ${channel.channelId} $uid $elapsed'); - }, userOffline: (uid, reason) { - log('userOffline ${channel.channelId} $uid $reason'); - }, leaveChannel: (stats) { - log('leaveChannel ${channel.channelId} ${stats.toJson()}'); - if (channelId == _channelId0) { - this.setState(() { - isJoined0 = false; - remoteUid0.clear(); - }); - } else if (channelId == _channelId1) { - this.setState(() { - isJoined1 = false; - remoteUid1.clear(); - }); - } - }, remoteVideoStateChanged: (uid, state, reason, elapsed) { - log('remoteVideoStateChanged ${uid} ${state} ${reason} ${elapsed}'); - if (state == VideoRemoteState.Starting) { + channel.setEventHandler(RtcChannelEventHandler( + warning: (warningCode) { + logSink.log('warning ${warningCode}'); + }, + error: (errorCode) { + logSink.log('error ${errorCode}'); + }, + joinChannelSuccess: (channel, uid, elapsed) { + logSink.log('joinChannelSuccess ${channel} ${uid} ${elapsed}'); + if (channelId == _channelId0) { + setState(() { + isJoined0 = true; + }); + } else if (channelId == _channelId1) { + setState(() { + isJoined1 = true; + }); + } + }, + userJoined: (uid, elapsed) { + logSink.log('userJoined ${channel.channelId} $uid $elapsed'); if (channelId == _channelId0) { this.setState(() { remoteUid0.add(uid); @@ -128,7 +116,9 @@ class _State extends State { remoteUid1.add(uid); }); } - } else if (state == VideoRemoteState.Stopped) { + }, + userOffline: (uid, reason) { + logSink.log('userOffline ${channel.channelId} $uid $reason'); if (channelId == _channelId0) { this.setState(() { remoteUid0.removeWhere((element) => element == uid); @@ -138,18 +128,32 @@ class _State extends State { remoteUid1.removeWhere((element) => element == uid); }); } - } - })); + }, + leaveChannel: (stats) { + logSink.log('leaveChannel ${channel.channelId} ${stats.toJson()}'); + if (channelId == _channelId0) { + this.setState(() { + isJoined0 = false; + remoteUid0.clear(); + }); + } else if (channelId == _channelId1) { + this.setState(() { + isJoined1 = false; + remoteUid1.clear(); + }); + } + }, + )); } _publishChannel0() async { - await _channel1.unpublish(); - await _channel0.publish(); + await _channel1.muteLocalVideoStream(true); + await _channel0.muteLocalVideoStream(false); } _publishChannel1() async { - await _channel0.unpublish(); - await _channel1.publish(); + await _channel0.muteLocalVideoStream(true); + await _channel1.muteLocalVideoStream(false); } _leaveChannel0() async { @@ -240,7 +244,7 @@ class _State extends State { } _renderVideo() { - List? remoteUid = null; + List remoteUid = []; if (renderChannelId == _channelId0) { remoteUid = remoteUid0; } else if (renderChannelId == _channelId1) { @@ -249,25 +253,30 @@ class _State extends State { return Expanded( child: Stack( children: [ - RtcLocalView.SurfaceView( - channelId: renderChannelId, - ), - if (remoteUid != null) + kIsWeb ? RtcLocalView.SurfaceView() : RtcLocalView.TextureView(), + if (remoteUid.isNotEmpty) Align( alignment: Alignment.topLeft, child: SingleChildScrollView( scrollDirection: Axis.horizontal, child: Row( - children: List.of(remoteUid.map( - (e) => Container( - width: 120, - height: 120, - child: RtcRemoteView.SurfaceView( - uid: e, - channelId: renderChannelId, - ), - ), - )), + children: remoteUid + .map( + (e) => Container( + width: 120, + height: 120, + child: kIsWeb + ? RtcRemoteView.SurfaceView( + uid: e, + channelId: renderChannelId!, + ) + : RtcRemoteView.TextureView( + uid: e, + channelId: renderChannelId!, + ), + ), + ) + .toList(), ), ), ) diff --git a/example/lib/examples/advanced/rtmp_streaming/rtmp_streaming.dart b/example/lib/examples/advanced/rtmp_streaming/rtmp_streaming.dart new file mode 100644 index 000000000..6e8ddd12f --- /dev/null +++ b/example/lib/examples/advanced/rtmp_streaming/rtmp_streaming.dart @@ -0,0 +1,266 @@ +import 'package:agora_rtc_engine/rtc_engine.dart'; +import 'package:agora_rtc_engine/rtc_local_view.dart' as RtcLocalView; +import 'package:agora_rtc_engine/rtc_remote_view.dart' as RtcRemoteView; +import 'package:agora_rtc_engine_example/config/agora.config.dart' as config; +import 'package:agora_rtc_engine_example/examples/log_sink.dart'; +import 'package:flutter/cupertino.dart'; +import 'package:flutter/foundation.dart'; +import 'package:flutter/material.dart'; +import 'package:permission_handler/permission_handler.dart'; + +/// RtmpStreaming Example +class RtmpStreaming extends StatefulWidget { + @override + State createState() => _RtmpStreamingState(); +} + +class _RtmpStreamingState extends State { + late final RtcEngine _engine; + String channelId = config.channelId; + bool isJoined = false; + bool switchCamera = true; + TextEditingController? _channelIdController; + late TextEditingController _rtmpUrlController; + bool _isStreaming = false; + int _remoteUid = 0; + + @override + void initState() { + super.initState(); + _channelIdController = TextEditingController(text: channelId); + _rtmpUrlController = TextEditingController(); + _initEngine(); + } + + @override + void dispose() { + super.dispose(); + _engine.destroy(); + } + + Future _initEngine() async { + _engine = await RtcEngine.createWithContext(RtcEngineContext(config.appId)); + this._addListeners(); + + await _engine.enableVideo(); + await _engine.startPreview(); + await _engine.setChannelProfile(ChannelProfile.LiveBroadcasting); + await _engine.setClientRole(ClientRole.Broadcaster); + } + + void _addListeners() { + _engine.setEventHandler(RtcEngineEventHandler( + warning: (warningCode) { + logSink.log('warning ${warningCode}'); + }, + error: (errorCode) { + logSink.log('error ${errorCode}'); + }, + joinChannelSuccess: (channel, uid, elapsed) { + logSink.log('joinChannelSuccess ${channel} ${uid} ${elapsed}'); + setState(() { + isJoined = true; + }); + + _startTranscoding(); + }, + userJoined: (uid, elapsed) { + logSink.log('userJoined ${uid} ${elapsed}'); + if (_remoteUid == 0) { + setState(() { + _remoteUid = uid; + }); + } + + // _startTranscoding(isRemoteUser: true); + }, + userOffline: (uid, reason) { + logSink.log('userOffline ${uid} ${reason}'); + setState(() { + _remoteUid = 0; + }); + }, + leaveChannel: (stats) { + logSink.log('leaveChannel ${stats.toJson()}'); + setState(() { + isJoined = false; + }); + }, + rtmpStreamingStateChanged: (String url, RtmpStreamingState state, + RtmpStreamingErrorCode errCode) { + logSink.log( + 'rtmpStreamingStateChanged url: $url, state: $state, errCode: $errCode'); + }, + rtmpStreamingEvent: (String url, RtmpStreamingEvent eventCode) { + logSink.log( + 'rtmpStreamingEvent url: $url, eventCode: ${eventCode.toString()}'); + }, + )); + } + + Future _joinChannel() async { + if (defaultTargetPlatform == TargetPlatform.android) { + await [Permission.microphone, Permission.camera].request(); + } + await _engine.joinChannel(config.token, channelId, null, config.uid); + } + + Future _leaveChannel() async { + await _engine.leaveChannel(); + } + + void _switchCamera() { + _engine.switchCamera().then((value) { + setState(() { + switchCamera = !switchCamera; + }); + }).catchError((err) { + print('switchCamera $err'); + }); + } + + Future _startTranscoding({bool isRemoteUser = false}) async { + if (_isStreaming && !isRemoteUser) return; + final streamUrl = _rtmpUrlController.text; + if (_isStreaming && isRemoteUser) { + await _engine.removePublishStreamUrl(streamUrl); + } + + _isStreaming = true; + + final List transcodingUsers = [ + TranscodingUser( + 0, + x: 0, + y: 0, + width: 360, + height: 640, + audioChannel: AudioChannel.Channel0, + alpha: 1.0, + ) + ]; + + int width = 360; + int height = 640; + + if (isRemoteUser) { + transcodingUsers.add(TranscodingUser( + _remoteUid, + x: 360, + y: 0, + width: 360, + height: 640, + audioChannel: AudioChannel.Channel0, + alpha: 1.0, + )); + width = 720; + height = 640; + } + + final lt = new LiveTranscoding( + transcodingUsers, + width: width, + height: height, + videoBitrate: 400, + videoCodecProfile: VideoCodecProfileType.High, + videoGop: 30, + videoFramerate: VideoFrameRate.Fps24, + lowLatency: false, + audioSampleRate: AudioSampleRateType.Type44100, + audioBitrate: 48, + audioChannels: AudioChannel.Channel1, + audioCodecProfile: AudioCodecProfileType.LCAAC, + ); + + // await _engine.setLiveTranscoding(lt); + // await _engine.enableEncryption(false, EncryptionConfig()); + try { + await _engine.addPublishStreamUrl(streamUrl, false); + } catch (e) { + logSink.log('addPublishStreamUrl error: ${e.toString()}'); + } + } + + @override + Widget build(BuildContext context) { + return Stack( + children: [ + Column( + children: [ + TextField( + controller: _channelIdController, + decoration: InputDecoration(hintText: 'Channel ID'), + onChanged: (text) { + setState(() { + channelId = text; + }); + }, + ), + TextField( + controller: _rtmpUrlController, + decoration: InputDecoration(hintText: 'Input rtmp url'), + ), + Row( + children: [ + Expanded( + flex: 1, + child: ElevatedButton( + onPressed: + isJoined ? this._leaveChannel : this._joinChannel, + child: Text('${isJoined ? 'Leave' : 'Join'} channel'), + ), + ) + ], + ), + _renderVideo(), + ], + ), + if (defaultTargetPlatform == TargetPlatform.android || + defaultTargetPlatform == TargetPlatform.iOS) + Align( + alignment: Alignment.bottomRight, + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + ElevatedButton( + onPressed: this._switchCamera, + child: Text('Camera ${switchCamera ? 'front' : 'rear'}'), + ), + ], + ), + ) + ], + ); + } + + Widget _renderVideo() { + return Expanded( + child: Stack( + children: [ + Container( + child: kIsWeb + ? RtcLocalView.SurfaceView() + : RtcLocalView.TextureView(), + ), + if (_remoteUid != 0) + Align( + alignment: Alignment.topLeft, + child: Container( + width: 120, + height: 120, + child: kIsWeb + ? RtcRemoteView.SurfaceView( + uid: _remoteUid, + channelId: channelId, + ) + : RtcRemoteView.TextureView( + uid: _remoteUid, + channelId: channelId, + ), + ), + ), + ], + ), + ); + } +} diff --git a/example/lib/examples/advanced/screen_sharing/screen_sharing.dart b/example/lib/examples/advanced/screen_sharing/screen_sharing.dart new file mode 100644 index 000000000..58167fdff --- /dev/null +++ b/example/lib/examples/advanced/screen_sharing/screen_sharing.dart @@ -0,0 +1,251 @@ +import 'dart:io'; +import 'dart:math'; + +import 'package:agora_rtc_engine/rtc_engine.dart'; +import 'package:agora_rtc_engine/rtc_local_view.dart' as RtcLocalView; +import 'package:agora_rtc_engine/rtc_remote_view.dart' as RtcRemoteView; +import 'package:agora_rtc_engine_example/config/agora.config.dart' as config; +import 'package:agora_rtc_engine_example/examples/log_sink.dart'; +import 'package:flutter/cupertino.dart'; +import 'package:flutter/foundation.dart'; +import 'package:flutter/material.dart'; +import 'package:permission_handler/permission_handler.dart'; + +const String _kDefaultAppGroup = 'io.agora'; + +/// ScreenSharing Example +class ScreenSharing extends StatefulWidget { + @override + State createState() => _State(); +} + +class _State extends State { + late final RtcEngine _engine; + String channelId = config.channelId; + bool isJoined = false, screenSharing = false; + List remoteUid = []; + TextEditingController? _controller; + + @override + void initState() { + super.initState(); + _controller = TextEditingController(text: channelId); + _initEngine(); + } + + @override + void dispose() { + super.dispose(); + _engine.destroy(); + } + + _initEngine() async { + _engine = await RtcEngine.createWithContext(RtcEngineContext(config.appId)); + _addListeners(); + + await _engine.enableVideo(); + await _engine.startPreview(); + await _engine.setChannelProfile(ChannelProfile.LiveBroadcasting); + await _engine.setClientRole(ClientRole.Broadcaster); + } + + _addListeners() { + _engine.setEventHandler(RtcEngineEventHandler( + warning: (warningCode) { + logSink.log('warning ${warningCode}'); + }, + error: (errorCode) { + logSink.log('error ${errorCode}'); + }, + joinChannelSuccess: (channel, uid, elapsed) { + logSink.log('joinChannelSuccess ${channel} ${uid} ${elapsed}'); + setState(() { + isJoined = true; + }); + }, + userJoined: (uid, elapsed) { + logSink.log('userJoined ${uid} ${elapsed}'); + if (uid == config.screenSharingUid) { + return; + } + setState(() { + remoteUid.add(uid); + }); + }, + userOffline: (uid, reason) { + logSink.log('userOffline ${uid} ${reason}'); + setState(() { + remoteUid.removeWhere((element) => element == uid); + }); + }, + leaveChannel: (stats) { + logSink.log('leaveChannel ${stats.toJson()}'); + setState(() { + isJoined = false; + remoteUid.clear(); + }); + }, + )); + } + + _joinChannel() async { + if (defaultTargetPlatform == TargetPlatform.android) { + await [Permission.microphone, Permission.camera].request(); + } + await _engine.joinChannel(config.token, channelId, null, config.uid); + } + + _leaveChannel() async { + await _engine.leaveChannel(); + } + + _startScreenShare() async { + final helper = await _engine.getScreenShareHelper( + appGroup: kIsWeb || Platform.isWindows ? null : _kDefaultAppGroup); + helper.setEventHandler(RtcEngineEventHandler( + joinChannelSuccess: (String channel, int uid, int elapsed) { + logSink.log( + 'ScreenSharing joinChannelSuccess ${channel} ${uid} ${elapsed}'); + ScaffoldMessenger.of(context).showSnackBar(SnackBar( + content: Text( + 'ScreenSharing joinChannelSuccess ${channel} ${uid} ${elapsed}'), + )); + }, + localVideoStateChanged: + (LocalVideoStreamState localVideoState, LocalVideoStreamError error) { + logSink.log( + 'ScreenSharing localVideoStateChanged ${localVideoState} ${error}'); + if (localVideoState == LocalVideoStreamState.Failed) { + _stopScreenShare(); + } + }, + )); + + await helper.disableAudio(); + await helper.enableVideo(); + await helper.setChannelProfile(ChannelProfile.LiveBroadcasting); + await helper.setClientRole(ClientRole.Broadcaster); + var windowId = 0; + var random = Random(); + if (!kIsWeb && + (Platform.isWindows || Platform.isMacOS || Platform.isAndroid)) { + final windows = _engine.enumerateWindows(); + if (windows.isNotEmpty) { + final index = random.nextInt(windows.length - 1); + logSink.log('ScreenSharing window with index $index'); + windowId = windows[index].id; + } + } + await helper.startScreenCaptureByWindowId(windowId); + setState(() { + screenSharing = true; + }); + await helper.joinChannel( + config.token, channelId, null, config.screenSharingUid); + } + + _stopScreenShare() async { + final helper = await _engine.getScreenShareHelper(); + await helper.destroy().then((value) { + setState(() { + screenSharing = false; + }); + }).catchError((err) { + logSink.log('_stopScreenShare $err'); + }); + } + + @override + Widget build(BuildContext context) { + return Stack( + children: [ + Column( + children: [ + TextField( + controller: _controller, + decoration: InputDecoration(hintText: 'Channel ID'), + onChanged: (text) { + setState(() { + channelId = text; + }); + }, + ), + Row( + children: [ + Expanded( + flex: 1, + child: ElevatedButton( + onPressed: isJoined ? _leaveChannel : _joinChannel, + child: Text('${isJoined ? 'Leave' : 'Join'} channel'), + ), + ) + ], + ), + _renderVideo(), + ], + ), + if (kIsWeb || (Platform.isWindows || Platform.isMacOS)) + Align( + alignment: Alignment.bottomRight, + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + ElevatedButton( + onPressed: + screenSharing ? _stopScreenShare : _startScreenShare, + child: + Text('${screenSharing ? 'Stop' : 'Start'} screen share'), + ), + ], + ), + ) + ], + ); + } + + _renderVideo() { + return Expanded( + child: Stack( + children: [ + Row( + children: [ + Expanded( + flex: 1, + child: kIsWeb + ? RtcLocalView.SurfaceView() + : RtcLocalView.TextureView()), + if (screenSharing) + Expanded( + flex: 1, + child: kIsWeb + ? RtcLocalView.SurfaceView.screenShare() + : RtcLocalView.TextureView.screenShare()), + ], + ), + Align( + alignment: Alignment.topLeft, + child: SingleChildScrollView( + scrollDirection: Axis.horizontal, + child: Row( + children: List.of(remoteUid.map( + (e) => Container( + width: 120, + height: 120, + child: kIsWeb + ? RtcRemoteView.SurfaceView( + uid: e, + channelId: channelId, + ) + : RtcRemoteView.TextureView( + uid: e, + channelId: channelId, + ), + ), + )), + ), + ), + ) + ], + )); + } +} diff --git a/example/lib/examples/advanced/set_encryption/set_encryption.dart b/example/lib/examples/advanced/set_encryption/set_encryption.dart new file mode 100644 index 000000000..c3c2574b5 --- /dev/null +++ b/example/lib/examples/advanced/set_encryption/set_encryption.dart @@ -0,0 +1,199 @@ +import 'dart:async'; +import 'dart:convert'; + +import 'package:agora_rtc_engine/rtc_engine.dart'; +import 'package:agora_rtc_engine_example/config/agora.config.dart' as config; +import 'package:agora_rtc_engine_example/examples/log_sink.dart'; +import 'package:flutter/cupertino.dart'; +import 'package:flutter/foundation.dart'; +import 'package:flutter/material.dart'; +import 'package:permission_handler/permission_handler.dart'; + +/// SetEncryption Example +class SetEncryption extends StatefulWidget { + @override + State createState() => _SetEncryptionState(); +} + +class _SetEncryptionState extends State { + late final RtcEngine _engine; + String channelId = config.channelId; + bool isJoined = false, + openMicrophone = true, + enableSpeakerphone = true, + playEffect = false; + late TextEditingController _controller; + + // Only take 3 EncryptionMode for demo purpose + final List encryptionModes = [ + EncryptionMode.AES128GCM2, + EncryptionMode.AES128XTS, + EncryptionMode.AES256GCM, + ]; + + late EncryptionMode _selectedEncryptionMode; + TextEditingController _encryptionKey = TextEditingController(); + late final TextEditingController _encryptionKdfSalt; + + @override + void initState() { + super.initState(); + _selectedEncryptionMode = encryptionModes[0]; + _controller = TextEditingController(text: channelId); + _encryptionKdfSalt = + TextEditingController(text: 'EncryptionKdfSaltInBase64Strings'); + _initEngine(); + } + + @override + void reassemble() { + super.reassemble(); + _destroy(); + } + + @override + void dispose() { + _controller?.dispose(); + _encryptionKey.dispose(); + _encryptionKdfSalt.dispose(); + _destroy(); + + super.dispose(); + } + + Future _initEngine() async { + _engine = await RtcEngine.createWithContext(RtcEngineContext(config.appId)); + this._addListeners(); + + await _engine.enableAudio(); + await _engine.setChannelProfile(ChannelProfile.LiveBroadcasting); + await _engine.setClientRole(ClientRole.Broadcaster); + } + + void _addListeners() { + _engine.setEventHandler(RtcEngineEventHandler( + warning: (warningCode) { + logSink.log('warning ${warningCode}'); + }, + error: (errorCode) { + logSink.log('error ${errorCode}'); + }, + joinChannelSuccess: (channel, uid, elapsed) { + logSink.log( + 'joinChannelSuccess channel: ${channel}, uid: ${uid}, elapsed: ${elapsed}'); + setState(() { + isJoined = true; + }); + }, + leaveChannel: (stats) async { + logSink.log('leaveChannel ${stats.toJson()}'); + setState(() { + isJoined = false; + }); + }, + )); + } + + Future _destroy() async { + await _leaveChannel(); + await _engine.destroy(); + } + + Future _joinChannel() async { + if (defaultTargetPlatform == TargetPlatform.android) { + await Permission.microphone.request(); + } + + final EncryptionConfig encryptionConfig = EncryptionConfig( + encryptionMode: _selectedEncryptionMode, + encryptionKey: _encryptionKey.text, + encryptionKdfSalt: utf8.encode(_encryptionKdfSalt.text), + ); + await _engine.enableEncryption(true, encryptionConfig); + + await _engine + .joinChannel(config.token, _controller.text, null, config.uid) + .catchError((onError) { + logSink.log('error ${onError.toString()}'); + }); + } + + Future _leaveChannel() async { + await _engine.leaveChannel(); + } + + @override + Widget build(BuildContext context) { + final dropDownMenus = >[]; + for (var v in encryptionModes) { + dropDownMenus.add(DropdownMenuItem( + child: Text('$v'), + value: v, + )); + } + + return Column( + children: [ + TextField( + controller: _controller, + decoration: InputDecoration(hintText: 'Channel ID'), + onChanged: (text) { + setState(() { + channelId = text; + }); + }, + ), + Row( + children: [ + Text('Encryption Mode: '), + DropdownButton( + items: dropDownMenus, + value: _selectedEncryptionMode, + onChanged: isJoined + ? null + : (v) { + setState(() { + _selectedEncryptionMode = v!; + }); + }, + ), + ], + ), + Row( + children: [ + Text('Input Encryption Key: '), + Expanded( + child: TextField( + controller: _encryptionKey, + readOnly: isJoined, + ), + ) + ], + ), + Row( + mainAxisSize: MainAxisSize.min, + children: [ + Text('Input EncryptionKdfSalt: '), + Expanded( + child: TextField( + controller: _encryptionKdfSalt, + readOnly: isJoined, + ), + ), + ], + ), + Row( + children: [ + Expanded( + flex: 1, + child: ElevatedButton( + onPressed: isJoined ? this._leaveChannel : this._joinChannel, + child: Text('${isJoined ? 'Leave' : 'Join'} channel'), + ), + ) + ], + ), + ], + ); + } +} diff --git a/example/lib/examples/advanced/set_video_encoder_configuration/set_video_encoder_configuration.dart b/example/lib/examples/advanced/set_video_encoder_configuration/set_video_encoder_configuration.dart new file mode 100644 index 000000000..b5eafe280 --- /dev/null +++ b/example/lib/examples/advanced/set_video_encoder_configuration/set_video_encoder_configuration.dart @@ -0,0 +1,241 @@ +import 'package:agora_rtc_engine/rtc_engine.dart'; +import 'package:agora_rtc_engine/rtc_local_view.dart' as RtcLocalView; +import 'package:agora_rtc_engine/rtc_remote_view.dart' as RtcRemoteView; +import 'package:agora_rtc_engine_example/config/agora.config.dart' as config; +import 'package:agora_rtc_engine_example/examples/log_sink.dart'; +import 'package:flutter/cupertino.dart'; +import 'package:flutter/foundation.dart'; +import 'package:flutter/material.dart'; +import 'package:permission_handler/permission_handler.dart'; + +/// SetVideoEncoderConfiguration Example +class SetVideoEncoderConfiguration extends StatefulWidget { + @override + State createState() => _SetVideoEncoderConfigurationState(); +} + +class _SetVideoEncoderConfigurationState + extends State { + late final RtcEngine _engine; + String channelId = config.channelId; + bool isJoined = false; + bool switchCamera = true; + TextEditingController? _channelIdController; + int _remoteUid = 0; + int _selectedDimensionIndex = 0; + List dimensions = [ + VideoDimensions(width: 640, height: 480), + VideoDimensions(width: 480, height: 480), + VideoDimensions(width: 480, height: 240), + ]; + @override + void initState() { + super.initState(); + _channelIdController = TextEditingController(text: channelId); + _initEngine(); + } + + @override + void dispose() { + super.dispose(); + _engine.destroy(); + } + + Future _initEngine() async { + _engine = await RtcEngine.createWithContext(RtcEngineContext(config.appId)); + this._addListeners(); + + await _engine.enableVideo(); + await _engine.startPreview(); + await _engine.setChannelProfile(ChannelProfile.LiveBroadcasting); + await _engine.setClientRole(ClientRole.Broadcaster); + } + + void _addListeners() { + _engine.setEventHandler(RtcEngineEventHandler( + warning: (warningCode) { + logSink.log('warning ${warningCode}'); + }, + error: (errorCode) { + debugPrint('error ${errorCode}'); + }, + joinChannelSuccess: (channel, uid, elapsed) { + logSink.log('joinChannelSuccess ${channel} ${uid} ${elapsed}'); + setState(() { + isJoined = true; + }); + }, + userJoined: (uid, elapsed) { + logSink.log('userJoined ${uid} ${elapsed}'); + if (_remoteUid == 0) { + setState(() { + _remoteUid = uid; + }); + } + }, + userOffline: (uid, reason) { + logSink.log('userOffline ${uid} ${reason}'); + setState(() { + _remoteUid = 0; + }); + }, + leaveChannel: (stats) { + logSink.log('leaveChannel ${stats.toJson()}'); + setState(() { + isJoined = false; + }); + }, + rtmpStreamingStateChanged: (String url, RtmpStreamingState state, + RtmpStreamingErrorCode errCode) { + logSink.log( + 'rtmpStreamingStateChanged url: $url, state: $state, errCode: $errCode'); + }, + rtmpStreamingEvent: (String url, RtmpStreamingEvent eventCode) { + logSink.log( + 'rtmpStreamingEvent url: $url, eventCode: ${eventCode.toString()}'); + }, + )); + } + + Future _joinChannel() async { + if (defaultTargetPlatform == TargetPlatform.android) { + await [Permission.microphone, Permission.camera].request(); + } + await _engine.joinChannel(config.token, channelId, null, config.uid); + await setVideoEncoderConfiguration(dim: _selectedDimensionIndex); + } + + Future _leaveChannel() async { + await _engine.leaveChannel(); + } + + Future setVideoEncoderConfiguration({int dim = 0}) async { + if (dim >= dimensions.length) { + logSink.log("Invalid dimension choice!"); + return; + } + + VideoEncoderConfiguration config = VideoEncoderConfiguration( + dimensions: dimensions[dim], + frameRate: VideoFrameRate.Fps15, + minFrameRate: VideoFrameRate.Min, + bitrate: 0, + minBitrate: 1, + orientationMode: VideoOutputOrientationMode.Adaptative, + degradationPrefer: DegradationPreference.MaintainFramerate, + mirrorMode: VideoMirrorMode.Auto, + ); + await _engine.setVideoEncoderConfiguration(config); + } + + void _switchCamera() { + _engine.switchCamera().then((value) { + setState(() { + switchCamera = !switchCamera; + }); + }).catchError((err) { + logSink.log('switchCamera $err'); + }); + } + + @override + Widget build(BuildContext context) { + final dimesionsMenus = >[]; + for (int i = 0; i < dimensions.length; i++) { + final e = dimensions[i]; + dimesionsMenus.add(DropdownMenuItem( + value: i, child: Text('width: ${e.width}, height: ${e.height}'))); + } + return Stack( + children: [ + Column( + children: [ + TextField( + controller: _channelIdController, + decoration: InputDecoration(hintText: 'Channel ID'), + onChanged: (text) { + setState(() { + channelId = text; + }); + }, + ), + Row( + children: [ + Expanded( + flex: 1, + child: ElevatedButton( + onPressed: + isJoined ? this._leaveChannel : this._joinChannel, + child: Text('${isJoined ? 'Leave' : 'Join'} channel'), + ), + ) + ], + ), + Row( + children: [ + Text('Video dimensions: '), + DropdownButton( + value: _selectedDimensionIndex, + items: dimesionsMenus, + onChanged: (value) { + setState(() { + _selectedDimensionIndex = value!; + }); + + setVideoEncoderConfiguration(dim: _selectedDimensionIndex); + }, + ), + ], + ), + _renderVideo(), + ], + ), + if (defaultTargetPlatform == TargetPlatform.android || + defaultTargetPlatform == TargetPlatform.iOS) + Align( + alignment: Alignment.bottomRight, + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + ElevatedButton( + onPressed: this._switchCamera, + child: Text('Camera ${switchCamera ? 'front' : 'rear'}'), + ), + ], + ), + ) + ], + ); + } + + Widget _renderVideo() { + return Expanded( + child: Stack( + children: [ + Container( + child: kIsWeb + ? RtcLocalView.SurfaceView() + : RtcLocalView.TextureView(), + ), + if (_remoteUid != 0) + Align( + alignment: Alignment.topLeft, + child: Container( + width: 120, + height: 120, + child: kIsWeb + ? RtcRemoteView.SurfaceView( + uid: _remoteUid, + channelId: channelId, + ) + : RtcRemoteView.TextureView( + uid: _remoteUid, + channelId: channelId, + ), + ), + ), + ], + ), + ); + } +} diff --git a/example/lib/examples/advanced/stream_message/stream_message.dart b/example/lib/examples/advanced/stream_message/stream_message.dart index f828fb0f0..b8ffb2ca7 100644 --- a/example/lib/examples/advanced/stream_message/stream_message.dart +++ b/example/lib/examples/advanced/stream_message/stream_message.dart @@ -1,9 +1,11 @@ -import 'dart:developer'; +import 'dart:convert'; +import 'dart:typed_data'; import 'package:agora_rtc_engine/rtc_engine.dart'; import 'package:agora_rtc_engine/rtc_local_view.dart' as RtcLocalView; import 'package:agora_rtc_engine/rtc_remote_view.dart' as RtcRemoteView; import 'package:agora_rtc_engine_example/config/agora.config.dart' as config; +import 'package:agora_rtc_engine_example/examples/log_sink.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; @@ -18,7 +20,7 @@ class StreamMessage extends StatefulWidget { class _State extends State { late final RtcEngine _engine; bool isJoined = false; - int? remoteUid; + List remoteUids = []; @override void initState() { @@ -45,9 +47,6 @@ class _State extends State { await _engine.setChannelProfile(ChannelProfile.LiveBroadcasting); await _engine.setClientRole(ClientRole.Broadcaster); - // Set audio route to speaker - await _engine.setDefaultAudioRoutetoSpeakerphone(true); - // start joining channel // 1. Users can only see each other after they join the // same channel successfully using the same app id. @@ -83,33 +82,38 @@ class _State extends State { } _addListener() { - _engine.setEventHandler(RtcEngineEventHandler(warning: (warningCode) { - log('Warning ${warningCode}'); - }, error: (errorCode) { - log('Warning ${errorCode}'); - }, joinChannelSuccess: (channel, uid, elapsed) { - log('joinChannelSuccess ${channel} ${uid} ${elapsed}'); - ; - setState(() { - isJoined = true; - }); - }, userJoined: (uid, elapsed) { - log('userJoined $uid $elapsed'); - this.setState(() { - remoteUid = uid; - }); - }, userOffline: (uid, reason) { - log('userOffline $uid $reason'); - this.setState(() { - remoteUid = null; - }); - }, streamMessage: (int uid, int streamId, String data) { - _showMyDialog(uid, streamId, data); - log('streamMessage $uid $streamId $data'); - }, streamMessageError: - (int uid, int streamId, ErrorCode error, int missed, int cached) { - log('streamMessage $uid $streamId $error $missed $cached'); - })); + _engine.setEventHandler(RtcEngineEventHandler( + warning: (warningCode) { + logSink.log('warning ${warningCode}'); + }, + error: (errorCode) { + logSink.log('error ${errorCode}'); + }, + joinChannelSuccess: (channel, uid, elapsed) { + logSink.log('joinChannelSuccess ${channel} ${uid} ${elapsed}'); + setState(() { + isJoined = true; + }); + }, + userJoined: (uid, elapsed) { + logSink.log('userJoined $uid $elapsed'); + remoteUids.add(uid); + this.setState(() {}); + }, + userOffline: (uid, reason) { + logSink.log('userOffline $uid $reason'); + remoteUids.remove(uid); + this.setState(() {}); + }, + streamMessage: (int uid, int streamId, Uint8List data) { + _showMyDialog(uid, streamId, utf8.decode(data)); + logSink.log('streamMessage $uid $streamId $data'); + }, + streamMessageError: + (int uid, int streamId, ErrorCode error, int missed, int cached) { + logSink.log('streamMessage $uid $streamId $error $missed $cached'); + }, + )); } _onPressSend() async { @@ -120,7 +124,8 @@ class _State extends State { var streamId = await _engine .createDataStreamWithConfig(DataStreamConfig(false, false)); if (streamId != null) { - _engine.sendStreamMessage(streamId, _controller.text); + _engine.sendStreamMessage( + streamId, Uint8List.fromList(utf8.encode(_controller.text))); } _controller.clear(); } @@ -132,6 +137,8 @@ class _State extends State { return Stack( children: [ Column( + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.start, children: [ !isJoined ? Row( @@ -169,24 +176,38 @@ class _State extends State { } _renderVideo() { - return Row(children: [ - Expanded( - child: AspectRatio( - aspectRatio: 1, - child: RtcLocalView.SurfaceView(), - )), - Expanded( - child: AspectRatio( - aspectRatio: 1, - child: remoteUid != null - ? RtcRemoteView.SurfaceView( - uid: remoteUid!, - ) - : Container( - color: Colors.grey[200], + final views = [ + Container( + height: 120, + width: 120, + child: kIsWeb ? RtcLocalView.SurfaceView() : RtcLocalView.TextureView(), + ), + ]; + if (remoteUids.isNotEmpty) { + views.addAll(remoteUids.map((uid) { + return (kIsWeb + ? Container( + height: 120, + width: 120, + child: RtcRemoteView.SurfaceView( + uid: uid, + channelId: config.channelId, ), - ), - ) - ]); + ) + : Container( + height: 120, + width: 120, + child: RtcRemoteView.TextureView( + uid: uid, + channelId: config.channelId, + ), + )); + })); + } else { + views.add(Container( + color: Colors.grey[200], + )); + } + return Wrap(children: views); } } diff --git a/example/lib/examples/advanced/voice_changer/voice_changer.dart b/example/lib/examples/advanced/voice_changer/voice_changer.dart index b0cffe006..2aa2bd05b 100644 --- a/example/lib/examples/advanced/voice_changer/voice_changer.dart +++ b/example/lib/examples/advanced/voice_changer/voice_changer.dart @@ -1,8 +1,7 @@ -import 'dart:developer'; - import 'package:agora_rtc_engine/rtc_engine.dart'; import 'package:agora_rtc_engine_example/config/agora.config.dart' as config; import 'package:agora_rtc_engine_example/examples/advanced/voice_changer/voice_changer.config.dart'; +import 'package:agora_rtc_engine_example/examples/log_sink.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; @@ -32,13 +31,73 @@ class _State extends State { Map selectedFreq = FreqOptions[0]; Map selectedReverbKey = ReverbKeyOptions[0]; - double voicePitchValue = 0.5; + double _voicePitchValue = 0.5; double bandGainValue = 0; double reverbValue = 1; + late final TextEditingController _channelId; + VoiceBeautifierPreset _selectedVoiceBeautifierPreset = + VoiceBeautifierPreset.VoiceBeautifierOff; + + AudioEffectPreset _selectedAudioEffectPreset = + AudioEffectPreset.AudioEffectOff; + + AudioReverbType _selectedAudioReverbType = AudioReverbType.DryLevel; + + double _audioEffectPresetParam1 = 0; + double _audioEffectPresetParam2 = 0; + + List _voiceBeautifierPresets = [ + VoiceBeautifierPreset.VoiceBeautifierOff, + VoiceBeautifierPreset.ChatBeautifierMagnetic, + VoiceBeautifierPreset.ChatBeautifierFresh, + ]; + + List _audioEffectPresets = [ + AudioEffectPreset.AudioEffectOff, + AudioEffectPreset.RoomAcousticsKTV, + AudioEffectPreset.RoomAcousticsVocalConcert, + ]; + + List _audioReverbTypes = [ + AudioReverbType.DryLevel, + AudioReverbType.WetLevel, + AudioReverbType.RoomSize, + ]; + + Map> _audioReverbTypeRanges = { + AudioReverbType.DryLevel: [-20.0, 10.0, 0.0], + AudioReverbType.WetLevel: [-20.0, 10.0, 0.0], + AudioReverbType.RoomSize: [0.0, 100.0, 0.0], + }; + + late double _selectedAudioReverbTypeValue; + + List _audioEqualizationBandFrequencys = [ + AudioEqualizationBandFrequency.Band31, + AudioEqualizationBandFrequency.Band62, + AudioEqualizationBandFrequency.Band125, + ]; + + late AudioEqualizationBandFrequency _selectedAudioEqualizationBandFrequencys; + + late double _selectedAudioEqualizationBandFrequencyValue; + + bool _setVoiceBeautifierPresetOnly = false; + @override void initState() { super.initState(); + _channelId = TextEditingController(text: config.channelId); + + _selectedVoiceBeautifierPreset = _voiceBeautifierPresets[0]; + _selectedAudioEffectPreset = _audioEffectPresets[0]; + _selectedAudioReverbType = _audioReverbTypes[0]; + _selectedAudioReverbTypeValue = + _audioReverbTypeRanges[_selectedAudioReverbType]![2]; + _selectedAudioEqualizationBandFrequencys = + _audioEqualizationBandFrequencys[0]; + _selectedAudioEqualizationBandFrequencyValue = 0.0; } @override @@ -58,315 +117,259 @@ class _State extends State { await _engine.setChannelProfile(ChannelProfile.LiveBroadcasting); await _engine.setClientRole(ClientRole.Broadcaster); - // Set audio route to speaker - await _engine.setDefaultAudioRoutetoSpeakerphone(true); - // start joining channel // 1. Users can only see each other after they join the // same channel successfully using the same app id. // 2. If app certificate is turned on at dashboard, token is needed // when joining channel. The channel name and uid used to calculate // the token has to match the ones used for channel join - await _engine.joinChannel(config.token, config.channelId, null, 0, null); + await _engine.joinChannel(config.token, _channelId.text, null, 0, null); } _addListener() { - _engine.setEventHandler(RtcEngineEventHandler(warning: (warningCode) { - log('Warning ${warningCode}'); - }, error: (errorCode) { - log('Warning ${errorCode}'); - }, joinChannelSuccess: (channel, uid, elapsed) { - log('joinChannelSuccess ${channel} ${uid} ${elapsed}'); - ; - setState(() { - isJoined = true; - uidMySelf = uid; - }); - }, userJoined: (uid, elapsed) { - log('userJoined $uid $elapsed'); - this.setState(() { - remoteUids.add(uid); - }); - }, userOffline: (uid, reason) { - log('userOffline $uid $reason'); - this.setState(() { - remoteUids.remove(uid); - }); - })); - } - - _onPressBFButton(dynamic type, int index) async { - switch (index) { - case 0: - case 1: - await _engine.setVoiceBeautifierPreset(type as VoiceBeautifierPreset); - this._updateSliderUI(AudioEffectPreset.AudioEffectOff); - break; - case 2: - case 3: - case 4: - case 5: - await _engine.setAudioEffectPreset(type as AudioEffectPreset); - this._updateSliderUI(type); - break; - default: - break; - } + _engine.setEventHandler(RtcEngineEventHandler( + warning: (warningCode) { + logSink.log('warning ${warningCode}'); + }, + error: (errorCode) { + logSink.log('error ${errorCode}'); + }, + joinChannelSuccess: (channel, uid, elapsed) { + logSink.log('joinChannelSuccess ${channel} ${uid} ${elapsed}'); + setState(() { + isJoined = true; + uidMySelf = uid; + }); + }, + userJoined: (uid, elapsed) { + logSink.log('userJoined $uid $elapsed'); + setState(() { + remoteUids.add(uid); + }); + }, + userOffline: (uid, reason) { + logSink.log('userOffline $uid $reason'); + setState(() { + remoteUids.remove(uid); + }); + }, + )); } - _updateSliderUI(AudioEffectPreset type) { - this.setState(() { - currentAudioEffectPreset = type; - switch (type) { - case AudioEffectPreset.RoomAcoustics3DVoice: - isEnableSlider1 = true; - isEnableSlider2 = false; - sliderTitle1 = 'Cycle'; - minimumValue1 = 1; - sliderValue1 = 1; - maximumValue1 = 3; - break; - case AudioEffectPreset.PitchCorrection: - isEnableSlider1 = true; - isEnableSlider2 = true; - sliderTitle1 = 'Tonic Mode'; - sliderTitle2 = 'Tonic Pitch'; - minimumValue1 = 1; - sliderValue1 = 1; - maximumValue1 = 3; - minimumValue2 = 1; - sliderValue2 = 1; - maximumValue2 = 12; - break; - default: - isEnableSlider1 = false; - isEnableSlider2 = false; - break; - } - }); + DropdownButton _createDropdownButton( + List enums, ValueGetter value, ValueChanged onChanged) { + return DropdownButton( + items: enums.map((e) { + return DropdownMenuItem( + value: e, + child: Text('$e'), + ); + }).toList(), + value: value(), + onChanged: onChanged); } - _onAudioEffectUpdate({ - double? value1, - double? value2, - }) async { - this.setState(() { - if (value1 != null) { - sliderValue1 = value1; - } - if (value2 != null) { - sliderValue2 = value2; - } - _engine.setAudioEffectParameters( - currentAudioEffectPreset, - (isEnableSlider1 ? sliderValue1 ?? minimumValue1 : 0).toInt(), - (isEnableSlider2 ? sliderValue2 ?? minimumValue2 : 0).toInt()); - }); - } + Widget _presets() { + if (_setVoiceBeautifierPresetOnly) { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text('Select VoiceBeautifierPreset: '), + _createDropdownButton( + _voiceBeautifierPresets, + () => _selectedVoiceBeautifierPreset, + (v) async { + setState(() { + _selectedVoiceBeautifierPreset = v!; + }); + }, + ), + ElevatedButton( + onPressed: () async { + await _engine + .setVoiceBeautifierPreset(_selectedVoiceBeautifierPreset); + }, + child: Text('setVoiceBeautifierPreset'), + ), + ], + ); + } - _onPressChangeFreq() { - return showDialog( - context: context, - barrierDismissible: false, - builder: (BuildContext context) { - return AlertDialog( - title: Text('Set Band Frequency'), - actions: [ - for (var freqOpt in FreqOptions) - TextButton( - child: Text(freqOpt['text'] as String), - onPressed: () { - setState(() { - selectedFreq = freqOpt; - _engine.setLocalVoiceEqualization( - freqOpt['type'] as AudioEqualizationBandFrequency, - bandGainValue.toInt()); - }); - Navigator.of(context).pop(); - }, - ), + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text('Select AudioEffectPreset: '), + _createDropdownButton( + _audioEffectPresets, + () => _selectedAudioEffectPreset, + (v) async { + setState(() { + _selectedAudioEffectPreset = v!; + }); + }, + ), ], - ); - }, - ); - } - - _onPressChangeReverbKey() { - return showDialog( - context: context, - barrierDismissible: false, - builder: (BuildContext context) { - return AlertDialog( - title: Text('Set Reverb Key'), - actions: [ - for (var reverbKey in ReverbKeyOptions) - TextButton( - child: Text(reverbKey['text'] as String), - onPressed: () { - setState(() { - selectedReverbKey = reverbKey; - }); - Navigator.of(context).pop(); - }, - ), + ), + ElevatedButton( + onPressed: () async { + await _engine.setAudioEffectPreset(_selectedAudioEffectPreset); + }, + child: Text('setAudioEffectPreset'), + ), + Row( + children: [ + Text('param1'), + Slider( + value: _audioEffectPresetParam1, + min: 0.0, + max: 10.0, + divisions: 10, + label: 'param1 $_audioEffectPresetParam1', + onChanged: (double value) { + setState(() { + _audioEffectPresetParam1 = value; + }); + }, + ), ], - ); - }, - ); - } - - _renderToolBar() { - return Padding( - padding: EdgeInsets.symmetric(horizontal: 8, vertical: 0), - child: Column( + ), + Row( children: [ - Row(children: [ - Text('Voice Beautifier & Effects Preset', - style: TextStyle(fontWeight: FontWeight.bold)) - ]), - Container( - width: MediaQuery.of(context).size.width, - child: Wrap(children: [ - for (var i = 0; i < VoiceChangeConfig.length; i++) - _renderBtnItem(VoiceChangeConfig[i], i) - ])), - if (isEnableSlider1) - Row( - mainAxisAlignment: MainAxisAlignment.end, - mainAxisSize: MainAxisSize.max, - children: [ - Expanded( - child: Text(sliderTitle1), - flex: 1, - ), - Expanded( - child: Slider( - value: sliderValue1!, - min: minimumValue1, - max: maximumValue1, - divisions: 5, - label: sliderTitle1, - onChanged: (double value) { - _onAudioEffectUpdate(value1: value); - }, - ), - flex: 2, - ) - ], - ), - if (isEnableSlider2) - Row( - mainAxisAlignment: MainAxisAlignment.end, - mainAxisSize: MainAxisSize.max, - children: [ - Expanded(child: Text(sliderTitle2), flex: 1), - Expanded( - child: Slider( - value: sliderValue2!, - min: minimumValue2, - max: maximumValue2, - divisions: 5, - label: sliderTitle1, - onChanged: (double value) { - _onAudioEffectUpdate(value2: value); - }, - ), - flex: 2) - ], - ), - Row(children: [ - Text('Customize Voice Effects', - style: TextStyle(fontWeight: FontWeight.bold)) - ]), - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Text('Pitch:'), - Slider( - value: voicePitchValue, - min: 0.5, - max: 2, - divisions: 5, - onChanged: (double value) { - setState(() { - voicePitchValue = value; - }); - _engine.setLocalVoicePitch(value); - }, - ) - ], + Text('param2'), + Slider( + value: _audioEffectPresetParam2, + min: 0.0, + max: 10.0, + divisions: 10, + label: 'param2 $_audioEffectPresetParam2', + onChanged: (double value) { + setState(() { + _audioEffectPresetParam2 = value; + }); + }, ), - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Text('BandFreq'), - TextButton( - child: Text(selectedFreq['text']), - onPressed: _onPressChangeFreq, - ) - ], + ], + ), + ElevatedButton( + onPressed: () async { + await _engine.setAudioEffectParameters( + _selectedAudioEffectPreset, + _audioEffectPresetParam1.toInt(), + _audioEffectPresetParam2.toInt(), + ); + }, + child: Text('setAudioEffectParameters'), + ), + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text('Select AudioReverbType: '), + _createDropdownButton( + _audioReverbTypes, + () => _selectedAudioReverbType, + (v) { + setState(() { + _selectedAudioReverbType = v!; + _selectedAudioReverbTypeValue = + _audioReverbTypeRanges[_selectedAudioReverbType]![2]; + }); + }, ), - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Text('BandGain:'), - Slider( - value: bandGainValue, - min: 0, - max: 9, - divisions: 5, - onChanged: (double value) async { - this.setState(() { - bandGainValue = value; - }); - _engine.setLocalVoiceEqualization( - selectedFreq['type'], value.toInt()); - }, - ) - ], + ], + ), + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text('Select Local Voice Reverb Value: '), + Slider( + value: _selectedAudioReverbTypeValue, + min: _audioReverbTypeRanges[_selectedAudioReverbType]![0], + max: _audioReverbTypeRanges[_selectedAudioReverbType]![1], + divisions: 10, + label: 'AudioReverbType Value $_selectedAudioReverbTypeValue', + onChanged: (double value) { + setState(() { + _selectedAudioReverbTypeValue = value; + }); + }, ), - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Text('BandKey'), - TextButton( - child: Text(selectedReverbKey['text']), - onPressed: _onPressChangeReverbKey, - ) - ], + ], + ), + ElevatedButton( + onPressed: () async { + await _engine.setLocalVoiceReverb(_selectedAudioReverbType, + _selectedAudioReverbTypeValue.toInt()); + }, + child: Text('setLocalVoiceReverb')), + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text('Select AudioEqualizationBandFrequency: '), + _createDropdownButton( + _audioEqualizationBandFrequencys, + () => _selectedAudioEqualizationBandFrequencys, + (v) async { + setState(() { + _selectedAudioEqualizationBandFrequencys = v!; + }); + }, ), - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Text('ReverbValue:'), - Slider( - value: reverbValue, - min: selectedReverbKey['min'], - max: selectedReverbKey['max'], - divisions: 5, - onChanged: (double value) async { - setState(() { - reverbValue = value; - }); - await _engine.setLocalVoiceReverb( - selectedReverbKey['type'], value.toInt()); - }, - ) - ], + ], + ), + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text('Select AudioEqualizationBandFrequency Value:'), + Slider( + value: _selectedAudioEqualizationBandFrequencyValue, + min: -15.0, + max: 15.0, + divisions: 10, + label: + 'AudioEqualizationBandFrequency Value: $_selectedAudioEqualizationBandFrequencyValue', + onChanged: (double value) { + setState(() { + _selectedAudioEqualizationBandFrequencyValue = value; + }); + }, ), ], - )); - } - - _renderBtnItem(Map config, int index) { - return _CusBtn( - config['alertTitle'], selectedVoiceToolBtn != index, config['options'], - (type) { - setState(() { - selectedVoiceToolBtn = index; - }); - _onPressBFButton(type, index); - }); + ), + ElevatedButton( + onPressed: () async { + await _engine.setLocalVoiceEqualization( + _selectedAudioEqualizationBandFrequencys, + _selectedAudioEqualizationBandFrequencyValue.toInt()); + }, + child: Text('setLocalVoiceEqualization')), + Row( + children: [ + Text('Pitch:'), + Slider( + value: _voicePitchValue, + min: 0.5, + max: 2, + divisions: 10, + label: 'Pitch $_voicePitchValue', + onChanged: (double value) { + setState(() { + _voicePitchValue = value; + }); + }, + ) + ], + ), + ElevatedButton( + onPressed: () async { + _engine.setLocalVoicePitch(_voicePitchValue); + }, + child: Text('setLocalVoicePitch'), + ), + ], + ); } @override @@ -375,8 +378,27 @@ class _State extends State { children: [ Column( children: [ - !isJoined - ? Row( + if (!isJoined) + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + TextField( + controller: _channelId, + ), + Row(mainAxisSize: MainAxisSize.min, children: [ + Text('setVoiceBeautifierPreset Only'), + Switch( + value: _setVoiceBeautifierPresetOnly, + onChanged: !isJoined + ? (v) { + setState(() { + _setVoiceBeautifierPresetOnly = v; + }); + } + : null, + ) + ]), + Row( children: [ Expanded( flex: 1, @@ -386,96 +408,17 @@ class _State extends State { ), ) ], - ) - : _renderUserUid(), - if (isJoined) _renderToolBar() + ), + ], + ), + if (isJoined) + Expanded( + child: SingleChildScrollView( + child: _presets(), + )), ], ), ], ); } - - _renderUserUid() { - final size = MediaQuery.of(context).size; - var list = [uidMySelf, ...remoteUids]; - return Container( - width: size.width, - height: 200, - child: ListView.builder( - itemCount: list.length, - itemBuilder: (context, index) { - return Center( - child: Padding( - child: Text( - 'AUDIO ONLY ${index == 0 ? 'LOCAL' : 'REMOTE'} UID: ${list[index]}', - style: TextStyle(fontSize: 14, color: Colors.black), - ), - padding: EdgeInsets.all(4.0), - ), - ); - }, - ), - ); - } -} - -class _CusBtn extends StatefulWidget { - String alertTitle; - dynamic options; - bool isOff = false; - void Function(dynamic type) onPressed; - - _CusBtn(this.alertTitle, this.isOff, this.options, this.onPressed); - - @override - State createState() => _CusBtnState(isOff); -} - -class _CusBtnState extends State<_CusBtn> { - String title = "Off"; - bool isEnable; - - _CusBtnState(this.isEnable); - - @override - void didUpdateWidget(covariant _CusBtn oldWidget) { - super.didUpdateWidget(oldWidget); - this.setState(() { - isEnable = !widget.isOff; - }); - } - - @override - Widget build(BuildContext context) { - return TextButton( - child: Text(isEnable ? title : 'Off'), - onPressed: _showMyDialog, - ); - } - - Future _showMyDialog() async { - return showDialog( - context: context, - barrierDismissible: false, - builder: (BuildContext context) { - return AlertDialog( - title: Text(widget.alertTitle), - actions: [ - for (var option in widget.options) - TextButton( - child: Text(option['text']), - onPressed: () { - setState(() { - isEnable = true; - title = option['text']; - widget.onPressed(option['type']); - }); - Navigator.of(context).pop(); - }, - ), - ], - ); - }, - ); - } } diff --git a/example/lib/examples/basic/join_channel_audio/join_channel_audio.dart b/example/lib/examples/basic/join_channel_audio/join_channel_audio.dart index 4068a0e82..c73316c99 100644 --- a/example/lib/examples/basic/join_channel_audio/join_channel_audio.dart +++ b/example/lib/examples/basic/join_channel_audio/join_channel_audio.dart @@ -1,13 +1,11 @@ -import 'dart:async'; -import 'dart:developer'; - import 'package:agora_rtc_engine/rtc_engine.dart'; import 'package:agora_rtc_engine_example/config/agora.config.dart' as config; -import 'package:flutter/cupertino.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:permission_handler/permission_handler.dart'; +import '../../log_sink.dart'; + /// JoinChannelAudio Example class JoinChannelAudio extends StatefulWidget { @override @@ -22,8 +20,10 @@ class _State extends State { enableSpeakerphone = true, playEffect = false; bool _enableInEarMonitoring = false; - double _recordingVolume = 0, _playbackVolume = 0, _inEarMonitoringVolume = 0; - TextEditingController? _controller; + double _recordingVolume = 100, + _playbackVolume = 100, + _inEarMonitoringVolume = 100; + late TextEditingController _controller; @override void initState() { @@ -49,14 +49,20 @@ class _State extends State { _addListeners() { _engine.setEventHandler(RtcEngineEventHandler( + warning: (warningCode) { + logSink.log('warning ${warningCode}'); + }, + error: (errorCode) { + logSink.log('error ${errorCode}'); + }, joinChannelSuccess: (channel, uid, elapsed) { - log('joinChannelSuccess ${channel} ${uid} ${elapsed}'); + logSink.log('joinChannelSuccess ${channel} ${uid} ${elapsed}'); setState(() { isJoined = true; }); }, leaveChannel: (stats) async { - log('leaveChannel ${stats.toJson()}'); + logSink.log('leaveChannel ${stats.toJson()}'); setState(() { isJoined = false; }); @@ -70,23 +76,34 @@ class _State extends State { } await _engine - .joinChannel(config.token, config.channelId, null, config.uid) + .joinChannel(config.token, _controller.text, null, config.uid) .catchError((onError) { - print('error ${onError.toString()}'); + logSink.log('error ${onError.toString()}'); }); } _leaveChannel() async { await _engine.leaveChannel(); + setState(() { + isJoined = false; + openMicrophone = true; + enableSpeakerphone = true; + playEffect = false; + _enableInEarMonitoring = false; + _recordingVolume = 100; + _playbackVolume = 100; + _inEarMonitoringVolume = 100; + }); } - _switchMicrophone() { - _engine.enableLocalAudio(!openMicrophone).then((value) { + _switchMicrophone() async { + // await _engine.muteLocalAudioStream(!openMicrophone); + await _engine.enableLocalAudio(!openMicrophone).then((value) { setState(() { openMicrophone = !openMicrophone; }); }).catchError((err) { - log('enableLocalAudio $err'); + logSink.log('enableLocalAudio $err'); }); } @@ -96,7 +113,7 @@ class _State extends State { enableSpeakerphone = !enableSpeakerphone; }); }).catchError((err) { - log('setEnableSpeakerphone $err'); + logSink.log('setEnableSpeakerphone $err'); }); } @@ -107,41 +124,31 @@ class _State extends State { playEffect = false; }); }).catchError((err) { - log('stopEffect $err'); + logSink.log('stopEffect $err'); }); } else { - _engine - .playEffect( - 1, - await (_engine.getAssetAbsolutePath("assets/Sound_Horizon.mp3") - as FutureOr), - -1, - 1, - 1, - 100, - true) - .then((value) { + final path = + (await _engine.getAssetAbsolutePath("assets/Sound_Horizon.mp3"))!; + _engine.playEffect(1, path, 0, 1, 1, 100, openMicrophone).then((value) { setState(() { playEffect = true; }); }).catchError((err) { - log('playEffect $err'); + logSink.log('playEffect $err'); }); } } - _onChangeInEarMonitoringVolume(double value) { - setState(() { - _inEarMonitoringVolume = value; - }); - _engine.setInEarMonitoringVolume(value.toInt()); + _onChangeInEarMonitoringVolume(double value) async { + _inEarMonitoringVolume = value; + await _engine.setInEarMonitoringVolume(_inEarMonitoringVolume.toInt()); + setState(() {}); } - _toggleInEarMonitoring(value) { - setState(() { - _enableInEarMonitoring = value; - }); - _engine.enableInEarMonitoring(value); + _toggleInEarMonitoring(value) async { + _enableInEarMonitoring = value; + await _engine.enableInEarMonitoring(_enableInEarMonitoring); + setState(() {}); } @override @@ -153,11 +160,6 @@ class _State extends State { TextField( controller: _controller, decoration: InputDecoration(hintText: 'Channel ID'), - onChanged: (text) { - setState(() { - channelId = text; - }); - }, ), Row( children: [ @@ -185,14 +187,15 @@ class _State extends State { child: Text('Microphone ${openMicrophone ? 'on' : 'off'}'), ), ElevatedButton( - onPressed: this._switchSpeakerphone, + onPressed: isJoined ? this._switchSpeakerphone : null, child: Text(enableSpeakerphone ? 'Speakerphone' : 'Earpiece'), ), - ElevatedButton( - onPressed: this._switchEffect, - child: Text('${playEffect ? 'Stop' : 'Play'} effect'), - ), + if (!kIsWeb) + ElevatedButton( + onPressed: isJoined ? this._switchEffect : null, + child: Text('${playEffect ? 'Stop' : 'Play'} effect'), + ), Row( mainAxisAlignment: MainAxisAlignment.end, children: [ @@ -203,12 +206,15 @@ class _State extends State { max: 400, divisions: 5, label: 'RecordingVolume', - onChanged: (double value) { - setState(() { - _recordingVolume = value; - }); - _engine.adjustRecordingSignalVolume(value.toInt()); - }, + onChanged: isJoined + ? (double value) { + setState(() { + _recordingVolume = value; + }); + _engine + .adjustRecordingSignalVolume(value.toInt()); + } + : null, ) ], ), @@ -222,12 +228,15 @@ class _State extends State { max: 400, divisions: 5, label: 'PlaybackVolume', - onChanged: (double value) { - setState(() { - _playbackVolume = value; - }); - _engine.adjustPlaybackSignalVolume(value.toInt()); - }, + onChanged: isJoined + ? (double value) { + setState(() { + _playbackVolume = value; + }); + _engine + .adjustPlaybackSignalVolume(value.toInt()); + } + : null, ) ], ), @@ -239,7 +248,7 @@ class _State extends State { Text('InEar Monitoring Volume:'), Switch( value: _enableInEarMonitoring, - onChanged: _toggleInEarMonitoring, + onChanged: isJoined ? _toggleInEarMonitoring : null, activeTrackColor: Colors.grey[350], activeColor: Colors.white, ) @@ -252,8 +261,11 @@ class _State extends State { min: 0, max: 100, divisions: 5, - label: 'InEar Monitoring Volume', - onChanged: _onChangeInEarMonitoringVolume, + label: + 'InEar Monitoring Volume $_inEarMonitoringVolume', + onChanged: isJoined + ? _onChangeInEarMonitoringVolume + : null, )) ], ), diff --git a/example/lib/examples/basic/join_channel_video/join_channel_video.dart b/example/lib/examples/basic/join_channel_video/join_channel_video.dart index d6a8b41d3..955847091 100644 --- a/example/lib/examples/basic/join_channel_video/join_channel_video.dart +++ b/example/lib/examples/basic/join_channel_video/join_channel_video.dart @@ -1,9 +1,8 @@ -import 'dart:developer'; - import 'package:agora_rtc_engine/rtc_engine.dart'; import 'package:agora_rtc_engine/rtc_local_view.dart' as RtcLocalView; import 'package:agora_rtc_engine/rtc_remote_view.dart' as RtcRemoteView; import 'package:agora_rtc_engine_example/config/agora.config.dart' as config; +import 'package:agora_rtc_engine_example/examples/log_sink.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; @@ -17,15 +16,16 @@ class JoinChannelVideo extends StatefulWidget { class _State extends State { late final RtcEngine _engine; - String channelId = config.channelId; + bool isJoined = false, switchCamera = true, switchRender = true; List remoteUid = []; - TextEditingController? _controller; + late TextEditingController _controller; + bool _isRenderSurfaceView = false; @override void initState() { super.initState(); - _controller = TextEditingController(text: channelId); + _controller = TextEditingController(text: config.channelId); this._initEngine(); } @@ -47,26 +47,32 @@ class _State extends State { _addListeners() { _engine.setEventHandler(RtcEngineEventHandler( + warning: (warningCode) { + logSink.log('warning ${warningCode}'); + }, + error: (errorCode) { + logSink.log('error ${errorCode}'); + }, joinChannelSuccess: (channel, uid, elapsed) { - log('joinChannelSuccess ${channel} ${uid} ${elapsed}'); + logSink.log('joinChannelSuccess ${channel} ${uid} ${elapsed}'); setState(() { isJoined = true; }); }, userJoined: (uid, elapsed) { - log('userJoined ${uid} ${elapsed}'); + logSink.log('userJoined ${uid} ${elapsed}'); setState(() { remoteUid.add(uid); }); }, userOffline: (uid, reason) { - log('userOffline ${uid} ${reason}'); + logSink.log('userOffline ${uid} ${reason}'); setState(() { remoteUid.removeWhere((element) => element == uid); }); }, leaveChannel: (stats) { - log('leaveChannel ${stats.toJson()}'); + logSink.log('leaveChannel ${stats.toJson()}'); setState(() { isJoined = false; remoteUid.clear(); @@ -79,7 +85,7 @@ class _State extends State { if (defaultTargetPlatform == TargetPlatform.android) { await [Permission.microphone, Permission.camera].request(); } - await _engine.joinChannel(config.token, channelId, null, config.uid); + await _engine.joinChannel(config.token, _controller.text, null, config.uid); } _leaveChannel() async { @@ -92,7 +98,7 @@ class _State extends State { switchCamera = !switchCamera; }); }).catchError((err) { - log('switchCamera $err'); + logSink.log('switchCamera $err'); }); } @@ -108,16 +114,33 @@ class _State extends State { return Stack( children: [ Column( + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.start, children: [ TextField( controller: _controller, decoration: InputDecoration(hintText: 'Channel ID'), - onChanged: (text) { - setState(() { - channelId = text; - }); - }, ), + if (!kIsWeb && + (defaultTargetPlatform == TargetPlatform.android || + defaultTargetPlatform == TargetPlatform.iOS)) + Row( + mainAxisSize: MainAxisSize.min, + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Text('Rendered by SurfaceView \n(default TextureView): '), + Switch( + value: _isRenderSurfaceView, + onChanged: isJoined + ? null + : (changed) { + setState(() { + _isRenderSurfaceView = changed; + }); + }, + ) + ], + ), Row( children: [ Expanded( @@ -133,18 +156,20 @@ class _State extends State { _renderVideo(), ], ), - Align( - alignment: Alignment.bottomRight, - child: Column( - mainAxisSize: MainAxisSize.min, - children: [ - ElevatedButton( - onPressed: this._switchCamera, - child: Text('Camera ${switchCamera ? 'front' : 'rear'}'), - ), - ], - ), - ) + if (defaultTargetPlatform == TargetPlatform.android || + defaultTargetPlatform == TargetPlatform.iOS) + Align( + alignment: Alignment.bottomRight, + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + ElevatedButton( + onPressed: this._switchCamera, + child: Text('Camera ${switchCamera ? 'front' : 'rear'}'), + ), + ], + ), + ) ], ); } @@ -153,7 +178,11 @@ class _State extends State { return Expanded( child: Stack( children: [ - RtcLocalView.SurfaceView(), + Container( + child: (kIsWeb || _isRenderSurfaceView) + ? RtcLocalView.SurfaceView(zOrderMediaOverlay: true, zOrderOnTop: true,) + : RtcLocalView.TextureView(), + ), Align( alignment: Alignment.topLeft, child: SingleChildScrollView( @@ -165,9 +194,15 @@ class _State extends State { child: Container( width: 120, height: 120, - child: RtcRemoteView.SurfaceView( - uid: e, - ), + child: (kIsWeb || _isRenderSurfaceView) + ? RtcRemoteView.SurfaceView( + uid: e, + channelId: _controller.text, + ) + : RtcRemoteView.TextureView( + uid: e, + channelId: _controller.text, + ), ), ), )), diff --git a/example/lib/examples/basic/string_uid/string_uid.dart b/example/lib/examples/basic/string_uid/string_uid.dart index 088591a6c..2833a76d2 100644 --- a/example/lib/examples/basic/string_uid/string_uid.dart +++ b/example/lib/examples/basic/string_uid/string_uid.dart @@ -1,13 +1,11 @@ -import 'dart:developer'; - import 'package:agora_rtc_engine/rtc_engine.dart'; import 'package:agora_rtc_engine_example/config/agora.config.dart' as config; -import 'package:flutter/cupertino.dart'; +import 'package:agora_rtc_engine_example/examples/log_sink.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:permission_handler/permission_handler.dart'; -/// MultiChannel Example +/// StringUid Example class StringUid extends StatefulWidget { @override State createState() => _State(); @@ -15,16 +13,14 @@ class StringUid extends StatefulWidget { class _State extends State { late final RtcEngine _engine; - String channelId = config.channelId; - String stringUid = config.stringUid; bool isJoined = false; - TextEditingController? _controller0, _controller1; + late TextEditingController _controller0, _controller1; @override void initState() { super.initState(); - _controller0 = TextEditingController(text: channelId); - _controller1 = TextEditingController(text: stringUid); + _controller0 = TextEditingController(text: config.channelId); + _controller1 = TextEditingController(text: config.stringUid); this._initEngine(); } @@ -38,20 +34,27 @@ class _State extends State { _engine = await RtcEngine.createWithContext(RtcEngineContext(config.appId)); this._addListeners(); + await _engine.enableAudio(); await _engine.setChannelProfile(ChannelProfile.LiveBroadcasting); await _engine.setClientRole(ClientRole.Broadcaster); } _addListeners() { _engine.setEventHandler(RtcEngineEventHandler( + warning: (warningCode) { + logSink.log('warning ${warningCode}'); + }, + error: (errorCode) { + logSink.log('error ${errorCode}'); + }, joinChannelSuccess: (channel, uid, elapsed) { - log('joinChannelSuccess ${channel} ${uid} ${elapsed}'); + logSink.log('joinChannelSuccess ${channel} ${uid} ${elapsed}'); setState(() { isJoined = true; }); }, leaveChannel: (stats) { - log('leaveChannel ${stats.toJson()}'); + logSink.log('leaveChannel ${stats.toJson()}'); setState(() { isJoined = false; }); @@ -64,7 +67,7 @@ class _State extends State { await Permission.microphone.request(); } await _engine.joinChannelWithUserAccount( - config.token, channelId, stringUid); + config.token, _controller0.text, _controller1.text); } _leaveChannel() async { @@ -72,13 +75,13 @@ class _State extends State { } _getUserInfo() { - _engine.getUserInfoByUserAccount(stringUid).then((userInfo) { - log('getUserInfoByUserAccount ${userInfo.toJson()}'); + _engine.getUserInfoByUserAccount(_controller1.text).then((userInfo) { + logSink.log('getUserInfoByUserAccount ${userInfo.toJson()}'); ScaffoldMessenger.of(context).showSnackBar(SnackBar( content: Text('${userInfo.toJson()}'), )); }).catchError((err) { - log('getUserInfoByUserAccount ${err}'); + logSink.log('getUserInfoByUserAccount ${err}'); }); } @@ -91,20 +94,10 @@ class _State extends State { TextField( controller: _controller0, decoration: InputDecoration(hintText: 'Channel ID'), - onChanged: (text) { - setState(() { - channelId = text; - }); - }, ), TextField( controller: _controller1, decoration: InputDecoration(hintText: 'String User ID'), - onChanged: (text) { - setState(() { - stringUid = text; - }); - }, ), Row( children: [ diff --git a/example/lib/examples/log_sink.dart b/example/lib/examples/log_sink.dart new file mode 100644 index 000000000..24a9babd1 --- /dev/null +++ b/example/lib/examples/log_sink.dart @@ -0,0 +1,164 @@ +import 'package:flutter/material.dart'; + +class LogActionWidget extends StatefulWidget { + const LogActionWidget({Key? key}) : super(key: key); + + @override + _LogActionWidgetState createState() => _LogActionWidgetState(); +} + +class _LogActionWidgetState extends State { + bool _isOverlayShowed = false; + + OverlayEntry? _overlayEntry; + + @override + void dispose() { + _removeOverlay(); + + super.dispose(); + } + + void _removeOverlay() { + if (_overlayEntry != null) { + _overlayEntry!.remove(); + _overlayEntry = null; + } + } + + @override + Widget build(BuildContext context) { + return TextButton( + onPressed: () { + if (_isOverlayShowed) { + _removeOverlay(); + } else { + _overlayEntry = OverlayEntry(builder: (c) { + return Positioned( + left: 0, + top: 0, + height: MediaQuery.of(context).size.height * 0.5, + width: MediaQuery.of(context).size.width, + child: Container( + color: Colors.black87, + child: SafeArea( + bottom: false, + child: Material( + color: Colors.transparent, + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisSize: MainAxisSize.max, + children: [ + Row( + mainAxisSize: MainAxisSize.max, + children: [ + TextButton( + onPressed: () { + logSink.clear(); + }, + child: Text( + 'Clear log', + style: TextStyle(color: Colors.white), + ), + ), + Expanded( + child: Align( + alignment: Alignment.topRight, + child: IconButton( + color: Colors.transparent, + onPressed: () { + _removeOverlay(); + _isOverlayShowed = !_isOverlayShowed; + }, + icon: Icon( + Icons.close, + color: Colors.white, + )), + ), + ), + ], + ), + Expanded( + child: SingleChildScrollView( + child: _LogActionInner(), + ), + ) + ], + ), + ), + ), + ), + ); + }); + Overlay.of(context)?.insert(_overlayEntry!); + } + _isOverlayShowed = !_isOverlayShowed; + // setState(() { + + // }); + }, + child: Text( + 'Log', + style: TextStyle(color: Colors.white), + )); + } +} + +class _LogActionInner extends StatefulWidget { + const _LogActionInner({Key? key}) : super(key: key); + + @override + __LogActionInnerState createState() => __LogActionInnerState(); +} + +class __LogActionInnerState extends State<_LogActionInner> { + VoidCallback? _listener; + + @override + void initState() { + super.initState(); + + _listener ??= () { + setState(() {}); + }; + + logSink.addListener(_listener!); + } + + @override + void dispose() { + if (_listener != null) { + logSink.removeListener(_listener!); + _listener = null; + } + super.dispose(); + } + + @override + Widget build(BuildContext context) { + return Container( + child: Text( + logSink.output(), + style: TextStyle(fontSize: 15, color: Colors.white), + )); + } +} + +class LogSink extends ChangeNotifier { + final StringBuffer stringBuffer = StringBuffer(); + void log(String log) { + stringBuffer.writeln(log); + notifyListeners(); + } + + String output() { + return stringBuffer.toString(); + } + + void clear() { + stringBuffer.clear(); + notifyListeners(); + } +} + +final LogSink logSink = LogSink(); diff --git a/example/lib/main.dart b/example/lib/main.dart index 9ff726aa4..d2ebe5226 100644 --- a/example/lib/main.dart +++ b/example/lib/main.dart @@ -3,16 +3,22 @@ import 'package:flutter/material.dart'; import 'examples/advanced/index.dart'; import 'examples/basic/index.dart'; import 'config/agora.config.dart' as config; +import 'examples/log_sink.dart'; void main() => runApp(MyApp()); /// This widget is the root of your application. -class MyApp extends StatelessWidget { +class MyApp extends StatefulWidget { + @override + State createState() => _MyAppState(); +} + +class _MyAppState extends State { final _DATA = [...Basic, ...Advanced]; bool _isConfigInvalid() { return config.appId == '' || - config.token == '' || + config.token == '' || config.channelId == ''; } @@ -49,6 +55,7 @@ class MyApp extends StatelessWidget { appBar: AppBar( title: Text( _DATA[index]['name'] as String), + actions: [LogActionWidget()], ), body: _DATA[index]['widget'] as Widget?, diff --git a/example/linux/flutter/CMakeLists.txt b/example/linux/flutter/CMakeLists.txt index 4f48a7ced..a1da1b9e5 100644 --- a/example/linux/flutter/CMakeLists.txt +++ b/example/linux/flutter/CMakeLists.txt @@ -25,6 +25,7 @@ pkg_check_modules(GTK REQUIRED IMPORTED_TARGET gtk+-3.0) pkg_check_modules(GLIB REQUIRED IMPORTED_TARGET glib-2.0) pkg_check_modules(GIO REQUIRED IMPORTED_TARGET gio-2.0) pkg_check_modules(BLKID REQUIRED IMPORTED_TARGET blkid) +pkg_check_modules(LZMA REQUIRED IMPORTED_TARGET liblzma) set(FLUTTER_LIBRARY "${EPHEMERAL_DIR}/libflutter_linux_gtk.so") @@ -67,6 +68,7 @@ target_link_libraries(flutter INTERFACE PkgConfig::GLIB PkgConfig::GIO PkgConfig::BLKID + PkgConfig::LZMA ) add_dependencies(flutter flutter_assemble) @@ -81,6 +83,7 @@ add_custom_command( ${FLUTTER_TOOL_ENVIRONMENT} "${FLUTTER_ROOT}/packages/flutter_tools/bin/tool_backend.sh" linux-x64 ${CMAKE_BUILD_TYPE} + VERBATIM ) add_custom_target(flutter_assemble DEPENDS "${FLUTTER_LIBRARY}" diff --git a/example/macos/Flutter/Flutter-Debug.xcconfig b/example/macos/Flutter/Flutter-Debug.xcconfig index 785633d3a..4b81f9b2d 100644 --- a/example/macos/Flutter/Flutter-Debug.xcconfig +++ b/example/macos/Flutter/Flutter-Debug.xcconfig @@ -1,2 +1,2 @@ -#include "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig" +#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig" #include "ephemeral/Flutter-Generated.xcconfig" diff --git a/example/macos/Flutter/Flutter-Release.xcconfig b/example/macos/Flutter/Flutter-Release.xcconfig index 5fba960c3..5caa9d157 100644 --- a/example/macos/Flutter/Flutter-Release.xcconfig +++ b/example/macos/Flutter/Flutter-Release.xcconfig @@ -1,2 +1,2 @@ -#include "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig" +#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig" #include "ephemeral/Flutter-Generated.xcconfig" diff --git a/example/macos/Flutter/GeneratedPluginRegistrant.swift b/example/macos/Flutter/GeneratedPluginRegistrant.swift index cccf817a5..aaa660f41 100644 --- a/example/macos/Flutter/GeneratedPluginRegistrant.swift +++ b/example/macos/Flutter/GeneratedPluginRegistrant.swift @@ -5,6 +5,8 @@ import FlutterMacOS import Foundation +import agora_rtc_engine func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) { + AgoraRtcEnginePlugin.register(with: registry.registrar(forPlugin: "AgoraRtcEnginePlugin")) } diff --git a/example/macos/Podfile b/example/macos/Podfile index dade8dfad..dcce224da 100644 --- a/example/macos/Podfile +++ b/example/macos/Podfile @@ -31,6 +31,8 @@ target 'Runner' do use_modular_headers! flutter_install_all_macos_pods File.dirname(File.realpath(__FILE__)) + + # pod 'AgoraRtcWrapper', :path => File.join(File.join('Flutter', 'ephemeral', '.symlinks'), 'plugins', 'agora_rtc_engine', 'macos') end post_install do |installer| diff --git a/example/macos/Runner.xcodeproj/project.pbxproj b/example/macos/Runner.xcodeproj/project.pbxproj index 477417f70..cb843717b 100644 --- a/example/macos/Runner.xcodeproj/project.pbxproj +++ b/example/macos/Runner.xcodeproj/project.pbxproj @@ -21,16 +21,13 @@ /* End PBXAggregateTarget section */ /* Begin PBXBuildFile section */ - 060CCBF305C4A6C9CCED5048 /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 36E44D2595C46B91D0004C54 /* Pods_Runner.framework */; }; 335BBD1B22A9A15E00E9071D /* GeneratedPluginRegistrant.swift in Sources */ = {isa = PBXBuildFile; fileRef = 335BBD1A22A9A15E00E9071D /* GeneratedPluginRegistrant.swift */; }; 33CC10F12044A3C60003C045 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 33CC10F02044A3C60003C045 /* AppDelegate.swift */; }; 33CC10F32044A3C60003C045 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 33CC10F22044A3C60003C045 /* Assets.xcassets */; }; 33CC10F62044A3C60003C045 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = 33CC10F42044A3C60003C045 /* MainMenu.xib */; }; 33CC11132044BFA00003C045 /* MainFlutterWindow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 33CC11122044BFA00003C045 /* MainFlutterWindow.swift */; }; - 33D1A10422148B71006C7A3E /* FlutterMacOS.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 33D1A10322148B71006C7A3E /* FlutterMacOS.framework */; }; - 33D1A10522148B93006C7A3E /* FlutterMacOS.framework in Bundle Framework */ = {isa = PBXBuildFile; fileRef = 33D1A10322148B71006C7A3E /* FlutterMacOS.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; - D73912F022F37F9E000D13A0 /* App.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D73912EF22F37F9E000D13A0 /* App.framework */; }; - D73912F222F3801D000D13A0 /* App.framework in Bundle Framework */ = {isa = PBXBuildFile; fileRef = D73912EF22F37F9E000D13A0 /* App.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; + 71A12612276C43D600AD2013 /* src in Resources */ = {isa = PBXBuildFile; fileRef = 71A12611276C43D600AD2013 /* src */; }; + E054FA7B384FB404A91AF760 /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C343761438CBBF9C13B4642E /* Pods_Runner.framework */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -50,8 +47,6 @@ dstPath = ""; dstSubfolderSpec = 10; files = ( - D73912F222F3801D000D13A0 /* App.framework in Bundle Framework */, - 33D1A10522148B93006C7A3E /* FlutterMacOS.framework in Bundle Framework */, ); name = "Bundle Framework"; runOnlyForDeploymentPostprocessing = 0; @@ -70,17 +65,17 @@ 33CEB47222A05771004F2AC0 /* Flutter-Debug.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = "Flutter-Debug.xcconfig"; sourceTree = ""; }; 33CEB47422A05771004F2AC0 /* Flutter-Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = "Flutter-Release.xcconfig"; sourceTree = ""; }; 33CEB47722A0578A004F2AC0 /* Flutter-Generated.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = "Flutter-Generated.xcconfig"; path = "ephemeral/Flutter-Generated.xcconfig"; sourceTree = ""; }; - 33D1A10322148B71006C7A3E /* FlutterMacOS.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = FlutterMacOS.framework; path = Flutter/ephemeral/FlutterMacOS.framework; sourceTree = SOURCE_ROOT; }; 33E51913231747F40026EE4D /* DebugProfile.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = DebugProfile.entitlements; sourceTree = ""; }; 33E51914231749380026EE4D /* Release.entitlements */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.entitlements; path = Release.entitlements; sourceTree = ""; }; 33E5194F232828860026EE4D /* AppInfo.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = AppInfo.xcconfig; sourceTree = ""; }; - 36E44D2595C46B91D0004C54 /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 71A12611276C43D600AD2013 /* src */ = {isa = PBXFileReference; lastKnownFileType = folder; name = src; path = ../../../integration_test_app/iris_integration_test/src; sourceTree = ""; }; 749D5FA7C6F6408AE21D6A6E /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = ""; }; 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Release.xcconfig; sourceTree = ""; }; 8B8419211BE18D371F9514ED /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = ""; }; 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = Debug.xcconfig; sourceTree = ""; }; + C343761438CBBF9C13B4642E /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; }; CF9662756C1A43FCBE8873F6 /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = ""; }; - D73912EF22F37F9E000D13A0 /* App.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = App.framework; path = Flutter/ephemeral/App.framework; sourceTree = SOURCE_ROOT; }; + F5ECE95525F8A3D4007A6F91 /* agora_rtc_engine_exampleDebug.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = agora_rtc_engine_exampleDebug.entitlements; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -88,9 +83,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - D73912F022F37F9E000D13A0 /* App.framework in Frameworks */, - 33D1A10422148B71006C7A3E /* FlutterMacOS.framework in Frameworks */, - 060CCBF305C4A6C9CCED5048 /* Pods_Runner.framework in Frameworks */, + E054FA7B384FB404A91AF760 /* Pods_Runner.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -145,8 +138,6 @@ 33CEB47222A05771004F2AC0 /* Flutter-Debug.xcconfig */, 33CEB47422A05771004F2AC0 /* Flutter-Release.xcconfig */, 33CEB47722A0578A004F2AC0 /* Flutter-Generated.xcconfig */, - D73912EF22F37F9E000D13A0 /* App.framework */, - 33D1A10322148B71006C7A3E /* FlutterMacOS.framework */, ); path = Flutter; sourceTree = ""; @@ -154,6 +145,8 @@ 33FAB671232836740065AC1E /* Runner */ = { isa = PBXGroup; children = ( + 71A12611276C43D600AD2013 /* src */, + F5ECE95525F8A3D4007A6F91 /* agora_rtc_engine_exampleDebug.entitlements */, 33CC10F02044A3C60003C045 /* AppDelegate.swift */, 33CC11122044BFA00003C045 /* MainFlutterWindow.swift */, 33E51913231747F40026EE4D /* DebugProfile.entitlements */, @@ -171,14 +164,13 @@ 8B8419211BE18D371F9514ED /* Pods-Runner.release.xcconfig */, CF9662756C1A43FCBE8873F6 /* Pods-Runner.profile.xcconfig */, ); - name = Pods; path = Pods; sourceTree = ""; }; D73912EC22F37F3D000D13A0 /* Frameworks */ = { isa = PBXGroup; children = ( - 36E44D2595C46B91D0004C54 /* Pods_Runner.framework */, + C343761438CBBF9C13B4642E /* Pods_Runner.framework */, ); name = Frameworks; sourceTree = ""; @@ -221,7 +213,6 @@ 33CC10EC2044A3C60003C045 = { CreatedOnToolsVersion = 9.2; LastSwiftMigration = 1100; - ProvisioningStyle = Automatic; SystemCapabilities = { com.apple.Sandbox = { enabled = 1; @@ -258,6 +249,7 @@ isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( + 71A12612276C43D600AD2013 /* src in Resources */, 33CC10F32044A3C60003C045 /* Assets.xcassets in Resources */, 33CC10F62044A3C60003C045 /* MainMenu.xib in Resources */, ); @@ -281,7 +273,7 @@ ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "echo \"$PRODUCT_NAME.app\" > \"$PROJECT_DIR\"/Flutter/ephemeral/.app_filename\n"; + shellScript = "echo \"$PRODUCT_NAME.app\" > \"$PROJECT_DIR\"/Flutter/ephemeral/.app_filename && \"$FLUTTER_ROOT\"/packages/flutter_tools/bin/macos_assemble.sh embed\n"; }; 33CC111E2044C6BF0003C045 /* ShellScript */ = { isa = PBXShellScriptBuildPhase; @@ -309,9 +301,38 @@ files = ( ); inputPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh", + "${PODS_ROOT}/AgoraIrisRTC_macOS/AgoraAIDenoiseExtension.framework", + "${PODS_ROOT}/AgoraIrisRTC_macOS/AgoraCIExtension.framework", + "${PODS_ROOT}/AgoraIrisRTC_macOS/AgoraCore.framework", + "${PODS_ROOT}/AgoraIrisRTC_macOS/AgoraDav1dExtension.framework", + "${PODS_ROOT}/AgoraIrisRTC_macOS/AgoraFDExtension.framework", + "${PODS_ROOT}/AgoraIrisRTC_macOS/AgoraJNDExtension.framework", + "${PODS_ROOT}/AgoraIrisRTC_macOS/AgoraRtcKit.framework", + "${PODS_ROOT}/AgoraIrisRTC_macOS/AgoraRtcWrapper.framework", + "${PODS_ROOT}/AgoraIrisRTC_macOS/AgoraSoundTouch.framework", + "${PODS_ROOT}/AgoraIrisRTC_macOS/AgoraVideoSegmentationExtension.framework", + "${PODS_ROOT}/AgoraIrisRTC_macOS/Agorafdkaac.framework", + "${PODS_ROOT}/AgoraIrisRTC_macOS/Agoraffmpeg.framework", + "${PODS_ROOT}/AgoraIrisRTC_macOS/av1.framework", + "${BUILT_PRODUCTS_DIR}/agora_rtc_engine/agora_rtc_engine.framework", ); name = "[CP] Embed Pods Frameworks"; outputPaths = ( + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/AgoraAIDenoiseExtension.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/AgoraCIExtension.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/AgoraCore.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/AgoraDav1dExtension.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/AgoraFDExtension.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/AgoraJNDExtension.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/AgoraRtcKit.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/AgoraRtcWrapper.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/AgoraSoundTouch.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/AgoraVideoSegmentationExtension.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Agorafdkaac.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Agoraffmpeg.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/av1.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/agora_rtc_engine.framework", ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; @@ -429,8 +450,10 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_ENABLE_MODULES = YES; CODE_SIGN_ENTITLEMENTS = Runner/DebugProfile.entitlements; + CODE_SIGN_IDENTITY = "-"; CODE_SIGN_STYLE = Automatic; COMBINE_HIDPI_IMAGES = YES; + DEVELOPMENT_TEAM = ""; FRAMEWORK_SEARCH_PATHS = ( "$(inherited)", "$(PROJECT_DIR)/Flutter/ephemeral", @@ -558,9 +581,12 @@ buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_ENABLE_MODULES = YES; - CODE_SIGN_ENTITLEMENTS = Runner/DebugProfile.entitlements; + CODE_SIGN_ENTITLEMENTS = Runner/agora_rtc_engine_exampleDebug.entitlements; + CODE_SIGN_IDENTITY = "-"; CODE_SIGN_STYLE = Automatic; COMBINE_HIDPI_IMAGES = YES; + DEVELOPMENT_TEAM = ""; + ENABLE_HARDENED_RUNTIME = NO; FRAMEWORK_SEARCH_PATHS = ( "$(inherited)", "$(PROJECT_DIR)/Flutter/ephemeral", @@ -583,8 +609,10 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_ENABLE_MODULES = YES; CODE_SIGN_ENTITLEMENTS = Runner/Release.entitlements; + CODE_SIGN_IDENTITY = "-"; CODE_SIGN_STYLE = Automatic; COMBINE_HIDPI_IMAGES = YES; + DEVELOPMENT_TEAM = ""; FRAMEWORK_SEARCH_PATHS = ( "$(inherited)", "$(PROJECT_DIR)/Flutter/ephemeral", diff --git a/example/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/example/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme index 7d0688701..53aba86a7 100644 --- a/example/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme +++ b/example/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme @@ -27,18 +27,6 @@ selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB" selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB" shouldUseLaunchSchemeArgsEnv = "YES"> - - - - - - + + + + PreviewsEnabled + + + diff --git a/example/macos/Runner/Configs/AppInfo.xcconfig b/example/macos/Runner/Configs/AppInfo.xcconfig index b57b23e39..04f9859b6 100644 --- a/example/macos/Runner/Configs/AppInfo.xcconfig +++ b/example/macos/Runner/Configs/AppInfo.xcconfig @@ -11,4 +11,4 @@ PRODUCT_NAME = agora_rtc_engine_example PRODUCT_BUNDLE_IDENTIFIER = io.agora.agoraRtcEngineExample // The copyright displayed in application information -PRODUCT_COPYRIGHT = Copyright © 2020 io.agora. All rights reserved. +PRODUCT_COPYRIGHT = Copyright © 2021 io.agora. All rights reserved. diff --git a/example/macos/Runner/DebugProfile.entitlements b/example/macos/Runner/DebugProfile.entitlements index dddb8a30c..55096fe72 100644 --- a/example/macos/Runner/DebugProfile.entitlements +++ b/example/macos/Runner/DebugProfile.entitlements @@ -4,8 +4,18 @@ com.apple.security.app-sandbox + com.apple.security.application-groups + + io.agora + com.apple.security.cs.allow-jit + com.apple.security.device.audio-input + + com.apple.security.device.camera + + com.apple.security.network.client + com.apple.security.network.server diff --git a/example/macos/Runner/Info.plist b/example/macos/Runner/Info.plist index 4789daa6a..15b44950a 100644 --- a/example/macos/Runner/Info.plist +++ b/example/macos/Runner/Info.plist @@ -22,10 +22,14 @@ $(FLUTTER_BUILD_NUMBER) LSMinimumSystemVersion $(MACOSX_DEPLOYMENT_TARGET) + NSCameraUsageDescription + CAMERA NSHumanReadableCopyright $(PRODUCT_COPYRIGHT) NSMainNibFile MainMenu + NSMicrophoneUsageDescription + MIC NSPrincipalClass NSApplication diff --git a/example/macos/Runner/Release.entitlements b/example/macos/Runner/Release.entitlements index 852fa1a47..c131bb503 100644 --- a/example/macos/Runner/Release.entitlements +++ b/example/macos/Runner/Release.entitlements @@ -4,5 +4,17 @@ com.apple.security.app-sandbox + com.apple.security.application-groups + + io.agora + + com.apple.security.device.audio-input + + com.apple.security.device.camera + + com.apple.security.network.client + + com.apple.security.network.server + diff --git a/example/macos/Runner/agora_rtc_engine_exampleDebug.entitlements b/example/macos/Runner/agora_rtc_engine_exampleDebug.entitlements new file mode 100644 index 000000000..e69de29bb diff --git a/example/lib/examples/advanced/custom_capture_audio/custom_capture_audio_api.dart b/example/pigeons/custom_capture_audio/custom_capture_audio_api.dart similarity index 100% rename from example/lib/examples/advanced/custom_capture_audio/custom_capture_audio_api.dart rename to example/pigeons/custom_capture_audio/custom_capture_audio_api.dart diff --git a/example/pubspec.yaml b/example/pubspec.yaml index 4df9e79c1..ae3407b94 100644 --- a/example/pubspec.yaml +++ b/example/pubspec.yaml @@ -24,7 +24,7 @@ dependencies: # Use with the CupertinoIcons class for iOS style icons. cupertino_icons: ^1.0.2 - permission_handler: ^6.0.1 + permission_handler: ^8.3.0 dev_dependencies: integration_test: @@ -52,6 +52,7 @@ flutter: # - images/a_dot_ham.jpeg assets: - assets/Sound_Horizon.mp3 + - assets/audio_mixing/Agora.io-Interactions.mp3 # An image asset can refer to one or more resolution-specific "variants", see # https://flutter.dev/assets-and-images/#resolution-aware. diff --git a/example/web/AgoraRtcWrapper.bundle.js b/example/web/AgoraRtcWrapper.bundle.js new file mode 100644 index 000000000..fcef81c9d --- /dev/null +++ b/example/web/AgoraRtcWrapper.bundle.js @@ -0,0 +1,2 @@ +/*! For license information please see AgoraRtcWrapper.bundle.js.LICENSE.txt */ +!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t():"function"==typeof define&&define.amd?define([],t):"object"==typeof exports?exports.IrisRtcEngine=t():e.IrisRtcEngine=t()}(self,(function(){return(()=>{"use strict";var e={424:function(e,t,i){e.exports=function(){function e(e,t,i){return e(i={path:t,exports:{},require:function(e,t){throw Error("Dynamic requires are not currently supported by @rollup/plugin-commonjs")}},i.exports),i.exports}function t(e,t,i){return(e=e.match(t))&&e.length>=i&&io(e[i],10)}function n(e,t,i){if(e.RTCPeerConnection){var n=(e=e.RTCPeerConnection.prototype).addEventListener;e.addEventListener=function(e,r){if(e!==t)return n.apply(this,arguments);let a=e=>{(e=i(e))&&r(e)};return this._eventMap=this._eventMap||{},this._eventMap[r]=a,n.apply(this,[e,a])};var r=e.removeEventListener;e.removeEventListener=function(e,i){if(e!==t||!this._eventMap||!this._eventMap[i])return r.apply(this,arguments);let n=this._eventMap[i];return delete this._eventMap[i],r.apply(this,[e,n])},Ja(e,"on"+t,{get(){return this["_on"+t]},set(e){this["_on"+t]&&(this.removeEventListener(t,this["_on"+t]),delete this["_on"+t]),e&&this.addEventListener(t,this["_on"+t]=e)},enumerable:!0,configurable:!0})}}function r(e){return"boolean"!=typeof e?Error("Argument type: "+typeof e+". Please use a boolean."):(no=e,e?"adapter.js logging disabled":"adapter.js logging enabled")}function a(e){return"boolean"!=typeof e?Error("Argument type: "+typeof e+". Please use a boolean."):(ro=!e,"adapter.js deprecation warnings "+(e?"disabled":"enabled"))}function o(){"object"!=typeof window||no||"undefined"!=typeof console&&"function"==typeof console.log&&console.log.apply(console,arguments)}function s(e,t){ro&&console.warn(e+" is deprecated, please use "+t+" instead.")}function c(e){let{navigator:i}=e,n={browser:null,version:null};if(void 0===e||!e.navigator)return n.browser="Not a browser.",n;if(i.mozGetUserMedia)n.browser="firefox",n.version=t(i.userAgent,/Firefox\/(\d+)\./,1);else if(i.webkitGetUserMedia||!1===e.isSecureContext&&e.webkitRTCPeerConnection&&!e.RTCIceGatherer)n.browser="chrome",n.version=t(i.userAgent,/Chrom(e|ium)\/(\d+)\./,2);else if(i.mediaDevices&&i.userAgent.match(/Edge\/(\d+).(\d+)$/))n.browser="edge",n.version=t(i.userAgent,/Edge\/(\d+).(\d+)$/,2);else{if(!e.RTCPeerConnection||!i.userAgent.match(/AppleWebKit\/(\d+)\./))return n.browser="Not a supported browser.",n;n.browser="safari",n.version=t(i.userAgent,/AppleWebKit\/(\d+)\./,1),n.supportsUnifiedPlan=e.RTCRtpTransceiver&&"currentDirection"in e.RTCRtpTransceiver.prototype}return n}function _(e){var t;return"[object Object]"===Object.prototype.toString.call(e)?Ka(t=xa(e)).call(t,(function(t,i){var n="[object Object]"===Object.prototype.toString.call(e[i]);let r=n?_(e[i]):e[i];return n=n&&!xa(r).length,void 0===r||n?t:Ba(t,{[i]:r})}),{}):e}function E(e,t,i){let n=i?"outbound-rtp":"inbound-rtp",r=new pa;if(null===t)return r;let a=[];return wa(e).call(e,(e=>{"track"===e.type&&e.trackIdentifier===t.id&&a.push(e)})),wa(a).call(a,(t=>{wa(e).call(e,(i=>{i.type===n&&i.trackId===t.id&&function e(t,i,n){var r;i&&!n.has(i.id)&&(n.set(i.id,i),wa(r=xa(i)).call(r,(r=>{if(La(r).call(r,"Id"))e(t,t.get(i[r]),n);else if(La(r).call(r,"Ids")){var a;wa(a=i[r]).call(a,(i=>{e(t,t.get(i),n)}))}})))}(e,i,r)}))})),r}function d(e){let t=e&&e.navigator;if(t.mediaDevices){var i=c(e),n=function(e){var t;if("object"!=typeof e||e.mandatory||e.optional)return e;const i={};var n;return wa(t=xa(e)).call(t,(t=>{if("require"!==t&&"advanced"!==t&&"mediaSource"!==t){var n="object"==typeof e[t]?e[t]:{ideal:e[t]};void 0!==n.exact&&"number"==typeof n.exact&&(n.min=n.max=n.exact);var r,a=function(e,t){return e?e+t.charAt(0).toUpperCase()+dc(t).call(t,1):"deviceId"===t?"sourceId":t};if(void 0!==n.ideal){i.optional=i.optional||[];let e={};"number"==typeof n.ideal?(e[a("min",t)]=n.ideal,i.optional.push(e),e={},e[a("max",t)]=n.ideal,i.optional.push(e)):(e[a("",t)]=n.ideal,i.optional.push(e))}void 0!==n.exact&&"number"!=typeof n.exact?(i.mandatory=i.mandatory||{},i.mandatory[a("",t)]=n.exact):wa(r=["min","max"]).call(r,(e=>{void 0!==n[e]&&(i.mandatory=i.mandatory||{},i.mandatory[a(e,t)]=n[e])}))}})),e.advanced&&(i.optional=No(n=i.optional||[]).call(n,e.advanced)),i},r=function(e,r){if(61<=i.version)return r(e);if((e=JSON.parse(En(e)))&&"object"==typeof e.audio){var a=function(e,t,i){t in e&&!(i in e)&&(e[i]=e[t],delete e[t])};a((e=JSON.parse(En(e))).audio,"autoGainControl","googAutoGainControl"),a(e.audio,"noiseSuppression","googNoiseSuppression"),e.audio=n(e.audio)}if(e&&"object"==typeof e.video){let o=e.video.facingMode;if(o=o&&("object"==typeof o?o:{ideal:o}),a=66>i.version,!(!o||"user"!==o.exact&&"environment"!==o.exact&&"user"!==o.ideal&&"environment"!==o.ideal||t.mediaDevices.getSupportedConstraints&&t.mediaDevices.getSupportedConstraints().facingMode&&!a)){let i;if(delete e.video.facingMode,"environment"===o.exact||"environment"===o.ideal?i=["back","rear"]:"user"!==o.exact&&"user"!==o.ideal||(i=["front"]),i)return t.mediaDevices.enumerateDevices().then((t=>{t=vo(t).call(t,(e=>"videoinput"===e.kind));let a=Rc(t).call(t,(e=>Dc(i).call(i,(t=>{var i;return Cc(i=e.label.toLowerCase()).call(i,t)}))));return!a&&t.length&&Cc(i).call(i,"back")&&(a=t[t.length-1]),a&&(e.video.deviceId=o.exact?{exact:a.deviceId}:{ideal:a.deviceId}),e.video=n(e.video),Lc("chrome: "+En(e)),r(e)}))}e.video=n(e.video)}return Lc("chrome: "+En(e)),r(e)},a=function(e){return 64<=i.version?e:{name:{PermissionDeniedError:"NotAllowedError",PermissionDismissedError:"NotAllowedError",InvalidStateError:"NotAllowedError",DevicesNotFoundError:"NotFoundError",ConstraintNotSatisfiedError:"OverconstrainedError",TrackStartError:"NotReadableError",MediaDeviceFailedDueToShutdown:"NotAllowedError",MediaDeviceKillSwitchOn:"NotAllowedError",TabCaptureError:"AbortError",ScreenCaptureError:"AbortError",DeviceCaptureError:"AbortError"}[e.name]||e.name,message:e.message,constraint:e.constraint||e.constraintName,toString(){return this.name+(this.message&&": ")+this.message}}};if(e=function(e,i,n){r(e,(e=>{t.webkitGetUserMedia(e,i,(e=>{n&&n(a(e))}))}))},t.getUserMedia=Sc(e).call(e,t),t.mediaDevices.getUserMedia){var o;let e=Sc(o=t.mediaDevices.getUserMedia).call(o,t.mediaDevices);t.mediaDevices.getUserMedia=function(t){return r(t,(t=>e(t).then((e=>{var i;if(t.audio&&!e.getAudioTracks().length||t.video&&!e.getVideoTracks().length)throw wa(i=e.getTracks()).call(i,(e=>{e.stop()})),new DOMException("","NotFoundError");return e}),(e=>js.reject(a(e))))))}}}}function l(e){e.MediaStream=e.MediaStream||e.webkitMediaStream}function u(e){if("object"!=typeof e||!e.RTCPeerConnection||"ontrack"in e.RTCPeerConnection.prototype)n(e,"track",(e=>(e.transceiver||Ja(e,"transceiver",{value:{receiver:e.receiver}}),e)));else{Ja(e.RTCPeerConnection.prototype,"ontrack",{get(){return this._ontrack},set(e){this._ontrack&&this.removeEventListener("track",this._ontrack),this.addEventListener("track",this._ontrack=e)},enumerable:!0,configurable:!0});let t=e.RTCPeerConnection.prototype.setRemoteDescription;e.RTCPeerConnection.prototype.setRemoteDescription=function(){return this._ontrackpoly||(this._ontrackpoly=t=>{var i;t.stream.addEventListener("addtrack",(i=>{let n;var r;n=e.RTCPeerConnection.prototype.getReceivers?Rc(r=this.getReceivers()).call(r,(e=>e.track&&e.track.id===i.track.id)):{track:i.track},(r=new Event("track")).track=i.track,r.receiver=n,r.transceiver={receiver:n},r.streams=[t.stream],this.dispatchEvent(r)})),wa(i=t.stream.getTracks()).call(i,(i=>{let n;var r;n=e.RTCPeerConnection.prototype.getReceivers?Rc(r=this.getReceivers()).call(r,(e=>e.track&&e.track.id===i.id)):{track:i},(r=new Event("track")).track=i,r.receiver=n,r.transceiver={receiver:n},r.streams=[t.stream],this.dispatchEvent(r)}))},this.addEventListener("addstream",this._ontrackpoly)),t.apply(this,arguments)}}}function h(e){if("object"==typeof e&&e.RTCPeerConnection&&!("getSenders"in e.RTCPeerConnection.prototype)&&"createDTMFSender"in e.RTCPeerConnection.prototype){let t=function(e,t){return{track:t,get dtmf(){return void 0===this._dtmf&&("audio"===t.kind?this._dtmf=e.createDTMFSender(t):this._dtmf=null),this._dtmf},_pc:e}};if(!e.RTCPeerConnection.prototype.getSenders){e.RTCPeerConnection.prototype.getSenders=function(){var e;return this._senders=this._senders||[],dc(e=this._senders).call(e)};let i=e.RTCPeerConnection.prototype.addTrack;e.RTCPeerConnection.prototype.addTrack=function(e,n){let r=i.apply(this,arguments);return r||(r=t(this,e),this._senders.push(r)),r};let n=e.RTCPeerConnection.prototype.removeTrack;e.RTCPeerConnection.prototype.removeTrack=function(e){var t;n.apply(this,arguments);let i=ac(t=this._senders).call(t,e);var r;-1!==i&&$s(r=this._senders).call(r,i,1)}}let i=e.RTCPeerConnection.prototype.addStream;e.RTCPeerConnection.prototype.addStream=function(e){var n;this._senders=this._senders||[],i.apply(this,[e]),wa(n=e.getTracks()).call(n,(e=>{this._senders.push(t(this,e))}))};let n=e.RTCPeerConnection.prototype.removeStream;e.RTCPeerConnection.prototype.removeStream=function(e){var t;this._senders=this._senders||[],n.apply(this,[e]),wa(t=e.getTracks()).call(t,(e=>{var t;let i=Rc(t=this._senders).call(t,(t=>t.track===e));var n,r;i&&$s(n=this._senders).call(n,ac(r=this._senders).call(r,i),1)}))}}else if("object"==typeof e&&e.RTCPeerConnection&&"getSenders"in e.RTCPeerConnection.prototype&&"createDTMFSender"in e.RTCPeerConnection.prototype&&e.RTCRtpSender&&!("dtmf"in e.RTCRtpSender.prototype)){let t=e.RTCPeerConnection.prototype.getSenders;e.RTCPeerConnection.prototype.getSenders=function(){let e=t.apply(this,[]);return wa(e).call(e,(e=>e._pc=this)),e},Ja(e.RTCRtpSender.prototype,"dtmf",{get(){return void 0===this._dtmf&&("audio"===this.track.kind?this._dtmf=this._pc.createDTMFSender(this.track):this._dtmf=null),this._dtmf}})}}function R(e){if(e.RTCPeerConnection){var t=e.RTCPeerConnection.prototype.getStats;e.RTCPeerConnection.prototype.getStats=function(){let[e,i,n]=arguments;if(0{var i;const n={id:e.id,timestamp:e.timestamp,type:{localcandidate:"local-candidate",remotecandidate:"remote-candidate"}[e.type]||e.type};wa(i=e.names()).call(i,(t=>{n[t]=e.stat(t)})),t[n.id]=n})),t},a=function(e){var t;return new pa(Js(t=xa(e)).call(t,(t=>[t,e[t]])))};return 2<=arguments.length?t.apply(this,[function(e){i(a(r(e)))},e]):new js(((e,i)=>{t.apply(this,[function(t){e(a(r(t)))},i])})).then(i,n)}}}function T(e){if("object"==typeof e&&e.RTCPeerConnection&&e.RTCRtpSender&&e.RTCRtpReceiver){if(!("getStats"in e.RTCRtpSender.prototype)){let t=e.RTCPeerConnection.prototype.getSenders;t&&(e.RTCPeerConnection.prototype.getSenders=function(){let e=t.apply(this,[]);return wa(e).call(e,(e=>e._pc=this)),e});let i=e.RTCPeerConnection.prototype.addTrack;i&&(e.RTCPeerConnection.prototype.addTrack=function(){let e=i.apply(this,arguments);return e._pc=this,e}),e.RTCRtpSender.prototype.getStats=function(){let e=this;return this._pc.getStats().then((t=>E(t,e.track,!0)))}}if(!("getStats"in e.RTCRtpReceiver.prototype)){let t=e.RTCPeerConnection.prototype.getReceivers;t&&(e.RTCPeerConnection.prototype.getReceivers=function(){let e=t.apply(this,[]);return wa(e).call(e,(e=>e._pc=this)),e}),n(e,"track",(e=>(e.receiver._pc=e.srcElement,e))),e.RTCRtpReceiver.prototype.getStats=function(){let e=this;return this._pc.getStats().then((t=>E(t,e.track,!1)))}}if("getStats"in e.RTCRtpSender.prototype&&"getStats"in e.RTCRtpReceiver.prototype){var t=e.RTCPeerConnection.prototype.getStats;e.RTCPeerConnection.prototype.getStats=function(){if(0{t.track===a&&(e?r=!0:e=t)})),wa(n=this.getReceivers()).call(n,(e=>(e.track===a&&(t?r=!0:t=e),e.track===a))),r||e&&t?js.reject(new DOMException("There are more than one sender or receiver for the track.","InvalidAccessError")):e?e.getStats():t?t.getStats():js.reject(new DOMException("There is no sender or receiver for the track.","InvalidAccessError"))}return t.apply(this,arguments)}}}}function A(e){e.RTCPeerConnection.prototype.getLocalStreams=function(){var e;return this._shimmedLocalStreams=this._shimmedLocalStreams||{},Js(e=xa(this._shimmedLocalStreams)).call(e,(e=>this._shimmedLocalStreams[e][0]))};let t=e.RTCPeerConnection.prototype.addTrack;e.RTCPeerConnection.prototype.addTrack=function(e,i){var n;if(!i)return t.apply(this,arguments);this._shimmedLocalStreams=this._shimmedLocalStreams||{};let r=t.apply(this,arguments);return this._shimmedLocalStreams[i.id]?-1===ac(n=this._shimmedLocalStreams[i.id]).call(n,r)&&this._shimmedLocalStreams[i.id].push(r):this._shimmedLocalStreams[i.id]=[i,r],r};let i=e.RTCPeerConnection.prototype.addStream;e.RTCPeerConnection.prototype.addStream=function(e){var t,n,r;this._shimmedLocalStreams=this._shimmedLocalStreams||{},wa(t=e.getTracks()).call(t,(e=>{var t;if(Rc(t=this.getSenders()).call(t,(t=>t.track===e)))throw new DOMException("Track already exists.","InvalidAccessError")}));let a=this.getSenders();i.apply(this,arguments),t=vo(n=this.getSenders()).call(n,(e=>-1===ac(a).call(a,e))),this._shimmedLocalStreams[e.id]=No(r=[e]).call(r,t)};let n=e.RTCPeerConnection.prototype.removeStream;e.RTCPeerConnection.prototype.removeStream=function(e){return this._shimmedLocalStreams=this._shimmedLocalStreams||{},delete this._shimmedLocalStreams[e.id],n.apply(this,arguments)};let r=e.RTCPeerConnection.prototype.removeTrack;e.RTCPeerConnection.prototype.removeTrack=function(e){var t;return this._shimmedLocalStreams=this._shimmedLocalStreams||{},e&&wa(t=xa(this._shimmedLocalStreams)).call(t,(t=>{var i;let n=ac(i=this._shimmedLocalStreams[t]).call(i,e);var r;-1!==n&&$s(r=this._shimmedLocalStreams[t]).call(r,n,1),1===this._shimmedLocalStreams[t].length&&delete this._shimmedLocalStreams[t]})),r.apply(this,arguments)}}function p(e){function t(e,t){var i;let n=t.sdp;return wa(i=xa(e._reverseStreams||[])).call(i,(t=>{t=e._reverseStreams[t],n=n.replace(new RegExp(e._streams[t.id].id,"g"),t.id)})),new RTCSessionDescription({type:t.type,sdp:n})}function i(e,t){var i;let n=t.sdp;return wa(i=xa(e._reverseStreams||[])).call(i,(t=>{t=e._reverseStreams[t],n=n.replace(new RegExp(t.id,"g"),e._streams[t.id].id)})),new RTCSessionDescription({type:t.type,sdp:n})}var n;if(e.RTCPeerConnection){var r=c(e);if(e.RTCPeerConnection.prototype.addTrack&&65<=r.version)return A(e);var a=e.RTCPeerConnection.prototype.getLocalStreams;e.RTCPeerConnection.prototype.getLocalStreams=function(){let e=a.apply(this);return this._reverseStreams=this._reverseStreams||{},Js(e).call(e,(e=>this._reverseStreams[e.id]))};var o=e.RTCPeerConnection.prototype.addStream;e.RTCPeerConnection.prototype.addStream=function(t){var i;this._streams=this._streams||{},this._reverseStreams=this._reverseStreams||{},wa(i=t.getTracks()).call(i,(e=>{var t;if(Rc(t=this.getSenders()).call(t,(t=>t.track===e)))throw new DOMException("Track already exists.","InvalidAccessError")})),this._reverseStreams[t.id]||(i=new e.MediaStream(t.getTracks()),this._streams[t.id]=i,this._reverseStreams[i.id]=t,t=i),o.apply(this,[t])};var s=e.RTCPeerConnection.prototype.removeStream;e.RTCPeerConnection.prototype.removeStream=function(e){this._streams=this._streams||{},this._reverseStreams=this._reverseStreams||{},s.apply(this,[this._streams[e.id]||e]),delete this._reverseStreams[this._streams[e.id]?this._streams[e.id].id:e.id],delete this._streams[e.id]},e.RTCPeerConnection.prototype.addTrack=function(t,i){var n,r,a;if("closed"===this.signalingState)throw new DOMException("The RTCPeerConnection's signalingState is 'closed'.","InvalidStateError");let o=dc([]).call(arguments,1);if(1!==o.length||!Rc(n=o[0].getTracks()).call(n,(e=>e===t)))throw new DOMException("The adapter.js addTrack polyfill only supports a single stream which is associated with the specified track.","NotSupportedError");if(Rc(r=this.getSenders()).call(r,(e=>e.track===t)))throw new DOMException("Track already exists.","InvalidAccessError");return this._streams=this._streams||{},this._reverseStreams=this._reverseStreams||{},(n=this._streams[i.id])?(n.addTrack(t),js.resolve().then((()=>{this.dispatchEvent(new Event("negotiationneeded"))}))):(n=new e.MediaStream([t]),this._streams[i.id]=n,this._reverseStreams[n.id]=i,this.addStream(n)),Rc(a=this.getSenders()).call(a,(e=>e.track===t))},wa(n=["createOffer","createAnswer"]).call(n,(function(i){let n=e.RTCPeerConnection.prototype[i];e.RTCPeerConnection.prototype[i]={[i](){const e=arguments;return arguments.length&&"function"==typeof arguments[0]?n.apply(this,[i=>{i=t(this,i),e[0].apply(null,[i])},t=>{e[1]&&e[1].apply(null,t)},arguments[2]]):n.apply(this,arguments).then((e=>t(this,e)))}}[i]}));var _=e.RTCPeerConnection.prototype.setLocalDescription;e.RTCPeerConnection.prototype.setLocalDescription=function(){return arguments.length&&arguments[0].type?(arguments[0]=i(this,arguments[0]),_.apply(this,arguments)):_.apply(this,arguments)};var E=_o(e.RTCPeerConnection.prototype,"localDescription");Ja(e.RTCPeerConnection.prototype,"localDescription",{get(){let e=E.get.apply(this);return""===e.type?e:t(this,e)}}),e.RTCPeerConnection.prototype.removeTrack=function(e){var t;if("closed"===this.signalingState)throw new DOMException("The RTCPeerConnection's signalingState is 'closed'.","InvalidStateError");if(!e._pc)throw new DOMException("Argument 1 of RTCPeerConnection.removeTrack does not implement interface RTCRtpSender.","TypeError");if(e._pc!==this)throw new DOMException("Sender was not created by this connection.","InvalidAccessError");let i;this._streams=this._streams||{},wa(t=xa(this._streams)).call(t,(t=>{var n;Rc(n=this._streams[t].getTracks()).call(n,(t=>e.track===t))&&(i=this._streams[t])})),i&&(1===i.getTracks().length?this.removeStream(this._reverseStreams[i.id]):i.removeTrack(e.track),this.dispatchEvent(new Event("negotiationneeded")))}}}function I(e){let t=c(e);if(!e.RTCPeerConnection&&e.webkitRTCPeerConnection&&(e.RTCPeerConnection=e.webkitRTCPeerConnection),e.RTCPeerConnection){var i;53>t.version&&wa(i=["setLocalDescription","setRemoteDescription","addIceCandidate"]).call(i,(function(t){let i=e.RTCPeerConnection.prototype[t];e.RTCPeerConnection.prototype[t]={[t](){return arguments[0]=new("addIceCandidate"===t?e.RTCIceCandidate:e.RTCSessionDescription)(arguments[0]),i.apply(this,arguments)}}[t]}));var n=e.RTCPeerConnection.prototype.addIceCandidate;e.RTCPeerConnection.prototype.addIceCandidate=function(){return arguments[0]?78>t.version&&arguments[0]&&""===arguments[0].candidate?js.resolve():n.apply(this,arguments):(arguments[1]&&arguments[1].apply(null),js.resolve())}}}function S(e){n(e,"negotiationneeded",(e=>{if("stable"===e.target.signalingState)return e}))}function O(e,t,i,n,r){return t=Wc.writeRtpDescription(e.kind,t),t+=Wc.writeIceParameters(e.iceGatherer.getLocalParameters()),t+=Wc.writeDtlsParameters(e.dtlsTransport.getLocalParameters(),"offer"===i?"actpass":r||"active"),t+="a=mid:"+e.mid+"\r\n",e.rtpSender&&e.rtpReceiver?t+="a=sendrecv\r\n":e.rtpSender?t+="a=sendonly\r\n":e.rtpReceiver?t+="a=recvonly\r\n":t+="a=inactive\r\n",e.rtpSender&&(i=e.rtpSender._initialTrackId||e.rtpSender.track.id,e.rtpSender._initialTrackId=i,t=t+"a="+(n="msid:"+(n?n.id:"-")+" "+i+"\r\n")+"a=ssrc:"+e.sendEncodingParameters[0].ssrc+" "+n,e.sendEncodingParameters[0].rtx&&(t+="a=ssrc:"+e.sendEncodingParameters[0].rtx.ssrc+" "+n,t+="a=ssrc-group:FID "+e.sendEncodingParameters[0].ssrc+" "+e.sendEncodingParameters[0].rtx.ssrc+"\r\n")),t+="a=ssrc:"+e.sendEncodingParameters[0].ssrc+" cname:"+Wc.localCName+"\r\n",e.rtpSender&&e.sendEncodingParameters[0].rtx&&(t+="a=ssrc:"+e.sendEncodingParameters[0].rtx.ssrc+" cname:"+Wc.localCName+"\r\n"),t}function m(e,t){var i={codecs:[],headerExtensions:[],fecMechanisms:[]},n=function(e,t){e=parseInt(e,10);for(var i=0;ijs.reject(function(e){return{name:{PermissionDeniedError:"NotAllowedError"}[e.name]||e.name,message:e.message,constraint:e.constraint,toString(){return this.name}}}(e))))}}function v(e){var t;"getDisplayMedia"in e.navigator&&e.navigator.mediaDevices&&(e.navigator.mediaDevices&&"getDisplayMedia"in e.navigator.mediaDevices||(e.navigator.mediaDevices.getDisplayMedia=Sc(t=e.navigator.getDisplayMedia).call(t,e.navigator)))}function D(e){let t=c(e);if(e.RTCIceGatherer&&(e.RTCIceCandidate||(e.RTCIceCandidate=function(e){return e}),e.RTCSessionDescription||(e.RTCSessionDescription=function(e){return e}),15025>t.version)){let t=_o(e.MediaStreamTrack.prototype,"enabled");Ja(e.MediaStreamTrack.prototype,"enabled",{set(e){t.set.call(this,e);let i=new Event("enabled");i.enabled=e,this.dispatchEvent(i)}})}!e.RTCRtpSender||"dtmf"in e.RTCRtpSender.prototype||Ja(e.RTCRtpSender.prototype,"dtmf",{get(){return void 0===this._dtmf&&("audio"===this.track.kind?this._dtmf=new e.RTCDtmfSender(this):"video"===this.track.kind&&(this._dtmf=null)),this._dtmf}}),e.RTCDtmfSender&&!e.RTCDTMFSender&&(e.RTCDTMFSender=e.RTCDtmfSender);let i=Yc(e,t.version);e.RTCPeerConnection=function(e){return e&&e.iceServers&&(e.iceServers=function(e,t){let i=!1;return e=JSON.parse(En(e)),vo(e).call(e,(e=>{if(e&&(e.urls||e.url)){var t=e.urls||e.url;e.url&&!e.urls&&s("RTCIceServer.url","RTCIceServer.urls");let n="string"==typeof t;return n&&(t=[t]),t=vo(t).call(t,(e=>0!==ac(e).call(e,"stun:")&&((e=bc(e).call(e,"turn")&&!bc(e).call(e,"turn:[")&&Cc(e).call(e,"transport=udp"))&&!i?(i=!0,!0):e&&!i))),delete e.url,e.urls=n?t[0]:t,!!t.length}}))}(e.iceServers,t.version),o("ICE servers after filtering:",e.iceServers)),new i(e)},e.RTCPeerConnection.prototype=i.prototype}function L(e){!e.RTCRtpSender||"replaceTrack"in e.RTCRtpSender.prototype||(e.RTCRtpSender.prototype.replaceTrack=e.RTCRtpSender.prototype.setTrack)}function P(e){let t=c(e),i=e&&e.navigator;if(e=e&&e.MediaStreamTrack,i.getUserMedia=function(e,t,n){s("navigator.getUserMedia","navigator.mediaDevices.getUserMedia"),i.mediaDevices.getUserMedia(e).then(t,n)},!(55t.version&&wa(i=["setLocalDescription","setRemoteDescription","addIceCandidate"]).call(i,(function(t){let i=e.RTCPeerConnection.prototype[t];e.RTCPeerConnection.prototype[t]={[t](){return arguments[0]=new("addIceCandidate"===t?e.RTCIceCandidate:e.RTCSessionDescription)(arguments[0]),i.apply(this,arguments)}}[t]}));var n=e.RTCPeerConnection.prototype.addIceCandidate;e.RTCPeerConnection.prototype.addIceCandidate=function(){return arguments[0]?68>t.version&&arguments[0]&&""===arguments[0].candidate?js.resolve():n.apply(this,arguments):(arguments[1]&&arguments[1].apply(null),js.resolve())};var r={inboundrtp:"inbound-rtp",outboundrtp:"outbound-rtp",candidatepair:"candidate-pair",localcandidate:"local-candidate",remotecandidate:"remote-candidate"},a=e.RTCPeerConnection.prototype.getStats;e.RTCPeerConnection.prototype.getStats=function(){let[e,i,n]=arguments;return a.apply(this,[e||null]).then((e=>{if(53>t.version&&!i)try{wa(e).call(e,(e=>{e.type=r[e.type]||e.type}))}catch(t){if("TypeError"!==t.name)throw t;wa(e).call(e,((t,i)=>{e.set(i,Ba({},t,{type:r[t.type]||t.type}))}))}return e})).then(i,n)}}}function k(e){if("object"==typeof e&&e.RTCPeerConnection&&e.RTCRtpSender&&(!e.RTCRtpSender||!("getStats"in e.RTCRtpSender.prototype))){var t=e.RTCPeerConnection.prototype.getSenders;t&&(e.RTCPeerConnection.prototype.getSenders=function(){let e=t.apply(this,[]);return wa(e).call(e,(e=>e._pc=this)),e});var i=e.RTCPeerConnection.prototype.addTrack;i&&(e.RTCPeerConnection.prototype.addTrack=function(){let e=i.apply(this,arguments);return e._pc=this,e}),e.RTCRtpSender.prototype.getStats=function(){return this.track?this._pc.getStats(this.track):js.resolve(new pa)}}}function U(e){if("object"==typeof e&&e.RTCPeerConnection&&e.RTCRtpSender&&(!e.RTCRtpSender||!("getStats"in e.RTCRtpReceiver.prototype))){var t=e.RTCPeerConnection.prototype.getReceivers;t&&(e.RTCPeerConnection.prototype.getReceivers=function(){let e=t.apply(this,[]);return wa(e).call(e,(e=>e._pc=this)),e}),n(e,"track",(e=>(e.receiver._pc=e.srcElement,e))),e.RTCRtpReceiver.prototype.getStats=function(){return this._pc.getStats(this.track)}}}function w(e){!e.RTCPeerConnection||"removeStream"in e.RTCPeerConnection.prototype||(e.RTCPeerConnection.prototype.removeStream=function(e){var t;s("removeStream","removeTrack"),wa(t=this.getSenders()).call(t,(t=>{var i;t.track&&Cc(i=e.getTracks()).call(i,t.track)&&this.removeTrack(t)}))})}function b(e){e.DataChannel&&!e.RTCDataChannel&&(e.RTCDataChannel=e.DataChannel)}function V(e){if("object"==typeof e&&e.RTCPeerConnection){if("getLocalStreams"in e.RTCPeerConnection.prototype||(e.RTCPeerConnection.prototype.getLocalStreams=function(){return this._localStreams||(this._localStreams=[]),this._localStreams}),!("addStream"in e.RTCPeerConnection.prototype)){let t=e.RTCPeerConnection.prototype.addTrack;e.RTCPeerConnection.prototype.addStream=function(e){var i,n,r;this._localStreams||(this._localStreams=[]),Cc(i=this._localStreams).call(i,e)||this._localStreams.push(e),wa(n=e.getAudioTracks()).call(n,(i=>t.call(this,i,e))),wa(r=e.getVideoTracks()).call(r,(i=>t.call(this,i,e)))},e.RTCPeerConnection.prototype.addTrack=function(e,i){var n;return i&&(this._localStreams?Cc(n=this._localStreams).call(n,i)||this._localStreams.push(i):this._localStreams=[i]),t.call(this,e,i)}}"removeStream"in e.RTCPeerConnection.prototype||(e.RTCPeerConnection.prototype.removeStream=function(e){var t,i,n;this._localStreams||(this._localStreams=[]);let r=ac(t=this._localStreams).call(t,e);if(-1!==r){$s(i=this._localStreams).call(i,r,1);var a=e.getTracks();wa(n=this.getSenders()).call(n,(e=>{Cc(a).call(a,e.track)&&this.removeTrack(e)}))}})}}function F(e){if("object"==typeof e&&e.RTCPeerConnection&&("getRemoteStreams"in e.RTCPeerConnection.prototype||(e.RTCPeerConnection.prototype.getRemoteStreams=function(){return this._remoteStreams?this._remoteStreams:[]}),!("onaddstream"in e.RTCPeerConnection.prototype))){Ja(e.RTCPeerConnection.prototype,"onaddstream",{get(){return this._onaddstream},set(e){this._onaddstream&&(this.removeEventListener("addstream",this._onaddstream),this.removeEventListener("track",this._onaddstreampoly)),this.addEventListener("addstream",this._onaddstream=e),this.addEventListener("track",this._onaddstreampoly=e=>{var t;wa(t=e.streams).call(t,(e=>{var t;this._remoteStreams||(this._remoteStreams=[]),Cc(t=this._remoteStreams).call(t,e)||(this._remoteStreams.push(e),(t=new Event("addstream")).stream=e,this.dispatchEvent(t))}))})}});let t=e.RTCPeerConnection.prototype.setRemoteDescription;e.RTCPeerConnection.prototype.setRemoteDescription=function(){let e=this;return this._onaddstreampoly||this.addEventListener("track",this._onaddstreampoly=function(t){var i;wa(i=t.streams).call(i,(t=>{var i;e._remoteStreams||(e._remoteStreams=[]),0<=ac(i=e._remoteStreams).call(i,t)||(e._remoteStreams.push(t),(i=new Event("addstream")).stream=t,e.dispatchEvent(i))}))}),t.apply(e,arguments)}}}function B(e){if("object"==typeof e&&e.RTCPeerConnection){var t=(e=e.RTCPeerConnection.prototype).createOffer,i=e.createAnswer,n=e.setLocalDescription,r=e.setRemoteDescription,a=e.addIceCandidate;e.createOffer=function(e,i){let n=t.apply(this,[2<=arguments.length?arguments[2]:arguments[0]]);return i?(n.then(e,i),js.resolve()):n},e.createAnswer=function(e,t){let n=i.apply(this,[2<=arguments.length?arguments[2]:arguments[0]]);return t?(n.then(e,t),js.resolve()):n};var o=function(e,t,i){return e=n.apply(this,[e]),i?(e.then(t,i),js.resolve()):e};e.setLocalDescription=o,o=function(e,t,i){return e=r.apply(this,[e]),i?(e.then(t,i),js.resolve()):e},e.setRemoteDescription=o,o=function(e,t,i){return e=a.apply(this,[e]),i?(e.then(t,i),js.resolve()):e},e.addIceCandidate=o}}function G(e){let t=e&&e.navigator;if(t.mediaDevices&&t.mediaDevices.getUserMedia){var i;e=t.mediaDevices;let n=Sc(i=e.getUserMedia).call(i,e);t.mediaDevices.getUserMedia=e=>n(x(e))}var n;!t.getUserMedia&&t.mediaDevices&&t.mediaDevices.getUserMedia&&(t.getUserMedia=Sc(n=function(e,i,n){t.mediaDevices.getUserMedia(e).then(i,n)}).call(n,t))}function x(e){return e&&void 0!==e.video?Ba({},e,{video:_(e.video)}):e}function H(e){let t=e.RTCPeerConnection;e.RTCPeerConnection=function(e,i){if(e&&e.iceServers){let t=[];for(let i=0;it.generateCertificate})}function W(e){"object"==typeof e&&e.RTCPeerConnection&&"receiver"in e.RTCTrackEvent.prototype&&!e.RTCTransceiver&&Ja(e.RTCTrackEvent.prototype,"transceiver",{get(){return{receiver:this.receiver}}})}function Y(e){let t=e.RTCPeerConnection.prototype.createOffer;e.RTCPeerConnection.prototype.createOffer=function(e){if(e){var i,n;void 0!==e.offerToReceiveAudio&&(e.offerToReceiveAudio=!!e.offerToReceiveAudio);let t=Rc(i=this.getTransceivers()).call(i,(e=>"audio"===e.receiver.track.kind));!1===e.offerToReceiveAudio&&t?"sendrecv"===t.direction?t.setDirection?t.setDirection("sendonly"):t.direction="sendonly":"recvonly"===t.direction&&(t.setDirection?t.setDirection("inactive"):t.direction="inactive"):!0!==e.offerToReceiveAudio||t||this.addTransceiver("audio"),void 0!==e.offerToReceiveVideo&&(e.offerToReceiveVideo=!!e.offerToReceiveVideo),i=Rc(n=this.getTransceivers()).call(n,(e=>"video"===e.receiver.track.kind)),!1===e.offerToReceiveVideo&&i?"sendrecv"===i.direction?i.setDirection?i.setDirection("sendonly"):i.direction="sendonly":"recvonly"===i.direction&&(i.setDirection?i.setDirection("inactive"):i.direction="inactive"):!0!==e.offerToReceiveVideo||i||this.addTransceiver("video")}return t.apply(this,arguments)}}function j(e){if(e.RTCIceCandidate&&(!e.RTCIceCandidate||!("foundation"in e.RTCIceCandidate.prototype))){var t=e.RTCIceCandidate;e.RTCIceCandidate=function(e){var i;if("object"==typeof e&&e.candidate&&0===ac(i=e.candidate).call(i,"a=")&&((e=JSON.parse(En(e))).candidate=e.candidate.substr(2)),e.candidate&&e.candidate.length){i=new t(e),e=Wc.parseCandidate(e.candidate);let n=Ba(i,e);return n.toJSON=function(){return{candidate:n.candidate,sdpMid:n.sdpMid,sdpMLineIndex:n.sdpMLineIndex,usernameFragment:n.usernameFragment}},n}return new t(e)},e.RTCIceCandidate.prototype=t.prototype,n(e,"icecandidate",(t=>(t.candidate&&Ja(t,"candidate",{value:new e.RTCIceCandidate(t.candidate),writable:"false"}),t)))}}function K(e){if(e.RTCPeerConnection){var t=c(e);"sctp"in e.RTCPeerConnection.prototype||Ja(e.RTCPeerConnection.prototype,"sctp",{get(){return void 0===this._sctp?null:this._sctp}});var i=function(e){return!(!e||!e.sdp)&&((e=Wc.splitSections(e.sdp)).shift(),Dc(e).call(e,(e=>{var t;return(e=Wc.parseMLine(e))&&"application"===e.kind&&-1!==ac(t=e.protocol).call(t,"SCTP")})))},n=function(e){return null===(e=e.sdp.match(/mozilla...THIS_IS_SDPARTA-(\d+)/))||2>e.length||(e=io(e[1],10))!=e?-1:e},r=function(e){let i=65536;return"firefox"===t.browser&&(i=57>t.version?-1===e?16384:2147483637:60>t.version?57===t.version?65535:65536:2147483637),i},a=function(e,i){let n=65536;return"firefox"===t.browser&&57===t.version&&(n=65535),0<(e=Wc.matchPrefix(e.sdp,"a=max-message-size:")).length?n=io(e[0].substr(19),10):"firefox"===t.browser&&-1!==i&&(n=2147483637),n},o=e.RTCPeerConnection.prototype.setRemoteDescription;e.RTCPeerConnection.prototype.setRemoteDescription=function(){if(this._sctp=null,"chrome"===t.browser&&76<=t.version){var{sdpSemantics:e}=this.getConfiguration();"plan-b"===e&&Ja(this,"sctp",{get(){return void 0===this._sctp?null:this._sctp},enumerable:!0,configurable:!0})}if(i(arguments[0])){var s=n(arguments[0]);let t;e=r(s),s=a(arguments[0],s),t=0===e&&0===s?Number.POSITIVE_INFINITY:0===e||0===s?Math.max(e,s):Math.min(e,s),Ja(e={},"maxMessageSize",{get:()=>t}),this._sctp=e}return o.apply(this,arguments)}}}function X(e){function t(e,t){let i=e.send;e.send=function(){var n=arguments[0];if(n=n.length||n.size||n.byteLength,"open"===e.readyState&&t.sctp&&n>t.sctp.maxMessageSize)throw new TypeError("Message too large (can send a maximum of "+t.sctp.maxMessageSize+" bytes)");return i.apply(e,arguments)}}if(e.RTCPeerConnection&&"createDataChannel"in e.RTCPeerConnection.prototype){var i=e.RTCPeerConnection.prototype.createDataChannel;e.RTCPeerConnection.prototype.createDataChannel=function(){let e=i.apply(this,arguments);return t(e,this),e},n(e,"datachannel",(e=>(t(e.channel,e.target),e)))}}function J(e){var t;if(e.RTCPeerConnection&&!("connectionState"in e.RTCPeerConnection.prototype)){var i=e.RTCPeerConnection.prototype;Ja(i,"connectionState",{get(){return{completed:"connected",checking:"connecting"}[this.iceConnectionState]||this.iceConnectionState},enumerable:!0,configurable:!0}),Ja(i,"onconnectionstatechange",{get(){return this._onconnectionstatechange||null},set(e){this._onconnectionstatechange&&(this.removeEventListener("connectionstatechange",this._onconnectionstatechange),delete this._onconnectionstatechange),e&&this.addEventListener("connectionstatechange",this._onconnectionstatechange=e)},enumerable:!0,configurable:!0}),wa(t=["setLocalDescription","setRemoteDescription"]).call(t,(e=>{let t=i[e];i[e]=function(){return this._connectionstatechangepoly||(this._connectionstatechangepoly=e=>{let t=e.target;if(t._lastConnectionState!==t.connectionState){t._lastConnectionState=t.connectionState;let i=new Event("connectionstatechange",e);t.dispatchEvent(i)}return e},this.addEventListener("iceconnectionstatechange",this._connectionstatechangepoly)),t.apply(this,arguments)}}))}}function Q(e){if(e.RTCPeerConnection){var t=c(e);if(!("chrome"===t.browser&&71<=t.version)){var i=e.RTCPeerConnection.prototype.setRemoteDescription;e.RTCPeerConnection.prototype.setRemoteDescription=function(e){var t,n;return e&&e.sdp&&-1!==ac(t=e.sdp).call(t,"\na=extmap-allow-mixed")&&(e.sdp=vo(n=e.sdp.split("\n")).call(n,(e=>"a=extmap-allow-mixed"!==Hc(e).call(e))).join("\n")),i.apply(this,arguments)}}}}function q(e){return"string"==typeof e?Ba({},$c[e]):e}function z(e){return"string"==typeof e?Ba({},e_[e]):e}function Z(e){return"string"==typeof e?Ba({},t_[e]):e}function $(e){return"string"==typeof e?Ba({},i_[e]):e}function ee(e,t){var i;Cc(i=xa(n_)).call(i,e)&&(n_[e]=t)}function te(e,t,i){return{sampleRate:e,stereo:t,bitrate:i}}function ie(e,t,i,n,r){return{width:e,height:t,frameRate:i,bitrateMin:n,bitrateMax:r}}function ne(e,t,i,n,r){return{width:{max:e},height:{max:t},frameRate:i,bitrateMin:n,bitrateMax:r}}function re(e,t){return{numSpatialLayers:e,numTemporalLayers:t}}function ae(e){return"[object Array]"===A_.call(e)}function oe(e){return null!==e&&"object"==typeof e}function se(e){return"[object Function]"===A_.call(e)}function ce(e,t){if(null!=e)if("object"!=typeof e&&(e=[e]),ae(e))for(var i=0,n=e.length;in||r&&("number"!=typeof e||0!=e%1))throw new G_(h_.INVALID_PARAMS,No(a=No(o="invalid ".concat(t,": the value range is [")).call(o,i,", ")).call(a,n,"]. integer only"))}function Se(e,t,i=1,n=255,r=!0){if(null==e)throw new G_(h_.INVALID_PARAMS,"".concat(t||"param"," cannot be empty"));var a,o,s;if(!Ne(e,i,n,r))throw new G_(h_.INVALID_PARAMS,No(a=No(o=No(s="Invalid ".concat(t||"string param",": Length of the string: [")).call(s,i,",")).call(o,n,"].")).call(a,r?" ASCII characters only.":""))}function Oe(e,t){if(!R_(e))throw new G_(h_.INVALID_PARAMS,"".concat(t," should be an array"))}function me(e){if("string"!=typeof e||!/^[a-zA-Z0-9 !#\$%&\(\)\+\-:;<=\.>\?@\[\]\^_\{\}\|~,]{1,64}$/.test(e))throw B_.error("Invalid Channel Name ".concat(e)),new G_(h_.INVALID_PARAMS,"The length must be within 64 bytes. The supported characters: a-z,A-Z,0-9,space,!, #, $, %, &, (, ), +, -, :, ;, <, =, ., >, ?, @, [, ], ^, _, {, }, |, ~, ,")}function fe(e){var t;if(!("number"==typeof e&&Math.floor(e)===e&&0<=e&&4294967295>=e||Ne(e,1,255)))throw B_.error(No(t="Invalid UID ".concat(e," ")).call(t,typeof e)),new G_(h_.INVALID_PARAMS,"[String uid] Length of the string: [1,255]. ASCII characters only. [Number uid] The value range is [0,10000]")}function Ne(e,t=1,i=255,n=!0){if(t="string"==typeof e&&e.length<=i&&e.length>=t){if(!(n=!n))e:if("string"!=typeof e)n=!1;else{for(n=0;n(t=e.charCodeAt(n))||255e.length)return!1;try{wa(e).call(e,(e=>{if(!e.urls)throw Error()}))}catch(e){return!1}return!0}function De(e){return Se(e.turnServerURL,"turnServerURL"),Se(e.username,"username"),Se(e.password,"password"),e.udpport&&Ie(e.udpport,"udpport",1,99999,!0),e.forceturn&&Ae(e.forceturn,"forceturn"),e.security&&Ae(e.security,"security"),e.tcpport&&Ie(e.tcpport,"tcpport",1,99999,!0),!0}function Le(e){return void 0!==e.level&&pe(e.level,"level",[1,2]),!0}function Pe(e,t){Se(e.url,"".concat(t,".url"),1,1e3,!1),null==e.x||Ie(e.x,"".concat(t,".x"),0,1e4),null==e.y||Ie(e.y,"".concat(t,".y"),0,1e4),null==e.width||Ie(e.width,"".concat(t,".width"),0,1e4),null==e.height||Ie(e.height,"".concat(t,".height"),0,1e4),null==e.zOrder||Ie(e.zOrder,"".concat(t,".zOrder"),0,255),null==e.alpha||Ie(e.alpha,"".concat(t,".alpha"),0,1,!1)}function ye(e){if(!e.channelName)throw new G_(h_.INVALID_PARAMS,"invalid channelName in info");if(!e.uid||"number"!=typeof e.uid)throw new G_(h_.INVALID_PARAMS,"invalid uid in info, uid must be a number");return e.token&&Se(e.token,"info.token",1,2047),fe(e.uid),me(e.channelName),!0}function Me(e){return pe(e,"mediaSource",["screen","window","application"]),!0}function ke(e){var t,i,n,r;let a=(e=e||navigator.userAgent).match(/(opera|chrome|safari|firefox|msie|trident(?=\/))\/?\s*(\d+)/i)||[];if("Chrome"===a[1]){var o=e.match(/(OPR(?=\/))\/?(\d+)/i);null!==o&&(a=o)}"Safari"===a[1]&&null!==(o=e.match(/version\/(\d+)/i))&&(a[2]=o[1]),-1!==ac(t=e.toLowerCase()).call(t,"qqbrowser")&&null!==(t=e.match(/(qqbrowser(?=\/))\/?(\d+)/i))&&(a=t),-1!==ac(i=e.toLowerCase()).call(i,"micromessenger")&&null!==(i=e.match(/(micromessenger(?=\/))\/?(\d+)/i))&&(a=i),-1!==ac(n=e.toLowerCase()).call(n,"edge")&&null!==(n=e.match(/(edge(?=\/))\/?(\d+)/i))&&(a=n),-1!==ac(r=e.toLowerCase()).call(r,"trident")&&null!==(r=/\brv[ :]+(\d+)/g.exec(e)||[])&&(a=["","IE",r[1]]),r=null,n=[{s:Vc.WIN_10,r:/(Windows 10.0|Windows NT 10.0)/},{s:Vc.WIN_81,r:/(Windows 8.1|Windows NT 6.3)/},{s:Vc.WIN_8,r:/(Windows 8|Windows NT 6.2)/},{s:Vc.WIN_7,r:/(Windows 7|Windows NT 6.1)/},{s:Vc.WIN_VISTA,r:/Windows NT 6.0/},{s:Vc.WIN_SERVER_2003,r:/Windows NT 5.2/},{s:Vc.WIN_XP,r:/(Windows NT 5.1|Windows XP)/},{s:Vc.WIN_2000,r:/(Windows NT 5.0|Windows 2000)/},{s:Vc.ANDROID,r:/Android/},{s:Vc.OPEN_BSD,r:/OpenBSD/},{s:Vc.SUN_OS,r:/SunOS/},{s:Vc.LINUX,r:/(Linux|X11)/},{s:Vc.IOS,r:/(iPhone|iPad|iPod)/},{s:Vc.MAC_OS_X,r:/Mac OS X/},{s:Vc.MAC_OS,r:/(MacPPC|MacIntel|Mac_PowerPC|Macintosh)/},{s:Vc.QNX,r:/QNX/},{s:Vc.UNIX,r:/UNIX/},{s:Vc.BEOS,r:/BeOS/},{s:Vc.OS_2,r:/OS\/2/},{s:Vc.SEARCH_BOT,r:/(nuhk|Googlebot|Yammybot|Openbot|Slurp|MSNBot|Ask Jeeves\/Teoma|ia_archiver)/}];for(let t in n)if((i=n[t]).r.test(e)){r=i.s;break}return{name:a[1],version:a[2],os:r}}function Ue(){return ke().name===Fc.CHROME}function we(){return ke().name===Fc.FIREFOX}function be(){return window.navigator.appVersion&&null!==window.navigator.appVersion.match(/Chrome\/([\w\W]*?)\./)&&35>=window.navigator.appVersion.match(/Chrome\/([\w\W]*?)\./)[1]}function Ve(){let e=ke();return e.name!==Fc.EDGE&&e.name!==Fc.SAFARI&&!!navigator.userAgent.toLocaleLowerCase().match(/chrome\/[\d]./i)}function Fe(e,t){var i=xa(e);if(md){var n=md(e);t&&(n=vo(n).call(n,(function(t){return _o(e,t).enumerable}))),i.push.apply(i,n)}return i}function Be(e){for(var t=1;te?1:.17<=e&&.36>e?2:.36<=e&&.59>e?3:.59<=e&&1>=e?4:1{window.setTimeout(t,e)}))}function Qe(e){let t=new G_(h_.TIMEOUT,"timeout");return new js(((i,n)=>{window.setTimeout((()=>n(t)),e)}))}function qe(e=7,t){var i,n;let r=Math.random().toString(16).substr(2,e).toLowerCase();return r.length===e?No(i="".concat(t)).call(i,r):No(n="".concat(t)).call(n,r)+qe(e-r.length,"")}function ze(e){return new js(((t,i)=>{let n=document.createElement("video");n.setAttribute("autoplay",""),n.setAttribute("muted",""),n.muted=!0,n.autoplay=!0,n.setAttribute("playsinline",""),n.setAttribute("style","position: absolute; top: 0; left: 0; width: 1px; height: 1px"),document.body.appendChild(n),n.addEventListener("playing",(()=>{!n.videoWidth&&we()||(document.body.removeChild(n),t([n.videoWidth,n.videoHeight]))})),n.srcObject=new MediaStream([e])}))}function Ze(e){return js.all(Js(e).call(e,(e=>e.then((e=>{throw e}),(e=>e))))).then((e=>{throw e}),(e=>e))}function $e(e,t,...i){return 0===e.getListeners(t).length?js.reject(new G_(h_.UNEXPECTED_ERROR,"can not emit promise")):new js(((n,r)=>{e.emit(t,...i,n,r)}))}function et(e,t,...i){return 0===e.getListeners(t).length?js.resolve():$e(e,t,...i)}function tt(e,t,...i){return 0===e.getListeners(t).length?null:it(e,t,...i)}function it(e,t,...i){let n=null,r=null;if(e.emit(t,...i,(e=>{n=e}),(e=>{r=e})),null!==r)throw r;if(null===n)throw new G_(h_.UNEXPECTED_ERROR,"handler is not sync");return n}function nt(e,t){-1!==(t=ac(e).call(e,t))&&$s(e).call(e,t,1)}function rt(e){let t=[];return wa(e).call(e,(e=>{-1===ac(t).call(t,e)&&t.push(e)})),t}function at(e){js.resolve().then(e)}function ot(e,t){Vd[t]||(Vd[t]=!0,e())}function st(e){e=window.atob(e);let t=new Uint8Array(new ArrayBuffer(e.length));for(let i=0;ie?"number"!=typeof e?e.max||e.exact||e.ideal||e.min||t:e:t;return e={audio:!1,video:{mandatory:{chromeMediaSource:"desktop",chromeMediaSourceId:e,maxHeight:i(t.height,1080),maxWidth:i(t.width,1920)}}},t.frameRate&&"number"!=typeof t.frameRate?(e.video.mandatory.maxFrameRate=t.frameRate.max,e.video.mandatory.minFrameRate=t.frameRate.min):"number"==typeof t.frameRate&&(e.video.mandatory.maxFrameRate=t.frameRate),await navigator.mediaDevices.getUserMedia(e)}async function Et(e){let t=["window","screen"];"application"!==e&&"window"!==e||(t=["window"]),"screen"===e&&(t=["screen"]);let i=dt();if(!i)throw new G_(h_.ELECTRON_IS_NULL);e=null;try{e=i.desktopCapturer.getSources({types:t})}catch(t){e=null}e&&e.then||(e=new js(((e,n)=>{i.desktopCapturer.getSources({types:t},((t,i)=>{t?n(t):e(i)}))})));try{return await e}catch(e){throw new G_(h_.ELECTRON_DESKTOP_CAPTURER_GET_SOURCES_ERROR,e.toString())}}function dt(){if(xd)return xd;try{return xd=window.require("electron"),xd}catch(e){return null}}async function lt(e,t){let i=0,n=null;for(;2>i;)try{n=await ut(e,t,0{const n=document.createElement("div");n.innerText="share screen",n.setAttribute("style","text-align: center; height: 25px; line-height: 25px; border-radius: 4px 4px 0 0; background: #D4D2D4; border-bottom: solid 1px #B9B8B9;");const r=document.createElement("div");r.setAttribute("style","width: 100%; height: 500px; padding: 15px 25px ; box-sizing: border-box;");const a=document.createElement("div");a.innerText="Agora Web Screensharing wants to share the contents of your screen with webdemo.agorabeckon.com. Choose what you'd like to share.",a.setAttribute("style","height: 12%;");const o=document.createElement("div");o.setAttribute("style","width: 100%; height: 80%; background: #FFF; border: solid 1px #CBCBCB; display: flex; flex-wrap: wrap; justify-content: space-around; overflow-y: scroll; padding: 0 15px; box-sizing: border-box;");const s=document.createElement("div");s.setAttribute("style","text-align: right; padding: 16px 0;");const c=document.createElement("button");c.innerHTML="cancel",c.setAttribute("style","width: 85px;"),c.onclick=()=>{document.body.removeChild(_);const e=Error("NotAllowedError");e.name="NotAllowedError",t(e)},s.appendChild(c),r.appendChild(a),r.appendChild(o),r.appendChild(s);const _=document.createElement("div");_.setAttribute("style","position: fixed; z-index: 99999999; top: 50%; left: 50%; width: 620px; height: 525px; background: #ECECEC; border-radius: 4px; -webkit-transform: translate(-50%,-50%); transform: translate(-50%,-50%);"),_.appendChild(n),_.appendChild(r),document.body.appendChild(_),Js(i).call(i,(t=>{if(t.id){const i=document.createElement("div");i.setAttribute("style","width: 30%; height: 160px; padding: 20px 0; text-align: center;box-sizing: content-box;");let n=t.thumbnail;const{width:r}=n.getSize();1920'+t.name.replace(/[\u00A0-\u9999<>&]/g,(function(e){return"&#"+e.charCodeAt(0)+";"}))+"",i.onclick=()=>{document.body.removeChild(_),e(t.id)},o.appendChild(i)}}))})));var i;return await _t(t,e)}(e.screen));else if(Ue()&&e.screen.extensionId&&e.screen.mandatory){if(!a.getStreamFromExtension)throw new G_(h_.NOT_SUPPORTED,"This browser does not support screen sharing");B_.debug("[".concat(t,'] Screen access on chrome stable, looking for extension"'));var o=await(n=e.screen.extensionId,r=t,new js(((e,t)=>{try{chrome.runtime.sendMessage(n,{getStream:!0},(i=>{if(!i||!i.streamId)return B_.error("[".concat(r,"] No response from Chrome Plugin. Plugin not installed properly"),i),void t(new G_(h_.CHROME_PLUGIN_NO_RESPONSE,"No response from Chrome Plugin. Plugin not installed properly"));e(i.streamId)}))}catch(e){var i;B_.error(No(i="[".concat(r,"] AgoraRTC screensharing plugin is not accessible(")).call(i,n,")"),e.toString()),t(new G_(h_.CHROME_PLUGIN_NOT_INSTALL))}})));e.screen.mandatory.chromeMediaSourceId=o,Rt(i,await navigator.mediaDevices.getUserMedia({video:{mandatory:e.screen.mandatory}}))}else if(a.getDisplayMedia)e.screen.mediaSource&&Me(e.screen.mediaSource),o={width:e.screen.width,height:e.screen.height,frameRate:e.screen.frameRate,displaySurface:"screen"===e.screen.mediaSource?"monitor":e.screen.mediaSource},B_.debug("[".concat(t,"] getDisplayMedia:"),En({video:o,audio:!!e.screenAudio})),Rt(i,await navigator.mediaDevices.getDisplayMedia({video:o,audio:!!e.screenAudio}));else{if(!we())throw B_.error("[".concat(t,"] This browser does not support screenSharing")),new G_(h_.NOT_SUPPORTED,"This browser does not support screen sharing");e.screen.mediaSource&&Me(e.screen.mediaSource),a={video:{mediaSource:e.screen.mediaSource,width:e.screen.width,height:e.screen.height,frameRate:e.screen.frameRate}},B_.debug(No(o="[".concat(t,"] getUserMedia: ")).call(o,En(a))),Rt(i,await navigator.mediaDevices.getUserMedia(a))}if(!e.video&&!e.audio)return i;let s;e={video:e.video,audio:e.audio},B_.debug("[".concat(t,"] GetUserMedia"),En(e)),o=null,(t=ke()).name!==Fc.SAFARI&&t.os!==Vc.IOS||(o=await Yd.lock());try{s=await navigator.mediaDevices.getUserMedia(e)}catch(e){throw o&&o(),e}return e.audio&&(jd=!0),e.video&&(Kd=!0),Rt(i,s),o&&o(),i}function ht(e,t){switch(e){case"Starting video failed":case"OverconstrainedError":case"TrackStartError":var i;return new G_(h_.MEDIA_OPTION_INVALID,No(i="".concat(e,": ")).call(i,t));case"NotFoundError":case"DevicesNotFoundError":var n;return new G_(h_.DEVICE_NOT_FOUND,No(n="".concat(e,": ")).call(n,t));case"NotSupportedError":var r;return new G_(h_.NOT_SUPPORTED,No(r="".concat(e,": ")).call(r,t));case"NotReadableError":var a;return new G_(h_.NOT_READABLE,No(a="".concat(e,": ")).call(a,t));case"InvalidStateError":case"NotAllowedError":case"PERMISSION_DENIED":case"PermissionDeniedError":var o;return new G_(h_.PERMISSION_DENIED,No(o="".concat(e,": ")).call(o,t));case"ConstraintNotSatisfiedError":var s;return new G_(h_.CONSTRAINT_NOT_SATISFIED,No(s="".concat(e,": ")).call(s,t));default:var c;return B_.error("getUserMedia unexpected error",e),new G_(h_.UNEXPECTED_ERROR,No(c="".concat(e,": ")).call(c,t))}}function Rt(e,t){let i=e.getVideoTracks()[0],n=e.getAudioTracks()[0],r=t.getVideoTracks()[0];(t=t.getAudioTracks()[0])&&(n&&e.removeTrack(n),e.addTrack(t)),r&&(i&&e.removeTrack(i),e.addTrack(r))}function Tt(e,t){var i=xa(e);if(md){var n=md(e);t&&(n=vo(n).call(n,(function(t){return _o(e,t).enumerable}))),i.push.apply(i,n)}return i}function At(e,t,i){return new js(((n,r)=>{t.timeout=t.timeout||n_.HTTP_CONNECT_TIMEOUT,t.responseType=t.responseType||"json",t.data&&!i?(t.data=En(t.data),Zd+=Xe(t.data)):i&&(Zd+=t.data.size),t.headers=t.headers||{},t.headers["Content-Type"]=t.headers["Content-Type"]||"application/json",t.method="POST",t.url=e,b_.request(t).then((e=>{"string"==typeof e.data?$d+=Xe(e.data):e.data instanceof ArrayBuffer||e.data instanceof Uint8Array?$d+=e.data.byteLength:$d+=Xe(En(e.data)),n(e.data)})).catch((e=>{b_.isCancel(e)?r(new G_(h_.OPERATION_ABORTED,"cancel token canceled")):"ECONNABORTED"===e.code?r(new G_(h_.NETWORK_TIMEOUT,e.message)):e.response?r(new G_(h_.NETWORK_RESPONSE_ERROR,e.response.status)):r(new G_(h_.NETWORK_ERROR,e.message))}))}))}async function pt(e,t){let i=new Blob([t.data],{type:"buffer"});return await At(e,function(e){for(var t=1;t{await Je(a),a*=r.timeoutFactor,a=Math.min(r.maxRetryTimeout,a)},s=!1;return(n=new js((async(n,a)=>{t=t||(()=>!1),i=i||(()=>!0);for(let c=0;cs=!0,n}function Ct(){if(!El&&(_l?(B_.info("create audio context"),El=new _l,El.onstatechange=()=>{dl.emit("state-change")},function(e){function t(t){"running"===e.state?i(!1):"closed"!==e.state&&(i(!0),t?e.resume().then(n,n):i(!1))}function i(e){if(o!==e){o=e;for(let t=0,i=a;t{var a;return e._inputNodes||(e._inputNodes=[]),Cc(a=e._inputNodes).call(a,i)||(i instanceof AudioNode?(e._inputNodes.push(i),t.call(e,i,n,r)):t.call(e,i,n)),e},e.disconnect=(n,r,a)=>{i.call(e),n?nt(e._inputNodes,n):e._inputNodes=[];for(let i of e._inputNodes)t.call(e,i)}}}function vt(e,t){let i=1/t,n=Ct(),r=n.createGain();r.gain.value=0,r.connect(n.destination);let a=!1,o=()=>{if(a)return void(r=null);const t=n.createOscillator();t.onended=o,t.connect(r),t.start(0),t.stop(n.currentTime+i),e(n.currentTime)};return o(),()=>{a=!0}}function Dt(e,t){var i=xa(e);if(md){var n=md(e);t&&(n=vo(n).call(n,(function(t){return _o(e,t).enumerable}))),i.push.apply(i,n)}return i}function Lt(e){for(var t=1;t{let t=await At(e+"".concat(-1===ac(e).call(e,"?")?"?":"&","action=wrtc_gateway"),{data:o,cancelToken:n,headers:{"X-Packet-Service-Type":0,"X-Packet-URI":69}});if(t.addresses&&0===t.addresses.length&&0===t.code)throw new G_(h_.VOID_GATEWAY_ADDRESS,"",{retry:!0,csIp:t.detail&&t.detail[502]});if(n_.GATEWAY_ADDRESS&&0({ip:e.ip,port:e.port,ticket:t.addresses[0]&&t.addresses[0].ticket})));t.addresses=e}return function(e,t){var i;let n=[".agora.io",".sd-rtn.com"],r=n[1]&&-1!==ac(t).call(t,n[1])?1:0;return e.addresses=e.addresses||[],{gatewayAddrs:Js(i=e.addresses).call(i,(e=>{var t,i,a;return e.ip.match(/^[\.:\d]+$/)?No(t=No(i="".concat(e.ip.replace(/[^\d]/g,"-"),".edge")).call(i,n[r++%n.length],":")).call(t,e.port):(B_.info("Cannot recognized as IP address ".concat(e.ip,". Used As Host instead")),No(a="".concat(e.ip,":")).call(a,e.port))})),uid:e.uid,cid:e.cid,vid:e.detail&&e.detail[8],uni_lbs_ip:e.detail&&e.detail[1],res:e,csIp:e.detail&&e.detail[502]}}(t,e)}),(t=>{if(0===t.res.code)return el.joinChooseServer(i.sid,{lts:a,succ:!0,csAddr:e,serverList:t.gatewayAddrs,ec:null,cid:t.res.cid.toString(),uid:t.res.uid.toString(),csIp:t.csIp}),!1;let n=mt(t.res.code);throw new G_(h_.CAN_NOT_GET_GATEWAY_SERVER,n.desc,{retry:n.retry,csIp:t.csIp})}),(t=>{return t.code!==h_.OPERATION_ABORTED&&(t.code===h_.CAN_NOT_GET_GATEWAY_SERVER||t.code===h_.VOID_GATEWAY_ADDRESS?(el.joinChooseServer(i.sid,{lts:a,succ:!1,csAddr:e,serverList:null,ec:t.message,csIp:t.data&&t.data.csIp}),B_.warning(No(n=No(r=No(o="[".concat(i.clientId,"] Choose server ")).call(o,e," failed, message: ")).call(r,t.message,", retry: ")).call(n,t.data.retry)),t.data.retry):(el.joinChooseServer(i.sid,{lts:a,succ:!1,csAddr:e,serverList:null,ec:t.code,csIp:t.data&&t.data.csIp}),B_.warning("[".concat(i.clientId,"] Choose server network error, retry"),t),!0));var n,r,o}),r)}async function Ut(e,t,i){return{gatewayInfo:await async function(e,t,i){var n,r;const a=Js(n=dc(r=n_.WEBCS_DOMAIN).call(r,0,n_.AJAX_REQUEST_CONCURRENT)).call(n,(t=>{var i;return{url:e.proxyServer?No(i="https://".concat(e.proxyServer,"/ap/?url=")).call(i,t+"/api/v1"):"https://".concat(t,"/api/v1"),areaCode:Nl()}}));let o=null;return o=await Ze([(async()=>await Gd({fragementLength:n_.FRAGEMENT_LENGTH,referenceList:a,asyncMapHandler:n=>(B_.debug("[".concat(e.clientId,"] Connect to choose_server:"),n.url),kt(n,e,t,i)),allFailedhandler:e=>{throw e[0]}}))(),(async()=>{var n;if(await Je(1e3),null!==o)return o;const r=Js(n=n_.WEBCS_DOMAIN_BACKUP_LIST).call(n,(t=>{var i;return{url:e.proxyServer?No(i="https://".concat(e.proxyServer,"/ap/?url=")).call(i,t+"/api/v1"):"https://".concat(t,"/api/v1"),areaCode:Nl()}}));return await Gd({fragementLength:n_.FRAGEMENT_LENGTH,referenceList:r,asyncMapHandler:n=>(B_.debug("[".concat(e.clientId,"] Connect to backup choose_server:"),n.url),kt(n,e,t,i)),allFailedhandler:e=>{throw e[0]}})})()]),o}(e,t,i)}}async function wt(e,t,i,n){var r;let a=dc(r=n_.ACCOUNT_REGISTER).call(r,0,n_.AJAX_REQUEST_CONCURRENT);return r=[],r=t.proxyServer?Js(a).call(a,(e=>{var i;return No(i="https://".concat(t.proxyServer,"/ap/?url=")).call(i,e+"/api/v1")})):Js(a).call(a,(e=>"https://".concat(e,"/api/v1"))),(await async function(e,t,i,n,r){let a=Pd(),o={sid:i.sid,opid:10,appid:i.appId,string_uid:t},s=e[0];if(0!==(i=await Nt((()=>At(s+"".concat(-1===ac(s).call(s,"?")?"?":"&","action=stringuid"),{data:o,cancelToken:n,headers:{"X-Packet-Service-Type":0,"X-Packet-URI":72}})),((i,n)=>{if(0===i.code){var r;if(0>=i.uid||i.uid>=Math.pow(2,32))throw B_.error(No(r="Invalid Uint Uid ".concat(t," => ")).call(r,i.uid),i),el.reqUserAccount(o.sid,{lts:a,success:!1,serverAddr:s,stringUid:o.string_uid,uid:i.uid,errorCode:h_.INVALID_UINT_UID_FROM_STRING_UID,extend:o}),new G_(h_.INVALID_UINT_UID_FROM_STRING_UID);return el.reqUserAccount(o.sid,{lts:a,success:!0,serverAddr:s,stringUid:o.string_uid,uid:i.uid,errorCode:null,extend:o}),!1}return(r=mt(i.code)).retry&&(s=e[(n+1)%e.length]),el.reqUserAccount(o.sid,{lts:a,success:!1,serverAddr:s,stringUid:o.string_uid,uid:i.uid,errorCode:r.desc,extend:o}),r.retry}),((t,i)=>t.code!==h_.OPERATION_ABORTED&&(el.reqUserAccount(o.sid,{lts:a,success:!1,serverAddr:s,stringUid:o.string_uid,uid:null,errorCode:t.code,extend:o}),s=e[(i+1)%e.length],!0)),r)).code)throw i=mt(i.code),new G_(h_.UNEXPECTED_RESPONSE,i.desc);return i}(r,e,t,i,n)).uid}async function bt(e,t,i,n){var r,a;let o=Js(r=dc(a=n_.UAP_AP).call(a,0,n_.AJAX_REQUEST_CONCURRENT)).call(r,(e=>{var i;return t.proxyServer?No(i="https://".concat(t.proxyServer,"/ap/?url=")).call(i,e+"/api/v1?action=uap"):"https://".concat(e,"/api/v1?action=uap")}));return await function(e,t,i,n,r){ml+=1;let a,o,s={sid:i.sid,command:"convergeAllocateEdge",uid:"666",appId:i.appId,ts:Math.floor(Pd()/1e3),seq:ml,requestId:ml,version:Qc,cname:i.cname},c={service_name:t,json_body:En(s)},_=e[0];return Nt((async()=>{a=Pd();var e=await At(_,{data:c,cancelToken:n,headers:{"X-Packet-Service-Type":"0","X-Packet-URI":"61"}});if(o=Pd()-a,0!==e.code){var i=new G_(h_.UNEXPECTED_RESPONSE,"live streaming ap error, code"+e.code,{retry:!0,responseTime:o});throw B_.error(i.toString()),i}if(200!==(e=JSON.parse(e.json_body)).code)throw e=new G_(h_.UNEXPECTED_RESPONSE,No(i="live streaming app center error, code: ".concat(e.code,", reason: ")).call(i,e.reason),{code:e.code,responseTime:o}),B_.error(e.toString()),e;if(!e.servers||0===e.servers.length)throw i=new G_(h_.UNEXPECTED_RESPONSE,"live streaming app center empty server",{code:e.code,responseTime:o}),B_.error(i.toString()),i;return i=function(e,t){var i;return{addressList:Js(i=e.servers).call(i,(e=>{var i,n;return No(i=No(n="wss://".concat(e.address.replace(/\./g,"-"),".edge.agora.io:")).call(n,e.wss,"?serviceName=")).call(i,encodeURIComponent(t))})),workerToken:e.workerToken,vid:e.vid}}(e,t),n_.LIVE_STREAMING_ADDRESS&&(i.addressList=n_.LIVE_STREAMING_ADDRESS instanceof Array?n_.LIVE_STREAMING_ADDRESS:[n_.LIVE_STREAMING_ADDRESS]),function(e){for(var t=1;t(el.apworkerEvent(i.sid,{success:!0,sc:200,serviceName:t,responseDetail:En(n.addressList),firstSuccess:0===r,responseTime:o,serverIp:e[r%e.length]}),!1)),((n,r)=>(el.apworkerEvent(i.sid,{success:!1,sc:n.data&&n.data.code||200,serviceName:t,responseTime:o,serverIp:e[r%e.length]}),!!(n.code!==h_.OPERATION_ABORTED&&n.code!==h_.UNEXPECTED_RESPONSE||n.data&&n.data.retry)&&(_=e[(r+1)%e.length],!0))),r)}(o,e,t,i,n)}function Vt(e,t){var i=xa(e);if(md){var n=md(e);t&&(n=vo(n).call(n,(function(t){return _o(e,t).enumerable}))),i.push.apply(i,n)}return i}function Ft(e){if(Array.isArray(e))return e.map((function(e){return e}));if(!Bt(e))return e;var t,i={};for(t in e)Bt(e[t])||Array.isArray(e[t])?i[t]=Ft(e[t]):i[t]=e[t];return i}function Bt(e){return!("object"!=typeof e||Array.isArray(e)||!e)}function Gt(e,t){function i(){this.constructor=e}yl(e,t),e.prototype=null===t?Object.create(t):(i.prototype=t.prototype,new i)}function xt(e,t,i,n){return new(i||(i=Promise))((function(r,a){function o(e){try{c(n.next(e))}catch(e){a(e)}}function s(e){try{c(n.throw(e))}catch(e){a(e)}}function c(e){e.done?r(e.value):new i((function(t){t(e.value)})).then(o,s)}c((n=n.apply(e,t||[])).next())}))}function Ht(e,t){function i(i){return function(o){return function(i){if(n)throw new TypeError("Generator is already executing.");for(;s;)try{if(n=1,r&&(a=2&i[0]?r.return:i[0]?r.throw||((a=r.return)&&a.call(r),0):r.next)&&!(a=a.call(r,i[1])).done)return a;switch(r=0,a&&(i=[2&i[0],a.value]),i[0]){case 0:case 1:a=i;break;case 4:return s.label++,{value:i[1],done:!1};case 5:s.label++,r=i[1],i=[0];continue;case 7:i=s.ops.pop(),s.trys.pop();continue;default:if(!((a=0<(a=s.trys).length&&a[a.length-1])||6!==i[0]&&2!==i[0])){s=0;continue}if(3===i[0]&&(!a||i[1]>a[0]&&i[1]o;o++)a[o]=o;o=0;for(var s=0;256>s;s++)o=(o+a[s]+t[s%i])%256,[a[s],a[o]]=[a[o],a[s]];for(o=i=0,s=0;s<0+n;s++)o=(o+a[i=(i+1)%256])%256,[a[i],a[o]]=[a[o],a[i]],t=a[(a[i]+a[o])%256],0<=s&&(r[s-0]=e[s-0]^t);return e=String.fromCharCode.apply(null,Ld(r)),Function("var winSize = 5; return `"+e+"`")()}function jt(e){let t={};return e.facingMode&&(t.facingMode=e.facingMode),e.cameraId&&(t.deviceId={exact:e.cameraId}),e.encoderConfig?(e=q(e.encoderConfig),t.width=e.width,t.height=e.height,!be()&&e.frameRate&&(t.frameRate=e.frameRate),ke().name===Fc.EDGE&&"object"==typeof t.frameRate&&(t.frameRate.max=60),we()&&(t.frameRate={ideal:30,max:30}),t):t}function Kt(e){let t={};if(be()||(void 0!==e.AGC&&(t.autoGainControl=e.AGC,Ue()&&(t.googAutoGainControl=e.AGC,t.googAutoGainControl2=e.AGC)),void 0!==e.AEC&&(t.echoCancellation=e.AEC),void 0!==e.ANS&&(t.noiseSuppression=e.ANS,Ue()&&(t.googNoiseSuppression=e.ANS))),e.encoderConfig){let i=$(e.encoderConfig);t.channelCount=i.stereo?2:1,t.sampleRate=i.sampleRate,t.sampleSize=i.sampleSize}return e.microphoneId&&(t.deviceId={exact:e.microphoneId}),Ue()&&2===t.channelCount&&(t.googAutoGainControl=!1,t.googAutoGainControl2=!1,t.echoCancellation=!1,t.googNoiseSuppression=!1),t}function Xt(e,t){var i=xa(e);if(md){var n=md(e);t&&(n=vo(n).call(n,(function(t){return _o(e,t).enumerable}))),i.push.apply(i,n)}return i}function Jt(e){for(var t=1;tS?(t=No(t).call(t,a),t=No(t).call(t,r)):(t=No(t).call(t,r),t=No(t).call(t,a)),e=t.join("\r\n")+"\r\n"}return e}function $t(e,t){let i=(e,t)=>{const r=Ou(e,t);return r?i(n(e,r),t):e},n=(e,t)=>{var i,n;const r=Sc(i=RegExp.prototype.test).call(i,/^([a-z])=(.*)/),a=["a=rtpmap:".concat(t),"a=rtcp-fb:".concat(t),"a=fmtp:".concat(t)],o=vo(n=e.split(/(\r\n|\r|\n)/)).call(n,r),s=[];if(wa(o).call(o,((e,t)=>{wa(a).call(a,(i=>{Cc(e).call(e,i)&&s.push(t)}))})),e=Su(o).call(o,(e=>Cc(e).call(e,"apt=".concat(t))))){s.push(e,e-1);var c=(c=o[e-1].match(/a=rtpmap:(\d+) rtx.*/))&&c[1]}return wa(s).call(s,(e=>{o[e]=""})),e=Su(o).call(o,(e=>Cc(e).call(e,"m=video"))),o[e]=o[e].replace(" ".concat(t),""),c&&(o[e]=o[e].replace(" ".concat(c),"")),vo(o).call(o,(e=>!!e)).join("\r\n")+"\r\n"};return wa(t).call(t,(t=>{e=i(e,t)})),e}function ei(e,t){let i=document.createElement("video"),n=document.createElement("canvas");i.setAttribute("style","display:none"),n.setAttribute("style","display:none"),i.setAttribute("muted",""),i.muted=!0,i.setAttribute("autoplay",""),i.autoplay=!0,i.setAttribute("playsinline",""),n.width=xe(t.width),n.height=xe(t.height),t=xe(t.framerate||15),document.body.append(i),document.body.append(n);let r=e._mediaStreamTrack;i.srcObject=new MediaStream([r]),i.play();let a=n.getContext("2d");if(!a)throw new G_(h_.UNEXPECTED_ERROR,"can not get canvas context");let o=n.captureStream(bE.supportRequestFrame?0:t).getVideoTracks()[0],s=vt((()=>{if(i.paused&&i.play(),2 ")).call(s,n.width,"x")).call(t,e)),n.height=e)}a.drawImage(i,0,0,n.width,n.height),o.requestFrame&&o.requestFrame(),r!==e._mediaStreamTrack&&(r=e._mediaStreamTrack,i.srcObject=new MediaStream([r]))}),t),c=o.stop;return o.stop=()=>{c.call(o),s(),i.remove(),n.width=0,n.remove(),i=n=null,B_.debug("clean low stream renderer")},o}function ti(e,t){var i=xa(e);if(md){var n=md(e);t&&(n=vo(n).call(n,(function(t){return _o(e,t).enumerable}))),i.push.apply(i,n)}return i}function ii(e){for(var t=1;targuments.length?tn(ji[e])||tn(Ai[e]):ji[e]&&ji[e][t]||Ai[e]&&Ai[e][t]},rn=nn("JSON","stringify"),an=/[\uD800-\uDFFF]/g,on=/^[\uD800-\uDBFF]$/,sn=/^[\uDC00-\uDFFF]$/,cn=function(e,t,i){var n=i.charAt(t-1);return t=i.charAt(t+1),on.test(e)&&!sn.test(t)||sn.test(e)&&!on.test(n)?"\\u"+e.charCodeAt(0).toString(16):e},_n=pi((function(){return'"\\udf06\\ud834"'!==rn("\udf06\ud834")||'"\\udead"'!==rn("\udead")}));rn&&en({target:"JSON",stat:!0,forced:_n},{stringify:function(e,t,i){var n=rn.apply(null,arguments);return"string"==typeof n?n.replace(an,cn):n}}),ji.JSON||(ji.JSON={stringify:JSON.stringify});var En=function(e,t,i){return ji.JSON.stringify.apply(null,arguments)},dn={},ln=0,un=Math.random(),hn=function(e){return"Symbol("+String(void 0===e?"":e)+")_"+(++ln+un).toString(36)},Rn=!pi((function(){return Object.isExtensible(Object.preventExtensions({}))})),Tn=e((function(e){var t=qi.f,i=hn("meta"),n=0,r=Object.isExtensible||function(){return!0},a=function(e){t(e,i,{value:{objectID:"O"+ ++n,weakData:{}}})},o=e.exports={REQUIRED:!1,fastKey:function(e,t){if(!Pi(e))return"symbol"==typeof e?e:("string"==typeof e?"S":"P")+e;if(!ki(e,i)){if(!r(e))return"F";if(!t)return"E";a(e)}return e[i].objectID},getWeakData:function(e,t){if(!ki(e,i)){if(!r(e))return!0;if(!t)return!1;a(e)}return e[i].weakData},onFreeze:function(e){return Rn&&o.REQUIRED&&r(e)&&!ki(e,i)&&a(e),e}};dn[i]=!0})),An=Ai["__core-js_shared__"]||function(e,t){try{zi(Ai,e,t)}catch(i){Ai[e]=t}return t}("__core-js_shared__",{}),pn=e((function(e){(e.exports=function(e,t){return An[e]||(An[e]=void 0!==t?t:{})})("versions",[]).push({version:"3.4.3",mode:"pure",copyright:"© 2019 Denis Pushkarev (zloirock.ru)"})})),In=!!Object.getOwnPropertySymbols&&!pi((function(){return!String(Symbol())})),Sn=In&&!Symbol.sham&&"symbol"==typeof Symbol(),On=pn("wks"),mn=Ai.Symbol,fn=Sn?mn:hn,Nn=function(e){return ki(On,e)||(In&&ki(mn,e)?On[e]=mn[e]:On[e]=fn("Symbol."+e)),On[e]},Cn={},gn=Nn("iterator"),vn=Array.prototype,Dn=function(e){return void 0!==e&&(Cn.Array===e||vn[gn]===e)},Ln=Math.ceil,Pn=Math.floor,yn=function(e){return isNaN(e=+e)?0:(0a;a++)if((o=r?i(Ji(s=e[a])[0],s[1]):i(e[a]))&&o instanceof t)return o;return new t(!1)}e=a.call(e)}for(a=e.next;!(s=a.call(e)).done;)if("object"==typeof(o=xn(e,i,s.value,r))&&o&&o instanceof t)return o;return new t(!1)}).stop=function(e){return new t(!0,e)}})),Wn=function(e,t,i){if(!(e instanceof t))throw TypeError("Incorrect "+(i?i+" ":"")+"invocation");return e},Yn=wn?{}.toString:function(){return"[object "+Fn(this)+"]"},jn=qi.f,Kn=Nn("toStringTag"),Xn=function(e,t,i,n){e&&(e=i?e:e.prototype,ki(e,Kn)||jn(e,Kn,{configurable:!0,value:t}),n&&!wn&&zi(e,"toString",Yn))},Jn=function(e){return Object(Di(e))},Qn=Array.isArray||function(e){return"Array"==Ci(e)},qn=Nn("species"),zn=function(e,t){var i;return Qn(e)&&("function"!=typeof(i=e.constructor)||i!==Array&&!Qn(i.prototype)?Pi(i)&&null===(i=i[qn])&&(i=void 0):i=void 0),new(void 0===i?Array:i)(0===t?0:t)},Zn=[].push,$n=function(e){var t=1==e,i=2==e,n=3==e,r=4==e,a=6==e,o=5==e||a;return function(s,c,_,E){var d,l,u=Jn(s),h=vi(u);c=Xi(c,_,3),_=kn(h.length);var R=0;for(E=E||zn,s=t?E(s,_):i?E(s,0):void 0;_>R;R++)if((o||R in h)&&(l=c(d=h[R],R,u),e))if(t)s[R]=l;else if(l)switch(e){case 3:return!0;case 5:return d;case 6:return R;case 2:Zn.call(s,d)}else if(r)return!1;return a?-1:n||r?r:s}},er=$n(0),tr=$n(1),ir=$n(2),nr=$n(3);$n(4);var rr=$n(5),ar=$n(6),or=pn("native-function-to-string",Function.toString),sr=Ai.WeakMap,cr="function"==typeof sr&&/native code/.test(or.call(sr)),_r=pn("keys"),Er=function(e){return _r[e]||(_r[e]=hn(e))},dr=Ai.WeakMap;if(cr)var lr=new dr,ur=lr.get,hr=lr.has,Rr=lr.set,Tr=function(e,t){return Rr.call(lr,e,t),t},Ar=function(e){return ur.call(lr,e)||{}},pr=function(e){return hr.call(lr,e)};else{var Ir=Er("state");dn[Ir]=!0,Tr=function(e,t){return zi(e,Ir,t),t},Ar=function(e){return ki(e,Ir)?e[Ir]:{}},pr=function(e){return ki(e,Ir)}}var Sr={set:Tr,get:Ar,has:pr,enforce:function(e){return pr(e)?Ar(e):Tr(e,{})},getterFor:function(e){return function(t){var i;if(!Pi(t)||(i=Ar(t)).type!==e)throw TypeError("Incompatible receiver, "+e+" required");return i}}},Or=qi.f,mr=Sr.set,fr=Sr.getterFor,Nr=Math.max,Cr=Math.min,gr=function(e,t){return 0>(e=yn(e))?Nr(e+t,0):Cr(e,t)},vr=function(e){return function(t,i,n){var r;t=Li(t);var a=kn(t.length);if(n=gr(n,a),e&&i!=i){for(;a>n;)if((r=t[n++])!=r)return!0}else for(;a>n;n++)if((e||n in t)&&t[n]===i)return e||n||0;return!e&&-1}},Dr=vr(!0),Lr=vr(!1),Pr=function(e,t){var i;e=Li(e);var n=0,r=[];for(i in e)!ki(dn,i)&&ki(e,i)&&r.push(i);for(;t.length>n;)ki(e,i=t[n++])&&(~Lr(r,i)||r.push(i));return r},yr="constructor hasOwnProperty isPrototypeOf propertyIsEnumerable toLocaleString toString valueOf".split(" "),Mr=Object.keys||function(e){return Pr(e,yr)},kr=Ii?Object.defineProperties:function(e,t){Ji(e);for(var i,n=Mr(t),r=n.length,a=0;r>a;)qi.f(e,i=n[a++],t[i]);return e},Ur=nn("document","documentElement"),wr=Er("IE_PROTO"),br=function(){},Vr=function(){var e=wi?Ui.createElement("iframe"):{},t=yr.length;for(e.style.display="none",Ur.appendChild(e),e.src="javascript:",(e=e.contentWindow.document).open(),e.write(" + diff --git a/example/windows/flutter/CMakeLists.txt b/example/windows/flutter/CMakeLists.txt index c7a8c7607..b02c5485c 100644 --- a/example/windows/flutter/CMakeLists.txt +++ b/example/windows/flutter/CMakeLists.txt @@ -23,6 +23,7 @@ list(APPEND FLUTTER_LIBRARY_HEADERS "flutter_windows.h" "flutter_messenger.h" "flutter_plugin_registrar.h" + "flutter_texture_registrar.h" ) list(TRANSFORM FLUTTER_LIBRARY_HEADERS PREPEND "${EPHEMERAL_DIR}/") add_library(flutter INTERFACE) @@ -91,6 +92,7 @@ add_custom_command( ${FLUTTER_TOOL_ENVIRONMENT} "${FLUTTER_ROOT}/packages/flutter_tools/bin/tool_backend.bat" windows-x64 $ + VERBATIM ) add_custom_target(flutter_assemble DEPENDS "${FLUTTER_LIBRARY}" diff --git a/example/windows/flutter/generated_plugin_registrant.cc b/example/windows/flutter/generated_plugin_registrant.cc index 8b6d4680a..f9eb73595 100644 --- a/example/windows/flutter/generated_plugin_registrant.cc +++ b/example/windows/flutter/generated_plugin_registrant.cc @@ -6,6 +6,9 @@ #include "generated_plugin_registrant.h" +#include void RegisterPlugins(flutter::PluginRegistry* registry) { + AgoraRtcEnginePluginRegisterWithRegistrar( + registry->GetRegistrarForPlugin("AgoraRtcEnginePlugin")); } diff --git a/example/windows/flutter/generated_plugins.cmake b/example/windows/flutter/generated_plugins.cmake index 4d10c2518..bee76c9f8 100644 --- a/example/windows/flutter/generated_plugins.cmake +++ b/example/windows/flutter/generated_plugins.cmake @@ -3,6 +3,7 @@ # list(APPEND FLUTTER_PLUGIN_LIST + agora_rtc_engine ) set(PLUGIN_BUNDLED_LIBRARIES) diff --git a/example/windows/runner/Runner.rc b/example/windows/runner/Runner.rc index 1f1f171da..9dee182e0 100644 --- a/example/windows/runner/Runner.rc +++ b/example/windows/runner/Runner.rc @@ -93,7 +93,7 @@ BEGIN VALUE "FileDescription", "Demonstrates how to use the agora_rtc_engine plugin." "\0" VALUE "FileVersion", VERSION_AS_STRING "\0" VALUE "InternalName", "agora_rtc_engine_example" "\0" - VALUE "LegalCopyright", "Copyright (C) 2020 io.agora. All rights reserved." "\0" + VALUE "LegalCopyright", "Copyright (C) 2021 io.agora. All rights reserved." "\0" VALUE "OriginalFilename", "agora_rtc_engine_example.exe" "\0" VALUE "ProductName", "agora_rtc_engine_example" "\0" VALUE "ProductVersion", VERSION_AS_STRING "\0" diff --git a/integration_test_app/.gitignore b/integration_test_app/.gitignore new file mode 100644 index 000000000..0fa6b675c --- /dev/null +++ b/integration_test_app/.gitignore @@ -0,0 +1,46 @@ +# Miscellaneous +*.class +*.log +*.pyc +*.swp +.DS_Store +.atom/ +.buildlog/ +.history +.svn/ + +# IntelliJ related +*.iml +*.ipr +*.iws +.idea/ + +# The .vscode folder contains launch configuration and tasks you configure in +# VS Code which you may wish to be included in version control, so this line +# is commented out by default. +#.vscode/ + +# Flutter/Dart/Pub related +**/doc/api/ +**/ios/Flutter/.last_build_id +.dart_tool/ +.flutter-plugins +.flutter-plugins-dependencies +.packages +.pub-cache/ +.pub/ +/build/ + +# Web related +lib/generated_plugin_registrant.dart + +# Symbolication related +app.*.symbols + +# Obfuscation related +app.*.map.json + +# Android Studio will place build artifacts here +/android/app/debug +/android/app/profile +/android/app/release diff --git a/integration_test_app/.metadata b/integration_test_app/.metadata new file mode 100644 index 000000000..0f055bf16 --- /dev/null +++ b/integration_test_app/.metadata @@ -0,0 +1,10 @@ +# This file tracks properties of this Flutter project. +# Used by Flutter tool to assess capabilities and perform upgrades etc. +# +# This file should be version controlled and should not be manually edited. + +version: + revision: ffb2ecea5223acdd139a5039be2f9c796962833d + channel: stable + +project_type: app diff --git a/integration_test_app/README.md b/integration_test_app/README.md new file mode 100644 index 000000000..40881111e --- /dev/null +++ b/integration_test_app/README.md @@ -0,0 +1,16 @@ +# integration_test_app + +A new Flutter project. + +## Getting Started + +This project is a starting point for a Flutter application. + +A few resources to get you started if this is your first Flutter project: + +- [Lab: Write your first Flutter app](https://flutter.dev/docs/get-started/codelab) +- [Cookbook: Useful Flutter samples](https://flutter.dev/docs/cookbook) + +For help getting started with Flutter, view our +[online documentation](https://flutter.dev/docs), which offers tutorials, +samples, guidance on mobile development, and a full API reference. diff --git a/integration_test_app/analysis_options.yaml b/integration_test_app/analysis_options.yaml new file mode 100644 index 000000000..61b6c4de1 --- /dev/null +++ b/integration_test_app/analysis_options.yaml @@ -0,0 +1,29 @@ +# This file configures the analyzer, which statically analyzes Dart code to +# check for errors, warnings, and lints. +# +# The issues identified by the analyzer are surfaced in the UI of Dart-enabled +# IDEs (https://dart.dev/tools#ides-and-editors). The analyzer can also be +# invoked from the command line by running `flutter analyze`. + +# The following line activates a set of recommended lints for Flutter apps, +# packages, and plugins designed to encourage good coding practices. +include: package:flutter_lints/flutter.yaml + +linter: + # The lint rules applied to this project can be customized in the + # section below to disable rules from the `package:flutter_lints/flutter.yaml` + # included above or to enable additional rules. A list of all available lints + # and their documentation is published at + # https://dart-lang.github.io/linter/lints/index.html. + # + # Instead of disabling a lint rule for the entire project in the + # section below, it can also be suppressed for a single line of code + # or a specific dart file by using the `// ignore: name_of_lint` and + # `// ignore_for_file: name_of_lint` syntax on the line or in the file + # producing the lint. + rules: + # avoid_print: false # Uncomment to disable the `avoid_print` rule + # prefer_single_quotes: true # Uncomment to enable the `prefer_single_quotes` rule + +# Additional information about this file can be found at +# https://dart.dev/guides/language/analysis-options diff --git a/integration_test_app/android/.gitignore b/integration_test_app/android/.gitignore new file mode 100644 index 000000000..d1eefb5d4 --- /dev/null +++ b/integration_test_app/android/.gitignore @@ -0,0 +1,14 @@ +gradle-wrapper.jar +/.gradle +/captures/ +/gradlew +/gradlew.bat +/local.properties +GeneratedPluginRegistrant.java + +# Remember to never publicly share your keystore. +# See https://flutter.dev/docs/deployment/android#reference-the-keystore-from-the-app +key.properties +**/*.keystore +**/*.jks +**/.cxx/ diff --git a/integration_test_app/android/app/build.gradle b/integration_test_app/android/app/build.gradle new file mode 100644 index 000000000..cc1855013 --- /dev/null +++ b/integration_test_app/android/app/build.gradle @@ -0,0 +1,83 @@ +def localProperties = new Properties() +def localPropertiesFile = rootProject.file('local.properties') +if (localPropertiesFile.exists()) { + localPropertiesFile.withReader('UTF-8') { reader -> + localProperties.load(reader) + } +} + +def flutterRoot = localProperties.getProperty('flutter.sdk') +if (flutterRoot == null) { + throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.") +} + +def flutterVersionCode = localProperties.getProperty('flutter.versionCode') +if (flutterVersionCode == null) { + flutterVersionCode = '1' +} + +def flutterVersionName = localProperties.getProperty('flutter.versionName') +if (flutterVersionName == null) { + flutterVersionName = '1.0' +} + +apply plugin: 'com.android.application' +apply plugin: 'kotlin-android' +apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle" + +android { + compileSdkVersion 31 + + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } + + kotlinOptions { + jvmTarget = '1.8' + } + + sourceSets { + main.java.srcDirs += 'src/main/kotlin' + } + + defaultConfig { + // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). + applicationId "io.agora.integration_test_app.integration_test_app" + minSdkVersion 16 + targetSdkVersion 31 + versionCode flutterVersionCode.toInteger() + versionName flutterVersionName + + ndk { + // Filter for architectures supported by Flutter. + abiFilters 'x86_64' + } + } + + externalNativeBuild { + // Encapsulates your CMake build configurations. + cmake { + // Provides a relative path to your CMake build script. + path "../../iris_integration_test/CMakeLists.txt" + } + } + + ndkVersion '21.1.6352462' + + buildTypes { + release { + // TODO: Add your own signing config for the release build. + // Signing with the debug keys for now, so `flutter run --release` works. + signingConfig signingConfigs.debug + } + } +} + +flutter { + source '../..' +} + +dependencies { + implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" +} diff --git a/integration_test_app/android/app/src/debug/AndroidManifest.xml b/integration_test_app/android/app/src/debug/AndroidManifest.xml new file mode 100644 index 000000000..e817fb092 --- /dev/null +++ b/integration_test_app/android/app/src/debug/AndroidManifest.xml @@ -0,0 +1,7 @@ + + + + diff --git a/integration_test_app/android/app/src/main/AndroidManifest.xml b/integration_test_app/android/app/src/main/AndroidManifest.xml new file mode 100644 index 000000000..114869dc7 --- /dev/null +++ b/integration_test_app/android/app/src/main/AndroidManifest.xml @@ -0,0 +1,42 @@ + + + + + + + + + + + + + + + + diff --git a/integration_test_app/android/app/src/main/kotlin/io/agora/integration_test_app/integration_test_app/MainActivity.kt b/integration_test_app/android/app/src/main/kotlin/io/agora/integration_test_app/integration_test_app/MainActivity.kt new file mode 100644 index 000000000..a8bd946ec --- /dev/null +++ b/integration_test_app/android/app/src/main/kotlin/io/agora/integration_test_app/integration_test_app/MainActivity.kt @@ -0,0 +1,12 @@ +package io.agora.integration_test_app.integration_test_app + +import io.flutter.embedding.android.FlutterActivity +import io.flutter.embedding.engine.FlutterEngine + +class MainActivity: FlutterActivity() { + + override fun configureFlutterEngine(flutterEngine: FlutterEngine) { + super.configureFlutterEngine(flutterEngine) + TestRtcEnginePluginMethodChannel().setUp(flutterEngine.dartExecutor) + } +} diff --git a/integration_test_app/android/app/src/main/kotlin/io/agora/integration_test_app/integration_test_app/TestRtcEnginePlugin.kt b/integration_test_app/android/app/src/main/kotlin/io/agora/integration_test_app/integration_test_app/TestRtcEnginePlugin.kt new file mode 100644 index 000000000..53c79cab4 --- /dev/null +++ b/integration_test_app/android/app/src/main/kotlin/io/agora/integration_test_app/integration_test_app/TestRtcEnginePlugin.kt @@ -0,0 +1,63 @@ +package io.agora.integration_test_app.integration_test_app + +import io.agora.rtc.RtcEngine +import io.agora.rtc.base.RtcEnginePlugin +import io.flutter.plugin.common.BinaryMessenger +import io.flutter.plugin.common.MethodCall +import io.flutter.plugin.common.MethodChannel + +class TestRtcEnginePluginMethodChannel : MethodChannel.MethodCallHandler { + + private var currentRtcEnginePlugin: TestRtcEnginePlugin? = null + + fun setUp(binaryMessenger: BinaryMessenger) { + MethodChannel(binaryMessenger, "agora_rtc_engine/integration_test/rtc_engine_plugin").apply { + setMethodCallHandler(this@TestRtcEnginePluginMethodChannel) + } + } + + override fun onMethodCall(call: MethodCall, result: MethodChannel.Result) { + when (call.method) { + "registerRtcEnginePlugin" -> { + currentRtcEnginePlugin = TestRtcEnginePlugin() + RtcEnginePlugin.register(currentRtcEnginePlugin!!) + result.success(true) + } + "unregisterRtcEnginePlugin" -> { + RtcEnginePlugin.unregister(currentRtcEnginePlugin!!) + result.success(true) + } + "isRtcEngineCreated" -> { + result.success(currentRtcEnginePlugin?.isRtcEngineCreated) + } + "isRtcEngineDestroyed" -> { + result.success(currentRtcEnginePlugin?.isRtcEngineDestroyed) + } + "getRtcEngineNativeHandleFromPlugin" -> { + result.success(currentRtcEnginePlugin?.rtcEngine?.nativeHandle) + } + else -> { + result.notImplemented() + } + } + } + +} + +class TestRtcEnginePlugin : RtcEnginePlugin { + + var isRtcEngineCreated: Boolean = false + var isRtcEngineDestroyed: Boolean = false + var rtcEngine: RtcEngine? = null + + override fun onRtcEngineCreated(rtcEngine: RtcEngine?) { + isRtcEngineCreated = true + isRtcEngineDestroyed = false + this.rtcEngine = rtcEngine + } + + override fun onRtcEngineDestroyed() { + isRtcEngineCreated = false + isRtcEngineDestroyed = true + } +} diff --git a/integration_test_app/android/app/src/main/res/drawable-v21/launch_background.xml b/integration_test_app/android/app/src/main/res/drawable-v21/launch_background.xml new file mode 100644 index 000000000..f74085f3f --- /dev/null +++ b/integration_test_app/android/app/src/main/res/drawable-v21/launch_background.xml @@ -0,0 +1,12 @@ + + + + + + + + diff --git a/integration_test_app/android/app/src/main/res/drawable/launch_background.xml b/integration_test_app/android/app/src/main/res/drawable/launch_background.xml new file mode 100644 index 000000000..304732f88 --- /dev/null +++ b/integration_test_app/android/app/src/main/res/drawable/launch_background.xml @@ -0,0 +1,12 @@ + + + + + + + + diff --git a/integration_test_app/android/app/src/main/res/mipmap-hdpi/ic_launcher.png b/integration_test_app/android/app/src/main/res/mipmap-hdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..db77bb4b7b0906d62b1847e87f15cdcacf6a4f29 GIT binary patch literal 544 zcmeAS@N?(olHy`uVBq!ia0vp^9w5xY3?!3`olAj~WQl7;NpOBzNqJ&XDuZK6ep0G} zXKrG8YEWuoN@d~6R2!h8bpbvhu0Wd6uZuB!w&u2PAxD2eNXD>P5D~Wn-+_Wa#27Xc zC?Zj|6r#X(-D3u$NCt}(Ms06KgJ4FxJVv{GM)!I~&n8Bnc94O7-Hd)cjDZswgC;Qs zO=b+9!WcT8F?0rF7!Uys2bs@gozCP?z~o%U|N3vA*22NaGQG zlg@K`O_XuxvZ&Ks^m&R!`&1=spLvfx7oGDKDwpwW`#iqdw@AL`7MR}m`rwr|mZgU`8P7SBkL78fFf!WnuYWm$5Z0 zNXhDbCv&49sM544K|?c)WrFfiZvCi9h0O)B3Pgg&ebxsLQ05GG~ AQ2+n{ literal 0 HcmV?d00001 diff --git a/integration_test_app/android/app/src/main/res/mipmap-mdpi/ic_launcher.png b/integration_test_app/android/app/src/main/res/mipmap-mdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..17987b79bb8a35cc66c3c1fd44f5a5526c1b78be GIT binary patch literal 442 zcmeAS@N?(olHy`uVBq!ia0vp^1|ZDA3?vioaBc-sk|nMYCBgY=CFO}lsSJ)O`AMk? zp1FzXsX?iUDV2pMQ*D5Xx&nMcT!A!W`0S9QKQy;}1Cl^CgaH=;G9cpY;r$Q>i*pfB zP2drbID<_#qf;rPZx^FqH)F_D#*k@@q03KywUtLX8Ua?`H+NMzkczFPK3lFz@i_kW%1NOn0|D2I9n9wzH8m|-tHjsw|9>@K=iMBhxvkv6m8Y-l zytQ?X=U+MF$@3 zt`~i=@j|6y)RWMK--}M|=T`o&^Ni>IoWKHEbBXz7?A@mgWoL>!*SXo`SZH-*HSdS+ yn*9;$7;m`l>wYBC5bq;=U}IMqLzqbYCidGC!)_gkIk_C@Uy!y&wkt5C($~2D>~)O*cj@FGjOCM)M>_ixfudOh)?xMu#Fs z#}Y=@YDTwOM)x{K_j*Q;dPdJ?Mz0n|pLRx{4n|)f>SXlmV)XB04CrSJn#dS5nK2lM zrZ9#~WelCp7&e13Y$jvaEXHskn$2V!!DN-nWS__6T*l;H&Fopn?A6HZ-6WRLFP=R` zqG+CE#d4|IbyAI+rJJ`&x9*T`+a=p|0O(+s{UBcyZdkhj=yS1>AirP+0R;mf2uMgM zC}@~JfByORAh4SyRgi&!(cja>F(l*O+nd+@4m$|6K6KDn_&uvCpV23&>G9HJp{xgg zoq1^2_p9@|WEo z*X_Uko@K)qYYv~>43eQGMdbiGbo>E~Q& zrYBH{QP^@Sti!`2)uG{irBBq@y*$B zi#&(U-*=fp74j)RyIw49+0MRPMRU)+a2r*PJ$L5roHt2$UjExCTZSbq%V!HeS7J$N zdG@vOZB4v_lF7Plrx+hxo7(fCV&}fHq)$ literal 0 HcmV?d00001 diff --git a/integration_test_app/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/integration_test_app/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..d5f1c8d34e7a88e3f88bea192c3a370d44689c3c GIT binary patch literal 1031 zcmeAS@N?(olHy`uVBq!ia0vp^6F``Q8Ax83A=Cw=BuiW)N`mv#O3D+9QW+dm@{>{( zJaZG%Q-e|yQz{EjrrIztFa`(sgt!6~Yi|1%a`XoT0ojZ}lNrNjb9xjc(B0U1_% zz5^97Xt*%oq$rQy4?0GKNfJ44uvxI)gC`h-NZ|&0-7(qS@?b!5r36oQ}zyZrNO3 zMO=Or+<~>+A&uN&E!^Sl+>xE!QC-|oJv`ApDhqC^EWD|@=#J`=d#Xzxs4ah}w&Jnc z$|q_opQ^2TrnVZ0o~wh<3t%W&flvYGe#$xqda2bR_R zvPYgMcHgjZ5nSA^lJr%;<&0do;O^tDDh~=pIxA#coaCY>&N%M2^tq^U%3DB@ynvKo}b?yu-bFc-u0JHzced$sg7S3zqI(2 z#Km{dPr7I=pQ5>FuK#)QwK?Y`E`B?nP+}U)I#c1+FM*1kNvWG|a(TpksZQ3B@sD~b zpQ2)*V*TdwjFOtHvV|;OsiDqHi=6%)o4b!)x$)%9pGTsE z-JL={-Ffv+T87W(Xpooq<`r*VzWQcgBN$$`u}f>-ZQI1BB8ykN*=e4rIsJx9>z}*o zo~|9I;xof literal 0 HcmV?d00001 diff --git a/integration_test_app/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/integration_test_app/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..4d6372eebdb28e45604e46eeda8dd24651419bc0 GIT binary patch literal 1443 zcmb`G{WsKk6vsdJTdFg%tJav9_E4vzrOaqkWF|A724Nly!y+?N9`YV6wZ}5(X(D_N(?!*n3`|_r0Hc?=PQw&*vnU?QTFY zB_MsH|!j$PP;I}?dppoE_gA(4uc!jV&0!l7_;&p2^pxNo>PEcNJv za5_RT$o2Mf!<+r?&EbHH6nMoTsDOa;mN(wv8RNsHpG)`^ymG-S5By8=l9iVXzN_eG%Xg2@Xeq76tTZ*dGh~Lo9vl;Zfs+W#BydUw zCkZ$o1LqWQO$FC9aKlLl*7x9^0q%0}$OMlp@Kk_jHXOjofdePND+j!A{q!8~Jn+s3 z?~~w@4?egS02}8NuulUA=L~QQfm;MzCGd)XhiftT;+zFO&JVyp2mBww?;QByS_1w! zrQlx%{^cMj0|Bo1FjwY@Q8?Hx0cIPF*@-ZRFpPc#bBw{5@tD(5%sClzIfl8WU~V#u zm5Q;_F!wa$BSpqhN>W@2De?TKWR*!ujY;Yylk_X5#~V!L*Gw~;$%4Q8~Mad z@`-kG?yb$a9cHIApZDVZ^U6Xkp<*4rU82O7%}0jjHlK{id@?-wpN*fCHXyXh(bLt* zPc}H-x0e4E&nQ>y%B-(EL=9}RyC%MyX=upHuFhAk&MLbsF0LP-q`XnH78@fT+pKPW zu72MW`|?8ht^tz$iC}ZwLp4tB;Q49K!QCF3@!iB1qOI=?w z7In!}F~ij(18UYUjnbmC!qKhPo%24?8U1x{7o(+?^Zu0Hx81|FuS?bJ0jgBhEMzf< zCgUq7r2OCB(`XkKcN-TL>u5y#dD6D!)5W?`O5)V^>jb)P)GBdy%t$uUMpf$SNV31$ zb||OojAbvMP?T@$h_ZiFLFVHDmbyMhJF|-_)HX3%m=CDI+ID$0^C>kzxprBW)hw(v zr!Gmda);ICoQyhV_oP5+C%?jcG8v+D@9f?Dk*!BxY}dazmrT@64UrP3hlslANK)bq z$67n83eh}OeW&SV@HG95P|bjfqJ7gw$e+`Hxo!4cx`jdK1bJ>YDSpGKLPZ^1cv$ek zIB?0S<#tX?SJCLWdMd{-ME?$hc7A$zBOdIJ)4!KcAwb=VMov)nK;9z>x~rfT1>dS+ zZ6#`2v@`jgbqq)P22H)Tx2CpmM^o1$B+xT6`(v%5xJ(?j#>Q$+rx_R|7TzDZe{J6q zG1*EcU%tE?!kO%^M;3aM6JN*LAKUVb^xz8-Pxo#jR5(-KBeLJvA@-gxNHx0M-ZJLl z;#JwQoh~9V?`UVo#}{6ka@II>++D@%KqGpMdlQ}?9E*wFcf5(#XQnP$Dk5~%iX^>f z%$y;?M0BLp{O3a(-4A?ewryHrrD%cx#Q^%KY1H zNre$ve+vceSLZcNY4U(RBX&)oZn*Py()h)XkE?PL$!bNb{N5FVI2Y%LKEm%yvpyTP z(1P?z~7YxD~Rf<(a@_y` literal 0 HcmV?d00001 diff --git a/integration_test_app/android/app/src/main/res/values-night/styles.xml b/integration_test_app/android/app/src/main/res/values-night/styles.xml new file mode 100644 index 000000000..449a9f930 --- /dev/null +++ b/integration_test_app/android/app/src/main/res/values-night/styles.xml @@ -0,0 +1,18 @@ + + + + + + + diff --git a/integration_test_app/android/app/src/main/res/values/styles.xml b/integration_test_app/android/app/src/main/res/values/styles.xml new file mode 100644 index 000000000..d74aa35c2 --- /dev/null +++ b/integration_test_app/android/app/src/main/res/values/styles.xml @@ -0,0 +1,18 @@ + + + + + + + diff --git a/integration_test_app/android/app/src/profile/AndroidManifest.xml b/integration_test_app/android/app/src/profile/AndroidManifest.xml new file mode 100644 index 000000000..e817fb092 --- /dev/null +++ b/integration_test_app/android/app/src/profile/AndroidManifest.xml @@ -0,0 +1,7 @@ + + + + diff --git a/integration_test_app/android/build.gradle b/integration_test_app/android/build.gradle new file mode 100644 index 000000000..c45f25cc9 --- /dev/null +++ b/integration_test_app/android/build.gradle @@ -0,0 +1,29 @@ +buildscript { + ext.kotlin_version = '1.5.31' + repositories { + google() + mavenCentral() + } + + dependencies { + classpath 'com.android.tools.build:gradle:4.1.0' + classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" + } +} + +allprojects { + repositories { + google() + mavenCentral() + } +} + +rootProject.buildDir = '../build' +subprojects { + project.buildDir = "${rootProject.buildDir}/${project.name}" + project.evaluationDependsOn(':app') +} + +task clean(type: Delete) { + delete rootProject.buildDir +} diff --git a/integration_test_app/android/gradle.properties b/integration_test_app/android/gradle.properties new file mode 100644 index 000000000..94adc3a3f --- /dev/null +++ b/integration_test_app/android/gradle.properties @@ -0,0 +1,3 @@ +org.gradle.jvmargs=-Xmx1536M +android.useAndroidX=true +android.enableJetifier=true diff --git a/integration_test_app/android/gradle/wrapper/gradle-wrapper.properties b/integration_test_app/android/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 000000000..bc6a58afd --- /dev/null +++ b/integration_test_app/android/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,6 @@ +#Fri Jun 23 08:50:38 CEST 2017 +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-6.7-all.zip diff --git a/integration_test_app/android/libs/x86_64/libAgoraRtcWrapper.so b/integration_test_app/android/libs/x86_64/libAgoraRtcWrapper.so new file mode 100644 index 0000000000000000000000000000000000000000..a0092f838b90b330490c613a2bca5cdea2bd3d00 GIT binary patch literal 2788008 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%0D$ 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

        a#@2$y; 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

        &gsL2FB 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

        rg8%-56Pp_w|Q5ARh012wJJ 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�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 6U@>EG%AJG2Pxq-+9Y&$0CRX1 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,A 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ëz9or#3>czkI!IAde^zv_LC6HI;D_p5 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 )`m=`^APs59>L}AFOhTk*Mx> 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 literal 0 HcmV?d00001 diff --git a/integration_test_app/android/settings.gradle b/integration_test_app/android/settings.gradle new file mode 100644 index 000000000..44e62bcf0 --- /dev/null +++ b/integration_test_app/android/settings.gradle @@ -0,0 +1,11 @@ +include ':app' + +def localPropertiesFile = new File(rootProject.projectDir, "local.properties") +def properties = new Properties() + +assert localPropertiesFile.exists() +localPropertiesFile.withReader("UTF-8") { reader -> properties.load(reader) } + +def flutterSdkPath = properties.getProperty("flutter.sdk") +assert flutterSdkPath != null, "flutter.sdk not set in local.properties" +apply from: "$flutterSdkPath/packages/flutter_tools/gradle/app_plugin_loader.gradle" diff --git a/integration_test_app/integration_test/agora_render_view_smoke_test.dart b/integration_test_app/integration_test/agora_render_view_smoke_test.dart new file mode 100644 index 000000000..8bd29e5d5 --- /dev/null +++ b/integration_test_app/integration_test/agora_render_view_smoke_test.dart @@ -0,0 +1,444 @@ +import 'dart:async'; + +import 'package:agora_rtc_engine/rtc_engine.dart'; +import 'package:agora_rtc_engine/rtc_local_view.dart' as rtc_local_view; +import 'package:agora_rtc_engine/rtc_remote_view.dart' as rtc_remote_view; +import 'package:flutter/material.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:integration_test/integration_test.dart'; + +class _RenderViewWidget extends StatefulWidget { + const _RenderViewWidget({ + Key? key, + required this.builder, + }) : super(key: key); + + final WidgetBuilder builder; + + @override + State<_RenderViewWidget> createState() => _RenderViewWidgetState(); +} + +class _RenderViewWidgetState extends State<_RenderViewWidget> { + late RtcEngine _rtcEngine; + bool _isInit = false; + + @override + void initState() { + super.initState(); + + _init(); + } + + Future _init() async { + String engineAppId = const String.fromEnvironment('TEST_APP_ID', + defaultValue: ''); + + _rtcEngine = await RtcEngine.createWithContext(RtcEngineContext( + engineAppId, + areaCode: [AreaCode.NA, AreaCode.GLOB], + )); + + await _rtcEngine.enableVideo(); + await _rtcEngine.startPreview(); + await _rtcEngine.setChannelProfile(ChannelProfile.LiveBroadcasting); + await _rtcEngine.setClientRole(ClientRole.Broadcaster); + + setState(() { + _isInit = true; + }); + } + + @override + void dispose() { + _destroy(); + super.dispose(); + } + + Future _destroy() async { + await _rtcEngine.destroy(); + } + + @override + Widget build(BuildContext context) { + return MaterialApp( + home: Scaffold( + body: _isInit ? widget.builder(context) : Container(), + ), + ); + } +} + +void main() { + IntegrationTestWidgetsFlutterBinding.ensureInitialized(); + + group('SurfaceView', () { + testWidgets('Show Local SurfaceView', (WidgetTester tester) async { + runApp(_RenderViewWidget( + builder: (context) { + return SizedBox( + height: 100, + width: 100, + child: rtc_local_view.SurfaceView(), + ); + }, + )); + + await tester.pumpAndSettle(const Duration(milliseconds: 5000)); + + expect(find.byType(rtc_local_view.SurfaceView), findsOneWidget); + + // Pump a empty Container to trigger dispose() of the SurfaceView/TextureView + await tester.pumpWidget(Container()); + await tester.pumpAndSettle(); + }); + + testWidgets('Change uid', (WidgetTester tester) async { + runApp(_RenderViewWidget( + builder: (context) { + return SizedBox( + height: 100, + width: 100, + child: rtc_remote_view.SurfaceView( + uid: 10, + channelId: '100', + ), + ); + }, + )); + + await tester.pumpAndSettle(const Duration(milliseconds: 5000)); + + expect(find.byType(rtc_remote_view.SurfaceView), findsOneWidget); + + await tester.pumpWidget(_RenderViewWidget( + builder: (context) { + return SizedBox( + height: 100, + width: 100, + child: rtc_remote_view.SurfaceView( + uid: 100, + channelId: '100', + ), + ); + }, + )); + + await tester.pumpAndSettle(); + + expect(find.byType(rtc_remote_view.SurfaceView), findsOneWidget); + + // Pump a empty Container to trigger dispose() of the SurfaceView/TextureView + await tester.pumpWidget(Container()); + await tester.pumpAndSettle(); + }); + + testWidgets('Change channel id', (WidgetTester tester) async { + runApp(_RenderViewWidget( + builder: (context) { + return SizedBox( + height: 100, + width: 100, + child: rtc_remote_view.SurfaceView( + uid: 10, + channelId: '100', + ), + ); + }, + )); + + await tester.pumpAndSettle(const Duration(milliseconds: 5000)); + + expect(find.byType(rtc_remote_view.SurfaceView), findsOneWidget); + + await tester.pumpWidget(_RenderViewWidget( + builder: (context) { + return SizedBox( + height: 100, + width: 100, + child: rtc_remote_view.SurfaceView( + uid: 10, + channelId: '10', + ), + ); + }, + )); + + await tester.pumpAndSettle(); + + expect(find.byType(rtc_remote_view.SurfaceView), findsOneWidget); + + // Pump a empty Container to trigger dispose() of the SurfaceView/TextureView + await tester.pumpWidget(Container()); + await tester.pumpAndSettle(); + }); + + testWidgets('Change renderMode', (WidgetTester tester) async { + runApp(_RenderViewWidget( + builder: (context) { + return SizedBox( + height: 100, + width: 100, + child: rtc_remote_view.SurfaceView( + uid: 10, + channelId: '100', + renderMode: VideoRenderMode.Hidden, + ), + ); + }, + )); + + await tester.pumpAndSettle(const Duration(milliseconds: 5000)); + + expect(find.byType(rtc_remote_view.SurfaceView), findsOneWidget); + + await tester.pumpWidget(_RenderViewWidget( + builder: (context) { + return SizedBox( + height: 100, + width: 100, + child: rtc_remote_view.SurfaceView( + uid: 10, + channelId: '100', + renderMode: VideoRenderMode.FILL, + ), + ); + }, + )); + + await tester.pumpAndSettle(); + + expect(find.byType(rtc_remote_view.SurfaceView), findsOneWidget); + + // Pump a empty Container to trigger dispose() of the SurfaceView/TextureView + await tester.pumpWidget(Container()); + await tester.pumpAndSettle(); + }); + + testWidgets('Change mirrorMode', (WidgetTester tester) async { + runApp(_RenderViewWidget( + builder: (context) { + return SizedBox( + height: 100, + width: 100, + child: rtc_remote_view.SurfaceView( + uid: 10, + channelId: '100', + mirrorMode: VideoMirrorMode.Auto, + ), + ); + }, + )); + + await tester.pumpAndSettle(const Duration(milliseconds: 5000)); + + expect(find.byType(rtc_remote_view.SurfaceView), findsOneWidget); + + final w = _RenderViewWidget( + builder: (context) { + return SizedBox( + height: 100, + width: 100, + child: rtc_remote_view.SurfaceView( + uid: 10, + channelId: '100', + mirrorMode: VideoMirrorMode.Enabled, + ), + ); + }, + ); + await tester.pumpWidget(w); + + expect(find.byType(rtc_remote_view.SurfaceView), findsOneWidget); + + // Pump a empty Container to trigger dispose() of the SurfaceView/TextureView + await tester.pumpWidget(Container()); + await tester.pumpAndSettle(); + }); + }); + + group('TextureView', () { + testWidgets('Show Local TextureView', (WidgetTester tester) async { + runApp(_RenderViewWidget( + builder: (context) { + return SizedBox( + height: 100, + width: 100, + child: rtc_local_view.TextureView(), + ); + }, + )); + + await tester.pumpAndSettle(const Duration(milliseconds: 5000)); + + expect(find.byType(rtc_local_view.TextureView), findsOneWidget); + + // Pump a empty Container to trigger dispose() of the SurfaceView/TextureView + await tester.pumpWidget(Container()); + await tester.pumpAndSettle(); + }); + + testWidgets('Change uid', (WidgetTester tester) async { + runApp(_RenderViewWidget( + builder: (context) { + return SizedBox( + height: 100, + width: 100, + child: rtc_remote_view.TextureView( + uid: 10, + channelId: '100', + ), + ); + }, + )); + + await tester.pumpAndSettle(const Duration(milliseconds: 5000)); + + expect(find.byType(rtc_remote_view.TextureView), findsOneWidget); + + await tester.pumpWidget(_RenderViewWidget( + builder: (context) { + return SizedBox( + height: 100, + width: 100, + child: rtc_remote_view.TextureView( + uid: 100, + channelId: '100', + ), + ); + }, + )); + + await tester.pumpAndSettle(); + + expect(find.byType(rtc_remote_view.TextureView), findsOneWidget); + + // Pump a empty Container to trigger dispose() of the SurfaceView/TextureView + await tester.pumpWidget(Container()); + await tester.pumpAndSettle(); + }); + + testWidgets('Change channel id', (WidgetTester tester) async { + runApp(_RenderViewWidget( + builder: (context) { + return SizedBox( + height: 100, + width: 100, + child: rtc_remote_view.TextureView( + uid: 10, + channelId: '100', + ), + ); + }, + )); + + await tester.pumpAndSettle(const Duration(milliseconds: 5000)); + + expect(find.byType(rtc_remote_view.TextureView), findsOneWidget); + + await tester.pumpWidget(_RenderViewWidget( + builder: (context) { + return SizedBox( + height: 100, + width: 100, + child: rtc_remote_view.TextureView( + uid: 10, + channelId: '10', + ), + ); + }, + )); + + await tester.pumpAndSettle(); + + expect(find.byType(rtc_remote_view.TextureView), findsOneWidget); + + // Pump a empty Container to trigger dispose() of the SurfaceView/TextureView + await tester.pumpWidget(Container()); + await tester.pumpAndSettle(); + }); + + testWidgets('Change renderMode', (WidgetTester tester) async { + runApp(_RenderViewWidget( + builder: (context) { + return SizedBox( + height: 100, + width: 100, + child: rtc_remote_view.TextureView( + uid: 10, + channelId: '100', + renderMode: VideoRenderMode.Hidden, + ), + ); + }, + )); + + await tester.pumpAndSettle(const Duration(milliseconds: 5000)); + + expect(find.byType(rtc_remote_view.TextureView), findsOneWidget); + + await tester.pumpWidget(_RenderViewWidget( + builder: (context) { + return SizedBox( + height: 100, + width: 100, + child: rtc_remote_view.TextureView( + uid: 10, + channelId: '100', + renderMode: VideoRenderMode.FILL, + ), + ); + }, + )); + + await tester.pumpAndSettle(); + + expect(find.byType(rtc_remote_view.TextureView), findsOneWidget); + + // Pump a empty Container to trigger dispose() of the SurfaceView/TextureView + await tester.pumpWidget(Container()); + await tester.pumpAndSettle(); + }); + + testWidgets('Change mirrorMode', (WidgetTester tester) async { + runApp(_RenderViewWidget( + builder: (context) { + return SizedBox( + height: 100, + width: 100, + child: rtc_remote_view.TextureView( + uid: 10, + channelId: '100', + mirrorMode: VideoMirrorMode.Auto, + ), + ); + }, + )); + + await tester.pumpAndSettle(const Duration(milliseconds: 5000)); + + expect(find.byType(rtc_remote_view.TextureView), findsOneWidget); + + final w = _RenderViewWidget( + builder: (context) { + return SizedBox( + height: 100, + width: 100, + child: rtc_remote_view.TextureView( + uid: 10, + channelId: '100', + mirrorMode: VideoMirrorMode.Enabled, + ), + ); + }, + ); + await tester.pumpWidget(w); + + expect(find.byType(rtc_remote_view.TextureView), findsOneWidget); + + // Pump a empty Container to trigger dispose() of the SurfaceView/TextureView + await tester.pumpWidget(Container()); + await tester.pumpAndSettle(); + }); + }); +} diff --git a/integration_test_app/integration_test/agora_rtc_channel_api_test.dart b/integration_test_app/integration_test/agora_rtc_channel_api_test.dart new file mode 100644 index 000000000..ff67c0240 --- /dev/null +++ b/integration_test_app/integration_test/agora_rtc_channel_api_test.dart @@ -0,0 +1,901 @@ +import 'dart:convert'; +import 'dart:typed_data'; + +import 'package:agora_rtc_engine/rtc_channel.dart'; +import 'package:agora_rtc_engine/rtc_engine.dart'; +import 'package:agora_rtc_engine/src/api_types.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:integration_test/integration_test.dart'; +import 'package:integration_test_app/main.dart' as app; +import 'package:integration_test_app/src/fake_iris_rtc_engine.dart'; + +void main() { + IntegrationTestWidgetsFlutterBinding.ensureInitialized(); + + late RtcEngine rtcEngine; + late RtcChannel rtcChannel; + late FakeIrisRtcEngine fakeIrisEngine; + + Future _createChannel() async { + rtcEngine = await RtcEngine.create('123'); + return RtcChannel.create('testapi'); + } + + tearDown(() async { + await rtcChannel.destroy(); + await rtcEngine.destroy(); + fakeIrisEngine.dispose(); + }); + + testWidgets('create', (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisEngine = FakeIrisRtcEngine(isMockChannel: true); + await fakeIrisEngine.initialize(); + + rtcChannel = await _createChannel(); + fakeIrisEngine.expectCalledApi( + ApiTypeChannel.kChannelCreateChannel.index, + jsonEncode({ + 'channelId': 'testapi', + }), + ); + }); + + group('setClientRole', () { + testWidgets('with `role`', (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisEngine = FakeIrisRtcEngine(isMockChannel: true); + await fakeIrisEngine.initialize(); + + rtcChannel = await _createChannel(); + await rtcChannel.setClientRole(ClientRole.Broadcaster); + fakeIrisEngine.expectCalledApi( + ApiTypeChannel.kChannelSetClientRole.index, + jsonEncode({ + 'channelId': 'testapi', + 'role': 1, + 'options': null, + }), + ); + }); + + testWidgets('with `role`, `options`', (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisEngine = FakeIrisRtcEngine(isMockChannel: true); + await fakeIrisEngine.initialize(); + + rtcChannel = await _createChannel(); + final ClientRoleOptions options = ClientRoleOptions( + audienceLatencyLevel: AudienceLatencyLevelType.LowLatency); + await rtcChannel.setClientRole(ClientRole.Broadcaster, options); + fakeIrisEngine.expectCalledApi( + ApiTypeChannel.kChannelSetClientRole.index, + jsonEncode({ + 'channelId': 'testapi', + 'role': 1, + 'options': options.toJson(), + }), + ); + }); + }); + + testWidgets('joinChannel', (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisEngine = FakeIrisRtcEngine(isMockChannel: true); + await fakeIrisEngine.initialize(); + + rtcChannel = await _createChannel(); + final ChannelMediaOptions options = + ChannelMediaOptions(autoSubscribeAudio: true); + await rtcChannel.joinChannel(null, null, 10, options); + fakeIrisEngine.expectCalledApi( + ApiTypeChannel.kChannelJoinChannel.index, + jsonEncode({ + 'channelId': 'testapi', + 'token': null, + 'info': null, + 'uid': 10, + 'options': options.toJson(), + }), + ); + }); + + testWidgets('joinChannelWithUserAccount', (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisEngine = FakeIrisRtcEngine(isMockChannel: true); + await fakeIrisEngine.initialize(); + + rtcChannel = await _createChannel(); + final ChannelMediaOptions options = + ChannelMediaOptions(autoSubscribeAudio: true); + await rtcChannel.joinChannelWithUserAccount(null, 'user1', options); + fakeIrisEngine.expectCalledApi( + ApiTypeChannel.kChannelJoinChannelWithUserAccount.index, + jsonEncode({ + 'channelId': 'testapi', + 'token': null, + 'userAccount': 'user1', + 'options': options.toJson(), + }), + ); + }); + + testWidgets('leaveChannel', (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisEngine = FakeIrisRtcEngine(isMockChannel: true); + await fakeIrisEngine.initialize(); + + rtcChannel = await _createChannel(); + await rtcChannel.leaveChannel(); + fakeIrisEngine.expectCalledApi( + ApiTypeChannel.kChannelLeaveChannel.index, + jsonEncode({ + 'channelId': 'testapi', + }), + ); + }); + + testWidgets('renewToken', (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisEngine = FakeIrisRtcEngine(isMockChannel: true); + await fakeIrisEngine.initialize(); + + rtcChannel = await _createChannel(); + await rtcChannel.renewToken('t'); + fakeIrisEngine.expectCalledApi( + ApiTypeChannel.kChannelRenewToken.index, + jsonEncode({ + 'channelId': 'testapi', + 'token': 't', + }), + ); + }); + + testWidgets('getConnectionState', (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisEngine = FakeIrisRtcEngine(isMockChannel: true); + await fakeIrisEngine.initialize(); + + fakeIrisEngine.mockCallApiReturnCode( + ApiTypeChannel.kChannelGetConnectionState.index, + jsonEncode({ + 'channelId': 'testapi', + }), + 2, + ); + rtcChannel = await _createChannel(); + final ret = await rtcChannel.getConnectionState(); + fakeIrisEngine.expectCalledApi( + ApiTypeChannel.kChannelGetConnectionState.index, + jsonEncode({ + 'channelId': 'testapi', + }), + ); + + expect(ret, ConnectionStateType.Connecting); + }); + + testWidgets('publish', (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisEngine = FakeIrisRtcEngine(isMockChannel: true); + await fakeIrisEngine.initialize(); + + rtcChannel = await _createChannel(); + // ignore: deprecated_member_use + await rtcChannel.publish(); + fakeIrisEngine.expectCalledApi( + ApiTypeChannel.kChannelPublish.index, + jsonEncode({ + 'channelId': 'testapi', + }), + ); + }); + + testWidgets('unpublish', (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisEngine = FakeIrisRtcEngine(isMockChannel: true); + await fakeIrisEngine.initialize(); + + rtcChannel = await _createChannel(); + // ignore: deprecated_member_use + await rtcChannel.unpublish(); + fakeIrisEngine.expectCalledApi( + ApiTypeChannel.kChannelUnPublish.index, + jsonEncode({ + 'channelId': 'testapi', + }), + ); + }); + + testWidgets('getCallId', (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisEngine = FakeIrisRtcEngine(isMockChannel: true); + await fakeIrisEngine.initialize(); + + fakeIrisEngine.mockCallApiResult( + ApiTypeChannel.kChannelGetCallId.index, + jsonEncode({ + 'channelId': 'testapi', + }), + '10', + ); + rtcChannel = await _createChannel(); + final ret = await rtcChannel.getCallId(); + fakeIrisEngine.expectCalledApi( + ApiTypeChannel.kChannelGetCallId.index, + jsonEncode({ + 'channelId': 'testapi', + }), + ); + + expect(ret, '10'); + }); + + testWidgets('adjustUserPlaybackSignalVolume', (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisEngine = FakeIrisRtcEngine(isMockChannel: true); + await fakeIrisEngine.initialize(); + + rtcChannel = await _createChannel(); + await rtcChannel.adjustUserPlaybackSignalVolume(10, 20); + fakeIrisEngine.expectCalledApi( + ApiTypeChannel.kChannelAdjustUserPlaybackSignalVolume.index, + jsonEncode({ + 'channelId': 'testapi', + 'uid': 10, + 'volume': 20, + }), + ); + }); + + testWidgets('muteAllRemoteAudioStreams', (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisEngine = FakeIrisRtcEngine(isMockChannel: true); + await fakeIrisEngine.initialize(); + + rtcChannel = await _createChannel(); + await rtcChannel.muteAllRemoteAudioStreams(true); + fakeIrisEngine.expectCalledApi( + ApiTypeChannel.kChannelMuteAllRemoteAudioStreams.index, + jsonEncode({ + 'channelId': 'testapi', + 'mute': true, + }), + ); + }); + + testWidgets('muteRemoteAudioStream', (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisEngine = FakeIrisRtcEngine(isMockChannel: true); + await fakeIrisEngine.initialize(); + + rtcChannel = await _createChannel(); + await rtcChannel.muteRemoteAudioStream(10, true); + fakeIrisEngine.expectCalledApi( + ApiTypeChannel.kChannelMuteRemoteAudioStream.index, + jsonEncode({ + 'channelId': 'testapi', + 'userId': 10, + 'mute': true, + }), + ); + }); + + testWidgets('setDefaultMuteAllRemoteAudioStreams', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisEngine = FakeIrisRtcEngine(isMockChannel: true); + await fakeIrisEngine.initialize(); + + rtcChannel = await _createChannel(); + // ignore: deprecated_member_use + await rtcChannel.setDefaultMuteAllRemoteAudioStreams(true); + fakeIrisEngine.expectCalledApi( + ApiTypeChannel.kChannelSetDefaultMuteAllRemoteAudioStreams.index, + jsonEncode({ + 'channelId': 'testapi', + 'mute': true, + }), + ); + }); + + testWidgets('muteAllRemoteVideoStreams', (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisEngine = FakeIrisRtcEngine(isMockChannel: true); + await fakeIrisEngine.initialize(); + + rtcChannel = await _createChannel(); + // ignore: deprecated_member_use + await rtcChannel.muteAllRemoteVideoStreams(true); + fakeIrisEngine.expectCalledApi( + ApiTypeChannel.kChannelMuteAllRemoteVideoStreams.index, + jsonEncode({ + 'channelId': 'testapi', + 'mute': true, + }), + ); + }); + + testWidgets('muteRemoteVideoStream', (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisEngine = FakeIrisRtcEngine(isMockChannel: true); + await fakeIrisEngine.initialize(); + + rtcChannel = await _createChannel(); + + await rtcChannel.muteRemoteVideoStream(10, true); + fakeIrisEngine.expectCalledApi( + ApiTypeChannel.kChannelMuteRemoteVideoStream.index, + jsonEncode({ + 'channelId': 'testapi', + 'userId': 10, + 'mute': true, + }), + ); + }); + + testWidgets('setDefaultMuteAllRemoteVideoStreams', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisEngine = FakeIrisRtcEngine(isMockChannel: true); + await fakeIrisEngine.initialize(); + + rtcChannel = await _createChannel(); + // ignore: deprecated_member_use + await rtcChannel.setDefaultMuteAllRemoteVideoStreams(true); + fakeIrisEngine.expectCalledApi( + ApiTypeChannel.kChannelSetDefaultMuteAllRemoteVideoStreams.index, + jsonEncode({ + 'channelId': 'testapi', + 'mute': true, + }), + ); + }); + + testWidgets('addInjectStreamUrl', (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisEngine = FakeIrisRtcEngine(isMockChannel: true); + await fakeIrisEngine.initialize(); + + rtcChannel = await _createChannel(); + final LiveInjectStreamConfig config = + LiveInjectStreamConfig(width: 10, height: 10); + await rtcChannel.addInjectStreamUrl('https://example.com', config); + fakeIrisEngine.expectCalledApi( + ApiTypeChannel.kChannelAddInjectStreamUrl.index, + jsonEncode({ + 'channelId': 'testapi', + 'url': 'https://example.com', + 'config': config.toJson(), + }), + ); + }); + + testWidgets('addPublishStreamUrl', (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisEngine = FakeIrisRtcEngine(isMockChannel: true); + await fakeIrisEngine.initialize(); + + rtcChannel = await _createChannel(); + await rtcChannel.addPublishStreamUrl('https://example.com', true); + fakeIrisEngine.expectCalledApi( + ApiTypeChannel.kChannelAddPublishStreamUrl.index, + jsonEncode({ + 'channelId': 'testapi', + 'url': 'https://example.com', + 'transcodingEnabled': true, + }), + ); + }); + + testWidgets( + 'createDataStream', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisEngine = FakeIrisRtcEngine(isMockChannel: true); + await fakeIrisEngine.initialize(); + + rtcChannel = await _createChannel(); + // ignore: deprecated_member_use + await rtcChannel.createDataStream(true, true); + fakeIrisEngine.expectCalledApi( + ApiTypeChannel.kChannelCreateDataStream.index, + jsonEncode({ + 'channelId': 'testapi', + 'reliable': true, + 'ordered': true, + }), + ); + } + ); + + testWidgets('registerMediaMetadataObserver', (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisEngine = FakeIrisRtcEngine(isMockChannel: true); + await fakeIrisEngine.initialize(); + + rtcChannel = await _createChannel(); + await rtcChannel.registerMediaMetadataObserver(); + fakeIrisEngine.expectCalledApi( + ApiTypeChannel.kChannelRegisterMediaMetadataObserver.index, + jsonEncode({ + 'channelId': 'testapi', + 'type': 0, + }), + ); + }); + + testWidgets('removeInjectStreamUrl', (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisEngine = FakeIrisRtcEngine(isMockChannel: true); + await fakeIrisEngine.initialize(); + + rtcChannel = await _createChannel(); + await rtcChannel.removeInjectStreamUrl('https://example.com'); + fakeIrisEngine.expectCalledApi( + ApiTypeChannel.kChannelRemoveInjectStreamUrl.index, + jsonEncode({ + 'channelId': 'testapi', + 'url': 'https://example.com', + }), + ); + }); + + testWidgets('removePublishStreamUrl', (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisEngine = FakeIrisRtcEngine(isMockChannel: true); + await fakeIrisEngine.initialize(); + + rtcChannel = await _createChannel(); + await rtcChannel.removePublishStreamUrl('https://example.com'); + fakeIrisEngine.expectCalledApi( + ApiTypeChannel.kChannelRemovePublishStreamUrl.index, + jsonEncode({ + 'channelId': 'testapi', + 'url': 'https://example.com', + }), + ); + }); + + testWidgets('sendMetadata', (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisEngine = FakeIrisRtcEngine(isMockChannel: true); + await fakeIrisEngine.initialize(); + + final Uint8List metadata = Uint8List.fromList([1, 1]); + fakeIrisEngine.setExplicitBufferSize( + ApiTypeChannel.kChannelSendMetadata.index, + jsonEncode({ + 'channelId': 'testapi', + 'metadata': { + 'size': metadata.length, + }, + }), + metadata.length, + ); + + rtcChannel = await _createChannel(); + + await rtcChannel.registerMediaMetadataObserver(); + await rtcChannel.sendMetadata(metadata); + fakeIrisEngine.expectCalledApi( + ApiTypeChannel.kChannelSendMetadata.index, + jsonEncode({ + 'channelId': 'testapi', + 'metadata': { + 'size': metadata.length, + }, + }), + buffer: metadata, + bufferSize: metadata.length, + ); + }); + + testWidgets('sendStreamMessage', (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisEngine = FakeIrisRtcEngine(isMockChannel: true); + await fakeIrisEngine.initialize(); + + final Uint8List message = Uint8List.fromList([1, 1]); + fakeIrisEngine.setExplicitBufferSize( + ApiTypeChannel.kChannelSendStreamMessage.index, + jsonEncode({ + 'channelId': 'testapi', + 'streamId': 10, + 'length': message.length, + }), + message.length, + ); + + rtcChannel = await _createChannel(); + + await rtcChannel.sendStreamMessage(10, message); + fakeIrisEngine.expectCalledApi( + ApiTypeChannel.kChannelSendStreamMessage.index, + jsonEncode({ + 'channelId': 'testapi', + 'streamId': 10, + 'length': message.length, + }), + buffer: message, + bufferSize: message.length, + ); + }); + + // TODO(littlegnal): Check if change the encryptionMode from int -> string is ok or not + testWidgets( + 'setEncryptionMode', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisEngine = FakeIrisRtcEngine(isMockChannel: true); + await fakeIrisEngine.initialize(); + + rtcChannel = await _createChannel(); + // ignore: deprecated_member_use + await rtcChannel.setEncryptionMode(EncryptionMode.AES128GCM); + fakeIrisEngine.expectCalledApi( + ApiTypeChannel.kChannelSetEncryptionMode.index, + jsonEncode({ + 'channelId': 'testapi', + 'encryptionMode': 5, + }), + ); + }, + skip: true, // TODO(littlegnal): [MS-99372] Need comfirm how to deal with this function + ); + + testWidgets('setEncryptionSecret', (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisEngine = FakeIrisRtcEngine(isMockChannel: true); + await fakeIrisEngine.initialize(); + + rtcChannel = await _createChannel(); + // ignore: deprecated_member_use + await rtcChannel.setEncryptionSecret('s'); + fakeIrisEngine.expectCalledApi( + ApiTypeChannel.kChannelSetEncryptionSecret.index, + jsonEncode({ + 'channelId': 'testapi', + 'secret': 's', + }), + ); + }); + + testWidgets('setLiveTranscoding', (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisEngine = FakeIrisRtcEngine(isMockChannel: true); + await fakeIrisEngine.initialize(); + + rtcChannel = await _createChannel(); + final LiveTranscoding transcoding = LiveTranscoding([TranscodingUser(10)]); + await rtcChannel.setLiveTranscoding(transcoding); + fakeIrisEngine.expectCalledApi( + ApiTypeChannel.kChannelSetLiveTranscoding.index, + jsonEncode({ + 'channelId': 'testapi', + 'transcoding': transcoding.toJson(), + }), + ); + }); + + testWidgets('setMaxMetadataSize', (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisEngine = FakeIrisRtcEngine(isMockChannel: true); + await fakeIrisEngine.initialize(); + + rtcChannel = await _createChannel(); + await rtcChannel.setMaxMetadataSize(10); + fakeIrisEngine.expectCalledApi( + ApiTypeChannel.kChannelSetMaxMetadataSize.index, + jsonEncode({ + 'channelId': 'testapi', + 'size': 10, + }), + ); + }); + + testWidgets('setRemoteDefaultVideoStreamType', (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisEngine = FakeIrisRtcEngine(isMockChannel: true); + await fakeIrisEngine.initialize(); + + rtcChannel = await _createChannel(); + await rtcChannel.setRemoteDefaultVideoStreamType(VideoStreamType.High); + fakeIrisEngine.expectCalledApi( + ApiTypeChannel.kChannelSetRemoteDefaultVideoStreamType.index, + jsonEncode({ + 'channelId': 'testapi', + 'streamType': 0, + }), + ); + }); + + testWidgets('setRemoteUserPriority', (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisEngine = FakeIrisRtcEngine(isMockChannel: true); + await fakeIrisEngine.initialize(); + + rtcChannel = await _createChannel(); + await rtcChannel.setRemoteUserPriority(10, UserPriority.High); + fakeIrisEngine.expectCalledApi( + ApiTypeChannel.kChannelSetRemoteUserPriority.index, + jsonEncode({ + 'channelId': 'testapi', + 'uid': 10, + 'userPriority': 50, + }), + ); + }); + + testWidgets('setRemoteVideoStreamType', (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisEngine = FakeIrisRtcEngine(isMockChannel: true); + await fakeIrisEngine.initialize(); + + rtcChannel = await _createChannel(); + await rtcChannel.setRemoteVideoStreamType(10, VideoStreamType.Low); + fakeIrisEngine.expectCalledApi( + ApiTypeChannel.kChannelSetRemoteVideoStreamType.index, + jsonEncode({ + 'channelId': 'testapi', + 'userId': 10, + 'streamType': 1, + }), + ); + }); + + testWidgets('setRemoteVoicePosition', (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisEngine = FakeIrisRtcEngine(isMockChannel: true); + await fakeIrisEngine.initialize(); + + rtcChannel = await _createChannel(); + await rtcChannel.setRemoteVoicePosition(10, 1.0, 2.0); + fakeIrisEngine.expectCalledApi( + ApiTypeChannel.kChannelSetRemoteVoicePosition.index, + jsonEncode({ + 'channelId': 'testapi', + 'uid': 10, + 'pan': 1.0, + 'gain': 2.0, + }), + ); + }); + + testWidgets('startChannelMediaRelay', (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisEngine = FakeIrisRtcEngine(isMockChannel: true); + await fakeIrisEngine.initialize(); + + rtcChannel = await _createChannel(); + final ChannelMediaRelayConfiguration config = + ChannelMediaRelayConfiguration( + ChannelMediaInfo('testapi', 10), + [ChannelMediaInfo('testapi', 10)], + ); + await rtcChannel.startChannelMediaRelay(config); + fakeIrisEngine.expectCalledApi( + ApiTypeChannel.kChannelStartChannelMediaRelay.index, + jsonEncode({ + 'channelId': 'testapi', + 'configuration': config.toJson(), + }), + ); + }); + + testWidgets('stopChannelMediaRelay', (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisEngine = FakeIrisRtcEngine(isMockChannel: true); + await fakeIrisEngine.initialize(); + + rtcChannel = await _createChannel(); + await rtcChannel.stopChannelMediaRelay(); + fakeIrisEngine.expectCalledApi( + ApiTypeChannel.kChannelStopChannelMediaRelay.index, + jsonEncode({ + 'channelId': 'testapi', + }), + ); + }); + + testWidgets( + 'unregisterMediaMetadataObserver', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisEngine = FakeIrisRtcEngine(isMockChannel: true); + await fakeIrisEngine.initialize(); + + rtcChannel = await _createChannel(); + await rtcChannel.unregisterMediaMetadataObserver(); + fakeIrisEngine.expectCalledApi( + ApiTypeChannel.kChannelUnRegisterMediaMetadataObserver.index, + jsonEncode({ + 'channelId': 'testapi', + }), + ); + }, + skip: true, // TODO(littlegnal): [MS-99374] Enable after iris fixed + ); + + testWidgets('updateChannelMediaRelay', (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisEngine = FakeIrisRtcEngine(isMockChannel: true); + await fakeIrisEngine.initialize(); + + rtcChannel = await _createChannel(); + final ChannelMediaRelayConfiguration config = + ChannelMediaRelayConfiguration( + ChannelMediaInfo('testapi', 10), + [ChannelMediaInfo('testapi', 10)], + ); + await rtcChannel.updateChannelMediaRelay(config); + fakeIrisEngine.expectCalledApi( + ApiTypeChannel.kChannelUpdateChannelMediaRelay.index, + jsonEncode({ + 'channelId': 'testapi', + 'configuration': config.toJson(), + }), + ); + }); + + testWidgets('enableEncryption', (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisEngine = FakeIrisRtcEngine(isMockChannel: true); + await fakeIrisEngine.initialize(); + + rtcChannel = await _createChannel(); + final EncryptionConfig config = EncryptionConfig( + encryptionMode: EncryptionMode.AES128GCM2, + ); + await rtcChannel.enableEncryption(true, config); + fakeIrisEngine.expectCalledApi( + ApiTypeChannel.kChannelEnableEncryption.index, + jsonEncode({ + 'channelId': 'testapi', + 'enabled': true, + 'config': config.toJson(), + }), + ); + }); + + testWidgets('createDataStreamWithConfig', (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisEngine = FakeIrisRtcEngine(isMockChannel: true); + await fakeIrisEngine.initialize(); + + rtcChannel = await _createChannel(); + final DataStreamConfig config = DataStreamConfig(true, true); + await rtcChannel.createDataStreamWithConfig(config); + fakeIrisEngine.expectCalledApi( + ApiTypeChannel.kChannelCreateDataStream.index, + jsonEncode({ + 'channelId': 'testapi', + 'config': config.toJson(), + }), + ); + }); + + testWidgets('enableRemoteSuperResolution', (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisEngine = FakeIrisRtcEngine(isMockChannel: true); + await fakeIrisEngine.initialize(); + + rtcChannel = await _createChannel(); + await rtcChannel.enableRemoteSuperResolution(10, true); + fakeIrisEngine.expectCalledApi( + ApiTypeChannel.kChannelEnableRemoteSuperResolution.index, + jsonEncode({ + 'channelId': 'testapi', + 'userId': 10, + 'enable': true, + }), + ); + }); + + testWidgets('muteLocalAudioStream', (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisEngine = FakeIrisRtcEngine(isMockChannel: true); + await fakeIrisEngine.initialize(); + + rtcChannel = await _createChannel(); + await rtcChannel.muteLocalAudioStream(true); + fakeIrisEngine.expectCalledApi( + ApiTypeChannel.kChannelMuteLocalAudioStream.index, + jsonEncode({ + 'channelId': 'testapi', + 'mute': true, + }), + ); + }); + + testWidgets('muteLocalVideoStream', (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisEngine = FakeIrisRtcEngine(isMockChannel: true); + await fakeIrisEngine.initialize(); + + rtcChannel = await _createChannel(); + await rtcChannel.muteLocalVideoStream(true); + fakeIrisEngine.expectCalledApi( + ApiTypeChannel.kChannelMuteLocalVideoStream.index, + jsonEncode({ + 'channelId': 'testapi', + 'mute': true, + }), + ); + }); + + testWidgets('pauseAllChannelMediaRelay', (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisEngine = FakeIrisRtcEngine(isMockChannel: true); + await fakeIrisEngine.initialize(); + + rtcChannel = await _createChannel(); + await rtcChannel.pauseAllChannelMediaRelay(); + fakeIrisEngine.expectCalledApi( + ApiTypeChannel.kChannelPauseAllChannelMediaRelay.index, + jsonEncode({ + 'channelId': 'testapi', + }), + ); + }); + + testWidgets('resumeAllChannelMediaRelay', (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisEngine = FakeIrisRtcEngine(isMockChannel: true); + await fakeIrisEngine.initialize(); + + rtcChannel = await _createChannel(); + await rtcChannel.resumeAllChannelMediaRelay(); + fakeIrisEngine.expectCalledApi( + ApiTypeChannel.kChannelResumeAllChannelMediaRelay.index, + jsonEncode({ + 'channelId': 'testapi', + }), + ); + }); +} diff --git a/integration_test_app/integration_test/agora_rtc_channel_event_handler_api_test.dart b/integration_test_app/integration_test/agora_rtc_channel_event_handler_api_test.dart new file mode 100644 index 000000000..298835dce --- /dev/null +++ b/integration_test_app/integration_test/agora_rtc_channel_event_handler_api_test.dart @@ -0,0 +1,993 @@ +import 'dart:convert'; +import 'dart:typed_data'; + +import 'package:agora_rtc_engine/rtc_channel.dart'; +import 'package:agora_rtc_engine/rtc_engine.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:integration_test/integration_test.dart'; +import 'package:integration_test_app/main.dart' as app; +import 'package:integration_test_app/src/event_handler_tester.dart'; +import 'package:integration_test_app/src/fake_iris_rtc_engine.dart'; + +void main() { + IntegrationTestWidgetsFlutterBinding.ensureInitialized(); + + late RtcEngine rtcEngine; + late RtcChannel rtcChannel; + late FakeIrisRtcEngine fakeIrisRtcEngine; + + Future _createChannel() async { + rtcEngine = await RtcEngine.create('123'); + return RtcChannel.create('testapi'); + } + + tearDown(() async { + await rtcChannel.destroy(); + await rtcEngine.destroy(); + fakeIrisRtcEngine.dispose(); + }); + + testEventCall('warning', ( + WidgetTester tester, + EventHandlerTester eventHandlerTester, + ) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisRtcEngine = FakeIrisRtcEngine(isMockChannel: true); + await fakeIrisRtcEngine.initialize(); + rtcChannel = await _createChannel(); + rtcChannel.setEventHandler(RtcChannelEventHandler( + warning: (WarningCode warn) { + expectSync(warn, WarningCode.AdmInterruption); + eventHandlerTester.markEventCalled(); + }, + )); + + await fakeIrisRtcEngine.fireAndWaitEvent( + tester, + 'onChannelWarning', + '{"channelId":"testapi","warn":1025,"msg":"warning"}', + ); + }); + + testEventCall('error', ( + WidgetTester tester, + EventHandlerTester eventHandlerTester, + ) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisRtcEngine = FakeIrisRtcEngine(isMockChannel: true); + await fakeIrisRtcEngine.initialize(); + rtcChannel = await _createChannel(); + rtcChannel.setEventHandler(RtcChannelEventHandler( + error: (ErrorCode err) { + expectSync(err, ErrorCode.AdmInitPlayout); + eventHandlerTester.markEventCalled(); + }, + )); + + await fakeIrisRtcEngine.fireAndWaitEvent( + tester, + 'onChannelError', + '{"channelId":"testapi","err":1008,"msg":"error"}', + ); + }); + + testEventCall('joinChannelSuccess', ( + WidgetTester tester, + EventHandlerTester eventHandlerTester, + ) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisRtcEngine = FakeIrisRtcEngine(isMockChannel: true); + await fakeIrisRtcEngine.initialize(); + rtcChannel = await _createChannel(); + rtcChannel.setEventHandler(RtcChannelEventHandler( + joinChannelSuccess: (String channel, int uid, int elapsed) { + expectSync(channel, 'testapi'); + expectSync(uid, 10); + expectSync(elapsed, 100); + eventHandlerTester.markEventCalled(); + }, + )); + + await fakeIrisRtcEngine.fireAndWaitEvent( + tester, + 'onJoinChannelSuccess', + '{"channelId":"testapi","channel":"testapi","uid":10,"elapsed":100}', + ); + }); + + testEventCall('rejoinChannelSuccess', ( + WidgetTester tester, + EventHandlerTester eventHandlerTester, + ) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisRtcEngine = FakeIrisRtcEngine(isMockChannel: true); + await fakeIrisRtcEngine.initialize(); + rtcChannel = await _createChannel(); + rtcChannel.setEventHandler(RtcChannelEventHandler( + rejoinChannelSuccess: (String channel, int uid, int elapsed) { + expectSync(channel, 'testapi'); + expectSync(uid, 10); + expectSync(elapsed, 100); + + eventHandlerTester.markEventCalled(); + }, + )); + + await fakeIrisRtcEngine.fireAndWaitEvent( + tester, + 'onRejoinChannelSuccess', + '{"channelId":"testapi","channel":"testapi","uid":10,"elapsed":100}', + ); + }); + + testEventCall('leaveChannel', ( + WidgetTester tester, + EventHandlerTester eventHandlerTester, + ) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisRtcEngine = FakeIrisRtcEngine(isMockChannel: true); + await fakeIrisRtcEngine.initialize(); + rtcChannel = await _createChannel(); + final expectSyncedStats = RtcStats(10, 20, 20, 100, 100, 200, 200, 10, 10, + 20, 20, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10); + rtcChannel.setEventHandler(RtcChannelEventHandler( + leaveChannel: (RtcStats stats) { + expectSync(jsonEncode(stats), jsonEncode(expectSyncedStats)); + + eventHandlerTester.markEventCalled(); + }, + )); + + await fakeIrisRtcEngine.fireAndWaitEvent( + tester, + 'onLeaveChannel', + '{"channelId":"testapi","stats":${jsonEncode(expectSyncedStats.toJson())}}', + ); + }); + + testEventCall('clientRoleChanged', ( + WidgetTester tester, + EventHandlerTester eventHandlerTester, + ) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisRtcEngine = FakeIrisRtcEngine(isMockChannel: true); + await fakeIrisRtcEngine.initialize(); + rtcChannel = await _createChannel(); + rtcChannel.setEventHandler(RtcChannelEventHandler( + clientRoleChanged: (ClientRole oldRole, ClientRole newRole) { + expectSync(oldRole, ClientRole.Broadcaster); + expectSync(newRole, ClientRole.Audience); + + eventHandlerTester.markEventCalled(); + }, + )); + + await fakeIrisRtcEngine.fireAndWaitEvent( + tester, + 'onClientRoleChanged', + '{"channelId":"testapi","oldRole":1,"newRole":2}', + ); + }); + + testEventCall('userJoined', ( + WidgetTester tester, + EventHandlerTester eventHandlerTester, + ) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisRtcEngine = FakeIrisRtcEngine(isMockChannel: true); + await fakeIrisRtcEngine.initialize(); + rtcChannel = await _createChannel(); + rtcChannel.setEventHandler(RtcChannelEventHandler( + userJoined: (int uid, int elapsed) { + expectSync(uid, 10); + expectSync(elapsed, 100); + + eventHandlerTester.markEventCalled(); + }, + )); + + await fakeIrisRtcEngine.fireAndWaitEvent( + tester, + 'onUserJoined', + '{"channelId":"testapi","uid":10,"elapsed":100}', + ); + }); + + testEventCall('userOffline', ( + WidgetTester tester, + EventHandlerTester eventHandlerTester, + ) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisRtcEngine = FakeIrisRtcEngine(isMockChannel: true); + await fakeIrisRtcEngine.initialize(); + rtcChannel = await _createChannel(); + rtcChannel.setEventHandler(RtcChannelEventHandler( + userOffline: (int uid, UserOfflineReason reason) { + expectSync(uid, 10); + expectSync(reason, UserOfflineReason.Dropped); + + eventHandlerTester.markEventCalled(); + }, + )); + + await fakeIrisRtcEngine.fireAndWaitEvent( + tester, + 'onUserOffline', + '{"channelId":"testapi","uid":10,"reason":1}', + ); + }); + + testEventCall('connectionStateChanged', ( + WidgetTester tester, + EventHandlerTester eventHandlerTester, + ) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisRtcEngine = FakeIrisRtcEngine(isMockChannel: true); + await fakeIrisRtcEngine.initialize(); + rtcChannel = await _createChannel(); + rtcChannel.setEventHandler(RtcChannelEventHandler( + connectionStateChanged: + (ConnectionStateType state, ConnectionChangedReason reason) { + expectSync(state, ConnectionStateType.Connecting); + expectSync(reason, ConnectionChangedReason.Interrupted); + + eventHandlerTester.markEventCalled(); + }, + )); + + await fakeIrisRtcEngine.fireAndWaitEvent( + tester, + 'onConnectionStateChanged', + '{"channelId":"testapi","state":2,"reason":2}', + ); + }); + + testEventCall('connectionLost', ( + WidgetTester tester, + EventHandlerTester eventHandlerTester, + ) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisRtcEngine = FakeIrisRtcEngine(isMockChannel: true); + await fakeIrisRtcEngine.initialize(); + rtcChannel = await _createChannel(); + rtcChannel.setEventHandler(RtcChannelEventHandler( + connectionLost: () { + eventHandlerTester.markEventCalled(); + }, + )); + + await fakeIrisRtcEngine.fireAndWaitEvent( + tester, + 'onConnectionLost', + '{"channelId":"testapi"}', + ); + }); + + testEventCall('tokenPrivilegeWillExpire', ( + WidgetTester tester, + EventHandlerTester eventHandlerTester, + ) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisRtcEngine = FakeIrisRtcEngine(isMockChannel: true); + await fakeIrisRtcEngine.initialize(); + rtcChannel = await _createChannel(); + rtcChannel.setEventHandler(RtcChannelEventHandler( + tokenPrivilegeWillExpire: (String token) { + expectSync(token, 't'); + eventHandlerTester.markEventCalled(); + }, + )); + + await fakeIrisRtcEngine.fireAndWaitEvent( + tester, + 'onTokenPrivilegeWillExpire', + '{"channelId":"testapi","token":"t"}', + ); + }); + + testEventCall('requestToken', ( + WidgetTester tester, + EventHandlerTester eventHandlerTester, + ) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisRtcEngine = FakeIrisRtcEngine(isMockChannel: true); + await fakeIrisRtcEngine.initialize(); + rtcChannel = await _createChannel(); + rtcChannel.setEventHandler(RtcChannelEventHandler( + requestToken: () { + eventHandlerTester.markEventCalled(); + }, + )); + + await fakeIrisRtcEngine.fireAndWaitEvent( + tester, + 'onRequestToken', + '{"channelId":"testapi"}', + ); + }); + + testEventCall('activeSpeaker', ( + WidgetTester tester, + EventHandlerTester eventHandlerTester, + ) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisRtcEngine = FakeIrisRtcEngine(isMockChannel: true); + await fakeIrisRtcEngine.initialize(); + rtcChannel = await _createChannel(); + rtcChannel.setEventHandler(RtcChannelEventHandler( + activeSpeaker: (int uid) { + expectSync(uid, 10); + eventHandlerTester.markEventCalled(); + }, + )); + + await fakeIrisRtcEngine.fireAndWaitEvent( + tester, + 'onActiveSpeaker', + '{"channelId":"testapi","uid":10}', + ); + }); + + testEventCall('videoSizeChanged', ( + WidgetTester tester, + EventHandlerTester eventHandlerTester, + ) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisRtcEngine = FakeIrisRtcEngine(isMockChannel: true); + await fakeIrisRtcEngine.initialize(); + rtcChannel = await _createChannel(); + rtcChannel.setEventHandler(RtcChannelEventHandler( + videoSizeChanged: (int uid, int width, int height, int rotation) { + expectSync(uid, 10); + expectSync(width, 100); + expectSync(height, 100); + expectSync(rotation, 30); + eventHandlerTester.markEventCalled(); + }, + )); + + await fakeIrisRtcEngine.fireAndWaitEvent( + tester, + 'onVideoSizeChanged', + '{"channelId":"testapi","uid":10,"width":100,"height":100,"rotation":30}', + ); + }); + + testEventCall('remoteVideoStateChanged', ( + WidgetTester tester, + EventHandlerTester eventHandlerTester, + ) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisRtcEngine = FakeIrisRtcEngine(isMockChannel: true); + await fakeIrisRtcEngine.initialize(); + rtcChannel = await _createChannel(); + rtcChannel.setEventHandler(RtcChannelEventHandler( + remoteVideoStateChanged: ( + int uid, + VideoRemoteState state, + VideoRemoteStateReason reason, + int elapsed, + ) { + expectSync(uid, 10); + expectSync(state, VideoRemoteState.Frozen); + expectSync(reason, VideoRemoteStateReason.LocalMuted); + expectSync(elapsed, 100); + eventHandlerTester.markEventCalled(); + }, + )); + + await fakeIrisRtcEngine.fireAndWaitEvent( + tester, + 'onRemoteVideoStateChanged', + '{"channelId":"testapi","uid":10,"state":3,"reason":3,"elapsed":100}', + ); + }); + + testEventCall('remoteAudioStateChanged', ( + WidgetTester tester, + EventHandlerTester eventHandlerTester, + ) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisRtcEngine = FakeIrisRtcEngine(isMockChannel: true); + await fakeIrisRtcEngine.initialize(); + rtcChannel = await _createChannel(); + rtcChannel.setEventHandler(RtcChannelEventHandler( + remoteAudioStateChanged: ( + int uid, + AudioRemoteState state, + AudioRemoteStateReason reason, + int elapsed, + ) { + expectSync(uid, 10); + expectSync(state, AudioRemoteState.Frozen); + expectSync(reason, AudioRemoteStateReason.LocalMuted); + expectSync(elapsed, 100); + eventHandlerTester.markEventCalled(); + }, + )); + + await fakeIrisRtcEngine.fireAndWaitEvent( + tester, + 'onRemoteAudioStateChanged', + '{"channelId":"testapi","uid":10,"state":3,"reason":3,"elapsed":100}', + ); + }); + + testEventCall('localPublishFallbackToAudioOnly', ( + WidgetTester tester, + EventHandlerTester eventHandlerTester, + ) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisRtcEngine = FakeIrisRtcEngine(isMockChannel: true); + await fakeIrisRtcEngine.initialize(); + rtcChannel = await _createChannel(); + rtcChannel.setEventHandler(RtcChannelEventHandler( + localPublishFallbackToAudioOnly: (bool isFallbackOrRecover) { + expectSync(isFallbackOrRecover, true); + eventHandlerTester.markEventCalled(); + }, + )); + + await fakeIrisRtcEngine.fireAndWaitEvent( + tester, + 'onLocalPublishFallbackToAudioOnly', + '{"channelId":"testapi","isFallbackOrRecover":true}', + ); + }); + + testEventCall('remoteSubscribeFallbackToAudioOnly', ( + WidgetTester tester, + EventHandlerTester eventHandlerTester, + ) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisRtcEngine = FakeIrisRtcEngine(isMockChannel: true); + await fakeIrisRtcEngine.initialize(); + rtcChannel = await _createChannel(); + rtcChannel.setEventHandler(RtcChannelEventHandler( + remoteSubscribeFallbackToAudioOnly: (int uid, bool isFallbackOrRecover) { + expectSync(uid, 10); + expectSync(isFallbackOrRecover, true); + eventHandlerTester.markEventCalled(); + }, + )); + + await fakeIrisRtcEngine.fireAndWaitEvent( + tester, + 'onRemoteSubscribeFallbackToAudioOnly', + '{"channelId":"testapi","uid":10,"isFallbackOrRecover":true}', + ); + }); + + testEventCall('rtcStats', ( + WidgetTester tester, + EventHandlerTester eventHandlerTester, + ) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisRtcEngine = FakeIrisRtcEngine(isMockChannel: true); + await fakeIrisRtcEngine.initialize(); + rtcChannel = await _createChannel(); + final expectSyncedStats = RtcStats(10, 20, 20, 100, 100, 200, 200, 10, 10, + 20, 20, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10); + rtcChannel.setEventHandler(RtcChannelEventHandler( + rtcStats: (RtcStats stats) { + expectSync(jsonEncode(stats), jsonEncode(expectSyncedStats.toJson())); + + eventHandlerTester.markEventCalled(); + }, + )); + + await fakeIrisRtcEngine.fireAndWaitEvent( + tester, + 'onRtcStats', + '{"channelId":"testapi","stats":${jsonEncode(expectSyncedStats.toJson())}}', + ); + }); + + testEventCall('networkQuality', ( + WidgetTester tester, + EventHandlerTester eventHandlerTester, + ) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisRtcEngine = FakeIrisRtcEngine(isMockChannel: true); + await fakeIrisRtcEngine.initialize(); + rtcChannel = await _createChannel(); + rtcChannel.setEventHandler(RtcChannelEventHandler( + networkQuality: + (int uid, NetworkQuality txQuality, NetworkQuality rxQuality) { + expectSync(uid, 10); + expectSync(txQuality, NetworkQuality.Detecting); + expectSync(rxQuality, NetworkQuality.Excellent); + + eventHandlerTester.markEventCalled(); + }, + )); + + await fakeIrisRtcEngine.fireAndWaitEvent( + tester, + 'onNetworkQuality', + '{"channelId":"testapi","uid":10,"txQuality":8,"rxQuality":1}', + ); + }); + + testEventCall('remoteVideoStats', ( + WidgetTester tester, + EventHandlerTester eventHandlerTester, + ) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisRtcEngine = FakeIrisRtcEngine(isMockChannel: true); + await fakeIrisRtcEngine.initialize(); + rtcChannel = await _createChannel(); + final expectSyncedRemoteVideoStats = RemoteVideoStats( + 10, 10, 10, 10, 10, 10, 10, 10, VideoStreamType.High, 10, 10, 10, 10); + rtcChannel.setEventHandler(RtcChannelEventHandler( + remoteVideoStats: (RemoteVideoStats stats) { + expectSync(jsonEncode(stats), jsonEncode(expectSyncedRemoteVideoStats)); + + eventHandlerTester.markEventCalled(); + }, + )); + + await fakeIrisRtcEngine.fireAndWaitEvent( + tester, + 'onRemoteVideoStats', + '{"channelId":"testapi","stats":${jsonEncode(expectSyncedRemoteVideoStats.toJson())}}', + ); + }); + + testEventCall('remoteAudioStats', ( + WidgetTester tester, + EventHandlerTester eventHandlerTester, + ) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisRtcEngine = FakeIrisRtcEngine(isMockChannel: true); + await fakeIrisRtcEngine.initialize(); + rtcChannel = await _createChannel(); + final expectSyncedRemoteAudioStats = RemoteAudioStats( + 10, + NetworkQuality.Excellent, + 10, + 10, + 10, + 10, + 10, + 10, + 10, + 10, + 10, + 10, + ExperienceQualityType.Good, + ExperiencePoorReason.RemoteNetworkQualityPoor, + 10, + ); + rtcChannel.setEventHandler(RtcChannelEventHandler( + remoteAudioStats: (RemoteAudioStats stats) { + expectSync(jsonEncode(stats), jsonEncode(expectSyncedRemoteAudioStats)); + + eventHandlerTester.markEventCalled(); + }, + )); + + await fakeIrisRtcEngine.fireAndWaitEvent( + tester, + 'onRemoteAudioStats', + '{"channelId":"testapi","stats":${jsonEncode(expectSyncedRemoteAudioStats.toJson())}}', + ); + }); + + testEventCall('rtmpStreamingStateChanged', ( + WidgetTester tester, + EventHandlerTester eventHandlerTester, + ) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisRtcEngine = FakeIrisRtcEngine(isMockChannel: true); + await fakeIrisRtcEngine.initialize(); + rtcChannel = await _createChannel(); + rtcChannel.setEventHandler(RtcChannelEventHandler( + rtmpStreamingStateChanged: (String url, RtmpStreamingState state, + RtmpStreamingErrorCode errCode) { + expectSync(url, 'https://example.com'); + expectSync(state, RtmpStreamingState.Recovering); + expectSync(errCode, RtmpStreamingErrorCode.FormatNotSupported); + + eventHandlerTester.markEventCalled(); + }, + )); + + await fakeIrisRtcEngine.fireAndWaitEvent( + tester, + 'onRtmpStreamingStateChanged', + '{"channelId":"testapi","url":"https://example.com","state":3,"errCode":10}', + ); + }); + + testEventCall('transcodingUpdated', ( + WidgetTester tester, + EventHandlerTester eventHandlerTester, + ) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisRtcEngine = FakeIrisRtcEngine(isMockChannel: true); + await fakeIrisRtcEngine.initialize(); + rtcChannel = await _createChannel(); + rtcChannel.setEventHandler(RtcChannelEventHandler( + transcodingUpdated: () { + eventHandlerTester.markEventCalled(); + }, + )); + + await fakeIrisRtcEngine.fireAndWaitEvent( + tester, + 'onTranscodingUpdated', + '{"channelId":"testapi"}', + ); + }); + + testEventCall('streamInjectedStatus', ( + WidgetTester tester, + EventHandlerTester eventHandlerTester, + ) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisRtcEngine = FakeIrisRtcEngine(isMockChannel: true); + await fakeIrisRtcEngine.initialize(); + rtcChannel = await _createChannel(); + rtcChannel.setEventHandler(RtcChannelEventHandler( + streamInjectedStatus: (String url, int uid, InjectStreamStatus status) { + expectSync(url, 'https://example.com'); + expectSync(uid, 10); + expectSync(status, InjectStreamStatus.StartTimedout); + eventHandlerTester.markEventCalled(); + }, + )); + + await fakeIrisRtcEngine.fireAndWaitEvent( + tester, + 'onStreamInjectedStatus', + '{"channelId":"testapi","url":"https://example.com","uid":10,"status":3}', + ); + }); + + testEventCall('streamMessage', ( + WidgetTester tester, + EventHandlerTester eventHandlerTester, + ) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisRtcEngine = FakeIrisRtcEngine(isMockChannel: true); + await fakeIrisRtcEngine.initialize(); + rtcChannel = await _createChannel(); + final buffer = Uint8List.fromList([1, 1]); + + rtcChannel.setEventHandler(RtcChannelEventHandler( + streamMessage: (int uid, int streamId, Uint8List data) { + expectSync(uid, 10); + expectSync(streamId, 20); + expectSync(data, buffer); + eventHandlerTester.markEventCalled(); + }, + )); + + await fakeIrisRtcEngine.fireAndWaitEvent( + tester, + 'onStreamMessage', + '{"channelId":"testapi","uid":10,"streamId":20,"length":2}', + buffer: buffer, + bufferSize: 2, + ); + }); + + testEventCall('streamMessageError', ( + WidgetTester tester, + EventHandlerTester eventHandlerTester, + ) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisRtcEngine = FakeIrisRtcEngine(isMockChannel: true); + await fakeIrisRtcEngine.initialize(); + rtcChannel = await _createChannel(); + final buffer = Uint8List.fromList([1, 1]); + + rtcChannel.setEventHandler(RtcChannelEventHandler( + streamMessageError: + (int uid, int streamId, ErrorCode error, int missed, int cached) { + expectSync(uid, 10); + expectSync(streamId, 20); + expectSync(error, ErrorCode.AdmInitPlayout); + expectSync(missed, 10); + expectSync(cached, 20); + eventHandlerTester.markEventCalled(); + }, + )); + + await fakeIrisRtcEngine.fireAndWaitEvent( + tester, + 'onStreamMessageError', + '{"channelId":"testapi","uid":10,"streamId":20,"code":1008,"missed":10,"cached":20}', + ); + }); + + testEventCall('channelMediaRelayStateChanged', ( + WidgetTester tester, + EventHandlerTester eventHandlerTester, + ) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisRtcEngine = FakeIrisRtcEngine(isMockChannel: true); + await fakeIrisRtcEngine.initialize(); + rtcChannel = await _createChannel(); + + rtcChannel.setEventHandler(RtcChannelEventHandler( + channelMediaRelayStateChanged: + (ChannelMediaRelayState state, ChannelMediaRelayError code) { + expectSync(state, ChannelMediaRelayState.Running); + expectSync(code, ChannelMediaRelayError.FailedPacketReceivedFromSource); + + eventHandlerTester.markEventCalled(); + }, + )); + + await fakeIrisRtcEngine.fireAndWaitEvent( + tester, + 'onChannelMediaRelayStateChanged', + '{"channelId":"testapi","state":2,"code":6}', + ); + }); + + testEventCall('channelMediaRelayEvent', ( + WidgetTester tester, + EventHandlerTester eventHandlerTester, + ) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisRtcEngine = FakeIrisRtcEngine(isMockChannel: true); + await fakeIrisRtcEngine.initialize(); + rtcChannel = await _createChannel(); + + rtcChannel.setEventHandler(RtcChannelEventHandler( + channelMediaRelayEvent: (ChannelMediaRelayEvent code) { + expectSync(code, ChannelMediaRelayEvent.JoinedDestinationChannel); + + eventHandlerTester.markEventCalled(); + }, + )); + + await fakeIrisRtcEngine.fireAndWaitEvent( + tester, + 'onChannelMediaRelayEvent', + '{"channelId":"testapi","code":3}', + ); + }); + + testEventCall('metadataReceived', ( + WidgetTester tester, + EventHandlerTester eventHandlerTester, + ) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisRtcEngine = FakeIrisRtcEngine(isMockChannel: true); + await fakeIrisRtcEngine.initialize(); + rtcChannel = await _createChannel(); + + final buffer = Uint8List.fromList([1, 1]); + final Metadata expectSyncedMetadata = Metadata(10, 1000); + + rtcChannel.setEventHandler(RtcChannelEventHandler( + metadataReceived: (Metadata metadata) { + expectSync(metadata.uid, expectSyncedMetadata.uid); + expectSync(metadata.timeStampMs, expectSyncedMetadata.timeStampMs); + expectSync(metadata.buffer, buffer); + + eventHandlerTester.markEventCalled(); + }, + )); + + await fakeIrisRtcEngine.fireAndWaitEvent( + tester, + 'onMetadataReceived', + '{"channelId":"testapi","metadata":${jsonEncode(expectSyncedMetadata.toJson())}}', + buffer: buffer, + bufferSize: 2, + ); + }); + + testEventCall('audioPublishStateChanged', ( + WidgetTester tester, + EventHandlerTester eventHandlerTester, + ) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisRtcEngine = FakeIrisRtcEngine(isMockChannel: true); + await fakeIrisRtcEngine.initialize(); + rtcChannel = await _createChannel(); + + rtcChannel.setEventHandler(RtcChannelEventHandler( + audioPublishStateChanged: (String channel, StreamPublishState oldState, + StreamPublishState newState, int elapseSinceLastState) { + expectSync(channel, 'testapi'); + expectSync(oldState, StreamPublishState.NoPublished); + expectSync(newState, StreamPublishState.Published); + expectSync(elapseSinceLastState, 100); + eventHandlerTester.markEventCalled(); + }, + )); + + await fakeIrisRtcEngine.fireAndWaitEvent( + tester, + 'onAudioPublishStateChanged', + '{"channelId":"testapi","oldState":1,"newState":3,"elapseSinceLastState":100}', + ); + }); + + testEventCall('videoPublishStateChanged', ( + WidgetTester tester, + EventHandlerTester eventHandlerTester, + ) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisRtcEngine = FakeIrisRtcEngine(isMockChannel: true); + await fakeIrisRtcEngine.initialize(); + rtcChannel = await _createChannel(); + + rtcChannel.setEventHandler(RtcChannelEventHandler( + videoPublishStateChanged: (String channel, StreamPublishState oldState, + StreamPublishState newState, int elapseSinceLastState) { + expectSync(channel, 'testapi'); + expectSync(oldState, StreamPublishState.NoPublished); + expectSync(newState, StreamPublishState.Published); + expectSync(elapseSinceLastState, 100); + eventHandlerTester.markEventCalled(); + }, + )); + + await fakeIrisRtcEngine.fireAndWaitEvent( + tester, + 'onVideoPublishStateChanged', + '{"channelId":"testapi","oldState":1,"newState":3,"elapseSinceLastState":100}', + ); + }); + + testEventCall('audioSubscribeStateChanged', ( + WidgetTester tester, + EventHandlerTester eventHandlerTester, + ) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisRtcEngine = FakeIrisRtcEngine(isMockChannel: true); + await fakeIrisRtcEngine.initialize(); + rtcChannel = await _createChannel(); + + rtcChannel.setEventHandler(RtcChannelEventHandler( + audioSubscribeStateChanged: ( + String channel, + int uid, + StreamSubscribeState oldState, + StreamSubscribeState newState, + int elapseSinceLastState, + ) { + expectSync(channel, 'testapi'); + expectSync(uid, 10); + expectSync(oldState, StreamSubscribeState.NoSubscribed); + expectSync(newState, StreamSubscribeState.Subscribing); + expectSync(elapseSinceLastState, 100); + eventHandlerTester.markEventCalled(); + }, + )); + + await fakeIrisRtcEngine.fireAndWaitEvent( + tester, + 'onAudioSubscribeStateChanged', + '{"channelId":"testapi","uid":10,"oldState":1,"newState":2,"elapseSinceLastState":100}', + ); + }); + + testEventCall('videoSubscribeStateChanged', ( + WidgetTester tester, + EventHandlerTester eventHandlerTester, + ) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisRtcEngine = FakeIrisRtcEngine(isMockChannel: true); + await fakeIrisRtcEngine.initialize(); + rtcChannel = await _createChannel(); + + rtcChannel.setEventHandler(RtcChannelEventHandler( + videoSubscribeStateChanged: ( + String channel, + int uid, + StreamSubscribeState oldState, + StreamSubscribeState newState, + int elapseSinceLastState, + ) { + expectSync(channel, 'testapi'); + expectSync(uid, 10); + expectSync(oldState, StreamSubscribeState.Subscribing); + expectSync(newState, StreamSubscribeState.Idle); + expectSync(elapseSinceLastState, 100); + eventHandlerTester.markEventCalled(); + }, + )); + + await fakeIrisRtcEngine.fireAndWaitEvent( + tester, + 'onVideoSubscribeStateChanged', + '{"channelId":"testapi","uid":10,"oldState":2,"newState":0,"elapseSinceLastState":100}', + ); + }); + + testEventCall('rtmpStreamingEvent', ( + WidgetTester tester, + EventHandlerTester eventHandlerTester, + ) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisRtcEngine = FakeIrisRtcEngine(isMockChannel: true); + await fakeIrisRtcEngine.initialize(); + rtcChannel = await _createChannel(); + + rtcChannel.setEventHandler(RtcChannelEventHandler( + rtmpStreamingEvent: (String url, RtmpStreamingEvent eventCode) { + expectSync(url, 'https://example.com'); + expectSync(eventCode, RtmpStreamingEvent.UrlAlreadyInUse); + + eventHandlerTester.markEventCalled(); + }, + )); + + await fakeIrisRtcEngine.fireAndWaitEvent( + tester, + 'onRtmpStreamingEvent', + '{"channelId":"testapi","url":"https://example.com","eventCode":2}', + ); + }); + + testEventCall('userSuperResolutionEnabled', ( + WidgetTester tester, + EventHandlerTester eventHandlerTester, + ) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisRtcEngine = FakeIrisRtcEngine(isMockChannel: true); + await fakeIrisRtcEngine.initialize(); + rtcChannel = await _createChannel(); + + rtcChannel.setEventHandler(RtcChannelEventHandler( + userSuperResolutionEnabled: + (int uid, bool enabled, SuperResolutionStateReason reason) { + expectSync(uid, 10); + expectSync(enabled, true); + expectSync(reason, SuperResolutionStateReason.StreamOverLimitation); + + eventHandlerTester.markEventCalled(); + }, + )); + + await fakeIrisRtcEngine.fireAndWaitEvent( + tester, + 'onUserSuperResolutionEnabled', + '{"channelId":"testapi","uid":10,"enabled":true,"reason":1}', + ); + }); +} diff --git a/integration_test_app/integration_test/agora_rtc_channel_event_handler_smoke_test.dart b/integration_test_app/integration_test/agora_rtc_channel_event_handler_smoke_test.dart new file mode 100644 index 000000000..f03865e3d --- /dev/null +++ b/integration_test_app/integration_test/agora_rtc_channel_event_handler_smoke_test.dart @@ -0,0 +1,9 @@ +import 'package:integration_test/integration_test.dart'; + +import 'agora_rtc_channel_event_handler_smoke_test.generated.dart' as rtc_channel_event; + +void main() { + IntegrationTestWidgetsFlutterBinding.ensureInitialized(); + + rtc_channel_event.rtcChannelEventHandlerSomkeTestCases(); +} diff --git a/integration_test_app/integration_test/agora_rtc_channel_event_handler_smoke_test.generated.dart b/integration_test_app/integration_test/agora_rtc_channel_event_handler_smoke_test.generated.dart new file mode 100644 index 000000000..295078687 --- /dev/null +++ b/integration_test_app/integration_test/agora_rtc_channel_event_handler_smoke_test.generated.dart @@ -0,0 +1,853 @@ +import 'package:agora_rtc_engine/rtc_channel.dart'; +import 'package:agora_rtc_engine/rtc_engine.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:integration_test_app/main.dart' as app; +import 'package:integration_test_app/src/fake_iris_rtc_engine.dart'; + +void rtcChannelEventHandlerSomkeTestCases() { + testWidgets('onChannelWarning', (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + FakeIrisRtcEngine fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + final rtcEngine = await RtcEngine.create('123'); + final rtcChannel = await RtcChannel.create('testapi'); + bool warningCalled = false; + rtcChannel.setEventHandler(RtcChannelEventHandler( + warning: (warn) { + warningCalled = true; + }, + )); + + fakeIrisEngine.fireRtcChannelEvent('onChannelWarning'); +// Wait for the `EventChannel` event be sent from Android/iOS side + await tester.pump(const Duration(milliseconds: 500)); + expect(warningCalled, isTrue); + + await rtcChannel.destroy(); + await rtcEngine.destroy(); + fakeIrisEngine.dispose(); + }); + testWidgets('onChannelError', (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + FakeIrisRtcEngine fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + final rtcEngine = await RtcEngine.create('123'); + final rtcChannel = await RtcChannel.create('testapi'); + bool errorCalled = false; + rtcChannel.setEventHandler(RtcChannelEventHandler( + error: (err) { + errorCalled = true; + }, + )); + + fakeIrisEngine.fireRtcChannelEvent('onChannelError'); +// Wait for the `EventChannel` event be sent from Android/iOS side + await tester.pump(const Duration(milliseconds: 500)); + expect(errorCalled, isTrue); + + await rtcChannel.destroy(); + await rtcEngine.destroy(); + fakeIrisEngine.dispose(); + }); + testWidgets('onJoinChannelSuccess', (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + FakeIrisRtcEngine fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + final rtcEngine = await RtcEngine.create('123'); + final rtcChannel = await RtcChannel.create('testapi'); + bool joinChannelSuccessCalled = false; + rtcChannel.setEventHandler(RtcChannelEventHandler( + joinChannelSuccess: (channel, uid, elapsed) { + joinChannelSuccessCalled = true; + }, + )); + + fakeIrisEngine.fireRtcChannelEvent('onJoinChannelSuccess'); +// Wait for the `EventChannel` event be sent from Android/iOS side + await tester.pump(const Duration(milliseconds: 500)); + expect(joinChannelSuccessCalled, isTrue); + + await rtcChannel.destroy(); + await rtcEngine.destroy(); + fakeIrisEngine.dispose(); + }); + testWidgets('onRejoinChannelSuccess', (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + FakeIrisRtcEngine fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + final rtcEngine = await RtcEngine.create('123'); + final rtcChannel = await RtcChannel.create('testapi'); + bool rejoinChannelSuccessCalled = false; + rtcChannel.setEventHandler(RtcChannelEventHandler( + rejoinChannelSuccess: (channel, uid, elapsed) { + rejoinChannelSuccessCalled = true; + }, + )); + + fakeIrisEngine.fireRtcChannelEvent('onRejoinChannelSuccess'); +// Wait for the `EventChannel` event be sent from Android/iOS side + await tester.pump(const Duration(milliseconds: 500)); + expect(rejoinChannelSuccessCalled, isTrue); + + await rtcChannel.destroy(); + await rtcEngine.destroy(); + fakeIrisEngine.dispose(); + }); + testWidgets('onLeaveChannel', (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + FakeIrisRtcEngine fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + final rtcEngine = await RtcEngine.create('123'); + final rtcChannel = await RtcChannel.create('testapi'); + bool leaveChannelCalled = false; + rtcChannel.setEventHandler(RtcChannelEventHandler( + leaveChannel: (stats) { + leaveChannelCalled = true; + }, + )); + + fakeIrisEngine.fireRtcChannelEvent('onLeaveChannel'); +// Wait for the `EventChannel` event be sent from Android/iOS side + await tester.pump(const Duration(milliseconds: 500)); + expect(leaveChannelCalled, isTrue); + + await rtcChannel.destroy(); + await rtcEngine.destroy(); + fakeIrisEngine.dispose(); + }); + testWidgets('onClientRoleChanged', (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + FakeIrisRtcEngine fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + final rtcEngine = await RtcEngine.create('123'); + final rtcChannel = await RtcChannel.create('testapi'); + bool clientRoleChangedCalled = false; + rtcChannel.setEventHandler(RtcChannelEventHandler( + clientRoleChanged: (oldRole, newRole) { + clientRoleChangedCalled = true; + }, + )); + + fakeIrisEngine.fireRtcChannelEvent('onClientRoleChanged'); +// Wait for the `EventChannel` event be sent from Android/iOS side + await tester.pump(const Duration(milliseconds: 500)); + expect(clientRoleChangedCalled, isTrue); + + await rtcChannel.destroy(); + await rtcEngine.destroy(); + fakeIrisEngine.dispose(); + }); + testWidgets('onUserJoined', (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + FakeIrisRtcEngine fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + final rtcEngine = await RtcEngine.create('123'); + final rtcChannel = await RtcChannel.create('testapi'); + bool userJoinedCalled = false; + rtcChannel.setEventHandler(RtcChannelEventHandler( + userJoined: (uid, elapsed) { + userJoinedCalled = true; + }, + )); + + fakeIrisEngine.fireRtcChannelEvent('onUserJoined'); +// Wait for the `EventChannel` event be sent from Android/iOS side + await tester.pump(const Duration(milliseconds: 500)); + expect(userJoinedCalled, isTrue); + + await rtcChannel.destroy(); + await rtcEngine.destroy(); + fakeIrisEngine.dispose(); + }); + testWidgets('onUserOffline', (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + FakeIrisRtcEngine fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + final rtcEngine = await RtcEngine.create('123'); + final rtcChannel = await RtcChannel.create('testapi'); + bool userOfflineCalled = false; + rtcChannel.setEventHandler(RtcChannelEventHandler( + userOffline: (uid, reason) { + userOfflineCalled = true; + }, + )); + + fakeIrisEngine.fireRtcChannelEvent('onUserOffline'); +// Wait for the `EventChannel` event be sent from Android/iOS side + await tester.pump(const Duration(milliseconds: 500)); + expect(userOfflineCalled, isTrue); + + await rtcChannel.destroy(); + await rtcEngine.destroy(); + fakeIrisEngine.dispose(); + }); + testWidgets('onConnectionStateChanged', (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + FakeIrisRtcEngine fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + final rtcEngine = await RtcEngine.create('123'); + final rtcChannel = await RtcChannel.create('testapi'); + bool connectionStateChangedCalled = false; + rtcChannel.setEventHandler(RtcChannelEventHandler( + connectionStateChanged: (state, reason) { + connectionStateChangedCalled = true; + }, + )); + + fakeIrisEngine.fireRtcChannelEvent('onConnectionStateChanged'); +// Wait for the `EventChannel` event be sent from Android/iOS side + await tester.pump(const Duration(milliseconds: 500)); + expect(connectionStateChangedCalled, isTrue); + + await rtcChannel.destroy(); + await rtcEngine.destroy(); + fakeIrisEngine.dispose(); + }); + testWidgets('onConnectionLost', (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + FakeIrisRtcEngine fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + final rtcEngine = await RtcEngine.create('123'); + final rtcChannel = await RtcChannel.create('testapi'); + bool connectionLostCalled = false; + rtcChannel.setEventHandler(RtcChannelEventHandler( + connectionLost: () { + connectionLostCalled = true; + }, + )); + + fakeIrisEngine.fireRtcChannelEvent('onConnectionLost'); +// Wait for the `EventChannel` event be sent from Android/iOS side + await tester.pump(const Duration(milliseconds: 500)); + expect(connectionLostCalled, isTrue); + + await rtcChannel.destroy(); + await rtcEngine.destroy(); + fakeIrisEngine.dispose(); + }); + testWidgets('onTokenPrivilegeWillExpire', (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + FakeIrisRtcEngine fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + final rtcEngine = await RtcEngine.create('123'); + final rtcChannel = await RtcChannel.create('testapi'); + bool tokenPrivilegeWillExpireCalled = false; + rtcChannel.setEventHandler(RtcChannelEventHandler( + tokenPrivilegeWillExpire: (token) { + tokenPrivilegeWillExpireCalled = true; + }, + )); + + fakeIrisEngine.fireRtcChannelEvent('onTokenPrivilegeWillExpire'); +// Wait for the `EventChannel` event be sent from Android/iOS side + await tester.pump(const Duration(milliseconds: 500)); + expect(tokenPrivilegeWillExpireCalled, isTrue); + + await rtcChannel.destroy(); + await rtcEngine.destroy(); + fakeIrisEngine.dispose(); + }); + testWidgets('onRequestToken', (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + FakeIrisRtcEngine fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + final rtcEngine = await RtcEngine.create('123'); + final rtcChannel = await RtcChannel.create('testapi'); + bool requestTokenCalled = false; + rtcChannel.setEventHandler(RtcChannelEventHandler( + requestToken: () { + requestTokenCalled = true; + }, + )); + + fakeIrisEngine.fireRtcChannelEvent('onRequestToken'); +// Wait for the `EventChannel` event be sent from Android/iOS side + await tester.pump(const Duration(milliseconds: 500)); + expect(requestTokenCalled, isTrue); + + await rtcChannel.destroy(); + await rtcEngine.destroy(); + fakeIrisEngine.dispose(); + }); + testWidgets('onActiveSpeaker', (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + FakeIrisRtcEngine fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + final rtcEngine = await RtcEngine.create('123'); + final rtcChannel = await RtcChannel.create('testapi'); + bool activeSpeakerCalled = false; + rtcChannel.setEventHandler(RtcChannelEventHandler( + activeSpeaker: (uid) { + activeSpeakerCalled = true; + }, + )); + + fakeIrisEngine.fireRtcChannelEvent('onActiveSpeaker'); +// Wait for the `EventChannel` event be sent from Android/iOS side + await tester.pump(const Duration(milliseconds: 500)); + expect(activeSpeakerCalled, isTrue); + + await rtcChannel.destroy(); + await rtcEngine.destroy(); + fakeIrisEngine.dispose(); + }); + testWidgets('onVideoSizeChanged', (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + FakeIrisRtcEngine fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + final rtcEngine = await RtcEngine.create('123'); + final rtcChannel = await RtcChannel.create('testapi'); + bool videoSizeChangedCalled = false; + rtcChannel.setEventHandler(RtcChannelEventHandler( + videoSizeChanged: (uid, width, height, rotation) { + videoSizeChangedCalled = true; + }, + )); + + fakeIrisEngine.fireRtcChannelEvent('onVideoSizeChanged'); +// Wait for the `EventChannel` event be sent from Android/iOS side + await tester.pump(const Duration(milliseconds: 500)); + expect(videoSizeChangedCalled, isTrue); + + await rtcChannel.destroy(); + await rtcEngine.destroy(); + fakeIrisEngine.dispose(); + }); + testWidgets('onRemoteVideoStateChanged', (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + FakeIrisRtcEngine fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + final rtcEngine = await RtcEngine.create('123'); + final rtcChannel = await RtcChannel.create('testapi'); + bool remoteVideoStateChangedCalled = false; + rtcChannel.setEventHandler(RtcChannelEventHandler( + remoteVideoStateChanged: (uid, state, reason, elapsed) { + remoteVideoStateChangedCalled = true; + }, + )); + + fakeIrisEngine.fireRtcChannelEvent('onRemoteVideoStateChanged'); +// Wait for the `EventChannel` event be sent from Android/iOS side + await tester.pump(const Duration(milliseconds: 500)); + expect(remoteVideoStateChangedCalled, isTrue); + + await rtcChannel.destroy(); + await rtcEngine.destroy(); + fakeIrisEngine.dispose(); + }); + testWidgets('onRemoteAudioStateChanged', (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + FakeIrisRtcEngine fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + final rtcEngine = await RtcEngine.create('123'); + final rtcChannel = await RtcChannel.create('testapi'); + bool remoteAudioStateChangedCalled = false; + rtcChannel.setEventHandler(RtcChannelEventHandler( + remoteAudioStateChanged: (uid, state, reason, elapsed) { + remoteAudioStateChangedCalled = true; + }, + )); + + fakeIrisEngine.fireRtcChannelEvent('onRemoteAudioStateChanged'); +// Wait for the `EventChannel` event be sent from Android/iOS side + await tester.pump(const Duration(milliseconds: 500)); + expect(remoteAudioStateChangedCalled, isTrue); + + await rtcChannel.destroy(); + await rtcEngine.destroy(); + fakeIrisEngine.dispose(); + }); + testWidgets('onLocalPublishFallbackToAudioOnly', (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + FakeIrisRtcEngine fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + final rtcEngine = await RtcEngine.create('123'); + final rtcChannel = await RtcChannel.create('testapi'); + bool localPublishFallbackToAudioOnlyCalled = false; + rtcChannel.setEventHandler(RtcChannelEventHandler( + localPublishFallbackToAudioOnly: (isFallbackOrRecover) { + localPublishFallbackToAudioOnlyCalled = true; + }, + )); + + fakeIrisEngine.fireRtcChannelEvent('onLocalPublishFallbackToAudioOnly'); +// Wait for the `EventChannel` event be sent from Android/iOS side + await tester.pump(const Duration(milliseconds: 500)); + expect(localPublishFallbackToAudioOnlyCalled, isTrue); + + await rtcChannel.destroy(); + await rtcEngine.destroy(); + fakeIrisEngine.dispose(); + }); + testWidgets('onRemoteSubscribeFallbackToAudioOnly', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + FakeIrisRtcEngine fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + final rtcEngine = await RtcEngine.create('123'); + final rtcChannel = await RtcChannel.create('testapi'); + bool remoteSubscribeFallbackToAudioOnlyCalled = false; + rtcChannel.setEventHandler(RtcChannelEventHandler( + remoteSubscribeFallbackToAudioOnly: (uid, isFallbackOrRecover) { + remoteSubscribeFallbackToAudioOnlyCalled = true; + }, + )); + + fakeIrisEngine.fireRtcChannelEvent('onRemoteSubscribeFallbackToAudioOnly'); +// Wait for the `EventChannel` event be sent from Android/iOS side + await tester.pump(const Duration(milliseconds: 500)); + expect(remoteSubscribeFallbackToAudioOnlyCalled, isTrue); + + await rtcChannel.destroy(); + await rtcEngine.destroy(); + fakeIrisEngine.dispose(); + }); + testWidgets('onRtcStats', (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + FakeIrisRtcEngine fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + final rtcEngine = await RtcEngine.create('123'); + final rtcChannel = await RtcChannel.create('testapi'); + bool rtcStatsCalled = false; + rtcChannel.setEventHandler(RtcChannelEventHandler( + rtcStats: (stats) { + rtcStatsCalled = true; + }, + )); + + fakeIrisEngine.fireRtcChannelEvent('onRtcStats'); +// Wait for the `EventChannel` event be sent from Android/iOS side + await tester.pump(const Duration(milliseconds: 500)); + expect(rtcStatsCalled, isTrue); + + await rtcChannel.destroy(); + await rtcEngine.destroy(); + fakeIrisEngine.dispose(); + }); + testWidgets('onNetworkQuality', (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + FakeIrisRtcEngine fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + final rtcEngine = await RtcEngine.create('123'); + final rtcChannel = await RtcChannel.create('testapi'); + bool networkQualityCalled = false; + rtcChannel.setEventHandler(RtcChannelEventHandler( + networkQuality: (uid, txQuality, rxQuality) { + networkQualityCalled = true; + }, + )); + + fakeIrisEngine.fireRtcChannelEvent('onNetworkQuality'); +// Wait for the `EventChannel` event be sent from Android/iOS side + await tester.pump(const Duration(milliseconds: 500)); + expect(networkQualityCalled, isTrue); + + await rtcChannel.destroy(); + await rtcEngine.destroy(); + fakeIrisEngine.dispose(); + }); + testWidgets('onRemoteVideoStats', (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + FakeIrisRtcEngine fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + final rtcEngine = await RtcEngine.create('123'); + final rtcChannel = await RtcChannel.create('testapi'); + bool remoteVideoStatsCalled = false; + rtcChannel.setEventHandler(RtcChannelEventHandler( + remoteVideoStats: (stats) { + remoteVideoStatsCalled = true; + }, + )); + + fakeIrisEngine.fireRtcChannelEvent('onRemoteVideoStats'); +// Wait for the `EventChannel` event be sent from Android/iOS side + await tester.pump(const Duration(milliseconds: 500)); + expect(remoteVideoStatsCalled, isTrue); + + await rtcChannel.destroy(); + await rtcEngine.destroy(); + fakeIrisEngine.dispose(); + }); + testWidgets('onRemoteAudioStats', (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + FakeIrisRtcEngine fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + final rtcEngine = await RtcEngine.create('123'); + final rtcChannel = await RtcChannel.create('testapi'); + bool remoteAudioStatsCalled = false; + rtcChannel.setEventHandler(RtcChannelEventHandler( + remoteAudioStats: (stats) { + remoteAudioStatsCalled = true; + }, + )); + + fakeIrisEngine.fireRtcChannelEvent('onRemoteAudioStats'); +// Wait for the `EventChannel` event be sent from Android/iOS side + await tester.pump(const Duration(milliseconds: 500)); + expect(remoteAudioStatsCalled, isTrue); + + await rtcChannel.destroy(); + await rtcEngine.destroy(); + fakeIrisEngine.dispose(); + }); + testWidgets('onRtmpStreamingStateChanged', (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + FakeIrisRtcEngine fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + final rtcEngine = await RtcEngine.create('123'); + final rtcChannel = await RtcChannel.create('testapi'); + bool rtmpStreamingStateChangedCalled = false; + rtcChannel.setEventHandler(RtcChannelEventHandler( + rtmpStreamingStateChanged: (url, state, errCode) { + rtmpStreamingStateChangedCalled = true; + }, + )); + + fakeIrisEngine.fireRtcChannelEvent('onRtmpStreamingStateChanged'); +// Wait for the `EventChannel` event be sent from Android/iOS side + await tester.pump(const Duration(milliseconds: 500)); + expect(rtmpStreamingStateChangedCalled, isTrue); + + await rtcChannel.destroy(); + await rtcEngine.destroy(); + fakeIrisEngine.dispose(); + }); + testWidgets('onTranscodingUpdated', (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + FakeIrisRtcEngine fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + final rtcEngine = await RtcEngine.create('123'); + final rtcChannel = await RtcChannel.create('testapi'); + bool transcodingUpdatedCalled = false; + rtcChannel.setEventHandler(RtcChannelEventHandler( + transcodingUpdated: () { + transcodingUpdatedCalled = true; + }, + )); + + fakeIrisEngine.fireRtcChannelEvent('onTranscodingUpdated'); +// Wait for the `EventChannel` event be sent from Android/iOS side + await tester.pump(const Duration(milliseconds: 500)); + expect(transcodingUpdatedCalled, isTrue); + + await rtcChannel.destroy(); + await rtcEngine.destroy(); + fakeIrisEngine.dispose(); + }); + testWidgets('onStreamInjectedStatus', (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + FakeIrisRtcEngine fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + final rtcEngine = await RtcEngine.create('123'); + final rtcChannel = await RtcChannel.create('testapi'); + bool streamInjectedStatusCalled = false; + rtcChannel.setEventHandler(RtcChannelEventHandler( + streamInjectedStatus: (url, uid, status) { + streamInjectedStatusCalled = true; + }, + )); + + fakeIrisEngine.fireRtcChannelEvent('onStreamInjectedStatus'); +// Wait for the `EventChannel` event be sent from Android/iOS side + await tester.pump(const Duration(milliseconds: 500)); + expect(streamInjectedStatusCalled, isTrue); + + await rtcChannel.destroy(); + await rtcEngine.destroy(); + fakeIrisEngine.dispose(); + }); + testWidgets('onStreamMessage', (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + FakeIrisRtcEngine fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + final rtcEngine = await RtcEngine.create('123'); + final rtcChannel = await RtcChannel.create('testapi'); + bool streamMessageCalled = false; + rtcChannel.setEventHandler(RtcChannelEventHandler( + streamMessage: (uid, streamId, data) { + streamMessageCalled = true; + }, + )); + + fakeIrisEngine.fireRtcChannelEvent('onStreamMessage'); +// Wait for the `EventChannel` event be sent from Android/iOS side + await tester.pump(const Duration(milliseconds: 500)); + expect(streamMessageCalled, isTrue); + + await rtcChannel.destroy(); + await rtcEngine.destroy(); + fakeIrisEngine.dispose(); + }); + testWidgets('onStreamMessageError', (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + FakeIrisRtcEngine fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + final rtcEngine = await RtcEngine.create('123'); + final rtcChannel = await RtcChannel.create('testapi'); + bool streamMessageErrorCalled = false; + rtcChannel.setEventHandler(RtcChannelEventHandler( + streamMessageError: (uid, streamId, error, missed, cached) { + streamMessageErrorCalled = true; + }, + )); + + fakeIrisEngine.fireRtcChannelEvent('onStreamMessageError'); +// Wait for the `EventChannel` event be sent from Android/iOS side + await tester.pump(const Duration(milliseconds: 500)); + expect(streamMessageErrorCalled, isTrue); + + await rtcChannel.destroy(); + await rtcEngine.destroy(); + fakeIrisEngine.dispose(); + }); + testWidgets('onChannelMediaRelayStateChanged', (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + FakeIrisRtcEngine fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + final rtcEngine = await RtcEngine.create('123'); + final rtcChannel = await RtcChannel.create('testapi'); + bool channelMediaRelayStateChangedCalled = false; + rtcChannel.setEventHandler(RtcChannelEventHandler( + channelMediaRelayStateChanged: (state, code) { + channelMediaRelayStateChangedCalled = true; + }, + )); + + fakeIrisEngine.fireRtcChannelEvent('onChannelMediaRelayStateChanged'); +// Wait for the `EventChannel` event be sent from Android/iOS side + await tester.pump(const Duration(milliseconds: 500)); + expect(channelMediaRelayStateChangedCalled, isTrue); + + await rtcChannel.destroy(); + await rtcEngine.destroy(); + fakeIrisEngine.dispose(); + }); + testWidgets('onChannelMediaRelayEvent', (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + FakeIrisRtcEngine fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + final rtcEngine = await RtcEngine.create('123'); + final rtcChannel = await RtcChannel.create('testapi'); + bool channelMediaRelayEventCalled = false; + rtcChannel.setEventHandler(RtcChannelEventHandler( + channelMediaRelayEvent: (code) { + channelMediaRelayEventCalled = true; + }, + )); + + fakeIrisEngine.fireRtcChannelEvent('onChannelMediaRelayEvent'); +// Wait for the `EventChannel` event be sent from Android/iOS side + await tester.pump(const Duration(milliseconds: 500)); + expect(channelMediaRelayEventCalled, isTrue); + + await rtcChannel.destroy(); + await rtcEngine.destroy(); + fakeIrisEngine.dispose(); + }); + testWidgets('onAudioPublishStateChanged', (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + FakeIrisRtcEngine fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + final rtcEngine = await RtcEngine.create('123'); + final rtcChannel = await RtcChannel.create('testapi'); + bool audioPublishStateChangedCalled = false; + rtcChannel.setEventHandler(RtcChannelEventHandler( + audioPublishStateChanged: + (channel, oldState, newState, elapseSinceLastState) { + audioPublishStateChangedCalled = true; + }, + )); + + fakeIrisEngine.fireRtcChannelEvent('onAudioPublishStateChanged'); +// Wait for the `EventChannel` event be sent from Android/iOS side + await tester.pump(const Duration(milliseconds: 500)); + expect(audioPublishStateChangedCalled, isTrue); + + await rtcChannel.destroy(); + await rtcEngine.destroy(); + fakeIrisEngine.dispose(); + }); + testWidgets('onVideoPublishStateChanged', (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + FakeIrisRtcEngine fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + final rtcEngine = await RtcEngine.create('123'); + final rtcChannel = await RtcChannel.create('testapi'); + bool videoPublishStateChangedCalled = false; + rtcChannel.setEventHandler(RtcChannelEventHandler( + videoPublishStateChanged: + (channel, oldState, newState, elapseSinceLastState) { + videoPublishStateChangedCalled = true; + }, + )); + + fakeIrisEngine.fireRtcChannelEvent('onVideoPublishStateChanged'); +// Wait for the `EventChannel` event be sent from Android/iOS side + await tester.pump(const Duration(milliseconds: 500)); + expect(videoPublishStateChangedCalled, isTrue); + + await rtcChannel.destroy(); + await rtcEngine.destroy(); + fakeIrisEngine.dispose(); + }); + testWidgets('onAudioSubscribeStateChanged', (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + FakeIrisRtcEngine fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + final rtcEngine = await RtcEngine.create('123'); + final rtcChannel = await RtcChannel.create('testapi'); + bool audioSubscribeStateChangedCalled = false; + rtcChannel.setEventHandler(RtcChannelEventHandler( + audioSubscribeStateChanged: + (channel, uid, oldState, newState, elapseSinceLastState) { + audioSubscribeStateChangedCalled = true; + }, + )); + + fakeIrisEngine.fireRtcChannelEvent('onAudioSubscribeStateChanged'); +// Wait for the `EventChannel` event be sent from Android/iOS side + await tester.pump(const Duration(milliseconds: 500)); + expect(audioSubscribeStateChangedCalled, isTrue); + + await rtcChannel.destroy(); + await rtcEngine.destroy(); + fakeIrisEngine.dispose(); + }); + testWidgets('onVideoSubscribeStateChanged', (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + FakeIrisRtcEngine fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + final rtcEngine = await RtcEngine.create('123'); + final rtcChannel = await RtcChannel.create('testapi'); + bool videoSubscribeStateChangedCalled = false; + rtcChannel.setEventHandler(RtcChannelEventHandler( + videoSubscribeStateChanged: + (channel, uid, oldState, newState, elapseSinceLastState) { + videoSubscribeStateChangedCalled = true; + }, + )); + + fakeIrisEngine.fireRtcChannelEvent('onVideoSubscribeStateChanged'); +// Wait for the `EventChannel` event be sent from Android/iOS side + await tester.pump(const Duration(milliseconds: 500)); + expect(videoSubscribeStateChangedCalled, isTrue); + + await rtcChannel.destroy(); + await rtcEngine.destroy(); + fakeIrisEngine.dispose(); + }); + testWidgets('onRtmpStreamingEvent', (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + FakeIrisRtcEngine fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + final rtcEngine = await RtcEngine.create('123'); + final rtcChannel = await RtcChannel.create('testapi'); + bool rtmpStreamingEventCalled = false; + rtcChannel.setEventHandler(RtcChannelEventHandler( + rtmpStreamingEvent: (url, eventCode) { + rtmpStreamingEventCalled = true; + }, + )); + + fakeIrisEngine.fireRtcChannelEvent('onRtmpStreamingEvent'); +// Wait for the `EventChannel` event be sent from Android/iOS side + await tester.pump(const Duration(milliseconds: 500)); + expect(rtmpStreamingEventCalled, isTrue); + + await rtcChannel.destroy(); + await rtcEngine.destroy(); + fakeIrisEngine.dispose(); + }); + testWidgets('onUserSuperResolutionEnabled', (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + FakeIrisRtcEngine fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + final rtcEngine = await RtcEngine.create('123'); + final rtcChannel = await RtcChannel.create('testapi'); + bool userSuperResolutionEnabledCalled = false; + rtcChannel.setEventHandler(RtcChannelEventHandler( + userSuperResolutionEnabled: (uid, enabled, reason) { + userSuperResolutionEnabledCalled = true; + }, + )); + + fakeIrisEngine.fireRtcChannelEvent('onUserSuperResolutionEnabled'); +// Wait for the `EventChannel` event be sent from Android/iOS side + await tester.pump(const Duration(milliseconds: 500)); + expect(userSuperResolutionEnabledCalled, isTrue); + + await rtcChannel.destroy(); + await rtcEngine.destroy(); + fakeIrisEngine.dispose(); + }); +} diff --git a/integration_test_app/integration_test/agora_rtc_device_manager_api_smoke_test.dart b/integration_test_app/integration_test/agora_rtc_device_manager_api_smoke_test.dart new file mode 100644 index 000000000..2fe53ae90 --- /dev/null +++ b/integration_test_app/integration_test/agora_rtc_device_manager_api_smoke_test.dart @@ -0,0 +1,41 @@ +import 'dart:io'; + +import 'package:agora_rtc_engine/rtc_engine.dart'; +import 'package:flutter/services.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:integration_test/integration_test.dart'; +import 'package:integration_test_app/main.dart' as app; + +import 'agora_rtc_device_manager_api_smoke_test.generated.dart' + as rtc_device_manager; + +void main() { + IntegrationTestWidgetsFlutterBinding.ensureInitialized(); + + rtc_device_manager.rtcDeviceManagerSmokeTestCases(); + + testWidgets( + 'getVideoDevice', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + String engineAppId = const String.fromEnvironment('TEST_APP_ID', + defaultValue: ''); + + RtcEngine rtcEngine = await RtcEngine.create(engineAppId); + + final deviceManager = rtcEngine.deviceManager; + + try { + await rtcEngine.enableVideo(); + await deviceManager.getVideoDevice(); + } catch (e) { + expect(e is PlatformException, isTrue); + } + + await rtcEngine.destroy(); + }, + skip: !(Platform.isMacOS || Platform.isWindows || Platform.isLinux), + ); +} diff --git a/integration_test_app/integration_test/agora_rtc_device_manager_api_smoke_test.generated.dart b/integration_test_app/integration_test/agora_rtc_device_manager_api_smoke_test.generated.dart new file mode 100644 index 000000000..e59405573 --- /dev/null +++ b/integration_test_app/integration_test/agora_rtc_device_manager_api_smoke_test.generated.dart @@ -0,0 +1,662 @@ +import 'dart:io'; + +import 'package:flutter/services.dart'; +import 'package:agora_rtc_engine/rtc_engine.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:integration_test_app/main.dart' as app; + +void rtcDeviceManagerSmokeTestCases() { + testWidgets( + 'enumerateAudioPlaybackDevices', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + String engineAppId = const String.fromEnvironment('TEST_APP_ID', + defaultValue: ''); + + RtcEngine rtcEngine = await RtcEngine.create(engineAppId); + final deviceManager = rtcEngine.deviceManager; + + try { + await deviceManager.enumerateAudioPlaybackDevices(); + } catch (e) { + if (e is! PlatformException) { + rethrow; + } + expect(e.code != '-7', isTrue); + } + + await rtcEngine.destroy(); + }, + skip: !(Platform.isMacOS || Platform.isWindows || Platform.isLinux), + ); + + testWidgets( + 'setAudioPlaybackDevice', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + String engineAppId = const String.fromEnvironment('TEST_APP_ID', + defaultValue: ''); + + RtcEngine rtcEngine = await RtcEngine.create(engineAppId); + final deviceManager = rtcEngine.deviceManager; + + try { + const String deviceId = "hello"; + await deviceManager.setAudioPlaybackDevice( + deviceId, + ); + } catch (e) { + if (e is! PlatformException) { + rethrow; + } + expect(e.code != '-7', isTrue); + } + + await rtcEngine.destroy(); + }, + skip: !(Platform.isMacOS || Platform.isWindows || Platform.isLinux), + ); + + testWidgets( + 'getAudioPlaybackDevice', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + String engineAppId = const String.fromEnvironment('TEST_APP_ID', + defaultValue: ''); + + RtcEngine rtcEngine = await RtcEngine.create(engineAppId); + final deviceManager = rtcEngine.deviceManager; + + try { + await deviceManager.getAudioPlaybackDevice(); + } catch (e) { + if (e is! PlatformException) { + rethrow; + } + expect(e.code != '-7', isTrue); + } + + await rtcEngine.destroy(); + }, + skip: !(Platform.isMacOS || Platform.isWindows || Platform.isLinux), + ); + + testWidgets( + 'getAudioPlaybackDeviceInfo', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + String engineAppId = const String.fromEnvironment('TEST_APP_ID', + defaultValue: ''); + + RtcEngine rtcEngine = await RtcEngine.create(engineAppId); + final deviceManager = rtcEngine.deviceManager; + + try { + await deviceManager.getAudioPlaybackDeviceInfo(); + } catch (e) { + if (e is! PlatformException) { + rethrow; + } + expect(e.code != '-7', isTrue); + } + + await rtcEngine.destroy(); + }, + skip: !(Platform.isMacOS || Platform.isWindows || Platform.isLinux), + ); + + testWidgets( + 'setAudioPlaybackDeviceVolume', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + String engineAppId = const String.fromEnvironment('TEST_APP_ID', + defaultValue: ''); + + RtcEngine rtcEngine = await RtcEngine.create(engineAppId); + final deviceManager = rtcEngine.deviceManager; + + try { + const int volume = 10; + await deviceManager.setAudioPlaybackDeviceVolume( + volume, + ); + } catch (e) { + if (e is! PlatformException) { + rethrow; + } + expect(e.code != '-7', isTrue); + } + + await rtcEngine.destroy(); + }, + skip: !(Platform.isMacOS || Platform.isWindows || Platform.isLinux), + ); + + testWidgets( + 'getAudioPlaybackDeviceVolume', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + String engineAppId = const String.fromEnvironment('TEST_APP_ID', + defaultValue: ''); + + RtcEngine rtcEngine = await RtcEngine.create(engineAppId); + final deviceManager = rtcEngine.deviceManager; + + try { + await deviceManager.getAudioPlaybackDeviceVolume(); + } catch (e) { + if (e is! PlatformException) { + rethrow; + } + expect(e.code != '-7', isTrue); + } + + await rtcEngine.destroy(); + }, + skip: !(Platform.isMacOS || Platform.isWindows || Platform.isLinux), + ); + + testWidgets( + 'setAudioPlaybackDeviceMute', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + String engineAppId = const String.fromEnvironment('TEST_APP_ID', + defaultValue: ''); + + RtcEngine rtcEngine = await RtcEngine.create(engineAppId); + final deviceManager = rtcEngine.deviceManager; + + try { + const bool mute = true; + await deviceManager.setAudioPlaybackDeviceMute( + mute, + ); + } catch (e) { + if (e is! PlatformException) { + rethrow; + } + expect(e.code != '-7', isTrue); + } + + await rtcEngine.destroy(); + }, + skip: !(Platform.isMacOS || Platform.isWindows || Platform.isLinux), + ); + + testWidgets( + 'getAudioPlaybackDeviceMute', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + String engineAppId = const String.fromEnvironment('TEST_APP_ID', + defaultValue: ''); + + RtcEngine rtcEngine = await RtcEngine.create(engineAppId); + final deviceManager = rtcEngine.deviceManager; + + try { + await deviceManager.getAudioPlaybackDeviceMute(); + } catch (e) { + if (e is! PlatformException) { + rethrow; + } + expect(e.code != '-7', isTrue); + } + + await rtcEngine.destroy(); + }, + skip: !(Platform.isMacOS || Platform.isWindows || Platform.isLinux), + ); + + testWidgets( + 'startAudioPlaybackDeviceTest', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + String engineAppId = const String.fromEnvironment('TEST_APP_ID', + defaultValue: ''); + + RtcEngine rtcEngine = await RtcEngine.create(engineAppId); + final deviceManager = rtcEngine.deviceManager; + + try { + const String testAudioFilePath = "hello"; + await deviceManager.startAudioPlaybackDeviceTest( + testAudioFilePath, + ); + } catch (e) { + if (e is! PlatformException) { + rethrow; + } + expect(e.code != '-7', isTrue); + } + + await rtcEngine.destroy(); + }, + skip: !(Platform.isMacOS || Platform.isWindows || Platform.isLinux), + ); + + testWidgets( + 'stopAudioPlaybackDeviceTest', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + String engineAppId = const String.fromEnvironment('TEST_APP_ID', + defaultValue: ''); + + RtcEngine rtcEngine = await RtcEngine.create(engineAppId); + final deviceManager = rtcEngine.deviceManager; + + try { + await deviceManager.stopAudioPlaybackDeviceTest(); + } catch (e) { + if (e is! PlatformException) { + rethrow; + } + expect(e.code != '-7', isTrue); + } + + await rtcEngine.destroy(); + }, + skip: !(Platform.isMacOS || Platform.isWindows || Platform.isLinux), + ); + + testWidgets( + 'enumerateAudioRecordingDevices', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + String engineAppId = const String.fromEnvironment('TEST_APP_ID', + defaultValue: ''); + + RtcEngine rtcEngine = await RtcEngine.create(engineAppId); + final deviceManager = rtcEngine.deviceManager; + + try { + await deviceManager.enumerateAudioRecordingDevices(); + } catch (e) { + if (e is! PlatformException) { + rethrow; + } + expect(e.code != '-7', isTrue); + } + + await rtcEngine.destroy(); + }, + skip: !(Platform.isMacOS || Platform.isWindows || Platform.isLinux), + ); + + testWidgets( + 'setAudioRecordingDevice', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + String engineAppId = const String.fromEnvironment('TEST_APP_ID', + defaultValue: ''); + + RtcEngine rtcEngine = await RtcEngine.create(engineAppId); + final deviceManager = rtcEngine.deviceManager; + + try { + const String deviceId = "hello"; + await deviceManager.setAudioRecordingDevice( + deviceId, + ); + } catch (e) { + if (e is! PlatformException) { + rethrow; + } + expect(e.code != '-7', isTrue); + } + + await rtcEngine.destroy(); + }, + skip: !(Platform.isMacOS || Platform.isWindows || Platform.isLinux), + ); + + testWidgets( + 'getAudioRecordingDevice', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + String engineAppId = const String.fromEnvironment('TEST_APP_ID', + defaultValue: ''); + + RtcEngine rtcEngine = await RtcEngine.create(engineAppId); + final deviceManager = rtcEngine.deviceManager; + + try { + await deviceManager.getAudioRecordingDevice(); + } catch (e) { + if (e is! PlatformException) { + rethrow; + } + expect(e.code != '-7', isTrue); + } + + await rtcEngine.destroy(); + }, + skip: !(Platform.isMacOS || Platform.isWindows || Platform.isLinux), + ); + + testWidgets( + 'getAudioRecordingDeviceInfo', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + String engineAppId = const String.fromEnvironment('TEST_APP_ID', + defaultValue: ''); + + RtcEngine rtcEngine = await RtcEngine.create(engineAppId); + final deviceManager = rtcEngine.deviceManager; + + try { + await deviceManager.getAudioRecordingDeviceInfo(); + } catch (e) { + if (e is! PlatformException) { + rethrow; + } + expect(e.code != '-7', isTrue); + } + + await rtcEngine.destroy(); + }, + skip: !(Platform.isMacOS || Platform.isWindows || Platform.isLinux), + ); + + testWidgets( + 'setAudioRecordingDeviceVolume', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + String engineAppId = const String.fromEnvironment('TEST_APP_ID', + defaultValue: ''); + + RtcEngine rtcEngine = await RtcEngine.create(engineAppId); + final deviceManager = rtcEngine.deviceManager; + + try { + const int volume = 10; + await deviceManager.setAudioRecordingDeviceVolume( + volume, + ); + } catch (e) { + if (e is! PlatformException) { + rethrow; + } + expect(e.code != '-7', isTrue); + } + + await rtcEngine.destroy(); + }, + skip: !(Platform.isMacOS || Platform.isWindows || Platform.isLinux), + ); + + testWidgets( + 'getAudioRecordingDeviceVolume', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + String engineAppId = const String.fromEnvironment('TEST_APP_ID', + defaultValue: ''); + + RtcEngine rtcEngine = await RtcEngine.create(engineAppId); + final deviceManager = rtcEngine.deviceManager; + + try { + await deviceManager.getAudioRecordingDeviceVolume(); + } catch (e) { + if (e is! PlatformException) { + rethrow; + } + expect(e.code != '-7', isTrue); + } + + await rtcEngine.destroy(); + }, + skip: !(Platform.isMacOS || Platform.isWindows || Platform.isLinux), + ); + + testWidgets( + 'setAudioRecordingDeviceMute', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + String engineAppId = const String.fromEnvironment('TEST_APP_ID', + defaultValue: ''); + + RtcEngine rtcEngine = await RtcEngine.create(engineAppId); + final deviceManager = rtcEngine.deviceManager; + + try { + const bool mute = true; + await deviceManager.setAudioRecordingDeviceMute( + mute, + ); + } catch (e) { + if (e is! PlatformException) { + rethrow; + } + expect(e.code != '-7', isTrue); + } + + await rtcEngine.destroy(); + }, + skip: !(Platform.isMacOS || Platform.isWindows || Platform.isLinux), + ); + + testWidgets( + 'getAudioRecordingDeviceMute', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + String engineAppId = const String.fromEnvironment('TEST_APP_ID', + defaultValue: ''); + + RtcEngine rtcEngine = await RtcEngine.create(engineAppId); + final deviceManager = rtcEngine.deviceManager; + + try { + await deviceManager.getAudioRecordingDeviceMute(); + } catch (e) { + if (e is! PlatformException) { + rethrow; + } + expect(e.code != '-7', isTrue); + } + + await rtcEngine.destroy(); + }, + skip: !(Platform.isMacOS || Platform.isWindows || Platform.isLinux), + ); + + testWidgets( + 'startAudioRecordingDeviceTest', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + String engineAppId = const String.fromEnvironment('TEST_APP_ID', + defaultValue: ''); + + RtcEngine rtcEngine = await RtcEngine.create(engineAppId); + final deviceManager = rtcEngine.deviceManager; + + try { + const int indicationInterval = 10; + await deviceManager.startAudioRecordingDeviceTest( + indicationInterval, + ); + } catch (e) { + if (e is! PlatformException) { + rethrow; + } + expect(e.code != '-7', isTrue); + } + + await rtcEngine.destroy(); + }, + skip: !(Platform.isMacOS || Platform.isWindows || Platform.isLinux), + ); + + testWidgets( + 'stopAudioRecordingDeviceTest', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + String engineAppId = const String.fromEnvironment('TEST_APP_ID', + defaultValue: ''); + + RtcEngine rtcEngine = await RtcEngine.create(engineAppId); + final deviceManager = rtcEngine.deviceManager; + + try { + await deviceManager.stopAudioRecordingDeviceTest(); + } catch (e) { + if (e is! PlatformException) { + rethrow; + } + expect(e.code != '-7', isTrue); + } + + await rtcEngine.destroy(); + }, + skip: !(Platform.isMacOS || Platform.isWindows || Platform.isLinux), + ); + + testWidgets( + 'startAudioDeviceLoopbackTest', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + String engineAppId = const String.fromEnvironment('TEST_APP_ID', + defaultValue: ''); + + RtcEngine rtcEngine = await RtcEngine.create(engineAppId); + final deviceManager = rtcEngine.deviceManager; + + try { + const int indicationInterval = 10; + await deviceManager.startAudioDeviceLoopbackTest( + indicationInterval, + ); + } catch (e) { + if (e is! PlatformException) { + rethrow; + } + expect(e.code != '-7', isTrue); + } + + await rtcEngine.destroy(); + }, + skip: !(Platform.isMacOS || Platform.isWindows || Platform.isLinux), + ); + + testWidgets( + 'stopAudioDeviceLoopbackTest', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + String engineAppId = const String.fromEnvironment('TEST_APP_ID', + defaultValue: ''); + + RtcEngine rtcEngine = await RtcEngine.create(engineAppId); + final deviceManager = rtcEngine.deviceManager; + + try { + await deviceManager.stopAudioDeviceLoopbackTest(); + } catch (e) { + if (e is! PlatformException) { + rethrow; + } + expect(e.code != '-7', isTrue); + } + + await rtcEngine.destroy(); + }, + skip: !(Platform.isMacOS || Platform.isWindows || Platform.isLinux), + ); + + testWidgets( + 'enumerateVideoDevices', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + String engineAppId = const String.fromEnvironment('TEST_APP_ID', + defaultValue: ''); + + RtcEngine rtcEngine = await RtcEngine.create(engineAppId); + final deviceManager = rtcEngine.deviceManager; + + try { + await deviceManager.enumerateVideoDevices(); + } catch (e) { + if (e is! PlatformException) { + rethrow; + } + expect(e.code != '-7', isTrue); + } + + await rtcEngine.destroy(); + }, + skip: !(Platform.isMacOS || Platform.isWindows || Platform.isLinux), + ); + + testWidgets( + 'setVideoDevice', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + String engineAppId = const String.fromEnvironment('TEST_APP_ID', + defaultValue: ''); + + RtcEngine rtcEngine = await RtcEngine.create(engineAppId); + final deviceManager = rtcEngine.deviceManager; + + try { + const String deviceId = "hello"; + await deviceManager.setVideoDevice( + deviceId, + ); + } catch (e) { + if (e is! PlatformException) { + rethrow; + } + expect(e.code != '-7', isTrue); + } + + await rtcEngine.destroy(); + }, + skip: !(Platform.isMacOS || Platform.isWindows || Platform.isLinux), + ); +} diff --git a/integration_test_app/integration_test/agora_rtc_engine_api_smoke_test.dart b/integration_test_app/integration_test/agora_rtc_engine_api_smoke_test.dart new file mode 100644 index 000000000..7ff9250d6 --- /dev/null +++ b/integration_test_app/integration_test/agora_rtc_engine_api_smoke_test.dart @@ -0,0 +1,231 @@ +import 'dart:io'; + +import 'package:agora_rtc_engine/rtc_engine.dart'; +import 'package:flutter/foundation.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:integration_test/integration_test.dart'; +import 'package:integration_test_app/main.dart' as app; +import 'package:integration_test_app/src/configs.dart' as config; + +void main() { + IntegrationTestWidgetsFlutterBinding.ensureInitialized(); + + testWidgets( + 'can create a RtcEngine after destroy multiple times', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + RtcEngine rtcEngine = await RtcEngine.create(config.appId); + await rtcEngine.enableVideo(); + await rtcEngine.destroy(); + + rtcEngine = await RtcEngine.create(config.appId); + await rtcEngine.enableVideo(); + await rtcEngine.destroy(); + + rtcEngine = await RtcEngine.create(config.appId); + await rtcEngine.enableVideo(); + await rtcEngine.destroy(); + }, + skip: !(Platform.isAndroid || Platform.isIOS), + ); + + testWidgets( + 'getCameraMaxZoomFactor', + (WidgetTester tester) async { + RtcEngine rtcEngine = await RtcEngine.create(config.appId); + await rtcEngine.startPreview(); + try { + await rtcEngine.getCameraMaxZoomFactor(); + } catch (e) { + final exception = e as PlatformException; + // -4 = ErrorCode.NotSupported + // It's allow this function return -4 + if ('-4' != exception.code) { + rethrow; + } + } + + await rtcEngine.destroy(); + }, + skip: !(Platform.isAndroid || Platform.isIOS), + ); + + testWidgets( + 'getCameraMaxZoomFactor', + (WidgetTester tester) async { + RtcEngine rtcEngine = await RtcEngine.create(config.appId); + await rtcEngine.startPreview(); + try { + await rtcEngine.getCameraMaxZoomFactor(); + } catch (e) { + final exception = e as PlatformException; + // -4 = ErrorCode.NotSupported + // It's allow this function return -4 + if ('-4' != exception.code) { + rethrow; + } + } + + await rtcEngine.destroy(); + }, + skip: !(Platform.isAndroid || Platform.isIOS), + ); + + testWidgets( + 'isCameraAutoFocusFaceModeSupported', + (WidgetTester tester) async { + RtcEngine rtcEngine = await RtcEngine.create(config.appId); + await rtcEngine.startPreview(); + await rtcEngine.isCameraAutoFocusFaceModeSupported(); + + await rtcEngine.destroy(); + }, + skip: !(Platform.isAndroid || Platform.isIOS), + ); + + testWidgets( + 'isCameraExposurePositionSupported', + (WidgetTester tester) async { + RtcEngine rtcEngine = await RtcEngine.create(config.appId); + await rtcEngine.startPreview(); + await rtcEngine.isCameraExposurePositionSupported(); + + await rtcEngine.destroy(); + }, + skip: !(Platform.isAndroid || Platform.isIOS), + ); + + testWidgets( + 'isCameraFocusSupported', + (WidgetTester tester) async { + RtcEngine rtcEngine = await RtcEngine.create(config.appId); + await rtcEngine.startPreview(); + await rtcEngine.isCameraFocusSupported(); + + await rtcEngine.destroy(); + }, + skip: !(Platform.isAndroid || Platform.isIOS), + ); + + testWidgets( + 'isCameraZoomSupported', + (WidgetTester tester) async { + RtcEngine rtcEngine = await RtcEngine.create(config.appId); + await rtcEngine.startPreview(); + await rtcEngine.isCameraZoomSupported(); + + await rtcEngine.destroy(); + }, + skip: !(Platform.isAndroid || Platform.isIOS), + ); + + testWidgets( + 'setCameraAutoFocusFaceModeEnabled', + (WidgetTester tester) async { + RtcEngine rtcEngine = await RtcEngine.create(config.appId); + await rtcEngine.startPreview(); + await rtcEngine.setCameraAutoFocusFaceModeEnabled(true); + + await rtcEngine.destroy(); + }, + skip: !(Platform.isAndroid || Platform.isIOS), + ); + + testWidgets( + 'setCameraExposurePosition', + (WidgetTester tester) async { + RtcEngine rtcEngine = await RtcEngine.create(config.appId); + await rtcEngine.startPreview(); + await rtcEngine.setCameraExposurePosition(10, 10); + + await rtcEngine.destroy(); + }, + skip: !(Platform.isAndroid || Platform.isIOS), + ); + + testWidgets( + 'setCameraFocusPositionInPreview', + (WidgetTester tester) async { + RtcEngine rtcEngine = await RtcEngine.create(config.appId); + await rtcEngine.startPreview(); + await rtcEngine.setCameraFocusPositionInPreview(10, 10); + + await rtcEngine.destroy(); + }, + skip: !(Platform.isAndroid || Platform.isIOS), + ); + + testWidgets( + 'setCameraZoomFactor', + (WidgetTester tester) async { + RtcEngine rtcEngine = await RtcEngine.create(config.appId); + await rtcEngine.startPreview(); + await rtcEngine.setCameraZoomFactor(1.0); + + await rtcEngine.destroy(); + }, + skip: !(Platform.isAndroid || Platform.isIOS), + ); + + testWidgets( + 'startRhythmPlayer', + (WidgetTester tester) async { + RtcEngine rtcEngine = await RtcEngine.create(config.appId); + await rtcEngine.startPreview(); + RhythmPlayerConfig c = + RhythmPlayerConfig(beatsPerMeasure: 2, beatsPerMinute: 2); + await rtcEngine.startRhythmPlayer('/path', '/path', c); + + await rtcEngine.destroy(); + }, + + // skip: !(Platform.isAndroid || Platform.isIOS), + // TODO(littlegnal): [MS-99386] Wait for iris fix. + skip: true, + ); + + testWidgets( + 'stopRhythmPlayer', + (WidgetTester tester) async { + RtcEngine rtcEngine = await RtcEngine.create(config.appId); + await rtcEngine.startPreview(); + + await rtcEngine.stopRhythmPlayer(); + + await rtcEngine.destroy(); + }, + skip: !(Platform.isAndroid || Platform.isIOS), + ); + + testWidgets( + 'configRhythmPlayer', + (WidgetTester tester) async { + RtcEngine rtcEngine = await RtcEngine.create(config.appId); + await rtcEngine.startPreview(); + + RhythmPlayerConfig c = RhythmPlayerConfig( + beatsPerMeasure: 2, beatsPerMinute: 2, publish: false); + await rtcEngine.configRhythmPlayer(c); + + await rtcEngine.destroy(); + }, + skip: !(Platform.isAndroid || Platform.isIOS), + ); + + testWidgets( + 'getNativeHandle', + (WidgetTester tester) async { + RtcEngine rtcEngine = await RtcEngine.create(config.appId); + await rtcEngine.startPreview(); + + final ret = await rtcEngine.getNativeHandle(); + expect(ret != 0, isTrue); + + await rtcEngine.destroy(); + }, + ); +} diff --git a/integration_test_app/integration_test/agora_rtc_engine_api_test.dart b/integration_test_app/integration_test/agora_rtc_engine_api_test.dart new file mode 100644 index 000000000..f5b16b3a5 --- /dev/null +++ b/integration_test_app/integration_test/agora_rtc_engine_api_test.dart @@ -0,0 +1,3279 @@ +import 'dart:convert'; +import 'dart:io'; +import 'dart:typed_data'; + +import 'package:agora_rtc_engine/rtc_engine.dart'; +import 'package:agora_rtc_engine/src/api_types.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:integration_test/integration_test.dart'; +import 'package:integration_test_app/main.dart' as app; +import 'package:integration_test_app/src/fake_iris_rtc_engine.dart'; + +void main() { + IntegrationTestWidgetsFlutterBinding.ensureInitialized(); + + late RtcEngine rtcEngine; + late FakeIrisRtcEngine fakeIrisEngine; + + tearDown(() async { + await rtcEngine.destroy(); + fakeIrisEngine.dispose(); + }); + + group('createWithContext', () { + testWidgets('with `appId`', (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + + final context = RtcEngineContext('123'); + + rtcEngine = await RtcEngine.createWithContext(context); + + fakeIrisEngine.expectCalledApi( + ApiTypeEngine.kEngineInitialize.index, + jsonEncode({ + 'context': context.toJson(), + 'appGroup': null, + }), + ); + + fakeIrisEngine.expectCalledApi( + ApiTypeEngine.kEngineSetAppType.index, + jsonEncode({ + 'appType': 4, + }), + ); + }); + + testWidgets('with `appId` and `areaCode`', (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + + final context = RtcEngineContext( + '123', + areaCode: const [AreaCode.GLOB], + ); + + rtcEngine = await RtcEngine.createWithContext(context); + + fakeIrisEngine.expectCalledApi( + ApiTypeEngine.kEngineInitialize.index, + jsonEncode({ + 'context': context.toJson(), + 'appGroup': null, + }), + ); + + fakeIrisEngine.expectCalledApi( + ApiTypeEngine.kEngineSetAppType.index, + jsonEncode({ + 'appType': 4, + }), + ); + }); + + testWidgets('with `appId`, `areaCode` and `logConfig`', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + + final context = RtcEngineContext( + '123', + areaCode: const [AreaCode.CN], + logConfig: LogConfig(filePath: '/path'), + ); + + rtcEngine = await RtcEngine.createWithContext(context); + + fakeIrisEngine.expectCalledApi( + ApiTypeEngine.kEngineInitialize.index, + jsonEncode({ + 'context': context.toJson(), + 'appGroup': null, + }), + ); + + fakeIrisEngine.expectCalledApi( + ApiTypeEngine.kEngineSetAppType.index, + jsonEncode({ + 'appType': 4, + }), + ); + }); + }); + + testWidgets('create', (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + + rtcEngine = await _createEngine(); + + fakeIrisEngine.expectCalledApi( + ApiTypeEngine.kEngineInitialize.index, + jsonEncode({ + 'context': RtcEngineContext('123').toJson(), + 'appGroup': null, + }), + ); + + fakeIrisEngine.expectCalledApi( + ApiTypeEngine.kEngineSetAppType.index, + jsonEncode({ + 'appType': 4, + }), + ); + }); + + testWidgets( + 'getErrorDescription', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + + rtcEngine = await _createEngine(); + + fakeIrisEngine.mockCallApiResult( + ApiTypeEngine.kEngineGetErrorDescription.index, + jsonEncode({ + 'code': 1, + }), + 'Fail', + ); + + final ret = await rtcEngine.getErrorDescription(1); + + fakeIrisEngine.expectCalledApi( + ApiTypeEngine.kEngineGetErrorDescription.index, + jsonEncode({ + 'code': 1, + }), + ); + expect(ret, 'Fail'); + }, + // TODO(littlegnal): Temporary skip for Windows, cause it will be crash this time + skip: Platform.isWindows, + ); + + testWidgets('setChannelProfile', (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + + rtcEngine = await _createEngine(); + + const channelProfile = ChannelProfile.LiveBroadcasting; + await rtcEngine.setChannelProfile(channelProfile); + + fakeIrisEngine.expectCalledApi( + ApiTypeEngine.kEngineSetChannelProfile.index, + jsonEncode({ + 'profile': 1, + }), + ); + }); + + group('setClientRole', () { + testWidgets('with `role`', (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + + rtcEngine = await _createEngine(); + + await rtcEngine.setClientRole(ClientRole.Broadcaster); + fakeIrisEngine.expectCalledApi( + ApiTypeEngine.kEngineSetClientRole.index, + jsonEncode({ + 'role': 1, + 'options': null, + }), + ); + }); + + testWidgets('with `role` and `options`', (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + + rtcEngine = await _createEngine(); + + final options = ClientRoleOptions( + audienceLatencyLevel: AudienceLatencyLevelType.UltraLowLatency, + ); + await rtcEngine.setClientRole(ClientRole.Broadcaster, options); + + fakeIrisEngine.expectCalledApi( + ApiTypeEngine.kEngineSetClientRole.index, + jsonEncode({ + 'role': 1, + 'options': options.toJson(), + }), + ); + }); + }); + + group('joinChannel', () { + testWidgets('with `token`, `channelName`, `optionalInfo` and `optionalUid`', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + + rtcEngine = await _createEngine(); + await rtcEngine.joinChannel(null, 'testapi', null, 1); + + fakeIrisEngine.expectCalledApi( + ApiTypeEngine.kEngineJoinChannel.index, + jsonEncode({ + 'token': null, + 'channelId': 'testapi', + 'info': null, + 'uid': 1, + 'options': null, + }), + ); + }); + + testWidgets( + 'with `token`, `channelName`, `optionalInfo`, `optionalUid` and `options`', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + + rtcEngine = await _createEngine(); + final ChannelMediaOptions options = + ChannelMediaOptions(autoSubscribeAudio: true); + await rtcEngine.joinChannel(null, 'testapi', null, 1, options); + + fakeIrisEngine.expectCalledApi( + ApiTypeEngine.kEngineJoinChannel.index, + jsonEncode({ + 'token': null, + 'channelId': 'testapi', + 'info': null, + 'uid': 1, + 'options': options.toJson(), + }), + ); + }); + }); + + group('switchChannel', () { + testWidgets('with `token`, `channelName`', (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + + rtcEngine = await _createEngine(); + await rtcEngine.switchChannel(null, 'testapi'); + + fakeIrisEngine.expectCalledApi( + ApiTypeEngine.kEngineSwitchChannel.index, + jsonEncode({ + 'token': null, + 'channelId': 'testapi', + 'options': null, + }), + ); + }); + + testWidgets('with `token`, `channelName`, `options`', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + + rtcEngine = await _createEngine(); + final ChannelMediaOptions options = + ChannelMediaOptions(autoSubscribeAudio: true); + await rtcEngine.switchChannel(null, 'testapi', options); + + fakeIrisEngine.expectCalledApi( + ApiTypeEngine.kEngineSwitchChannel.index, + jsonEncode({ + 'token': null, + 'channelId': 'testapi', + 'options': options.toJson(), + }), + ); + }); + }); + + testWidgets('leaveChannel', (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + + rtcEngine = await _createEngine(); + await rtcEngine.leaveChannel(); + + fakeIrisEngine.expectCalledApi( + ApiTypeEngine.kEngineLeaveChannel.index, + jsonEncode({}), + ); + }); + + testWidgets('renewToken', (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + + rtcEngine = await _createEngine(); + await rtcEngine.renewToken('123'); + + fakeIrisEngine.expectCalledApi( + ApiTypeEngine.kEngineRenewToken.index, + jsonEncode({ + 'token': '123', + }), + ); + }); + + testWidgets('getConnectionState', (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + + fakeIrisEngine.mockCallApiReturnCode( + ApiTypeEngine.kEngineGetConnectionState.index, + jsonEncode({}), + 3, + ); + + rtcEngine = await _createEngine(); + final ret = await rtcEngine.getConnectionState(); + + fakeIrisEngine.expectCalledApi( + ApiTypeEngine.kEngineGetConnectionState.index, + jsonEncode({}), + ); + + expect(ret, ConnectionStateType.Connected); + }); + + testWidgets('getCallId', (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + + fakeIrisEngine.mockCallApiResult( + ApiTypeEngine.kEngineGetCallId.index, + jsonEncode({}), + '2', + ); + + rtcEngine = await _createEngine(); + final ret = await rtcEngine.getCallId(); + + fakeIrisEngine.expectCalledApi( + ApiTypeEngine.kEngineGetCallId.index, + jsonEncode({}), + ); + + expect(ret, '2'); + }); + + group('rate', () { + testWidgets('with `callId`, `rating`', (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + + rtcEngine = await _createEngine(); + await rtcEngine.rate('123', 5); + + fakeIrisEngine.expectCalledApi( + ApiTypeEngine.kEngineRate.index, + jsonEncode({ + 'callId': '123', + 'rating': 5, + 'description': null, + }), + ); + }); + + testWidgets('with `callId`, `rating`, `description`', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + + rtcEngine = await _createEngine(); + await rtcEngine.rate('123', 5, description: 'des'); + + fakeIrisEngine.expectCalledApi( + ApiTypeEngine.kEngineRate.index, + jsonEncode({ + 'callId': '123', + 'rating': 5, + 'description': 'des', + }), + ); + }); + }); + + testWidgets('complain', (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + + rtcEngine = await _createEngine(); + await rtcEngine.complain('123', 'des'); + + fakeIrisEngine.expectCalledApi( + ApiTypeEngine.kEngineComplain.index, + jsonEncode({ + 'callId': '123', + 'description': 'des', + }), + ); + }); + + testWidgets('setParameters', (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + + rtcEngine = await _createEngine(); + await rtcEngine.setParameters('params'); + + fakeIrisEngine.expectCalledApi( + ApiTypeEngine.kEngineSetParameters.index, + jsonEncode({ + 'parameters': 'params', + }), + ); + }); + + testWidgets('getUserInfoByUid', (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + + final expectedUserInfo = UserInfo(10, 'user1'); + + fakeIrisEngine.mockCallApiResult( + ApiTypeEngine.kEngineGetUserInfoByUid.index, + jsonEncode({ + 'uid': 10, + }), + jsonEncode(expectedUserInfo.toJson()), + ); + + rtcEngine = await _createEngine(); + final ret = await rtcEngine.getUserInfoByUid(10); + + fakeIrisEngine.expectCalledApi( + ApiTypeEngine.kEngineGetUserInfoByUid.index, + jsonEncode({ + 'uid': 10, + }), + ); + + expect(jsonEncode(ret), jsonEncode(expectedUserInfo.toJson())); + }); + + testWidgets('getUserInfoByUserAccount', (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + + final expectedUserInfo = UserInfo(10, 'user1'); + + fakeIrisEngine.mockCallApiResult( + ApiTypeEngine.kEngineGetUserInfoByUserAccount.index, + jsonEncode({ + 'userAccount': 'user1', + }), + jsonEncode(expectedUserInfo.toJson()), + ); + + rtcEngine = await _createEngine(); + final ret = await rtcEngine.getUserInfoByUserAccount('user1'); + + fakeIrisEngine.expectCalledApi( + ApiTypeEngine.kEngineGetUserInfoByUserAccount.index, + jsonEncode({ + 'userAccount': 'user1', + }), + ); + + expect(jsonEncode(ret), jsonEncode(expectedUserInfo.toJson())); + }); + + group('joinChannelWithUserAccount', () { + testWidgets('with `token`, `channelName`, `userAccount`', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + + rtcEngine = await _createEngine(); + await rtcEngine.joinChannelWithUserAccount(null, 'testapi', 'user1'); + + fakeIrisEngine.expectCalledApi( + ApiTypeEngine.kEngineJoinChannelWithUserAccount.index, + jsonEncode({ + 'token': null, + 'channelId': 'testapi', + 'userAccount': 'user1', + 'options': null, + }), + ); + }); + + testWidgets('with `token`, `channelName`, `userAccount`, `options`', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + + rtcEngine = await _createEngine(); + final ChannelMediaOptions options = ChannelMediaOptions( + autoSubscribeAudio: true, + ); + await rtcEngine.joinChannelWithUserAccount( + null, 'testapi', 'user1', options); + + fakeIrisEngine.expectCalledApi( + ApiTypeEngine.kEngineJoinChannelWithUserAccount.index, + jsonEncode({ + 'token': null, + 'channelId': 'testapi', + 'userAccount': 'user1', + 'options': options.toJson(), + }), + ); + }); + }); + + testWidgets('registerLocalUserAccount', (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + + rtcEngine = await _createEngine(); + await rtcEngine.registerLocalUserAccount('123', 'user1'); + + fakeIrisEngine.expectCalledApi( + ApiTypeEngine.kEngineRegisterLocalUserAccount.index, + jsonEncode({ + 'appId': '123', + 'userAccount': 'user1', + }), + ); + }); + + testWidgets('adjustPlaybackSignalVolume', (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + + rtcEngine = await _createEngine(); + await rtcEngine.adjustPlaybackSignalVolume(10); + + fakeIrisEngine.expectCalledApi( + ApiTypeEngine.kEngineAdjustPlaybackSignalVolume.index, + jsonEncode({ + 'volume': 10, + }), + ); + }); + + testWidgets('adjustRecordingSignalVolume', (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + + rtcEngine = await _createEngine(); + await rtcEngine.adjustRecordingSignalVolume(10); + + fakeIrisEngine.expectCalledApi( + ApiTypeEngine.kEngineAdjustRecordingSignalVolume.index, + jsonEncode({ + 'volume': 10, + }), + ); + }); + + testWidgets('adjustUserPlaybackSignalVolume', (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + + rtcEngine = await _createEngine(); + await rtcEngine.adjustUserPlaybackSignalVolume(123, 10); + + fakeIrisEngine.expectCalledApi( + ApiTypeEngine.kEngineAdjustUserPlaybackSignalVolume.index, + jsonEncode({ + 'uid': 123, + 'volume': 10, + }), + ); + }); + + testWidgets( + 'enableLoopbackRecording', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + + rtcEngine = await _createEngine(); + await rtcEngine.enableLoopbackRecording(true); + + fakeIrisEngine.expectCalledApi( + ApiTypeEngine.kEngineEnableLoopBackRecording.index, + jsonEncode({ + 'enabled': true, + 'deviceName': null, + }), + ); + }, + skip: (Platform.isAndroid || Platform.isIOS), + ); + + testWidgets('disableAudio', (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + + rtcEngine = await _createEngine(); + await rtcEngine.disableAudio(); + + fakeIrisEngine.expectCalledApi( + ApiTypeEngine.kEngineDisableAudio.index, + jsonEncode({}), + ); + }); + + testWidgets('enableAudio', (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + + rtcEngine = await _createEngine(); + await rtcEngine.enableAudio(); + + fakeIrisEngine.expectCalledApi( + ApiTypeEngine.kEngineEnableAudio.index, + jsonEncode({}), + ); + }); + + testWidgets('enableAudioVolumeIndication', (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + + rtcEngine = await _createEngine(); + await rtcEngine.enableAudioVolumeIndication(10, 10, true); + + fakeIrisEngine.expectCalledApi( + ApiTypeEngine.kEngineEnableAudioVolumeIndication.index, + jsonEncode({ + 'interval': 10, + 'smooth': 10, + 'report_vad': true, + }), + ); + }); + + testWidgets('enableLocalAudio', (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + + rtcEngine = await _createEngine(); + await rtcEngine.enableLocalAudio(true); + + fakeIrisEngine.expectCalledApi( + ApiTypeEngine.kEngineEnableLocalAudio.index, + jsonEncode({ + 'enabled': true, + }), + ); + }); + + testWidgets('muteAllRemoteAudioStreams', (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + + rtcEngine = await _createEngine(); + await rtcEngine.muteAllRemoteAudioStreams(true); + + fakeIrisEngine.expectCalledApi( + ApiTypeEngine.kEngineMuteAllRemoteAudioStreams.index, + jsonEncode({ + 'mute': true, + }), + ); + }); + + testWidgets('muteLocalAudioStream', (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + + rtcEngine = await _createEngine(); + await rtcEngine.muteLocalAudioStream(true); + + fakeIrisEngine.expectCalledApi( + ApiTypeEngine.kEngineMuteLocalAudioStream.index, + jsonEncode({ + 'mute': true, + }), + ); + }); + + testWidgets('muteRemoteAudioStream', (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + + rtcEngine = await _createEngine(); + await rtcEngine.muteRemoteAudioStream(10, true); + + fakeIrisEngine.expectCalledApi( + ApiTypeEngine.kEngineMuteRemoteAudioStream.index, + jsonEncode({ + 'userId': 10, + 'mute': true, + }), + ); + }); + + testWidgets('setAudioProfile', (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + + rtcEngine = await _createEngine(); + await rtcEngine.setAudioProfile( + AudioProfile.Default, + AudioScenario.Default, + ); + + fakeIrisEngine.expectCalledApi( + ApiTypeEngine.kEngineSetAudioProfile.index, + jsonEncode({ + 'profile': 0, + 'scenario': 0, + }), + ); + }); + + testWidgets('disableVideo', (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + + rtcEngine = await _createEngine(); + await rtcEngine.disableVideo(); + + fakeIrisEngine.expectCalledApi( + ApiTypeEngine.kEngineDisableVideo.index, + jsonEncode({}), + ); + }); + + testWidgets('enableLocalVideo', (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + + rtcEngine = await _createEngine(); + await rtcEngine.enableLocalVideo(true); + + fakeIrisEngine.expectCalledApi( + ApiTypeEngine.kEngineEnableLocalVideo.index, + jsonEncode({ + 'enabled': true, + }), + ); + }); + + testWidgets('enableVideo', (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + + rtcEngine = await _createEngine(); + await rtcEngine.enableVideo(); + + fakeIrisEngine.expectCalledApi( + ApiTypeEngine.kEngineEnableVideo.index, + jsonEncode({}), + ); + }); + + testWidgets('muteAllRemoteVideoStreams', (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + + rtcEngine = await _createEngine(); + await rtcEngine.muteAllRemoteVideoStreams(true); + + fakeIrisEngine.expectCalledApi( + ApiTypeEngine.kEngineMuteAllRemoteVideoStreams.index, + jsonEncode({ + 'mute': true, + }), + ); + }); + + testWidgets('muteLocalVideoStream', (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + + rtcEngine = await _createEngine(); + await rtcEngine.muteLocalVideoStream(true); + + fakeIrisEngine.expectCalledApi( + ApiTypeEngine.kEngineMuteLocalVideoStream.index, + jsonEncode({ + 'mute': true, + }), + ); + }); + + testWidgets('muteRemoteVideoStream', (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + + rtcEngine = await _createEngine(); + await rtcEngine.muteRemoteVideoStream(10, true); + + fakeIrisEngine.expectCalledApi( + ApiTypeEngine.kEngineMuteRemoteVideoStream.index, + jsonEncode({ + 'userId': 10, + 'mute': true, + }), + ); + }); + + testWidgets('setBeautyEffectOptions', (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + + rtcEngine = await _createEngine(); + BeautyOptions options = + BeautyOptions(lighteningContrastLevel: LighteningContrastLevel.High); + await rtcEngine.setBeautyEffectOptions(true, options); + + fakeIrisEngine.expectCalledApi( + ApiTypeEngine.kEngineSetBeautyEffectOptions.index, + jsonEncode({ + 'enabled': true, + 'options': options.toJson(), + }), + ); + }); + + testWidgets('setVideoEncoderConfiguration', (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + + rtcEngine = await _createEngine(); + VideoEncoderConfiguration config = VideoEncoderConfiguration( + dimensions: VideoDimensions(width: 10, height: 10)); + await rtcEngine.setVideoEncoderConfiguration(config); + + fakeIrisEngine.expectCalledApi( + ApiTypeEngine.kEngineSetVideoEncoderConfiguration.index, + jsonEncode({ + 'config': config.toJson(), + }), + ); + }); + + testWidgets('startPreview', (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + + rtcEngine = await _createEngine(); + + await rtcEngine.startPreview(); + + fakeIrisEngine.expectCalledApi( + ApiTypeEngine.kEngineStartPreview.index, + jsonEncode({}), + ); + }); + + testWidgets('stopPreview', (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + + rtcEngine = await _createEngine(); + + await rtcEngine.stopPreview(); + + fakeIrisEngine.expectCalledApi( + ApiTypeEngine.kEngineStopPreview.index, + jsonEncode({}), + ); + }); + + testWidgets('adjustAudioMixingPlayoutVolume', (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + + rtcEngine = await _createEngine(); + + await rtcEngine.adjustAudioMixingPlayoutVolume(10); + + fakeIrisEngine.expectCalledApi( + ApiTypeEngine.kEngineAdjustAudioMixingPlayoutVolume.index, + jsonEncode({ + 'volume': 10, + }), + ); + }); + + testWidgets('adjustAudioMixingPublishVolume', (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + + rtcEngine = await _createEngine(); + + await rtcEngine.adjustAudioMixingPublishVolume(10); + + fakeIrisEngine.expectCalledApi( + ApiTypeEngine.kEngineAdjustAudioMixingPublishVolume.index, + jsonEncode({ + 'volume': 10, + }), + ); + }); + + testWidgets('adjustAudioMixingVolume', (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + + rtcEngine = await _createEngine(); + + await rtcEngine.adjustAudioMixingVolume(10); + + fakeIrisEngine.expectCalledApi( + ApiTypeEngine.kEngineAdjustAudioMixingVolume.index, + jsonEncode({ + 'volume': 10, + }), + ); + }); + + testWidgets('getAudioMixingCurrentPosition', (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + + fakeIrisEngine.mockCallApiReturnCode( + ApiTypeEngine.kEngineGetAudioMixingCurrentPosition.index, + jsonEncode({}), + 10); + + rtcEngine = await _createEngine(); + + final ret = await rtcEngine.getAudioMixingCurrentPosition(); + + fakeIrisEngine.expectCalledApi( + ApiTypeEngine.kEngineGetAudioMixingCurrentPosition.index, + jsonEncode({}), + ); + + expect(ret, 10); + }); + + testWidgets('getAudioMixingDuration', (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + + fakeIrisEngine.mockCallApiReturnCode( + ApiTypeEngine.kEngineGetAudioMixingDuration.index, jsonEncode({}), 10); + + rtcEngine = await _createEngine(); + + final ret = await rtcEngine.getAudioMixingDuration(); + + fakeIrisEngine.expectCalledApi( + ApiTypeEngine.kEngineGetAudioMixingDuration.index, + jsonEncode({}), + ); + + expect(ret, 10); + }); + + testWidgets('getAudioMixingPlayoutVolume', (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + + fakeIrisEngine.mockCallApiReturnCode( + ApiTypeEngine.kEngineGetAudioMixingPlayoutVolume.index, + jsonEncode({}), + 10); + + rtcEngine = await _createEngine(); + + final ret = await rtcEngine.getAudioMixingPlayoutVolume(); + + fakeIrisEngine.expectCalledApi( + ApiTypeEngine.kEngineGetAudioMixingPlayoutVolume.index, + jsonEncode({}), + ); + + expect(ret, 10); + }); + + testWidgets('getAudioMixingPublishVolume', (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + + fakeIrisEngine.mockCallApiReturnCode( + ApiTypeEngine.kEngineGetAudioMixingPublishVolume.index, + jsonEncode({}), + 10); + + rtcEngine = await _createEngine(); + + final ret = await rtcEngine.getAudioMixingPublishVolume(); + + fakeIrisEngine.expectCalledApi( + ApiTypeEngine.kEngineGetAudioMixingPublishVolume.index, + jsonEncode({}), + ); + + expect(ret, 10); + }); + + testWidgets('pauseAudioMixing', (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + + rtcEngine = await _createEngine(); + + await rtcEngine.pauseAudioMixing(); + + fakeIrisEngine.expectCalledApi( + ApiTypeEngine.kEnginePauseAudioMixing.index, + jsonEncode({}), + ); + }); + + testWidgets('resumeAudioMixing', (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + + rtcEngine = await _createEngine(); + + await rtcEngine.resumeAudioMixing(); + + fakeIrisEngine.expectCalledApi( + ApiTypeEngine.kEngineResumeAudioMixing.index, + jsonEncode({}), + ); + }); + + testWidgets('setAudioMixingPosition', (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + + rtcEngine = await _createEngine(); + + await rtcEngine.setAudioMixingPosition(10); + + fakeIrisEngine.expectCalledApi( + ApiTypeEngine.kEngineSetAudioMixingPosition.index, + jsonEncode({ + 'pos': 10, + }), + ); + }); + + group('startAudioMixing', () { + testWidgets('with `filePath`, `loopback`, `replace`, `cycle`', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + + rtcEngine = await _createEngine(); + + await rtcEngine.startAudioMixing('/path', true, true, 10); + + fakeIrisEngine.expectCalledApi( + ApiTypeEngine.kEngineStartAudioMixing.index, + jsonEncode({ + 'filePath': '/path', + 'loopback': true, + 'replace': true, + 'cycle': 10, + 'startPos': null, + }), + ); + }); + + testWidgets('with `filePath`, `loopback`, `replace`, `cycle`, `startPos`', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + + rtcEngine = await _createEngine(); + + await rtcEngine.startAudioMixing('/path', true, true, 10, 20); + + fakeIrisEngine.expectCalledApi( + ApiTypeEngine.kEngineStartAudioMixing.index, + jsonEncode({ + 'filePath': '/path', + 'loopback': true, + 'replace': true, + 'cycle': 10, + 'startPos': 20, + }), + ); + }); + }); + + testWidgets('stopAudioMixing', (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + + rtcEngine = await _createEngine(); + + await rtcEngine.stopAudioMixing(); + + fakeIrisEngine.expectCalledApi( + ApiTypeEngine.kEngineStopAudioMixing.index, + jsonEncode({}), + ); + }); + + testWidgets('addInjectStreamUrl', (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + + rtcEngine = await _createEngine(); + + final LiveInjectStreamConfig config = + LiveInjectStreamConfig(width: 10, height: 10); + + await rtcEngine.addInjectStreamUrl('https://example.com', config); + + fakeIrisEngine.expectCalledApi( + ApiTypeEngine.kEngineAddInjectStreamUrl.index, + jsonEncode({ + 'url': 'https://example.com', + 'config': config.toJson(), + }), + ); + }); + + testWidgets('addPublishStreamUrl', (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + + rtcEngine = await _createEngine(); + + await rtcEngine.addPublishStreamUrl('https://example.com', true); + + fakeIrisEngine.expectCalledApi( + ApiTypeEngine.kEngineAddPublishStreamUrl.index, + jsonEncode({ + 'url': 'https://example.com', + 'transcodingEnabled': true, + }), + ); + }); + + testWidgets('addVideoWatermark', (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + + rtcEngine = await _createEngine(); + + final WatermarkOptions options = WatermarkOptions(visibleInPreview: true); + await rtcEngine.addVideoWatermark('https://example.com', options); + + fakeIrisEngine.expectCalledApi( + ApiTypeEngine.kEngineAddVideoWaterMark.index, + jsonEncode({ + 'watermarkUrl': 'https://example.com', + 'options': options.toJson(), + }), + ); + }); + + testWidgets('clearVideoWatermarks', (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + + rtcEngine = await _createEngine(); + + await rtcEngine.clearVideoWatermarks(); + + fakeIrisEngine.expectCalledApi( + ApiTypeEngine.kEngineClearVideoWaterMarks.index, + jsonEncode({}), + ); + }); + + testWidgets('createDataStream', (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + + fakeIrisEngine.mockCallApiReturnCode( + ApiTypeEngine.kEngineCreateDataStream.index, + jsonEncode({ + 'reliable': true, + 'ordered': true, + }), + 10); + + rtcEngine = await _createEngine(); + + final ret = await rtcEngine.createDataStream(true, true); + + fakeIrisEngine.expectCalledApi( + ApiTypeEngine.kEngineCreateDataStream.index, + jsonEncode({ + 'reliable': true, + 'ordered': true, + }), + ); + + expect(ret, 10); + }); + + testWidgets('disableLastmileTest', (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + + rtcEngine = await _createEngine(); + + await rtcEngine.disableLastmileTest(); + + fakeIrisEngine.expectCalledApi( + ApiTypeEngine.kEngineDisableLastMileTest.index, + jsonEncode({}), + ); + }); + + testWidgets('enableDualStreamMode', (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + + rtcEngine = await _createEngine(); + + await rtcEngine.enableDualStreamMode(true); + + fakeIrisEngine.expectCalledApi( + ApiTypeEngine.kEngineEnableDualStreamMode.index, + jsonEncode({ + 'enabled': true, + }), + ); + }); + + testWidgets( + 'enableInEarMonitoring', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + + rtcEngine = await _createEngine(); + + await rtcEngine.enableInEarMonitoring(true); + + fakeIrisEngine.expectCalledApi( + ApiTypeEngine.kEngineEnableInEarMonitoring.index, + jsonEncode({ + 'enabled': true, + }), + ); + }, + skip: !(Platform.isAndroid || Platform.isIOS), + ); + + testWidgets('enableLastmileTest', (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + + rtcEngine = await _createEngine(); + + await rtcEngine.enableLastmileTest(); + + fakeIrisEngine.expectCalledApi( + ApiTypeEngine.kEngineEnableLastMileTest.index, + jsonEncode({}), + ); + }); + + testWidgets('enableSoundPositionIndication', (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + + rtcEngine = await _createEngine(); + + await rtcEngine.enableSoundPositionIndication(true); + + fakeIrisEngine.expectCalledApi( + ApiTypeEngine.kEngineEnableSoundPositionIndication.index, + jsonEncode({ + 'enabled': true, + }), + ); + }); + + testWidgets( + 'isSpeakerphoneEnabled', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + + fakeIrisEngine.mockCallApiReturnCode( + ApiTypeEngine.kEngineIsSpeakerPhoneEnabled.index, + jsonEncode({}), + 1, + ); + + rtcEngine = await _createEngine(); + + final ret = await rtcEngine.isSpeakerphoneEnabled(); + + fakeIrisEngine.expectCalledApi( + ApiTypeEngine.kEngineIsSpeakerPhoneEnabled.index, + jsonEncode({}), + ); + + expect(ret, true); + }, + skip: !(Platform.isAndroid || Platform.isIOS), + ); + + testWidgets('pauseAllEffects', (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + + rtcEngine = await _createEngine(); + + await rtcEngine.pauseAllEffects(); + + fakeIrisEngine.expectCalledApi( + ApiTypeEngine.kEnginePauseAllEffects.index, + jsonEncode({}), + ); + }); + + testWidgets('pauseEffect', (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + + rtcEngine = await _createEngine(); + + await rtcEngine.pauseEffect(10); + + fakeIrisEngine.expectCalledApi( + ApiTypeEngine.kEnginePauseEffect.index, + jsonEncode({ + 'soundId': 10, + }), + ); + }); + + group('playEffect', () { + testWidgets( + 'with `soundId`, `filePath`, `loopCount`, `pitch`, `pan`, `gain`, `publish`', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + + rtcEngine = await _createEngine(); + + await rtcEngine.playEffect(10, '/path', 10, 1.0, 2.0, 3, true); + + fakeIrisEngine.expectCalledApi( + ApiTypeEngine.kEnginePlayEffect.index, + jsonEncode({ + 'soundId': 10, + 'filePath': '/path', + 'loopCount': 10, + 'pitch': 1.0, + 'pan': 2.0, + 'gain': 3, + 'publish': true, + 'startPos': null, + }), + ); + }); + + testWidgets( + 'with `soundId`, `filePath`, `loopCount`, `pitch`, `pan`, `gain`, `publish`, `startPos`', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + + rtcEngine = await _createEngine(); + + await rtcEngine.playEffect(10, '/path', 10, 1.0, 2.0, 3, true, 20); + + fakeIrisEngine.expectCalledApi( + ApiTypeEngine.kEnginePlayEffect.index, + jsonEncode({ + 'soundId': 10, + 'filePath': '/path', + 'loopCount': 10, + 'pitch': 1.0, + 'pan': 2.0, + 'gain': 3, + 'publish': true, + 'startPos': 20, + }), + ); + }); + }); + + testWidgets('setEffectPosition', (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + + rtcEngine = await _createEngine(); + + await rtcEngine.setEffectPosition(10, 20); + + fakeIrisEngine.expectCalledApi( + ApiTypeEngine.kEngineSetEffectPosition.index, + jsonEncode({ + 'soundId': 10, + 'pos': 20, + }), + ); + }); + + testWidgets('getEffectDuration', (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + + rtcEngine = await _createEngine(); + + await rtcEngine.getEffectDuration('/path'); + + fakeIrisEngine.expectCalledApi( + ApiTypeEngine.kEngineGetEffectDuration.index, + jsonEncode({ + 'filePath': '/path', + }), + ); + }); + + testWidgets('getEffectCurrentPosition', (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + + rtcEngine = await _createEngine(); + + await rtcEngine.getEffectCurrentPosition(10); + + fakeIrisEngine.expectCalledApi( + ApiTypeEngine.kEngineGetEffectCurrentPosition.index, + jsonEncode({ + 'soundId': 10, + }), + ); + }); + + testWidgets('preloadEffect', (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + + rtcEngine = await _createEngine(); + + await rtcEngine.preloadEffect(10, '/path'); + + fakeIrisEngine.expectCalledApi( + ApiTypeEngine.kEnginePreloadEffect.index, + jsonEncode({ + 'soundId': 10, + 'filePath': '/path', + }), + ); + }); + + testWidgets('preloadEffect', (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + + rtcEngine = await _createEngine(); + + await rtcEngine.preloadEffect(10, '/path'); + + fakeIrisEngine.expectCalledApi( + ApiTypeEngine.kEnginePreloadEffect.index, + jsonEncode({ + 'soundId': 10, + 'filePath': '/path', + }), + ); + }); + + testWidgets('registerMediaMetadataObserver', (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + + rtcEngine = await _createEngine(); + + await rtcEngine.registerMediaMetadataObserver(); + + fakeIrisEngine.expectCalledApi( + ApiTypeEngine.kEngineRegisterMediaMetadataObserver.index, + jsonEncode({'type': 0}), + ); + }); + + testWidgets('removeInjectStreamUrl', (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + + rtcEngine = await _createEngine(); + + await rtcEngine.removeInjectStreamUrl('https://example.com'); + + fakeIrisEngine.expectCalledApi( + ApiTypeEngine.kEngineRemoveInjectStreamUrl.index, + jsonEncode({ + 'url': 'https://example.com', + }), + ); + }); + + testWidgets('removePublishStreamUrl', (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + + rtcEngine = await _createEngine(); + + await rtcEngine.removePublishStreamUrl('https://example.com'); + + fakeIrisEngine.expectCalledApi( + ApiTypeEngine.kEngineRemovePublishStreamUrl.index, + jsonEncode({ + 'url': 'https://example.com', + }), + ); + }); + + testWidgets('resumeAllEffects', (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + + rtcEngine = await _createEngine(); + + await rtcEngine.resumeAllEffects(); + + fakeIrisEngine.expectCalledApi( + ApiTypeEngine.kEngineResumeAllEffects.index, + jsonEncode({}), + ); + }); + + testWidgets('resumeEffect', (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + + rtcEngine = await _createEngine(); + + await rtcEngine.resumeEffect(10); + + fakeIrisEngine.expectCalledApi( + ApiTypeEngine.kEngineResumeEffect.index, + jsonEncode({ + 'soundId': 10, + }), + ); + }); + + testWidgets('sendMetadata', (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + + final bytes = Uint8List.fromList([1, 1, 1, 1, 1]); + + fakeIrisEngine.setExplicitBufferSize( + ApiTypeEngine.kEngineResumeEffect.index, + jsonEncode({ + 'metadata': { + 'size': bytes.length, + }, + }), + bytes.length); + + rtcEngine = await _createEngine(); + + await rtcEngine.sendMetadata(bytes); + + fakeIrisEngine.expectCalledApi( + ApiTypeEngine.kEngineSendMetadata.index, + jsonEncode({ + 'metadata': { + 'size': bytes.length, + }, + }), + buffer: bytes, + bufferSize: bytes.length, + ); + }); + + testWidgets('sendStreamMessage', (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + + final bytes = Uint8List.fromList([1, 1, 1, 1, 1]); + + fakeIrisEngine.setExplicitBufferSize( + ApiTypeEngine.kEngineSendStreamMessage.index, + jsonEncode({ + 'streamId': 10, + 'length': bytes.length, + }), + bytes.length); + + rtcEngine = await _createEngine(); + + await rtcEngine.sendStreamMessage(10, bytes); + + fakeIrisEngine.expectCalledApi( + ApiTypeEngine.kEngineSendStreamMessage.index, + jsonEncode({ + 'streamId': 10, + 'length': bytes.length, + }), + buffer: bytes, + bufferSize: bytes.length, + ); + }); + + testWidgets( + 'setCameraCapturerConfiguration', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + + rtcEngine = await _createEngine(); + + final CameraCapturerConfiguration config = CameraCapturerConfiguration( + preference: CameraCaptureOutputPreference.Performance); + await rtcEngine.setCameraCapturerConfiguration(config); + + fakeIrisEngine.expectCalledApi( + ApiTypeEngine.kEngineSetCameraCapturerConfiguration.index, + jsonEncode({ + 'config': config.toJson(), + }), + ); + }, + //!(Platform.isAndroid || Platform.isIOS), + skip: true, // TODO(littlegnal): [MS-102785] Wait for iris fix it + ); + + testWidgets( + 'setDefaultAudioRoutetoSpeakerphone', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + + rtcEngine = await _createEngine(); + + await rtcEngine.setDefaultAudioRoutetoSpeakerphone(true); + + fakeIrisEngine.expectCalledApi( + ApiTypeEngine.kEngineSetDefaultAudioRouteToSpeakerPhone.index, + jsonEncode({ + 'defaultToSpeaker': true, + }), + ); + }, + skip: !(Platform.isAndroid || Platform.isIOS), + ); + + testWidgets('setEffectsVolume', (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + + rtcEngine = await _createEngine(); + + await rtcEngine.setEffectsVolume(10); + + fakeIrisEngine.expectCalledApi( + ApiTypeEngine.kEngineSetEffectsVolume.index, + jsonEncode({ + 'volume': 10, + }), + ); + }); + + testWidgets( + 'setEnableSpeakerphone', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + + rtcEngine = await _createEngine(); + + await rtcEngine.setEnableSpeakerphone(true); + + fakeIrisEngine.expectCalledApi( + ApiTypeEngine.kEngineSetEnableSpeakerPhone.index, + jsonEncode({ + 'speakerOn': true, + }), + ); + }, + skip: !(Platform.isAndroid || Platform.isIOS), + ); + + testWidgets( + 'setInEarMonitoringVolume', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + + rtcEngine = await _createEngine(); + + await rtcEngine.setInEarMonitoringVolume(10); + + fakeIrisEngine.expectCalledApi( + ApiTypeEngine.kEngineSetInEarMonitoringVolume.index, + jsonEncode({ + 'volume': 10, + }), + ); + }, + skip: !(Platform.isAndroid || Platform.isIOS), + ); + + testWidgets('setLiveTranscoding', (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + + rtcEngine = await _createEngine(); + final LiveTranscoding transcoding = + LiveTranscoding([TranscodingUser(100)], width: 10, height: 10); + await rtcEngine.setLiveTranscoding(transcoding); + + fakeIrisEngine.expectCalledApi( + ApiTypeEngine.kEngineSetLiveTranscoding.index, + jsonEncode({ + 'transcoding': transcoding.toJson(), + }), + ); + }); + + testWidgets('setLocalPublishFallbackOption', (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + + rtcEngine = await _createEngine(); + await rtcEngine + .setLocalPublishFallbackOption(StreamFallbackOptions.AudioOnly); + + fakeIrisEngine.expectCalledApi( + ApiTypeEngine.kEngineSetLocalPublishFallbackOption.index, + jsonEncode({ + 'option': 2, + }), + ); + }); + + testWidgets('setLocalVoiceEqualization', (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + + rtcEngine = await _createEngine(); + await rtcEngine.setLocalVoiceEqualization( + AudioEqualizationBandFrequency.Band4K, + 10, + ); + + fakeIrisEngine.expectCalledApi( + ApiTypeEngine.kEngineSetLocalVoiceEqualization.index, + jsonEncode({ + 'bandFrequency': 7, + 'bandGain': 10, + }), + ); + }); + + testWidgets('setLocalVoicePitch', (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + + rtcEngine = await _createEngine(); + await rtcEngine.setLocalVoicePitch(10.0); + + fakeIrisEngine.expectCalledApi( + ApiTypeEngine.kEngineSetLocalVoicePitch.index, + jsonEncode({ + 'pitch': 10.0, + }), + ); + }); + + testWidgets('setLocalVoiceReverb', (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + + rtcEngine = await _createEngine(); + await rtcEngine.setLocalVoiceReverb(AudioReverbType.RoomSize, 10); + + fakeIrisEngine.expectCalledApi( + ApiTypeEngine.kEngineSetLocalVoiceReverb.index, + jsonEncode({ + 'reverbKey': 2, + 'value': 10, + }), + ); + }); + + testWidgets('setMaxMetadataSize', (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + + rtcEngine = await _createEngine(); + await rtcEngine.setMaxMetadataSize(10); + + fakeIrisEngine.expectCalledApi( + ApiTypeEngine.kEngineSetMaxMetadataSize.index, + jsonEncode({ + 'size': 10, + }), + ); + }); + + testWidgets('setRemoteDefaultVideoStreamType', (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + + rtcEngine = await _createEngine(); + await rtcEngine.setRemoteDefaultVideoStreamType(VideoStreamType.High); + + fakeIrisEngine.expectCalledApi( + ApiTypeEngine.kEngineSetRemoteDefaultVideoStreamType.index, + jsonEncode({ + 'streamType': 0, + }), + ); + }); + + testWidgets('setRemoteSubscribeFallbackOption', (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + + rtcEngine = await _createEngine(); + await rtcEngine + .setRemoteSubscribeFallbackOption(StreamFallbackOptions.AudioOnly); + + fakeIrisEngine.expectCalledApi( + ApiTypeEngine.kEngineSetRemoteSubscribeFallbackOption.index, + jsonEncode({ + 'option': 2, + }), + ); + }); + + testWidgets('setRemoteUserPriority', (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + + rtcEngine = await _createEngine(); + await rtcEngine.setRemoteUserPriority(10, UserPriority.High); + + fakeIrisEngine.expectCalledApi( + ApiTypeEngine.kEngineSetRemoteUserPriority.index, + jsonEncode({ + 'uid': 10, + 'userPriority': 50, + }), + ); + }); + + testWidgets('setRemoteVideoStreamType', (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + + rtcEngine = await _createEngine(); + await rtcEngine.setRemoteVideoStreamType(10, VideoStreamType.High); + + fakeIrisEngine.expectCalledApi( + ApiTypeEngine.kEngineSetRemoteVideoStreamType.index, + jsonEncode({ + 'userId': 10, + 'streamType': 0, + }), + ); + }); + + testWidgets('setRemoteVoicePosition', (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + + rtcEngine = await _createEngine(); + await rtcEngine.setRemoteVoicePosition(10, 1.0, 2.0); + + fakeIrisEngine.expectCalledApi( + ApiTypeEngine.kEngineSetRemoteVoicePosition.index, + jsonEncode({ + 'uid': 10, + 'pan': 1.0, + 'gain': 2.0, + }), + ); + }); + + testWidgets('setVolumeOfEffect', (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + + rtcEngine = await _createEngine(); + await rtcEngine.setVolumeOfEffect(10, 10); + + fakeIrisEngine.expectCalledApi( + ApiTypeEngine.kEngineSetVolumeOfEffect.index, + jsonEncode({ + 'soundId': 10, + 'volume': 10, + }), + ); + }); + + testWidgets('startAudioRecordingWithConfig', (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + + rtcEngine = await _createEngine(); + final AudioRecordingConfiguration config = + AudioRecordingConfiguration('/path'); + await rtcEngine.startAudioRecordingWithConfig(config); + + fakeIrisEngine.expectCalledApi( + ApiTypeEngine.kEngineStartAudioRecording.index, + jsonEncode({ + 'config': config.toJson(), + }), + ); + }); + + testWidgets('startChannelMediaRelay', (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + + rtcEngine = await _createEngine(); + final ChannelMediaRelayConfiguration config = + ChannelMediaRelayConfiguration( + ChannelMediaInfo('testapi', 10), + [ChannelMediaInfo('testapi', 100)], + ); + await rtcEngine.startChannelMediaRelay(config); + + fakeIrisEngine.expectCalledApi( + ApiTypeEngine.kEngineStartChannelMediaRelay.index, + jsonEncode({ + 'configuration': config.toJson(), + }), + ); + }); + + testWidgets('startEchoTest', (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + + rtcEngine = await _createEngine(); + + await rtcEngine.startEchoTest(intervalInSeconds: 10); + + fakeIrisEngine.expectCalledApi( + ApiTypeEngine.kEngineStartEchoTest.index, + jsonEncode({ + 'intervalInSeconds': 10, + }), + ); + }); + + testWidgets('startEchoTest EchoTestConfiguration', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + + rtcEngine = await _createEngine(); + + var config = EchoTestConfiguration(enableAudio: true); + await rtcEngine.startEchoTest(config: config); + + fakeIrisEngine.expectCalledApi( + ApiTypeEngine.kEngineStartEchoTest.index, + jsonEncode({ + 'config': config.toJson(), + }), + ); + }); + + testWidgets('startLastmileProbeTest', (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + + rtcEngine = await _createEngine(); + + final LastmileProbeConfig config = LastmileProbeConfig(true, true, 10, 20); + + await rtcEngine.startLastmileProbeTest(config); + + fakeIrisEngine.expectCalledApi( + ApiTypeEngine.kEngineStartLastMileProbeTest.index, + jsonEncode({ + 'config': config.toJson(), + }), + ); + }); + + testWidgets('stopAllEffects', (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + + rtcEngine = await _createEngine(); + + await rtcEngine.stopAllEffects(); + + fakeIrisEngine.expectCalledApi( + ApiTypeEngine.kEngineStopAllEffects.index, + jsonEncode({}), + ); + }); + + testWidgets('stopAudioRecording', (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + + rtcEngine = await _createEngine(); + + await rtcEngine.stopAudioRecording(); + + fakeIrisEngine.expectCalledApi( + ApiTypeEngine.kEngineStopAudioRecording.index, + jsonEncode({}), + ); + }); + + testWidgets('stopChannelMediaRelay', (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + + rtcEngine = await _createEngine(); + + await rtcEngine.stopChannelMediaRelay(); + + fakeIrisEngine.expectCalledApi( + ApiTypeEngine.kEngineStopChannelMediaRelay.index, + jsonEncode({}), + ); + }); + + testWidgets('stopEchoTest', (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + + rtcEngine = await _createEngine(); + + await rtcEngine.stopEchoTest(); + + fakeIrisEngine.expectCalledApi( + ApiTypeEngine.kEngineStopEchoTest.index, + jsonEncode({}), + ); + }); + + testWidgets('stopEffect', (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + + rtcEngine = await _createEngine(); + + await rtcEngine.stopEffect(10); + + fakeIrisEngine.expectCalledApi( + ApiTypeEngine.kEngineStopEffect.index, + jsonEncode({ + 'soundId': 10, + }), + ); + }); + + testWidgets('stopLastmileProbeTest', (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + + rtcEngine = await _createEngine(); + + await rtcEngine.stopLastmileProbeTest(); + + fakeIrisEngine.expectCalledApi( + ApiTypeEngine.kEngineStopLastMileProbeTest.index, + jsonEncode({}), + ); + }); + + testWidgets( + 'switchCamera', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + + rtcEngine = await _createEngine(); + + await rtcEngine.switchCamera(); + + fakeIrisEngine.expectCalledApi( + ApiTypeEngine.kEngineSwitchCamera.index, + jsonEncode({}), + ); + }, + skip: !(Platform.isAndroid || Platform.isIOS), + ); + + testWidgets('unloadEffect', (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + + rtcEngine = await _createEngine(); + + await rtcEngine.unloadEffect(10); + + fakeIrisEngine.expectCalledApi( + ApiTypeEngine.kEngineUnloadEffect.index, + jsonEncode({ + 'soundId': 10, + }), + ); + }); + + testWidgets('unregisterMediaMetadataObserver', (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + + rtcEngine = await _createEngine(); + + await rtcEngine.unregisterMediaMetadataObserver(); + + fakeIrisEngine.expectCalledApi( + ApiTypeEngine.kEngineUnRegisterMediaMetadataObserver.index, + jsonEncode({'type': 0}), + ); + }); + + testWidgets('updateChannelMediaRelay', (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + + rtcEngine = await _createEngine(); + final ChannelMediaRelayConfiguration config = + ChannelMediaRelayConfiguration( + ChannelMediaInfo('testapi', 10), + [ChannelMediaInfo('testapi', 10)], + ); + await rtcEngine.updateChannelMediaRelay(config); + + fakeIrisEngine.expectCalledApi( + ApiTypeEngine.kEngineUpdateChannelMediaRelay.index, + jsonEncode({ + 'configuration': config.toJson(), + }), + ); + }); + + testWidgets( + 'enableFaceDetection', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + + rtcEngine = await _createEngine(); + + await rtcEngine.enableFaceDetection(true); + + fakeIrisEngine.expectCalledApi( + ApiTypeEngine.kEngineEnableFaceDetection.index, + jsonEncode({ + 'enable': true, + }), + ); + }, + skip: !(Platform.isAndroid || Platform.isIOS), + ); + + testWidgets('setAudioMixingPitch', (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + + rtcEngine = await _createEngine(); + + await rtcEngine.setAudioMixingPitch(10); + + fakeIrisEngine.expectCalledApi( + ApiTypeEngine.kEngineSetAudioMixingPitch.index, + jsonEncode({ + 'pitch': 10, + }), + ); + }); + + testWidgets('enableEncryption', (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + + rtcEngine = await _createEngine(); + final EncryptionConfig config = + EncryptionConfig(encryptionMode: EncryptionMode.AES128ECB); + await rtcEngine.enableEncryption(true, config); + + fakeIrisEngine.expectCalledApi( + ApiTypeEngine.kEngineEnableEncryption.index, + jsonEncode({ + 'enabled': true, + 'config': config.toJson(), + }), + ); + }); + + testWidgets('sendCustomReportMessage', (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + + rtcEngine = await _createEngine(); + await rtcEngine.sendCustomReportMessage( + '123', 'category', 'event', 'label', 10); + + fakeIrisEngine.expectCalledApi( + ApiTypeEngine.kEngineSendCustomReportMessage.index, + jsonEncode({ + 'id': '123', + 'category': 'category', + 'event': 'event', + 'label': 'label', + 'value': 10, + }), + ); + }); + + testWidgets( + 'setAudioSessionOperationRestriction', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + + rtcEngine = await _createEngine(); + await rtcEngine.setAudioSessionOperationRestriction( + AudioSessionOperationRestriction.All); + + fakeIrisEngine.expectCalledApi( + ApiTypeEngine.kEngineSetAudioSessionOperationRestriction.index, + jsonEncode({ + 'restriction': 1 << 7, + }), + ); + }, + skip: !Platform.isIOS, + ); + + testWidgets('setAudioEffectParameters', (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + + rtcEngine = await _createEngine(); + await rtcEngine.setAudioEffectParameters( + AudioEffectPreset.AudioEffectOff, 1, 2); + + fakeIrisEngine.expectCalledApi( + ApiTypeEngine.kEngineSetAudioEffectParameters.index, + jsonEncode({ + 'preset': 0x00000000, + 'param1': 1, + 'param2': 2, + }), + ); + }); + + testWidgets('setAudioEffectPreset', (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + + rtcEngine = await _createEngine(); + await rtcEngine.setAudioEffectPreset(AudioEffectPreset.PitchCorrection); + + fakeIrisEngine.expectCalledApi( + ApiTypeEngine.kEngineSetAudioEffectPreset.index, + jsonEncode({ + 'preset': 0x02040100, + }), + ); + }); + + testWidgets('setVoiceBeautifierPreset', (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + + rtcEngine = await _createEngine(); + await rtcEngine + .setVoiceBeautifierPreset(VoiceBeautifierPreset.SingingBeautifier); + + fakeIrisEngine.expectCalledApi( + ApiTypeEngine.kEngineSetVoiceBeautifierPreset.index, + jsonEncode({ + 'preset': 0x01020100, + }), + ); + }); + + testWidgets('createDataStreamWithConfig', (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + + rtcEngine = await _createEngine(); + final DataStreamConfig config = DataStreamConfig(true, true); + await rtcEngine.createDataStreamWithConfig(config); + + fakeIrisEngine.expectCalledApi( + ApiTypeEngine.kEngineCreateDataStream.index, + jsonEncode({ + 'config': config.toJson(), + }), + ); + }); + + testWidgets('enableDeepLearningDenoise', (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + + rtcEngine = await _createEngine(); + await rtcEngine.enableDeepLearningDenoise(true); + + fakeIrisEngine.expectCalledApi( + ApiTypeEngine.kEngineEnableDeepLearningDenoise.index, + jsonEncode({ + 'enable': true, + }), + ); + }); + + testWidgets('enableRemoteSuperResolution', (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + + rtcEngine = await _createEngine(); + await rtcEngine.enableRemoteSuperResolution(10, true); + + fakeIrisEngine.expectCalledApi( + ApiTypeEngine.kEngineEnableRemoteSuperResolution.index, + jsonEncode({ + 'userId': 10, + 'enable': true, + }), + ); + }); + + testWidgets('setCloudProxy', (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + + rtcEngine = await _createEngine(); + await rtcEngine.setCloudProxy(CloudProxyType.TCP); + + fakeIrisEngine.expectCalledApi( + ApiTypeEngine.kEngineSetCloudProxy.index, + jsonEncode({ + 'proxyType': 2, + }), + ); + }); + + testWidgets('uploadLogFile', (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + + fakeIrisEngine.mockCallApiResult( + ApiTypeEngine.kEngineUploadLogFile.index, + jsonEncode({}), + '1', + ); + + rtcEngine = await _createEngine(); + final ret = await rtcEngine.uploadLogFile(); + + fakeIrisEngine.expectCalledApi( + ApiTypeEngine.kEngineUploadLogFile.index, + jsonEncode({}), + ); + + expect(ret, '1'); + }); + + testWidgets('setVoiceBeautifierParameters', (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + + rtcEngine = await _createEngine(); + await rtcEngine.setVoiceBeautifierParameters( + VoiceBeautifierPreset.SingingBeautifier, 1, 2); + + fakeIrisEngine.expectCalledApi( + ApiTypeEngine.kEngineSetVoiceBeautifierParameters.index, + jsonEncode({ + 'preset': 0x01020100, + 'param1': 1, + 'param2': 2, + }), + ); + }); + + testWidgets('setVoiceConversionPreset', (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + + rtcEngine = await _createEngine(); + await rtcEngine.setVoiceConversionPreset(VoiceConversionPreset.Sweet); + + fakeIrisEngine.expectCalledApi( + ApiTypeEngine.kEngineSetVoiceConversionPreset.index, + jsonEncode({ + 'preset': 50397696, + }), + ); + }); + + testWidgets('pauseAllChannelMediaRelay', (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + + rtcEngine = await _createEngine(); + await rtcEngine.pauseAllChannelMediaRelay(); + + fakeIrisEngine.expectCalledApi( + ApiTypeEngine.kEnginePauseAllChannelMediaRelay.index, + jsonEncode({}), + ); + }); + + testWidgets('resumeAllChannelMediaRelay', (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + + rtcEngine = await _createEngine(); + await rtcEngine.resumeAllChannelMediaRelay(); + + fakeIrisEngine.expectCalledApi( + ApiTypeEngine.kEngineResumeAllChannelMediaRelay.index, + jsonEncode({}), + ); + }); + + testWidgets('setLocalAccessPoint', (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + + rtcEngine = await _createEngine(); + await rtcEngine.setLocalAccessPoint(['127.0.0.1'], 'example.com'); + + fakeIrisEngine.expectCalledApi( + ApiTypeEngine.kEngineSetLocalAccessPoint.index, + jsonEncode({ + 'ips': ['127.0.0.1'], + 'domain': 'example.com', + }), + ); + }); + + testWidgets( + 'setScreenCaptureContentHint', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + + rtcEngine = await _createEngine(); + await rtcEngine.setScreenCaptureContentHint(VideoContentHint.Motion); + + fakeIrisEngine.expectCalledApi( + ApiTypeEngine.kEngineSetScreenCaptureContentHint.index, + jsonEncode({ + 'contentHint': 1, + }), + ); + }, + skip: (Platform.isAndroid || Platform.isIOS), + ); + + group('startScreenCaptureByDisplayId', () { + testWidgets( + 'with `displayId`', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + + rtcEngine = await _createEngine(); + await rtcEngine.startScreenCaptureByDisplayId( + 10, + ); + + fakeIrisEngine.expectCalledApi( + ApiTypeEngine.kEngineStartScreenCaptureByDisplayId.index, + jsonEncode({ + 'displayId': 10, + 'regionRect': null, + 'captureParams': null, + }), + ); + }, + skip: !Platform.isMacOS, + ); + + testWidgets( + 'with `displayId`, `regionRect`', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + + rtcEngine = await _createEngine(); + final rect = Rectangle(x: 10, y: 10); + await rtcEngine.startScreenCaptureByDisplayId(10, rect); + + fakeIrisEngine.expectCalledApi( + ApiTypeEngine.kEngineStartScreenCaptureByDisplayId.index, + jsonEncode({ + 'displayId': 10, + 'regionRect': rect.toJson(), + 'captureParams': null, + }), + ); + }, + skip: !Platform.isMacOS, + ); + + testWidgets( + 'with `displayId`, `regionRect`, `captureParams`', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + + rtcEngine = await _createEngine(); + final rect = Rectangle(x: 10, y: 10); + final ScreenCaptureParameters params = ScreenCaptureParameters( + dimensions: VideoDimensions(width: 10, height: 10)); + await rtcEngine.startScreenCaptureByDisplayId(10, rect, params); + + fakeIrisEngine.expectCalledApi( + ApiTypeEngine.kEngineStartScreenCaptureByDisplayId.index, + jsonEncode({ + 'displayId': 10, + 'regionRect': rect.toJson(), + 'captureParams': params.toJson(), + }), + ); + }, + skip: !Platform.isMacOS, + ); + }); + + group('startScreenCaptureByScreenRect', () { + testWidgets( + 'with `screenRect`', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + + rtcEngine = await _createEngine(); + final rect = Rectangle(x: 10, y: 10); + await rtcEngine.startScreenCaptureByScreenRect(rect); + + fakeIrisEngine.expectCalledApi( + ApiTypeEngine.kEngineStartScreenCaptureByScreenRect.index, + jsonEncode({ + 'screenRect': rect.toJson(), + 'regionRect': null, + 'captureParams': null, + }), + ); + }, + skip: !Platform.isWindows, + ); + + testWidgets( + 'with `screenRect`, `regionRect`', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + + rtcEngine = await _createEngine(); + final screenRect = Rectangle(x: 10, y: 10); + final regionRect = Rectangle(x: 20, y: 20); + + await rtcEngine.startScreenCaptureByScreenRect(screenRect, regionRect); + + fakeIrisEngine.expectCalledApi( + ApiTypeEngine.kEngineStartScreenCaptureByScreenRect.index, + jsonEncode({ + 'screenRect': screenRect.toJson(), + 'regionRect': regionRect.toJson(), + 'captureParams': null, + }), + ); + }, + skip: !Platform.isWindows, + ); + + testWidgets( + 'with `screenRect`, `regionRect`, `captureParams`', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + + rtcEngine = await _createEngine(); + final screenRect = Rectangle(x: 10, y: 10); + final regionRect = Rectangle(x: 20, y: 20); + final ScreenCaptureParameters params = ScreenCaptureParameters( + dimensions: VideoDimensions(width: 10, height: 10)); + await rtcEngine.startScreenCaptureByScreenRect( + screenRect, regionRect, params); + + fakeIrisEngine.expectCalledApi( + ApiTypeEngine.kEngineStartScreenCaptureByScreenRect.index, + jsonEncode({ + 'screenRect': screenRect.toJson(), + 'regionRect': regionRect.toJson(), + 'captureParams': params.toJson(), + }), + ); + }, + skip: !Platform.isWindows, + ); + }); + + group('startScreenCaptureByWindowId', () { + testWidgets( + 'with `windowId`', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + + rtcEngine = await _createEngine(); + await rtcEngine.startScreenCaptureByWindowId(10); + + fakeIrisEngine.expectCalledApi( + ApiTypeEngine.kEngineStartScreenCaptureByWindowId.index, + jsonEncode({ + 'windowId': 10, + 'regionRect': null, + 'captureParams': null, + }), + ); + }, + skip: (Platform.isAndroid || Platform.isIOS), + ); + + testWidgets( + 'with `windowId`, `regionRect`', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + + rtcEngine = await _createEngine(); + final regionRect = Rectangle(x: 20, y: 20); + await rtcEngine.startScreenCaptureByWindowId(10, regionRect); + + fakeIrisEngine.expectCalledApi( + ApiTypeEngine.kEngineStartScreenCaptureByWindowId.index, + jsonEncode({ + 'windowId': 10, + 'regionRect': regionRect.toJson(), + 'captureParams': null, + }), + ); + }, + skip: (Platform.isAndroid || Platform.isIOS), + ); + + testWidgets( + 'with `windowId`, `regionRect`, `captureParams`', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + + rtcEngine = await _createEngine(); + final regionRect = Rectangle(x: 20, y: 20); + final ScreenCaptureParameters params = ScreenCaptureParameters( + dimensions: VideoDimensions(width: 10, height: 10)); + await rtcEngine.startScreenCaptureByWindowId(10, regionRect, params); + + fakeIrisEngine.expectCalledApi( + ApiTypeEngine.kEngineStartScreenCaptureByWindowId.index, + jsonEncode({ + 'windowId': 10, + 'regionRect': regionRect.toJson(), + 'captureParams': params.toJson(), + }), + ); + }, + skip: (Platform.isAndroid || Platform.isIOS), + ); + }); + + testWidgets( + 'stopScreenCapture', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + + rtcEngine = await _createEngine(); + await rtcEngine.stopScreenCapture(); + + fakeIrisEngine.expectCalledApi( + ApiTypeEngine.kEngineStopScreenCapture.index, + jsonEncode({}), + ); + }, + skip: (Platform.isAndroid || Platform.isIOS), + ); + + testWidgets( + 'updateScreenCaptureParameters', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + + rtcEngine = await _createEngine(); + final ScreenCaptureParameters params = ScreenCaptureParameters( + dimensions: VideoDimensions(width: 10, height: 10)); + await rtcEngine.updateScreenCaptureParameters(params); + + fakeIrisEngine.expectCalledApi( + ApiTypeEngine.kEngineUpdateScreenCaptureParameters.index, + jsonEncode({ + 'captureParams': params.toJson(), + }), + ); + }, + skip: (Platform.isAndroid || Platform.isIOS), + ); + + testWidgets( + 'updateScreenCaptureRegion', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + + rtcEngine = await _createEngine(); + final Rectangle rect = Rectangle(width: 10, height: 10); + await rtcEngine.updateScreenCaptureRegion(rect); + + fakeIrisEngine.expectCalledApi( + ApiTypeEngine.kEngineUpdateScreenCaptureRegion.index, + jsonEncode({ + 'regionRect': rect.toJson(), + }), + ); + }, + skip: (Platform.isAndroid || Platform.isIOS), + ); + + group('startScreenCapture', () { + testWidgets( + 'with `windowId`', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + + rtcEngine = await _createEngine(); + await rtcEngine.startScreenCapture(10); + + fakeIrisEngine.expectCalledApi( + ApiTypeEngine.kEngineStartScreenCapture.index, + jsonEncode({ + 'windowId': 10, + 'captureFreq': 0, + 'rect': null, + 'bitrate': 0, + }), + ); + }, + skip: (Platform.isAndroid || Platform.isIOS), + ); + + testWidgets( + 'with `windowId`, `captureFreq`', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + + rtcEngine = await _createEngine(); + await rtcEngine.startScreenCapture(10, 20); + + fakeIrisEngine.expectCalledApi( + ApiTypeEngine.kEngineStartScreenCapture.index, + jsonEncode({ + 'windowId': 10, + 'captureFreq': 20, + 'rect': null, + 'bitrate': 0, + }), + ); + }, + skip: (Platform.isAndroid || Platform.isIOS), + ); + + testWidgets( + 'with `windowId`, `captureFreq`, `rect`', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + + rtcEngine = await _createEngine(); + final rect = Rect(left: 10, right: 10); + await rtcEngine.startScreenCapture(10, 20, rect); + + fakeIrisEngine.expectCalledApi( + ApiTypeEngine.kEngineStartScreenCapture.index, + jsonEncode({ + 'windowId': 10, + 'captureFreq': 20, + 'rect': rect.toJson(), + 'bitrate': 0, + }), + ); + }, + skip: (Platform.isAndroid || Platform.isIOS), + ); + + testWidgets( + 'with `windowId`, `captureFreq`, `rect`, `bitrate`', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + + rtcEngine = await _createEngine(); + final rect = Rect(left: 10, right: 10); + await rtcEngine.startScreenCapture(10, 20, rect, 30); + + fakeIrisEngine.expectCalledApi( + ApiTypeEngine.kEngineStartScreenCapture.index, + jsonEncode({ + 'windowId': 10, + 'captureFreq': 20, + 'rect': rect.toJson(), + 'bitrate': 30, + }), + ); + }, + skip: (Platform.isAndroid || Platform.isIOS), + ); + }); + + testWidgets( + 'getCameraMaxZoomFactor', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + + rtcEngine = await _createEngine(); + await rtcEngine.getCameraMaxZoomFactor(); + + fakeIrisEngine.expectCalledApi( + ApiTypeEngine.kEngineGetCameraMaxZoomFactor.index, + jsonEncode({}), + ); + }, + skip: !Platform.isAndroid, // Can only run on Android emulator + ); + + testWidgets( + 'isCameraAutoFocusFaceModeSupported', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + + rtcEngine = await _createEngine(); + await rtcEngine.isCameraAutoFocusFaceModeSupported(); + + fakeIrisEngine.expectCalledApi( + ApiTypeEngine.kEngineIsCameraAutoFocusFaceModeSupported.index, + jsonEncode({}), + ); + }, + skip: !(Platform.isAndroid || Platform.isIOS), + ); + + testWidgets( + 'isCameraExposurePositionSupported', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + + rtcEngine = await _createEngine(); + await rtcEngine.isCameraExposurePositionSupported(); + + fakeIrisEngine.expectCalledApi( + ApiTypeEngine.kEngineIsCameraExposurePositionSupported.index, + jsonEncode({}), + ); + }, + skip: !(Platform.isAndroid || Platform.isIOS), + ); + + testWidgets( + 'isCameraFocusSupported', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + + rtcEngine = await _createEngine(); + await rtcEngine.isCameraFocusSupported(); + + fakeIrisEngine.expectCalledApi( + ApiTypeEngine.kEngineIsCameraFocusSupported.index, + jsonEncode({}), + ); + }, + skip: !(Platform.isAndroid || Platform.isIOS), + ); + + testWidgets( + 'isCameraZoomSupported', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + + fakeIrisEngine.mockCallApiReturnCode( + ApiTypeEngine.kEngineIsCameraZoomSupported.index, jsonEncode({}), 1); + rtcEngine = await _createEngine(); + + final ret = await rtcEngine.isCameraZoomSupported(); + + fakeIrisEngine.expectCalledApi( + ApiTypeEngine.kEngineIsCameraZoomSupported.index, + jsonEncode({}), + ); + + expect(ret, true); + }, + skip: !(Platform.isAndroid || Platform.isIOS), + ); + + testWidgets( + 'takeSnapshot', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + + rtcEngine = await _createEngine(); + await rtcEngine.takeSnapshot('testapi', 20, '/path'); + + fakeIrisEngine.expectCalledApi( + ApiTypeEngine.kEngineTakeSnapshot.index, + jsonEncode({ + 'channel': 'testapi', + 'uid': 20, + 'filePath': '/path', + }), + ); + }, + + // skip: !Platform.isAndroid, + // TODO(littlegnal): [MS-99390] Currently fail on Android + skip: true, + ); +} + +Future _createEngine() async { + return RtcEngine.create('123'); +} diff --git a/integration_test_app/integration_test/agora_rtc_engine_event_handler_api_test.dart b/integration_test_app/integration_test/agora_rtc_engine_event_handler_api_test.dart new file mode 100644 index 000000000..ff41ec3b5 --- /dev/null +++ b/integration_test_app/integration_test/agora_rtc_engine_event_handler_api_test.dart @@ -0,0 +1,1773 @@ +import 'dart:convert'; +import 'dart:typed_data'; + +import 'package:agora_rtc_engine/rtc_engine.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:integration_test/integration_test.dart'; +import 'package:integration_test_app/src/event_handler_tester.dart'; +import 'package:integration_test_app/src/fake_iris_rtc_engine.dart'; +import 'package:integration_test_app/main.dart' as app; + +void main() { + IntegrationTestWidgetsFlutterBinding.ensureInitialized(); + + late RtcEngine rtcEngine; + late FakeIrisRtcEngine fakeIrisEngine; + + tearDown(() async { + await rtcEngine.destroy(); + fakeIrisEngine.dispose(); + }); + + Future _createRtcEngine() { + return RtcEngine.create('123'); + } + + testWidgets('warning', (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + rtcEngine = await _createRtcEngine(); + WarningCode? code; + rtcEngine.setEventHandler(RtcEngineEventHandler( + warning: (WarningCode warn) { + code = warn; + }, + )); + + await fakeIrisEngine.fireAndWaitEvent( + tester, 'onWarning', '{"warn":16,"msg":"warning"}'); + expect(code == WarningCode.InitVideo, isTrue); + }); + + testWidgets('error', (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + rtcEngine = await _createRtcEngine(); + ErrorCode? errorCode; + rtcEngine.setEventHandler(RtcEngineEventHandler(error: (ErrorCode err) { + errorCode = err; + })); + + await fakeIrisEngine.fireAndWaitEvent( + tester, 'onError', '{"err":11,"msg":"error"}'); + expect(errorCode == ErrorCode.Canceled, isTrue); + }); + + testWidgets('joinChannelSuccess', (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + rtcEngine = await _createRtcEngine(); + String channelRet = ''; + int uidRet = 0; + int elapsedRet = 0; + rtcEngine.setEventHandler(RtcEngineEventHandler( + joinChannelSuccess: (String channel, int uid, int elapsed) { + channelRet = channel; + uidRet = uid; + elapsedRet = elapsed; + }, + )); + + await fakeIrisEngine.fireAndWaitEvent( + tester, + 'onJoinChannelSuccess', + '{"channel":"testapi","uid":10, "elapsed":100}', + ); + expect(channelRet, 'testapi'); + expect(uidRet, 10); + expect(elapsedRet, 100); + }); + + testWidgets('apiCallExecuted', (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + rtcEngine = await _createRtcEngine(); + ErrorCode? errorRet; + String apiRet = ''; + String resultRet = ''; + rtcEngine.setEventHandler(RtcEngineEventHandler( + apiCallExecuted: (ErrorCode error, String api, String result) { + errorRet = error; + apiRet = api; + resultRet = result; + }, + )); + + await fakeIrisEngine.fireAndWaitEvent( + tester, + 'onApiCallExecuted', + '{"err":1,"api":"joinChannel", "result":"failed"}', + ); + expect(errorRet, ErrorCode.Failed); + expect(apiRet, 'joinChannel'); + expect(resultRet, 'failed'); + }); + + testWidgets('rejoinChannelSuccess', (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + rtcEngine = await _createRtcEngine(); + String channelRet = ''; + int uidRet = 0; + int elapsedRet = 0; + rtcEngine.setEventHandler(RtcEngineEventHandler( + rejoinChannelSuccess: (String channel, int uid, int elapsed) { + channelRet = channel; + uidRet = uid; + elapsedRet = elapsed; + }, + )); + + await fakeIrisEngine.fireAndWaitEvent( + tester, + 'onRejoinChannelSuccess', + '{"channel":"testapi","uid":10, "elapsed":100}', + ); + expect(channelRet, 'testapi'); + expect(uidRet, 10); + expect(elapsedRet, 100); + }); + + testWidgets('leaveChannel', (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + rtcEngine = await _createRtcEngine(); + RtcStats? statsRet; + rtcEngine.setEventHandler(RtcEngineEventHandler( + leaveChannel: (RtcStats stats) { + statsRet = stats; + }, + )); + + final expectedStats = RtcStats(10, 20, 20, 100, 100, 200, 200, 10, 10, 20, + 20, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10); + + await fakeIrisEngine.fireAndWaitEvent( + tester, + 'onLeaveChannel', + '{"stats":${jsonEncode(expectedStats.toJson())}}', + ); + expect(jsonEncode(statsRet), jsonEncode(expectedStats)); + }); + + testWidgets('localUserRegistered', (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + rtcEngine = await _createRtcEngine(); + int uidRet = 0; + String userAccountRet = ''; + rtcEngine.setEventHandler(RtcEngineEventHandler( + localUserRegistered: (int uid, String userAccount) { + uidRet = uid; + userAccountRet = userAccount; + }, + )); + + await fakeIrisEngine.fireAndWaitEvent( + tester, + 'onLocalUserRegistered', + '{"uid":10,"userAccount":"user1"}', + ); + expect(uidRet, 10); + expect(userAccountRet, 'user1'); + }); + + testWidgets('userInfoUpdated', (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + rtcEngine = await _createRtcEngine(); + int uidRet = 0; + UserInfo? userInfoRet; + rtcEngine.setEventHandler(RtcEngineEventHandler( + userInfoUpdated: (int uid, UserInfo userInfo) { + uidRet = uid; + userInfoRet = userInfo; + }, + )); + final expectedUserInfo = UserInfo(10, 'user1'); + await fakeIrisEngine.fireAndWaitEvent( + tester, + 'onUserInfoUpdated', + '{"uid":10,"info":${jsonEncode(expectedUserInfo.toJson())}}', + ); + expect(uidRet, 10); + expect(jsonEncode(userInfoRet), jsonEncode(expectedUserInfo)); + }); + + testWidgets('clientRoleChanged', (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + rtcEngine = await _createRtcEngine(); + ClientRole? oldRoleRet; + ClientRole? newRoleRet; + rtcEngine.setEventHandler(RtcEngineEventHandler( + clientRoleChanged: (ClientRole oldRole, ClientRole newRole) { + oldRoleRet = oldRole; + newRoleRet = newRole; + }, + )); + await fakeIrisEngine.fireAndWaitEvent( + tester, + 'onClientRoleChanged', + '{"oldRole":1,"newRole":2}', + ); + expect(oldRoleRet, ClientRole.Broadcaster); + expect(newRoleRet, ClientRole.Audience); + }); + + testWidgets('userJoined', (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + rtcEngine = await _createRtcEngine(); + int uidRet = 0; + int elapsedRet = 0; + rtcEngine.setEventHandler(RtcEngineEventHandler( + userJoined: (int uid, int elapsed) { + uidRet = uid; + elapsedRet = elapsed; + }, + )); + await fakeIrisEngine.fireAndWaitEvent( + tester, + 'onUserJoined', + '{"uid":10,"elapsed":100}', + ); + expect(uidRet, 10); + expect(elapsedRet, 100); + }); + + testWidgets('userOffline', (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + rtcEngine = await _createRtcEngine(); + int uidRet = 0; + UserOfflineReason? reasonRet; + rtcEngine.setEventHandler(RtcEngineEventHandler( + userOffline: (int uid, UserOfflineReason reason) { + uidRet = uid; + reasonRet = reason; + }, + )); + await fakeIrisEngine.fireAndWaitEvent( + tester, + 'onUserOffline', + '{"uid":10,"reason":2}', + ); + expect(uidRet, 10); + expect(reasonRet, UserOfflineReason.BecomeAudience); + }); + + testWidgets('connectionStateChanged', (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + rtcEngine = await _createRtcEngine(); + ConnectionStateType? stateRet; + ConnectionChangedReason? reasonRet; + rtcEngine.setEventHandler(RtcEngineEventHandler( + connectionStateChanged: + (ConnectionStateType state, ConnectionChangedReason reason) { + stateRet = state; + reasonRet = reason; + }, + )); + await fakeIrisEngine.fireAndWaitEvent( + tester, + 'onConnectionStateChanged', + '{"state":3,"reason":1}', + ); + expect(stateRet, ConnectionStateType.Connected); + expect(reasonRet, ConnectionChangedReason.JoinSuccess); + }); + + testWidgets('networkTypeChanged', (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + rtcEngine = await _createRtcEngine(); + NetworkType? typeRet; + rtcEngine.setEventHandler(RtcEngineEventHandler( + networkTypeChanged: (NetworkType type) { + typeRet = type; + }, + )); + await fakeIrisEngine.fireAndWaitEvent( + tester, 'onNetworkTypeChanged', '{"type":2}'); + expect(typeRet, NetworkType.WIFI); + }); + + testWidgets('connectionLost', (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + rtcEngine = await _createRtcEngine(); + bool called = false; + rtcEngine.setEventHandler(RtcEngineEventHandler( + connectionLost: () { + called = true; + }, + )); + await fakeIrisEngine.fireAndWaitEvent(tester, 'onConnectionLost', '{}'); + expect(called, isTrue); + }); + + testWidgets('tokenPrivilegeWillExpire', (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + rtcEngine = await _createRtcEngine(); + String tokenRet = ''; + rtcEngine.setEventHandler(RtcEngineEventHandler( + tokenPrivilegeWillExpire: (String token) { + tokenRet = token; + }, + )); + await fakeIrisEngine.fireAndWaitEvent( + tester, 'onTokenPrivilegeWillExpire', '{"token":"t"}'); + expect(tokenRet, 't'); + }); + + testWidgets('requestToken', (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + rtcEngine = await _createRtcEngine(); + bool called = false; + rtcEngine.setEventHandler(RtcEngineEventHandler( + requestToken: () { + called = true; + }, + )); + await fakeIrisEngine.fireAndWaitEvent(tester, 'onRequestToken', '{}'); + expect(called, isTrue); + }); + + testWidgets('audioVolumeIndication', (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + rtcEngine = await _createRtcEngine(); + List speakersRet = []; + int totalVolumeRet = 0; + rtcEngine.setEventHandler(RtcEngineEventHandler( + audioVolumeIndication: ( + List speakers, + int totalVolume, + ) { + speakersRet = speakers; + totalVolumeRet = totalVolume; + }, + )); + final expectedSpeakers = [AudioVolumeInfo(10, 100, 20, 'testapi')]; + await fakeIrisEngine.fireAndWaitEvent( + tester, + 'onAudioVolumeIndication', + '{"speakers":${jsonEncode(expectedSpeakers)},"speakerNumber":1,"totalVolume":10}', + ); + expect(jsonEncode(speakersRet), jsonEncode(expectedSpeakers)); + expect(totalVolumeRet, 10); + }); + + testWidgets('activeSpeaker', (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + rtcEngine = await _createRtcEngine(); + int uidRet = 0; + rtcEngine.setEventHandler(RtcEngineEventHandler( + activeSpeaker: (int uid) { + uidRet = uid; + }, + )); + await fakeIrisEngine.fireAndWaitEvent( + tester, + 'onActiveSpeaker', + '{"uid":10}', + ); + expect(uidRet, 10); + }); + + testWidgets('firstLocalAudioFrame', (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + rtcEngine = await _createRtcEngine(); + int elapsedRet = 0; + rtcEngine.setEventHandler(RtcEngineEventHandler( + firstLocalAudioFrame: (int elapsed) { + elapsedRet = elapsed; + }, + )); + await fakeIrisEngine.fireAndWaitEvent( + tester, 'onFirstLocalAudioFrame', '{"elapsed":100}'); + expect(elapsedRet, 100); + }); + + testWidgets('firstLocalVideoFrame', (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + rtcEngine = await _createRtcEngine(); + int widthRet = 0; + int heightRet = 0; + int elapsedRet = 0; + rtcEngine.setEventHandler(RtcEngineEventHandler( + firstLocalVideoFrame: (int width, int height, int elapsed) { + widthRet = width; + heightRet = height; + elapsedRet = elapsed; + }, + )); + await fakeIrisEngine.fireAndWaitEvent( + tester, + 'onFirstLocalVideoFrame', + '{"width":10,"height":10,"elapsed":100}', + ); + expect(widthRet, 10); + expect(heightRet, 10); + expect(elapsedRet, 100); + }); + + testWidgets('videoSizeChanged', (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + rtcEngine = await _createRtcEngine(); + int uidRet = 0; + int widthRet = 0; + int heightRet = 0; + int rotationRet = 0; + rtcEngine.setEventHandler(RtcEngineEventHandler( + videoSizeChanged: (int uid, int width, int height, int rotation) { + uidRet = uid; + widthRet = width; + heightRet = height; + rotationRet = rotation; + }, + )); + await fakeIrisEngine.fireAndWaitEvent( + tester, + 'onVideoSizeChanged', + '{"uid":10,"width":20,"height":20,"rotation":30}', + ); + expect(uidRet, 10); + expect(widthRet, 20); + expect(heightRet, 20); + expect(rotationRet, 30); + }); + + testWidgets('remoteVideoStateChanged', (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + rtcEngine = await _createRtcEngine(); + int uidRet = 0; + VideoRemoteState? stateRet; + VideoRemoteStateReason? reasonRet; + int elapsedRet = 0; + rtcEngine.setEventHandler(RtcEngineEventHandler( + remoteVideoStateChanged: (int uid, VideoRemoteState state, + VideoRemoteStateReason reason, int elapsed) { + uidRet = uid; + stateRet = state; + reasonRet = reason; + elapsedRet = elapsed; + }, + )); + await fakeIrisEngine.fireAndWaitEvent( + tester, + 'onRemoteVideoStateChanged', + '{"uid":10,"state":1,"reason":1,"elapsed":100}', + ); + expect(uidRet, 10); + expect(stateRet, VideoRemoteState.Starting); + expect(reasonRet, VideoRemoteStateReason.NetworkCongestion); + expect(elapsedRet, 100); + }); + + testWidgets('localVideoStateChanged', (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + rtcEngine = await _createRtcEngine(); + LocalVideoStreamState? localVideoStateRet; + LocalVideoStreamError? errorRet; + rtcEngine.setEventHandler(RtcEngineEventHandler( + localVideoStateChanged: + (LocalVideoStreamState localVideoState, LocalVideoStreamError error) { + localVideoStateRet = localVideoState; + errorRet = error; + }, + )); + await fakeIrisEngine.fireAndWaitEvent( + tester, + 'onLocalVideoStateChanged', + '{"localVideoState":1,"error":2}', + ); + expect(localVideoStateRet, LocalVideoStreamState.Capturing); + expect(errorRet, LocalVideoStreamError.DeviceNoPermission); + }); + + testWidgets('remoteAudioStateChanged', (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + rtcEngine = await _createRtcEngine(); + int uidRet = 0; + AudioRemoteState? stateRet; + AudioRemoteStateReason? reasonRet; + int elapsedRet = 0; + rtcEngine.setEventHandler(RtcEngineEventHandler( + remoteAudioStateChanged: (int uid, AudioRemoteState state, + AudioRemoteStateReason reason, int elapsed) { + uidRet = uid; + stateRet = state; + reasonRet = reason; + elapsedRet = elapsed; + }, + )); + await fakeIrisEngine.fireAndWaitEvent( + tester, + 'onRemoteAudioStateChanged', + '{"uid":10,"state":1,"reason":2,"elapsed":100}', + ); + + expect(uidRet, 10); + expect(stateRet, AudioRemoteState.Starting); + expect(reasonRet, AudioRemoteStateReason.NetworkRecovery); + expect(elapsedRet, 100); + }); + + testWidgets('localAudioStateChanged', (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + rtcEngine = await _createRtcEngine(); + AudioLocalState? stateRet; + AudioLocalError? errorRet; + rtcEngine.setEventHandler(RtcEngineEventHandler( + localAudioStateChanged: (AudioLocalState state, AudioLocalError error) { + stateRet = state; + errorRet = error; + }, + )); + await fakeIrisEngine.fireAndWaitEvent( + tester, + 'onLocalAudioStateChanged', + '{"state":2,"error":8}', + ); + + expect(stateRet, AudioLocalState.Encoding); + expect(errorRet, AudioLocalError.Interrupted); + }); + + testWidgets('onLocalPublishFallbackToAudioOnly', (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + rtcEngine = await _createRtcEngine(); + bool isFallbackOrRecoverRet = false; + rtcEngine.setEventHandler(RtcEngineEventHandler( + localPublishFallbackToAudioOnly: (bool isFallbackOrRecover) { + isFallbackOrRecoverRet = isFallbackOrRecover; + }, + )); + await fakeIrisEngine.fireAndWaitEvent( + tester, + 'onLocalPublishFallbackToAudioOnly', + '{"isFallbackOrRecover":true}', + ); + + expect(isFallbackOrRecoverRet, isTrue); + }); + + testWidgets('remoteSubscribeFallbackToAudioOnly', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + rtcEngine = await _createRtcEngine(); + int uidRet = 0; + bool isFallbackOrRecoverRet = false; + rtcEngine.setEventHandler(RtcEngineEventHandler( + remoteSubscribeFallbackToAudioOnly: (int uid, bool isFallbackOrRecover) { + uidRet = uid; + isFallbackOrRecoverRet = isFallbackOrRecover; + }, + )); + await fakeIrisEngine.fireAndWaitEvent( + tester, + 'onRemoteSubscribeFallbackToAudioOnly', + '{"uid":10,"isFallbackOrRecover":true}', + ); + expect(uidRet, 10); + expect(isFallbackOrRecoverRet, true); + }); + + testWidgets('audioRouteChanged', (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + rtcEngine = await _createRtcEngine(); + AudioOutputRouting? routingRet; + rtcEngine.setEventHandler(RtcEngineEventHandler( + audioRouteChanged: (AudioOutputRouting routing) { + routingRet = routing; + }, + )); + await fakeIrisEngine.fireAndWaitEvent( + tester, + 'onAudioRouteChanged', + '{"routing":7}', + ); + expect(routingRet, AudioOutputRouting.HDMI); + }); + + testWidgets('cameraFocusAreaChanged', (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + rtcEngine = await _createRtcEngine(); + Rect? rectRet; + rtcEngine.setEventHandler(RtcEngineEventHandler( + cameraFocusAreaChanged: (Rect rect) { + rectRet = rect; + }, + )); + final expectedRect = Rect( + x: 10, + y: 10, + width: 10, + height: 10, + left: 10, + top: 10, + right: 20, + bottom: 20, + ); + await fakeIrisEngine.fireAndWaitEvent( + tester, + 'onCameraFocusAreaChanged', + '{"x":10,"y":10,"width":10,"height":10}', + ); + expect(jsonEncode(rectRet), jsonEncode(expectedRect)); + }); + + testWidgets('cameraExposureAreaChanged', (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + rtcEngine = await _createRtcEngine(); + Rect? rectRet; + rtcEngine.setEventHandler(RtcEngineEventHandler( + cameraExposureAreaChanged: (Rect rect) { + rectRet = rect; + }, + )); + final expectedRect = Rect( + x: 10, + y: 10, + width: 10, + height: 10, + left: 10, + top: 10, + right: 20, + bottom: 20, + ); + await fakeIrisEngine.fireAndWaitEvent( + tester, + 'onCameraExposureAreaChanged', + '{"x":10,"y":10,"width":10,"height":10}', + ); + expect(jsonEncode(rectRet), jsonEncode(expectedRect)); + }); + + testWidgets('facePositionChanged', (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + rtcEngine = await _createRtcEngine(); + int imageWidthRet = 0; + int imageHeightRet = 0; + List? facesRet; + rtcEngine.setEventHandler(RtcEngineEventHandler( + facePositionChanged: + (int imageWidth, int imageHeight, List faces) { + imageWidthRet = imageWidth; + imageHeightRet = imageHeight; + facesRet = faces; + }, + )); + final expectedFaces = [FacePositionInfo(10, 10, 10, 10, 10)]; + await fakeIrisEngine.fireAndWaitEvent( + tester, + 'onFacePositionChanged', + '{"imageWidth":10,"imageHeight":10,"vecRectangle":[{"x":10,"y":10,"width":10,"height":10}],"vecDistance":[10]}', + ); + expect(imageWidthRet, 10); + expect(imageHeightRet, 10); + expect(jsonEncode(facesRet), jsonEncode(expectedFaces)); + }); + + testWidgets('rtcStats', (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + rtcEngine = await _createRtcEngine(); + RtcStats? statsRet; + rtcEngine.setEventHandler(RtcEngineEventHandler( + rtcStats: (RtcStats stats) { + statsRet = stats; + }, + )); + final expectedStats = RtcStats(10, 20, 20, 100, 100, 200, 200, 10, 10, 20, + 20, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10); + await fakeIrisEngine.fireAndWaitEvent( + tester, + 'onRtcStats', + '{"stats":${jsonEncode(expectedStats.toJson())}}', + ); + expect(jsonEncode(statsRet), jsonEncode(expectedStats)); + }); + + testWidgets('networkQuality', (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + rtcEngine = await _createRtcEngine(); + int uidRet = 0; + NetworkQuality? txQualityRet; + NetworkQuality? rxQualityRet; + rtcEngine.setEventHandler(RtcEngineEventHandler( + networkQuality: + (int uid, NetworkQuality txQuality, NetworkQuality rxQuality) { + uidRet = uid; + txQualityRet = txQuality; + rxQualityRet = rxQuality; + }, + )); + await fakeIrisEngine.fireAndWaitEvent( + tester, + 'onNetworkQuality', + '{"uid":10,"txQuality":2,"rxQuality":4}', + ); + expect(uidRet, 10); + expect(txQualityRet, NetworkQuality.Good); + expect(rxQualityRet, NetworkQuality.Bad); + }); + + testWidgets('lastmileProbeResult', (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + rtcEngine = await _createRtcEngine(); + LastmileProbeResult? resultRet; + rtcEngine.setEventHandler(RtcEngineEventHandler( + lastmileProbeResult: (LastmileProbeResult result) { + resultRet = result; + }, + )); + final expectLastmileProbeResult = LastmileProbeResult( + LastmileProbeResultState.Complete, + 10, + LastmileProbeOneWayResult(1, 2, 3), + LastmileProbeOneWayResult(1, 2, 3), + ); + await fakeIrisEngine.fireAndWaitEvent( + tester, + 'onLastmileProbeResult', + '{"result":${jsonEncode(expectLastmileProbeResult.toJson())}}', + ); + expect(jsonEncode(resultRet), jsonEncode(expectLastmileProbeResult)); + }); + + testWidgets('localVideoStats', (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + rtcEngine = await _createRtcEngine(); + LocalVideoStats? statsRet; + rtcEngine.setEventHandler(RtcEngineEventHandler( + localVideoStats: (LocalVideoStats stats) { + statsRet = stats; + }, + )); + final expectLocalVideoStats = LocalVideoStats( + 10, + 10, + 10, + 10, + 10, + 10, + VideoQualityAdaptIndication.AdaptDownBandwidth, + 10, + 10, + 10, + 10, + VideoCodecType.E264, + 10, + 10, + CaptureBrightnessLevelType.Bright, + ); + await fakeIrisEngine.fireAndWaitEvent( + tester, + 'onLocalVideoStats', + '{"stats":${jsonEncode(expectLocalVideoStats.toJson())}}', + ); + expect(jsonEncode(statsRet), jsonEncode(expectLocalVideoStats)); + }); + + testWidgets('localAudioStats', (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + rtcEngine = await _createRtcEngine(); + LocalAudioStats? statsRet; + rtcEngine.setEventHandler(RtcEngineEventHandler( + localAudioStats: (LocalAudioStats stats) { + statsRet = stats; + }, + )); + final expectLocalAudioStats = LocalAudioStats(10, 10, 10, 10); + await fakeIrisEngine.fireAndWaitEvent( + tester, + 'onLocalAudioStats', + '{"stats":${jsonEncode(expectLocalAudioStats.toJson())}}', + ); + expect(jsonEncode(statsRet), jsonEncode(expectLocalAudioStats)); + }); + + testWidgets('remoteVideoStats', (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + rtcEngine = await _createRtcEngine(); + RemoteVideoStats? statsRet; + rtcEngine.setEventHandler(RtcEngineEventHandler( + remoteVideoStats: (RemoteVideoStats stats) { + statsRet = stats; + }, + )); + final expectRemoteVideoStats = RemoteVideoStats( + 10, 10, 10, 10, 10, 10, 10, 10, VideoStreamType.High, 10, 10, 10, 10); + await fakeIrisEngine.fireAndWaitEvent( + tester, + 'onRemoteVideoStats', + '{"stats":${jsonEncode(expectRemoteVideoStats.toJson())}}', + ); + expect(jsonEncode(statsRet), jsonEncode(expectRemoteVideoStats)); + }); + + testWidgets('remoteAudioStats', (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + rtcEngine = await _createRtcEngine(); + RemoteAudioStats? statsRet; + rtcEngine.setEventHandler(RtcEngineEventHandler( + remoteAudioStats: (RemoteAudioStats stats) { + statsRet = stats; + }, + )); + final expectRemoteAudioStats = RemoteAudioStats( + 10, + NetworkQuality.Down, + 10, + 10, + 10, + 10, + 10, + 10, + 10, + 10, + 10, + 10, + ExperienceQualityType.Bad, + ExperiencePoorReason.LocalNetworkQualityPoor, + 10, + ); + await fakeIrisEngine.fireAndWaitEvent( + tester, + 'onRemoteAudioStats', + '{"stats":${jsonEncode(expectRemoteAudioStats.toJson())}}', + ); + expect(jsonEncode(statsRet), jsonEncode(expectRemoteAudioStats)); + }); + + testWidgets('audioMixingFinished', (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + rtcEngine = await _createRtcEngine(); + bool called = false; + rtcEngine.setEventHandler(RtcEngineEventHandler( + audioMixingFinished: () { + called = true; + }, + )); + await fakeIrisEngine.fireAndWaitEvent( + tester, 'onAudioMixingFinished', '{}'); + expect(called, true); + }); + + testWidgets('audioMixingStateChanged', (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + rtcEngine = await _createRtcEngine(); + AudioMixingStateCode? stateRet; + AudioMixingReason? reasonRet; + rtcEngine.setEventHandler(RtcEngineEventHandler( + audioMixingStateChanged: + (AudioMixingStateCode state, AudioMixingReason reason) { + stateRet = state; + reasonRet = reason; + }, + )); + await fakeIrisEngine.fireAndWaitEvent( + tester, + 'onAudioMixingStateChanged', + '{"state":711,"reason":725}', + ); + expect(stateRet, AudioMixingStateCode.Paused); + expect(reasonRet, AudioMixingReason.PausedByUser); + }); + + testWidgets('audioEffectFinished', (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + rtcEngine = await _createRtcEngine(); + int soundIdRet = 0; + rtcEngine.setEventHandler(RtcEngineEventHandler( + audioEffectFinished: (int soundId) { + soundIdRet = soundId; + }, + )); + await fakeIrisEngine.fireAndWaitEvent( + tester, + 'onAudioEffectFinished', + '{"soundId":10}', + ); + expect(soundIdRet, 10); + }); + + testWidgets('rtmpStreamingStateChanged', (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + rtcEngine = await _createRtcEngine(); + String urlRet = ''; + RtmpStreamingState? stateRet; + RtmpStreamingErrorCode? errCodeRet; + rtcEngine.setEventHandler(RtcEngineEventHandler( + rtmpStreamingStateChanged: (String url, RtmpStreamingState state, + RtmpStreamingErrorCode errCode) { + urlRet = url; + stateRet = state; + errCodeRet = errCode; + }, + )); + await fakeIrisEngine.fireAndWaitEvent( + tester, + 'onRtmpStreamingStateChanged', + '{"url":"https://example.com","state":3,"errCode":2}', + ); + expect(urlRet, 'https://example.com'); + expect(stateRet, RtmpStreamingState.Recovering); + expect(errCodeRet, RtmpStreamingErrorCode.EncryptedStreamNotAllowed); + }); + + testWidgets('transcodingUpdated', (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + rtcEngine = await _createRtcEngine(); + bool called = false; + rtcEngine.setEventHandler(RtcEngineEventHandler( + transcodingUpdated: () { + called = true; + }, + )); + await fakeIrisEngine.fireAndWaitEvent(tester, 'onTranscodingUpdated', '{}'); + expect(called, isTrue); + }); + + testWidgets('streamInjectedStatus', (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + rtcEngine = await _createRtcEngine(); + String urlRet = ''; + int uidRet = 0; + InjectStreamStatus? statusRet; + rtcEngine.setEventHandler(RtcEngineEventHandler( + streamInjectedStatus: (String url, int uid, InjectStreamStatus status) { + urlRet = url; + uidRet = uid; + statusRet = status; + }, + )); + await fakeIrisEngine.fireAndWaitEvent( + tester, + 'onStreamInjectedStatus', + '{"url":"https://example.com","uid":10,"status":0}', + ); + expect(urlRet, 'https://example.com'); + expect(uidRet, 10); + expect(statusRet, InjectStreamStatus.StartSuccess); + }); + + testWidgets('streamMessage', (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + rtcEngine = await _createRtcEngine(); + int uidRet = 0; + int streamIdRet = 0; + Uint8List? dataRet; + rtcEngine.setEventHandler(RtcEngineEventHandler( + streamMessage: (int uid, int streamId, Uint8List data) { + uidRet = uid; + streamIdRet = streamId; + dataRet = data; + }, + )); + final buffer = Uint8List.fromList([1, 1]); + await fakeIrisEngine.fireAndWaitEvent( + tester, + 'onStreamMessage', + '{"uid":10,"uid":10,"streamId":20,"length":2}', + buffer: buffer, + bufferSize: 2, + ); + expect(uidRet, 10); + expect(streamIdRet, 20); + expect(dataRet, buffer); + }); + + testWidgets('streamMessageError', (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + rtcEngine = await _createRtcEngine(); + int uidRet = 0; + int streamIdRet = 0; + ErrorCode? errorRet; + int missedRet = 0; + int cachedRet = 0; + rtcEngine.setEventHandler(RtcEngineEventHandler( + streamMessageError: + (int uid, int streamId, ErrorCode error, int missed, int cached) { + uidRet = uid; + streamIdRet = streamId; + errorRet = error; + missedRet = missed; + cachedRet = cached; + }, + )); + await fakeIrisEngine.fireAndWaitEvent( + tester, + 'onStreamMessageError', + '{"uid":10,"streamId":20,"code":1022,"missed":2,"cached":3}', + ); + expect(uidRet, 10); + expect(streamIdRet, 20); + expect(errorRet, ErrorCode.AdmInitLoopback); + expect(missedRet, 2); + expect(cachedRet, 3); + }); + + testWidgets('mediaEngineLoadSuccess', (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + rtcEngine = await _createRtcEngine(); + bool called = false; + rtcEngine.setEventHandler(RtcEngineEventHandler( + mediaEngineLoadSuccess: () { + called = true; + }, + )); + await fakeIrisEngine.fireAndWaitEvent( + tester, 'onMediaEngineLoadSuccess', '{}'); + expect(called, isTrue); + }); + + testWidgets('mediaEngineStartCallSuccess', (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + rtcEngine = await _createRtcEngine(); + bool called = false; + rtcEngine.setEventHandler(RtcEngineEventHandler( + mediaEngineStartCallSuccess: () { + called = true; + }, + )); + await fakeIrisEngine.fireAndWaitEvent( + tester, 'onMediaEngineStartCallSuccess', '{}'); + expect(called, isTrue); + }); + + testWidgets('channelMediaRelayStateChanged', (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + rtcEngine = await _createRtcEngine(); + ChannelMediaRelayState? stateRet; + ChannelMediaRelayError? codeRet; + rtcEngine.setEventHandler(RtcEngineEventHandler( + channelMediaRelayStateChanged: + (ChannelMediaRelayState state, ChannelMediaRelayError code) { + stateRet = state; + codeRet = code; + }, + )); + await fakeIrisEngine.fireAndWaitEvent( + tester, + 'onChannelMediaRelayStateChanged', + '{"state":1,"code":9}', + ); + expect(stateRet, ChannelMediaRelayState.Connecting); + expect(codeRet, ChannelMediaRelayError.InternalError); + }); + + testWidgets('channelMediaRelayEvent', (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + rtcEngine = await _createRtcEngine(); + ChannelMediaRelayEvent? codeRet; + rtcEngine.setEventHandler(RtcEngineEventHandler( + channelMediaRelayEvent: (ChannelMediaRelayEvent code) { + codeRet = code; + }, + )); + await fakeIrisEngine.fireAndWaitEvent( + tester, + 'onChannelMediaRelayEvent', + '{"code":2}', + ); + expect(codeRet, ChannelMediaRelayEvent.JoinedSourceChannel); + }); + + testWidgets('firstRemoteVideoFrame', (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + rtcEngine = await _createRtcEngine(); + int uidRet = 0; + int widthRet = 0; + int heightRet = 0; + int elapsedRet = 0; + rtcEngine.setEventHandler(RtcEngineEventHandler( + firstRemoteVideoFrame: (int uid, int width, int height, int elapsed) { + uidRet = uid; + widthRet = width; + heightRet = height; + elapsedRet = elapsed; + }, + )); + await fakeIrisEngine.fireAndWaitEvent( + tester, + 'onFirstRemoteVideoFrame', + '{"uid":10,"width":100,"height":100,"elapsed":50}', + ); + expect(uidRet, 10); + expect(widthRet, 100); + expect(heightRet, 100); + expect(elapsedRet, 50); + }); + + testWidgets('firstRemoteAudioFrame', (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + rtcEngine = await _createRtcEngine(); + int uidRet = 0; + int elapsedRet = 0; + rtcEngine.setEventHandler(RtcEngineEventHandler( + firstRemoteAudioFrame: (int uid, int elapsed) { + uidRet = uid; + elapsedRet = elapsed; + }, + )); + await fakeIrisEngine.fireAndWaitEvent( + tester, + 'onFirstRemoteAudioFrame', + '{"uid":10,"elapsed":50}', + ); + expect(uidRet, 10); + expect(elapsedRet, 50); + }); + + testWidgets('firstRemoteAudioDecoded', (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + rtcEngine = await _createRtcEngine(); + int uidRet = 0; + int elapsedRet = 0; + rtcEngine.setEventHandler(RtcEngineEventHandler( + firstRemoteAudioDecoded: (int uid, int elapsed) { + uidRet = uid; + elapsedRet = elapsed; + }, + )); + await fakeIrisEngine.fireAndWaitEvent( + tester, + 'onFirstRemoteAudioDecoded', + '{"uid":10,"elapsed":50}', + ); + expect(uidRet, 10); + expect(elapsedRet, 50); + }); + + testWidgets('userMuteAudio', (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + rtcEngine = await _createRtcEngine(); + int uidRet = 0; + bool mutedRet = false; + rtcEngine.setEventHandler(RtcEngineEventHandler( + userMuteAudio: (int uid, bool muted) { + uidRet = uid; + mutedRet = muted; + }, + )); + await fakeIrisEngine.fireAndWaitEvent( + tester, + 'onUserMuteAudio', + '{"uid":10,"muted":true}', + ); + expect(uidRet, 10); + expect(mutedRet, true); + }); + + testWidgets('streamPublished', (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + rtcEngine = await _createRtcEngine(); + String urlRet = ''; + ErrorCode? errorRet; + rtcEngine.setEventHandler(RtcEngineEventHandler( + streamPublished: (String url, ErrorCode error) { + urlRet = url; + errorRet = error; + }, + )); + await fakeIrisEngine.fireAndWaitEvent( + tester, + 'onStreamPublished', + '{"url":"https://example.com","error":1027}', + ); + expect(urlRet, 'https://example.com'); + expect(errorRet, ErrorCode.AdmNoPermission); + }); + + testWidgets('streamUnpublished', (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + rtcEngine = await _createRtcEngine(); + String urlRet = ''; + rtcEngine.setEventHandler(RtcEngineEventHandler( + streamUnpublished: (String url) { + urlRet = url; + }, + )); + await fakeIrisEngine.fireAndWaitEvent( + tester, + 'onStreamUnpublished', + '{"url":"https://example.com"}', + ); + expect(urlRet, 'https://example.com'); + }); + + testWidgets('metadataReceived', (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + rtcEngine = await _createRtcEngine(); + Metadata? metadataRet; + rtcEngine.setEventHandler(RtcEngineEventHandler( + metadataReceived: (Metadata metadata) { + metadataRet = metadata; + }, + )); + final buffer = Uint8List.fromList([1, 1]); + final Metadata expectedMetadata = Metadata(10, 1000); + await fakeIrisEngine.fireAndWaitEvent( + tester, + 'onMetadataReceived', + '{"metadata":${jsonEncode(expectedMetadata.toJson())}}', + buffer: buffer, + bufferSize: 2, + ); + expect(metadataRet!.uid, expectedMetadata.uid); + expect(metadataRet!.timeStampMs, expectedMetadata.timeStampMs); + expect(metadataRet!.buffer, buffer); + }); + + testWidgets('firstLocalAudioFramePublished', (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + rtcEngine = await _createRtcEngine(); + int elapsedRet = 0; + rtcEngine.setEventHandler(RtcEngineEventHandler( + firstLocalAudioFramePublished: (int elapsed) { + elapsedRet = elapsed; + }, + )); + await fakeIrisEngine.fireAndWaitEvent( + tester, + 'onFirstLocalAudioFramePublished', + '{"elapsed":100}', + ); + expect(elapsedRet, 100); + }); + + testWidgets('firstLocalVideoFramePublished', (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + rtcEngine = await _createRtcEngine(); + int elapsedRet = 0; + rtcEngine.setEventHandler(RtcEngineEventHandler( + firstLocalVideoFramePublished: (int elapsed) { + elapsedRet = elapsed; + }, + )); + await fakeIrisEngine.fireAndWaitEvent( + tester, + 'onFirstLocalVideoFramePublished', + '{"elapsed":100}', + ); + expect(elapsedRet, 100); + }); + + testWidgets('audioPublishStateChanged', (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + rtcEngine = await _createRtcEngine(); + String channelRet = ''; + StreamPublishState? oldStateRet; + StreamPublishState? newStateRet; + int elapseSinceLastStateRet = 0; + rtcEngine.setEventHandler(RtcEngineEventHandler( + audioPublishStateChanged: (String channel, StreamPublishState oldState, + StreamPublishState newState, int elapseSinceLastState) { + channelRet = channel; + oldStateRet = oldState; + newStateRet = newState; + elapseSinceLastStateRet = elapseSinceLastState; + }, + )); + await fakeIrisEngine.fireAndWaitEvent( + tester, + 'onAudioPublishStateChanged', + '{"channel":"testapi","oldState":3,"newState":1,"elapseSinceLastState":10}', + ); + expect(channelRet, 'testapi'); + expect(oldStateRet, StreamPublishState.Published); + expect(newStateRet, StreamPublishState.NoPublished); + expect(elapseSinceLastStateRet, 10); + }); + + testWidgets('videoPublishStateChanged', (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + rtcEngine = await _createRtcEngine(); + String channelRet = ''; + StreamPublishState? oldStateRet; + StreamPublishState? newStateRet; + int elapseSinceLastStateRet = 0; + rtcEngine.setEventHandler(RtcEngineEventHandler( + videoPublishStateChanged: (String channel, StreamPublishState oldState, + StreamPublishState newState, int elapseSinceLastState) { + channelRet = channel; + oldStateRet = oldState; + newStateRet = newState; + elapseSinceLastStateRet = elapseSinceLastState; + }, + )); + await fakeIrisEngine.fireAndWaitEvent( + tester, + 'onVideoPublishStateChanged', + '{"channel":"testapi","oldState":3,"newState":1,"elapseSinceLastState":10}', + ); + expect(channelRet, 'testapi'); + expect(oldStateRet, StreamPublishState.Published); + expect(newStateRet, StreamPublishState.NoPublished); + expect(elapseSinceLastStateRet, 10); + }); + + testWidgets('audioSubscribeStateChanged', (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + rtcEngine = await _createRtcEngine(); + String channelRet = ''; + int uidRet = 0; + StreamSubscribeState? oldStateRet; + StreamSubscribeState? newStateRet; + int elapseSinceLastStateRet = 0; + rtcEngine.setEventHandler(RtcEngineEventHandler( + audioSubscribeStateChanged: (String channel, + int uid, + StreamSubscribeState oldState, + StreamSubscribeState newState, + int elapseSinceLastState) { + channelRet = channel; + uidRet = uid; + oldStateRet = oldState; + newStateRet = newState; + elapseSinceLastStateRet = elapseSinceLastState; + }, + )); + await fakeIrisEngine.fireAndWaitEvent( + tester, + 'onAudioSubscribeStateChanged', + '{"channel":"testapi","uid":10,"oldState":1,"newState":2,"elapseSinceLastState":10}', + ); + expect(channelRet, 'testapi'); + expect(uidRet, 10); + expect(oldStateRet, StreamSubscribeState.NoSubscribed); + expect(newStateRet, StreamSubscribeState.Subscribing); + expect(elapseSinceLastStateRet, 10); + }); + + testWidgets('videoSubscribeStateChanged', (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + rtcEngine = await _createRtcEngine(); + String channelRet = ''; + int uidRet = 0; + StreamSubscribeState? oldStateRet; + StreamSubscribeState? newStateRet; + int elapseSinceLastStateRet = 0; + rtcEngine.setEventHandler(RtcEngineEventHandler( + videoSubscribeStateChanged: (String channel, + int uid, + StreamSubscribeState oldState, + StreamSubscribeState newState, + int elapseSinceLastState) { + channelRet = channel; + uidRet = uid; + oldStateRet = oldState; + newStateRet = newState; + elapseSinceLastStateRet = elapseSinceLastState; + }, + )); + await fakeIrisEngine.fireAndWaitEvent( + tester, + 'onVideoSubscribeStateChanged', + '{"channel":"testapi","uid":10,"oldState":1,"newState":2,"elapseSinceLastState":10}', + ); + expect(channelRet, 'testapi'); + expect(uidRet, 10); + expect(oldStateRet, StreamSubscribeState.NoSubscribed); + expect(newStateRet, StreamSubscribeState.Subscribing); + expect(elapseSinceLastStateRet, 10); + }); + + testWidgets('rtmpStreamingEvent', (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + rtcEngine = await _createRtcEngine(); + String urlRet = ''; + RtmpStreamingEvent? eventCodeRet; + rtcEngine.setEventHandler(RtcEngineEventHandler( + rtmpStreamingEvent: (String url, RtmpStreamingEvent eventCode) { + urlRet = url; + eventCodeRet = eventCode; + }, + )); + await fakeIrisEngine.fireAndWaitEvent( + tester, + 'onRtmpStreamingEvent', + '{"url":"https://example.com","eventCode":1}', + ); + expect(urlRet, 'https://example.com'); + expect(eventCodeRet, RtmpStreamingEvent.FailedLoadImage); + }); + + testWidgets('userSuperResolutionEnabled', (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + rtcEngine = await _createRtcEngine(); + int uidRet = 0; + bool enabledRet = false; + SuperResolutionStateReason? reasonRet; + rtcEngine.setEventHandler(RtcEngineEventHandler( + userSuperResolutionEnabled: + (int uid, bool enabled, SuperResolutionStateReason reason) { + uidRet = uid; + enabledRet = enabled; + reasonRet = reason; + }, + )); + await fakeIrisEngine.fireAndWaitEvent( + tester, + 'onUserSuperResolutionEnabled', + '{"uid":10,"enabled":true,"reason":1}', + ); + expect(uidRet, 10); + expect(enabledRet, isTrue); + expect(reasonRet, SuperResolutionStateReason.StreamOverLimitation); + }); + + testWidgets('uploadLogResult', (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + rtcEngine = await _createRtcEngine(); + String requestIdRet = ''; + bool successRet = false; + UploadErrorReason? reasonRet; + rtcEngine.setEventHandler(RtcEngineEventHandler( + uploadLogResult: + (String requestId, bool success, UploadErrorReason reason) { + requestIdRet = requestId; + successRet = success; + reasonRet = reason; + }, + )); + await fakeIrisEngine.fireAndWaitEvent( + tester, + 'onUploadLogResult', + '{"requestId":"10","success":true,"reason":2}', + ); + expect(requestIdRet, '10'); + expect(successRet, isTrue); + expect(reasonRet, UploadErrorReason.ServerError); + }); + + testWidgets('videoDeviceStateChanged', (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + rtcEngine = await _createRtcEngine(); + String deviceIdRet = ''; + MediaDeviceType? deviceTypeRet; + MediaDeviceStateType? deviceStateRet; + rtcEngine.setEventHandler(RtcEngineEventHandler( + videoDeviceStateChanged: (String deviceId, MediaDeviceType deviceType, + MediaDeviceStateType deviceState) { + deviceIdRet = deviceId; + deviceTypeRet = deviceType; + deviceStateRet = deviceState; + }, + )); + await fakeIrisEngine.fireAndWaitEvent( + tester, + 'onVideoDeviceStateChanged', + '{"deviceId":"10","deviceType":4,"deviceState":0}', + ); + expect(deviceIdRet, '10'); + expect(deviceTypeRet, MediaDeviceType.AudioApplicationPlayoutDevice); + expect(deviceStateRet, MediaDeviceStateType.MediaDeviceStateIdle); + }); + + testWidgets('audioDeviceVolumeChanged', (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + rtcEngine = await _createRtcEngine(); + MediaDeviceType? deviceTypeRet; + int volumeRet = 0; + bool mutedRet = false; + rtcEngine.setEventHandler(RtcEngineEventHandler( + audioDeviceVolumeChanged: + (MediaDeviceType deviceType, int volume, bool muted) { + deviceTypeRet = deviceType; + volumeRet = volume; + mutedRet = muted; + }, + )); + await fakeIrisEngine.fireAndWaitEvent( + tester, + 'onAudioDeviceVolumeChanged', + '{"deviceType":3,"volume":20,"muted":true}', + ); + expect(deviceTypeRet, MediaDeviceType.VideoCaptureDevice); + expect(volumeRet, 20); + expect(mutedRet, isTrue); + }); + + testWidgets('audioDeviceStateChanged', (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + rtcEngine = await _createRtcEngine(); + String deviceIdRet = ''; + MediaDeviceType? deviceTypeRet; + MediaDeviceStateType? deviceStateRet; + rtcEngine.setEventHandler(RtcEngineEventHandler( + audioDeviceStateChanged: (String deviceId, MediaDeviceType deviceType, + MediaDeviceStateType deviceState) { + deviceIdRet = deviceId; + deviceTypeRet = deviceType; + deviceStateRet = deviceState; + }, + )); + await fakeIrisEngine.fireAndWaitEvent( + tester, + 'onAudioDeviceStateChanged', + '{"deviceId":"20","deviceType":1,"deviceState":8}', + ); + expect(deviceIdRet, '20'); + expect(deviceTypeRet, MediaDeviceType.AudioRecordingDevice); + expect(deviceStateRet, MediaDeviceStateType.MediaDeviceStateUnplugged); + }); + + testWidgets('remoteAudioMixingBegin', (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + rtcEngine = await _createRtcEngine(); + bool called = false; + rtcEngine.setEventHandler(RtcEngineEventHandler( + remoteAudioMixingBegin: () { + called = true; + }, + )); + await fakeIrisEngine.fireAndWaitEvent( + tester, 'onRemoteAudioMixingBegin', '{}'); + expect(called, true); + }); + + testWidgets('remoteAudioMixingEnd', (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + rtcEngine = await _createRtcEngine(); + bool called = false; + rtcEngine.setEventHandler(RtcEngineEventHandler( + remoteAudioMixingEnd: () { + called = true; + }, + )); + await fakeIrisEngine.fireAndWaitEvent( + tester, 'onRemoteAudioMixingEnd', '{}'); + expect(called, true); + }); + + testEventCall('snapshotTaken', ( + WidgetTester tester, + EventHandlerTester eventHandlerTester, + ) async { + app.main(); + await tester.pumpAndSettle(); + fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + rtcEngine = await _createRtcEngine(); + rtcEngine.setEventHandler(RtcEngineEventHandler( + snapshotTaken: (String channel, int uid, String filePath, int width, + int height, int errCode) { + expectSync(channel, 'testapi'); + expectSync(uid, 10); + expectSync(filePath, '/path'); + expectSync(width, 10); + expectSync(height, 10); + expectSync(errCode, 0); + eventHandlerTester.markEventCalled(); + }, + )); + await fakeIrisEngine.fireAndWaitEvent( + tester, + 'onSnapshotTaken', + '{"channel":"testapi","uid":10,"filePath":"/path","width":10,"height":10,"errCode":0}', + ); + }); +} diff --git a/integration_test_app/integration_test/agora_rtc_engine_event_handler_smoke_test.dart b/integration_test_app/integration_test/agora_rtc_engine_event_handler_smoke_test.dart new file mode 100644 index 000000000..b45803d07 --- /dev/null +++ b/integration_test_app/integration_test/agora_rtc_engine_event_handler_smoke_test.dart @@ -0,0 +1,10 @@ + +import 'package:integration_test/integration_test.dart'; + +import 'agora_rtc_engine_event_handler_smoke_test.generated.dart' as rtc_engine_event; + +void main() { + IntegrationTestWidgetsFlutterBinding.ensureInitialized(); + + rtc_engine_event.rtcEngineEventHandlerSomkeTestCases(); +} diff --git a/integration_test_app/integration_test/agora_rtc_engine_event_handler_smoke_test.generated.dart b/integration_test_app/integration_test/agora_rtc_engine_event_handler_smoke_test.generated.dart new file mode 100644 index 000000000..d25138c44 --- /dev/null +++ b/integration_test_app/integration_test/agora_rtc_engine_event_handler_smoke_test.generated.dart @@ -0,0 +1,2326 @@ +import 'dart:io'; +import 'package:agora_rtc_engine/rtc_engine.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:integration_test_app/main.dart' as app; +import 'package:integration_test_app/src/fake_iris_rtc_engine.dart'; + +void rtcEngineEventHandlerSomkeTestCases() { + testWidgets( + 'onWarning', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + FakeIrisRtcEngine fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + final rtcEngine = await RtcEngine.create('123'); + bool warningCalled = false; + rtcEngine.setEventHandler(RtcEngineEventHandler( + warning: (warn) { + warningCalled = true; + }, + )); + + fakeIrisEngine.fireRtcEngineEvent('onWarning'); +// Wait for the `EventChannel` event be sent from Android/iOS side + await tester.pump(const Duration(milliseconds: 500)); + expect(warningCalled, isTrue); + + rtcEngine.destroy(); + fakeIrisEngine.dispose(); + }, + ); + + testWidgets( + 'onError', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + FakeIrisRtcEngine fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + final rtcEngine = await RtcEngine.create('123'); + bool errorCalled = false; + rtcEngine.setEventHandler(RtcEngineEventHandler( + error: (err) { + errorCalled = true; + }, + )); + + fakeIrisEngine.fireRtcEngineEvent('onError'); +// Wait for the `EventChannel` event be sent from Android/iOS side + await tester.pump(const Duration(milliseconds: 500)); + expect(errorCalled, isTrue); + + rtcEngine.destroy(); + fakeIrisEngine.dispose(); + }, + ); + + testWidgets( + 'onApiCallExecuted', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + FakeIrisRtcEngine fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + final rtcEngine = await RtcEngine.create('123'); + bool apiCallExecutedCalled = false; + rtcEngine.setEventHandler(RtcEngineEventHandler( + apiCallExecuted: (error, api, result) { + apiCallExecutedCalled = true; + }, + )); + + fakeIrisEngine.fireRtcEngineEvent('onApiCallExecuted'); +// Wait for the `EventChannel` event be sent from Android/iOS side + await tester.pump(const Duration(milliseconds: 500)); + expect(apiCallExecutedCalled, isTrue); + + rtcEngine.destroy(); + fakeIrisEngine.dispose(); + }, + ); + + testWidgets( + 'onJoinChannelSuccess', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + FakeIrisRtcEngine fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + final rtcEngine = await RtcEngine.create('123'); + bool joinChannelSuccessCalled = false; + rtcEngine.setEventHandler(RtcEngineEventHandler( + joinChannelSuccess: (channel, uid, elapsed) { + joinChannelSuccessCalled = true; + }, + )); + + fakeIrisEngine.fireRtcEngineEvent('onJoinChannelSuccess'); +// Wait for the `EventChannel` event be sent from Android/iOS side + await tester.pump(const Duration(milliseconds: 500)); + expect(joinChannelSuccessCalled, isTrue); + + rtcEngine.destroy(); + fakeIrisEngine.dispose(); + }, + ); + + testWidgets( + 'onRejoinChannelSuccess', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + FakeIrisRtcEngine fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + final rtcEngine = await RtcEngine.create('123'); + bool rejoinChannelSuccessCalled = false; + rtcEngine.setEventHandler(RtcEngineEventHandler( + rejoinChannelSuccess: (channel, uid, elapsed) { + rejoinChannelSuccessCalled = true; + }, + )); + + fakeIrisEngine.fireRtcEngineEvent('onRejoinChannelSuccess'); +// Wait for the `EventChannel` event be sent from Android/iOS side + await tester.pump(const Duration(milliseconds: 500)); + expect(rejoinChannelSuccessCalled, isTrue); + + rtcEngine.destroy(); + fakeIrisEngine.dispose(); + }, + ); + + testWidgets( + 'onLeaveChannel', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + FakeIrisRtcEngine fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + final rtcEngine = await RtcEngine.create('123'); + bool leaveChannelCalled = false; + rtcEngine.setEventHandler(RtcEngineEventHandler( + leaveChannel: (stats) { + leaveChannelCalled = true; + }, + )); + + fakeIrisEngine.fireRtcEngineEvent('onLeaveChannel'); +// Wait for the `EventChannel` event be sent from Android/iOS side + await tester.pump(const Duration(milliseconds: 500)); + expect(leaveChannelCalled, isTrue); + + rtcEngine.destroy(); + fakeIrisEngine.dispose(); + }, + ); + + testWidgets( + 'onLocalUserRegistered', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + FakeIrisRtcEngine fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + final rtcEngine = await RtcEngine.create('123'); + bool localUserRegisteredCalled = false; + rtcEngine.setEventHandler(RtcEngineEventHandler( + localUserRegistered: (uid, userAccount) { + localUserRegisteredCalled = true; + }, + )); + + fakeIrisEngine.fireRtcEngineEvent('onLocalUserRegistered'); +// Wait for the `EventChannel` event be sent from Android/iOS side + await tester.pump(const Duration(milliseconds: 500)); + expect(localUserRegisteredCalled, isTrue); + + rtcEngine.destroy(); + fakeIrisEngine.dispose(); + }, + ); + + testWidgets( + 'onUserInfoUpdated', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + FakeIrisRtcEngine fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + final rtcEngine = await RtcEngine.create('123'); + bool userInfoUpdatedCalled = false; + rtcEngine.setEventHandler(RtcEngineEventHandler( + userInfoUpdated: (uid, userInfo) { + userInfoUpdatedCalled = true; + }, + )); + + fakeIrisEngine.fireRtcEngineEvent('onUserInfoUpdated'); +// Wait for the `EventChannel` event be sent from Android/iOS side + await tester.pump(const Duration(milliseconds: 500)); + expect(userInfoUpdatedCalled, isTrue); + + rtcEngine.destroy(); + fakeIrisEngine.dispose(); + }, + ); + + testWidgets( + 'onClientRoleChanged', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + FakeIrisRtcEngine fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + final rtcEngine = await RtcEngine.create('123'); + bool clientRoleChangedCalled = false; + rtcEngine.setEventHandler(RtcEngineEventHandler( + clientRoleChanged: (oldRole, newRole) { + clientRoleChangedCalled = true; + }, + )); + + fakeIrisEngine.fireRtcEngineEvent('onClientRoleChanged'); +// Wait for the `EventChannel` event be sent from Android/iOS side + await tester.pump(const Duration(milliseconds: 500)); + expect(clientRoleChangedCalled, isTrue); + + rtcEngine.destroy(); + fakeIrisEngine.dispose(); + }, + ); + + testWidgets( + 'onUserJoined', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + FakeIrisRtcEngine fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + final rtcEngine = await RtcEngine.create('123'); + bool userJoinedCalled = false; + rtcEngine.setEventHandler(RtcEngineEventHandler( + userJoined: (uid, elapsed) { + userJoinedCalled = true; + }, + )); + + fakeIrisEngine.fireRtcEngineEvent('onUserJoined'); +// Wait for the `EventChannel` event be sent from Android/iOS side + await tester.pump(const Duration(milliseconds: 500)); + expect(userJoinedCalled, isTrue); + + rtcEngine.destroy(); + fakeIrisEngine.dispose(); + }, + ); + + testWidgets( + 'onUserOffline', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + FakeIrisRtcEngine fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + final rtcEngine = await RtcEngine.create('123'); + bool userOfflineCalled = false; + rtcEngine.setEventHandler(RtcEngineEventHandler( + userOffline: (uid, reason) { + userOfflineCalled = true; + }, + )); + + fakeIrisEngine.fireRtcEngineEvent('onUserOffline'); +// Wait for the `EventChannel` event be sent from Android/iOS side + await tester.pump(const Duration(milliseconds: 500)); + expect(userOfflineCalled, isTrue); + + rtcEngine.destroy(); + fakeIrisEngine.dispose(); + }, + ); + + testWidgets( + 'onConnectionStateChanged', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + FakeIrisRtcEngine fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + final rtcEngine = await RtcEngine.create('123'); + bool connectionStateChangedCalled = false; + rtcEngine.setEventHandler(RtcEngineEventHandler( + connectionStateChanged: (state, reason) { + connectionStateChangedCalled = true; + }, + )); + + fakeIrisEngine.fireRtcEngineEvent('onConnectionStateChanged'); +// Wait for the `EventChannel` event be sent from Android/iOS side + await tester.pump(const Duration(milliseconds: 500)); + expect(connectionStateChangedCalled, isTrue); + + rtcEngine.destroy(); + fakeIrisEngine.dispose(); + }, + ); + + testWidgets( + 'onNetworkTypeChanged', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + FakeIrisRtcEngine fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + final rtcEngine = await RtcEngine.create('123'); + bool networkTypeChangedCalled = false; + rtcEngine.setEventHandler(RtcEngineEventHandler( + networkTypeChanged: (type) { + networkTypeChangedCalled = true; + }, + )); + + fakeIrisEngine.fireRtcEngineEvent('onNetworkTypeChanged'); +// Wait for the `EventChannel` event be sent from Android/iOS side + await tester.pump(const Duration(milliseconds: 500)); + expect(networkTypeChangedCalled, isTrue); + + rtcEngine.destroy(); + fakeIrisEngine.dispose(); + }, + ); + + testWidgets( + 'onConnectionLost', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + FakeIrisRtcEngine fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + final rtcEngine = await RtcEngine.create('123'); + bool connectionLostCalled = false; + rtcEngine.setEventHandler(RtcEngineEventHandler( + connectionLost: () { + connectionLostCalled = true; + }, + )); + + fakeIrisEngine.fireRtcEngineEvent('onConnectionLost'); +// Wait for the `EventChannel` event be sent from Android/iOS side + await tester.pump(const Duration(milliseconds: 500)); + expect(connectionLostCalled, isTrue); + + rtcEngine.destroy(); + fakeIrisEngine.dispose(); + }, + ); + + testWidgets( + 'onTokenPrivilegeWillExpire', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + FakeIrisRtcEngine fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + final rtcEngine = await RtcEngine.create('123'); + bool tokenPrivilegeWillExpireCalled = false; + rtcEngine.setEventHandler(RtcEngineEventHandler( + tokenPrivilegeWillExpire: (token) { + tokenPrivilegeWillExpireCalled = true; + }, + )); + + fakeIrisEngine.fireRtcEngineEvent('onTokenPrivilegeWillExpire'); +// Wait for the `EventChannel` event be sent from Android/iOS side + await tester.pump(const Duration(milliseconds: 500)); + expect(tokenPrivilegeWillExpireCalled, isTrue); + + rtcEngine.destroy(); + fakeIrisEngine.dispose(); + }, + ); + + testWidgets( + 'onRequestToken', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + FakeIrisRtcEngine fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + final rtcEngine = await RtcEngine.create('123'); + bool requestTokenCalled = false; + rtcEngine.setEventHandler(RtcEngineEventHandler( + requestToken: () { + requestTokenCalled = true; + }, + )); + + fakeIrisEngine.fireRtcEngineEvent('onRequestToken'); +// Wait for the `EventChannel` event be sent from Android/iOS side + await tester.pump(const Duration(milliseconds: 500)); + expect(requestTokenCalled, isTrue); + + rtcEngine.destroy(); + fakeIrisEngine.dispose(); + }, + ); + + testWidgets( + 'onAudioVolumeIndication', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + FakeIrisRtcEngine fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + final rtcEngine = await RtcEngine.create('123'); + bool audioVolumeIndicationCalled = false; + rtcEngine.setEventHandler(RtcEngineEventHandler( + audioVolumeIndication: (speakers, totalVolume) { + audioVolumeIndicationCalled = true; + }, + )); + + fakeIrisEngine.fireRtcEngineEvent('onAudioVolumeIndication'); +// Wait for the `EventChannel` event be sent from Android/iOS side + await tester.pump(const Duration(milliseconds: 500)); + expect(audioVolumeIndicationCalled, isTrue); + + rtcEngine.destroy(); + fakeIrisEngine.dispose(); + }, + ); + + testWidgets( + 'onActiveSpeaker', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + FakeIrisRtcEngine fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + final rtcEngine = await RtcEngine.create('123'); + bool activeSpeakerCalled = false; + rtcEngine.setEventHandler(RtcEngineEventHandler( + activeSpeaker: (uid) { + activeSpeakerCalled = true; + }, + )); + + fakeIrisEngine.fireRtcEngineEvent('onActiveSpeaker'); +// Wait for the `EventChannel` event be sent from Android/iOS side + await tester.pump(const Duration(milliseconds: 500)); + expect(activeSpeakerCalled, isTrue); + + rtcEngine.destroy(); + fakeIrisEngine.dispose(); + }, + ); + + testWidgets( + 'onFirstLocalAudioFrame', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + FakeIrisRtcEngine fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + final rtcEngine = await RtcEngine.create('123'); + bool firstLocalAudioFrameCalled = false; + rtcEngine.setEventHandler(RtcEngineEventHandler( + firstLocalAudioFrame: (elapsed) { + firstLocalAudioFrameCalled = true; + }, + )); + + fakeIrisEngine.fireRtcEngineEvent('onFirstLocalAudioFrame'); +// Wait for the `EventChannel` event be sent from Android/iOS side + await tester.pump(const Duration(milliseconds: 500)); + expect(firstLocalAudioFrameCalled, isTrue); + + rtcEngine.destroy(); + fakeIrisEngine.dispose(); + }, + ); + + testWidgets( + 'onFirstLocalVideoFrame', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + FakeIrisRtcEngine fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + final rtcEngine = await RtcEngine.create('123'); + bool firstLocalVideoFrameCalled = false; + rtcEngine.setEventHandler(RtcEngineEventHandler( + firstLocalVideoFrame: (width, height, elapsed) { + firstLocalVideoFrameCalled = true; + }, + )); + + fakeIrisEngine.fireRtcEngineEvent('onFirstLocalVideoFrame'); +// Wait for the `EventChannel` event be sent from Android/iOS side + await tester.pump(const Duration(milliseconds: 500)); + expect(firstLocalVideoFrameCalled, isTrue); + + rtcEngine.destroy(); + fakeIrisEngine.dispose(); + }, + ); + + testWidgets( + 'onUserMuteVideo', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + FakeIrisRtcEngine fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + final rtcEngine = await RtcEngine.create('123'); + bool userMuteVideoCalled = false; + rtcEngine.setEventHandler(RtcEngineEventHandler( + userMuteVideo: (uid, muted) { + userMuteVideoCalled = true; + }, + )); + + fakeIrisEngine.fireRtcEngineEvent('onUserMuteVideo'); +// Wait for the `EventChannel` event be sent from Android/iOS side + await tester.pump(const Duration(milliseconds: 500)); + expect(userMuteVideoCalled, isTrue); + + rtcEngine.destroy(); + fakeIrisEngine.dispose(); + }, + ); + + testWidgets( + 'onVideoSizeChanged', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + FakeIrisRtcEngine fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + final rtcEngine = await RtcEngine.create('123'); + bool videoSizeChangedCalled = false; + rtcEngine.setEventHandler(RtcEngineEventHandler( + videoSizeChanged: (uid, width, height, rotation) { + videoSizeChangedCalled = true; + }, + )); + + fakeIrisEngine.fireRtcEngineEvent('onVideoSizeChanged'); +// Wait for the `EventChannel` event be sent from Android/iOS side + await tester.pump(const Duration(milliseconds: 500)); + expect(videoSizeChangedCalled, isTrue); + + rtcEngine.destroy(); + fakeIrisEngine.dispose(); + }, + ); + + testWidgets( + 'onRemoteVideoStateChanged', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + FakeIrisRtcEngine fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + final rtcEngine = await RtcEngine.create('123'); + bool remoteVideoStateChangedCalled = false; + rtcEngine.setEventHandler(RtcEngineEventHandler( + remoteVideoStateChanged: (uid, state, reason, elapsed) { + remoteVideoStateChangedCalled = true; + }, + )); + + fakeIrisEngine.fireRtcEngineEvent('onRemoteVideoStateChanged'); +// Wait for the `EventChannel` event be sent from Android/iOS side + await tester.pump(const Duration(milliseconds: 500)); + expect(remoteVideoStateChangedCalled, isTrue); + + rtcEngine.destroy(); + fakeIrisEngine.dispose(); + }, + ); + + testWidgets( + 'onLocalVideoStateChanged', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + FakeIrisRtcEngine fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + final rtcEngine = await RtcEngine.create('123'); + bool localVideoStateChangedCalled = false; + rtcEngine.setEventHandler(RtcEngineEventHandler( + localVideoStateChanged: (localVideoState, error) { + localVideoStateChangedCalled = true; + }, + )); + + fakeIrisEngine.fireRtcEngineEvent('onLocalVideoStateChanged'); +// Wait for the `EventChannel` event be sent from Android/iOS side + await tester.pump(const Duration(milliseconds: 500)); + expect(localVideoStateChangedCalled, isTrue); + + rtcEngine.destroy(); + fakeIrisEngine.dispose(); + }, + ); + + testWidgets( + 'onRemoteAudioStateChanged', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + FakeIrisRtcEngine fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + final rtcEngine = await RtcEngine.create('123'); + bool remoteAudioStateChangedCalled = false; + rtcEngine.setEventHandler(RtcEngineEventHandler( + remoteAudioStateChanged: (uid, state, reason, elapsed) { + remoteAudioStateChangedCalled = true; + }, + )); + + fakeIrisEngine.fireRtcEngineEvent('onRemoteAudioStateChanged'); +// Wait for the `EventChannel` event be sent from Android/iOS side + await tester.pump(const Duration(milliseconds: 500)); + expect(remoteAudioStateChangedCalled, isTrue); + + rtcEngine.destroy(); + fakeIrisEngine.dispose(); + }, + ); + + testWidgets( + 'onLocalAudioStateChanged', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + FakeIrisRtcEngine fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + final rtcEngine = await RtcEngine.create('123'); + bool localAudioStateChangedCalled = false; + rtcEngine.setEventHandler(RtcEngineEventHandler( + localAudioStateChanged: (state, error) { + localAudioStateChangedCalled = true; + }, + )); + + fakeIrisEngine.fireRtcEngineEvent('onLocalAudioStateChanged'); +// Wait for the `EventChannel` event be sent from Android/iOS side + await tester.pump(const Duration(milliseconds: 500)); + expect(localAudioStateChangedCalled, isTrue); + + rtcEngine.destroy(); + fakeIrisEngine.dispose(); + }, + ); + + testWidgets( + 'onRequestAudioFileInfo', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + FakeIrisRtcEngine fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + final rtcEngine = await RtcEngine.create('123'); + bool requestAudioFileInfoCallbackCalled = false; + rtcEngine.setEventHandler(RtcEngineEventHandler( + requestAudioFileInfoCallback: (info, error) { + requestAudioFileInfoCallbackCalled = true; + }, + )); + + fakeIrisEngine.fireRtcEngineEvent('onRequestAudioFileInfo'); +// Wait for the `EventChannel` event be sent from Android/iOS side + await tester.pump(const Duration(milliseconds: 500)); + expect(requestAudioFileInfoCallbackCalled, isTrue); + + rtcEngine.destroy(); + fakeIrisEngine.dispose(); + }, + ); + + testWidgets( + 'onRequestAudioFileInfo', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + FakeIrisRtcEngine fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + final rtcEngine = await RtcEngine.create('123'); + bool requestAudioFileInfoCalled = false; + rtcEngine.setEventHandler(RtcEngineEventHandler( + requestAudioFileInfo: (info, error) { + requestAudioFileInfoCalled = true; + }, + )); + + fakeIrisEngine.fireRtcEngineEvent('onRequestAudioFileInfo'); +// Wait for the `EventChannel` event be sent from Android/iOS side + await tester.pump(const Duration(milliseconds: 500)); + expect(requestAudioFileInfoCalled, isTrue); + + rtcEngine.destroy(); + fakeIrisEngine.dispose(); + }, + ); + + testWidgets( + 'onLocalPublishFallbackToAudioOnly', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + FakeIrisRtcEngine fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + final rtcEngine = await RtcEngine.create('123'); + bool localPublishFallbackToAudioOnlyCalled = false; + rtcEngine.setEventHandler(RtcEngineEventHandler( + localPublishFallbackToAudioOnly: (isFallbackOrRecover) { + localPublishFallbackToAudioOnlyCalled = true; + }, + )); + + fakeIrisEngine.fireRtcEngineEvent('onLocalPublishFallbackToAudioOnly'); +// Wait for the `EventChannel` event be sent from Android/iOS side + await tester.pump(const Duration(milliseconds: 500)); + expect(localPublishFallbackToAudioOnlyCalled, isTrue); + + rtcEngine.destroy(); + fakeIrisEngine.dispose(); + }, + ); + + testWidgets( + 'onRemoteSubscribeFallbackToAudioOnly', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + FakeIrisRtcEngine fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + final rtcEngine = await RtcEngine.create('123'); + bool remoteSubscribeFallbackToAudioOnlyCalled = false; + rtcEngine.setEventHandler(RtcEngineEventHandler( + remoteSubscribeFallbackToAudioOnly: (uid, isFallbackOrRecover) { + remoteSubscribeFallbackToAudioOnlyCalled = true; + }, + )); + + fakeIrisEngine.fireRtcEngineEvent('onRemoteSubscribeFallbackToAudioOnly'); +// Wait for the `EventChannel` event be sent from Android/iOS side + await tester.pump(const Duration(milliseconds: 500)); + expect(remoteSubscribeFallbackToAudioOnlyCalled, isTrue); + + rtcEngine.destroy(); + fakeIrisEngine.dispose(); + }, + ); + + testWidgets( + 'onAudioRouteChanged', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + FakeIrisRtcEngine fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + final rtcEngine = await RtcEngine.create('123'); + bool audioRouteChangedCalled = false; + rtcEngine.setEventHandler(RtcEngineEventHandler( + audioRouteChanged: (routing) { + audioRouteChangedCalled = true; + }, + )); + + fakeIrisEngine.fireRtcEngineEvent('onAudioRouteChanged'); +// Wait for the `EventChannel` event be sent from Android/iOS side + await tester.pump(const Duration(milliseconds: 500)); + expect(audioRouteChangedCalled, isTrue); + + rtcEngine.destroy(); + fakeIrisEngine.dispose(); + }, + ); + + testWidgets( + 'onCameraFocusAreaChanged', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + FakeIrisRtcEngine fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + final rtcEngine = await RtcEngine.create('123'); + bool cameraFocusAreaChangedCalled = false; + rtcEngine.setEventHandler(RtcEngineEventHandler( + cameraFocusAreaChanged: (rect) { + cameraFocusAreaChangedCalled = true; + }, + )); + + fakeIrisEngine.fireRtcEngineEvent('onCameraFocusAreaChanged'); +// Wait for the `EventChannel` event be sent from Android/iOS side + await tester.pump(const Duration(milliseconds: 500)); + expect(cameraFocusAreaChangedCalled, isTrue); + + rtcEngine.destroy(); + fakeIrisEngine.dispose(); + }, + ); + + testWidgets( + 'onCameraExposureAreaChanged', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + FakeIrisRtcEngine fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + final rtcEngine = await RtcEngine.create('123'); + bool cameraExposureAreaChangedCalled = false; + rtcEngine.setEventHandler(RtcEngineEventHandler( + cameraExposureAreaChanged: (rect) { + cameraExposureAreaChangedCalled = true; + }, + )); + + fakeIrisEngine.fireRtcEngineEvent('onCameraExposureAreaChanged'); +// Wait for the `EventChannel` event be sent from Android/iOS side + await tester.pump(const Duration(milliseconds: 500)); + expect(cameraExposureAreaChangedCalled, isTrue); + + rtcEngine.destroy(); + fakeIrisEngine.dispose(); + }, + ); + + testWidgets( + 'onFacePositionChanged', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + FakeIrisRtcEngine fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + final rtcEngine = await RtcEngine.create('123'); + bool facePositionChangedCalled = false; + rtcEngine.setEventHandler(RtcEngineEventHandler( + facePositionChanged: (imageWidth, imageHeight, faces) { + facePositionChangedCalled = true; + }, + )); + + fakeIrisEngine.fireRtcEngineEvent('onFacePositionChanged'); +// Wait for the `EventChannel` event be sent from Android/iOS side + await tester.pump(const Duration(milliseconds: 500)); + expect(facePositionChangedCalled, isTrue); + + rtcEngine.destroy(); + fakeIrisEngine.dispose(); + }, + skip: !(Platform.isAndroid || Platform.isIOS), + ); + + testWidgets( + 'onRtcStats', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + FakeIrisRtcEngine fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + final rtcEngine = await RtcEngine.create('123'); + bool rtcStatsCalled = false; + rtcEngine.setEventHandler(RtcEngineEventHandler( + rtcStats: (stats) { + rtcStatsCalled = true; + }, + )); + + fakeIrisEngine.fireRtcEngineEvent('onRtcStats'); +// Wait for the `EventChannel` event be sent from Android/iOS side + await tester.pump(const Duration(milliseconds: 500)); + expect(rtcStatsCalled, isTrue); + + rtcEngine.destroy(); + fakeIrisEngine.dispose(); + }, + ); + + testWidgets( + 'onLastmileQuality', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + FakeIrisRtcEngine fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + final rtcEngine = await RtcEngine.create('123'); + bool lastmileQualityCalled = false; + rtcEngine.setEventHandler(RtcEngineEventHandler( + lastmileQuality: (quality) { + lastmileQualityCalled = true; + }, + )); + + fakeIrisEngine.fireRtcEngineEvent('onLastmileQuality'); +// Wait for the `EventChannel` event be sent from Android/iOS side + await tester.pump(const Duration(milliseconds: 500)); + expect(lastmileQualityCalled, isTrue); + + rtcEngine.destroy(); + fakeIrisEngine.dispose(); + }, + ); + + testWidgets( + 'onNetworkQuality', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + FakeIrisRtcEngine fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + final rtcEngine = await RtcEngine.create('123'); + bool networkQualityCalled = false; + rtcEngine.setEventHandler(RtcEngineEventHandler( + networkQuality: (uid, txQuality, rxQuality) { + networkQualityCalled = true; + }, + )); + + fakeIrisEngine.fireRtcEngineEvent('onNetworkQuality'); +// Wait for the `EventChannel` event be sent from Android/iOS side + await tester.pump(const Duration(milliseconds: 500)); + expect(networkQualityCalled, isTrue); + + rtcEngine.destroy(); + fakeIrisEngine.dispose(); + }, + ); + + testWidgets( + 'onLastmileProbeResult', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + FakeIrisRtcEngine fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + final rtcEngine = await RtcEngine.create('123'); + bool lastmileProbeResultCalled = false; + rtcEngine.setEventHandler(RtcEngineEventHandler( + lastmileProbeResult: (result) { + lastmileProbeResultCalled = true; + }, + )); + + fakeIrisEngine.fireRtcEngineEvent('onLastmileProbeResult'); +// Wait for the `EventChannel` event be sent from Android/iOS side + await tester.pump(const Duration(milliseconds: 500)); + expect(lastmileProbeResultCalled, isTrue); + + rtcEngine.destroy(); + fakeIrisEngine.dispose(); + }, + ); + + testWidgets( + 'onLocalVideoStats', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + FakeIrisRtcEngine fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + final rtcEngine = await RtcEngine.create('123'); + bool localVideoStatsCalled = false; + rtcEngine.setEventHandler(RtcEngineEventHandler( + localVideoStats: (stats) { + localVideoStatsCalled = true; + }, + )); + + fakeIrisEngine.fireRtcEngineEvent('onLocalVideoStats'); +// Wait for the `EventChannel` event be sent from Android/iOS side + await tester.pump(const Duration(milliseconds: 500)); + expect(localVideoStatsCalled, isTrue); + + rtcEngine.destroy(); + fakeIrisEngine.dispose(); + }, + ); + + testWidgets( + 'onLocalAudioStats', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + FakeIrisRtcEngine fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + final rtcEngine = await RtcEngine.create('123'); + bool localAudioStatsCalled = false; + rtcEngine.setEventHandler(RtcEngineEventHandler( + localAudioStats: (stats) { + localAudioStatsCalled = true; + }, + )); + + fakeIrisEngine.fireRtcEngineEvent('onLocalAudioStats'); +// Wait for the `EventChannel` event be sent from Android/iOS side + await tester.pump(const Duration(milliseconds: 500)); + expect(localAudioStatsCalled, isTrue); + + rtcEngine.destroy(); + fakeIrisEngine.dispose(); + }, + ); + + testWidgets( + 'onRemoteVideoStats', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + FakeIrisRtcEngine fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + final rtcEngine = await RtcEngine.create('123'); + bool remoteVideoStatsCalled = false; + rtcEngine.setEventHandler(RtcEngineEventHandler( + remoteVideoStats: (stats) { + remoteVideoStatsCalled = true; + }, + )); + + fakeIrisEngine.fireRtcEngineEvent('onRemoteVideoStats'); +// Wait for the `EventChannel` event be sent from Android/iOS side + await tester.pump(const Duration(milliseconds: 500)); + expect(remoteVideoStatsCalled, isTrue); + + rtcEngine.destroy(); + fakeIrisEngine.dispose(); + }, + ); + + testWidgets( + 'onRemoteAudioStats', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + FakeIrisRtcEngine fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + final rtcEngine = await RtcEngine.create('123'); + bool remoteAudioStatsCalled = false; + rtcEngine.setEventHandler(RtcEngineEventHandler( + remoteAudioStats: (stats) { + remoteAudioStatsCalled = true; + }, + )); + + fakeIrisEngine.fireRtcEngineEvent('onRemoteAudioStats'); +// Wait for the `EventChannel` event be sent from Android/iOS side + await tester.pump(const Duration(milliseconds: 500)); + expect(remoteAudioStatsCalled, isTrue); + + rtcEngine.destroy(); + fakeIrisEngine.dispose(); + }, + ); + + testWidgets( + 'onAudioMixingFinished', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + FakeIrisRtcEngine fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + final rtcEngine = await RtcEngine.create('123'); + bool audioMixingFinishedCalled = false; + rtcEngine.setEventHandler(RtcEngineEventHandler( + audioMixingFinished: () { + audioMixingFinishedCalled = true; + }, + )); + + fakeIrisEngine.fireRtcEngineEvent('onAudioMixingFinished'); +// Wait for the `EventChannel` event be sent from Android/iOS side + await tester.pump(const Duration(milliseconds: 500)); + expect(audioMixingFinishedCalled, isTrue); + + rtcEngine.destroy(); + fakeIrisEngine.dispose(); + }, + ); + + testWidgets( + 'onAudioMixingStateChanged', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + FakeIrisRtcEngine fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + final rtcEngine = await RtcEngine.create('123'); + bool audioMixingStateChangedCalled = false; + rtcEngine.setEventHandler(RtcEngineEventHandler( + audioMixingStateChanged: (state, reason) { + audioMixingStateChangedCalled = true; + }, + )); + + fakeIrisEngine.fireRtcEngineEvent('onAudioMixingStateChanged'); +// Wait for the `EventChannel` event be sent from Android/iOS side + await tester.pump(const Duration(milliseconds: 500)); + expect(audioMixingStateChangedCalled, isTrue); + + rtcEngine.destroy(); + fakeIrisEngine.dispose(); + }, + ); + + testWidgets( + 'onAudioEffectFinished', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + FakeIrisRtcEngine fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + final rtcEngine = await RtcEngine.create('123'); + bool audioEffectFinishedCalled = false; + rtcEngine.setEventHandler(RtcEngineEventHandler( + audioEffectFinished: (soundId) { + audioEffectFinishedCalled = true; + }, + )); + + fakeIrisEngine.fireRtcEngineEvent('onAudioEffectFinished'); +// Wait for the `EventChannel` event be sent from Android/iOS side + await tester.pump(const Duration(milliseconds: 500)); + expect(audioEffectFinishedCalled, isTrue); + + rtcEngine.destroy(); + fakeIrisEngine.dispose(); + }, + ); + + testWidgets( + 'onRtmpStreamingStateChanged', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + FakeIrisRtcEngine fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + final rtcEngine = await RtcEngine.create('123'); + bool rtmpStreamingStateChangedCalled = false; + rtcEngine.setEventHandler(RtcEngineEventHandler( + rtmpStreamingStateChanged: (url, state, errCode) { + rtmpStreamingStateChangedCalled = true; + }, + )); + + fakeIrisEngine.fireRtcEngineEvent('onRtmpStreamingStateChanged'); +// Wait for the `EventChannel` event be sent from Android/iOS side + await tester.pump(const Duration(milliseconds: 500)); + expect(rtmpStreamingStateChangedCalled, isTrue); + + rtcEngine.destroy(); + fakeIrisEngine.dispose(); + }, + ); + + testWidgets( + 'onTranscodingUpdated', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + FakeIrisRtcEngine fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + final rtcEngine = await RtcEngine.create('123'); + bool transcodingUpdatedCalled = false; + rtcEngine.setEventHandler(RtcEngineEventHandler( + transcodingUpdated: () { + transcodingUpdatedCalled = true; + }, + )); + + fakeIrisEngine.fireRtcEngineEvent('onTranscodingUpdated'); +// Wait for the `EventChannel` event be sent from Android/iOS side + await tester.pump(const Duration(milliseconds: 500)); + expect(transcodingUpdatedCalled, isTrue); + + rtcEngine.destroy(); + fakeIrisEngine.dispose(); + }, + ); + + testWidgets( + 'onStreamInjectedStatus', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + FakeIrisRtcEngine fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + final rtcEngine = await RtcEngine.create('123'); + bool streamInjectedStatusCalled = false; + rtcEngine.setEventHandler(RtcEngineEventHandler( + streamInjectedStatus: (url, uid, status) { + streamInjectedStatusCalled = true; + }, + )); + + fakeIrisEngine.fireRtcEngineEvent('onStreamInjectedStatus'); +// Wait for the `EventChannel` event be sent from Android/iOS side + await tester.pump(const Duration(milliseconds: 500)); + expect(streamInjectedStatusCalled, isTrue); + + rtcEngine.destroy(); + fakeIrisEngine.dispose(); + }, + ); + + testWidgets( + 'onStreamMessage', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + FakeIrisRtcEngine fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + final rtcEngine = await RtcEngine.create('123'); + bool streamMessageCalled = false; + rtcEngine.setEventHandler(RtcEngineEventHandler( + streamMessage: (uid, streamId, data) { + streamMessageCalled = true; + }, + )); + + fakeIrisEngine.fireRtcEngineEvent('onStreamMessage'); +// Wait for the `EventChannel` event be sent from Android/iOS side + await tester.pump(const Duration(milliseconds: 500)); + expect(streamMessageCalled, isTrue); + + rtcEngine.destroy(); + fakeIrisEngine.dispose(); + }, + ); + + testWidgets( + 'onStreamMessageError', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + FakeIrisRtcEngine fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + final rtcEngine = await RtcEngine.create('123'); + bool streamMessageErrorCalled = false; + rtcEngine.setEventHandler(RtcEngineEventHandler( + streamMessageError: (uid, streamId, error, missed, cached) { + streamMessageErrorCalled = true; + }, + )); + + fakeIrisEngine.fireRtcEngineEvent('onStreamMessageError'); +// Wait for the `EventChannel` event be sent from Android/iOS side + await tester.pump(const Duration(milliseconds: 500)); + expect(streamMessageErrorCalled, isTrue); + + rtcEngine.destroy(); + fakeIrisEngine.dispose(); + }, + ); + + testWidgets( + 'onMediaEngineLoadSuccess', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + FakeIrisRtcEngine fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + final rtcEngine = await RtcEngine.create('123'); + bool mediaEngineLoadSuccessCalled = false; + rtcEngine.setEventHandler(RtcEngineEventHandler( + mediaEngineLoadSuccess: () { + mediaEngineLoadSuccessCalled = true; + }, + )); + + fakeIrisEngine.fireRtcEngineEvent('onMediaEngineLoadSuccess'); +// Wait for the `EventChannel` event be sent from Android/iOS side + await tester.pump(const Duration(milliseconds: 500)); + expect(mediaEngineLoadSuccessCalled, isTrue); + + rtcEngine.destroy(); + fakeIrisEngine.dispose(); + }, + ); + + testWidgets( + 'onMediaEngineStartCallSuccess', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + FakeIrisRtcEngine fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + final rtcEngine = await RtcEngine.create('123'); + bool mediaEngineStartCallSuccessCalled = false; + rtcEngine.setEventHandler(RtcEngineEventHandler( + mediaEngineStartCallSuccess: () { + mediaEngineStartCallSuccessCalled = true; + }, + )); + + fakeIrisEngine.fireRtcEngineEvent('onMediaEngineStartCallSuccess'); +// Wait for the `EventChannel` event be sent from Android/iOS side + await tester.pump(const Duration(milliseconds: 500)); + expect(mediaEngineStartCallSuccessCalled, isTrue); + + rtcEngine.destroy(); + fakeIrisEngine.dispose(); + }, + ); + + testWidgets( + 'onChannelMediaRelayStateChanged', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + FakeIrisRtcEngine fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + final rtcEngine = await RtcEngine.create('123'); + bool channelMediaRelayStateChangedCalled = false; + rtcEngine.setEventHandler(RtcEngineEventHandler( + channelMediaRelayStateChanged: (state, code) { + channelMediaRelayStateChangedCalled = true; + }, + )); + + fakeIrisEngine.fireRtcEngineEvent('onChannelMediaRelayStateChanged'); +// Wait for the `EventChannel` event be sent from Android/iOS side + await tester.pump(const Duration(milliseconds: 500)); + expect(channelMediaRelayStateChangedCalled, isTrue); + + rtcEngine.destroy(); + fakeIrisEngine.dispose(); + }, + ); + + testWidgets( + 'onChannelMediaRelayEvent', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + FakeIrisRtcEngine fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + final rtcEngine = await RtcEngine.create('123'); + bool channelMediaRelayEventCalled = false; + rtcEngine.setEventHandler(RtcEngineEventHandler( + channelMediaRelayEvent: (code) { + channelMediaRelayEventCalled = true; + }, + )); + + fakeIrisEngine.fireRtcEngineEvent('onChannelMediaRelayEvent'); +// Wait for the `EventChannel` event be sent from Android/iOS side + await tester.pump(const Duration(milliseconds: 500)); + expect(channelMediaRelayEventCalled, isTrue); + + rtcEngine.destroy(); + fakeIrisEngine.dispose(); + }, + ); + + testWidgets( + 'onFirstRemoteVideoFrame', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + FakeIrisRtcEngine fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + final rtcEngine = await RtcEngine.create('123'); + bool firstRemoteVideoFrameCalled = false; + rtcEngine.setEventHandler(RtcEngineEventHandler( + firstRemoteVideoFrame: (uid, width, height, elapsed) { + firstRemoteVideoFrameCalled = true; + }, + )); + + fakeIrisEngine.fireRtcEngineEvent('onFirstRemoteVideoFrame'); +// Wait for the `EventChannel` event be sent from Android/iOS side + await tester.pump(const Duration(milliseconds: 500)); + expect(firstRemoteVideoFrameCalled, isTrue); + + rtcEngine.destroy(); + fakeIrisEngine.dispose(); + }, + ); + + testWidgets( + 'onFirstRemoteAudioFrame', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + FakeIrisRtcEngine fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + final rtcEngine = await RtcEngine.create('123'); + bool firstRemoteAudioFrameCalled = false; + rtcEngine.setEventHandler(RtcEngineEventHandler( + firstRemoteAudioFrame: (uid, elapsed) { + firstRemoteAudioFrameCalled = true; + }, + )); + + fakeIrisEngine.fireRtcEngineEvent('onFirstRemoteAudioFrame'); +// Wait for the `EventChannel` event be sent from Android/iOS side + await tester.pump(const Duration(milliseconds: 500)); + expect(firstRemoteAudioFrameCalled, isTrue); + + rtcEngine.destroy(); + fakeIrisEngine.dispose(); + }, + ); + + testWidgets( + 'onFirstRemoteAudioDecoded', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + FakeIrisRtcEngine fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + final rtcEngine = await RtcEngine.create('123'); + bool firstRemoteAudioDecodedCalled = false; + rtcEngine.setEventHandler(RtcEngineEventHandler( + firstRemoteAudioDecoded: (uid, elapsed) { + firstRemoteAudioDecodedCalled = true; + }, + )); + + fakeIrisEngine.fireRtcEngineEvent('onFirstRemoteAudioDecoded'); +// Wait for the `EventChannel` event be sent from Android/iOS side + await tester.pump(const Duration(milliseconds: 500)); + expect(firstRemoteAudioDecodedCalled, isTrue); + + rtcEngine.destroy(); + fakeIrisEngine.dispose(); + }, + ); + + testWidgets( + 'onUserMuteAudio', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + FakeIrisRtcEngine fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + final rtcEngine = await RtcEngine.create('123'); + bool userMuteAudioCalled = false; + rtcEngine.setEventHandler(RtcEngineEventHandler( + userMuteAudio: (uid, muted) { + userMuteAudioCalled = true; + }, + )); + + fakeIrisEngine.fireRtcEngineEvent('onUserMuteAudio'); +// Wait for the `EventChannel` event be sent from Android/iOS side + await tester.pump(const Duration(milliseconds: 500)); + expect(userMuteAudioCalled, isTrue); + + rtcEngine.destroy(); + fakeIrisEngine.dispose(); + }, + ); + + testWidgets( + 'onStreamPublished', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + FakeIrisRtcEngine fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + final rtcEngine = await RtcEngine.create('123'); + bool streamPublishedCalled = false; + rtcEngine.setEventHandler(RtcEngineEventHandler( + streamPublished: (url, error) { + streamPublishedCalled = true; + }, + )); + + fakeIrisEngine.fireRtcEngineEvent('onStreamPublished'); +// Wait for the `EventChannel` event be sent from Android/iOS side + await tester.pump(const Duration(milliseconds: 500)); + expect(streamPublishedCalled, isTrue); + + rtcEngine.destroy(); + fakeIrisEngine.dispose(); + }, + ); + + testWidgets( + 'onStreamUnpublished', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + FakeIrisRtcEngine fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + final rtcEngine = await RtcEngine.create('123'); + bool streamUnpublishedCalled = false; + rtcEngine.setEventHandler(RtcEngineEventHandler( + streamUnpublished: (url) { + streamUnpublishedCalled = true; + }, + )); + + fakeIrisEngine.fireRtcEngineEvent('onStreamUnpublished'); +// Wait for the `EventChannel` event be sent from Android/iOS side + await tester.pump(const Duration(milliseconds: 500)); + expect(streamUnpublishedCalled, isTrue); + + rtcEngine.destroy(); + fakeIrisEngine.dispose(); + }, + ); + + testWidgets( + 'onRemoteAudioTransportStats', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + FakeIrisRtcEngine fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + final rtcEngine = await RtcEngine.create('123'); + bool remoteAudioTransportStatsCalled = false; + rtcEngine.setEventHandler(RtcEngineEventHandler( + remoteAudioTransportStats: (uid, delay, lost, rxKBitRate) { + remoteAudioTransportStatsCalled = true; + }, + )); + + fakeIrisEngine.fireRtcEngineEvent('onRemoteAudioTransportStats'); +// Wait for the `EventChannel` event be sent from Android/iOS side + await tester.pump(const Duration(milliseconds: 500)); + expect(remoteAudioTransportStatsCalled, isTrue); + + rtcEngine.destroy(); + fakeIrisEngine.dispose(); + }, + ); + + testWidgets( + 'onRemoteVideoTransportStats', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + FakeIrisRtcEngine fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + final rtcEngine = await RtcEngine.create('123'); + bool remoteVideoTransportStatsCalled = false; + rtcEngine.setEventHandler(RtcEngineEventHandler( + remoteVideoTransportStats: (uid, delay, lost, rxKBitRate) { + remoteVideoTransportStatsCalled = true; + }, + )); + + fakeIrisEngine.fireRtcEngineEvent('onRemoteVideoTransportStats'); +// Wait for the `EventChannel` event be sent from Android/iOS side + await tester.pump(const Duration(milliseconds: 500)); + expect(remoteVideoTransportStatsCalled, isTrue); + + rtcEngine.destroy(); + fakeIrisEngine.dispose(); + }, + ); + + testWidgets( + 'onUserEnableVideo', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + FakeIrisRtcEngine fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + final rtcEngine = await RtcEngine.create('123'); + bool userEnableVideoCalled = false; + rtcEngine.setEventHandler(RtcEngineEventHandler( + userEnableVideo: (uid, enabled) { + userEnableVideoCalled = true; + }, + )); + + fakeIrisEngine.fireRtcEngineEvent('onUserEnableVideo'); +// Wait for the `EventChannel` event be sent from Android/iOS side + await tester.pump(const Duration(milliseconds: 500)); + expect(userEnableVideoCalled, isTrue); + + rtcEngine.destroy(); + fakeIrisEngine.dispose(); + }, + ); + + testWidgets( + 'onUserEnableLocalVideo', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + FakeIrisRtcEngine fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + final rtcEngine = await RtcEngine.create('123'); + bool userEnableLocalVideoCalled = false; + rtcEngine.setEventHandler(RtcEngineEventHandler( + userEnableLocalVideo: (uid, enabled) { + userEnableLocalVideoCalled = true; + }, + )); + + fakeIrisEngine.fireRtcEngineEvent('onUserEnableLocalVideo'); +// Wait for the `EventChannel` event be sent from Android/iOS side + await tester.pump(const Duration(milliseconds: 500)); + expect(userEnableLocalVideoCalled, isTrue); + + rtcEngine.destroy(); + fakeIrisEngine.dispose(); + }, + ); + + testWidgets( + 'onFirstRemoteVideoDecoded', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + FakeIrisRtcEngine fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + final rtcEngine = await RtcEngine.create('123'); + bool firstRemoteVideoDecodedCalled = false; + rtcEngine.setEventHandler(RtcEngineEventHandler( + firstRemoteVideoDecoded: (uid, width, height, elapsed) { + firstRemoteVideoDecodedCalled = true; + }, + )); + + fakeIrisEngine.fireRtcEngineEvent('onFirstRemoteVideoDecoded'); +// Wait for the `EventChannel` event be sent from Android/iOS side + await tester.pump(const Duration(milliseconds: 500)); + expect(firstRemoteVideoDecodedCalled, isTrue); + + rtcEngine.destroy(); + fakeIrisEngine.dispose(); + }, + ); + + testWidgets( + 'onMicrophoneEnabled', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + FakeIrisRtcEngine fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + final rtcEngine = await RtcEngine.create('123'); + bool microphoneEnabledCalled = false; + rtcEngine.setEventHandler(RtcEngineEventHandler( + microphoneEnabled: (enabled) { + microphoneEnabledCalled = true; + }, + )); + + fakeIrisEngine.fireRtcEngineEvent('onMicrophoneEnabled'); +// Wait for the `EventChannel` event be sent from Android/iOS side + await tester.pump(const Duration(milliseconds: 500)); + expect(microphoneEnabledCalled, isTrue); + + rtcEngine.destroy(); + fakeIrisEngine.dispose(); + }, + ); + + testWidgets( + 'onConnectionInterrupted', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + FakeIrisRtcEngine fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + final rtcEngine = await RtcEngine.create('123'); + bool connectionInterruptedCalled = false; + rtcEngine.setEventHandler(RtcEngineEventHandler( + connectionInterrupted: () { + connectionInterruptedCalled = true; + }, + )); + + fakeIrisEngine.fireRtcEngineEvent('onConnectionInterrupted'); +// Wait for the `EventChannel` event be sent from Android/iOS side + await tester.pump(const Duration(milliseconds: 500)); + expect(connectionInterruptedCalled, isTrue); + + rtcEngine.destroy(); + fakeIrisEngine.dispose(); + }, + ); + + testWidgets( + 'onConnectionBanned', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + FakeIrisRtcEngine fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + final rtcEngine = await RtcEngine.create('123'); + bool connectionBannedCalled = false; + rtcEngine.setEventHandler(RtcEngineEventHandler( + connectionBanned: () { + connectionBannedCalled = true; + }, + )); + + fakeIrisEngine.fireRtcEngineEvent('onConnectionBanned'); +// Wait for the `EventChannel` event be sent from Android/iOS side + await tester.pump(const Duration(milliseconds: 500)); + expect(connectionBannedCalled, isTrue); + + rtcEngine.destroy(); + fakeIrisEngine.dispose(); + }, + ); + + testWidgets( + 'onAudioQuality', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + FakeIrisRtcEngine fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + final rtcEngine = await RtcEngine.create('123'); + bool audioQualityCalled = false; + rtcEngine.setEventHandler(RtcEngineEventHandler( + audioQuality: (uid, quality, delay, lost) { + audioQualityCalled = true; + }, + )); + + fakeIrisEngine.fireRtcEngineEvent('onAudioQuality'); +// Wait for the `EventChannel` event be sent from Android/iOS side + await tester.pump(const Duration(milliseconds: 500)); + expect(audioQualityCalled, isTrue); + + rtcEngine.destroy(); + fakeIrisEngine.dispose(); + }, + ); + + testWidgets( + 'onCameraReady', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + FakeIrisRtcEngine fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + final rtcEngine = await RtcEngine.create('123'); + bool cameraReadyCalled = false; + rtcEngine.setEventHandler(RtcEngineEventHandler( + cameraReady: () { + cameraReadyCalled = true; + }, + )); + + fakeIrisEngine.fireRtcEngineEvent('onCameraReady'); +// Wait for the `EventChannel` event be sent from Android/iOS side + await tester.pump(const Duration(milliseconds: 500)); + expect(cameraReadyCalled, isTrue); + + rtcEngine.destroy(); + fakeIrisEngine.dispose(); + }, + ); + + testWidgets( + 'onVideoStopped', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + FakeIrisRtcEngine fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + final rtcEngine = await RtcEngine.create('123'); + bool videoStoppedCalled = false; + rtcEngine.setEventHandler(RtcEngineEventHandler( + videoStopped: () { + videoStoppedCalled = true; + }, + )); + + fakeIrisEngine.fireRtcEngineEvent('onVideoStopped'); +// Wait for the `EventChannel` event be sent from Android/iOS side + await tester.pump(const Duration(milliseconds: 500)); + expect(videoStoppedCalled, isTrue); + + rtcEngine.destroy(); + fakeIrisEngine.dispose(); + }, + ); + + testWidgets( + 'onFirstLocalAudioFramePublished', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + FakeIrisRtcEngine fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + final rtcEngine = await RtcEngine.create('123'); + bool firstLocalAudioFramePublishedCalled = false; + rtcEngine.setEventHandler(RtcEngineEventHandler( + firstLocalAudioFramePublished: (elapsed) { + firstLocalAudioFramePublishedCalled = true; + }, + )); + + fakeIrisEngine.fireRtcEngineEvent('onFirstLocalAudioFramePublished'); +// Wait for the `EventChannel` event be sent from Android/iOS side + await tester.pump(const Duration(milliseconds: 500)); + expect(firstLocalAudioFramePublishedCalled, isTrue); + + rtcEngine.destroy(); + fakeIrisEngine.dispose(); + }, + ); + + testWidgets( + 'onFirstLocalVideoFramePublished', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + FakeIrisRtcEngine fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + final rtcEngine = await RtcEngine.create('123'); + bool firstLocalVideoFramePublishedCalled = false; + rtcEngine.setEventHandler(RtcEngineEventHandler( + firstLocalVideoFramePublished: (elapsed) { + firstLocalVideoFramePublishedCalled = true; + }, + )); + + fakeIrisEngine.fireRtcEngineEvent('onFirstLocalVideoFramePublished'); +// Wait for the `EventChannel` event be sent from Android/iOS side + await tester.pump(const Duration(milliseconds: 500)); + expect(firstLocalVideoFramePublishedCalled, isTrue); + + rtcEngine.destroy(); + fakeIrisEngine.dispose(); + }, + ); + + testWidgets( + 'onAudioPublishStateChanged', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + FakeIrisRtcEngine fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + final rtcEngine = await RtcEngine.create('123'); + bool audioPublishStateChangedCalled = false; + rtcEngine.setEventHandler(RtcEngineEventHandler( + audioPublishStateChanged: + (channel, oldState, newState, elapseSinceLastState) { + audioPublishStateChangedCalled = true; + }, + )); + + fakeIrisEngine.fireRtcEngineEvent('onAudioPublishStateChanged'); +// Wait for the `EventChannel` event be sent from Android/iOS side + await tester.pump(const Duration(milliseconds: 500)); + expect(audioPublishStateChangedCalled, isTrue); + + rtcEngine.destroy(); + fakeIrisEngine.dispose(); + }, + ); + + testWidgets( + 'onVideoPublishStateChanged', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + FakeIrisRtcEngine fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + final rtcEngine = await RtcEngine.create('123'); + bool videoPublishStateChangedCalled = false; + rtcEngine.setEventHandler(RtcEngineEventHandler( + videoPublishStateChanged: + (channel, oldState, newState, elapseSinceLastState) { + videoPublishStateChangedCalled = true; + }, + )); + + fakeIrisEngine.fireRtcEngineEvent('onVideoPublishStateChanged'); +// Wait for the `EventChannel` event be sent from Android/iOS side + await tester.pump(const Duration(milliseconds: 500)); + expect(videoPublishStateChangedCalled, isTrue); + + rtcEngine.destroy(); + fakeIrisEngine.dispose(); + }, + ); + + testWidgets( + 'onAudioSubscribeStateChanged', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + FakeIrisRtcEngine fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + final rtcEngine = await RtcEngine.create('123'); + bool audioSubscribeStateChangedCalled = false; + rtcEngine.setEventHandler(RtcEngineEventHandler( + audioSubscribeStateChanged: + (channel, uid, oldState, newState, elapseSinceLastState) { + audioSubscribeStateChangedCalled = true; + }, + )); + + fakeIrisEngine.fireRtcEngineEvent('onAudioSubscribeStateChanged'); +// Wait for the `EventChannel` event be sent from Android/iOS side + await tester.pump(const Duration(milliseconds: 500)); + expect(audioSubscribeStateChangedCalled, isTrue); + + rtcEngine.destroy(); + fakeIrisEngine.dispose(); + }, + ); + + testWidgets( + 'onVideoSubscribeStateChanged', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + FakeIrisRtcEngine fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + final rtcEngine = await RtcEngine.create('123'); + bool videoSubscribeStateChangedCalled = false; + rtcEngine.setEventHandler(RtcEngineEventHandler( + videoSubscribeStateChanged: + (channel, uid, oldState, newState, elapseSinceLastState) { + videoSubscribeStateChangedCalled = true; + }, + )); + + fakeIrisEngine.fireRtcEngineEvent('onVideoSubscribeStateChanged'); +// Wait for the `EventChannel` event be sent from Android/iOS side + await tester.pump(const Duration(milliseconds: 500)); + expect(videoSubscribeStateChangedCalled, isTrue); + + rtcEngine.destroy(); + fakeIrisEngine.dispose(); + }, + ); + + testWidgets( + 'onRtmpStreamingEvent', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + FakeIrisRtcEngine fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + final rtcEngine = await RtcEngine.create('123'); + bool rtmpStreamingEventCalled = false; + rtcEngine.setEventHandler(RtcEngineEventHandler( + rtmpStreamingEvent: (url, eventCode) { + rtmpStreamingEventCalled = true; + }, + )); + + fakeIrisEngine.fireRtcEngineEvent('onRtmpStreamingEvent'); +// Wait for the `EventChannel` event be sent from Android/iOS side + await tester.pump(const Duration(milliseconds: 500)); + expect(rtmpStreamingEventCalled, isTrue); + + rtcEngine.destroy(); + fakeIrisEngine.dispose(); + }, + ); + + testWidgets( + 'onUserSuperResolutionEnabled', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + FakeIrisRtcEngine fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + final rtcEngine = await RtcEngine.create('123'); + bool userSuperResolutionEnabledCalled = false; + rtcEngine.setEventHandler(RtcEngineEventHandler( + userSuperResolutionEnabled: (uid, enabled, reason) { + userSuperResolutionEnabledCalled = true; + }, + )); + + fakeIrisEngine.fireRtcEngineEvent('onUserSuperResolutionEnabled'); +// Wait for the `EventChannel` event be sent from Android/iOS side + await tester.pump(const Duration(milliseconds: 500)); + expect(userSuperResolutionEnabledCalled, isTrue); + + rtcEngine.destroy(); + fakeIrisEngine.dispose(); + }, + ); + + testWidgets( + 'onUploadLogResult', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + FakeIrisRtcEngine fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + final rtcEngine = await RtcEngine.create('123'); + bool uploadLogResultCalled = false; + rtcEngine.setEventHandler(RtcEngineEventHandler( + uploadLogResult: (requestId, success, reason) { + uploadLogResultCalled = true; + }, + )); + + fakeIrisEngine.fireRtcEngineEvent('onUploadLogResult'); +// Wait for the `EventChannel` event be sent from Android/iOS side + await tester.pump(const Duration(milliseconds: 500)); + expect(uploadLogResultCalled, isTrue); + + rtcEngine.destroy(); + fakeIrisEngine.dispose(); + }, + ); + + testWidgets( + 'onAirPlayConnected', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + FakeIrisRtcEngine fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + final rtcEngine = await RtcEngine.create('123'); + bool airPlayIsConnectedCalled = false; + rtcEngine.setEventHandler(RtcEngineEventHandler( + airPlayIsConnected: () { + airPlayIsConnectedCalled = true; + }, + )); + + fakeIrisEngine.fireRtcEngineEvent('onAirPlayConnected'); +// Wait for the `EventChannel` event be sent from Android/iOS side + await tester.pump(const Duration(milliseconds: 500)); + expect(airPlayIsConnectedCalled, isTrue); + + rtcEngine.destroy(); + fakeIrisEngine.dispose(); + }, + ); + + testWidgets( + 'onAirPlayConnected', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + FakeIrisRtcEngine fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + final rtcEngine = await RtcEngine.create('123'); + bool airPlayConnectedCalled = false; + rtcEngine.setEventHandler(RtcEngineEventHandler( + airPlayConnected: () { + airPlayConnectedCalled = true; + }, + )); + + fakeIrisEngine.fireRtcEngineEvent('onAirPlayConnected'); +// Wait for the `EventChannel` event be sent from Android/iOS side + await tester.pump(const Duration(milliseconds: 500)); + expect(airPlayConnectedCalled, isTrue); + + rtcEngine.destroy(); + fakeIrisEngine.dispose(); + }, + ); + + testWidgets( + 'onVirtualBackgroundSourceEnabled', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + FakeIrisRtcEngine fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + final rtcEngine = await RtcEngine.create('123'); + bool virtualBackgroundSourceEnabledCalled = false; + rtcEngine.setEventHandler(RtcEngineEventHandler( + virtualBackgroundSourceEnabled: (enabled, reason) { + virtualBackgroundSourceEnabledCalled = true; + }, + )); + + fakeIrisEngine.fireRtcEngineEvent('onVirtualBackgroundSourceEnabled'); +// Wait for the `EventChannel` event be sent from Android/iOS side + await tester.pump(const Duration(milliseconds: 500)); + expect(virtualBackgroundSourceEnabledCalled, isTrue); + + rtcEngine.destroy(); + fakeIrisEngine.dispose(); + }, + ); + + testWidgets( + 'onVideoDeviceStateChanged', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + FakeIrisRtcEngine fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + final rtcEngine = await RtcEngine.create('123'); + bool videoDeviceStateChangedCalled = false; + rtcEngine.setEventHandler(RtcEngineEventHandler( + videoDeviceStateChanged: (deviceId, deviceType, deviceState) { + videoDeviceStateChangedCalled = true; + }, + )); + + fakeIrisEngine.fireRtcEngineEvent('onVideoDeviceStateChanged'); +// Wait for the `EventChannel` event be sent from Android/iOS side + await tester.pump(const Duration(milliseconds: 500)); + expect(videoDeviceStateChangedCalled, isTrue); + + rtcEngine.destroy(); + fakeIrisEngine.dispose(); + }, + ); + + testWidgets( + 'onAudioDeviceVolumeChanged', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + FakeIrisRtcEngine fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + final rtcEngine = await RtcEngine.create('123'); + bool audioDeviceVolumeChangedCalled = false; + rtcEngine.setEventHandler(RtcEngineEventHandler( + audioDeviceVolumeChanged: (deviceType, volume, muted) { + audioDeviceVolumeChangedCalled = true; + }, + )); + + fakeIrisEngine.fireRtcEngineEvent('onAudioDeviceVolumeChanged'); +// Wait for the `EventChannel` event be sent from Android/iOS side + await tester.pump(const Duration(milliseconds: 500)); + expect(audioDeviceVolumeChangedCalled, isTrue); + + rtcEngine.destroy(); + fakeIrisEngine.dispose(); + }, + ); + + testWidgets( + 'onAudioDeviceStateChanged', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + FakeIrisRtcEngine fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + final rtcEngine = await RtcEngine.create('123'); + bool audioDeviceStateChangedCalled = false; + rtcEngine.setEventHandler(RtcEngineEventHandler( + audioDeviceStateChanged: (deviceId, deviceType, deviceState) { + audioDeviceStateChangedCalled = true; + }, + )); + + fakeIrisEngine.fireRtcEngineEvent('onAudioDeviceStateChanged'); +// Wait for the `EventChannel` event be sent from Android/iOS side + await tester.pump(const Duration(milliseconds: 500)); + expect(audioDeviceStateChangedCalled, isTrue); + + rtcEngine.destroy(); + fakeIrisEngine.dispose(); + }, + ); + + testWidgets( + 'onRemoteAudioMixingBegin', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + FakeIrisRtcEngine fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + final rtcEngine = await RtcEngine.create('123'); + bool remoteAudioMixingBeginCalled = false; + rtcEngine.setEventHandler(RtcEngineEventHandler( + remoteAudioMixingBegin: () { + remoteAudioMixingBeginCalled = true; + }, + )); + + fakeIrisEngine.fireRtcEngineEvent('onRemoteAudioMixingBegin'); +// Wait for the `EventChannel` event be sent from Android/iOS side + await tester.pump(const Duration(milliseconds: 500)); + expect(remoteAudioMixingBeginCalled, isTrue); + + rtcEngine.destroy(); + fakeIrisEngine.dispose(); + }, + ); + + testWidgets( + 'onRemoteAudioMixingEnd', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + FakeIrisRtcEngine fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + final rtcEngine = await RtcEngine.create('123'); + bool remoteAudioMixingEndCalled = false; + rtcEngine.setEventHandler(RtcEngineEventHandler( + remoteAudioMixingEnd: () { + remoteAudioMixingEndCalled = true; + }, + )); + + fakeIrisEngine.fireRtcEngineEvent('onRemoteAudioMixingEnd'); +// Wait for the `EventChannel` event be sent from Android/iOS side + await tester.pump(const Duration(milliseconds: 500)); + expect(remoteAudioMixingEndCalled, isTrue); + + rtcEngine.destroy(); + fakeIrisEngine.dispose(); + }, + ); + + testWidgets( + 'onSnapshotTaken', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + FakeIrisRtcEngine fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + final rtcEngine = await RtcEngine.create('123'); + bool snapshotTakenCalled = false; + rtcEngine.setEventHandler(RtcEngineEventHandler( + snapshotTaken: (channel, uid, filePath, width, height, errCode) { + snapshotTakenCalled = true; + }, + )); + + fakeIrisEngine.fireRtcEngineEvent('onSnapshotTaken'); +// Wait for the `EventChannel` event be sent from Android/iOS side + await tester.pump(const Duration(milliseconds: 500)); + expect(snapshotTakenCalled, isTrue); + + rtcEngine.destroy(); + fakeIrisEngine.dispose(); + }, + ); +} diff --git a/integration_test_app/integration_test/agora_rtc_engine_subprocess_api_smoke_test.dart b/integration_test_app/integration_test/agora_rtc_engine_subprocess_api_smoke_test.dart new file mode 100644 index 000000000..087909a8a --- /dev/null +++ b/integration_test_app/integration_test/agora_rtc_engine_subprocess_api_smoke_test.dart @@ -0,0 +1,10 @@ +import 'package:integration_test/integration_test.dart'; + +import 'agora_rtc_engine_subprocess_api_smoke_test.generated.dart' + as rtc_engine_subprocess; + +void main() { + IntegrationTestWidgetsFlutterBinding.ensureInitialized(); + + rtc_engine_subprocess.rtcEngineSubProcessSmokeTestCases(); +} diff --git a/integration_test_app/integration_test/agora_rtc_engine_subprocess_api_smoke_test.generated.dart b/integration_test_app/integration_test/agora_rtc_engine_subprocess_api_smoke_test.generated.dart new file mode 100644 index 000000000..baf93fc1f --- /dev/null +++ b/integration_test_app/integration_test/agora_rtc_engine_subprocess_api_smoke_test.generated.dart @@ -0,0 +1,4244 @@ +import 'dart:io'; + +import 'package:agora_rtc_engine/rtc_engine.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:integration_test_app/main.dart' as app; + +void rtcEngineSubProcessSmokeTestCases() { + testWidgets( + 'setChannelProfile', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + String engineAppId = const String.fromEnvironment('TEST_APP_ID', + defaultValue: ''); + + RtcEngine rtcEngine = await RtcEngine.createWithContext(RtcEngineContext( + engineAppId, + areaCode: [AreaCode.NA, AreaCode.GLOB], + )); + + final screenShareHelper = + await rtcEngine.getScreenShareHelper(appGroup: 'io.agora'); + + const ChannelProfile profile = ChannelProfile.Communication; + await screenShareHelper.setChannelProfile( + profile, + ); + + await screenShareHelper.destroy(); + await rtcEngine.destroy(); + }, + skip: !(Platform.isMacOS || Platform.isWindows || Platform.isLinux), + ); + + testWidgets( + 'setClientRole', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + String engineAppId = const String.fromEnvironment('TEST_APP_ID', + defaultValue: ''); + + RtcEngine rtcEngine = await RtcEngine.createWithContext(RtcEngineContext( + engineAppId, + areaCode: [AreaCode.NA, AreaCode.GLOB], + )); + + final screenShareHelper = + await rtcEngine.getScreenShareHelper(appGroup: 'io.agora'); + + const ClientRole role = ClientRole.Broadcaster; + const AudienceLatencyLevelType optionsAudienceLatencyLevel = + AudienceLatencyLevelType.LowLatency; + final ClientRoleOptions options = ClientRoleOptions( + audienceLatencyLevel: optionsAudienceLatencyLevel, + ); + await screenShareHelper.setClientRole( + role, + options, + ); + + await screenShareHelper.destroy(); + await rtcEngine.destroy(); + }, + skip: !(Platform.isMacOS || Platform.isWindows || Platform.isLinux), + ); + + testWidgets( + 'joinChannel', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + String engineAppId = const String.fromEnvironment('TEST_APP_ID', + defaultValue: ''); + + RtcEngine rtcEngine = await RtcEngine.createWithContext(RtcEngineContext( + engineAppId, + areaCode: [AreaCode.NA, AreaCode.GLOB], + )); + + final screenShareHelper = + await rtcEngine.getScreenShareHelper(appGroup: 'io.agora'); + + const String token = "hello"; + const String channelName = "hello"; + const String optionalInfo = "hello"; + const int optionalUid = 10; + const bool optionsAutoSubscribeAudio = true; + const bool optionsAutoSubscribeVideo = true; + const bool optionsPublishLocalAudio = true; + const bool optionsPublishLocalVideo = true; + final ChannelMediaOptions options = ChannelMediaOptions( + autoSubscribeAudio: optionsAutoSubscribeAudio, + autoSubscribeVideo: optionsAutoSubscribeVideo, + publishLocalAudio: optionsPublishLocalAudio, + publishLocalVideo: optionsPublishLocalVideo, + ); + await screenShareHelper.joinChannel( + token, + channelName, + optionalInfo, + optionalUid, + options, + ); + + await screenShareHelper.destroy(); + await rtcEngine.destroy(); + }, + skip: !(Platform.isMacOS || Platform.isWindows || Platform.isLinux), + ); + + testWidgets( + 'switchChannel', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + String engineAppId = const String.fromEnvironment('TEST_APP_ID', + defaultValue: ''); + + RtcEngine rtcEngine = await RtcEngine.createWithContext(RtcEngineContext( + engineAppId, + areaCode: [AreaCode.NA, AreaCode.GLOB], + )); + + final screenShareHelper = + await rtcEngine.getScreenShareHelper(appGroup: 'io.agora'); + + const String token = "hello"; + const String channelName = "hello"; + const bool optionsAutoSubscribeAudio = true; + const bool optionsAutoSubscribeVideo = true; + const bool optionsPublishLocalAudio = true; + const bool optionsPublishLocalVideo = true; + final ChannelMediaOptions options = ChannelMediaOptions( + autoSubscribeAudio: optionsAutoSubscribeAudio, + autoSubscribeVideo: optionsAutoSubscribeVideo, + publishLocalAudio: optionsPublishLocalAudio, + publishLocalVideo: optionsPublishLocalVideo, + ); + await screenShareHelper.switchChannel( + token, + channelName, + options, + ); + + await screenShareHelper.destroy(); + await rtcEngine.destroy(); + }, + skip: !(Platform.isMacOS || Platform.isWindows || Platform.isLinux), + ); + + testWidgets( + 'leaveChannel', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + String engineAppId = const String.fromEnvironment('TEST_APP_ID', + defaultValue: ''); + + RtcEngine rtcEngine = await RtcEngine.createWithContext(RtcEngineContext( + engineAppId, + areaCode: [AreaCode.NA, AreaCode.GLOB], + )); + + final screenShareHelper = + await rtcEngine.getScreenShareHelper(appGroup: 'io.agora'); + + await screenShareHelper.leaveChannel(); + + await screenShareHelper.destroy(); + await rtcEngine.destroy(); + }, + skip: !(Platform.isMacOS || Platform.isWindows || Platform.isLinux), + ); + + testWidgets( + 'renewToken', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + String engineAppId = const String.fromEnvironment('TEST_APP_ID', + defaultValue: ''); + + RtcEngine rtcEngine = await RtcEngine.createWithContext(RtcEngineContext( + engineAppId, + areaCode: [AreaCode.NA, AreaCode.GLOB], + )); + + final screenShareHelper = + await rtcEngine.getScreenShareHelper(appGroup: 'io.agora'); + + const String token = "hello"; + await screenShareHelper.renewToken( + token, + ); + + await screenShareHelper.destroy(); + await rtcEngine.destroy(); + }, + skip: !(Platform.isMacOS || Platform.isWindows || Platform.isLinux), + ); + + testWidgets( + 'enableWebSdkInteroperability', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + String engineAppId = const String.fromEnvironment('TEST_APP_ID', + defaultValue: ''); + + RtcEngine rtcEngine = await RtcEngine.createWithContext(RtcEngineContext( + engineAppId, + areaCode: [AreaCode.NA, AreaCode.GLOB], + )); + + final screenShareHelper = + await rtcEngine.getScreenShareHelper(appGroup: 'io.agora'); + + const bool enabled = true; + await screenShareHelper.enableWebSdkInteroperability( + enabled, + ); + + await screenShareHelper.destroy(); + await rtcEngine.destroy(); + }, + skip: !(Platform.isMacOS || Platform.isWindows || Platform.isLinux), + ); + + testWidgets( + 'getCallId', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + String engineAppId = const String.fromEnvironment('TEST_APP_ID', + defaultValue: ''); + + RtcEngine rtcEngine = await RtcEngine.createWithContext(RtcEngineContext( + engineAppId, + areaCode: [AreaCode.NA, AreaCode.GLOB], + )); + + final screenShareHelper = + await rtcEngine.getScreenShareHelper(appGroup: 'io.agora'); + + await screenShareHelper.getCallId(); + + await screenShareHelper.destroy(); + await rtcEngine.destroy(); + }, + skip: !(Platform.isMacOS || Platform.isWindows || Platform.isLinux), + ); + + testWidgets( + 'rate', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + String engineAppId = const String.fromEnvironment('TEST_APP_ID', + defaultValue: ''); + + RtcEngine rtcEngine = await RtcEngine.createWithContext(RtcEngineContext( + engineAppId, + areaCode: [AreaCode.NA, AreaCode.GLOB], + )); + + final screenShareHelper = + await rtcEngine.getScreenShareHelper(appGroup: 'io.agora'); + + const String callId = "hello"; + const int rating = 10; + const String description = "hello"; + await screenShareHelper.rate( + callId, + rating, + description: description, + ); + + await screenShareHelper.destroy(); + await rtcEngine.destroy(); + }, + skip: !(Platform.isMacOS || Platform.isWindows || Platform.isLinux), + ); + + testWidgets( + 'complain', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + String engineAppId = const String.fromEnvironment('TEST_APP_ID', + defaultValue: ''); + + RtcEngine rtcEngine = await RtcEngine.createWithContext(RtcEngineContext( + engineAppId, + areaCode: [AreaCode.NA, AreaCode.GLOB], + )); + + final screenShareHelper = + await rtcEngine.getScreenShareHelper(appGroup: 'io.agora'); + + const String callId = "hello"; + const String description = "hello"; + await screenShareHelper.complain( + callId, + description, + ); + + await screenShareHelper.destroy(); + await rtcEngine.destroy(); + }, + skip: !(Platform.isMacOS || Platform.isWindows || Platform.isLinux), + ); + + testWidgets( + 'setLogFile', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + String engineAppId = const String.fromEnvironment('TEST_APP_ID', + defaultValue: ''); + + RtcEngine rtcEngine = await RtcEngine.createWithContext(RtcEngineContext( + engineAppId, + areaCode: [AreaCode.NA, AreaCode.GLOB], + )); + + final screenShareHelper = + await rtcEngine.getScreenShareHelper(appGroup: 'io.agora'); + + const String filePath = "hello"; + await screenShareHelper.setLogFile( + filePath, + ); + + await screenShareHelper.destroy(); + await rtcEngine.destroy(); + }, + skip: !(Platform.isMacOS || Platform.isWindows || Platform.isLinux), + ); + + testWidgets( + 'setLogFilter', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + String engineAppId = const String.fromEnvironment('TEST_APP_ID', + defaultValue: ''); + + RtcEngine rtcEngine = await RtcEngine.createWithContext(RtcEngineContext( + engineAppId, + areaCode: [AreaCode.NA, AreaCode.GLOB], + )); + + final screenShareHelper = + await rtcEngine.getScreenShareHelper(appGroup: 'io.agora'); + + const LogFilter filter = LogFilter.Off; + await screenShareHelper.setLogFilter( + filter, + ); + + await screenShareHelper.destroy(); + await rtcEngine.destroy(); + }, + skip: !(Platform.isMacOS || Platform.isWindows || Platform.isLinux), + ); + + testWidgets( + 'setLogFileSize', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + String engineAppId = const String.fromEnvironment('TEST_APP_ID', + defaultValue: ''); + + RtcEngine rtcEngine = await RtcEngine.createWithContext(RtcEngineContext( + engineAppId, + areaCode: [AreaCode.NA, AreaCode.GLOB], + )); + + final screenShareHelper = + await rtcEngine.getScreenShareHelper(appGroup: 'io.agora'); + + const int fileSizeInKBytes = 10; + await screenShareHelper.setLogFileSize( + fileSizeInKBytes, + ); + + await screenShareHelper.destroy(); + await rtcEngine.destroy(); + }, + skip: !(Platform.isMacOS || Platform.isWindows || Platform.isLinux), + ); + + testWidgets( + 'setParameters', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + String engineAppId = const String.fromEnvironment('TEST_APP_ID', + defaultValue: ''); + + RtcEngine rtcEngine = await RtcEngine.createWithContext(RtcEngineContext( + engineAppId, + areaCode: [AreaCode.NA, AreaCode.GLOB], + )); + + final screenShareHelper = + await rtcEngine.getScreenShareHelper(appGroup: 'io.agora'); + + const String parameters = "hello"; + await screenShareHelper.setParameters( + parameters, + ); + + await screenShareHelper.destroy(); + await rtcEngine.destroy(); + }, + skip: !(Platform.isMacOS || Platform.isWindows || Platform.isLinux), + ); + + testWidgets( + 'joinChannelWithUserAccount', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + String engineAppId = const String.fromEnvironment('TEST_APP_ID', + defaultValue: ''); + + RtcEngine rtcEngine = await RtcEngine.createWithContext(RtcEngineContext( + engineAppId, + areaCode: [AreaCode.NA, AreaCode.GLOB], + )); + + final screenShareHelper = + await rtcEngine.getScreenShareHelper(appGroup: 'io.agora'); + + const String token = "hello"; + const String channelName = "hello"; + const String userAccount = "hello"; + const bool optionsAutoSubscribeAudio = true; + const bool optionsAutoSubscribeVideo = true; + const bool optionsPublishLocalAudio = true; + const bool optionsPublishLocalVideo = true; + final ChannelMediaOptions options = ChannelMediaOptions( + autoSubscribeAudio: optionsAutoSubscribeAudio, + autoSubscribeVideo: optionsAutoSubscribeVideo, + publishLocalAudio: optionsPublishLocalAudio, + publishLocalVideo: optionsPublishLocalVideo, + ); + await screenShareHelper.joinChannelWithUserAccount( + token, + channelName, + userAccount, + options, + ); + + await screenShareHelper.destroy(); + await rtcEngine.destroy(); + }, + skip: !(Platform.isMacOS || Platform.isWindows || Platform.isLinux), + ); + + testWidgets( + 'registerLocalUserAccount', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + String engineAppId = const String.fromEnvironment('TEST_APP_ID', + defaultValue: ''); + + RtcEngine rtcEngine = await RtcEngine.createWithContext(RtcEngineContext( + engineAppId, + areaCode: [AreaCode.NA, AreaCode.GLOB], + )); + + final screenShareHelper = + await rtcEngine.getScreenShareHelper(appGroup: 'io.agora'); + + const String appId = "hello"; + const String userAccount = "hello"; + await screenShareHelper.registerLocalUserAccount( + appId, + userAccount, + ); + + await screenShareHelper.destroy(); + await rtcEngine.destroy(); + }, + skip: !(Platform.isMacOS || Platform.isWindows || Platform.isLinux), + ); + + testWidgets( + 'adjustPlaybackSignalVolume', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + String engineAppId = const String.fromEnvironment('TEST_APP_ID', + defaultValue: ''); + + RtcEngine rtcEngine = await RtcEngine.createWithContext(RtcEngineContext( + engineAppId, + areaCode: [AreaCode.NA, AreaCode.GLOB], + )); + + final screenShareHelper = + await rtcEngine.getScreenShareHelper(appGroup: 'io.agora'); + + const int volume = 10; + await screenShareHelper.adjustPlaybackSignalVolume( + volume, + ); + + await screenShareHelper.destroy(); + await rtcEngine.destroy(); + }, + skip: !(Platform.isMacOS || Platform.isWindows || Platform.isLinux), + ); + + testWidgets( + 'adjustRecordingSignalVolume', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + String engineAppId = const String.fromEnvironment('TEST_APP_ID', + defaultValue: ''); + + RtcEngine rtcEngine = await RtcEngine.createWithContext(RtcEngineContext( + engineAppId, + areaCode: [AreaCode.NA, AreaCode.GLOB], + )); + + final screenShareHelper = + await rtcEngine.getScreenShareHelper(appGroup: 'io.agora'); + + const int volume = 10; + await screenShareHelper.adjustRecordingSignalVolume( + volume, + ); + + await screenShareHelper.destroy(); + await rtcEngine.destroy(); + }, + skip: !(Platform.isMacOS || Platform.isWindows || Platform.isLinux), + ); + + testWidgets( + 'adjustUserPlaybackSignalVolume', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + String engineAppId = const String.fromEnvironment('TEST_APP_ID', + defaultValue: ''); + + RtcEngine rtcEngine = await RtcEngine.createWithContext(RtcEngineContext( + engineAppId, + areaCode: [AreaCode.NA, AreaCode.GLOB], + )); + + final screenShareHelper = + await rtcEngine.getScreenShareHelper(appGroup: 'io.agora'); + + const int uid = 10; + const int volume = 10; + await screenShareHelper.adjustUserPlaybackSignalVolume( + uid, + volume, + ); + + await screenShareHelper.destroy(); + await rtcEngine.destroy(); + }, + skip: !(Platform.isMacOS || Platform.isWindows || Platform.isLinux), + ); + + testWidgets( + 'enableLoopbackRecording', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + String engineAppId = const String.fromEnvironment('TEST_APP_ID', + defaultValue: ''); + + RtcEngine rtcEngine = await RtcEngine.createWithContext(RtcEngineContext( + engineAppId, + areaCode: [AreaCode.NA, AreaCode.GLOB], + )); + + final screenShareHelper = + await rtcEngine.getScreenShareHelper(appGroup: 'io.agora'); + + const bool enabled = true; + const String deviceName = "hello"; + await screenShareHelper.enableLoopbackRecording( + enabled, + deviceName: deviceName, + ); + + await screenShareHelper.destroy(); + await rtcEngine.destroy(); + }, + skip: !(Platform.isMacOS || Platform.isWindows || Platform.isLinux), + ); + + testWidgets( + 'disableAudio', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + String engineAppId = const String.fromEnvironment('TEST_APP_ID', + defaultValue: ''); + + RtcEngine rtcEngine = await RtcEngine.createWithContext(RtcEngineContext( + engineAppId, + areaCode: [AreaCode.NA, AreaCode.GLOB], + )); + + final screenShareHelper = + await rtcEngine.getScreenShareHelper(appGroup: 'io.agora'); + + await screenShareHelper.disableAudio(); + + await screenShareHelper.destroy(); + await rtcEngine.destroy(); + }, + skip: !(Platform.isMacOS || Platform.isWindows || Platform.isLinux), + ); + + testWidgets( + 'enableAudio', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + String engineAppId = const String.fromEnvironment('TEST_APP_ID', + defaultValue: ''); + + RtcEngine rtcEngine = await RtcEngine.createWithContext(RtcEngineContext( + engineAppId, + areaCode: [AreaCode.NA, AreaCode.GLOB], + )); + + final screenShareHelper = + await rtcEngine.getScreenShareHelper(appGroup: 'io.agora'); + + await screenShareHelper.enableAudio(); + + await screenShareHelper.destroy(); + await rtcEngine.destroy(); + }, + skip: !(Platform.isMacOS || Platform.isWindows || Platform.isLinux), + ); + + testWidgets( + 'enableAudioVolumeIndication', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + String engineAppId = const String.fromEnvironment('TEST_APP_ID', + defaultValue: ''); + + RtcEngine rtcEngine = await RtcEngine.createWithContext(RtcEngineContext( + engineAppId, + areaCode: [AreaCode.NA, AreaCode.GLOB], + )); + + final screenShareHelper = + await rtcEngine.getScreenShareHelper(appGroup: 'io.agora'); + + const int interval = 10; + const int smooth = 10; + const bool report_vad = true; + await screenShareHelper.enableAudioVolumeIndication( + interval, + smooth, + report_vad, + ); + + await screenShareHelper.destroy(); + await rtcEngine.destroy(); + }, + skip: !(Platform.isMacOS || Platform.isWindows || Platform.isLinux), + ); + + testWidgets( + 'enableLocalAudio', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + String engineAppId = const String.fromEnvironment('TEST_APP_ID', + defaultValue: ''); + + RtcEngine rtcEngine = await RtcEngine.createWithContext(RtcEngineContext( + engineAppId, + areaCode: [AreaCode.NA, AreaCode.GLOB], + )); + + final screenShareHelper = + await rtcEngine.getScreenShareHelper(appGroup: 'io.agora'); + + const bool enabled = true; + await screenShareHelper.enableLocalAudio( + enabled, + ); + + await screenShareHelper.destroy(); + await rtcEngine.destroy(); + }, + skip: !(Platform.isMacOS || Platform.isWindows || Platform.isLinux), + ); + + testWidgets( + 'muteAllRemoteAudioStreams', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + String engineAppId = const String.fromEnvironment('TEST_APP_ID', + defaultValue: ''); + + RtcEngine rtcEngine = await RtcEngine.createWithContext(RtcEngineContext( + engineAppId, + areaCode: [AreaCode.NA, AreaCode.GLOB], + )); + + final screenShareHelper = + await rtcEngine.getScreenShareHelper(appGroup: 'io.agora'); + + const bool muted = true; + await screenShareHelper.muteAllRemoteAudioStreams( + muted, + ); + + await screenShareHelper.destroy(); + await rtcEngine.destroy(); + }, + skip: !(Platform.isMacOS || Platform.isWindows || Platform.isLinux), + ); + + testWidgets( + 'muteLocalAudioStream', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + String engineAppId = const String.fromEnvironment('TEST_APP_ID', + defaultValue: ''); + + RtcEngine rtcEngine = await RtcEngine.createWithContext(RtcEngineContext( + engineAppId, + areaCode: [AreaCode.NA, AreaCode.GLOB], + )); + + final screenShareHelper = + await rtcEngine.getScreenShareHelper(appGroup: 'io.agora'); + + const bool muted = true; + await screenShareHelper.muteLocalAudioStream( + muted, + ); + + await screenShareHelper.destroy(); + await rtcEngine.destroy(); + }, + skip: !(Platform.isMacOS || Platform.isWindows || Platform.isLinux), + ); + + testWidgets( + 'muteRemoteAudioStream', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + String engineAppId = const String.fromEnvironment('TEST_APP_ID', + defaultValue: ''); + + RtcEngine rtcEngine = await RtcEngine.createWithContext(RtcEngineContext( + engineAppId, + areaCode: [AreaCode.NA, AreaCode.GLOB], + )); + + final screenShareHelper = + await rtcEngine.getScreenShareHelper(appGroup: 'io.agora'); + + const int uid = 10; + const bool muted = true; + await screenShareHelper.muteRemoteAudioStream( + uid, + muted, + ); + + await screenShareHelper.destroy(); + await rtcEngine.destroy(); + }, + skip: !(Platform.isMacOS || Platform.isWindows || Platform.isLinux), + ); + + testWidgets( + 'setAudioProfile', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + String engineAppId = const String.fromEnvironment('TEST_APP_ID', + defaultValue: ''); + + RtcEngine rtcEngine = await RtcEngine.createWithContext(RtcEngineContext( + engineAppId, + areaCode: [AreaCode.NA, AreaCode.GLOB], + )); + + final screenShareHelper = + await rtcEngine.getScreenShareHelper(appGroup: 'io.agora'); + + const AudioProfile profile = AudioProfile.Default; + const AudioScenario scenario = AudioScenario.Default; + await screenShareHelper.setAudioProfile( + profile, + scenario, + ); + + await screenShareHelper.destroy(); + await rtcEngine.destroy(); + }, + skip: !(Platform.isMacOS || Platform.isWindows || Platform.isLinux), + ); + + testWidgets( + 'setDefaultMuteAllRemoteAudioStreams', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + String engineAppId = const String.fromEnvironment('TEST_APP_ID', + defaultValue: ''); + + RtcEngine rtcEngine = await RtcEngine.createWithContext(RtcEngineContext( + engineAppId, + areaCode: [AreaCode.NA, AreaCode.GLOB], + )); + + final screenShareHelper = + await rtcEngine.getScreenShareHelper(appGroup: 'io.agora'); + + const bool muted = true; + await screenShareHelper.setDefaultMuteAllRemoteAudioStreams( + muted, + ); + + await screenShareHelper.destroy(); + await rtcEngine.destroy(); + }, + skip: !(Platform.isMacOS || Platform.isWindows || Platform.isLinux), + ); + + testWidgets( + 'disableVideo', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + String engineAppId = const String.fromEnvironment('TEST_APP_ID', + defaultValue: ''); + + RtcEngine rtcEngine = await RtcEngine.createWithContext(RtcEngineContext( + engineAppId, + areaCode: [AreaCode.NA, AreaCode.GLOB], + )); + + final screenShareHelper = + await rtcEngine.getScreenShareHelper(appGroup: 'io.agora'); + + await screenShareHelper.disableVideo(); + + await screenShareHelper.destroy(); + await rtcEngine.destroy(); + }, + skip: !(Platform.isMacOS || Platform.isWindows || Platform.isLinux), + ); + + testWidgets( + 'enableLocalVideo', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + String engineAppId = const String.fromEnvironment('TEST_APP_ID', + defaultValue: ''); + + RtcEngine rtcEngine = await RtcEngine.createWithContext(RtcEngineContext( + engineAppId, + areaCode: [AreaCode.NA, AreaCode.GLOB], + )); + + final screenShareHelper = + await rtcEngine.getScreenShareHelper(appGroup: 'io.agora'); + + const bool enabled = true; + await screenShareHelper.enableLocalVideo( + enabled, + ); + + await screenShareHelper.destroy(); + await rtcEngine.destroy(); + }, + skip: !(Platform.isMacOS || Platform.isWindows || Platform.isLinux), + ); + + testWidgets( + 'enableVideo', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + String engineAppId = const String.fromEnvironment('TEST_APP_ID', + defaultValue: ''); + + RtcEngine rtcEngine = await RtcEngine.createWithContext(RtcEngineContext( + engineAppId, + areaCode: [AreaCode.NA, AreaCode.GLOB], + )); + + final screenShareHelper = + await rtcEngine.getScreenShareHelper(appGroup: 'io.agora'); + + await screenShareHelper.enableVideo(); + + await screenShareHelper.destroy(); + await rtcEngine.destroy(); + }, + skip: !(Platform.isMacOS || Platform.isWindows || Platform.isLinux), + ); + + testWidgets( + 'muteAllRemoteVideoStreams', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + String engineAppId = const String.fromEnvironment('TEST_APP_ID', + defaultValue: ''); + + RtcEngine rtcEngine = await RtcEngine.createWithContext(RtcEngineContext( + engineAppId, + areaCode: [AreaCode.NA, AreaCode.GLOB], + )); + + final screenShareHelper = + await rtcEngine.getScreenShareHelper(appGroup: 'io.agora'); + + const bool muted = true; + await screenShareHelper.muteAllRemoteVideoStreams( + muted, + ); + + await screenShareHelper.destroy(); + await rtcEngine.destroy(); + }, + skip: !(Platform.isMacOS || Platform.isWindows || Platform.isLinux), + ); + + testWidgets( + 'muteLocalVideoStream', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + String engineAppId = const String.fromEnvironment('TEST_APP_ID', + defaultValue: ''); + + RtcEngine rtcEngine = await RtcEngine.createWithContext(RtcEngineContext( + engineAppId, + areaCode: [AreaCode.NA, AreaCode.GLOB], + )); + + final screenShareHelper = + await rtcEngine.getScreenShareHelper(appGroup: 'io.agora'); + + const bool muted = true; + await screenShareHelper.muteLocalVideoStream( + muted, + ); + + await screenShareHelper.destroy(); + await rtcEngine.destroy(); + }, + skip: !(Platform.isMacOS || Platform.isWindows || Platform.isLinux), + ); + + testWidgets( + 'muteRemoteVideoStream', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + String engineAppId = const String.fromEnvironment('TEST_APP_ID', + defaultValue: ''); + + RtcEngine rtcEngine = await RtcEngine.createWithContext(RtcEngineContext( + engineAppId, + areaCode: [AreaCode.NA, AreaCode.GLOB], + )); + + final screenShareHelper = + await rtcEngine.getScreenShareHelper(appGroup: 'io.agora'); + + const int uid = 10; + const bool muted = true; + await screenShareHelper.muteRemoteVideoStream( + uid, + muted, + ); + + await screenShareHelper.destroy(); + await rtcEngine.destroy(); + }, + skip: !(Platform.isMacOS || Platform.isWindows || Platform.isLinux), + ); + + testWidgets( + 'setBeautyEffectOptions', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + String engineAppId = const String.fromEnvironment('TEST_APP_ID', + defaultValue: ''); + + RtcEngine rtcEngine = await RtcEngine.createWithContext(RtcEngineContext( + engineAppId, + areaCode: [AreaCode.NA, AreaCode.GLOB], + )); + + final screenShareHelper = + await rtcEngine.getScreenShareHelper(appGroup: 'io.agora'); + + const bool enabled = true; + const LighteningContrastLevel optionsLighteningContrastLevel = + LighteningContrastLevel.Low; + const double optionsLighteningLevel = 10.0; + const double optionsSmoothnessLevel = 10.0; + const double optionsRednessLevel = 10.0; + final BeautyOptions options = BeautyOptions( + lighteningContrastLevel: optionsLighteningContrastLevel, + lighteningLevel: optionsLighteningLevel, + smoothnessLevel: optionsSmoothnessLevel, + rednessLevel: optionsRednessLevel, + ); + await screenShareHelper.setBeautyEffectOptions( + enabled, + options, + ); + + await screenShareHelper.destroy(); + await rtcEngine.destroy(); + }, + skip: !(Platform.isMacOS || Platform.isWindows || Platform.isLinux), + ); + + testWidgets( + 'setDefaultMuteAllRemoteVideoStreams', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + String engineAppId = const String.fromEnvironment('TEST_APP_ID', + defaultValue: ''); + + RtcEngine rtcEngine = await RtcEngine.createWithContext(RtcEngineContext( + engineAppId, + areaCode: [AreaCode.NA, AreaCode.GLOB], + )); + + final screenShareHelper = + await rtcEngine.getScreenShareHelper(appGroup: 'io.agora'); + + const bool muted = true; + await screenShareHelper.setDefaultMuteAllRemoteVideoStreams( + muted, + ); + + await screenShareHelper.destroy(); + await rtcEngine.destroy(); + }, + skip: !(Platform.isMacOS || Platform.isWindows || Platform.isLinux), + ); + + testWidgets( + 'startPreview', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + String engineAppId = const String.fromEnvironment('TEST_APP_ID', + defaultValue: ''); + + RtcEngine rtcEngine = await RtcEngine.createWithContext(RtcEngineContext( + engineAppId, + areaCode: [AreaCode.NA, AreaCode.GLOB], + )); + + final screenShareHelper = + await rtcEngine.getScreenShareHelper(appGroup: 'io.agora'); + + await screenShareHelper.startPreview(); + + await screenShareHelper.destroy(); + await rtcEngine.destroy(); + }, + skip: !(Platform.isMacOS || Platform.isWindows || Platform.isLinux), + ); + + testWidgets( + 'stopPreview', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + String engineAppId = const String.fromEnvironment('TEST_APP_ID', + defaultValue: ''); + + RtcEngine rtcEngine = await RtcEngine.createWithContext(RtcEngineContext( + engineAppId, + areaCode: [AreaCode.NA, AreaCode.GLOB], + )); + + final screenShareHelper = + await rtcEngine.getScreenShareHelper(appGroup: 'io.agora'); + + await screenShareHelper.stopPreview(); + + await screenShareHelper.destroy(); + await rtcEngine.destroy(); + }, + skip: !(Platform.isMacOS || Platform.isWindows || Platform.isLinux), + ); + + testWidgets( + 'adjustAudioMixingPlayoutVolume', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + String engineAppId = const String.fromEnvironment('TEST_APP_ID', + defaultValue: ''); + + RtcEngine rtcEngine = await RtcEngine.createWithContext(RtcEngineContext( + engineAppId, + areaCode: [AreaCode.NA, AreaCode.GLOB], + )); + + final screenShareHelper = + await rtcEngine.getScreenShareHelper(appGroup: 'io.agora'); + + const int volume = 10; + await screenShareHelper.adjustAudioMixingPlayoutVolume( + volume, + ); + + await screenShareHelper.destroy(); + await rtcEngine.destroy(); + }, + skip: !(Platform.isMacOS || Platform.isWindows || Platform.isLinux), + ); + + testWidgets( + 'adjustAudioMixingPublishVolume', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + String engineAppId = const String.fromEnvironment('TEST_APP_ID', + defaultValue: ''); + + RtcEngine rtcEngine = await RtcEngine.createWithContext(RtcEngineContext( + engineAppId, + areaCode: [AreaCode.NA, AreaCode.GLOB], + )); + + final screenShareHelper = + await rtcEngine.getScreenShareHelper(appGroup: 'io.agora'); + + const int volume = 10; + await screenShareHelper.adjustAudioMixingPublishVolume( + volume, + ); + + await screenShareHelper.destroy(); + await rtcEngine.destroy(); + }, + skip: !(Platform.isMacOS || Platform.isWindows || Platform.isLinux), + ); + + testWidgets( + 'adjustAudioMixingVolume', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + String engineAppId = const String.fromEnvironment('TEST_APP_ID', + defaultValue: ''); + + RtcEngine rtcEngine = await RtcEngine.createWithContext(RtcEngineContext( + engineAppId, + areaCode: [AreaCode.NA, AreaCode.GLOB], + )); + + final screenShareHelper = + await rtcEngine.getScreenShareHelper(appGroup: 'io.agora'); + + const int volume = 10; + await screenShareHelper.adjustAudioMixingVolume( + volume, + ); + + await screenShareHelper.destroy(); + await rtcEngine.destroy(); + }, + skip: !(Platform.isMacOS || Platform.isWindows || Platform.isLinux), + ); + + testWidgets( + 'getAudioMixingCurrentPosition', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + String engineAppId = const String.fromEnvironment('TEST_APP_ID', + defaultValue: ''); + + RtcEngine rtcEngine = await RtcEngine.createWithContext(RtcEngineContext( + engineAppId, + areaCode: [AreaCode.NA, AreaCode.GLOB], + )); + + final screenShareHelper = + await rtcEngine.getScreenShareHelper(appGroup: 'io.agora'); + + await screenShareHelper.getAudioMixingCurrentPosition(); + + await screenShareHelper.destroy(); + await rtcEngine.destroy(); + }, + skip: !(Platform.isMacOS || Platform.isWindows || Platform.isLinux), + ); + + testWidgets( + 'getAudioMixingDuration', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + String engineAppId = const String.fromEnvironment('TEST_APP_ID', + defaultValue: ''); + + RtcEngine rtcEngine = await RtcEngine.createWithContext(RtcEngineContext( + engineAppId, + areaCode: [AreaCode.NA, AreaCode.GLOB], + )); + + final screenShareHelper = + await rtcEngine.getScreenShareHelper(appGroup: 'io.agora'); + + const String filePath = "hello"; + await screenShareHelper.getAudioMixingDuration( + filePath, + ); + + await screenShareHelper.destroy(); + await rtcEngine.destroy(); + }, + skip: !(Platform.isMacOS || Platform.isWindows || Platform.isLinux), + ); + + testWidgets( + 'getAudioFileInfo', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + String engineAppId = const String.fromEnvironment('TEST_APP_ID', + defaultValue: ''); + + RtcEngine rtcEngine = await RtcEngine.createWithContext(RtcEngineContext( + engineAppId, + areaCode: [AreaCode.NA, AreaCode.GLOB], + )); + + final screenShareHelper = + await rtcEngine.getScreenShareHelper(appGroup: 'io.agora'); + + const String filePath = "hello"; + await screenShareHelper.getAudioFileInfo( + filePath, + ); + + await screenShareHelper.destroy(); + await rtcEngine.destroy(); + }, + skip: !(Platform.isMacOS || Platform.isWindows || Platform.isLinux), + ); + + testWidgets( + 'getAudioMixingPlayoutVolume', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + String engineAppId = const String.fromEnvironment('TEST_APP_ID', + defaultValue: ''); + + RtcEngine rtcEngine = await RtcEngine.createWithContext(RtcEngineContext( + engineAppId, + areaCode: [AreaCode.NA, AreaCode.GLOB], + )); + + final screenShareHelper = + await rtcEngine.getScreenShareHelper(appGroup: 'io.agora'); + + await screenShareHelper.getAudioMixingPlayoutVolume(); + + await screenShareHelper.destroy(); + await rtcEngine.destroy(); + }, + skip: !(Platform.isMacOS || Platform.isWindows || Platform.isLinux), + ); + + testWidgets( + 'getAudioMixingPublishVolume', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + String engineAppId = const String.fromEnvironment('TEST_APP_ID', + defaultValue: ''); + + RtcEngine rtcEngine = await RtcEngine.createWithContext(RtcEngineContext( + engineAppId, + areaCode: [AreaCode.NA, AreaCode.GLOB], + )); + + final screenShareHelper = + await rtcEngine.getScreenShareHelper(appGroup: 'io.agora'); + + await screenShareHelper.getAudioMixingPublishVolume(); + + await screenShareHelper.destroy(); + await rtcEngine.destroy(); + }, + skip: !(Platform.isMacOS || Platform.isWindows || Platform.isLinux), + ); + + testWidgets( + 'pauseAudioMixing', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + String engineAppId = const String.fromEnvironment('TEST_APP_ID', + defaultValue: ''); + + RtcEngine rtcEngine = await RtcEngine.createWithContext(RtcEngineContext( + engineAppId, + areaCode: [AreaCode.NA, AreaCode.GLOB], + )); + + final screenShareHelper = + await rtcEngine.getScreenShareHelper(appGroup: 'io.agora'); + + await screenShareHelper.pauseAudioMixing(); + + await screenShareHelper.destroy(); + await rtcEngine.destroy(); + }, + skip: !(Platform.isMacOS || Platform.isWindows || Platform.isLinux), + ); + + testWidgets( + 'resumeAudioMixing', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + String engineAppId = const String.fromEnvironment('TEST_APP_ID', + defaultValue: ''); + + RtcEngine rtcEngine = await RtcEngine.createWithContext(RtcEngineContext( + engineAppId, + areaCode: [AreaCode.NA, AreaCode.GLOB], + )); + + final screenShareHelper = + await rtcEngine.getScreenShareHelper(appGroup: 'io.agora'); + + await screenShareHelper.resumeAudioMixing(); + + await screenShareHelper.destroy(); + await rtcEngine.destroy(); + }, + skip: !(Platform.isMacOS || Platform.isWindows || Platform.isLinux), + ); + + testWidgets( + 'setAudioMixingPosition', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + String engineAppId = const String.fromEnvironment('TEST_APP_ID', + defaultValue: ''); + + RtcEngine rtcEngine = await RtcEngine.createWithContext(RtcEngineContext( + engineAppId, + areaCode: [AreaCode.NA, AreaCode.GLOB], + )); + + final screenShareHelper = + await rtcEngine.getScreenShareHelper(appGroup: 'io.agora'); + + const int pos = 10; + await screenShareHelper.setAudioMixingPosition( + pos, + ); + + await screenShareHelper.destroy(); + await rtcEngine.destroy(); + }, + skip: !(Platform.isMacOS || Platform.isWindows || Platform.isLinux), + ); + + testWidgets( + 'startAudioMixing', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + String engineAppId = const String.fromEnvironment('TEST_APP_ID', + defaultValue: ''); + + RtcEngine rtcEngine = await RtcEngine.createWithContext(RtcEngineContext( + engineAppId, + areaCode: [AreaCode.NA, AreaCode.GLOB], + )); + + final screenShareHelper = + await rtcEngine.getScreenShareHelper(appGroup: 'io.agora'); + + const String filePath = "hello"; + const bool loopback = true; + const bool replace = true; + const int cycle = 10; + const int startPos = 10; + await screenShareHelper.startAudioMixing( + filePath, + loopback, + replace, + cycle, + startPos, + ); + + await screenShareHelper.destroy(); + await rtcEngine.destroy(); + }, + skip: !(Platform.isMacOS || Platform.isWindows || Platform.isLinux), + ); + + testWidgets( + 'stopAudioMixing', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + String engineAppId = const String.fromEnvironment('TEST_APP_ID', + defaultValue: ''); + + RtcEngine rtcEngine = await RtcEngine.createWithContext(RtcEngineContext( + engineAppId, + areaCode: [AreaCode.NA, AreaCode.GLOB], + )); + + final screenShareHelper = + await rtcEngine.getScreenShareHelper(appGroup: 'io.agora'); + + await screenShareHelper.stopAudioMixing(); + + await screenShareHelper.destroy(); + await rtcEngine.destroy(); + }, + skip: !(Platform.isMacOS || Platform.isWindows || Platform.isLinux), + ); + + testWidgets( + 'addInjectStreamUrl', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + String engineAppId = const String.fromEnvironment('TEST_APP_ID', + defaultValue: ''); + + RtcEngine rtcEngine = await RtcEngine.createWithContext(RtcEngineContext( + engineAppId, + areaCode: [AreaCode.NA, AreaCode.GLOB], + )); + + final screenShareHelper = + await rtcEngine.getScreenShareHelper(appGroup: 'io.agora'); + + const String url = "hello"; + const VideoFrameRate configVideoFramerate = VideoFrameRate.Min; + const AudioSampleRateType configAudioSampleRate = + AudioSampleRateType.Type32000; + const AudioChannel configAudioChannels = AudioChannel.Channel0; + const int configWidth = 10; + const int configHeight = 10; + const int configVideoGop = 10; + const int configVideoBitrate = 10; + const int configAudioBitrate = 10; + final LiveInjectStreamConfig config = LiveInjectStreamConfig( + width: configWidth, + height: configHeight, + videoGop: configVideoGop, + videoFramerate: configVideoFramerate, + videoBitrate: configVideoBitrate, + audioSampleRate: configAudioSampleRate, + audioBitrate: configAudioBitrate, + audioChannels: configAudioChannels, + ); + await screenShareHelper.addInjectStreamUrl( + url, + config, + ); + + await screenShareHelper.destroy(); + await rtcEngine.destroy(); + }, + skip: !(Platform.isMacOS || Platform.isWindows || Platform.isLinux), + ); + + testWidgets( + 'addPublishStreamUrl', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + String engineAppId = const String.fromEnvironment('TEST_APP_ID', + defaultValue: ''); + + RtcEngine rtcEngine = await RtcEngine.createWithContext(RtcEngineContext( + engineAppId, + areaCode: [AreaCode.NA, AreaCode.GLOB], + )); + + final screenShareHelper = + await rtcEngine.getScreenShareHelper(appGroup: 'io.agora'); + + const String url = "hello"; + const bool transcodingEnabled = true; + await screenShareHelper.addPublishStreamUrl( + url, + transcodingEnabled, + ); + + await screenShareHelper.destroy(); + await rtcEngine.destroy(); + }, + skip: !(Platform.isMacOS || Platform.isWindows || Platform.isLinux), + ); + + testWidgets( + 'addVideoWatermark', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + String engineAppId = const String.fromEnvironment('TEST_APP_ID', + defaultValue: ''); + + RtcEngine rtcEngine = await RtcEngine.createWithContext(RtcEngineContext( + engineAppId, + areaCode: [AreaCode.NA, AreaCode.GLOB], + )); + + final screenShareHelper = + await rtcEngine.getScreenShareHelper(appGroup: 'io.agora'); + + const String watermarkUrl = "hello"; + const int positionInLandscapeModeX = 10; + const int positionInLandscapeModeY = 10; + const int positionInLandscapeModeWidth = 10; + const int positionInLandscapeModeHeight = 10; + final Rectangle optionsPositionInLandscapeMode = Rectangle( + x: positionInLandscapeModeX, + y: positionInLandscapeModeY, + width: positionInLandscapeModeWidth, + height: positionInLandscapeModeHeight, + ); + const int positionInPortraitModeX = 10; + const int positionInPortraitModeY = 10; + const int positionInPortraitModeWidth = 10; + const int positionInPortraitModeHeight = 10; + final Rectangle optionsPositionInPortraitMode = Rectangle( + x: positionInPortraitModeX, + y: positionInPortraitModeY, + width: positionInPortraitModeWidth, + height: positionInPortraitModeHeight, + ); + const bool optionsVisibleInPreview = true; + final WatermarkOptions options = WatermarkOptions( + visibleInPreview: optionsVisibleInPreview, + positionInLandscapeMode: optionsPositionInLandscapeMode, + positionInPortraitMode: optionsPositionInPortraitMode, + ); + await screenShareHelper.addVideoWatermark( + watermarkUrl, + options, + ); + + await screenShareHelper.destroy(); + await rtcEngine.destroy(); + }, + skip: !(Platform.isMacOS || Platform.isWindows || Platform.isLinux), + ); + + testWidgets( + 'clearVideoWatermarks', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + String engineAppId = const String.fromEnvironment('TEST_APP_ID', + defaultValue: ''); + + RtcEngine rtcEngine = await RtcEngine.createWithContext(RtcEngineContext( + engineAppId, + areaCode: [AreaCode.NA, AreaCode.GLOB], + )); + + final screenShareHelper = + await rtcEngine.getScreenShareHelper(appGroup: 'io.agora'); + + await screenShareHelper.clearVideoWatermarks(); + + await screenShareHelper.destroy(); + await rtcEngine.destroy(); + }, + skip: !(Platform.isMacOS || Platform.isWindows || Platform.isLinux), + ); + + testWidgets( + 'disableLastmileTest', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + String engineAppId = const String.fromEnvironment('TEST_APP_ID', + defaultValue: ''); + + RtcEngine rtcEngine = await RtcEngine.createWithContext(RtcEngineContext( + engineAppId, + areaCode: [AreaCode.NA, AreaCode.GLOB], + )); + + final screenShareHelper = + await rtcEngine.getScreenShareHelper(appGroup: 'io.agora'); + + await screenShareHelper.disableLastmileTest(); + + await screenShareHelper.destroy(); + await rtcEngine.destroy(); + }, + skip: !(Platform.isMacOS || Platform.isWindows || Platform.isLinux), + ); + + testWidgets( + 'enableDualStreamMode', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + String engineAppId = const String.fromEnvironment('TEST_APP_ID', + defaultValue: ''); + + RtcEngine rtcEngine = await RtcEngine.createWithContext(RtcEngineContext( + engineAppId, + areaCode: [AreaCode.NA, AreaCode.GLOB], + )); + + final screenShareHelper = + await rtcEngine.getScreenShareHelper(appGroup: 'io.agora'); + + const bool enabled = true; + await screenShareHelper.enableDualStreamMode( + enabled, + ); + + await screenShareHelper.destroy(); + await rtcEngine.destroy(); + }, + skip: !(Platform.isMacOS || Platform.isWindows || Platform.isLinux), + ); + + testWidgets( + 'enableInEarMonitoring', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + String engineAppId = const String.fromEnvironment('TEST_APP_ID', + defaultValue: ''); + + RtcEngine rtcEngine = await RtcEngine.createWithContext(RtcEngineContext( + engineAppId, + areaCode: [AreaCode.NA, AreaCode.GLOB], + )); + + final screenShareHelper = + await rtcEngine.getScreenShareHelper(appGroup: 'io.agora'); + + const bool enabled = true; + await screenShareHelper.enableInEarMonitoring( + enabled, + ); + + await screenShareHelper.destroy(); + await rtcEngine.destroy(); + }, + skip: !(Platform.isMacOS || Platform.isWindows || Platform.isLinux), + ); + + testWidgets( + 'enableLastmileTest', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + String engineAppId = const String.fromEnvironment('TEST_APP_ID', + defaultValue: ''); + + RtcEngine rtcEngine = await RtcEngine.createWithContext(RtcEngineContext( + engineAppId, + areaCode: [AreaCode.NA, AreaCode.GLOB], + )); + + final screenShareHelper = + await rtcEngine.getScreenShareHelper(appGroup: 'io.agora'); + + await screenShareHelper.enableLastmileTest(); + + await screenShareHelper.destroy(); + await rtcEngine.destroy(); + }, + skip: !(Platform.isMacOS || Platform.isWindows || Platform.isLinux), + ); + + testWidgets( + 'enableSoundPositionIndication', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + String engineAppId = const String.fromEnvironment('TEST_APP_ID', + defaultValue: ''); + + RtcEngine rtcEngine = await RtcEngine.createWithContext(RtcEngineContext( + engineAppId, + areaCode: [AreaCode.NA, AreaCode.GLOB], + )); + + final screenShareHelper = + await rtcEngine.getScreenShareHelper(appGroup: 'io.agora'); + + const bool enabled = true; + await screenShareHelper.enableSoundPositionIndication( + enabled, + ); + + await screenShareHelper.destroy(); + await rtcEngine.destroy(); + }, + skip: !(Platform.isMacOS || Platform.isWindows || Platform.isLinux), + ); + + testWidgets( + 'getEffectsVolume', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + String engineAppId = const String.fromEnvironment('TEST_APP_ID', + defaultValue: ''); + + RtcEngine rtcEngine = await RtcEngine.createWithContext(RtcEngineContext( + engineAppId, + areaCode: [AreaCode.NA, AreaCode.GLOB], + )); + + final screenShareHelper = + await rtcEngine.getScreenShareHelper(appGroup: 'io.agora'); + + await screenShareHelper.getEffectsVolume(); + + await screenShareHelper.destroy(); + await rtcEngine.destroy(); + }, + skip: !(Platform.isMacOS || Platform.isWindows || Platform.isLinux), + ); + + testWidgets( + 'isCameraTorchSupported', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + String engineAppId = const String.fromEnvironment('TEST_APP_ID', + defaultValue: ''); + + RtcEngine rtcEngine = await RtcEngine.createWithContext(RtcEngineContext( + engineAppId, + areaCode: [AreaCode.NA, AreaCode.GLOB], + )); + + final screenShareHelper = + await rtcEngine.getScreenShareHelper(appGroup: 'io.agora'); + + await screenShareHelper.isCameraTorchSupported(); + + await screenShareHelper.destroy(); + await rtcEngine.destroy(); + }, + skip: !(Platform.isMacOS || Platform.isWindows || Platform.isLinux), + ); + + testWidgets( + 'isSpeakerphoneEnabled', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + String engineAppId = const String.fromEnvironment('TEST_APP_ID', + defaultValue: ''); + + RtcEngine rtcEngine = await RtcEngine.createWithContext(RtcEngineContext( + engineAppId, + areaCode: [AreaCode.NA, AreaCode.GLOB], + )); + + final screenShareHelper = + await rtcEngine.getScreenShareHelper(appGroup: 'io.agora'); + + await screenShareHelper.isSpeakerphoneEnabled(); + + await screenShareHelper.destroy(); + await rtcEngine.destroy(); + }, + skip: !(Platform.isMacOS || Platform.isWindows || Platform.isLinux), + ); + + testWidgets( + 'pauseAllEffects', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + String engineAppId = const String.fromEnvironment('TEST_APP_ID', + defaultValue: ''); + + RtcEngine rtcEngine = await RtcEngine.createWithContext(RtcEngineContext( + engineAppId, + areaCode: [AreaCode.NA, AreaCode.GLOB], + )); + + final screenShareHelper = + await rtcEngine.getScreenShareHelper(appGroup: 'io.agora'); + + await screenShareHelper.pauseAllEffects(); + + await screenShareHelper.destroy(); + await rtcEngine.destroy(); + }, + skip: !(Platform.isMacOS || Platform.isWindows || Platform.isLinux), + ); + + testWidgets( + 'pauseEffect', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + String engineAppId = const String.fromEnvironment('TEST_APP_ID', + defaultValue: ''); + + RtcEngine rtcEngine = await RtcEngine.createWithContext(RtcEngineContext( + engineAppId, + areaCode: [AreaCode.NA, AreaCode.GLOB], + )); + + final screenShareHelper = + await rtcEngine.getScreenShareHelper(appGroup: 'io.agora'); + + const int soundId = 10; + await screenShareHelper.pauseEffect( + soundId, + ); + + await screenShareHelper.destroy(); + await rtcEngine.destroy(); + }, + skip: !(Platform.isMacOS || Platform.isWindows || Platform.isLinux), + ); + + testWidgets( + 'playEffect', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + String engineAppId = const String.fromEnvironment('TEST_APP_ID', + defaultValue: ''); + + RtcEngine rtcEngine = await RtcEngine.createWithContext(RtcEngineContext( + engineAppId, + areaCode: [AreaCode.NA, AreaCode.GLOB], + )); + + final screenShareHelper = + await rtcEngine.getScreenShareHelper(appGroup: 'io.agora'); + + const int soundId = 10; + const String filePath = "hello"; + const int loopCount = 10; + const double pitch = 10.0; + const double pan = 10.0; + const int gain = 10; + const bool publish = true; + const int startPos = 10; + await screenShareHelper.playEffect( + soundId, + filePath, + loopCount, + pitch, + pan, + gain, + publish, + startPos, + ); + + await screenShareHelper.destroy(); + await rtcEngine.destroy(); + }, + skip: !(Platform.isMacOS || Platform.isWindows || Platform.isLinux), + ); + + testWidgets( + 'setEffectPosition', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + String engineAppId = const String.fromEnvironment('TEST_APP_ID', + defaultValue: ''); + + RtcEngine rtcEngine = await RtcEngine.createWithContext(RtcEngineContext( + engineAppId, + areaCode: [AreaCode.NA, AreaCode.GLOB], + )); + + final screenShareHelper = + await rtcEngine.getScreenShareHelper(appGroup: 'io.agora'); + + const int soundId = 10; + const int pos = 10; + await screenShareHelper.setEffectPosition( + soundId, + pos, + ); + + await screenShareHelper.destroy(); + await rtcEngine.destroy(); + }, + skip: !(Platform.isMacOS || Platform.isWindows || Platform.isLinux), + ); + + testWidgets( + 'getEffectDuration', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + String engineAppId = const String.fromEnvironment('TEST_APP_ID', + defaultValue: ''); + + RtcEngine rtcEngine = await RtcEngine.createWithContext(RtcEngineContext( + engineAppId, + areaCode: [AreaCode.NA, AreaCode.GLOB], + )); + + final screenShareHelper = + await rtcEngine.getScreenShareHelper(appGroup: 'io.agora'); + + const String filePath = "hello"; + await screenShareHelper.getEffectDuration( + filePath, + ); + + await screenShareHelper.destroy(); + await rtcEngine.destroy(); + }, + skip: !(Platform.isMacOS || Platform.isWindows || Platform.isLinux), + ); + + testWidgets( + 'getEffectCurrentPosition', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + String engineAppId = const String.fromEnvironment('TEST_APP_ID', + defaultValue: ''); + + RtcEngine rtcEngine = await RtcEngine.createWithContext(RtcEngineContext( + engineAppId, + areaCode: [AreaCode.NA, AreaCode.GLOB], + )); + + final screenShareHelper = + await rtcEngine.getScreenShareHelper(appGroup: 'io.agora'); + + const int soundId = 10; + await screenShareHelper.getEffectCurrentPosition( + soundId, + ); + + await screenShareHelper.destroy(); + await rtcEngine.destroy(); + }, + skip: !(Platform.isMacOS || Platform.isWindows || Platform.isLinux), + ); + + testWidgets( + 'preloadEffect', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + String engineAppId = const String.fromEnvironment('TEST_APP_ID', + defaultValue: ''); + + RtcEngine rtcEngine = await RtcEngine.createWithContext(RtcEngineContext( + engineAppId, + areaCode: [AreaCode.NA, AreaCode.GLOB], + )); + + final screenShareHelper = + await rtcEngine.getScreenShareHelper(appGroup: 'io.agora'); + + const int soundId = 10; + const String filePath = "hello"; + await screenShareHelper.preloadEffect( + soundId, + filePath, + ); + + await screenShareHelper.destroy(); + await rtcEngine.destroy(); + }, + skip: !(Platform.isMacOS || Platform.isWindows || Platform.isLinux), + ); + + testWidgets( + 'registerMediaMetadataObserver', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + String engineAppId = const String.fromEnvironment('TEST_APP_ID', + defaultValue: ''); + + RtcEngine rtcEngine = await RtcEngine.createWithContext(RtcEngineContext( + engineAppId, + areaCode: [AreaCode.NA, AreaCode.GLOB], + )); + + final screenShareHelper = + await rtcEngine.getScreenShareHelper(appGroup: 'io.agora'); + + await screenShareHelper.registerMediaMetadataObserver(); + + await screenShareHelper.destroy(); + await rtcEngine.destroy(); + }, + skip: !(Platform.isMacOS || Platform.isWindows || Platform.isLinux), + ); + + testWidgets( + 'removeInjectStreamUrl', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + String engineAppId = const String.fromEnvironment('TEST_APP_ID', + defaultValue: ''); + + RtcEngine rtcEngine = await RtcEngine.createWithContext(RtcEngineContext( + engineAppId, + areaCode: [AreaCode.NA, AreaCode.GLOB], + )); + + final screenShareHelper = + await rtcEngine.getScreenShareHelper(appGroup: 'io.agora'); + + const String url = "hello"; + await screenShareHelper.removeInjectStreamUrl( + url, + ); + + await screenShareHelper.destroy(); + await rtcEngine.destroy(); + }, + skip: !(Platform.isMacOS || Platform.isWindows || Platform.isLinux), + ); + + testWidgets( + 'removePublishStreamUrl', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + String engineAppId = const String.fromEnvironment('TEST_APP_ID', + defaultValue: ''); + + RtcEngine rtcEngine = await RtcEngine.createWithContext(RtcEngineContext( + engineAppId, + areaCode: [AreaCode.NA, AreaCode.GLOB], + )); + + final screenShareHelper = + await rtcEngine.getScreenShareHelper(appGroup: 'io.agora'); + + const String url = "hello"; + await screenShareHelper.removePublishStreamUrl( + url, + ); + + await screenShareHelper.destroy(); + await rtcEngine.destroy(); + }, + skip: !(Platform.isMacOS || Platform.isWindows || Platform.isLinux), + ); + + testWidgets( + 'resumeAllEffects', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + String engineAppId = const String.fromEnvironment('TEST_APP_ID', + defaultValue: ''); + + RtcEngine rtcEngine = await RtcEngine.createWithContext(RtcEngineContext( + engineAppId, + areaCode: [AreaCode.NA, AreaCode.GLOB], + )); + + final screenShareHelper = + await rtcEngine.getScreenShareHelper(appGroup: 'io.agora'); + + await screenShareHelper.resumeAllEffects(); + + await screenShareHelper.destroy(); + await rtcEngine.destroy(); + }, + skip: !(Platform.isMacOS || Platform.isWindows || Platform.isLinux), + ); + + testWidgets( + 'resumeEffect', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + String engineAppId = const String.fromEnvironment('TEST_APP_ID', + defaultValue: ''); + + RtcEngine rtcEngine = await RtcEngine.createWithContext(RtcEngineContext( + engineAppId, + areaCode: [AreaCode.NA, AreaCode.GLOB], + )); + + final screenShareHelper = + await rtcEngine.getScreenShareHelper(appGroup: 'io.agora'); + + const int soundId = 10; + await screenShareHelper.resumeEffect( + soundId, + ); + + await screenShareHelper.destroy(); + await rtcEngine.destroy(); + }, + skip: !(Platform.isMacOS || Platform.isWindows || Platform.isLinux), + ); + + testWidgets( + 'setCameraCapturerConfiguration', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + String engineAppId = const String.fromEnvironment('TEST_APP_ID', + defaultValue: ''); + + RtcEngine rtcEngine = await RtcEngine.createWithContext(RtcEngineContext( + engineAppId, + areaCode: [AreaCode.NA, AreaCode.GLOB], + )); + + final screenShareHelper = + await rtcEngine.getScreenShareHelper(appGroup: 'io.agora'); + + const CameraCaptureOutputPreference configPreference = + CameraCaptureOutputPreference.Auto; + const CameraDirection configCameraDirection = CameraDirection.Rear; + const int configCaptureWidth = 10; + const int configCaptureHeight = 10; + final CameraCapturerConfiguration config = CameraCapturerConfiguration( + preference: configPreference, + captureWidth: configCaptureWidth, + captureHeight: configCaptureHeight, + cameraDirection: configCameraDirection, + ); + await screenShareHelper.setCameraCapturerConfiguration( + config, + ); + + await screenShareHelper.destroy(); + await rtcEngine.destroy(); + }, + skip: !(Platform.isMacOS || Platform.isWindows || Platform.isLinux), + ); + + testWidgets( + 'setCameraTorchOn', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + String engineAppId = const String.fromEnvironment('TEST_APP_ID', + defaultValue: ''); + + RtcEngine rtcEngine = await RtcEngine.createWithContext(RtcEngineContext( + engineAppId, + areaCode: [AreaCode.NA, AreaCode.GLOB], + )); + + final screenShareHelper = + await rtcEngine.getScreenShareHelper(appGroup: 'io.agora'); + + const bool isOn = true; + await screenShareHelper.setCameraTorchOn( + isOn, + ); + + await screenShareHelper.destroy(); + await rtcEngine.destroy(); + }, + skip: !(Platform.isMacOS || Platform.isWindows || Platform.isLinux), + ); + + testWidgets( + 'setDefaultAudioRoutetoSpeakerphone', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + String engineAppId = const String.fromEnvironment('TEST_APP_ID', + defaultValue: ''); + + RtcEngine rtcEngine = await RtcEngine.createWithContext(RtcEngineContext( + engineAppId, + areaCode: [AreaCode.NA, AreaCode.GLOB], + )); + + final screenShareHelper = + await rtcEngine.getScreenShareHelper(appGroup: 'io.agora'); + + const bool defaultToSpeaker = true; + await screenShareHelper.setDefaultAudioRoutetoSpeakerphone( + defaultToSpeaker, + ); + + await screenShareHelper.destroy(); + await rtcEngine.destroy(); + }, + skip: !(Platform.isMacOS || Platform.isWindows || Platform.isLinux), + ); + + testWidgets( + 'setEffectsVolume', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + String engineAppId = const String.fromEnvironment('TEST_APP_ID', + defaultValue: ''); + + RtcEngine rtcEngine = await RtcEngine.createWithContext(RtcEngineContext( + engineAppId, + areaCode: [AreaCode.NA, AreaCode.GLOB], + )); + + final screenShareHelper = + await rtcEngine.getScreenShareHelper(appGroup: 'io.agora'); + + const int volume = 10; + await screenShareHelper.setEffectsVolume( + volume, + ); + + await screenShareHelper.destroy(); + await rtcEngine.destroy(); + }, + skip: !(Platform.isMacOS || Platform.isWindows || Platform.isLinux), + ); + + testWidgets( + 'setEnableSpeakerphone', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + String engineAppId = const String.fromEnvironment('TEST_APP_ID', + defaultValue: ''); + + RtcEngine rtcEngine = await RtcEngine.createWithContext(RtcEngineContext( + engineAppId, + areaCode: [AreaCode.NA, AreaCode.GLOB], + )); + + final screenShareHelper = + await rtcEngine.getScreenShareHelper(appGroup: 'io.agora'); + + const bool speakerOn = true; + await screenShareHelper.setEnableSpeakerphone( + speakerOn, + ); + + await screenShareHelper.destroy(); + await rtcEngine.destroy(); + }, + skip: !(Platform.isMacOS || Platform.isWindows || Platform.isLinux), + ); + + testWidgets( + 'setEncryptionMode', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + String engineAppId = const String.fromEnvironment('TEST_APP_ID', + defaultValue: ''); + + RtcEngine rtcEngine = await RtcEngine.createWithContext(RtcEngineContext( + engineAppId, + areaCode: [AreaCode.NA, AreaCode.GLOB], + )); + + final screenShareHelper = + await rtcEngine.getScreenShareHelper(appGroup: 'io.agora'); + + const EncryptionMode encryptionMode = EncryptionMode.None; + await screenShareHelper.setEncryptionMode( + encryptionMode, + ); + + await screenShareHelper.destroy(); + await rtcEngine.destroy(); + }, + skip: !(Platform.isMacOS || Platform.isWindows || Platform.isLinux), + ); + + testWidgets( + 'setEncryptionSecret', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + String engineAppId = const String.fromEnvironment('TEST_APP_ID', + defaultValue: ''); + + RtcEngine rtcEngine = await RtcEngine.createWithContext(RtcEngineContext( + engineAppId, + areaCode: [AreaCode.NA, AreaCode.GLOB], + )); + + final screenShareHelper = + await rtcEngine.getScreenShareHelper(appGroup: 'io.agora'); + + const String secret = "hello"; + await screenShareHelper.setEncryptionSecret( + secret, + ); + + await screenShareHelper.destroy(); + await rtcEngine.destroy(); + }, + skip: !(Platform.isMacOS || Platform.isWindows || Platform.isLinux), + ); + + testWidgets( + 'setInEarMonitoringVolume', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + String engineAppId = const String.fromEnvironment('TEST_APP_ID', + defaultValue: ''); + + RtcEngine rtcEngine = await RtcEngine.createWithContext(RtcEngineContext( + engineAppId, + areaCode: [AreaCode.NA, AreaCode.GLOB], + )); + + final screenShareHelper = + await rtcEngine.getScreenShareHelper(appGroup: 'io.agora'); + + const int volume = 10; + await screenShareHelper.setInEarMonitoringVolume( + volume, + ); + + await screenShareHelper.destroy(); + await rtcEngine.destroy(); + }, + skip: !(Platform.isMacOS || Platform.isWindows || Platform.isLinux), + ); + + testWidgets( + 'setLocalPublishFallbackOption', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + String engineAppId = const String.fromEnvironment('TEST_APP_ID', + defaultValue: ''); + + RtcEngine rtcEngine = await RtcEngine.createWithContext(RtcEngineContext( + engineAppId, + areaCode: [AreaCode.NA, AreaCode.GLOB], + )); + + final screenShareHelper = + await rtcEngine.getScreenShareHelper(appGroup: 'io.agora'); + + const StreamFallbackOptions option = StreamFallbackOptions.Disabled; + await screenShareHelper.setLocalPublishFallbackOption( + option, + ); + + await screenShareHelper.destroy(); + await rtcEngine.destroy(); + }, + skip: !(Platform.isMacOS || Platform.isWindows || Platform.isLinux), + ); + + testWidgets( + 'setLocalVoiceChanger', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + String engineAppId = const String.fromEnvironment('TEST_APP_ID', + defaultValue: ''); + + RtcEngine rtcEngine = await RtcEngine.createWithContext(RtcEngineContext( + engineAppId, + areaCode: [AreaCode.NA, AreaCode.GLOB], + )); + + final screenShareHelper = + await rtcEngine.getScreenShareHelper(appGroup: 'io.agora'); + + const AudioVoiceChanger voiceChanger = AudioVoiceChanger.Off; + await screenShareHelper.setLocalVoiceChanger( + voiceChanger, + ); + + await screenShareHelper.destroy(); + await rtcEngine.destroy(); + }, + skip: !(Platform.isMacOS || Platform.isWindows || Platform.isLinux), + ); + + testWidgets( + 'setLocalVoiceEqualization', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + String engineAppId = const String.fromEnvironment('TEST_APP_ID', + defaultValue: ''); + + RtcEngine rtcEngine = await RtcEngine.createWithContext(RtcEngineContext( + engineAppId, + areaCode: [AreaCode.NA, AreaCode.GLOB], + )); + + final screenShareHelper = + await rtcEngine.getScreenShareHelper(appGroup: 'io.agora'); + + const AudioEqualizationBandFrequency bandFrequency = + AudioEqualizationBandFrequency.Band31; + const int bandGain = 10; + await screenShareHelper.setLocalVoiceEqualization( + bandFrequency, + bandGain, + ); + + await screenShareHelper.destroy(); + await rtcEngine.destroy(); + }, + skip: !(Platform.isMacOS || Platform.isWindows || Platform.isLinux), + ); + + testWidgets( + 'setLocalVoicePitch', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + String engineAppId = const String.fromEnvironment('TEST_APP_ID', + defaultValue: ''); + + RtcEngine rtcEngine = await RtcEngine.createWithContext(RtcEngineContext( + engineAppId, + areaCode: [AreaCode.NA, AreaCode.GLOB], + )); + + final screenShareHelper = + await rtcEngine.getScreenShareHelper(appGroup: 'io.agora'); + + const double pitch = 10.0; + await screenShareHelper.setLocalVoicePitch( + pitch, + ); + + await screenShareHelper.destroy(); + await rtcEngine.destroy(); + }, + skip: !(Platform.isMacOS || Platform.isWindows || Platform.isLinux), + ); + + testWidgets( + 'setLocalVoiceReverb', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + String engineAppId = const String.fromEnvironment('TEST_APP_ID', + defaultValue: ''); + + RtcEngine rtcEngine = await RtcEngine.createWithContext(RtcEngineContext( + engineAppId, + areaCode: [AreaCode.NA, AreaCode.GLOB], + )); + + final screenShareHelper = + await rtcEngine.getScreenShareHelper(appGroup: 'io.agora'); + + const AudioReverbType reverbKey = AudioReverbType.DryLevel; + const int value = 10; + await screenShareHelper.setLocalVoiceReverb( + reverbKey, + value, + ); + + await screenShareHelper.destroy(); + await rtcEngine.destroy(); + }, + skip: !(Platform.isMacOS || Platform.isWindows || Platform.isLinux), + ); + + testWidgets( + 'setLocalVoiceReverbPreset', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + String engineAppId = const String.fromEnvironment('TEST_APP_ID', + defaultValue: ''); + + RtcEngine rtcEngine = await RtcEngine.createWithContext(RtcEngineContext( + engineAppId, + areaCode: [AreaCode.NA, AreaCode.GLOB], + )); + + final screenShareHelper = + await rtcEngine.getScreenShareHelper(appGroup: 'io.agora'); + + const AudioReverbPreset reverbPreset = AudioReverbPreset.Off; + await screenShareHelper.setLocalVoiceReverbPreset( + reverbPreset, + ); + + await screenShareHelper.destroy(); + await rtcEngine.destroy(); + }, + skip: !(Platform.isMacOS || Platform.isWindows || Platform.isLinux), + ); + + testWidgets( + 'setMaxMetadataSize', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + String engineAppId = const String.fromEnvironment('TEST_APP_ID', + defaultValue: ''); + + RtcEngine rtcEngine = await RtcEngine.createWithContext(RtcEngineContext( + engineAppId, + areaCode: [AreaCode.NA, AreaCode.GLOB], + )); + + final screenShareHelper = + await rtcEngine.getScreenShareHelper(appGroup: 'io.agora'); + + const int size = 10; + await screenShareHelper.setMaxMetadataSize( + size, + ); + + await screenShareHelper.destroy(); + await rtcEngine.destroy(); + }, + skip: !(Platform.isMacOS || Platform.isWindows || Platform.isLinux), + ); + + testWidgets( + 'setRemoteDefaultVideoStreamType', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + String engineAppId = const String.fromEnvironment('TEST_APP_ID', + defaultValue: ''); + + RtcEngine rtcEngine = await RtcEngine.createWithContext(RtcEngineContext( + engineAppId, + areaCode: [AreaCode.NA, AreaCode.GLOB], + )); + + final screenShareHelper = + await rtcEngine.getScreenShareHelper(appGroup: 'io.agora'); + + const VideoStreamType streamType = VideoStreamType.High; + await screenShareHelper.setRemoteDefaultVideoStreamType( + streamType, + ); + + await screenShareHelper.destroy(); + await rtcEngine.destroy(); + }, + skip: !(Platform.isMacOS || Platform.isWindows || Platform.isLinux), + ); + + testWidgets( + 'setRemoteSubscribeFallbackOption', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + String engineAppId = const String.fromEnvironment('TEST_APP_ID', + defaultValue: ''); + + RtcEngine rtcEngine = await RtcEngine.createWithContext(RtcEngineContext( + engineAppId, + areaCode: [AreaCode.NA, AreaCode.GLOB], + )); + + final screenShareHelper = + await rtcEngine.getScreenShareHelper(appGroup: 'io.agora'); + + const StreamFallbackOptions option = StreamFallbackOptions.Disabled; + await screenShareHelper.setRemoteSubscribeFallbackOption( + option, + ); + + await screenShareHelper.destroy(); + await rtcEngine.destroy(); + }, + skip: !(Platform.isMacOS || Platform.isWindows || Platform.isLinux), + ); + + testWidgets( + 'setRemoteUserPriority', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + String engineAppId = const String.fromEnvironment('TEST_APP_ID', + defaultValue: ''); + + RtcEngine rtcEngine = await RtcEngine.createWithContext(RtcEngineContext( + engineAppId, + areaCode: [AreaCode.NA, AreaCode.GLOB], + )); + + final screenShareHelper = + await rtcEngine.getScreenShareHelper(appGroup: 'io.agora'); + + const int uid = 10; + const UserPriority userPriority = UserPriority.High; + await screenShareHelper.setRemoteUserPriority( + uid, + userPriority, + ); + + await screenShareHelper.destroy(); + await rtcEngine.destroy(); + }, + skip: !(Platform.isMacOS || Platform.isWindows || Platform.isLinux), + ); + + testWidgets( + 'setRemoteVideoStreamType', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + String engineAppId = const String.fromEnvironment('TEST_APP_ID', + defaultValue: ''); + + RtcEngine rtcEngine = await RtcEngine.createWithContext(RtcEngineContext( + engineAppId, + areaCode: [AreaCode.NA, AreaCode.GLOB], + )); + + final screenShareHelper = + await rtcEngine.getScreenShareHelper(appGroup: 'io.agora'); + + const int userId = 10; + const VideoStreamType streamType = VideoStreamType.High; + await screenShareHelper.setRemoteVideoStreamType( + userId, + streamType, + ); + + await screenShareHelper.destroy(); + await rtcEngine.destroy(); + }, + skip: !(Platform.isMacOS || Platform.isWindows || Platform.isLinux), + ); + + testWidgets( + 'setRemoteVoicePosition', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + String engineAppId = const String.fromEnvironment('TEST_APP_ID', + defaultValue: ''); + + RtcEngine rtcEngine = await RtcEngine.createWithContext(RtcEngineContext( + engineAppId, + areaCode: [AreaCode.NA, AreaCode.GLOB], + )); + + final screenShareHelper = + await rtcEngine.getScreenShareHelper(appGroup: 'io.agora'); + + const int uid = 10; + const double pan = 10.0; + const double gain = 10.0; + await screenShareHelper.setRemoteVoicePosition( + uid, + pan, + gain, + ); + + await screenShareHelper.destroy(); + await rtcEngine.destroy(); + }, + skip: !(Platform.isMacOS || Platform.isWindows || Platform.isLinux), + ); + + testWidgets( + 'setVolumeOfEffect', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + String engineAppId = const String.fromEnvironment('TEST_APP_ID', + defaultValue: ''); + + RtcEngine rtcEngine = await RtcEngine.createWithContext(RtcEngineContext( + engineAppId, + areaCode: [AreaCode.NA, AreaCode.GLOB], + )); + + final screenShareHelper = + await rtcEngine.getScreenShareHelper(appGroup: 'io.agora'); + + const int soundId = 10; + const int volume = 10; + await screenShareHelper.setVolumeOfEffect( + soundId, + volume, + ); + + await screenShareHelper.destroy(); + await rtcEngine.destroy(); + }, + skip: !(Platform.isMacOS || Platform.isWindows || Platform.isLinux), + ); + + testWidgets( + 'startAudioRecording', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + String engineAppId = const String.fromEnvironment('TEST_APP_ID', + defaultValue: ''); + + RtcEngine rtcEngine = await RtcEngine.createWithContext(RtcEngineContext( + engineAppId, + areaCode: [AreaCode.NA, AreaCode.GLOB], + )); + + final screenShareHelper = + await rtcEngine.getScreenShareHelper(appGroup: 'io.agora'); + + const String filePath = "hello"; + const AudioSampleRateType sampleRate = AudioSampleRateType.Type32000; + const AudioRecordingQuality quality = AudioRecordingQuality.Low; + await screenShareHelper.startAudioRecording( + filePath, + sampleRate, + quality, + ); + + await screenShareHelper.destroy(); + await rtcEngine.destroy(); + }, + skip: !(Platform.isMacOS || Platform.isWindows || Platform.isLinux), + ); + + testWidgets( + 'startAudioRecordingWithConfig', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + String engineAppId = const String.fromEnvironment('TEST_APP_ID', + defaultValue: ''); + + RtcEngine rtcEngine = await RtcEngine.createWithContext(RtcEngineContext( + engineAppId, + areaCode: [AreaCode.NA, AreaCode.GLOB], + )); + + final screenShareHelper = + await rtcEngine.getScreenShareHelper(appGroup: 'io.agora'); + + const AudioRecordingQuality configRecordingQuality = + AudioRecordingQuality.Low; + const AudioRecordingPosition configRecordingPosition = + AudioRecordingPosition.PositionMixedRecordingAndPlayback; + const AudioSampleRateType configRecordingSampleRate = + AudioSampleRateType.Type32000; + const String configFilePath = "hello"; + final AudioRecordingConfiguration config = AudioRecordingConfiguration( + configFilePath, + recordingQuality: configRecordingQuality, + recordingPosition: configRecordingPosition, + recordingSampleRate: configRecordingSampleRate, + ); + await screenShareHelper.startAudioRecordingWithConfig( + config, + ); + + await screenShareHelper.destroy(); + await rtcEngine.destroy(); + }, + skip: !(Platform.isMacOS || Platform.isWindows || Platform.isLinux), + ); + + testWidgets( + 'startChannelMediaRelay', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + String engineAppId = const String.fromEnvironment('TEST_APP_ID', + defaultValue: ''); + + RtcEngine rtcEngine = await RtcEngine.createWithContext(RtcEngineContext( + engineAppId, + areaCode: [AreaCode.NA, AreaCode.GLOB], + )); + + final screenShareHelper = + await rtcEngine.getScreenShareHelper(appGroup: 'io.agora'); + + const String srcInfoChannelName = "hello"; + const int srcInfoUid = 10; + const String srcInfoToken = "hello"; + final ChannelMediaInfo channelMediaRelayConfigurationSrcInfo = + ChannelMediaInfo( + srcInfoChannelName, + srcInfoUid, + token: srcInfoToken, + ); + const List channelMediaRelayConfigurationDestInfos = []; + final ChannelMediaRelayConfiguration channelMediaRelayConfiguration = + ChannelMediaRelayConfiguration( + channelMediaRelayConfigurationSrcInfo, + channelMediaRelayConfigurationDestInfos, + ); + await screenShareHelper.startChannelMediaRelay( + channelMediaRelayConfiguration, + ); + + await screenShareHelper.destroy(); + await rtcEngine.destroy(); + }, + skip: !(Platform.isMacOS || Platform.isWindows || Platform.isLinux), + ); + + testWidgets( + 'startLastmileProbeTest', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + String engineAppId = const String.fromEnvironment('TEST_APP_ID', + defaultValue: ''); + + RtcEngine rtcEngine = await RtcEngine.createWithContext(RtcEngineContext( + engineAppId, + areaCode: [AreaCode.NA, AreaCode.GLOB], + )); + + final screenShareHelper = + await rtcEngine.getScreenShareHelper(appGroup: 'io.agora'); + + const bool configProbeUplink = true; + const bool configProbeDownlink = true; + const int configExpectedUplinkBitrate = 10; + const int configExpectedDownlinkBitrate = 10; + final LastmileProbeConfig config = LastmileProbeConfig( + configProbeUplink, + configProbeDownlink, + configExpectedUplinkBitrate, + configExpectedDownlinkBitrate, + ); + await screenShareHelper.startLastmileProbeTest( + config, + ); + + await screenShareHelper.destroy(); + await rtcEngine.destroy(); + }, + skip: !(Platform.isMacOS || Platform.isWindows || Platform.isLinux), + ); + + testWidgets( + 'stopAllEffects', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + String engineAppId = const String.fromEnvironment('TEST_APP_ID', + defaultValue: ''); + + RtcEngine rtcEngine = await RtcEngine.createWithContext(RtcEngineContext( + engineAppId, + areaCode: [AreaCode.NA, AreaCode.GLOB], + )); + + final screenShareHelper = + await rtcEngine.getScreenShareHelper(appGroup: 'io.agora'); + + await screenShareHelper.stopAllEffects(); + + await screenShareHelper.destroy(); + await rtcEngine.destroy(); + }, + skip: !(Platform.isMacOS || Platform.isWindows || Platform.isLinux), + ); + + testWidgets( + 'stopAudioRecording', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + String engineAppId = const String.fromEnvironment('TEST_APP_ID', + defaultValue: ''); + + RtcEngine rtcEngine = await RtcEngine.createWithContext(RtcEngineContext( + engineAppId, + areaCode: [AreaCode.NA, AreaCode.GLOB], + )); + + final screenShareHelper = + await rtcEngine.getScreenShareHelper(appGroup: 'io.agora'); + + await screenShareHelper.stopAudioRecording(); + + await screenShareHelper.destroy(); + await rtcEngine.destroy(); + }, + skip: !(Platform.isMacOS || Platform.isWindows || Platform.isLinux), + ); + + testWidgets( + 'stopChannelMediaRelay', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + String engineAppId = const String.fromEnvironment('TEST_APP_ID', + defaultValue: ''); + + RtcEngine rtcEngine = await RtcEngine.createWithContext(RtcEngineContext( + engineAppId, + areaCode: [AreaCode.NA, AreaCode.GLOB], + )); + + final screenShareHelper = + await rtcEngine.getScreenShareHelper(appGroup: 'io.agora'); + + await screenShareHelper.stopChannelMediaRelay(); + + await screenShareHelper.destroy(); + await rtcEngine.destroy(); + }, + skip: !(Platform.isMacOS || Platform.isWindows || Platform.isLinux), + ); + + testWidgets( + 'stopEchoTest', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + String engineAppId = const String.fromEnvironment('TEST_APP_ID', + defaultValue: ''); + + RtcEngine rtcEngine = await RtcEngine.createWithContext(RtcEngineContext( + engineAppId, + areaCode: [AreaCode.NA, AreaCode.GLOB], + )); + + final screenShareHelper = + await rtcEngine.getScreenShareHelper(appGroup: 'io.agora'); + + await screenShareHelper.stopEchoTest(); + + await screenShareHelper.destroy(); + await rtcEngine.destroy(); + }, + skip: !(Platform.isMacOS || Platform.isWindows || Platform.isLinux), + ); + + testWidgets( + 'stopEffect', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + String engineAppId = const String.fromEnvironment('TEST_APP_ID', + defaultValue: ''); + + RtcEngine rtcEngine = await RtcEngine.createWithContext(RtcEngineContext( + engineAppId, + areaCode: [AreaCode.NA, AreaCode.GLOB], + )); + + final screenShareHelper = + await rtcEngine.getScreenShareHelper(appGroup: 'io.agora'); + + const int soundId = 10; + await screenShareHelper.stopEffect( + soundId, + ); + + await screenShareHelper.destroy(); + await rtcEngine.destroy(); + }, + skip: !(Platform.isMacOS || Platform.isWindows || Platform.isLinux), + ); + + testWidgets( + 'stopLastmileProbeTest', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + String engineAppId = const String.fromEnvironment('TEST_APP_ID', + defaultValue: ''); + + RtcEngine rtcEngine = await RtcEngine.createWithContext(RtcEngineContext( + engineAppId, + areaCode: [AreaCode.NA, AreaCode.GLOB], + )); + + final screenShareHelper = + await rtcEngine.getScreenShareHelper(appGroup: 'io.agora'); + + await screenShareHelper.stopLastmileProbeTest(); + + await screenShareHelper.destroy(); + await rtcEngine.destroy(); + }, + skip: !(Platform.isMacOS || Platform.isWindows || Platform.isLinux), + ); + + testWidgets( + 'switchCamera', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + String engineAppId = const String.fromEnvironment('TEST_APP_ID', + defaultValue: ''); + + RtcEngine rtcEngine = await RtcEngine.createWithContext(RtcEngineContext( + engineAppId, + areaCode: [AreaCode.NA, AreaCode.GLOB], + )); + + final screenShareHelper = + await rtcEngine.getScreenShareHelper(appGroup: 'io.agora'); + + await screenShareHelper.switchCamera(); + + await screenShareHelper.destroy(); + await rtcEngine.destroy(); + }, + skip: !(Platform.isMacOS || Platform.isWindows || Platform.isLinux), + ); + + testWidgets( + 'unloadEffect', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + String engineAppId = const String.fromEnvironment('TEST_APP_ID', + defaultValue: ''); + + RtcEngine rtcEngine = await RtcEngine.createWithContext(RtcEngineContext( + engineAppId, + areaCode: [AreaCode.NA, AreaCode.GLOB], + )); + + final screenShareHelper = + await rtcEngine.getScreenShareHelper(appGroup: 'io.agora'); + + const int soundId = 10; + await screenShareHelper.unloadEffect( + soundId, + ); + + await screenShareHelper.destroy(); + await rtcEngine.destroy(); + }, + skip: !(Platform.isMacOS || Platform.isWindows || Platform.isLinux), + ); + + testWidgets( + 'unregisterMediaMetadataObserver', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + String engineAppId = const String.fromEnvironment('TEST_APP_ID', + defaultValue: ''); + + RtcEngine rtcEngine = await RtcEngine.createWithContext(RtcEngineContext( + engineAppId, + areaCode: [AreaCode.NA, AreaCode.GLOB], + )); + + final screenShareHelper = + await rtcEngine.getScreenShareHelper(appGroup: 'io.agora'); + + await screenShareHelper.unregisterMediaMetadataObserver(); + + await screenShareHelper.destroy(); + await rtcEngine.destroy(); + }, + skip: !(Platform.isMacOS || Platform.isWindows || Platform.isLinux), + ); + + testWidgets( + 'updateChannelMediaRelay', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + String engineAppId = const String.fromEnvironment('TEST_APP_ID', + defaultValue: ''); + + RtcEngine rtcEngine = await RtcEngine.createWithContext(RtcEngineContext( + engineAppId, + areaCode: [AreaCode.NA, AreaCode.GLOB], + )); + + final screenShareHelper = + await rtcEngine.getScreenShareHelper(appGroup: 'io.agora'); + + const String srcInfoChannelName = "hello"; + const int srcInfoUid = 10; + const String srcInfoToken = "hello"; + final ChannelMediaInfo channelMediaRelayConfigurationSrcInfo = + ChannelMediaInfo( + srcInfoChannelName, + srcInfoUid, + token: srcInfoToken, + ); + const List channelMediaRelayConfigurationDestInfos = []; + final ChannelMediaRelayConfiguration channelMediaRelayConfiguration = + ChannelMediaRelayConfiguration( + channelMediaRelayConfigurationSrcInfo, + channelMediaRelayConfigurationDestInfos, + ); + await screenShareHelper.updateChannelMediaRelay( + channelMediaRelayConfiguration, + ); + + await screenShareHelper.destroy(); + await rtcEngine.destroy(); + }, + skip: !(Platform.isMacOS || Platform.isWindows || Platform.isLinux), + ); + + testWidgets( + 'enableFaceDetection', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + String engineAppId = const String.fromEnvironment('TEST_APP_ID', + defaultValue: ''); + + RtcEngine rtcEngine = await RtcEngine.createWithContext(RtcEngineContext( + engineAppId, + areaCode: [AreaCode.NA, AreaCode.GLOB], + )); + + final screenShareHelper = + await rtcEngine.getScreenShareHelper(appGroup: 'io.agora'); + + const bool enable = true; + await screenShareHelper.enableFaceDetection( + enable, + ); + + await screenShareHelper.destroy(); + await rtcEngine.destroy(); + }, + skip: !(Platform.isMacOS || Platform.isWindows || Platform.isLinux), + ); + + testWidgets( + 'setAudioMixingPitch', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + String engineAppId = const String.fromEnvironment('TEST_APP_ID', + defaultValue: ''); + + RtcEngine rtcEngine = await RtcEngine.createWithContext(RtcEngineContext( + engineAppId, + areaCode: [AreaCode.NA, AreaCode.GLOB], + )); + + final screenShareHelper = + await rtcEngine.getScreenShareHelper(appGroup: 'io.agora'); + + const int pitch = 10; + await screenShareHelper.setAudioMixingPitch( + pitch, + ); + + await screenShareHelper.destroy(); + await rtcEngine.destroy(); + }, + skip: !(Platform.isMacOS || Platform.isWindows || Platform.isLinux), + ); + + testWidgets( + 'setAudioMixingPlaybackSpeed', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + String engineAppId = const String.fromEnvironment('TEST_APP_ID', + defaultValue: ''); + + RtcEngine rtcEngine = await RtcEngine.createWithContext(RtcEngineContext( + engineAppId, + areaCode: [AreaCode.NA, AreaCode.GLOB], + )); + + final screenShareHelper = + await rtcEngine.getScreenShareHelper(appGroup: 'io.agora'); + + const int speed = 10; + await screenShareHelper.setAudioMixingPlaybackSpeed( + speed, + ); + + await screenShareHelper.destroy(); + await rtcEngine.destroy(); + }, + skip: !(Platform.isMacOS || Platform.isWindows || Platform.isLinux), + ); + + testWidgets( + 'getAudioTrackCount', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + String engineAppId = const String.fromEnvironment('TEST_APP_ID', + defaultValue: ''); + + RtcEngine rtcEngine = await RtcEngine.createWithContext(RtcEngineContext( + engineAppId, + areaCode: [AreaCode.NA, AreaCode.GLOB], + )); + + final screenShareHelper = + await rtcEngine.getScreenShareHelper(appGroup: 'io.agora'); + + await screenShareHelper.getAudioTrackCount(); + + await screenShareHelper.destroy(); + await rtcEngine.destroy(); + }, + skip: !(Platform.isMacOS || Platform.isWindows || Platform.isLinux), + ); + + testWidgets( + 'selectAudioTrack', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + String engineAppId = const String.fromEnvironment('TEST_APP_ID', + defaultValue: ''); + + RtcEngine rtcEngine = await RtcEngine.createWithContext(RtcEngineContext( + engineAppId, + areaCode: [AreaCode.NA, AreaCode.GLOB], + )); + + final screenShareHelper = + await rtcEngine.getScreenShareHelper(appGroup: 'io.agora'); + + const int index = 10; + await screenShareHelper.selectAudioTrack( + index, + ); + + await screenShareHelper.destroy(); + await rtcEngine.destroy(); + }, + skip: !(Platform.isMacOS || Platform.isWindows || Platform.isLinux), + ); + + testWidgets( + 'setAudioMixingDualMonoMode', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + String engineAppId = const String.fromEnvironment('TEST_APP_ID', + defaultValue: ''); + + RtcEngine rtcEngine = await RtcEngine.createWithContext(RtcEngineContext( + engineAppId, + areaCode: [AreaCode.NA, AreaCode.GLOB], + )); + + final screenShareHelper = + await rtcEngine.getScreenShareHelper(appGroup: 'io.agora'); + + const AudioMixingDualMonoMode mode = AudioMixingDualMonoMode.Auto; + await screenShareHelper.setAudioMixingDualMonoMode( + mode, + ); + + await screenShareHelper.destroy(); + await rtcEngine.destroy(); + }, + skip: !(Platform.isMacOS || Platform.isWindows || Platform.isLinux), + ); + + testWidgets( + 'enableEncryption', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + String engineAppId = const String.fromEnvironment('TEST_APP_ID', + defaultValue: ''); + + RtcEngine rtcEngine = await RtcEngine.createWithContext(RtcEngineContext( + engineAppId, + areaCode: [AreaCode.NA, AreaCode.GLOB], + )); + + final screenShareHelper = + await rtcEngine.getScreenShareHelper(appGroup: 'io.agora'); + + const bool enabled = true; + const EncryptionMode configEncryptionMode = EncryptionMode.None; + const String configEncryptionKey = "hello"; + const List configEncryptionKdfSalt = []; + final EncryptionConfig config = EncryptionConfig( + encryptionMode: configEncryptionMode, + encryptionKey: configEncryptionKey, + encryptionKdfSalt: configEncryptionKdfSalt, + ); + await screenShareHelper.enableEncryption( + enabled, + config, + ); + + await screenShareHelper.destroy(); + await rtcEngine.destroy(); + }, + skip: !(Platform.isMacOS || Platform.isWindows || Platform.isLinux), + ); + + testWidgets( + 'sendCustomReportMessage', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + String engineAppId = const String.fromEnvironment('TEST_APP_ID', + defaultValue: ''); + + RtcEngine rtcEngine = await RtcEngine.createWithContext(RtcEngineContext( + engineAppId, + areaCode: [AreaCode.NA, AreaCode.GLOB], + )); + + final screenShareHelper = + await rtcEngine.getScreenShareHelper(appGroup: 'io.agora'); + + const String id = "hello"; + const String category = "hello"; + const String event = "hello"; + const String label = "hello"; + const int value = 10; + await screenShareHelper.sendCustomReportMessage( + id, + category, + event, + label, + value, + ); + + await screenShareHelper.destroy(); + await rtcEngine.destroy(); + }, + skip: !(Platform.isMacOS || Platform.isWindows || Platform.isLinux), + ); + + testWidgets( + 'setAudioSessionOperationRestriction', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + String engineAppId = const String.fromEnvironment('TEST_APP_ID', + defaultValue: ''); + + RtcEngine rtcEngine = await RtcEngine.createWithContext(RtcEngineContext( + engineAppId, + areaCode: [AreaCode.NA, AreaCode.GLOB], + )); + + final screenShareHelper = + await rtcEngine.getScreenShareHelper(appGroup: 'io.agora'); + + const AudioSessionOperationRestriction restriction = + AudioSessionOperationRestriction.None; + await screenShareHelper.setAudioSessionOperationRestriction( + restriction, + ); + + await screenShareHelper.destroy(); + await rtcEngine.destroy(); + }, + skip: !(Platform.isMacOS || Platform.isWindows || Platform.isLinux), + ); + + testWidgets( + 'setAudioEffectParameters', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + String engineAppId = const String.fromEnvironment('TEST_APP_ID', + defaultValue: ''); + + RtcEngine rtcEngine = await RtcEngine.createWithContext(RtcEngineContext( + engineAppId, + areaCode: [AreaCode.NA, AreaCode.GLOB], + )); + + final screenShareHelper = + await rtcEngine.getScreenShareHelper(appGroup: 'io.agora'); + + const AudioEffectPreset preset = AudioEffectPreset.AudioEffectOff; + const int param1 = 10; + const int param2 = 10; + await screenShareHelper.setAudioEffectParameters( + preset, + param1, + param2, + ); + + await screenShareHelper.destroy(); + await rtcEngine.destroy(); + }, + skip: !(Platform.isMacOS || Platform.isWindows || Platform.isLinux), + ); + + testWidgets( + 'setAudioEffectPreset', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + String engineAppId = const String.fromEnvironment('TEST_APP_ID', + defaultValue: ''); + + RtcEngine rtcEngine = await RtcEngine.createWithContext(RtcEngineContext( + engineAppId, + areaCode: [AreaCode.NA, AreaCode.GLOB], + )); + + final screenShareHelper = + await rtcEngine.getScreenShareHelper(appGroup: 'io.agora'); + + const AudioEffectPreset preset = AudioEffectPreset.AudioEffectOff; + await screenShareHelper.setAudioEffectPreset( + preset, + ); + + await screenShareHelper.destroy(); + await rtcEngine.destroy(); + }, + skip: !(Platform.isMacOS || Platform.isWindows || Platform.isLinux), + ); + + testWidgets( + 'setVoiceBeautifierPreset', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + String engineAppId = const String.fromEnvironment('TEST_APP_ID', + defaultValue: ''); + + RtcEngine rtcEngine = await RtcEngine.createWithContext(RtcEngineContext( + engineAppId, + areaCode: [AreaCode.NA, AreaCode.GLOB], + )); + + final screenShareHelper = + await rtcEngine.getScreenShareHelper(appGroup: 'io.agora'); + + const VoiceBeautifierPreset preset = + VoiceBeautifierPreset.VoiceBeautifierOff; + await screenShareHelper.setVoiceBeautifierPreset( + preset, + ); + + await screenShareHelper.destroy(); + await rtcEngine.destroy(); + }, + skip: !(Platform.isMacOS || Platform.isWindows || Platform.isLinux), + ); + + testWidgets( + 'enableDeepLearningDenoise', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + String engineAppId = const String.fromEnvironment('TEST_APP_ID', + defaultValue: ''); + + RtcEngine rtcEngine = await RtcEngine.createWithContext(RtcEngineContext( + engineAppId, + areaCode: [AreaCode.NA, AreaCode.GLOB], + )); + + final screenShareHelper = + await rtcEngine.getScreenShareHelper(appGroup: 'io.agora'); + + const bool enable = true; + await screenShareHelper.enableDeepLearningDenoise( + enable, + ); + + await screenShareHelper.destroy(); + await rtcEngine.destroy(); + }, + skip: !(Platform.isMacOS || Platform.isWindows || Platform.isLinux), + ); + + testWidgets( + 'enableRemoteSuperResolution', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + String engineAppId = const String.fromEnvironment('TEST_APP_ID', + defaultValue: ''); + + RtcEngine rtcEngine = await RtcEngine.createWithContext(RtcEngineContext( + engineAppId, + areaCode: [AreaCode.NA, AreaCode.GLOB], + )); + + final screenShareHelper = + await rtcEngine.getScreenShareHelper(appGroup: 'io.agora'); + + const int userId = 10; + const bool enable = true; + await screenShareHelper.enableRemoteSuperResolution( + userId, + enable, + ); + + await screenShareHelper.destroy(); + await rtcEngine.destroy(); + }, + skip: !(Platform.isMacOS || Platform.isWindows || Platform.isLinux), + ); + + testWidgets( + 'setCloudProxy', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + String engineAppId = const String.fromEnvironment('TEST_APP_ID', + defaultValue: ''); + + RtcEngine rtcEngine = await RtcEngine.createWithContext(RtcEngineContext( + engineAppId, + areaCode: [AreaCode.NA, AreaCode.GLOB], + )); + + final screenShareHelper = + await rtcEngine.getScreenShareHelper(appGroup: 'io.agora'); + + const CloudProxyType proxyType = CloudProxyType.None; + await screenShareHelper.setCloudProxy( + proxyType, + ); + + await screenShareHelper.destroy(); + await rtcEngine.destroy(); + }, + skip: !(Platform.isMacOS || Platform.isWindows || Platform.isLinux), + ); + + testWidgets( + 'uploadLogFile', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + String engineAppId = const String.fromEnvironment('TEST_APP_ID', + defaultValue: ''); + + RtcEngine rtcEngine = await RtcEngine.createWithContext(RtcEngineContext( + engineAppId, + areaCode: [AreaCode.NA, AreaCode.GLOB], + )); + + final screenShareHelper = + await rtcEngine.getScreenShareHelper(appGroup: 'io.agora'); + + await screenShareHelper.uploadLogFile(); + + await screenShareHelper.destroy(); + await rtcEngine.destroy(); + }, + skip: !(Platform.isMacOS || Platform.isWindows || Platform.isLinux), + ); + + testWidgets( + 'setVoiceBeautifierParameters', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + String engineAppId = const String.fromEnvironment('TEST_APP_ID', + defaultValue: ''); + + RtcEngine rtcEngine = await RtcEngine.createWithContext(RtcEngineContext( + engineAppId, + areaCode: [AreaCode.NA, AreaCode.GLOB], + )); + + final screenShareHelper = + await rtcEngine.getScreenShareHelper(appGroup: 'io.agora'); + + const VoiceBeautifierPreset preset = + VoiceBeautifierPreset.VoiceBeautifierOff; + const int param1 = 10; + const int param2 = 10; + await screenShareHelper.setVoiceBeautifierParameters( + preset, + param1, + param2, + ); + + await screenShareHelper.destroy(); + await rtcEngine.destroy(); + }, + skip: !(Platform.isMacOS || Platform.isWindows || Platform.isLinux), + ); + + testWidgets( + 'setVoiceConversionPreset', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + String engineAppId = const String.fromEnvironment('TEST_APP_ID', + defaultValue: ''); + + RtcEngine rtcEngine = await RtcEngine.createWithContext(RtcEngineContext( + engineAppId, + areaCode: [AreaCode.NA, AreaCode.GLOB], + )); + + final screenShareHelper = + await rtcEngine.getScreenShareHelper(appGroup: 'io.agora'); + + const VoiceConversionPreset preset = VoiceConversionPreset.Off; + await screenShareHelper.setVoiceConversionPreset( + preset, + ); + + await screenShareHelper.destroy(); + await rtcEngine.destroy(); + }, + skip: !(Platform.isMacOS || Platform.isWindows || Platform.isLinux), + ); + + testWidgets( + 'pauseAllChannelMediaRelay', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + String engineAppId = const String.fromEnvironment('TEST_APP_ID', + defaultValue: ''); + + RtcEngine rtcEngine = await RtcEngine.createWithContext(RtcEngineContext( + engineAppId, + areaCode: [AreaCode.NA, AreaCode.GLOB], + )); + + final screenShareHelper = + await rtcEngine.getScreenShareHelper(appGroup: 'io.agora'); + + await screenShareHelper.pauseAllChannelMediaRelay(); + + await screenShareHelper.destroy(); + await rtcEngine.destroy(); + }, + skip: !(Platform.isMacOS || Platform.isWindows || Platform.isLinux), + ); + + testWidgets( + 'resumeAllChannelMediaRelay', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + String engineAppId = const String.fromEnvironment('TEST_APP_ID', + defaultValue: ''); + + RtcEngine rtcEngine = await RtcEngine.createWithContext(RtcEngineContext( + engineAppId, + areaCode: [AreaCode.NA, AreaCode.GLOB], + )); + + final screenShareHelper = + await rtcEngine.getScreenShareHelper(appGroup: 'io.agora'); + + await screenShareHelper.resumeAllChannelMediaRelay(); + + await screenShareHelper.destroy(); + await rtcEngine.destroy(); + }, + skip: !(Platform.isMacOS || Platform.isWindows || Platform.isLinux), + ); + + testWidgets( + 'setLocalAccessPoint', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + String engineAppId = const String.fromEnvironment('TEST_APP_ID', + defaultValue: ''); + + RtcEngine rtcEngine = await RtcEngine.createWithContext(RtcEngineContext( + engineAppId, + areaCode: [AreaCode.NA, AreaCode.GLOB], + )); + + final screenShareHelper = + await rtcEngine.getScreenShareHelper(appGroup: 'io.agora'); + + const List ips = []; + const String domain = "hello"; + await screenShareHelper.setLocalAccessPoint( + ips, + domain, + ); + + await screenShareHelper.destroy(); + await rtcEngine.destroy(); + }, + skip: !(Platform.isMacOS || Platform.isWindows || Platform.isLinux), + ); + + testWidgets( + 'setScreenCaptureContentHint', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + String engineAppId = const String.fromEnvironment('TEST_APP_ID', + defaultValue: ''); + + RtcEngine rtcEngine = await RtcEngine.createWithContext(RtcEngineContext( + engineAppId, + areaCode: [AreaCode.NA, AreaCode.GLOB], + )); + + final screenShareHelper = + await rtcEngine.getScreenShareHelper(appGroup: 'io.agora'); + + const VideoContentHint contentHint = VideoContentHint.None; + await screenShareHelper.setScreenCaptureContentHint( + contentHint, + ); + + await screenShareHelper.destroy(); + await rtcEngine.destroy(); + }, + skip: !(Platform.isMacOS || Platform.isWindows || Platform.isLinux), + ); + + testWidgets( + 'startScreenCaptureByDisplayId', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + String engineAppId = const String.fromEnvironment('TEST_APP_ID', + defaultValue: ''); + + RtcEngine rtcEngine = await RtcEngine.createWithContext(RtcEngineContext( + engineAppId, + areaCode: [AreaCode.NA, AreaCode.GLOB], + )); + + final screenShareHelper = + await rtcEngine.getScreenShareHelper(appGroup: 'io.agora'); + + const int displayId = 10; + const int regionRectX = 10; + const int regionRectY = 10; + const int regionRectWidth = 10; + const int regionRectHeight = 10; + final Rectangle regionRect = Rectangle( + x: regionRectX, + y: regionRectY, + width: regionRectWidth, + height: regionRectHeight, + ); + const int dimensionsWidth = 10; + const int dimensionsHeight = 10; + final VideoDimensions captureParamsDimensions = VideoDimensions( + width: dimensionsWidth, + height: dimensionsHeight, + ); + const int captureParamsFrameRate = 10; + const int captureParamsBitrate = 10; + const bool captureParamsCaptureMouseCursor = true; + const bool captureParamsWindowFocus = true; + const List captureParamsExcludeWindowList = []; + final ScreenCaptureParameters captureParams = ScreenCaptureParameters( + dimensions: captureParamsDimensions, + frameRate: captureParamsFrameRate, + bitrate: captureParamsBitrate, + captureMouseCursor: captureParamsCaptureMouseCursor, + windowFocus: captureParamsWindowFocus, + excludeWindowList: captureParamsExcludeWindowList, + ); + await screenShareHelper.startScreenCaptureByDisplayId( + displayId, + regionRect, + captureParams, + ); + + await screenShareHelper.destroy(); + await rtcEngine.destroy(); + }, + skip: !(Platform.isMacOS || Platform.isWindows || Platform.isLinux), + ); + + testWidgets( + 'startScreenCaptureByScreenRect', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + String engineAppId = const String.fromEnvironment('TEST_APP_ID', + defaultValue: ''); + + RtcEngine rtcEngine = await RtcEngine.createWithContext(RtcEngineContext( + engineAppId, + areaCode: [AreaCode.NA, AreaCode.GLOB], + )); + + final screenShareHelper = + await rtcEngine.getScreenShareHelper(appGroup: 'io.agora'); + + const int screenRectX = 10; + const int screenRectY = 10; + const int screenRectWidth = 10; + const int screenRectHeight = 10; + final Rectangle screenRect = Rectangle( + x: screenRectX, + y: screenRectY, + width: screenRectWidth, + height: screenRectHeight, + ); + const int regionRectX = 10; + const int regionRectY = 10; + const int regionRectWidth = 10; + const int regionRectHeight = 10; + final Rectangle regionRect = Rectangle( + x: regionRectX, + y: regionRectY, + width: regionRectWidth, + height: regionRectHeight, + ); + const int dimensionsWidth = 10; + const int dimensionsHeight = 10; + final VideoDimensions captureParamsDimensions = VideoDimensions( + width: dimensionsWidth, + height: dimensionsHeight, + ); + const int captureParamsFrameRate = 10; + const int captureParamsBitrate = 10; + const bool captureParamsCaptureMouseCursor = true; + const bool captureParamsWindowFocus = true; + const List captureParamsExcludeWindowList = []; + final ScreenCaptureParameters captureParams = ScreenCaptureParameters( + dimensions: captureParamsDimensions, + frameRate: captureParamsFrameRate, + bitrate: captureParamsBitrate, + captureMouseCursor: captureParamsCaptureMouseCursor, + windowFocus: captureParamsWindowFocus, + excludeWindowList: captureParamsExcludeWindowList, + ); + await screenShareHelper.startScreenCaptureByScreenRect( + screenRect, + regionRect, + captureParams, + ); + + await screenShareHelper.destroy(); + await rtcEngine.destroy(); + }, + skip: !(Platform.isMacOS || Platform.isWindows || Platform.isLinux), + ); + + testWidgets( + 'startScreenCaptureByWindowId', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + String engineAppId = const String.fromEnvironment('TEST_APP_ID', + defaultValue: ''); + + RtcEngine rtcEngine = await RtcEngine.createWithContext(RtcEngineContext( + engineAppId, + areaCode: [AreaCode.NA, AreaCode.GLOB], + )); + + final screenShareHelper = + await rtcEngine.getScreenShareHelper(appGroup: 'io.agora'); + + const int windowId = 10; + const int regionRectX = 10; + const int regionRectY = 10; + const int regionRectWidth = 10; + const int regionRectHeight = 10; + final Rectangle regionRect = Rectangle( + x: regionRectX, + y: regionRectY, + width: regionRectWidth, + height: regionRectHeight, + ); + const int dimensionsWidth = 10; + const int dimensionsHeight = 10; + final VideoDimensions captureParamsDimensions = VideoDimensions( + width: dimensionsWidth, + height: dimensionsHeight, + ); + const int captureParamsFrameRate = 10; + const int captureParamsBitrate = 10; + const bool captureParamsCaptureMouseCursor = true; + const bool captureParamsWindowFocus = true; + const List captureParamsExcludeWindowList = []; + final ScreenCaptureParameters captureParams = ScreenCaptureParameters( + dimensions: captureParamsDimensions, + frameRate: captureParamsFrameRate, + bitrate: captureParamsBitrate, + captureMouseCursor: captureParamsCaptureMouseCursor, + windowFocus: captureParamsWindowFocus, + excludeWindowList: captureParamsExcludeWindowList, + ); + await screenShareHelper.startScreenCaptureByWindowId( + windowId, + regionRect, + captureParams, + ); + + await screenShareHelper.destroy(); + await rtcEngine.destroy(); + }, + skip: !(Platform.isMacOS || Platform.isWindows || Platform.isLinux), + ); + + testWidgets( + 'stopScreenCapture', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + String engineAppId = const String.fromEnvironment('TEST_APP_ID', + defaultValue: ''); + + RtcEngine rtcEngine = await RtcEngine.createWithContext(RtcEngineContext( + engineAppId, + areaCode: [AreaCode.NA, AreaCode.GLOB], + )); + + final screenShareHelper = + await rtcEngine.getScreenShareHelper(appGroup: 'io.agora'); + + await screenShareHelper.stopScreenCapture(); + + await screenShareHelper.destroy(); + await rtcEngine.destroy(); + }, + skip: !(Platform.isMacOS || Platform.isWindows || Platform.isLinux), + ); + + testWidgets( + 'updateScreenCaptureParameters', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + String engineAppId = const String.fromEnvironment('TEST_APP_ID', + defaultValue: ''); + + RtcEngine rtcEngine = await RtcEngine.createWithContext(RtcEngineContext( + engineAppId, + areaCode: [AreaCode.NA, AreaCode.GLOB], + )); + + final screenShareHelper = + await rtcEngine.getScreenShareHelper(appGroup: 'io.agora'); + + const int dimensionsWidth = 10; + const int dimensionsHeight = 10; + final VideoDimensions captureParamsDimensions = VideoDimensions( + width: dimensionsWidth, + height: dimensionsHeight, + ); + const int captureParamsFrameRate = 10; + const int captureParamsBitrate = 10; + const bool captureParamsCaptureMouseCursor = true; + const bool captureParamsWindowFocus = true; + const List captureParamsExcludeWindowList = []; + final ScreenCaptureParameters captureParams = ScreenCaptureParameters( + dimensions: captureParamsDimensions, + frameRate: captureParamsFrameRate, + bitrate: captureParamsBitrate, + captureMouseCursor: captureParamsCaptureMouseCursor, + windowFocus: captureParamsWindowFocus, + excludeWindowList: captureParamsExcludeWindowList, + ); + await screenShareHelper.updateScreenCaptureParameters( + captureParams, + ); + + await screenShareHelper.destroy(); + await rtcEngine.destroy(); + }, + skip: !(Platform.isMacOS || Platform.isWindows || Platform.isLinux), + ); + + testWidgets( + 'updateScreenCaptureRegion', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + String engineAppId = const String.fromEnvironment('TEST_APP_ID', + defaultValue: ''); + + RtcEngine rtcEngine = await RtcEngine.createWithContext(RtcEngineContext( + engineAppId, + areaCode: [AreaCode.NA, AreaCode.GLOB], + )); + + final screenShareHelper = + await rtcEngine.getScreenShareHelper(appGroup: 'io.agora'); + + const int regionRectX = 10; + const int regionRectY = 10; + const int regionRectWidth = 10; + const int regionRectHeight = 10; + final Rectangle regionRect = Rectangle( + x: regionRectX, + y: regionRectY, + width: regionRectWidth, + height: regionRectHeight, + ); + await screenShareHelper.updateScreenCaptureRegion( + regionRect, + ); + + await screenShareHelper.destroy(); + await rtcEngine.destroy(); + }, + skip: !(Platform.isMacOS || Platform.isWindows || Platform.isLinux), + ); + + testWidgets( + 'startScreenCapture', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + String engineAppId = const String.fromEnvironment('TEST_APP_ID', + defaultValue: ''); + + RtcEngine rtcEngine = await RtcEngine.createWithContext(RtcEngineContext( + engineAppId, + areaCode: [AreaCode.NA, AreaCode.GLOB], + )); + + final screenShareHelper = + await rtcEngine.getScreenShareHelper(appGroup: 'io.agora'); + + const int windowId = 10; + const int captureFreq = 10; + const int rectX = 10; + const int rectY = 10; + const int rectWidth = 10; + const int rectHeight = 10; + const int rectLeft = 10; + const int rectTop = 10; + const int rectRight = 10; + const int rectBottom = 10; + final Rect rect = Rect( + x: rectX, + y: rectY, + width: rectWidth, + height: rectHeight, + left: rectLeft, + top: rectTop, + right: rectRight, + bottom: rectBottom, + ); + const int bitrate = 10; + await screenShareHelper.startScreenCapture( + windowId, + captureFreq, + rect, + bitrate, + ); + + await screenShareHelper.destroy(); + await rtcEngine.destroy(); + }, + skip: !(Platform.isMacOS || Platform.isWindows || Platform.isLinux), + ); +} diff --git a/integration_test_app/integration_test/rtc_engine_plugin_test.dart b/integration_test_app/integration_test/rtc_engine_plugin_test.dart new file mode 100644 index 000000000..bac9bfd1d --- /dev/null +++ b/integration_test_app/integration_test/rtc_engine_plugin_test.dart @@ -0,0 +1,86 @@ +import 'dart:io'; + +import 'package:agora_rtc_engine/rtc_engine.dart'; +import 'package:flutter/services.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:integration_test/integration_test.dart'; +import 'package:integration_test_app/main.dart' as app; + +void main() { + IntegrationTestWidgetsFlutterBinding.ensureInitialized(); + + const MethodChannel methodChannel = + MethodChannel('agora_rtc_engine/integration_test/rtc_engine_plugin'); + + testWidgets( + 'RtcEnginePlugin callbacks called', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + String engineAppId = const String.fromEnvironment('TEST_APP_ID', + defaultValue: ''); + + final context = RtcEngineContext( + engineAppId, + areaCode: const [AreaCode.GLOB], + ); + + await methodChannel.invokeMethod('registerRtcEnginePlugin'); + + final rtcEngine = await RtcEngine.createWithContext(context); + + final isRtcEngineCreated = + await methodChannel.invokeMethod('isRtcEngineCreated'); + expect(isRtcEngineCreated, isTrue); + + final rtcEngineNativeHandleFromPlugin = await methodChannel + .invokeMethod('getRtcEngineNativeHandleFromPlugin'); + + final rtcEngineNativeHandle = await rtcEngine.getNativeHandle(); + expect(rtcEngineNativeHandle == rtcEngineNativeHandleFromPlugin, isTrue); + + await rtcEngine.destroy(); + + final isRtcEngineDestroyed = + await methodChannel.invokeMethod('isRtcEngineDestroyed'); + + expect(isRtcEngineDestroyed, isTrue); + + await methodChannel.invokeMethod('unregisterRtcEnginePlugin'); + }, + skip: !(Platform.isAndroid || Platform.isIOS), + ); + + testWidgets( + 'should not call RtcEnginePlugin callbacks after unregister', + (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + String engineAppId = const String.fromEnvironment('TEST_APP_ID', + defaultValue: ''); + + final context = RtcEngineContext( + engineAppId, + areaCode: const [AreaCode.GLOB], + ); + + await methodChannel.invokeMethod('registerRtcEnginePlugin'); + await methodChannel.invokeMethod('unregisterRtcEnginePlugin'); + + final rtcEngine = await RtcEngine.createWithContext(context); + final isRtcEngineCreated = + await methodChannel.invokeMethod('isRtcEngineCreated'); + expect(isRtcEngineCreated, isFalse); + + await rtcEngine.destroy(); + + final isRtcEngineDestroyed = + await methodChannel.invokeMethod('isRtcEngineDestroyed'); + + expect(isRtcEngineDestroyed, isFalse); + }, + skip: !(Platform.isAndroid || Platform.isIOS), + ); +} diff --git a/integration_test_app/ios/.gitignore b/integration_test_app/ios/.gitignore new file mode 100644 index 000000000..151026b91 --- /dev/null +++ b/integration_test_app/ios/.gitignore @@ -0,0 +1,33 @@ +*.mode1v3 +*.mode2v3 +*.moved-aside +*.pbxuser +*.perspectivev3 +**/*sync/ +.sconsign.dblite +.tags* +**/.vagrant/ +**/DerivedData/ +Icon? +**/Pods/ +**/.symlinks/ +profile +xcuserdata +**/.generated/ +Flutter/App.framework +Flutter/Flutter.framework +Flutter/Flutter.podspec +Flutter/Generated.xcconfig +Flutter/ephemeral/ +Flutter/app.flx +Flutter/app.zip +Flutter/flutter_assets/ +Flutter/flutter_export_environment.sh +ServiceDefinitions.json +Runner/GeneratedPluginRegistrant.* + +# Exceptions to above rules. +!default.mode1v3 +!default.mode2v3 +!default.pbxuser +!default.perspectivev3 diff --git a/integration_test_app/ios/Flutter/AppFrameworkInfo.plist b/integration_test_app/ios/Flutter/AppFrameworkInfo.plist new file mode 100644 index 000000000..8d4492f97 --- /dev/null +++ b/integration_test_app/ios/Flutter/AppFrameworkInfo.plist @@ -0,0 +1,26 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + App + CFBundleIdentifier + io.flutter.flutter.app + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + App + CFBundlePackageType + FMWK + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1.0 + MinimumOSVersion + 9.0 + + diff --git a/integration_test_app/ios/Flutter/Debug.xcconfig b/integration_test_app/ios/Flutter/Debug.xcconfig new file mode 100644 index 000000000..ec97fc6f3 --- /dev/null +++ b/integration_test_app/ios/Flutter/Debug.xcconfig @@ -0,0 +1,2 @@ +#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig" +#include "Generated.xcconfig" diff --git a/integration_test_app/ios/Flutter/Release.xcconfig b/integration_test_app/ios/Flutter/Release.xcconfig new file mode 100644 index 000000000..c4855bfe2 --- /dev/null +++ b/integration_test_app/ios/Flutter/Release.xcconfig @@ -0,0 +1,2 @@ +#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig" +#include "Generated.xcconfig" diff --git a/integration_test_app/ios/Podfile b/integration_test_app/ios/Podfile new file mode 100644 index 000000000..37b65e893 --- /dev/null +++ b/integration_test_app/ios/Podfile @@ -0,0 +1,51 @@ +# Uncomment this line to define a global platform for your project +# platform :ios, '9.0' + +# CocoaPods analytics sends network stats synchronously affecting flutter build latency. +ENV['COCOAPODS_DISABLE_STATS'] = 'true' + +project 'Runner', { + 'Debug' => :debug, + 'Profile' => :release, + 'Release' => :release, +} + +def flutter_root + generated_xcode_build_settings_path = File.expand_path(File.join('..', 'Flutter', 'Generated.xcconfig'), __FILE__) + unless File.exist?(generated_xcode_build_settings_path) + raise "#{generated_xcode_build_settings_path} must exist. If you're running pod install manually, make sure flutter pub get is executed first" + end + + File.foreach(generated_xcode_build_settings_path) do |line| + matches = line.match(/FLUTTER_ROOT\=(.*)/) + return matches[1].strip if matches + end + raise "FLUTTER_ROOT not found in #{generated_xcode_build_settings_path}. Try deleting Generated.xcconfig, then run flutter pub get" +end + +require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root) + +flutter_ios_podfile_setup + +target 'Runner' do + use_frameworks! + use_modular_headers! + + flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__)) + +# pod 'AgoraRtcWrapper', :path => File.join('.symlinks', 'plugins', 'agora_rtc_engine', 'ios') + + pod 'iris_integration_test', :path => File.join('Runner') +end + +post_install do |installer| + installer.pods_project.targets.each do |target| + flutter_additional_ios_build_settings(target) + # Temporary exclude arm64 to allow run integration test on simulator + # https://developer.apple.com/forums/thread/656509 + target.build_configurations.each do |config| + config.build_settings['ONLY_ACTIVE_ARCH'] = 'YES' + config.build_settings["EXCLUDED_ARCHS[sdk=iphonesimulator*]"] = "i386 arm64" + end + end +end diff --git a/integration_test_app/ios/Runner.xcodeproj/project.pbxproj b/integration_test_app/ios/Runner.xcodeproj/project.pbxproj new file mode 100644 index 000000000..f0db7d76f --- /dev/null +++ b/integration_test_app/ios/Runner.xcodeproj/project.pbxproj @@ -0,0 +1,557 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 51; + objects = { + +/* Begin PBXBuildFile section */ + 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; }; + 2E9FC2DDC679AFFB2777E76B /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 5F9179ECA94BD538060DB477 /* Pods_Runner.framework */; }; + 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; }; + 71E4E3A22799532F00995B98 /* TestRtcEnginePlugin.h in Sources */ = {isa = PBXBuildFile; fileRef = 71E4E3A12799532F00995B98 /* TestRtcEnginePlugin.h */; }; + 71E4E3A42799551500995B98 /* TestRtcEnginePlugin.m in Sources */ = {isa = PBXBuildFile; fileRef = 71E4E3A32799551500995B98 /* TestRtcEnginePlugin.m */; }; + 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; }; + 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; }; + 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; }; + 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; }; +/* End PBXBuildFile section */ + +/* Begin PBXCopyFilesBuildPhase section */ + 9705A1C41CF9048500538489 /* Embed Frameworks */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = ""; + dstSubfolderSpec = 10; + files = ( + ); + name = "Embed Frameworks"; + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXCopyFilesBuildPhase section */ + +/* Begin PBXFileReference section */ + 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = ""; }; + 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = ""; }; + 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = ""; }; + 5F9179ECA94BD538060DB477 /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 71E4E3A12799532F00995B98 /* TestRtcEnginePlugin.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = TestRtcEnginePlugin.h; sourceTree = ""; }; + 71E4E3A32799551500995B98 /* TestRtcEnginePlugin.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = TestRtcEnginePlugin.m; sourceTree = ""; }; + 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = ""; }; + 74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; + 7A047A870FD831349AAC6657 /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = ""; }; + 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = ""; }; + 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = ""; }; + 9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = ""; }; + 97C146EE1CF9000F007C117D /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 97C146FB1CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; + 97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; + 97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; + 97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 9BD580314D3C72C45A778A8E /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = ""; }; + EFD2E945A055B0D898822577 /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 97C146EB1CF9000F007C117D /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 2E9FC2DDC679AFFB2777E76B /* Pods_Runner.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 4593D6CAA56A8C9187DAEA4C /* Frameworks */ = { + isa = PBXGroup; + children = ( + 5F9179ECA94BD538060DB477 /* Pods_Runner.framework */, + ); + name = Frameworks; + sourceTree = ""; + }; + 9740EEB11CF90186004384FC /* Flutter */ = { + isa = PBXGroup; + children = ( + 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */, + 9740EEB21CF90195004384FC /* Debug.xcconfig */, + 7AFA3C8E1D35360C0083082E /* Release.xcconfig */, + 9740EEB31CF90195004384FC /* Generated.xcconfig */, + ); + name = Flutter; + sourceTree = ""; + }; + 97C146E51CF9000F007C117D = { + isa = PBXGroup; + children = ( + 9740EEB11CF90186004384FC /* Flutter */, + 97C146F01CF9000F007C117D /* Runner */, + 97C146EF1CF9000F007C117D /* Products */, + B8B83F9ED5653BABF12F23A6 /* Pods */, + 4593D6CAA56A8C9187DAEA4C /* Frameworks */, + ); + sourceTree = ""; + }; + 97C146EF1CF9000F007C117D /* Products */ = { + isa = PBXGroup; + children = ( + 97C146EE1CF9000F007C117D /* Runner.app */, + ); + name = Products; + sourceTree = ""; + }; + 97C146F01CF9000F007C117D /* Runner */ = { + isa = PBXGroup; + children = ( + 97C146FA1CF9000F007C117D /* Main.storyboard */, + 97C146FD1CF9000F007C117D /* Assets.xcassets */, + 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */, + 97C147021CF9000F007C117D /* Info.plist */, + 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */, + 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */, + 74858FAE1ED2DC5600515810 /* AppDelegate.swift */, + 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */, + 71E4E3A12799532F00995B98 /* TestRtcEnginePlugin.h */, + 71E4E3A32799551500995B98 /* TestRtcEnginePlugin.m */, + ); + path = Runner; + sourceTree = ""; + }; + B8B83F9ED5653BABF12F23A6 /* Pods */ = { + isa = PBXGroup; + children = ( + 9BD580314D3C72C45A778A8E /* Pods-Runner.debug.xcconfig */, + 7A047A870FD831349AAC6657 /* Pods-Runner.release.xcconfig */, + EFD2E945A055B0D898822577 /* Pods-Runner.profile.xcconfig */, + ); + path = Pods; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 97C146ED1CF9000F007C117D /* Runner */ = { + isa = PBXNativeTarget; + buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */; + buildPhases = ( + B70B96731F115CB39361F26E /* [CP] Check Pods Manifest.lock */, + 9740EEB61CF901F6004384FC /* Run Script */, + 97C146EA1CF9000F007C117D /* Sources */, + 97C146EB1CF9000F007C117D /* Frameworks */, + 97C146EC1CF9000F007C117D /* Resources */, + 9705A1C41CF9048500538489 /* Embed Frameworks */, + 3B06AD1E1E4923F5004D2608 /* Thin Binary */, + 9A05C78F37F1C41D3D9E9EA6 /* [CP] Embed Pods Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = Runner; + productName = Runner; + productReference = 97C146EE1CF9000F007C117D /* Runner.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 97C146E61CF9000F007C117D /* Project object */ = { + isa = PBXProject; + attributes = { + LastUpgradeCheck = 1300; + ORGANIZATIONNAME = ""; + TargetAttributes = { + 97C146ED1CF9000F007C117D = { + CreatedOnToolsVersion = 7.3.1; + LastSwiftMigration = 1100; + }; + }; + }; + buildConfigurationList = 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */; + compatibilityVersion = "Xcode 9.3"; + developmentRegion = en; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 97C146E51CF9000F007C117D; + productRefGroup = 97C146EF1CF9000F007C117D /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 97C146ED1CF9000F007C117D /* Runner */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 97C146EC1CF9000F007C117D /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */, + 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */, + 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */, + 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXShellScriptBuildPhase section */ + 3B06AD1E1E4923F5004D2608 /* Thin Binary */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + name = "Thin Binary"; + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" embed_and_thin"; + }; + 9740EEB61CF901F6004384FC /* Run Script */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + name = "Run Script"; + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build"; + }; + 9A05C78F37F1C41D3D9E9EA6 /* [CP] Embed Pods Frameworks */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-input-files.xcfilelist", + ); + name = "[CP] Embed Pods Frameworks"; + outputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-output-files.xcfilelist", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n"; + showEnvVarsInLog = 0; + }; + B70B96731F115CB39361F26E /* [CP] Check Pods Manifest.lock */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", + ); + name = "[CP] Check Pods Manifest.lock"; + outputFileListPaths = ( + ); + outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; + showEnvVarsInLog = 0; + }; +/* End PBXShellScriptBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 97C146EA1CF9000F007C117D /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */, + 71E4E3A22799532F00995B98 /* TestRtcEnginePlugin.h in Sources */, + 71E4E3A42799551500995B98 /* TestRtcEnginePlugin.m in Sources */, + 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXVariantGroup section */ + 97C146FA1CF9000F007C117D /* Main.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 97C146FB1CF9000F007C117D /* Base */, + ); + name = Main.storyboard; + sourceTree = ""; + }; + 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 97C147001CF9000F007C117D /* Base */, + ); + name = LaunchScreen.storyboard; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + 249021D3217E4FDB00AE95B9 /* Profile */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 9.0; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = iphoneos; + SUPPORTED_PLATFORMS = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + }; + name = Profile; + }; + 249021D4217E4FDB00AE95B9 /* Profile */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; + ENABLE_BITCODE = NO; + INFOPLIST_FILE = Runner/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = io.agora.integrationtestapp.integrationTestApp; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; + SWIFT_VERSION = 5.0; + VERSIONING_SYSTEM = "apple-generic"; + }; + name = Profile; + }; + 97C147031CF9000F007C117D /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 9.0; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + 97C147041CF9000F007C117D /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 9.0; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = iphoneos; + SUPPORTED_PLATFORMS = iphoneos; + SWIFT_COMPILATION_MODE = wholemodule; + SWIFT_OPTIMIZATION_LEVEL = "-O"; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + 97C147061CF9000F007C117D /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; + ENABLE_BITCODE = NO; + "EXCLUDED_ARCHS[sdk=iphonesimulator*]" = "i386 arm64"; + INFOPLIST_FILE = Runner/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = io.agora.integrationtestapp.integrationTestApp; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 5.0; + VERSIONING_SYSTEM = "apple-generic"; + }; + name = Debug; + }; + 97C147071CF9000F007C117D /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; + ENABLE_BITCODE = NO; + INFOPLIST_FILE = Runner/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = io.agora.integrationtestapp.integrationTestApp; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; + SWIFT_VERSION = 5.0; + VERSIONING_SYSTEM = "apple-generic"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 97C147031CF9000F007C117D /* Debug */, + 97C147041CF9000F007C117D /* Release */, + 249021D3217E4FDB00AE95B9 /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 97C147061CF9000F007C117D /* Debug */, + 97C147071CF9000F007C117D /* Release */, + 249021D4217E4FDB00AE95B9 /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 97C146E61CF9000F007C117D /* Project object */; +} diff --git a/integration_test_app/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/integration_test_app/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 000000000..919434a62 --- /dev/null +++ b/integration_test_app/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/integration_test_app/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/integration_test_app/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 000000000..18d981003 --- /dev/null +++ b/integration_test_app/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/integration_test_app/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings b/integration_test_app/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings new file mode 100644 index 000000000..f9b0d7c5e --- /dev/null +++ b/integration_test_app/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings @@ -0,0 +1,8 @@ + + + + + PreviewsEnabled + + + diff --git a/integration_test_app/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/integration_test_app/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme new file mode 100644 index 000000000..3db53b6e1 --- /dev/null +++ b/integration_test_app/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme @@ -0,0 +1,91 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/integration_test_app/ios/Runner.xcworkspace/contents.xcworkspacedata b/integration_test_app/ios/Runner.xcworkspace/contents.xcworkspacedata new file mode 100644 index 000000000..21a3cc14c --- /dev/null +++ b/integration_test_app/ios/Runner.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,10 @@ + + + + + + + diff --git a/integration_test_app/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/integration_test_app/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 000000000..18d981003 --- /dev/null +++ b/integration_test_app/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/integration_test_app/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings b/integration_test_app/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings new file mode 100644 index 000000000..f9b0d7c5e --- /dev/null +++ b/integration_test_app/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings @@ -0,0 +1,8 @@ + + + + + PreviewsEnabled + + + diff --git a/integration_test_app/ios/Runner/AppDelegate.swift b/integration_test_app/ios/Runner/AppDelegate.swift new file mode 100644 index 000000000..737f8f5fc --- /dev/null +++ b/integration_test_app/ios/Runner/AppDelegate.swift @@ -0,0 +1,16 @@ +import UIKit +import Flutter + +@UIApplicationMain +@objc class AppDelegate: FlutterAppDelegate { + override func application( + _ application: UIApplication, + didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? + ) -> Bool { + GeneratedPluginRegistrant.register(with: self) + let controller : FlutterViewController = window?.rootViewController as! FlutterViewController + TestRtcEnginePluginMethodChannel().setUp(controller.binaryMessenger) + + return super.application(application, didFinishLaunchingWithOptions: launchOptions) + } +} diff --git a/integration_test_app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json b/integration_test_app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 000000000..d36b1fab2 --- /dev/null +++ b/integration_test_app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,122 @@ +{ + "images" : [ + { + "size" : "20x20", + "idiom" : "iphone", + "filename" : "Icon-App-20x20@2x.png", + "scale" : "2x" + }, + { + "size" : "20x20", + "idiom" : "iphone", + "filename" : "Icon-App-20x20@3x.png", + "scale" : "3x" + }, + { + "size" : "29x29", + "idiom" : "iphone", + "filename" : "Icon-App-29x29@1x.png", + "scale" : "1x" + }, + { + "size" : "29x29", + "idiom" : "iphone", + "filename" : "Icon-App-29x29@2x.png", + "scale" : "2x" + }, + { + "size" : "29x29", + "idiom" : "iphone", + "filename" : "Icon-App-29x29@3x.png", + "scale" : "3x" + }, + { + "size" : "40x40", + "idiom" : "iphone", + "filename" : "Icon-App-40x40@2x.png", + "scale" : "2x" + }, + { + "size" : "40x40", + "idiom" : "iphone", + "filename" : "Icon-App-40x40@3x.png", + "scale" : "3x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "Icon-App-60x60@2x.png", + "scale" : "2x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "Icon-App-60x60@3x.png", + "scale" : "3x" + }, + { + "size" : "20x20", + "idiom" : "ipad", + "filename" : "Icon-App-20x20@1x.png", + "scale" : "1x" + }, + { + "size" : "20x20", + "idiom" : "ipad", + "filename" : "Icon-App-20x20@2x.png", + "scale" : "2x" + }, + { + "size" : "29x29", + "idiom" : "ipad", + "filename" : "Icon-App-29x29@1x.png", + "scale" : "1x" + }, + { + "size" : "29x29", + "idiom" : "ipad", + "filename" : "Icon-App-29x29@2x.png", + "scale" : "2x" + }, + { + "size" : "40x40", + "idiom" : "ipad", + "filename" : "Icon-App-40x40@1x.png", + "scale" : "1x" + }, + { + "size" : "40x40", + "idiom" : "ipad", + "filename" : "Icon-App-40x40@2x.png", + "scale" : "2x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "Icon-App-76x76@1x.png", + "scale" : "1x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "Icon-App-76x76@2x.png", + "scale" : "2x" + }, + { + "size" : "83.5x83.5", + "idiom" : "ipad", + "filename" : "Icon-App-83.5x83.5@2x.png", + "scale" : "2x" + }, + { + "size" : "1024x1024", + "idiom" : "ios-marketing", + "filename" : "Icon-App-1024x1024@1x.png", + "scale" : "1x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} diff --git a/integration_test_app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png b/integration_test_app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png new file mode 100644 index 0000000000000000000000000000000000000000..dc9ada4725e9b0ddb1deab583e5b5102493aa332 GIT binary patch literal 10932 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 literal 0 HcmV?d00001 diff --git a/integration_test_app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png b/integration_test_app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png new file mode 100644 index 0000000000000000000000000000000000000000..f091b6b0bca859a3f474b03065bef75ba58a9e4c GIT binary patch literal 1588 zcmV-42Fv-0P)C1SqPt}wig>|5Crh^=oyX$BK<}M8eLU3e2hGT;=G|!_SP)7zNI6fqUMB=)y zRAZ>eDe#*r`yDAVgB_R*LB*MAc)8(b{g{9McCXW!lq7r(btRoB9!8B-#AI6JMb~YFBEvdsV)`mEQO^&#eRKx@b&x- z5lZm*!WfD8oCLzfHGz#u7sT0^VLMI1MqGxF^v+`4YYnVYgk*=kU?HsSz{v({E3lb9 z>+xILjBN)t6`=g~IBOelGQ(O990@BfXf(DRI5I$qN$0Gkz-FSc$3a+2fX$AedL4u{ z4V+5Ong(9LiGcIKW?_352sR;LtDPmPJXI{YtT=O8=76o9;*n%_m|xo!i>7$IrZ-{l z-x3`7M}qzHsPV@$v#>H-TpjDh2UE$9g6sysUREDy_R(a)>=eHw-WAyfIN z*qb!_hW>G)Tu8nSw9yn#3wFMiLcfc4pY0ek1}8(NqkBR@t4{~oC>ryc-h_ByH(Cg5 z>ao-}771+xE3um9lWAY1FeQFxowa1(!J(;Jg*wrg!=6FdRX+t_<%z&d&?|Bn){>zm zZQj(aA_HeBY&OC^jj*)N`8fa^ePOU72VpInJoI1?`ty#lvlNzs(&MZX+R%2xS~5Kh zX*|AU4QE#~SgPzOXe9>tRj>hjU@c1k5Y_mW*Jp3fI;)1&g3j|zDgC+}2Q_v%YfDax z!?umcN^n}KYQ|a$Lr+51Nf9dkkYFSjZZjkma$0KOj+;aQ&721~t7QUKx61J3(P4P1 zstI~7-wOACnWP4=8oGOwz%vNDqD8w&Q`qcNGGrbbf&0s9L0De{4{mRS?o0MU+nR_! zrvshUau0G^DeMhM_v{5BuLjb#Hh@r23lDAk8oF(C+P0rsBpv85EP>4CVMx#04MOfG z;P%vktHcXwTj~+IE(~px)3*MY77e}p#|c>TD?sMatC0Tu4iKKJ0(X8jxQY*gYtxsC z(zYC$g|@+I+kY;dg_dE>scBf&bP1Nc@Hz<3R)V`=AGkc;8CXqdi=B4l2k|g;2%#m& z*jfX^%b!A8#bI!j9-0Fi0bOXl(-c^AB9|nQaE`*)Hw+o&jS9@7&Gov#HbD~#d{twV zXd^Tr^mWLfFh$@Dr$e;PBEz4(-2q1FF0}c;~B5sA}+Q>TOoP+t>wf)V9Iy=5ruQa;z)y zI9C9*oUga6=hxw6QasLPnee@3^Rr*M{CdaL5=R41nLs(AHk_=Y+A9$2&H(B7!_pURs&8aNw7?`&Z&xY_Ye z)~D5Bog^td-^QbUtkTirdyK^mTHAOuptDflut!#^lnKqU md>ggs(5nOWAqO?umG&QVYK#ibz}*4>0000U6E9hRK9^#O7(mu>ETqrXGsduA8$)?`v2seloOCza43C{NQ$$gAOH**MCn0Q?+L7dl7qnbRdqZ8LSVp1ItDxhxD?t@5_yHg6A8yI zC*%Wgg22K|8E#!~cTNYR~@Y9KepMPrrB8cABapAFa=`H+UGhkXUZV1GnwR1*lPyZ;*K(i~2gp|@bzp8}og7e*#% zEnr|^CWdVV!-4*Y_7rFvlww2Ze+>j*!Z!pQ?2l->4q#nqRu9`ELo6RMS5=br47g_X zRw}P9a7RRYQ%2Vsd0Me{_(EggTnuN6j=-?uFS6j^u69elMypu?t>op*wBx<=Wx8?( ztpe^(fwM6jJX7M-l*k3kEpWOl_Vk3@(_w4oc}4YF4|Rt=2V^XU?#Yz`8(e?aZ@#li0n*=g^qOcVpd-Wbok=@b#Yw zqn8u9a)z>l(1kEaPYZ6hwubN6i<8QHgsu0oE) ziJ(p;Wxm>sf!K+cw>R-(^Y2_bahB+&KI9y^);#0qt}t-$C|Bo71lHi{_+lg#f%RFy z0um=e3$K3i6K{U_4K!EX?F&rExl^W|G8Z8;`5z-k}OGNZ0#WVb$WCpQu-_YsiqKP?BB# vzVHS-CTUF4Ozn5G+mq_~Qqto~ahA+K`|lyv3(-e}00000NkvXXu0mjfd`9t{ literal 0 HcmV?d00001 diff --git a/integration_test_app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png b/integration_test_app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..d0ef06e7edb86cdfe0d15b4b0d98334a86163658 GIT binary patch literal 1716 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 literal 0 HcmV?d00001 diff --git a/integration_test_app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png b/integration_test_app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..c8f9ed8f5cee1c98386d13b17e89f719e83555b2 GIT binary patch literal 1895 zcmV-t2blPYP)FQtfgmafE#=YDCq`qUBt#QpG%*H6QHY765~R=q zZ6iudfM}q!Pz#~9JgOi8QJ|DSu?1-*(kSi1K4#~5?#|rh?sS)(-JQqX*}ciXJ56_H zdw=^s_srbAdqxlvGyrgGet#6T7_|j;95sL%MtM;q86vOxKM$f#puR)Bjv9Zvz9-di zXOTSsZkM83)E9PYBXC<$6(|>lNLVBb&&6y{NByFCp%6+^ALR@NCTse_wqvNmSWI-m z!$%KlHFH2omF!>#%1l3LTZg(s7eof$7*xB)ZQ0h?ejh?Ta9fDv59+u#MokW+1t8Zb zgHv%K(u9G^Lv`lh#f3<6!JVTL3(dCpxHbnbA;kKqQyd1~^Xe0VIaYBSWm6nsr;dFj z4;G-RyL?cYgsN1{L4ZFFNa;8)Rv0fM0C(~Tkit94 zz#~A)59?QjD&pAPSEQ)p8gP|DS{ng)j=2ux)_EzzJ773GmQ_Cic%3JJhC0t2cx>|v zJcVusIB!%F90{+}8hG3QU4KNeKmK%T>mN57NnCZ^56=0?&3@!j>a>B43pi{!u z7JyDj7`6d)qVp^R=%j>UIY6f+3`+qzIc!Y_=+uN^3BYV|o+$vGo-j-Wm<10%A=(Yk^beI{t%ld@yhKjq0iNjqN4XMGgQtbKubPM$JWBz}YA65k%dm*awtC^+f;a-x4+ddbH^7iDWGg&N0n#MW{kA|=8iMUiFYvMoDY@sPC#t$55gn6ykUTPAr`a@!(;np824>2xJthS z*ZdmT`g5-`BuJs`0LVhz+D9NNa3<=6m;cQLaF?tCv8)zcRSh66*Z|vXhG@$I%U~2l z?`Q zykI#*+rQ=z6Jm=Bui-SfpDYLA=|vzGE(dYm=OC8XM&MDo7ux4UF1~0J1+i%aCUpRe zt3L_uNyQ*cE(38Uy03H%I*)*Bh=Lb^Xj3?I^Hnbeq72(EOK^Y93CNp*uAA{5Lc=ky zx=~RKa4{iTm{_>_vSCm?$Ej=i6@=m%@VvAITnigVg{&@!7CDgs908761meDK5azA} z4?=NOH|PdvabgJ&fW2{Mo$Q0CcD8Qc84%{JPYt5EiG{MdLIAeX%T=D7NIP4%Hw}p9 zg)==!2Lbp#j{u_}hMiao9=!VSyx0gHbeCS`;q&vzeq|fs`y&^X-lso(Ls@-706qmA z7u*T5PMo_w3{se1t2`zWeO^hOvTsohG_;>J0wVqVe+n)AbQCx)yh9;w+J6?NF5Lmo zecS@ieAKL8%bVd@+-KT{yI|S}O>pYckUFs;ry9Ow$CD@ztz5K-*D$^{i(_1llhSh^ zEkL$}tsQt5>QA^;QgjgIfBDmcOgi5YDyu?t6vSnbp=1+@6D& z5MJ}B8q;bRlVoxasyhcUF1+)o`&3r0colr}QJ3hcSdLu;9;td>kf@Tcn<@9sIx&=m z;AD;SCh95=&p;$r{Xz3iWCO^MX83AGJ(yH&eTXgv|0=34#-&WAmw{)U7OU9!Wz^!7 zZ%jZFi@JR;>Mhi7S>V7wQ176|FdW2m?&`qa(ScO^CFPR80HucLHOTy%5s*HR0^8)i h0WYBP*#0Ks^FNSabJA*5${_#%002ovPDHLkV1oKhTl@e3 literal 0 HcmV?d00001 diff --git a/integration_test_app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png b/integration_test_app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png new file mode 100644 index 0000000000000000000000000000000000000000..a6d6b8609df07bf62e5100a53a01510388bd2b22 GIT binary patch literal 2665 zcmV-v3YPVWP)oFh3q0MFesq&64WThn3$;G69TfjsAv=f2G9}p zgSx99+!YV6qME!>9MD13x)k(+XE7W?_O4LoLb5ND8 zaV{9+P@>42xDfRiYBMSgD$0!vssptcb;&?u9u(LLBKmkZ>RMD=kvD3h`sk6!QYtBa ztlZI#nu$8lJ^q2Z79UTgZe>BU73(Aospiq+?SdMt8lDZ;*?@tyWVZVS_Q7S&*tJaiRlJ z+aSMOmbg3@h5}v;A*c8SbqM3icg-`Cnwl;7Ts%A1RkNIp+Txl-Ckkvg4oxrqGA5ewEgYqwtECD<_3Egu)xGllKt&J8g&+=ac@Jq4-?w6M3b*>w5 z69N3O%=I^6&UL5gZ!}trC7bUj*12xLdkNs~Bz4QdJJ*UDZox2UGR}SNg@lmOvhCc~ z*f_UeXv(=#I#*7>VZx2ObEN~UoGUTl=-@)E;YtCRZ>SVp$p9yG5hEFZ!`wI!spd)n zSk+vK0Vin7FL{7f&6OB%f;SH22dtbcF<|9fi2Fp%q4kxL!b1#l^)8dUwJ zwEf{(wJj@8iYDVnKB`eSU+;ml-t2`@%_)0jDM`+a46xhDbBj2+&Ih>1A>6aky#(-SYyE{R3f#y57wfLs z6w1p~$bp;6!9DX$M+J~S@D6vJAaElETnsX4h9a5tvPhC3L@qB~bOzkL@^z0k_hS{T4PF*TDrgdXp+dzsE? z>V|VR035Pl9n5&-RePFdS{7KAr2vPOqR9=M$vXA1Yy5>w;EsF`;OK{2pkn-kpp9Pw z)r;5JfJKKaT$4qCb{TaXHjb$QA{y0EYy*+b1XI;6Ah- zw13P)xT`>~eFoJC!>{2XL(a_#upp3gaR1#5+L(Jmzp4TBnx{~WHedpJ1ch8JFk~Sw z>F+gN+i+VD?gMXwcIhn8rz`>e>J^TI3E-MW>f}6R-pL}>WMOa0k#jN+`RyUVUC;#D zg|~oS^$6%wpF{^Qr+}X>0PKcr3Fc&>Z>uv@C);pwDs@2bZWhYP!rvGx?_|q{d`t<*XEb#=aOb=N+L@CVBGqImZf&+a zCQEa3$~@#kC);pasdG=f6tuIi0PO-y&tvX%>Mv=oY3U$nD zJ#gMegnQ46pq+3r=;zmgcG+zRc9D~c>z+jo9&D+`E6$LmyFqlmCYw;-Zooma{sR@~ z)_^|YL1&&@|GXo*pivH7k!msl+$Sew3%XJnxajt0K%3M6Bd&YFNy9}tWG^aovK2eX z1aL1%7;KRDrA@eG-Wr6w+;*H_VD~qLiVI`{_;>o)k`{8xa3EJT1O_>#iy_?va0eR? zDV=N%;Zjb%Z2s$@O>w@iqt!I}tLjGk!=p`D23I}N4Be@$(|iSA zf3Ih7b<{zqpDB4WF_5X1(peKe+rASze%u8eKLn#KKXt;UZ+Adf$_TO+vTqshLLJ5c z52HucO=lrNVae5XWOLm!V@n-ObU11!b+DN<$RuU+YsrBq*lYT;?AwJpmNKniF0Q1< zJCo>Q$=v$@&y=sj6{r!Y&y&`0$-I}S!H_~pI&2H8Z1C|BX4VgZ^-! zje3-;x0PBD!M`v*J_)rL^+$<1VJhH*2Fi~aA7s&@_rUHYJ9zD=M%4AFQ`}k8OC$9s XsPq=LnkwKG00000NkvXXu0mjfhAk5^ literal 0 HcmV?d00001 diff --git a/integration_test_app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png b/integration_test_app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..a6d6b8609df07bf62e5100a53a01510388bd2b22 GIT binary patch literal 2665 zcmV-v3YPVWP)oFh3q0MFesq&64WThn3$;G69TfjsAv=f2G9}p zgSx99+!YV6qME!>9MD13x)k(+XE7W?_O4LoLb5ND8 zaV{9+P@>42xDfRiYBMSgD$0!vssptcb;&?u9u(LLBKmkZ>RMD=kvD3h`sk6!QYtBa ztlZI#nu$8lJ^q2Z79UTgZe>BU73(Aospiq+?SdMt8lDZ;*?@tyWVZVS_Q7S&*tJaiRlJ z+aSMOmbg3@h5}v;A*c8SbqM3icg-`Cnwl;7Ts%A1RkNIp+Txl-Ckkvg4oxrqGA5ewEgYqwtECD<_3Egu)xGllKt&J8g&+=ac@Jq4-?w6M3b*>w5 z69N3O%=I^6&UL5gZ!}trC7bUj*12xLdkNs~Bz4QdJJ*UDZox2UGR}SNg@lmOvhCc~ z*f_UeXv(=#I#*7>VZx2ObEN~UoGUTl=-@)E;YtCRZ>SVp$p9yG5hEFZ!`wI!spd)n zSk+vK0Vin7FL{7f&6OB%f;SH22dtbcF<|9fi2Fp%q4kxL!b1#l^)8dUwJ zwEf{(wJj@8iYDVnKB`eSU+;ml-t2`@%_)0jDM`+a46xhDbBj2+&Ih>1A>6aky#(-SYyE{R3f#y57wfLs z6w1p~$bp;6!9DX$M+J~S@D6vJAaElETnsX4h9a5tvPhC3L@qB~bOzkL@^z0k_hS{T4PF*TDrgdXp+dzsE? z>V|VR035Pl9n5&-RePFdS{7KAr2vPOqR9=M$vXA1Yy5>w;EsF`;OK{2pkn-kpp9Pw z)r;5JfJKKaT$4qCb{TaXHjb$QA{y0EYy*+b1XI;6Ah- zw13P)xT`>~eFoJC!>{2XL(a_#upp3gaR1#5+L(Jmzp4TBnx{~WHedpJ1ch8JFk~Sw z>F+gN+i+VD?gMXwcIhn8rz`>e>J^TI3E-MW>f}6R-pL}>WMOa0k#jN+`RyUVUC;#D zg|~oS^$6%wpF{^Qr+}X>0PKcr3Fc&>Z>uv@C);pwDs@2bZWhYP!rvGx?_|q{d`t<*XEb#=aOb=N+L@CVBGqImZf&+a zCQEa3$~@#kC);pasdG=f6tuIi0PO-y&tvX%>Mv=oY3U$nD zJ#gMegnQ46pq+3r=;zmgcG+zRc9D~c>z+jo9&D+`E6$LmyFqlmCYw;-Zooma{sR@~ z)_^|YL1&&@|GXo*pivH7k!msl+$Sew3%XJnxajt0K%3M6Bd&YFNy9}tWG^aovK2eX z1aL1%7;KRDrA@eG-Wr6w+;*H_VD~qLiVI`{_;>o)k`{8xa3EJT1O_>#iy_?va0eR? zDV=N%;Zjb%Z2s$@O>w@iqt!I}tLjGk!=p`D23I}N4Be@$(|iSA zf3Ih7b<{zqpDB4WF_5X1(peKe+rASze%u8eKLn#KKXt;UZ+Adf$_TO+vTqshLLJ5c z52HucO=lrNVae5XWOLm!V@n-ObU11!b+DN<$RuU+YsrBq*lYT;?AwJpmNKniF0Q1< zJCo>Q$=v$@&y=sj6{r!Y&y&`0$-I}S!H_~pI&2H8Z1C|BX4VgZ^-! zje3-;x0PBD!M`v*J_)rL^+$<1VJhH*2Fi~aA7s&@_rUHYJ9zD=M%4AFQ`}k8OC$9s XsPq=LnkwKG00000NkvXXu0mjfhAk5^ literal 0 HcmV?d00001 diff --git a/integration_test_app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png b/integration_test_app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png new file mode 100644 index 0000000000000000000000000000000000000000..75b2d164a5a98e212cca15ea7bf2ab5de5108680 GIT binary patch literal 3831 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 literal 0 HcmV?d00001 diff --git a/integration_test_app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png b/integration_test_app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png new file mode 100644 index 0000000000000000000000000000000000000000..c4df70d39da7941ef3f6dcb7f06a192d8dcb308d GIT binary patch literal 1888 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 iW8Zci7-kcv6Uzs@r-FtIZ-&5|)J Q1PU{Fy85}Sb4q9e0B4a5jsO4v literal 0 HcmV?d00001 diff --git a/integration_test_app/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png b/integration_test_app/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..9da19eacad3b03bb08bbddbbf4ac48dd78b3d838 GIT binary patch literal 68 zcmeAS@N?(olHy`uVBq!ia0vp^j3CUx0wlM}@Gt=>Zci7-kcv6Uzs@r-FtIZ-&5|)J Q1PU{Fy85}Sb4q9e0B4a5jsO4v literal 0 HcmV?d00001 diff --git a/integration_test_app/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png b/integration_test_app/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png new file mode 100644 index 0000000000000000000000000000000000000000..9da19eacad3b03bb08bbddbbf4ac48dd78b3d838 GIT binary patch literal 68 zcmeAS@N?(olHy`uVBq!ia0vp^j3CUx0wlM}@Gt=>Zci7-kcv6Uzs@r-FtIZ-&5|)J Q1PU{Fy85}Sb4q9e0B4a5jsO4v literal 0 HcmV?d00001 diff --git a/integration_test_app/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md b/integration_test_app/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md new file mode 100644 index 000000000..89c2725b7 --- /dev/null +++ b/integration_test_app/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md @@ -0,0 +1,5 @@ +# Launch Screen Assets + +You can customize the launch screen with your own desired assets by replacing the image files in this directory. + +You can also do it by opening your Flutter project's Xcode project with `open ios/Runner.xcworkspace`, selecting `Runner/Assets.xcassets` in the Project Navigator and dropping in the desired images. \ No newline at end of file diff --git a/integration_test_app/ios/Runner/Base.lproj/LaunchScreen.storyboard b/integration_test_app/ios/Runner/Base.lproj/LaunchScreen.storyboard new file mode 100644 index 000000000..f2e259c7c --- /dev/null +++ b/integration_test_app/ios/Runner/Base.lproj/LaunchScreen.storyboard @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/integration_test_app/ios/Runner/Base.lproj/Main.storyboard b/integration_test_app/ios/Runner/Base.lproj/Main.storyboard new file mode 100644 index 000000000..f3c28516f --- /dev/null +++ b/integration_test_app/ios/Runner/Base.lproj/Main.storyboard @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/integration_test_app/ios/Runner/Info.plist b/integration_test_app/ios/Runner/Info.plist new file mode 100644 index 000000000..c9d74fce6 --- /dev/null +++ b/integration_test_app/ios/Runner/Info.plist @@ -0,0 +1,45 @@ + + + + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + integration_test_app + CFBundlePackageType + APPL + CFBundleShortVersionString + $(FLUTTER_BUILD_NAME) + CFBundleSignature + ???? + CFBundleVersion + $(FLUTTER_BUILD_NUMBER) + LSRequiresIPhoneOS + + UILaunchStoryboardName + LaunchScreen + UIMainStoryboardFile + Main + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UISupportedInterfaceOrientations~ipad + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UIViewControllerBasedStatusBarAppearance + + + diff --git a/integration_test_app/ios/Runner/Runner-Bridging-Header.h b/integration_test_app/ios/Runner/Runner-Bridging-Header.h new file mode 100644 index 000000000..3462f98d4 --- /dev/null +++ b/integration_test_app/ios/Runner/Runner-Bridging-Header.h @@ -0,0 +1,10 @@ +#import "GeneratedPluginRegistrant.h" + +#if __has_include() +#import +#endif +#if __has_include() +#import +#endif + +#import "TestRtcEnginePlugin.h" diff --git a/integration_test_app/ios/Runner/TestRtcEnginePlugin.h b/integration_test_app/ios/Runner/TestRtcEnginePlugin.h new file mode 100644 index 000000000..ac4d67cce --- /dev/null +++ b/integration_test_app/ios/Runner/TestRtcEnginePlugin.h @@ -0,0 +1,11 @@ +#ifndef TestRtcEnginePlugin_h +#define TestRtcEnginePlugin_h + +@import agora_rtc_engine; +#import + +@interface TestRtcEnginePluginMethodChannel : NSObject +- (void)setUp:(NSObject*)messenger; +@end + +#endif /* TestRtcEnginePlugin_h */ diff --git a/integration_test_app/ios/Runner/TestRtcEnginePlugin.m b/integration_test_app/ios/Runner/TestRtcEnginePlugin.m new file mode 100644 index 000000000..c6ce59a06 --- /dev/null +++ b/integration_test_app/ios/Runner/TestRtcEnginePlugin.m @@ -0,0 +1,57 @@ +#import +#import "TestRtcEnginePlugin.h" + +@interface TestRtcEnginePlugin : NSObject +@property(nonatomic) bool isRtcEngineCreated; +@property(nonatomic) bool isRtcEngineDestroy; +@property(nonatomic) AgoraRtcEngineKit *_Nullable rtcEngine; + +@end + +@implementation TestRtcEnginePlugin + +- (void)onRtcEngineCreated:(AgoraRtcEngineKit * _Nullable)rtcEngine { + self.isRtcEngineCreated = true; + self.isRtcEngineDestroy = false; + self.rtcEngine = rtcEngine; +} + +- (void)onRtcEngineDestroyed { + self.isRtcEngineCreated = false; + self.isRtcEngineDestroy = true; +} + +@end + +@interface TestRtcEnginePluginMethodChannel() +@property(nonatomic) TestRtcEnginePlugin *currentRtcEnginePlugin; +@end + +@implementation TestRtcEnginePluginMethodChannel + +- (void)setUp:(NSObject*)messenger { + FlutterMethodChannel* methodChannel = [FlutterMethodChannel + methodChannelWithName:@"agora_rtc_engine/integration_test/rtc_engine_plugin" + binaryMessenger:messenger]; + + [methodChannel setMethodCallHandler:^(FlutterMethodCall* call, FlutterResult result) { + if ([@"registerRtcEnginePlugin" isEqualToString:call.method]) { + self.currentRtcEnginePlugin = [TestRtcEnginePlugin new]; + [RtcEnginePluginRegistrant register:self.currentRtcEnginePlugin]; + result(@true); + } else if ([@"unregisterRtcEnginePlugin" isEqualToString:call.method]) { + [RtcEnginePluginRegistrant unregister:self.currentRtcEnginePlugin]; + result(@true); + } else if ([@"isRtcEngineCreated" isEqualToString:call.method]) { + result(@([[self currentRtcEnginePlugin] isRtcEngineCreated])); + } else if ([@"isRtcEngineDestroyed" isEqualToString:call.method]) { + result(@([[self currentRtcEnginePlugin] isRtcEngineDestroy])); + } else if ([@"getRtcEngineNativeHandleFromPlugin" isEqualToString:call.method]) { + result(@((intptr_t)[[[self currentRtcEnginePlugin] rtcEngine] getNativeHandle])); + } else { + result(FlutterMethodNotImplemented); + } + }]; +} + +@end diff --git a/integration_test_app/ios/Runner/iris_integration_test.framework/Info.plist b/integration_test_app/ios/Runner/iris_integration_test.framework/Info.plist new file mode 100644 index 0000000000000000000000000000000000000000..2cf0a772e41ed0e1bd7e95a25c7cf51b3cd0bb82 GIT binary patch literal 720 zcmZ8f%Wl&^6rDS~S}1hdP)Z6VP~IEMPH9C}NR1m5wP{1`GzC>LQ)l9gusxO^QS%8b z*t0_Fh8@4ahA&`&kl0jw1N{KT#-@nb+_~qTb6+zDfy<*|Aym)Eq z@|9^aGh4bkcWwT9dEv(5t;+2?m8HA)?mw_dX)WPyzeVjK_u00Qc@`RMv+okb9gkEHkxw^5#B9VkPiyGWzEgA%@ z|4KLO!V9D?JDJwaLXb_^JN37ymliz*^7f?O&^I#n%j}vGySlk&i$2@WZN4tj;y(8h zZ`;Vly-rhZj@zt3J?@S>RZV|V>#qBbe4nB0n1?*FxF0hor0G_ym_@Ng2p0-Ta0N9eIlFQr}TD zOYLa2`ihpSgH#zaqlX001k%uRWTQj$4t+vj z(06nKQ!o#Y;VEoF7btKT!CQC_AK)W=hOh7qe!wyOgkNxi%eaCyyoxvR3%rN-aSvq& N!yk(t + + + + BuildMachineOSBuild + 21A559 + CFBundleDevelopmentRegion + English + CFBundleExecutable + iris_integration_test + CFBundleIdentifier + io.agora.iris.it + CFBundleInfoDictionaryVersion + 6.0 + CFBundlePackageType + FMWK + CFBundleSignature + ???? + CFBundleSupportedPlatforms + + MacOSX + + CSResourcesFileMapped + + DTCompiler + com.apple.compilers.llvm.clang.1_0 + DTPlatformBuild + 13A233 + DTPlatformName + macosx + DTPlatformVersion + 11.3 + DTSDKBuild + 20E214 + DTSDKName + macosx11.3 + DTXcode + 1300 + DTXcodeBuild + 13A233 + LSMinimumSystemVersion + 11.3 + + diff --git a/integration_test_app/ios/Runner/iris_integration_test.framework/Versions/A/Resources/Info.plist b/integration_test_app/ios/Runner/iris_integration_test.framework/Versions/A/Resources/Info.plist new file mode 100644 index 000000000..46af6af83 --- /dev/null +++ b/integration_test_app/ios/Runner/iris_integration_test.framework/Versions/A/Resources/Info.plist @@ -0,0 +1,44 @@ + + + + + BuildMachineOSBuild + 21A559 + CFBundleDevelopmentRegion + English + CFBundleExecutable + iris_integration_test + CFBundleIdentifier + io.agora.iris.it + CFBundleInfoDictionaryVersion + 6.0 + CFBundlePackageType + FMWK + CFBundleSignature + ???? + CFBundleSupportedPlatforms + + MacOSX + + CSResourcesFileMapped + + DTCompiler + com.apple.compilers.llvm.clang.1_0 + DTPlatformBuild + 13A233 + DTPlatformName + macosx + DTPlatformVersion + 11.3 + DTSDKBuild + 20E214 + DTSDKName + macosx11.3 + DTXcode + 1300 + DTXcodeBuild + 13A233 + LSMinimumSystemVersion + 11.3 + + diff --git a/integration_test_app/ios/Runner/iris_integration_test.framework/Versions/A/_CodeSignature/CodeResources b/integration_test_app/ios/Runner/iris_integration_test.framework/Versions/A/_CodeSignature/CodeResources new file mode 100644 index 000000000..f2b9744e0 --- /dev/null +++ b/integration_test_app/ios/Runner/iris_integration_test.framework/Versions/A/_CodeSignature/CodeResources @@ -0,0 +1,128 @@ + + + + + files + + Resources/Info.plist + + ihOrG63Z85aeyts4gWzKq3ViYT0= + + + files2 + + Resources/Info.plist + + hash2 + + eex+rhGoWNxC1PnnUIJi7HG/jObgiA/PusBHvSY+2Zk= + + + + rules + + ^Resources/ + + ^Resources/.*\.lproj/ + + optional + + weight + 1000 + + ^Resources/.*\.lproj/locversion.plist$ + + omit + + weight + 1100 + + ^Resources/Base\.lproj/ + + weight + 1010 + + ^version.plist$ + + + rules2 + + .*\.dSYM($|/) + + weight + 11 + + ^(.*/)?\.DS_Store$ + + omit + + weight + 2000 + + ^(Frameworks|SharedFrameworks|PlugIns|Plug-ins|XPCServices|Helpers|MacOS|Library/(Automator|Spotlight|LoginItems))/ + + nested + + weight + 10 + + ^.* + + ^Info\.plist$ + + omit + + weight + 20 + + ^PkgInfo$ + + omit + + weight + 20 + + ^Resources/ + + weight + 20 + + ^Resources/.*\.lproj/ + + optional + + weight + 1000 + + ^Resources/.*\.lproj/locversion.plist$ + + omit + + weight + 1100 + + ^Resources/Base\.lproj/ + + weight + 1010 + + ^[^/]+$ + + nested + + weight + 10 + + ^embedded\.provisionprofile$ + + weight + 20 + + ^version\.plist$ + + weight + 20 + + + + diff --git a/integration_test_app/ios/Runner/iris_integration_test.framework/Versions/A/iris_integration_test b/integration_test_app/ios/Runner/iris_integration_test.framework/Versions/A/iris_integration_test new file mode 100755 index 0000000000000000000000000000000000000000..669423a35ad8782d469eb25546adb72994f0f84e GIT binary patch literal 332096 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

        ;DH`}Thm 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 OKtMo1K;VA~f&T-(Q;#D6 literal 0 HcmV?d00001 diff --git a/integration_test_app/ios/Runner/iris_integration_test.framework/Versions/Current/Resources/Info.plist b/integration_test_app/ios/Runner/iris_integration_test.framework/Versions/Current/Resources/Info.plist new file mode 100644 index 000000000..46af6af83 --- /dev/null +++ b/integration_test_app/ios/Runner/iris_integration_test.framework/Versions/Current/Resources/Info.plist @@ -0,0 +1,44 @@ + + + + + BuildMachineOSBuild + 21A559 + CFBundleDevelopmentRegion + English + CFBundleExecutable + iris_integration_test + CFBundleIdentifier + io.agora.iris.it + CFBundleInfoDictionaryVersion + 6.0 + CFBundlePackageType + FMWK + CFBundleSignature + ???? + CFBundleSupportedPlatforms + + MacOSX + + CSResourcesFileMapped + + DTCompiler + com.apple.compilers.llvm.clang.1_0 + DTPlatformBuild + 13A233 + DTPlatformName + macosx + DTPlatformVersion + 11.3 + DTSDKBuild + 20E214 + DTSDKName + macosx11.3 + DTXcode + 1300 + DTXcodeBuild + 13A233 + LSMinimumSystemVersion + 11.3 + + diff --git a/integration_test_app/ios/Runner/iris_integration_test.framework/Versions/Current/_CodeSignature/CodeResources b/integration_test_app/ios/Runner/iris_integration_test.framework/Versions/Current/_CodeSignature/CodeResources new file mode 100644 index 000000000..f2b9744e0 --- /dev/null +++ b/integration_test_app/ios/Runner/iris_integration_test.framework/Versions/Current/_CodeSignature/CodeResources @@ -0,0 +1,128 @@ + + + + + files + + Resources/Info.plist + + ihOrG63Z85aeyts4gWzKq3ViYT0= + + + files2 + + Resources/Info.plist + + hash2 + + eex+rhGoWNxC1PnnUIJi7HG/jObgiA/PusBHvSY+2Zk= + + + + rules + + ^Resources/ + + ^Resources/.*\.lproj/ + + optional + + weight + 1000 + + ^Resources/.*\.lproj/locversion.plist$ + + omit + + weight + 1100 + + ^Resources/Base\.lproj/ + + weight + 1010 + + ^version.plist$ + + + rules2 + + .*\.dSYM($|/) + + weight + 11 + + ^(.*/)?\.DS_Store$ + + omit + + weight + 2000 + + ^(Frameworks|SharedFrameworks|PlugIns|Plug-ins|XPCServices|Helpers|MacOS|Library/(Automator|Spotlight|LoginItems))/ + + nested + + weight + 10 + + ^.* + + ^Info\.plist$ + + omit + + weight + 20 + + ^PkgInfo$ + + omit + + weight + 20 + + ^Resources/ + + weight + 20 + + ^Resources/.*\.lproj/ + + optional + + weight + 1000 + + ^Resources/.*\.lproj/locversion.plist$ + + omit + + weight + 1100 + + ^Resources/Base\.lproj/ + + weight + 1010 + + ^[^/]+$ + + nested + + weight + 10 + + ^embedded\.provisionprofile$ + + weight + 20 + + ^version\.plist$ + + weight + 20 + + + + diff --git a/integration_test_app/ios/Runner/iris_integration_test.framework/Versions/Current/iris_integration_test b/integration_test_app/ios/Runner/iris_integration_test.framework/Versions/Current/iris_integration_test new file mode 100755 index 0000000000000000000000000000000000000000..669423a35ad8782d469eb25546adb72994f0f84e GIT binary patch literal 332096 zcmeFa34mKw+5dmjMatSBAXT=oN!e4@0xAI-nF0fWQb4xJFdf>`b{eNMP{3kfs7xA1 zB8wIQ33~;U2m)m(q)^);AVE>a?KLRs9jO{zpo*{kf1mSw&&|!9OlNq}_ox3i7bfR^ z?m5p{p7WgbE`9lLzx&4~juRT~IL-&~_d)zM;lkqd);M#V594p)D934OIX!;X>E=@H zPq7vq@>pD!KSX7YmX@yeg>sLkJG z$jg!6NnK&d&rnBgIsKtnkuiI%mi^_F5G^fpTU!=fI`4w{b6Zkfoz$C^6<6g8-lb4Y zzNDQp%O*ri%Z%2pRxj|N_zH|~9D@iCSI#DcZD~1a>d7a@r%ct_L_M-xwzZREuV`%I zYePsg?t?=_ulsd?nx{;1-dU@RX1<0SQiwhn#*fuBMRF3zk#Ki+fVY zxf}*JYx*ds|DsXO<|2zfIZnlO`P%~L=fU0CT&@4J^z>2A!F9ZLz%@zd`BC@Ye)M-f z)^>a1hIgO)<(#b#!nFwgj4nnaRs6}hYH!V`eQ=H>y+iVF7XBnI$@{3Wqs<@ncg)QB zovo*JwVm17nnFidUvq&#h(*g5g=^z=K9E5cLe7ER3px*+JNp9pYuk6<1123X<5HX& zT}<|cA3I|U3>UTGr(L?Bt9{-9$5KR+adt%g^um>L95{Ues`J1L+dF2?ZS9zOVB7o| z?F$ZUz2rcX!Tmoux4WyWz4O4JIkcc?^=tpY0}hb?=e4%YUvOYz{tTE2^%3uwIlH61 z1wN-tlWaI2#h>W4cWTH|6Q-5E6+!wH0p)pnE{r)Fng|;#O7qHUYnE$)~*s!6Vf8W@F`$bZUUR8~%A>qcW zg`Momx{qpzxF=R&oO?cD7=8H5vjbLQ_430^xcBe2asMnlv(@*jJT$~WV%HL;kqmC?h_s7kPUl;#y?u5OiNjie@iNk2Q;ortIzXU_PWx)Hx|O+724Y&%2NhwE-HHj!QAHf2^eWtuDQ zYnCPBKbFkE)BQA(QRNyvHD%Vg=VQ~{-+*iMh4dG#cTe;(7c8&(zgfrs%5_q8VltWT zKR0EjBV)~FqwUP%sMKfQqM~~mYAhT7b0!XbE^=WG$C}FR76V%5o(^AY2?(%e987AN z+aa|q-Z$L_Z`tujkuxPkpU=c^8E{PueI|*Xm64`Q-$Y|Q-Q}jf6-_vG{~I9~?TVzy zNq4cS??&VIMK8(h3M1F|hy-!>mP9ivW4%9&^**wT2xa;ra7;W)7Mm+sa|Irg;nBM| zCZYOF3hokz=46-5RzhI*|&KJ$iHky;=Vs=s9ZNZiL z_4C432x5$Uu)p8Fzb|GIXbj_bvHdl4DPsrQLk2BSOl!QqY#PF&AK<$03S<#D+uh%kd6sPQ7(MSf8(-K&BKCdrc!VE9KjMFX z9seuW6-_O9_MK^dgXVpfsdPkdR`XD{mI-Oyjz>r~39W{&-V&#y%eYB+di&u|ck7 z-?M%6iA>($xP=we^4Hx}4YurlOhdbr>JY=)n7@Wa6(PbOo1lW`=Rh zddaZqI`l$LFTl(ftwn!PbWgzrZ-()fL9qLm9tV_Sj7hwikcQXG|Z|HvLuiqlmC)y)*uXqJ~{!BqaXZCKca~KNIR* ze1$}D^`?koN&Gg&CFY`p+Ay#^JgmX2b$|E{%;yd0d3AgP!gE@3qAOAGcX)cX_defTp<(82a-3&EFF$&3g zKPohYb0icm@w_y!40=SiL!MT2APLOBB2AgKlb(-HD#|$EO;RMM zvdM=CI^J~~I2HvTe@12ynv4mPUCiBOp>?3kEC3E9X;Y`i^ExSTaPRdNLWER23 zVRE$blQPX14VzILePx7z!7Oz@Fa~p>=5?9or8Lg8I}J8uD|{&@KxucLSXSSnw7c|6 zVr!;@cgNvkHoh*i*mU=*(@Ts_#n4wwhDO{m)#!9oFjJ~WjNb(K*>Ew$J8+~3>%^*W zA*3^lyYM^k3EVdteA(vWSxI3B38JlKCo?x$VanLECehUQh-A;5qmiKWYf*aEtA@%h zmP<{XBSOZ#!V9buvK3K8ftZBcw??7GuI%kwW8+z}SWZ1V{IXHOpbVVt#kt%HHf0yf zdDh7+-a`@)+sZ7SAg66BhQ`Tlx=DJJW-H^{3^FZ!i64irVs z-Iv8HyTV9d%6HHWEK#6XlWnn15tETMOkb}rDq}&}#c~PBuNO!5BQEd)SL9OP3ggrF zh>-gOWLt`L4Zx(fWU-uj#X81UEJS8A@Ch%@g;o&NC+Dz@_}|woUWZeJ(Y42#_}_8r zRIl2m@Yr7@Lul8(hlyt6f5&hs9R{XLa`8vF2(3uNa__yab^&JRM`7ugnq>Yt2g~Q+ z{KM`i*!j53#ji&%>RX)-?(eGoe^VB#^FLuDLpxG48m@P*lMA{cj>u$w(0bFXZ{2f{ z4&*S9n3dXk_v{)uu5S}2|0aJ}$HMdxGkQF%^<=m>{1g*Mzk9x%WEa6#Ca>E)CC#O; zx&NfTc**^RB-DqM273G6>8^XM5nAJ3grN| z8)8$k4mm2sO$XVt5T$(ro&#GNTi}%!CAjV*_}4R9AAWrwH{-qO`_2m_A2PyF-@iaF zI|6-gj&!6Tp1$v^ksFb|*Jz#fyT6x{s=iM`gY@)$oh0Pb_e1TH@EZ3CY|{+Vchx?h z+*`b5CvdR7#C~58YY+Hy0cY2DItu&t2jM?{bKiIyWNZJ3Uq(iE6RAOy#^Ckc=ANHF ze-YchjIH!xUE2o}+XZ3SH(|AUs!F0Uh#KS}mwM}AU4){o%Gwxl%<-g5dI@)nYw@(r zAHE>cQ@r($m%jU^gvUPGn)o`LIX#QkjUL~F{Ts233g!e&YsRb<4-D{_?quTY27Y8Z zc3pAX{vzhtzsZkjbLgyXdo$5t?e+MtFZYRx(3zZ2kpV#saPa<>v5z?t zb}0MsiC62#vu`7R?|<7Q2HBVK-+W{7t6~G~!>fO>KNrj1s@*lM5p%}u;P`RI?O7AX zOhI;v&^&3VveHmP^|tb^M;@(x4%WA(C;eB@Ua5c6tcSz@Dv2^LU*B~kr8L~O#e&u_y zKkDD4RYtE@akr5KWL$ubU9*xis%8Hw_Mq{b@&@`dYoGq{VRy|i>fN7VZLfpdPt^ zZ`J1xb@Uyq?;v~i|9`E0ei!>X|K#?0zv@5Gzia*4`P24npSxgnqiz4awa-g*qp$4Z zUW3;eT#a*Yz9Z?qm;O2G*z27kHNA)oh zdq2^e3k2ss+TWp^w!f;lPiy*UI5p|_tc!X5V+JFo(LaVvDTBM2RE9#))lC%fkrhm_ zY0mS}rjShET=y4RP7zw`Zs!T<2A&tL;yzIgS8`thoFv<2l7Os4Fl9BHQFDsXsiC4f zPcs~o45x8!=a=k{O?$-rYch824wInLJIvO!D{g@&S{0j^Tt20tkPw!OxE*t@gbA*% zY+oaFjXQ-WVf+g8r&>QUH^BYUvm{P4M0xw0^v8OmUjJ_TmuAQwGp;GSY17_on{IkM zDv`YNSAS>jJ)bbRKl0)iJ9hUng~AqI78@gOl8#{WjgE4PpajSK1-JFX1=C|vev@IYQ5(3Oc0)DhY#QeCuXqLi1wGV3EAAwsWomSPX-L?~Htedq@&uZRqv5?7_7+%9 zR;#>D|MaA^E%X~h^j~JaY<8|qfWh`>?cdDrhqQmSXVLe&rkrcsUy7@V4$)pzpTYj( z1(h3W{!q7m2HS_&uWgU6wMWEh%U8{B{rdL&O+04(zesJwJ)vwHtJhxy(+{$pUsn4^ zZO?PwI!oK~8JJXPRT~YP{h!}g*VjIKHuYuJCur|K|Fg|X{q{JN{SVHcSKhk%^`$?Y z|9^UWdTQOjS$leu?dkjf!}j##zgK&5H~*Qn*=qkEw8tP1)qYmKJ{sfU^V)_!_}4*g z=nud3S7tRmpFP*Kr)#}&cq8}#LHWN*HkwU# zk^j35RP*01{7=dMi88?%)E=Ti`@r@g+65lY*!MS*Epu}Ym1*tM_W<2)7n_Mg)OUZz z*IwN=^{$y8>iQNH!}+(YaUVu?dbeK>*1GLC&toFhepu;RH*BUx21@Sk3NSQ0MS_K+ z?q`}+tLq-7p04|KlY1jlbn^z9i%r?Bn=;|1?5S9xB*rymr-re%2u~_zRwF4_pXZd5 zl*E!*vpW78*;)UM8xsy}SO?c{?i>Uf|0u$h@mLTZ>ABHsztUCM`Hb2}b$$U`k-aqB zA38@98FD^#x%vn6i4v&2xljID>MIu3I=1Om{mpz$=9lGvXb^w*wUPDI!Ct=n0(JW{ zV=gPpcrNJ=?taM5lIB13%F@l7&v|_j9@T^XL1aH08?dp8}GOR2EbGtL&khxtNsoU~a^H*;^T0gyt+Pi5==o4XJ zWx&GsK0AEj-$$4Oj6u1{1S{_xY@OL*K#b@T-n(++!9 zk8@AOa&GAKs_oZ*KgyJsLwDUi#&n<`{)Op*jYid;2G@t^7t2oBfWsb&ZkCj(PwCB8 zyKPcF+!yY}v(V_C^^s_F!v5Ad^n75jzP7=#G7NAG!2Ras`bm?F;cpr}kg@m>A~W&Ex?E*%CF6h9Y<--fKKojy4iV zqdSdsda(!V{!Rjm)GG1RL_+4mpG;_ZjAhZ%ri?z_v%y?@M4t4)WqHQn8Fz;oo{lxM20YpN;2)&#m;0`m(~XjdWaB~~x08>3*xd>22OG~d$U3B< zuAXNj?yk7zjld@wb;vW6vX{%p0Q%i#8>zHvqsIOLQ$tzYNi?Q9&N#+v{lH4ZGJt1W zp+ICWZ*(GwBHGmvsT+3-f1;;(i7p(6RAt9Zs>ICszpn}{A$p`_HW&K`b~GXUNh7d% zig*10p5t}~%-a$*d6RlvKTzFb{GDz*u5~Z?r3^IsAQ0|}N@27VI9-pH0b927`zzO_ zCE?7XyuNaPs+XCbx0_mVimm+Z9y~bQX?Akb%xo;am83ZHlktS-{e<}jbCia&pRO~guWwF%*3B^PZT@(kj9&LKMq1Jdhvu>8rN`_IE%+b zww^0btH=dA9!6_4VBY32b6+uvvYoh^)0k|AB2FxeOzE1!I4|Sem3jJ>(lkYYWEFusTsA2szQ*v3{N)kU|(-L+-Wk`cQlI=%sy7)QDE*LSG!1W zJ{C6lm;IN^w-ia+725U|vHozeKZV7js9iHtao>?gpg231sj^){PVw|pjsIQqxK#b; zq5R|5pCpYT$2-kW)#BEp;-OH?AAh29W^}2S{yDM|!knW=lsjbnUVhDb=w2_Z)kn0Z zzI6+@bV&qkq~AJ@sRKBH#(fGqALp#|W^4<5rfYBS7&$MpWw zs*)*21X+jglK3BdiByf#zaG~5@Y@Hf**r9VOWpNFwSKg2N=A3PnAR+7esmxBMZ3$O z-Su^s-8~Q;x`F1OnqDIt|0!$()g+ekDLhaX++Rte{wrqu(Xj^|kMx)0WLKQMbJ>*- zHz9!%y1IVXyq}gu4<#$Pd(@|3e4bZW4nWZEwQj#=vj9acZ_0+1vDVP^u#IzT?AFu}dR^CX9{y-wH zxLZrHQ6Kh!(~4{AOKM1z8(2R{y~FkIWCuBmax31|;VUY|BK&%#rc3 zd)I}cs#Kh3nODg>VM?@nbyBnFy@x1JISwCE{t?()#w>&o%sUC+P35V>UItzi!5_wN$Y5#je|C z?6|tlX_Iawu(@RCn|^!x$r!0AThv;8Nc((K{EZ&``Kjt_`4jFP*#n+%M>QQ0uZ%Z+ zV^iP9-<*l*X+(@*&Z5d$Pm4LYR|*C+YST0A<(aSq`{V@(1_RFg)eI=v?)5Gr^Jbsr zrtG2f@yuFNcDp1TcW()9#&4Z;R`AHOyOmz7xR14N?0pB;xBC)8Y0hkZs^w$F+WYy^ zmg@8;+TN}Gn7+Qd;+`t;nt^P~S7%ES@_`DOG@8LbjZ&HRFvylXlf_O~`t?w+*lg|m zxSC#dzXY0r9qfxpRUcSxA`il54Ax|&tL=Y9wx6z+M7vYS%oE$UU5)=SN<8Iv&eyM8mzNNB*pbQGQStTTZ;-`*#Wdgvn9s{7bX4>D-uTbQU%ji* zCRDtIbkj0@ZZ2sn#r$(gY{DTM5Nt{O=icc0ybKFcCqI!BBe0eN*a`VHE_y+a4>4%L z3tF^6i|)l47b>9<59o$R97~tyT_{T7dY{3U_X2H0XdP(_oZYZ z145w|%em$PS^SzUXxa-q%NJJ82jzIW7gWC7V560DUr<%wWe7U3nf&0-8TgazEM2)O zk8@oPp74VICcRm2d-MHRpgGr$2WU|kmvFZY6Gz_Gt{t7L<5R>mPOfom7G-^Dx_fl! z;`W$bLcMv?jhL?(=Qcw(ns3Rx36+%{Ch6eCMTc?`3hn7#*Fk143K8J0S!Ue8hgA|1 zGP8%o1W}Vrcx5EP{KoVQnMvX&b4a%z0;*CoQ;;Eh&+o{PUAH`9gr*HPWmyhPF-&n} zr&Xp@n(fJwl=~Tv1I4%#`>ze2H5U<=HzTQ-V>?er=Q8AKvEXOa`$|;+Pn&}R=Gb)2f8BdtV z%oIx?*HrYN;k#x&fOKRJ&5Wn$OUL15P)>f3nk0&}Ifg#kFEPs~P-a__eRL!_4<0`I z(}xZ~czg<0mFq7%Kk zWK*4@>bURKFUsxBC)u7o_OE|bKT_I?`;68JfOP^zb3Q9`jdAYDLnT{h{)2WUb23q} z82;`e8d!bU`BpH087nId3x*wh-X<8{U!IZ8mm|i$z4^6o&ULfdvDViKj+R>pqVCU$ zVpQGPO*2gq)wOSbCW`pbpNQ4?=A5!VhkUBB1jy$+uxEI9#nfLc5 zCH__S_g;D)dV|_)@9#ZkuIkus>ZIh}WiBOH7#R{k@sOYhbM+iZMp#NcHDGb0nNx4&|={mH#BGwFd%2G`G9nVZ9AF<+a^@ayM|-9H#^z1*`d ziSejn?vKcNJR`%7S*I>{Z^q6RGB0b8qWfL!03g@PF|rl);!5``I-pB{ve}O_QwRBQ zR9|<$y9I{7UVItz?UlF<`x-y~eK1Ab^YMKH1YgF~k?V^NFZeKDqy69$Mj8tGmNy;{v^z`{LV@BYjX( zpILO>iO7H?tPk~IpGD_Jtj6+yJZOOufXyvO&|&wlqhnLuS0n>}!;X|mZqm#0+?XKz&hKE2$Xo|-8_)j4;JF-m-K zA)}k~5`RW-0f_hFKS{$_gnXHgD>r3tT&P<@?)|cIkswz|5Y3)EA)Ir+X=L#HX5XS- zJRy7*1l$$o+9Ps~%Xo@o`h)I|%r$-F`^r_K8M7ICHBKD+Jf@6K6=a~|z992E+Q)cV zW)8LwztU^$QS9X$*)`_U^yeb4dq_3+qrLlSIrBU$?}X3@WC4MGT|U}iGIZH$Q|{90 z_{+%5qLMxud%8TQX`Zmg>pXpnpv*bR z-+U9bES>XqaqPPHK`W>l)@#|axuqgow#Gk;hqANXdDN4JGk0H5*X}KlwsGa$r;)lY zv|q-9v@Zu9q($lVnTA3p{($=n^xeFdfPB9yJvlxVDHZA6P021QxZjTXpLo#r7+k*$ z$J$?Oo2yZ`S!YRaS`kZwwq5sTV~5f}(6xS5p$O=AZx^urY<4gK~EN zwP#%-*ngsWu}-n+=vZNr*w>%L0SeM=OYS61581KdI?!XT6>oC>XlE*B}H-F z=gi#=lu4i8N0po2!9LFqi^}5BLNhX$4@1^IpAj?tmH95D8K|VCxpw{;8{EF4$WIwE z{dj%=<(45F=h^8cd%xN&fv0%w5%K%On=wPQ(67%|V7Fv9ubko~KbA8G&Z-ye`Y6W{X+D0g-BSFJzM7jz{bd^TGKCHwrq5aC5% z43BO@tFq*7&^pG{VzreQ#ccff9@7R~q>K9%rZ1D}6uKln*W;JA`nCFy{%?fyZ{!zx zz@NN7dW{SYHTx-5`<45L8Pm!4>y04u?>|US@Wm%k>uSzr_lCy}NXx{(f1)!WG2x;- z-7oR8Q-US+6ro+X@|5jMnljps?Tbp8_>0EtA&sQuPWu>ooSOc-XI;wV-_}1~oN-4> zZqVZ*YS;bYato{R=0?bUTgFcHT1$UX+i(cbi=Y(+%Vi5bxheATzT= zdH6je_;fFm@;nA3_c~d`QPO|b1g;F}vk{m2O3dc{n4VRsY6+KT;@>ifIx;-r>!t3e zao?`CeTQxRjIcftz zo&Shw1pNquKRkWEav&t%(!Z)^^%6lcCInugMT{~Xl7`^AdDDU=6;v_)2JQY?d+@I} zMgN$7`E6K|cJI{vLzLRz1KRRMJo^{hmp$>ehfNpYy1zArz=}xp7;VbR8`Mx|&&qM` z25o@2j)ov_ICRLzsbz|eJ3PD?c0a|7Zc$!^H!4G)aGdEeWRP6#9&W{?0qIi`FwSxA zDc{mONSHPo%M;JwBCF54pC2~)m;O8J?Xy?gi`9?#-z?h3_`ATk@e1dMD4hPQGp;-J z70IT|D$CVQ*W5vX@B>oL}E0Cnz{3?&Z(grv?_(YKr9v)+1E>___(F$KJr z1Z}Q&AA}}@D|T4tu+N{{@8Q}0)!MWCn?F5kCgAh8@(2zr%`5`@jXv<0mwfQaeBn<9 zpywn2)(KJ<*O>G8+5st?yt#u@oQbKHVApHqUwO-J(ln=8`byC8P(MBwZZ6sHUKHIg z8i{6z%TyvJ72w&Ql;1ZV;GBA}-%o|<`0Y{a*KaSQbtFd}*K41Cdzj$v<%QMy@XcRD zKko5^{G+w`GvgJyb(zD%W-ft28(pBCU2e|NU+H_5(vi3>-w!NHLo{y@n!OCK{Da4@ zsy?LS!j!_KW4_<3+pMZYXvJUJp#6(}JiD#AAF(fbb~h;vbUYY{67V{Frb@i44Z25Ta>1^vGx+2KjA3`(R=y- z#r)~orzLG^yd#=FdE>+2@`?V?CmLI_|K2Dn%RClvq-w6>hP}_`$aG1*7g}~t5>GQ2 zyX>+twwSlrvHICX%>qq9hUMGy8#WAX?^*o&i^oeOHS064zNKE>*GvwijA*GN`hI7` zl*iwHbN@8Zqgnf^+K<|(SUCQqk2of5pF6~6#+GJ^WNrXp{sAp43~S%8FzkN%eq#y! zVhMkFz}_dpG>zSX=-}4d{159^*W=al%J_gO(op(vZ0bf{yG0OdB@__-B-FX zvyXxM16$oCV7GVVrosEXKkyvl8}|MH0{!pZA9z-BRC|A5GBWUQbAKR<@c|ZM=3n}J zAv*m*_37DztLt0y&!^b=rT6ax*Rk)q^Al;?CM=TDwWthEX;@jczw`Xj#L&|I*X|GC z*#KD3a@Z^W(3K2%f1pzyXYk!0AnX1xR&|Dlyg#r?nv{%wL);&D29ejlKOlXqxj!I5 zYVHphnZW%4b1iUxz+4;t{s8I*|#{2gtg4(#uL$CdP|`}<^Xf8X$s`}=cIPj>E~ zbH9PaM!LVh8!D>0zrU?iTfP1LU*S_5)e+y0N78?48{zs~Z;zN+;WF4wMQR@Py_`}LRmlej_wlP1jguGI99E!&~LpZ)r6G`6z)5pyCfQIhE= z|J&}@XN|dGzd&5>*B>uiB68k?_v^m$Wk7H}SnXdox}MHi`-s%oht8Ai_n%~|cgsJc zFSqZfnl4t}B{A=IV1f{MU)Afs?R;yKO-<*7`OTJZ98itNj0#m-_0M+)=f|#RPuyUN zi+PSe{Km`cTc5f=!MnyA8;{WB>&!pA_+=ha{rAbgv1c{1t7W*c^DPbUjX4XUEZLX9 zzup+NiPs4)>!YlMMK~LvRcCykSaCM~s(giGk_nH-+p{o?4Hx|+leFc9;Tn15S>#npzcW$0e)H$YcRR7T zCjO%4Y2i3ug!-=(AkqYGaP%yC(aY3}k}2%Cq7WE}z9LS!|P zX_`RmhdDHDDCx4R$k9@!Hu3&vLGA`Rk*3C`X0+hB44Xq!W#1q_y%xbO~ z7vQPy#3Zp$lYecFx6S2NmHzt-GTc0{D+W&6A8Pxx{nuk-jLM|{+HoJ8dhh86W}{OA z?O*0Q=KBeQ+Ghk=tr?GzFSJ$L-ekXA=1CjbzwO)dc`qv>YKHQP*-J6)0zH#dGx98N z8KOqyX0FQZ3RLSjtJ(@|VFG-8G7}(Eu8}F%$eG$;pmA_WM zYa}Mw2s}R`+SSgi#=bPX*Z=wYn~n9SUig1{e;Et3PortfDEcVtr03n;ed*;)dgew&R-Uc% z#rheE^$bl9+Q8!mFZi;^ z31ukx%7B^BPu(AUw&rc4s!BK?j@B4E*VwjHYPx%CrK61KO`6R7-OS0&L>{If^IrIb z2TuuSxQ{-_kA&YJNtRxf>7<4?&nzsh{9)qLpuS#C@WosZ^zng5v(69#x^ zK?Q2_;}3^?Rp-~9y~#Mqf1e6-k-jZY+C$9Ge&=ZT`IC`9b8FFvk$>;=FOeO}-enGk z{CV?_|JuG9xT@dkw-$B%qYUfi{qP}K9?q#9AWZwI#%G@1q4`M@(f+@_Kc@dBfBN?6 zAAbTme;q7eJ6~7-dg=M&XY2Gw&;9(``27LiOZqnd()`3y>*Xh?K!5zh#s7? z*ZFIAQ2T{{rn#nzlJQK_3)*AQ9>hQWi%{=$^9j1<-(v_xOttbse~d zrWfR3dw#F}vGlJ)vEJ@?Odj7hdi;w&|H1f!{9e-wh7WQu{veMa{1E-Yl+4;p^S7EZ zuVkm=w|RNyEtx%LnpaKD{5891mAoE>!DW4B(VtPLZf5!$e;mJcydOW!B~6twW7znzas2BhBZ>08)IanQ91d#iIjFB752wGNf6)FB-w^t(-#)AI@3;T(;+J}H zrC!RC*)-;fzWIcB28ILHmnT15{)h9gX`ey;{tp=GWtwYxDBt*_`X1W9s^5|ISHtBm z7+;<6!|7)P{zI3in%;2sqUE*ym#0LpeU8lE)30{igY0Q!{{G&)cK%TI~}TDXk`6zJX+$gzp?d&8a0i3==Irf^W|Xu4cDIP z`v>YrE5X+v;r@9<${-rjoxzjjrGm^Fvoq-G&ft8xB)h2>=_9(h!DH{wdi|je4MX?u z)X$*%_2zj+-EWzJ2ik|-uR&fnx?kP5<+rhk^sn3R_TS&H_q@aV^+);q{jFbLb>DaJ zrDyh+_JS>P|LRw`_uRq5&+3&DhIJCZe@w+dKk&r{&{}1kO{lgbHIDQ4& zZ@u;^rivw;-L9G9pMOet+a4vZ;o=XbS7l@SePcJr%}RgY;OR&0yI%f+?Xx})*Zzi% ze`Ebaa6IGqQCkAvd>#J7%@;R1-&gs1^T|N@{5crW`0%fm_xDf!%-Q+laQ*dg`5R7t zxb!{$n)#~O+rRsKLWh!Sm*St#yw~&F>QP`+4*G1@oITzt@@H8_e&Q%2iiQ4L8h^cRB~|le6E;8Qv$@Fl#InJMbkr+f&XyFK3^S zv#aFnY&pZ7x(%}su`|#iXY=IR3^}`0&d!#zUO7w1*_Y+)lX7;CoPA8r9+9(yST;UVIxuVdqMy;mXiHr4Uqb zK6E8{K6vv}d||e5_P{?!Ha70;jkisV|9+dsJpY@w4t?P0XU0DL0eeNmjQzxA&-wE? z_RyVsJRU0Dns~Pi4U+jh^7{GES(#DJ8=+QHuUj~$JI?82FLgeJe;yTe8FsEln5#p( zKN)iF4IRY%?h{Vf+?o6zJ#JJ&g+T`(&(-)fUIB$nGfgSyKD2r?ybokWH*$YnVYKwQwoZZoWTCmZ6mV)t`Ac3SN9fB;Kerc-R297%iA6Ap?5vO~IO;?M% z@njEXvJC45HYGUtldW^wJ-yZXO`7U?96Y4YLA5^7s!XlNBuU7Y+^R{kFnOwX6}2|M zt+i`@=f_U}#F0mm+9xiUeOY@;SEOU_$X*?LMcNm(wYSe$5SiDyaQ3|Jd65O(snq<= zuJ#!b3Fma7!dg=>5BX=_9C_>$eU&sT!xPEGQzsT3CyIBX&O+cAE?)i^esBmoxXatW z+;Q@7UASpHFEQqExQKLuxDm(M4{i*RCg2wFpj{Gf2@fx(;HIJoBkrN-@Wnk0alv)) z6lei%4CY*fn>Y$GaMK@moHE=9=F1hh$rBLv3H+VnINQQaPDeT5=I~s|A#fvSJI)li z#q*F~xY4BJ%z_)c&~X;Z^*Lz5aMSZ0=N7mrbhr<|&0PjRxY5gzF5F1kao&KNzs7O? zEN(B#`6TkyhjigOH#*KlxZ#_Tb-1!*-oj~e_G3dXjdnuOF^GSR6RM1b+$K&aHxBNm za4|VgZ0UpwxV;|U&Iu*9Lw>e%M&;nSKXjTq!3iZ#L?N0He>38phV;?5<<4?K<+Bj)xp2=#`WL{z4e~RckTVO{W+9Hb z$iqC8wF}$@w;N@EUL%(|q15F_`%0vF73%RCa0Y2OqejVZ@aTV5uSDqv{e#?F)GHC_ zO^z7dBJ?3giEb=n(AcJ&g%zDEP;YWrPLdZE&1LV$a+&c}=z0N$Iq6@i0g7K#w@f#A zopO$D)fI7M(9TA#^@&KCh4Z==IG|>7U-7f zmgzcoGJd)-x=Ffex_P=qx@Ee~U6iLAqno6gqMM^zpj)C_rdy#KzFXsq(M`}z(oNA# z)6LP%(=E^~(Jj-h&~@(7_``G~bfa`*bQ5%wbW?QGbn|p8bYu5wya~EVx@o#Ox_P<< zx<$Grx@Ee~GUk(Rgl>#(l5U!Ao^FwDnQn!y^EJjtH$pc`H$gW=H%&K3H&3@fw@9}{ zw@lZ$Pt%FejnPfeP0`KKEzm8|tBi_L>89!C=;rAb>6Ym_@&qrA2;C^% z7~KTjB;7RK9Nj$KBHc3G3SH;x8h@B>gl?2>jBbK%l5U!Aj&6Z&iEf2%_!}C3gl?2> zjBb){if)c>fo_RznQn!y^C0t0H$pc`H$gW=H%B*5w@9~4w?a2u(0HSC6LfQQ3v|O8 z%=uYh9DR;F`FZA#;l9S}O@Zruyq@HB26sIECgY)N{TpsW0}Tx{G|MK?`1M>kKmK(|DU-ED|ns! zHutR}tS4S}EJrCHqig*eZbJhN4Ky^+&_F{24GlCj(9l3b0}Tx{G|468L8xec^J&o>{(3i0PEx_$oKGElj%wqBv6hyzPoCB_>7cpo9W%RT zwX}D3&hMNuDSokY>ZhHY_?|vB=*{bAoIEMo($cnYVe196FP=2%aGcL=U9g~~>(W$v z%j}K|=f|D&tYkP}81-1bxK+Nqr$$#Rb`YXiFuRUqdF=*0LWtm@Z#|S>wpDQyBD1j! z%2e82VSN_Z)C;7q_r2intE5UzCp8wM_obMm~-c*Yw)-rS9!j@Ef=Yshit#fC0 zUD|SS)Jd0CS!>R16Pt1A+!-wky1FlDxnOq3jP_0^$IeU}=*fq+&Ya)bddTd~*$WQt z>}s2I$keGgJ*}%P-Z67_M|&KNdD)nJLGAzase{5FYQrBltF@z}eJ)yV`X4s^$A{_$ z(re$fVKm6JK@ktiNP7L~p~BY5#PZsfJHiGH-E=zJKsD1lE`hpQPHSJ#J+B=)>m0YW zC~QzJ53bSHq)ErOcTH)Z+di|ks~sI7`9$$?5+h<+v0ItJEC>& z-1%*-$ctQvAJ&3ye0G<_I8UOCzW*qXn-o9o#A%1NNOY6me{^P`LR2vm)wHf7y4pME z&F(Y6>jLvoPx{4Z!nJ841D+h&Q!EYIV@&h~&%%JVZ- zBf%HK*d(Bwr$c~wCOyGkgYEO$=A{I47E_lBE+sB#?-I-lqK?|scNr0t4_`e(EzVeH zEDX&#{5Yqxd4AiR$IYM7?yP}N1wLb(!V~gaF~5Z;T4Wabaqn*M>QxQ4jHynu;L(yn75=llP>CusBG?9ozilgvb9EAzQs91Si zBpQpRlJbM_I3kf)G@MA{1ph%2M=~5uhGRm}a5{uo^m-T<5gbx}4_u8zqJ>ZrK2b0*+4K2#1#QsIbXDFKclClH4p{=$iZM1s1BCBW%WA|FBl!%`3^D;7;7+qEf`Mrk4_ zdkm6Lkmx9y3*|$FP$?9P#PU+P_6kCXcEu3n$iaMKu~;IF+#`cgT#^v*G>!(cf#oW% z(^o@^lpHp+IZq_K3$?K^efZ+cOT{M1c)UPN(Zp_2GXadG2*<=+G+`563<{8#O?VYz z8t^uUK`(0}8gU%wjxmn2bI5U`+W>H^HJo-*CB5i}RDRcS z%1QEca*n)&TqHk4E|Y&mcDC2}!kaQa@=fG4xdIk_J4wF9FyzTU zAs2Vj@E;nl^3h$CXMv@>v54|b^{ z^7Z7%z8e42+6*yn!4(M8h8mSHefhpC%{Cw~$lhpOXvZ-4A7Ye8}-GSoAOH$no&UluP7Kf1LRx zAMgp~2-1<`8FGR=?`ZW;laGxl=gAdvf&9`j%pZCGW0fo9KCt93f^x_)>Nw>nxtkm# zZ!(4HlUI=oDBuB_+9k2cg@_Ml3&w<|LNH-}*$XiWS zj*)L7r^s)S^W^y_X!sI&+Y^;5P3!^pQQPTkY|u%Ump<23b8k?#VFe44z^H1)5LA0&rimvZcPI^!o_0ygsGTj`%Cho>_= z*sUDrlk?;|$R+ac$QAOGGgLkdyOv`qIY#~yIYn+dQ}dH2r@&I*Meov;33v}-vIZ&8kr$0d~$INTp(XYE|Pbgr~VGwxg6goN60sJsDG6F zEICO&Y(C3NJ`F7SDUt6ZJLm`G_#49~$tzPDK8Aikjy*oDoFmU8m&x~mO@EGlL5?5L zKSAEPQ{~g-bI5t}rQ{O%yW|Raj|D0pIZflAN{*6mA*acICg;h`T`FH9UqP;r^JHh5 z#$O^Q$Q5#$ykED*S0K+Km&xNVR{!wn8s8)21o^v{sDGM#$3o_heD_5|eju&>CGr(lDwoM8U&Z*)FUoOTk8+CqF1bKna5d%0Z<1r^C*?SFvD#yTdD zo((qrH+lchF+TDS$rbWfu2KK+*&6?ay&8Xn{18~;OQD~W<2U3Sd7q4iFOn}J=g<$z zaX(n(6X*x!_&GU6zGI2{=g22ymGk7#=aq}(XUNf{iO!kPM}P7La+&AxFvA+^GI(@)y6P`Y&1kFS9-{PRKERsd5bCf*gsPloJ>iOLqyU9`V zK{u;^iu^b^N8aHU^)Hf_f~CK#koUY*{UftA{%?|F_%$a)jJ`kNPLbZ;}h-)_WNr`3GbNVT8JIQ78ljI7y_bCmZyhPCUQa7W7pnht)}> z3b~gYzEtCTmK-IoCnw1VtYrM;*U3fl4bQ5-bD75XDmg~p>pAsLlIM_9C4SyRsLjD~&O+Mx&mCuo{Czr@8$dRixzR};+@G z{KS7TzAvc%<3CppU#tA1vT~aI)a%M+a`G1ppVRQ4_@#1;yyF|nIr1`cfxPFhBtO{y zA>U{i_piUG@jXrd1o?npYxp$ze8Z@3@-_4?k{=_N$-g0ouhaOC_>IOFBhM!%$uE&} zG9R8B}pKlobGx=q5 ziu@09_{$o8|2H-LDEVA+lKgdYj=b4AmXF*-u8?!&^iqxg$K=RO%6tA!FbP_?HaheiS+Mdo6#0ybn1^o<>fQuOX+&Pm*)wKalg}-Tt8Q7s)4(OXN;+nS3|7 zLhdI!H*5YkuV{SvTa@=Fhi_9pg`6PIC+EmtBp1jJlgs3H$QAOGw=_K`ukmNdVX{k( zl6U?i^+`^VQ{=nIIr5*$1@dlxqQ1xpa*2EsxkBzIhi`YxvE!drK1%)!IYC}SPLap` zMZ@RFhm-T<3&{oYL*yd4OfHf4d|TrylTRa8$Z4{3hvxS?9sj2CF>)(8Nxp-e zCjXe6Cx_ov`6BsPa+$n{?A)d4KTD2~|3;3Hr~RG!AwNV;k>4Wc$S3}{hA)usA(zPi zAeYGp{X@f7$g|1eyET8elVjxnA}7e>H!y$XW5_A;0&<#sFF8lv)CuYQgZwdafxL)Z zB0owlliwy+$OnfsKIb0I{{nKDTp<E;&lxYm~~z$Svdq`37>5yqcUMuP3L;`;BJ# z$VqaAd?Pt_ujY3pIYEAloFwl)M&nD9PbKHbSCI4M2gwEU&&Wmc_^}#ai9Cf|CNCsA z%QSxvk;CL)lOyC^KS2GFljJ1%E95l!yW~81(k3cjBws-;+wkNHdAD&I-uas5?^1G@ zyp|jx@3N_ekCMB{3GyrC6nO(VO^$D-@;UM)T5^*79derd(Xh(r$cxE&@=9`%yy?~&zD&N9>^z|P8z4u>ANwHlNB#;q zM*bB!L7uRUhEI~uCa1}Ha*q64a-O{1wklsFA4e{eQ{)QyF0%7=&HsaKE(2nPa&ttw~}+@?~x1Sowir`68Us;h5UJP_#2x4)#M0y>j^3! zB~K&A$hVV|$g=M)#~tJpdDD+Ff8>+M1@g7z68SlDh5QaV{D{UM-HYjy=aUoUyU8i? zf01+KZ6~UHfjoy?BCjQv$?uY#M>YK^d#iked?`6bevq6b|Aw3*NB2?rH2JgSJo!;_ zf&9UJHGGjgpIjm@BbUj)AXmuS@2B$4W19b|0`TkNmwl6N7Gd0hPuB2OU4$@`JdA}7dm$Vu`Q$w&YKd_aM(BA40y8JcWEC`7H9+$g{{R$P3A@ zkUvlU75NtOU&#-Uw>(hGBlnr)*p*x&A4-0MJeB-s@_FPjPpbT<$=i|_lP8jwk|&ez z1MfT*_b4KoFjkL%D=4ftsqxkRsM+$|6}F9kt07<-tJJ%Pn3KJ zxruxVc&p9ve6tfW0_THgsHpjUB)~rgUpPAC^k48)s{{}!G$HT(v~L_1axf%%EdG1o zFNHrjgipqgpGDrj&-N#uve?@uARz4X>-_J&W+iQRwkD~s_Rz4Dt z_p`{`_fhYryycO~=b7H$DR0@zr{x5PI49%B&yv1<-}Q)(vH$t732wqm{~b{@Eb@L9 zdHa6ssg$=2FVp|~?M>wUEb{h!+FK}Zd8G38{o6MvZ`sNx0{Qo|q;KEX9r!r=pFsKj z;U)im7J2)A@3o&$dCN9^zrIA?&mwQ%2mU?fEss<_{ShtT2aeYCEnE4RoZt{g()Y8Z zZ{IhLQ{J+Km-_dYSLFRH^7j4YZ4t4I|CUE8Z{KIWit?7Nd<1!rLs-&}2;dNw^wT>U zbe2)xviM8>aoHT=h`gUg-o7vW8_HXj@MiuZCpg3r`IL`E-o9VG+c8>x%MwiF!@lq$ z?`M&ZMGy!_7v(L(OY?7htLevlEb{4yUbvg`maTkpjQR^p`hFJqvSbp+k0@{1%14ZE zHGMyeynR3Xx0JVR<)Z<4KZ|^HPYp2ZSn7{#pY z|3@`JD<2D_?`M&>@7w>5@|LZ5g&(Bi+2<4BZyycO~$0&adSy^!+UI;k`A$a>`q_^2va_pG7`J z`D3SQ{w-U1e}3!b-+pi6M#@_rseF#<^P-VmaY77=~pPHAsAAK6C(yh3@)R(`nr$0$EQ zdCMb}Pf~vTNt%DlBb856K04p#@*T=sw(|b^miFgoN#A}CWxrh`R(^~PMoIlmPaaYzrVA| z=_+s8$`7YM`@NoTQ{J+bA1?pl1GN0NOxN@+TY0~}ME`yk{Y5Fi?HMX>d8G0Q%735o zmPaa|qI~#FP2ciJ<#Uv8ro3eBMPigv=t^9E5Cn^6j-%I}^s~rEDSyOynt#hy-k+Yx`&s0ZyzmU=EnE3;Apd?A`4r_N=WF_wt$aEl?`M&( zQ2rjuTek9%fV`hY-hQ8}xkb~rY~>lf*M9sg^7eaPuTtLfNaa(LG=s?`%TKoQ;XwZV zEa|5i{`Zu(Y~}s=JsB7MEb;})-`J|@Tek9keTlrEMZQG&JuXmr%U0f>Uy=8-$d@U< zkn)zTd@@jeKa0Hm-q{AqTekB4^y;N=zmJw{)BIbu^8WIQyq_ig)IplTU1qTU$Rm}v z-(P!<@|LZr>TVe_!<@lO*?MW`5oEt2$M6s_InLsVdwb_kQ66hw>+9YywYMxAFsr@-xCe zC46A;b$N67Y0UEDKD*}$9~k^eFaH`dzbWbesPKWoU-0-EGykUWKO%f!@TWY!#>~Gh z{Ch6g@&gX#?+U*od|>c(ei!LOjX8bX-}e^b1B0*SWxmGD$9;c)BYa@+Gn54XFlN5S z%*XwJUwzT$9~k^8Cesi2QwCYgeB39vEqq|`w^evfUt{L)&e{O)6FxBbT3+UB%zWHe z_ysj9KX51?_Zz-Q_`u*#dGc$_={M(WfS(pVF!)7}uQBs+f8w7D9~gX{-?;qmO8TF6 z$>tw8l#lxvmxK=tzRoYFuQAKNFmE&XQsD!K@>hia4&eib^0$Tm372jDBTQoP*4U&K zFVbI)S$^CvxhQ<#(DZR1XZPxBXr4;;$hJz^7hUc;sj41QYvabM?GG%X)El#ly8e?$1dq5SQm zR{rac*z|$H*X6ZHA8O3ycSHD#Ez1W6f6_+ZSATKe=*NW*48Be;F8$k*{vWn&`oN+5 zUEv??SUxcLsrC02HiIu0{*++w)AFB@@SnbA(+3XaF9`qn!UqO_!7G1_x&F3=|5;aT z`oQ3)<^QJeZwnt7{3$PejXC|>!hii$sXxKsraG&go@PR}5 zxPSIT!UqOFt^9Cb?b>xKKQQ<=z4FtT%MbV4KIT!&2L?Ya|5IOS6ZlTy1Bdb#g#Y

        ;DH`}Thm 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 OKtMo1K;VA~f&T-(Q;#D6 literal 0 HcmV?d00001 diff --git a/integration_test_app/ios/Runner/iris_integration_test.framework/iris_integration_test b/integration_test_app/ios/Runner/iris_integration_test.framework/iris_integration_test new file mode 100755 index 0000000000000000000000000000000000000000..128ec2abde90e941a69f180a88468b15f8ad5412 GIT binary patch literal 318800 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 WN%h#3FI5yD%2LH2^QGvwfBY|i;0QMW literal 0 HcmV?d00001 diff --git a/integration_test_app/ios/Runner/iris_integration_test.podspec b/integration_test_app/ios/Runner/iris_integration_test.podspec new file mode 100644 index 000000000..a70668883 --- /dev/null +++ b/integration_test_app/ios/Runner/iris_integration_test.podspec @@ -0,0 +1,17 @@ +# +# To learn more about a Podspec see http://guides.cocoapods.org/syntax/podspec.html. +# Run `pod lib lint agora_rtc_engine.podspec` to validate before publishing. +# + +Pod::Spec.new do |s| + s.name = 'iris_integration_test' + s.version = '3.3.1' + s.summary = 'A new flutter plugin project.' + s.description = 'project.description' + s.homepage = 'https://github.com/AgoraIO/Flutter-SDK' + s.license = { :file => '../LICENSE' } + s.author = { 'Agora' => 'developer@agora.io' } + s.source = { :path => '.' } + s.vendored_frameworks = 'iris_integration_test.framework' + s.platform = :ios, '9.0' +end diff --git a/integration_test_app/iris_integration_test/.gitignore b/integration_test_app/iris_integration_test/.gitignore new file mode 100644 index 000000000..657efaf07 --- /dev/null +++ b/integration_test_app/iris_integration_test/.gitignore @@ -0,0 +1 @@ +/third_party/googletest/ \ No newline at end of file diff --git a/integration_test_app/iris_integration_test/.gitmodules b/integration_test_app/iris_integration_test/.gitmodules new file mode 100644 index 000000000..95fbdd378 --- /dev/null +++ b/integration_test_app/iris_integration_test/.gitmodules @@ -0,0 +1,3 @@ +[submodule "third_party/googletest"] + branch = main + url = https://github.com/google/googletest.git diff --git a/integration_test_app/iris_integration_test/CMakeLists.txt b/integration_test_app/iris_integration_test/CMakeLists.txt new file mode 100644 index 000000000..393fffeaa --- /dev/null +++ b/integration_test_app/iris_integration_test/CMakeLists.txt @@ -0,0 +1,123 @@ +cmake_minimum_required(VERSION 3.10.2) + +set(CMAKE_CXX_STANDARD 11) + +set(CMAKE_EXPORT_COMPILE_COMMANDS ON) + +# set(CMAKE_XCODE_ATTRIBUTE_CODE_SIGNING_REQUIRED "NO") +# set(CMAKE_XCODE_ATTRIBUTE_CODE_SIGNING_ALLOWED "NO") + +project(iris_integration_test) + +set(LIBRARY_NAME iris_integration_test) + +file(GLOB SOURCES + "${CMAKE_CURRENT_SOURCE_DIR}/src/*.h" + "${CMAKE_CURRENT_SOURCE_DIR}/src/*.cc" + ) + +add_library(${LIBRARY_NAME} SHARED + ${SOURCES} + ) + +target_include_directories(${LIBRARY_NAME} PUBLIC + "${CMAKE_CURRENT_SOURCE_DIR}/src" + "${CMAKE_CURRENT_SOURCE_DIR}/third_party/agora/rtc/include" + "${CMAKE_CURRENT_SOURCE_DIR}/third_party/iris" +) + +if (CMAKE_SYSTEM_NAME STREQUAL "Android") +# if(UNIX AND NOT APPLE) +# if (PLATFORM STREQUAL "ANDROID") + if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/../../android/libs/${ANDROID_ABI}") + set(LIBS_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../../android/libs/${ANDROID_ABI}") + else() + set(LIBS_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../android/libs/${ANDROID_ABI}") + endif() + + add_library(libAgoraRtcWrapper SHARED IMPORTED) + set_target_properties( + libAgoraRtcWrapper + PROPERTIES IMPORTED_LOCATION + ${LIBS_DIR}/libAgoraRtcWrapper.so + ) + + target_link_libraries(${LIBRARY_NAME} + PRIVATE + libAgoraRtcWrapper + + ) +elseif (CMAKE_SYSTEM_NAME STREQUAL "iOS") + if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/../../ios/AgoraRtcWrapper.podspec") + set(LIBS_DIR + "${CMAKE_CURRENT_SOURCE_DIR}/../../ios/" + ) + else() + # set(LIBS_DIR + # "" + # ) + + # /Users/fenglang/codes/aw/Agora-Flutter-SDK/integration_test_app/ios/Pods/AgoraIrisRTC_iOS/AgoraRtcWrapper.framework + set(LIBS_DIR + "${CMAKE_CURRENT_SOURCE_DIR}/../ios/Pods/AgoraIrisRTC_iOS" + ) + endif() + + set(FRAMEWORKS + "-framework AgoraRtcWrapper" + ) + + set_target_properties(${LIBRARY_NAME} PROPERTIES + FRAMEWORK TRUE + FRAMEWORK_VERSION A + MACOSX_FRAMEWORK_IDENTIFIER io.agora.iris.it + CXX_VISIBILITY_PRESET hidden + LINK_FLAGS "-Wl -F ${LIBS_DIR} -rpath ${CMAKE_CURRENT_SOURCE_DIR}/../../ios/Pods/AgoraRtcEngine_macOS" + ) + + target_link_libraries(${LIBRARY_NAME} + PUBLIC + "${FRAMEWORKS}" + ) +elseif (CMAKE_SYSTEM_NAME STREQUAL "Darwin") + + if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/../../macos/AgoraRtcWrapper.podspec") + set(LIBS_DIR + "${CMAKE_CURRENT_SOURCE_DIR}/../../macos/" + ) + else() + set(LIBS_DIR + "${CMAKE_CURRENT_SOURCE_DIR}/../macos/Pods/AgoraIrisRTC_macOS" + ) + endif() + + set(FRAMEWORKS + "-framework AgoraRtcWrapper" + ) + + set_target_properties(${LIBRARY_NAME} PROPERTIES + FRAMEWORK TRUE + FRAMEWORK_VERSION A + MACOSX_FRAMEWORK_IDENTIFIER io.agora.iris.it + CXX_VISIBILITY_PRESET hidden + LINK_FLAGS "-Wl -F ${LIBS_DIR} -rpath ${CMAKE_CURRENT_SOURCE_DIR}/../../macos/Pods/AgoraRtcEngine_macOS" + ) + + target_link_libraries(${LIBRARY_NAME} + PUBLIC + "${FRAMEWORKS}" + ) +else() + # /Users/fenglang/codes/aw/Agora-Flutter/integration_test_app/ + set(LIBS_DIR + "${CMAKE_CURRENT_SOURCE_DIR}/../../windows/third_party/iris/Agora_Native_SDK_for_Windows_IRIS/x64/Release/AgoraRtcWrapper.lib" + ) + target_link_libraries(${LIBRARY_NAME} PUBLIC + ${LIBS_DIR} + ) + +endif() + +if (APPLE) + add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/unittest) +endif() diff --git a/integration_test_app/iris_integration_test/README.md b/integration_test_app/iris_integration_test/README.md new file mode 100644 index 000000000..bfc944d39 --- /dev/null +++ b/integration_test_app/iris_integration_test/README.md @@ -0,0 +1,2 @@ +## unit test +unit test can only be run on macOS at this time. \ No newline at end of file diff --git a/integration_test_app/iris_integration_test/build-android.sh b/integration_test_app/iris_integration_test/build-android.sh new file mode 100644 index 000000000..f49ea44e4 --- /dev/null +++ b/integration_test_app/iris_integration_test/build-android.sh @@ -0,0 +1,40 @@ +#!/usr/bin/env bash + +set -e +set -x + +ROOT_PATH=$(pwd) +IRIS_INTEGRATION_TEST_PATH=$ROOT_PATH/integration_test_app/iris_integration_test + +if [ ! -d "$IRIS_INTEGRATION_TEST_PATH/build/android" ]; then + mkdir -p $IRIS_INTEGRATION_TEST_PATH/build/android +fi + +cd $IRIS_INTEGRATION_TEST_PATH/build/android +echo "$IRIS_INTEGRATION_TEST_PATH" +cmake \ + -G "Ninja" \ + -DANDROID_ABI="x86_64" \ + -DANDROID_NDK="$ANDROID_NDK" \ + -DCMAKE_TOOLCHAIN_FILE="$ANDROID_NDK"/build/cmake/android.toolchain.cmake \ + -DANDROID_TOOLCHAIN=clang \ + -DANDROID_PLATFORM=android-16 \ + -DCMAKE_BUILD_TYPE="Debug" \ + -DIRIS_SDK_TYPE=RTC \ + -DPLATFORM="ANDROID" \ + "$IRIS_INTEGRATION_TEST_PATH" + +cmake --build . --config "Debug" + +# cmake \ +# -G Xcode \ +# -DPLATFORM="MAC" \ +# -DCMAKE_OSX_ARCHITECTURES="x86_64" \ +# -DCMAKE_BUILD_TYPE="Debug" \ +# -DRUN_TEST=1 \ +# "$IRIS_INTEGRATION_TEST_PATH" +# cmake --build . --config "Debug" +# +# popd + +# cp -r "${IRIS_INTEGRATION_TEST_PATH}/build/mac/Debug/iris_integration_test.framework" "${IRIS_INTEGRATION_TEST_PATH}/../macos/Runner" \ No newline at end of file diff --git a/integration_test_app/iris_integration_test/build-ios.sh b/integration_test_app/iris_integration_test/build-ios.sh new file mode 100644 index 000000000..2d7ad5059 --- /dev/null +++ b/integration_test_app/iris_integration_test/build-ios.sh @@ -0,0 +1,30 @@ +#!/usr/bin/env bash + +set -e +set -x + +ROOT_PATH=$(pwd) +IRIS_INTEGRATION_TEST_PATH=$ROOT_PATH/integration_test_app/iris_integration_test + +if [ ! -d "$IRIS_INTEGRATION_TEST_PATH/build/ios" ]; then + mkdir -p $IRIS_INTEGRATION_TEST_PATH/build/ios +fi + +pushd $IRIS_INTEGRATION_TEST_PATH/build/ios + +# if [[ "$1" == "OS64COMBINED" ]]; then +# archs="armv7;arm64" +# fi + cmake \ + -G "Xcode" \ + -DCMAKE_TOOLCHAIN_FILE="${IRIS_INTEGRATION_TEST_PATH}/ios.toolchain.cmake" \ + -DPLATFORM="SIMULATOR64" \ + -DDEPLOYMENT_TARGET="9.0" \ + -DCMAKE_BUILD_TYPE="Debug" \ + "$IRIS_INTEGRATION_TEST_PATH" +cmake --build . --config "Debug" + +popd + +# /Users/fenglang/codes/aw/Agora-Flutter/integration_test_app/iris_integration_test/build/ios/Debug-iphonesimulator/iris_integration_test.framework +cp -r "${IRIS_INTEGRATION_TEST_PATH}/build/ios/Debug-iphonesimulator/iris_integration_test.framework" "${IRIS_INTEGRATION_TEST_PATH}/../ios/Runner" \ No newline at end of file diff --git a/integration_test_app/iris_integration_test/build-macos.sh b/integration_test_app/iris_integration_test/build-macos.sh new file mode 100644 index 000000000..730b055e6 --- /dev/null +++ b/integration_test_app/iris_integration_test/build-macos.sh @@ -0,0 +1,26 @@ +#!/usr/bin/env bash + +set -e +set -x + +ROOT_PATH=$(pwd) +IRIS_INTEGRATION_TEST_PATH=$ROOT_PATH/integration_test_app/iris_integration_test + +if [ ! -d "$IRIS_INTEGRATION_TEST_PATH/build/mac" ]; then + mkdir -p $IRIS_INTEGRATION_TEST_PATH/build/mac +fi + +pushd $IRIS_INTEGRATION_TEST_PATH/build/mac + +cmake \ + -G Xcode \ + -DPLATFORM="MAC" \ + -DCMAKE_OSX_ARCHITECTURES="x86_64" \ + -DCMAKE_BUILD_TYPE="Debug" \ + -DRUN_TEST=1 \ + "$IRIS_INTEGRATION_TEST_PATH" +cmake --build . --config "Debug" + +popd + +cp -r "${IRIS_INTEGRATION_TEST_PATH}/build/mac/Debug/iris_integration_test.framework" "${IRIS_INTEGRATION_TEST_PATH}/../macos/Runner" \ No newline at end of file diff --git a/integration_test_app/iris_integration_test/ios.toolchain.cmake b/integration_test_app/iris_integration_test/ios.toolchain.cmake new file mode 100644 index 000000000..168b4b984 --- /dev/null +++ b/integration_test_app/iris_integration_test/ios.toolchain.cmake @@ -0,0 +1,927 @@ +# This file is part of the ios-cmake project. It was retrieved from +# https://github.com/gerstrong/ios-cmake.git which is a fork of +# https://github.com/cristeab/ios-cmake.git, which again is a fork of +# https://code.google.com/p/ios-cmake/. Which in turn is based off of +# the Platform/Darwin.cmake and Platform/UnixPaths.cmake files which +# are included with CMake 2.8.4 +# +# The ios-cmake project is licensed under the new BSD license. +# +# Copyright (c) 2014, Bogdan Cristea and LTE Engineering Software, +# Kitware, Inc., Insight Software Consortium. All rights reserved. +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# 3. Neither the name of the copyright holder nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +# COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# +# This file is based off of the Platform/Darwin.cmake and +# Platform/UnixPaths.cmake files which are included with CMake 2.8.4 +# It has been altered for iOS development. +# +# Updated by Alex Stewart (alexs.mac@gmail.com) +# +# ***************************************************************************** +# Now maintained by Alexander Widerberg (widerbergaren [at] gmail.com) +# under the BSD-3-Clause license +# https://github.com/leetal/ios-cmake +# ***************************************************************************** +# +# INFORMATION / HELP +# +# The following options control the behaviour of this toolchain: +# +# PLATFORM: (default "OS64") +# OS = Build for iPhoneOS. +# OS64 = Build for arm64 iphoneOS. +# OS64COMBINED = Build for arm64 x86_64 iphoneOS. Combined into FAT STATIC lib (supported on 3.14+ of CMakewith "-G Xcode" argument ONLY) +# SIMULATOR = Build for x86 i386 iphoneOS Simulator. +# SIMULATOR64 = Build for x86_64 iphoneOS Simulator. +# SIMULATORARM64 = Build for arm64 iphoneOS Simulator. +# TVOS = Build for arm64 tvOS. +# TVOSCOMBINED = Build for arm64 x86_64 tvOS. Combined into FAT STATIC lib (supported on 3.14+ of CMake with "-G Xcode" argument ONLY) +# SIMULATOR_TVOS = Build for x86_64 tvOS Simulator. +# WATCHOS = Build for armv7k arm64_32 for watchOS. +# WATCHOSCOMBINED = Build for armv7k arm64_32 x86_64 watchOS. Combined into FAT STATIC lib (supported on 3.14+ of CMake with "-G Xcode" argument ONLY) +# SIMULATOR_WATCHOS = Build for x86_64 for watchOS Simulator. +# MAC = Build for x86_64 macOS. +# MAC_ARM64 = Build for Apple Silicon macOS. +# MAC_CATALYST = Build for x86_64 macOS with Catalyst support (iOS toolchain on macOS). +# Note: The build argument "MACOSX_DEPLOYMENT_TARGET" can be used to control min-version of macOS +# MAC_CATALYST_ARM64 = Build for Apple Silicon macOS with Catalyst support (iOS toolchain on macOS). +# Note: The build argument "MACOSX_DEPLOYMENT_TARGET" can be used to control min-version of macOS +# +# CMAKE_OSX_SYSROOT: Path to the SDK to use. By default this is +# automatically determined from PLATFORM and xcodebuild, but +# can also be manually specified (although this should not be required). +# +# CMAKE_DEVELOPER_ROOT: Path to the Developer directory for the platform +# being compiled for. By default this is automatically determined from +# CMAKE_OSX_SYSROOT, but can also be manually specified (although this should +# not be required). +# +# DEPLOYMENT_TARGET: Minimum SDK version to target. Default 2.0 on watchOS and 9.0 on tvOS+iOS +# +# ENABLE_BITCODE: (1|0) Enables or disables bitcode support. Default 1 (true) +# +# ENABLE_ARC: (1|0) Enables or disables ARC support. Default 1 (true, ARC enabled by default) +# +# ENABLE_VISIBILITY: (1|0) Enables or disables symbol visibility support. Default 0 (false, visibility hidden by default) +# +# ENABLE_STRICT_TRY_COMPILE: (1|0) Enables or disables strict try_compile() on all Check* directives (will run linker +# to actually check if linking is possible). Default 0 (false, will set CMAKE_TRY_COMPILE_TARGET_TYPE to STATIC_LIBRARY) +# +# ARCHS: (armv7 armv7s armv7k arm64 arm64_32 i386 x86_64) If specified, will override the default architectures for the given PLATFORM +# OS = armv7 armv7s arm64 (if applicable) +# OS64 = arm64 (if applicable) +# SIMULATOR = i386 +# SIMULATOR64 = x86_64 +# SIMULATORARM64 = arm64 +# TVOS = arm64 +# SIMULATOR_TVOS = x86_64 (i386 has since long been deprecated) +# WATCHOS = armv7k arm64_32 (if applicable) +# SIMULATOR_WATCHOS = x86_64 (i386 has since long been deprecated) +# MAC = x86_64 +# MAC_ARM64 = arm64 +# MAC_CATALYST = x86_64 +# MAC_CATALYST_ARM64 = arm64 +# +# This toolchain defines the following properties (available via get_property()) for use externally: +# +# PLATFORM: The currently targeted platform. +# XCODE_VERSION: Version number (not including Build version) of Xcode detected. +# SDK_VERSION: Version of SDK being used. +# OSX_ARCHITECTURES: Architectures being compiled for (generated from PLATFORM). +# APPLE_TARGET_TRIPLE: Used by autoconf build systems. NOTE: If "ARCHS" are overridden, this will *NOT* be set! +# +# This toolchain defines the following macros for use externally: +# +# set_xcode_property (TARGET XCODE_PROPERTY XCODE_VALUE XCODE_VARIANT) +# A convenience macro for setting xcode specific properties on targets. +# Available variants are: All, Release, RelWithDebInfo, Debug, MinSizeRel +# example: set_xcode_property (myioslib IPHONEOS_DEPLOYMENT_TARGET "3.1" "all"). +# +# find_host_package (PROGRAM ARGS) +# A macro used to find executable programs on the host system, not within the +# environment. Thanks to the android-cmake project for providing the +# command. +# + +cmake_minimum_required(VERSION 3.8.0) + +# CMake invokes the toolchain file twice during the first build, but only once during subsequent rebuilds. +if(IOS_TOOLCHAIN_HAS_RUN) + return() +endif(IOS_TOOLCHAIN_HAS_RUN) +set(IOS_TOOLCHAIN_HAS_RUN true) + +############################################################################### +# OPTIONS # +############################################################################### + +option(DROP_32_BIT "Drops the 32-bit targets universally." YES) + +############################################################################### +# END OPTIONS # +############################################################################### + +# List of supported platform values +list(APPEND _supported_platforms + "OS" "OS64" "OS64COMBINED" "SIMULATOR" "SIMULATOR64" "SIMULATORARM64" + "TVOS" "TVOSCOMBINED" "SIMULATOR_TVOS" + "WATCHOS" "WATCHOSCOMBINED" "SIMULATOR_WATCHOS" + "MAC" "MAC_ARM64" + "MAC_CATALYST" "MAC_CATALYST_ARM64") + +# Cache what generator is used +set(USED_CMAKE_GENERATOR "${CMAKE_GENERATOR}") + +# Check if using a CMake version capable of building combined FAT builds (simulator and target slices combined in one static lib) +if(${CMAKE_VERSION} VERSION_GREATER_EQUAL "3.14") + set(MODERN_CMAKE YES) +endif() + +# Get the Xcode version being used. +# Problem: CMake runs toolchain files multiple times, but can't read cache variables on some runs. +# Workaround: On first run (in which cache variables are always accessible), set an intermediary environment variable. +# +# NOTE: This pattern is used i many places in this toolchain to speed up checks of all sorts +if(DEFINED XCODE_VERSION_INT) + # Environment variables are always preserved. + set(ENV{_XCODE_VERSION_INT} "${XCODE_VERSION_INT}") +elseif(DEFINED ENV{_XCODE_VERSION_INT}) + set(XCODE_VERSION_INT "$ENV{_XCODE_VERSION_INT}") +elseif(NOT DEFINED XCODE_VERSION_INT) + find_program(XCODEBUILD_EXECUTABLE xcodebuild) + if(NOT XCODEBUILD_EXECUTABLE) + message(FATAL_ERROR "xcodebuild not found. Please install either the standalone commandline tools or Xcode.") + endif() + execute_process(COMMAND ${XCODEBUILD_EXECUTABLE} -version + OUTPUT_VARIABLE XCODE_VERSION_INT + ERROR_QUIET + OUTPUT_STRIP_TRAILING_WHITESPACE) + string(REGEX MATCH "Xcode [0-9\\.]+" XCODE_VERSION_INT "${XCODE_VERSION_INT}") + string(REGEX REPLACE "Xcode ([0-9\\.]+)" "\\1" XCODE_VERSION_INT "${XCODE_VERSION_INT}") + set(XCODE_VERSION_INT "${XCODE_VERSION_INT}" CACHE INTERNAL "") +endif() + +# Assuming that xcode 12.0 is installed you most probably have ios sdk 14.0 or later installed (tested on Big Sur) +# if you don't set a deployment target it will be set the way you only get 64-bit builds +if(NOT DEFINED DEPLOYMENT_TARGET AND XCODE_VERSION_INT VERSION_GREATER 12.0) + # Temporarily fix the arm64 issues in CMake install-combined by excluding arm64 for simulator builds (needed for Apple Silicon...) + set(CMAKE_XCODE_ATTRIBUTE_EXCLUDED_ARCHS[sdk=iphonesimulator*] "arm64") +endif() + +# Check if the platform variable is set +if(DEFINED PLATFORM) + # Environment variables are always preserved. + set(ENV{_PLATFORM} "${PLATFORM}") +elseif(DEFINED ENV{_PLATFORM}) + set(PLATFORM "$ENV{_PLATFORM}") +elseif(NOT DEFINED PLATFORM) + message(FATAL_ERROR "PLATFORM argument not set. Bailing configure since I don't know what target you want to build for!") +endif () + +# Safeguard that the platform value is set and is one of the supported values +list(FIND _supported_platforms ${PLATFORM} contains_PLATFORM) +if("${contains_PLATFORM}" EQUAL "-1") + string(REPLACE ";" "\n * " _supported_platforms_formatted "${_supported_platforms}") + message(FATAL_ERROR " Invalid PLATFORM specified! Current value: ${PLATFORM}.\n" + " Supported PLATFORM values: \n * ${_supported_platforms_formatted}") +endif() + +# Check if Apple Silicon is supported +if(PLATFORM MATCHES "^(MAC_ARM64)$|^(MAC_CATALYST_ARM64)$" AND ${CMAKE_VERSION} VERSION_LESS "3.19.5") + message(FATAL_ERROR "Apple Silicon builds requires a minimum of CMake 3.19.5") +endif() + +# Touch toolchain variable to suppress "unused variable" warning. +# This happens if CMake is invoked with the same command line the second time. +if(CMAKE_TOOLCHAIN_FILE) +endif() + +# Fix for PThread library not in path +set(CMAKE_THREAD_LIBS_INIT "-lpthread") +set(CMAKE_HAVE_THREADS_LIBRARY 1) +set(CMAKE_USE_WIN32_THREADS_INIT 0) +set(CMAKE_USE_PTHREADS_INIT 1) + +# Specify minimum version of deployment target. +if(NOT DEFINED DEPLOYMENT_TARGET) + if (PLATFORM MATCHES "WATCHOS") + # Unless specified, SDK version 4.0 is used by default as minimum target version (watchOS). + set(DEPLOYMENT_TARGET "4.0") + elseif(PLATFORM STREQUAL "MAC") + # Unless specified, SDK version 10.13 (High sierra) is used by default as minimum target version (macos). + set(DEPLOYMENT_TARGET "10.13") + elseif(PLATFORM STREQUAL "MAC_ARM64") + # Unless specified, SDK version 11.0 (Big Sur) is used by default as minimum target version (macos on arm). + set(DEPLOYMENT_TARGET "11.0") + elseif(PLATFORM STREQUAL "MAC_CATALYST" OR PLATFORM STREQUAL "MAC_CATALYST_ARM64") + # Unless specified, SDK version 13.0 is used by default as minimum target version (mac catalyst minimum requirement). + set(DEPLOYMENT_TARGET "13.0") + else() + # Unless specified, SDK version 11.0 is used by default as minimum target version (iOS, tvOS). + set(DEPLOYMENT_TARGET "11.0") + endif() + message(STATUS "[DEFAULTS] Using the default min-version since DEPLOYMENT_TARGET not provided!") +elseif(DEFINED DEPLOYMENT_TARGET AND PLATFORM STREQUAL "MAC_CATALYST" AND ${DEPLOYMENT_TARGET} VERSION_LESS "13.0") + message(FATAL_ERROR "Mac Catalyst builds requires a minimum deployment target of 13.0!") +endif() + +# Store the DEPLOYMENT_TARGET in the cache +set(DEPLOYMENT_TARGET "${DEPLOYMENT_TARGET}" CACHE INTERNAL "") + +# Handle the case where we are targeting iOS and a version above 10.3.4 (32-bit support dropped officially) +if(PLATFORM STREQUAL "OS" AND DEPLOYMENT_TARGET VERSION_GREATER_EQUAL 10.3.4) + set(PLATFORM "OS64") + message(STATUS "Targeting minimum SDK version ${DEPLOYMENT_TARGET}. Dropping 32-bit support.") +elseif(PLATFORM STREQUAL "SIMULATOR" AND DEPLOYMENT_TARGET VERSION_GREATER_EQUAL 10.3.4) + set(PLATFORM "SIMULATOR64") + message(STATUS "Targeting minimum SDK version ${DEPLOYMENT_TARGET}. Dropping 32-bit support.") +endif() + +set(PLATFORM_INT "${PLATFORM}") + +if(DEFINED ARCHS) + string(REPLACE ";" "-" ARCHS_SPLIT "${ARCHS}") +endif() + +# Determine the platform name and architectures for use in xcodebuild commands +# from the specified PLATFORM_INT name. +if(PLATFORM_INT STREQUAL "OS") + set(SDK_NAME iphoneos) + if(NOT ARCHS) + set(ARCHS armv7 armv7s arm64) + set(APPLE_TARGET_TRIPLE_INT arm-apple-ios) + endif() +elseif(PLATFORM_INT STREQUAL "OS64") + set(SDK_NAME iphoneos) + if(NOT ARCHS) + if (XCODE_VERSION_INT VERSION_GREATER 10.0) + set(ARCHS arm64) # Add arm64e when Apple have fixed the integration issues with it, libarclite_iphoneos.a is currently missung bitcode markers for example + else() + set(ARCHS arm64) + endif() + set(APPLE_TARGET_TRIPLE_INT aarch64-apple-ios) + else() + set(APPLE_TARGET_TRIPLE_INT ${ARCHS_SPLIT}-apple-ios) + endif() +elseif(PLATFORM_INT STREQUAL "OS64COMBINED") + set(SDK_NAME iphoneos) + if(MODERN_CMAKE) + if(NOT ARCHS) + if (XCODE_VERSION_INT VERSION_GREATER 10.0) + set(ARCHS arm64 x86_64) # Add arm64e when Apple have fixed the integration issues with it, libarclite_iphoneos.a is currently missung bitcode markers for example + set(CMAKE_XCODE_ATTRIBUTE_ARCHS[sdk=iphoneos*] "arm64") + set(CMAKE_XCODE_ATTRIBUTE_ARCHS[sdk=iphonesimulator*] "x86_64") + set(CMAKE_XCODE_ATTRIBUTE_VALID_ARCHS[sdk=iphoneos*] "arm64") + set(CMAKE_XCODE_ATTRIBUTE_VALID_ARCHS[sdk=iphonesimulator*] "x86_64") + else() + set(ARCHS arm64 x86_64) + set(CMAKE_XCODE_ATTRIBUTE_ARCHS[sdk=iphoneos*] "arm64") + set(CMAKE_XCODE_ATTRIBUTE_ARCHS[sdk=iphonesimulator*] "x86_64") + set(CMAKE_XCODE_ATTRIBUTE_VALID_ARCHS[sdk=iphoneos*] "arm64") + set(CMAKE_XCODE_ATTRIBUTE_VALID_ARCHS[sdk=iphonesimulator*] "x86_64") + endif() + set(APPLE_TARGET_TRIPLE_INT aarch64-x86_64-apple-ios) + else() + set(APPLE_TARGET_TRIPLE_INT ${ARCHS_SPLIT}-apple-ios) + endif() + else() + message(FATAL_ERROR "Please make sure that you are running CMake 3.14+ to make the OS64COMBINED setting work") + endif() +elseif(PLATFORM_INT STREQUAL "SIMULATOR") + set(SDK_NAME iphonesimulator) + if(NOT ARCHS) + set(ARCHS i386) + set(APPLE_TARGET_TRIPLE_INT i386-apple-ios) + else() + set(APPLE_TARGET_TRIPLE_INT ${ARCHS_SPLIT}-apple-ios) + endif() + message(DEPRECATION "SIMULATOR IS DEPRECATED. Consider using SIMULATOR64 instead.") +elseif(PLATFORM_INT STREQUAL "SIMULATOR64") + set(SDK_NAME iphonesimulator) + if(NOT ARCHS) + set(ARCHS x86_64) + set(APPLE_TARGET_TRIPLE_INT x86_64-apple-ios) + else() + set(APPLE_TARGET_TRIPLE_INT ${ARCHS_SPLIT}-apple-ios) + endif() +elseif(PLATFORM_INT STREQUAL "SIMULATORARM64") + set(SDK_NAME iphonesimulator) + if(NOT ARCHS) + set(ARCHS arm64) + set(APPLE_TARGET_TRIPLE_INT aarch64-apple-ios) + else() + set(APPLE_TARGET_TRIPLE_INT ${ARCHS_SPLIT}-apple-ios) + endif() +elseif(PLATFORM_INT STREQUAL "TVOS") + set(SDK_NAME appletvos) + if(NOT ARCHS) + set(ARCHS arm64) + set(APPLE_TARGET_TRIPLE_INT aarch64-apple-tvos) + else() + set(APPLE_TARGET_TRIPLE_INT ${ARCHS_SPLIT}-apple-tvos) + endif() +elseif (PLATFORM_INT STREQUAL "TVOSCOMBINED") + set(SDK_NAME appletvos) + if(MODERN_CMAKE) + if(NOT ARCHS) + set(ARCHS arm64 x86_64) + set(APPLE_TARGET_TRIPLE_INT aarch64-x86_64-apple-tvos) + set(CMAKE_XCODE_ATTRIBUTE_ARCHS[sdk=appletvos*] "arm64") + set(CMAKE_XCODE_ATTRIBUTE_ARCHS[sdk=appletvsimulator*] "x86_64") + set(CMAKE_XCODE_ATTRIBUTE_VALID_ARCHS[sdk=appletvos*] "arm64") + set(CMAKE_XCODE_ATTRIBUTE_VALID_ARCHS[sdk=appletvsimulator*] "x86_64") + else() + set(APPLE_TARGET_TRIPLE_INT ${ARCHS_SPLIT}-apple-tvos) + endif() + else() + message(FATAL_ERROR "Please make sure that you are running CMake 3.14+ to make the TVOSCOMBINED setting work") + endif() +elseif(PLATFORM_INT STREQUAL "SIMULATOR_TVOS") + set(SDK_NAME appletvsimulator) + if(NOT ARCHS) + set(ARCHS x86_64) + set(APPLE_TARGET_TRIPLE_INT x86_64-apple-tvos) + else() + set(APPLE_TARGET_TRIPLE_INT ${ARCHS_SPLIT}-apple-tvos) + endif() +elseif(PLATFORM_INT STREQUAL "WATCHOS") + set(SDK_NAME watchos) + if(NOT ARCHS) + if (XCODE_VERSION_INT VERSION_GREATER 10.0) + set(ARCHS armv7k arm64_32) + set(APPLE_TARGET_TRIPLE_INT aarch64_32-apple-watchos) + else() + set(ARCHS armv7k) + set(APPLE_TARGET_TRIPLE_INT arm-apple-watchos) + endif() + else() + set(APPLE_TARGET_TRIPLE_INT ${ARCHS_SPLIT}-apple-watchos) + endif() +elseif(PLATFORM_INT STREQUAL "WATCHOSCOMBINED") + set(SDK_NAME watchos) + if(MODERN_CMAKE) + if(NOT ARCHS) + if (XCODE_VERSION_INT VERSION_GREATER 10.0) + set(ARCHS armv7k arm64_32 i386) + set(APPLE_TARGET_TRIPLE_INT aarch64_32-i386-apple-watchos) + set(CMAKE_XCODE_ATTRIBUTE_ARCHS[sdk=watchos*] "armv7k arm64_32") + set(CMAKE_XCODE_ATTRIBUTE_ARCHS[sdk=watchsimulator*] "i386") + set(CMAKE_XCODE_ATTRIBUTE_VALID_ARCHS[sdk=watchos*] "armv7k arm64_32") + set(CMAKE_XCODE_ATTRIBUTE_VALID_ARCHS[sdk=watchsimulator*] "i386") + else() + set(ARCHS armv7k i386) + set(APPLE_TARGET_TRIPLE_INT arm-i386-apple-watchos) + set(CMAKE_XCODE_ATTRIBUTE_ARCHS[sdk=watchos*] "armv7k") + set(CMAKE_XCODE_ATTRIBUTE_ARCHS[sdk=watchsimulator*] "i386") + set(CMAKE_XCODE_ATTRIBUTE_VALID_ARCHS[sdk=watchos*] "armv7k") + set(CMAKE_XCODE_ATTRIBUTE_VALID_ARCHS[sdk=watchsimulator*] "i386") + endif() + else() + set(APPLE_TARGET_TRIPLE_INT ${ARCHS_SPLIT}-apple-watchos) + endif() + else() + message(FATAL_ERROR "Please make sure that you are running CMake 3.14+ to make the WATCHOSCOMBINED setting work") + endif() +elseif(PLATFORM_INT STREQUAL "SIMULATOR_WATCHOS") + set(SDK_NAME watchsimulator) + if(NOT ARCHS) + set(ARCHS i386) + set(APPLE_TARGET_TRIPLE_INT i386-apple-watchos) + else() + set(APPLE_TARGET_TRIPLE_INT ${ARCHS_SPLIT}-apple-watchos) + endif() +elseif(PLATFORM_INT STREQUAL "MAC" OR PLATFORM_INT STREQUAL "MAC_CATALYST") + set(SDK_NAME macosx) + if(NOT ARCHS) + set(ARCHS x86_64) + endif() + string(REPLACE ";" "-" ARCHS_SPLIT "${ARCHS}") + if(PLATFORM_INT STREQUAL "MAC") + set(APPLE_TARGET_TRIPLE_INT ${ARCHS_SPLIT}-apple-macosx) + elseif(PLATFORM_INT STREQUAL "MAC_CATALYST") + set(APPLE_TARGET_TRIPLE_INT ${ARCHS_SPLIT}-apple-ios${DEPLOYMENT_TARGET}-macabi) + endif() +elseif(PLATFORM_INT MATCHES "^(MAC_ARM64)$|^(MAC_CATALYST_ARM64)$") + set(SDK_NAME macosx) + if(NOT ARCHS) + set(ARCHS arm64) + endif() + string(REPLACE ";" "-" ARCHS_SPLIT "${ARCHS}") + if(PLATFORM_INT STREQUAL "MAC_ARM64") + set(APPLE_TARGET_TRIPLE_INT ${ARCHS_SPLIT}-apple-macosx) + elseif(PLATFORM_INT STREQUAL "MAC_CATALYST_ARM64") + set(APPLE_TARGET_TRIPLE_INT ${ARCHS_SPLIT}-apple-ios${DEPLOYMENT_TARGET}-macabi) + endif() +else() + message(FATAL_ERROR "Invalid PLATFORM: ${PLATFORM_INT}") +endif() + +if(MODERN_CMAKE AND PLATFORM_INT MATCHES ".*COMBINED" AND NOT CMAKE_GENERATOR MATCHES "Xcode") + message(FATAL_ERROR "The COMBINED options only work with Xcode generator, -G Xcode") +endif() + +if(CMAKE_GENERATOR MATCHES "Xcode" AND PLATFORM_INT MATCHES "MAC_CATALYST_.*") + set(CMAKE_XCODE_ATTRIBUTE_CLANG_CXX_LIBRARY "libc++") + set(CMAKE_XCODE_ATTRIBUTE_SUPPORTED_PLATFORMS "macosx") + set(CMAKE_XCODE_EFFECTIVE_PLATFORMS "-maccatalyst") + if(NOT DEFINED MACOSX_DEPLOYMENT_TARGET) + set(CMAKE_XCODE_ATTRIBUTE_MACOSX_DEPLOYMENT_TARGET "10.15") + else() + set(CMAKE_XCODE_ATTRIBUTE_MACOSX_DEPLOYMENT_TARGET "${MACOSX_DEPLOYMENT_TARGET}") + endif() +elseif(CMAKE_GENERATOR MATCHES "Xcode") + set(CMAKE_XCODE_ATTRIBUTE_IPHONEOS_DEPLOYMENT_TARGET "${DEPLOYMENT_TARGET}") + if(NOT PLATFORM_INT MATCHES ".*COMBINED") + set(CMAKE_XCODE_ATTRIBUTE_ARCHS[sdk=${SDK_NAME}*] "${ARCHS}") + set(CMAKE_XCODE_ATTRIBUTE_VALID_ARCHS[sdk=${SDK_NAME}*] "${ARCHS}") + endif() +endif() + +# If user did not specify the SDK root to use, then query xcodebuild for it. +if(DEFINED CMAKE_OSX_SYSROOT_INT) + # Environment variables are always preserved. + set(ENV{_CMAKE_OSX_SYSROOT_INT} "${CMAKE_OSX_SYSROOT_INT}") +elseif(DEFINED ENV{_CMAKE_OSX_SYSROOT_INT}) + set(CMAKE_OSX_SYSROOT_INT "$ENV{_CMAKE_OSX_SYSROOT_INT}") +elseif(NOT DEFINED CMAKE_OSX_SYSROOT_INT) + execute_process(COMMAND ${XCODEBUILD_EXECUTABLE} -version -sdk ${SDK_NAME} Path + OUTPUT_VARIABLE CMAKE_OSX_SYSROOT_INT + ERROR_QUIET + OUTPUT_STRIP_TRAILING_WHITESPACE) +endif() + +if (NOT DEFINED CMAKE_OSX_SYSROOT_INT AND NOT DEFINED CMAKE_OSX_SYSROOT) + message(SEND_ERROR "Please make sure that Xcode is installed and that the toolchain" + "is pointing to the correct path. Please run:" + "sudo xcode-select -s /Applications/Xcode.app/Contents/Developer" + "and see if that fixes the problem for you.") + message(FATAL_ERROR "Invalid CMAKE_OSX_SYSROOT: ${CMAKE_OSX_SYSROOT} " + "does not exist.") +elseif(DEFINED CMAKE_OSX_SYSROOT_INT) + set(CMAKE_OSX_SYSROOT_INT "${CMAKE_OSX_SYSROOT_INT}" CACHE INTERNAL "") + # Specify the location or name of the platform SDK to be used in CMAKE_OSX_SYSROOT. + set(CMAKE_OSX_SYSROOT "${CMAKE_OSX_SYSROOT_INT}" CACHE INTERNAL "") +endif() + +# Use bitcode or not +if(NOT DEFINED ENABLE_BITCODE AND NOT ARCHS MATCHES "((^|;|, )(i386|x86_64))+") + # Unless specified, enable bitcode support by default + message(STATUS "[DEFAULTS] Enabling bitcode support by default. ENABLE_BITCODE not provided!") + set(ENABLE_BITCODE TRUE) +elseif(NOT DEFINED ENABLE_BITCODE) + message(STATUS "[DEFAULTS] Disabling bitcode support by default on simulators. ENABLE_BITCODE not provided for override!") + set(ENABLE_BITCODE FALSE) +endif() +set(ENABLE_BITCODE_INT ${ENABLE_BITCODE} CACHE BOOL + "Whether or not to enable bitcode" FORCE) +# Use ARC or not +if(NOT DEFINED ENABLE_ARC) + # Unless specified, enable ARC support by default + set(ENABLE_ARC TRUE) + message(STATUS "[DEFAULTS] Enabling ARC support by default. ENABLE_ARC not provided!") +endif() +set(ENABLE_ARC_INT ${ENABLE_ARC} CACHE BOOL "Whether or not to enable ARC" FORCE) +# Use hidden visibility or not +if(NOT DEFINED ENABLE_VISIBILITY) + # Unless specified, disable symbols visibility by default + set(ENABLE_VISIBILITY FALSE) + message(STATUS "[DEFAULTS] Hiding symbols visibility by default. ENABLE_VISIBILITY not provided!") +endif() +set(ENABLE_VISIBILITY_INT ${ENABLE_VISIBILITY} CACHE BOOL "Whether or not to hide symbols from the dynamic linker (-fvisibility=hidden)" FORCE) +# Set strict compiler checks or not +if(NOT DEFINED ENABLE_STRICT_TRY_COMPILE) + # Unless specified, disable strict try_compile() + set(ENABLE_STRICT_TRY_COMPILE FALSE) + message(STATUS "[DEFAULTS] Using NON-strict compiler checks by default. ENABLE_STRICT_TRY_COMPILE not provided!") +endif() +set(ENABLE_STRICT_TRY_COMPILE_INT ${ENABLE_STRICT_TRY_COMPILE} CACHE BOOL + "Whether or not to use strict compiler checks" FORCE) + +# Get the SDK version information. +if(DEFINED SDK_VERSION) + # Environment variables are always preserved. + set(ENV{_SDK_VERSION} "${SDK_VERSION}") +elseif(DEFINED ENV{_SDK_VERSION}) + set(SDK_VERSION "$ENV{_SDK_VERSION}") +elseif(NOT DEFINED SDK_VERSION) + execute_process(COMMAND ${XCODEBUILD_EXECUTABLE} -sdk ${CMAKE_OSX_SYSROOT_INT} -version SDKVersion + OUTPUT_VARIABLE SDK_VERSION + ERROR_QUIET + OUTPUT_STRIP_TRAILING_WHITESPACE) +endif() + +# Find the Developer root for the specific iOS platform being compiled for +# from CMAKE_OSX_SYSROOT. Should be ../../ from SDK specified in +# CMAKE_OSX_SYSROOT. There does not appear to be a direct way to obtain +# this information from xcrun or xcodebuild. +if (NOT DEFINED CMAKE_DEVELOPER_ROOT AND NOT CMAKE_GENERATOR MATCHES "Xcode") + get_filename_component(PLATFORM_SDK_DIR ${CMAKE_OSX_SYSROOT_INT} PATH) + get_filename_component(CMAKE_DEVELOPER_ROOT ${PLATFORM_SDK_DIR} PATH) + if (NOT EXISTS "${CMAKE_DEVELOPER_ROOT}") + message(FATAL_ERROR "Invalid CMAKE_DEVELOPER_ROOT: ${CMAKE_DEVELOPER_ROOT} does not exist.") + endif() +endif() + +# Find the C & C++ compilers for the specified SDK. +if(DEFINED CMAKE_C_COMPILER) + # Environment variables are always preserved. + set(ENV{_CMAKE_C_COMPILER} "${CMAKE_C_COMPILER}") +elseif(DEFINED ENV{_CMAKE_C_COMPILER}) + set(CMAKE_C_COMPILER "$ENV{_CMAKE_C_COMPILER}") +elseif(NOT DEFINED CMAKE_C_COMPILER) + execute_process(COMMAND xcrun -sdk ${CMAKE_OSX_SYSROOT_INT} -find clang + OUTPUT_VARIABLE CMAKE_C_COMPILER + ERROR_QUIET + OUTPUT_STRIP_TRAILING_WHITESPACE) +endif() +if(DEFINED CMAKE_CXX_COMPILER) + # Environment variables are always preserved. + set(ENV{_CMAKE_CXX_COMPILER} "${CMAKE_CXX_COMPILER}") +elseif(DEFINED ENV{_CMAKE_CXX_COMPILER}) + set(CMAKE_CXX_COMPILER "$ENV{_CMAKE_CXX_COMPILER}") +elseif(NOT DEFINED CMAKE_CXX_COMPILER) + execute_process(COMMAND xcrun -sdk ${CMAKE_OSX_SYSROOT_INT} -find clang++ + OUTPUT_VARIABLE CMAKE_CXX_COMPILER + ERROR_QUIET + OUTPUT_STRIP_TRAILING_WHITESPACE) +endif() +# Find (Apple's) libtool. +if(DEFINED BUILD_LIBTOOL) + # Environment variables are always preserved. + set(ENV{_BUILD_LIBTOOL} "${BUILD_LIBTOOL}") +elseif(DEFINED ENV{_BUILD_LIBTOOL}) + set(BUILD_LIBTOOL "$ENV{_BUILD_LIBTOOL}") +elseif(NOT DEFINED BUILD_LIBTOOL) + execute_process(COMMAND xcrun -sdk ${CMAKE_OSX_SYSROOT_INT} -find libtool + OUTPUT_VARIABLE BUILD_LIBTOOL + ERROR_QUIET + OUTPUT_STRIP_TRAILING_WHITESPACE) +endif() +# Find the toolchain's provided install_name_tool if none is found on the host +if(DEFINED CMAKE_INSTALL_NAME_TOOL) + # Environment variables are always preserved. + set(ENV{_CMAKE_INSTALL_NAME_TOOL} "${CMAKE_INSTALL_NAME_TOOL}") +elseif(DEFINED ENV{_CMAKE_INSTALL_NAME_TOOL}) + set(CMAKE_INSTALL_NAME_TOOL "$ENV{_CMAKE_INSTALL_NAME_TOOL}") +elseif(NOT DEFINED CMAKE_INSTALL_NAME_TOOL) + execute_process(COMMAND xcrun -sdk ${CMAKE_OSX_SYSROOT_INT} -find install_name_tool + OUTPUT_VARIABLE CMAKE_INSTALL_NAME_TOOL_INT + ERROR_QUIET + OUTPUT_STRIP_TRAILING_WHITESPACE) + set(CMAKE_INSTALL_NAME_TOOL ${CMAKE_INSTALL_NAME_TOOL_INT} CACHE INTERNAL "") +endif() + +# Configure libtool to be used instead of ar + ranlib to build static libraries. +# This is required on Xcode 7+, but should also work on previous versions of +# Xcode. +get_property(languages GLOBAL PROPERTY ENABLED_LANGUAGES) +foreach(lang ${languages}) + set(CMAKE_${lang}_CREATE_STATIC_LIBRARY "${BUILD_LIBTOOL} -static -o " CACHE INTERNAL "") +endforeach() + +# CMake 3.14+ support building for iOS, watchOS and tvOS out of the box. +if(MODERN_CMAKE) + if(SDK_NAME MATCHES "iphone") + set(CMAKE_SYSTEM_NAME iOS) + elseif(SDK_NAME MATCHES "macosx") + set(CMAKE_SYSTEM_NAME Darwin) + elseif(SDK_NAME MATCHES "appletv") + set(CMAKE_SYSTEM_NAME tvOS) + elseif(SDK_NAME MATCHES "watch") + set(CMAKE_SYSTEM_NAME watchOS) + endif() + # Provide flags for a combined FAT library build on newer CMake versions + if(PLATFORM_INT MATCHES ".*COMBINED") + set(CMAKE_XCODE_ATTRIBUTE_ONLY_ACTIVE_ARCH "NO") + set(CMAKE_IOS_INSTALL_COMBINED YES) + message(STATUS "Will combine built (static) artifacts into FAT lib...") + endif() +elseif(NOT DEFINED CMAKE_SYSTEM_NAME AND ${CMAKE_VERSION} VERSION_GREATER_EQUAL "3.10") + # Legacy code path prior to CMake 3.14 or fallback if no CMAKE_SYSTEM_NAME specified + set(CMAKE_SYSTEM_NAME iOS) +elseif(NOT DEFINED CMAKE_SYSTEM_NAME) + # Legacy code path prior to CMake 3.14 or fallback if no CMAKE_SYSTEM_NAME specified + set(CMAKE_SYSTEM_NAME Darwin) +endif() +# Standard settings. +set(CMAKE_SYSTEM_VERSION ${SDK_VERSION} CACHE INTERNAL "") +set(UNIX TRUE CACHE BOOL "") +set(APPLE TRUE CACHE BOOL "") +if(PLATFORM STREQUAL "MAC" OR PLATFORM STREQUAL "MAC_ARM64") + set(IOS FALSE CACHE BOOL "") + set(MACOS TRUE CACHE BOOL "") +elseif(PLATFORM STREQUAL "MAC_CATALYST" OR PLATFORM STREQUAL "MAC_CATALYST_ARM64") + set(IOS TRUE CACHE BOOL "") + set(MACOS TRUE CACHE BOOL "") +else() + set(IOS TRUE CACHE BOOL "") +endif() +set(CMAKE_AR ar CACHE FILEPATH "" FORCE) +set(CMAKE_RANLIB ranlib CACHE FILEPATH "" FORCE) +set(CMAKE_STRIP strip CACHE FILEPATH "" FORCE) +# Set the architectures for which to build. +set(CMAKE_OSX_ARCHITECTURES ${ARCHS} CACHE INTERNAL "") +# Change the type of target generated for try_compile() so it'll work when cross-compiling, weak compiler checks +if(NOT ENABLE_STRICT_TRY_COMPILE_INT) + set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY) +endif() +# All iOS/Darwin specific settings - some may be redundant. +set(CMAKE_MACOSX_BUNDLE YES) +set(CMAKE_XCODE_ATTRIBUTE_CODE_SIGNING_REQUIRED "NO") +set(CMAKE_XCODE_ATTRIBUTE_CODE_SIGNING_ALLOWED "NO") +set(CMAKE_SHARED_LIBRARY_PREFIX "lib") +set(CMAKE_SHARED_LIBRARY_SUFFIX ".dylib") +set(CMAKE_SHARED_MODULE_PREFIX "lib") +set(CMAKE_SHARED_MODULE_SUFFIX ".so") +set(CMAKE_C_COMPILER_ABI ELF) +set(CMAKE_CXX_COMPILER_ABI ELF) +set(CMAKE_C_HAS_ISYSROOT 1) +set(CMAKE_CXX_HAS_ISYSROOT 1) +set(CMAKE_MODULE_EXISTS 1) +set(CMAKE_DL_LIBS "") +set(CMAKE_C_OSX_COMPATIBILITY_VERSION_FLAG "-compatibility_version ") +set(CMAKE_C_OSX_CURRENT_VERSION_FLAG "-current_version ") +set(CMAKE_CXX_OSX_COMPATIBILITY_VERSION_FLAG "${CMAKE_C_OSX_COMPATIBILITY_VERSION_FLAG}") +set(CMAKE_CXX_OSX_CURRENT_VERSION_FLAG "${CMAKE_C_OSX_CURRENT_VERSION_FLAG}") + +if(ARCHS MATCHES "((^|;|, )(arm64|arm64e|x86_64))+") + set(CMAKE_C_SIZEOF_DATA_PTR 8) + set(CMAKE_CXX_SIZEOF_DATA_PTR 8) + if(ARCHS MATCHES "((^|;|, )(arm64|arm64e))+") + set(CMAKE_SYSTEM_PROCESSOR "aarch64") + else() + set(CMAKE_SYSTEM_PROCESSOR "x86_64") + endif() +else() + set(CMAKE_C_SIZEOF_DATA_PTR 4) + set(CMAKE_CXX_SIZEOF_DATA_PTR 4) + set(CMAKE_SYSTEM_PROCESSOR "arm") +endif() + +# Note that only Xcode 7+ supports the newer more specific: +# -m${SDK_NAME}-version-min flags, older versions of Xcode use: +# -m(ios/ios-simulator)-version-min instead. +if(${CMAKE_VERSION} VERSION_LESS "3.11") + if(PLATFORM_INT STREQUAL "OS" OR PLATFORM_INT STREQUAL "OS64") + if(XCODE_VERSION_INT VERSION_LESS 7.0) + set(SDK_NAME_VERSION_FLAGS + "-mios-version-min=${DEPLOYMENT_TARGET}") + else() + # Xcode 7.0+ uses flags we can build directly from SDK_NAME. + set(SDK_NAME_VERSION_FLAGS + "-m${SDK_NAME}-version-min=${DEPLOYMENT_TARGET}") + endif() + elseif(PLATFORM_INT STREQUAL "TVOS") + set(SDK_NAME_VERSION_FLAGS + "-mtvos-version-min=${DEPLOYMENT_TARGET}") + elseif(PLATFORM_INT STREQUAL "SIMULATOR_TVOS") + set(SDK_NAME_VERSION_FLAGS + "-mtvos-simulator-version-min=${DEPLOYMENT_TARGET}") + elseif(PLATFORM_INT STREQUAL "WATCHOS") + set(SDK_NAME_VERSION_FLAGS + "-mwatchos-version-min=${DEPLOYMENT_TARGET}") + elseif(PLATFORM_INT STREQUAL "SIMULATOR_WATCHOS") + set(SDK_NAME_VERSION_FLAGS + "-mwatchos-simulator-version-min=${DEPLOYMENT_TARGET}") + elseif(PLATFORM_INT STREQUAL "MAC") + set(SDK_NAME_VERSION_FLAGS + "-mmacosx-version-min=${DEPLOYMENT_TARGET}") + else() + # SIMULATOR or SIMULATOR64 both use -mios-simulator-version-min. + set(SDK_NAME_VERSION_FLAGS + "-mios-simulator-version-min=${DEPLOYMENT_TARGET}") + endif() +elseif(NOT PLATFORM_INT STREQUAL "MAC_CATALYST") + # Newer versions of CMake sets the version min flags correctly, skip this for Mac Catalyst targets + set(CMAKE_OSX_DEPLOYMENT_TARGET ${DEPLOYMENT_TARGET}) +endif() + +if(DEFINED APPLE_TARGET_TRIPLE_INT) + set(APPLE_TARGET_TRIPLE ${APPLE_TARGET_TRIPLE_INT} CACHE INTERNAL "") +endif() + +if(PLATFORM_INT STREQUAL "MAC_CATALYST") + set(C_TARGET_FLAGS "-target ${APPLE_TARGET_TRIPLE_INT} -isystem ${CMAKE_OSX_SYSROOT_INT}/System/iOSSupport/usr/include") +endif() + +if(ENABLE_BITCODE_INT) + set(BITCODE "-fembed-bitcode") + set(CMAKE_XCODE_ATTRIBUTE_BITCODE_GENERATION_MODE "bitcode") + set(CMAKE_XCODE_ATTRIBUTE_ENABLE_BITCODE "YES") +else() + set(BITCODE "") + set(CMAKE_XCODE_ATTRIBUTE_ENABLE_BITCODE "NO") +endif() + +if(ENABLE_ARC_INT) + set(FOBJC_ARC "-fobjc-arc") + set(CMAKE_XCODE_ATTRIBUTE_CLANG_ENABLE_OBJC_ARC "YES") +else() + set(FOBJC_ARC "-fno-objc-arc") + set(CMAKE_XCODE_ATTRIBUTE_CLANG_ENABLE_OBJC_ARC "NO") +endif() + +if(NOT ENABLE_VISIBILITY_INT) + foreach(lang ${languages}) + set(CMAKE_${lang}_VISIBILITY_PRESET "hidden" CACHE INTERNAL "") + endforeach() + set(CMAKE_XCODE_ATTRIBUTE_GCC_SYMBOLS_PRIVATE_EXTERN "YES") + set(VISIBILITY "-fvisibility=hidden -fvisibility-inlines-hidden") +else() + foreach(lang ${languages}) + set(CMAKE_${lang}_VISIBILITY_PRESET "default" CACHE INTERNAL "") + endforeach() + set(CMAKE_XCODE_ATTRIBUTE_GCC_SYMBOLS_PRIVATE_EXTERN "NO") + set(VISIBILITY "-fvisibility=default") +endif() + +#Check if Xcode generator is used, since that will handle these flags automagically +if(CMAKE_GENERATOR MATCHES "Xcode") + message(STATUS "Not setting any manual command-line buildflags, since Xcode is selected as generator.") +else() + # Hidden visibility is required for C++ on iOS. + set(CMAKE_C_FLAGS "${C_TARGET_FLAGS} ${SDK_NAME_VERSION_FLAGS} ${BITCODE} -fobjc-abi-version=2 ${FOBJC_ARC} ${CMAKE_C_FLAGS}") + set(CMAKE_CXX_FLAGS "${C_TARGET_FLAGS} ${SDK_NAME_VERSION_FLAGS} ${BITCODE} ${VISIBILITY} -fobjc-abi-version=2 ${FOBJC_ARC} ${CMAKE_CXX_FLAGS}") + set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS} -O0 -g ${CMAKE_CXX_FLAGS_DEBUG}") + set(CMAKE_CXX_FLAGS_MINSIZEREL "${CMAKE_CXX_FLAGS} -DNDEBUG -Os -ffast-math ${CMAKE_CXX_FLAGS_MINSIZEREL}") + set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS} -DNDEBUG -O2 -g -ffast-math ${CMAKE_CXX_FLAGS_RELWITHDEBINFO}") + set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS} -DNDEBUG -O3 -ffast-math ${CMAKE_CXX_FLAGS_RELEASE}") + set(CMAKE_C_LINK_FLAGS "${C_TARGET_FLAGS} ${SDK_NAME_VERSION_FLAGS} -Wl,-search_paths_first ${CMAKE_C_LINK_FLAGS}") + set(CMAKE_CXX_LINK_FLAGS "${C_TARGET_FLAGS} ${SDK_NAME_VERSION_FLAGS} -Wl,-search_paths_first ${CMAKE_CXX_LINK_FLAGS}") + set(CMAKE_ASM_FLAGS "${CMAKE_C_FLAGS} -x assembler-with-cpp -arch ${CMAKE_OSX_ARCHITECTURES}") +endif() + +## Print status messages to inform of the current state +message(STATUS "Configuring ${SDK_NAME} build for platform: ${PLATFORM_INT}, architecture(s): ${ARCHS}") +message(STATUS "Using SDK: ${CMAKE_OSX_SYSROOT_INT}") +message(STATUS "Using C compiler: ${CMAKE_C_COMPILER}") +message(STATUS "Using CXX compiler: ${CMAKE_CXX_COMPILER}") +message(STATUS "Using libtool: ${BUILD_LIBTOOL}") +message(STATUS "Using install name tool: ${CMAKE_INSTALL_NAME_TOOL}") +if(DEFINED APPLE_TARGET_TRIPLE) + message(STATUS "Autoconf target triple: ${APPLE_TARGET_TRIPLE}") +endif() +message(STATUS "Using minimum deployment version: ${DEPLOYMENT_TARGET}" + " (SDK version: ${SDK_VERSION})") +if(MODERN_CMAKE) + message(STATUS "Merging integrated CMake 3.14+ iOS,tvOS,watchOS,macOS toolchain(s) with this toolchain!") +endif() +if(CMAKE_GENERATOR MATCHES "Xcode") + message(STATUS "Using Xcode version: ${XCODE_VERSION_INT}") +endif() +message(STATUS "CMake version: ${CMAKE_VERSION}") +if(DEFINED SDK_NAME_VERSION_FLAGS) + message(STATUS "Using version flags: ${SDK_NAME_VERSION_FLAGS}") +endif() +message(STATUS "Using a data_ptr size of: ${CMAKE_CXX_SIZEOF_DATA_PTR}") +if(ENABLE_BITCODE_INT) + message(STATUS "Bitcode: Enabled") +else() + message(STATUS "Bitcode: Disabled") +endif() + +if(ENABLE_ARC_INT) + message(STATUS "ARC: Enabled") +else() + message(STATUS "ARC: Disabled") +endif() + +if(ENABLE_VISIBILITY_INT) + message(STATUS "Hiding symbols: Disabled") +else() + message(STATUS "Hiding symbols: Enabled") +endif() + +# Set global properties +set_property(GLOBAL PROPERTY PLATFORM "${PLATFORM}") +set_property(GLOBAL PROPERTY APPLE_TARGET_TRIPLE "${APPLE_TARGET_TRIPLE_INT}") +set_property(GLOBAL PROPERTY SDK_VERSION "${SDK_VERSION}") +set_property(GLOBAL PROPERTY XCODE_VERSION "${XCODE_VERSION_INT}") +set_property(GLOBAL PROPERTY OSX_ARCHITECTURES "${CMAKE_OSX_ARCHITECTURES}") + +# Export configurable variables for the try_compile() command. +set(CMAKE_TRY_COMPILE_PLATFORM_VARIABLES + PLATFORM + XCODE_VERSION_INT + SDK_VERSION + DEPLOYMENT_TARGET + CMAKE_DEVELOPER_ROOT + CMAKE_OSX_SYSROOT_INT + ENABLE_BITCODE + ENABLE_ARC + CMAKE_C_COMPILER + CMAKE_CXX_COMPILER + BUILD_LIBTOOL + CMAKE_INSTALL_NAME_TOOL + CMAKE_C_FLAGS + CMAKE_CXX_FLAGS + CMAKE_CXX_FLAGS_DEBUG + CMAKE_CXX_FLAGS_MINSIZEREL + CMAKE_CXX_FLAGS_RELWITHDEBINFO + CMAKE_CXX_FLAGS_RELEASE + CMAKE_C_LINK_FLAGS + CMAKE_CXX_LINK_FLAGS + CMAKE_ASM_FLAGS + ) + +set(CMAKE_PLATFORM_HAS_INSTALLNAME 1) +set(CMAKE_SHARED_LINKER_FLAGS "-rpath @executable_path/Frameworks -rpath @loader_path/Frameworks") +set(CMAKE_SHARED_LIBRARY_CREATE_C_FLAGS "-dynamiclib -Wl,-headerpad_max_install_names") +set(CMAKE_SHARED_MODULE_CREATE_C_FLAGS "-bundle -Wl,-headerpad_max_install_names") +set(CMAKE_SHARED_MODULE_LOADER_C_FLAG "-Wl,-bundle_loader,") +set(CMAKE_SHARED_MODULE_LOADER_CXX_FLAG "-Wl,-bundle_loader,") +set(CMAKE_FIND_LIBRARY_SUFFIXES ".tbd" ".dylib" ".so" ".a") +set(CMAKE_SHARED_LIBRARY_SONAME_C_FLAG "-install_name") + +# Set the find root to the SDK developer roots. +# Note: CMAKE_FIND_ROOT_PATH is only useful when cross-compiling. Thus, do not set on macOS builds. +if(NOT PLATFORM_INT STREQUAL "MAC" AND NOT PLATFORM_INT STREQUAL "MAC_ARM64") + list(APPEND CMAKE_FIND_ROOT_PATH "${CMAKE_OSX_SYSROOT_INT}" CACHE INTERNAL "") + set(CMAKE_IGNORE_PATH "/System/Library/Frameworks;/usr/local/lib" CACHE INTERNAL "") +endif() + +# Default to searching for frameworks first. +set(CMAKE_FIND_FRAMEWORK FIRST) + +# Set up the default search directories for frameworks. +if(PLATFORM_INT MATCHES "MAC_CATALYST.*") + set(CMAKE_FRAMEWORK_PATH + ${CMAKE_DEVELOPER_ROOT}/Library/PrivateFrameworks + ${CMAKE_OSX_SYSROOT_INT}/System/Library/Frameworks + ${CMAKE_OSX_SYSROOT_INT}/System/iOSSupport/System/Library/Frameworks + ${CMAKE_FRAMEWORK_PATH} CACHE INTERNAL "") +else() + set(CMAKE_FRAMEWORK_PATH + ${CMAKE_DEVELOPER_ROOT}/Library/PrivateFrameworks + ${CMAKE_OSX_SYSROOT_INT}/System/Library/Frameworks + ${CMAKE_FRAMEWORK_PATH} CACHE INTERNAL "") +endif() + +# By default, search both the specified iOS SDK and the remainder of the host filesystem. +if(NOT CMAKE_FIND_ROOT_PATH_MODE_PROGRAM) + set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM BOTH CACHE INTERNAL "") +endif() +if(NOT CMAKE_FIND_ROOT_PATH_MODE_LIBRARY) + set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY BOTH CACHE INTERNAL "") +endif() +if(NOT CMAKE_FIND_ROOT_PATH_MODE_INCLUDE) + set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE BOTH CACHE INTERNAL "") +endif() +if(NOT CMAKE_FIND_ROOT_PATH_MODE_PACKAGE) + set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE BOTH CACHE INTERNAL "") +endif() + +# +# Some helper-macros below to simplify and beautify the CMakeFile +# + +# This little macro lets you set any Xcode specific property. +macro(set_xcode_property TARGET XCODE_PROPERTY XCODE_VALUE XCODE_RELVERSION) + set(XCODE_RELVERSION_I "${XCODE_RELVERSION}") + if(XCODE_RELVERSION_I STREQUAL "All") + set_property(TARGET ${TARGET} PROPERTY XCODE_ATTRIBUTE_${XCODE_PROPERTY} "${XCODE_VALUE}") + else() + set_property(TARGET ${TARGET} PROPERTY XCODE_ATTRIBUTE_${XCODE_PROPERTY}[variant=${XCODE_RELVERSION_I}] "${XCODE_VALUE}") + endif() +endmacro(set_xcode_property) + +# This macro lets you find executable programs on the host system. +macro(find_host_package) + set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) + set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY NEVER) + set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE NEVER) + set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE NEVER) + set(_TOOLCHAIN_IOS ${IOS}) + set(IOS FALSE) + find_package(${ARGN}) + set(IOS ${_TOOLCHAIN_IOS}) + set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM BOTH) + set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY BOTH) + set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE BOTH) + set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE BOTH) +endmacro(find_host_package) diff --git a/integration_test_app/iris_integration_test/src/fake_rtc_engine.h b/integration_test_app/iris_integration_test/src/fake_rtc_engine.h new file mode 100644 index 000000000..bebb66d15 --- /dev/null +++ b/integration_test_app/iris_integration_test/src/fake_rtc_engine.h @@ -0,0 +1,83 @@ +#ifndef FAKE_RTC_ENGINE_H_ +#define FAKE_RTC_ENGINE_H_ + +#include "fake_rtc_engine_internal.h" + +namespace agora +{ + namespace rtc + { + class FakeRtcChannel : public FakeChannelInternal + { + public: + IChannelEventHandler *channel_event_handler_; + FakeRtcChannel() {} + ~FakeRtcChannel() override {} + int release() override + { + return 0; + } + + int setChannelEventHandler(IChannelEventHandler *channelEh) override + { + channel_event_handler_ = channelEh; + return 0; + } + + int createDataStream(int *streamId, bool reliable, bool ordered) override + { + *streamId = 100; + return 0; + } + int createDataStream(int *streamId, DataStreamConfig &config) override + { + *streamId = 100; + return 0; + } + }; + + class FakeRtcEngine : public agora::rtc::FakeRtcEngineInternal + { + + public: + FakeRtcChannel *channel_; + IRtcEngineEventHandler *event_handler_; + + FakeRtcEngine() : channel_(nullptr), event_handler_(nullptr) {} + + ~FakeRtcEngine() override + { + if (channel_) + { + delete channel_; + channel_ = nullptr; + } + } + + IChannel *createChannel(const char *channelId) override + { + channel_ = new FakeRtcChannel(); + return channel_; + } + + bool registerEventHandler(IRtcEngineEventHandler *eventHandler) override + { + event_handler_ = eventHandler; + return 0; + } + + int createDataStream(int *streamId, bool reliable, bool ordered) override + { + *streamId = 100; + return 0; + } + int createDataStream(int *streamId, DataStreamConfig &config) override + { + *streamId = 100; + return 0; + } + }; + } +} + +#endif // FAKE_RTC_ENGINE_H_ \ No newline at end of file diff --git a/integration_test_app/iris_integration_test/src/fake_rtc_engine_internal.h b/integration_test_app/iris_integration_test/src/fake_rtc_engine_internal.h new file mode 100644 index 000000000..9f37f50ab --- /dev/null +++ b/integration_test_app/iris_integration_test/src/fake_rtc_engine_internal.h @@ -0,0 +1,575 @@ +#ifndef FAKE_RTC_ENGINE_INTERNAL_H_ +#define FAKE_RTC_ENGINE_INTERNAL_H_ + +#include "IAgoraRtcEngine2.h" + +namespace agora { +namespace rtc { + +class FakeChannelInternal : public agora::rtc::IChannel { + public: + ~FakeChannelInternal() override {} + virtual int release() override { return 0; } + virtual int setChannelEventHandler(IChannelEventHandler *channelEh) override { + return 0; + } + int joinChannel(const char *token, const char *info, uid_t uid, + const ChannelMediaOptions &options) override { + return 0; + } + int joinChannelWithUserAccount(const char *token, const char *userAccount, + const ChannelMediaOptions &options) override { + return 0; + } + int leaveChannel() override { return 0; } + int publish() override { return 0; } + int unpublish() override { return 0; } + const char *channelId() override { return "testapi"; } + int getCallId(util::AString &callId) override { return 0; } + int renewToken(const char *token) override { return 0; } + int setEncryptionSecret(const char *secret) override { return 0; } + int setEncryptionMode(const char *encryptionMode) override { return 0; } + int enableEncryption(bool enabled, const EncryptionConfig &config) override { + return 0; + } + int registerPacketObserver(IPacketObserver *observer) override { return 0; } + int registerMediaMetadataObserver( + IMetadataObserver *observer, + IMetadataObserver::METADATA_TYPE type) override { + return 0; + } + int setClientRole(CLIENT_ROLE_TYPE role) override { return 0; } + int setClientRole(CLIENT_ROLE_TYPE role, + const ClientRoleOptions &options) override { + return 0; + } + + int setRemoteUserPriority(uid_t uid, PRIORITY_TYPE userPriority) override { + return 0; + } + int setRemoteVoicePosition(uid_t uid, double pan, double gain) override { + return 0; + } + int setRemoteRenderMode(uid_t userId, RENDER_MODE_TYPE renderMode, + VIDEO_MIRROR_MODE_TYPE mirrorMode) override { + return 0; + } + int setDefaultMuteAllRemoteAudioStreams(bool mute) override { return 0; } + int setDefaultMuteAllRemoteVideoStreams(bool mute) override { return 0; } + int muteLocalAudioStream(bool mute) override { return 0; } + int muteLocalVideoStream(bool mute) override { return 0; } + int muteAllRemoteAudioStreams(bool mute) override { return 0; } + int adjustUserPlaybackSignalVolume(uid_t userId, int volume) override { + return 0; + } + int muteRemoteAudioStream(uid_t userId, bool mute) override { return 0; } + int muteAllRemoteVideoStreams(bool mute) override { return 0; } + int muteRemoteVideoStream(uid_t userId, bool mute) override { return 0; } + int setRemoteVideoStreamType(uid_t userId, + REMOTE_VIDEO_STREAM_TYPE streamType) override { + return 0; + } + int setRemoteDefaultVideoStreamType( + REMOTE_VIDEO_STREAM_TYPE streamType) override { + return 0; + } + virtual int createDataStream(int *streamId, bool reliable, bool ordered) override { + return 0; + } + virtual int createDataStream(int *streamId, DataStreamConfig &config) override { + return 0; + } + int sendStreamMessage(int streamId, const char *data, + size_t length) override { + return 0; + } + int addPublishStreamUrl(const char *url, bool transcodingEnabled) override { + return 0; + } + int removePublishStreamUrl(const char *url) override { return 0; } + int setLiveTranscoding(const LiveTranscoding &transcoding) override { + return 0; + } + int addInjectStreamUrl(const char *url, + const InjectStreamConfig &config) override { + return 0; + } + int removeInjectStreamUrl(const char *url) override { return 0; } + int startChannelMediaRelay( + const ChannelMediaRelayConfiguration &configuration) override { + return 0; + } + int updateChannelMediaRelay( + const ChannelMediaRelayConfiguration &configuration) override { + return 0; + } + int pauseAllChannelMediaRelay() override { return 0; } + int resumeAllChannelMediaRelay() override { return 0; } + int stopChannelMediaRelay() override { return 0; } + CONNECTION_STATE_TYPE getConnectionState() override { + return CONNECTION_STATE_CONNECTING; + } + int enableRemoteSuperResolution(uid_t userId, bool enable) override { + return 0; + } +}; + +class FakeRtcEngineInternal : public IRtcEngine3 { + public: + int setVideoProfileEx(int width, int height, int frameRate, + int bitrate) override { + return 0; + } + int setAppType(AppType appType) override { return 0; } + + public: + virtual IChannel *createChannel(const char *channelId) override { + return new FakeChannelInternal(); + } + + public: + int initialize(const RtcEngineContext &context) override { return 0; } + int setChannelProfile(CHANNEL_PROFILE_TYPE profile) override { return 0; } + int setClientRole(CLIENT_ROLE_TYPE role) override { return 0; } + int setClientRole(CLIENT_ROLE_TYPE role, + const ClientRoleOptions &options) override { + return 0; + } + int joinChannel(const char *token, const char *channelId, const char *info, + uid_t uid) override { + return 0; + } + int joinChannel(const char *token, const char *channelId, const char *info, + uid_t uid, const ChannelMediaOptions &options) override { + return 0; + } + int switchChannel(const char *token, const char *channelId) override { + return 0; + } + int switchChannel(const char *token, const char *channelId, + const ChannelMediaOptions &options) override { + return 0; + } + int leaveChannel() override { return 0; } + int renewToken(const char *token) override { return 0; } + int queryInterface(INTERFACE_ID_TYPE iid, void **inter) override { return 0; } + int registerLocalUserAccount(const char *appId, + const char *userAccount) override { + return 0; + } + int joinChannelWithUserAccount(const char *token, const char *channelId, + const char *userAccount) override { + return 0; + } + int joinChannelWithUserAccount(const char *token, const char *channelId, + const char *userAccount, + const ChannelMediaOptions &options) override { + return 0; + } + int getUserInfoByUserAccount(const char *userAccount, + UserInfo *userInfo) override { + return 0; + } + int getUserInfoByUid(uid_t uid, UserInfo *userInfo) override { return 0; } + int startEchoTest() override { return 0; } + int startEchoTest(int intervalInSeconds) override { return 0; } + int startEchoTest(const EchoTestConfiguration &config) override { return 0; } + int stopEchoTest() override { return 0; } + int setCloudProxy(CLOUD_PROXY_TYPE proxyType) override { return 0; } + int enableVideo() override { return 0; } + int disableVideo() override { return 0; } + int setVideoProfile(VIDEO_PROFILE_TYPE profile, + bool swapWidthAndHeight) override { + return 0; + } + int setVideoEncoderConfiguration( + const VideoEncoderConfiguration &config) override { + return 0; + } + int setCameraCapturerConfiguration( + const CameraCapturerConfiguration &config) override { + return 0; + } + int setupLocalVideo(const VideoCanvas &canvas) override { return 0; } + int setupRemoteVideo(const VideoCanvas &canvas) override { return 0; } + int startPreview() override { return 0; } + int setRemoteUserPriority(uid_t uid, PRIORITY_TYPE userPriority) override { + return 0; + } + int stopPreview() override { return 0; } + int enableAudio() override { return 0; } + int enableLocalAudio(bool enabled) override { return 0; } + int disableAudio() override { return 0; } + int setAudioProfile(AUDIO_PROFILE_TYPE profile, + AUDIO_SCENARIO_TYPE scenario) override { + return 0; + } + int muteLocalAudioStream(bool mute) override { return 0; } + int muteAllRemoteAudioStreams(bool mute) override { return 0; } + int setDefaultMuteAllRemoteAudioStreams(bool mute) override { return 0; } + int adjustUserPlaybackSignalVolume(unsigned int uid, int volume) override { + return 0; + } + int muteRemoteAudioStream(uid_t userId, bool mute) override { return 0; } + int muteLocalVideoStream(bool mute) override { return 0; } + int enableLocalVideo(bool enabled) override { return 0; } + int muteAllRemoteVideoStreams(bool mute) override { return 0; } + int setDefaultMuteAllRemoteVideoStreams(bool mute) override { return 0; } + int muteRemoteVideoStream(uid_t userId, bool mute) override { return 0; } + int setRemoteVideoStreamType(uid_t userId, + REMOTE_VIDEO_STREAM_TYPE streamType) override { + return 0; + } + int setRemoteDefaultVideoStreamType( + REMOTE_VIDEO_STREAM_TYPE streamType) override { + return 0; + } + int enableAudioVolumeIndication(int interval, int smooth, + bool report_vad) override { + return 0; + } + int startAudioRecording(const char *filePath, + AUDIO_RECORDING_QUALITY_TYPE quality) override { + return 0; + } + int startAudioRecording(const char *filePath, int sampleRate, + AUDIO_RECORDING_QUALITY_TYPE quality) override { + return 0; + } + int startAudioRecording(const AudioRecordingConfiguration &config) override { + return 0; + } + int stopAudioRecording() override { return 0; } + int startAudioMixing(const char *filePath, bool loopback, bool replace, + int cycle) override { + return 0; + } + int startAudioMixing(const char *filePath, bool loopback, bool replace, + int cycle, int startPos) override { + return 0; + } + int setAudioMixingPlaybackSpeed(int speed) override { return 0; } + int stopAudioMixing() override { return 0; } + int pauseAudioMixing() override { return 0; } + int selectAudioTrack(int index) override { return 0; } + int getAudioTrackCount() override { return 0; } + int setAudioMixingDualMonoMode( + agora::media::AUDIO_MIXING_DUAL_MONO_MODE mode) override { + return 0; + } + int resumeAudioMixing() override { return 0; } + int setHighQualityAudioParameters(bool fullband, bool stereo, + bool fullBitrate) override { + return 0; + } + int adjustAudioMixingVolume(int volume) override { return 0; } + int adjustAudioMixingPlayoutVolume(int volume) override { return 0; } + int getAudioMixingPlayoutVolume() override { return 0; } + int adjustAudioMixingPublishVolume(int volume) override { return 0; } + int getAudioMixingPublishVolume() override { return 0; } + int getAudioMixingDuration() override { return 0; } + int getAudioMixingCurrentPosition() override { return 0; } + int setAudioMixingPosition(int pos) override { return 0; } + int setAudioMixingPitch(int pitch) override { return 0; } + int getEffectsVolume() override { return 0; } + int setEffectsVolume(int volume) override { return 0; } + int setVolumeOfEffect(int soundId, int volume) override { return 0; } +#if defined(__ANDROID__) || (defined(__APPLE__) && TARGET_OS_IOS) + int enableFaceDetection(bool enable) override { return 0; } +#endif + int playEffect(int soundId, const char *filePath, int loopCount, double pitch, + double pan, int gain, bool publish) override { + return 0; + } + int playEffect(int soundId, const char *filePath, int loopCount, double pitch, + double pan, int gain, bool publish, int startPos) override { + return 0; + } + int stopEffect(int soundId) override { return 0; } + int stopAllEffects() override { return 0; } + int preloadEffect(int soundId, const char *filePath) override { return 0; } + int unloadEffect(int soundId) override { return 0; } + int pauseEffect(int soundId) override { return 0; } + int pauseAllEffects() override { return 0; } + int resumeEffect(int soundId) override { return 0; } + int resumeAllEffects() override { return 0; } + int getEffectDuration(const char *filePath) override { return 0; } + int setEffectPosition(int soundId, int pos) override { return 0; } + int getEffectCurrentPosition(int soundId) override { return 0; } + int getAudioFileInfo(const char *filePath) override { return 0; } + int enableDeepLearningDenoise(bool enable) override { return 0; } + int enableSoundPositionIndication(bool enabled) override { return 0; } + int setRemoteVoicePosition(uid_t uid, double pan, double gain) override { + return 0; + } + int setLocalVoicePitch(double pitch) override { return 0; } + int setLocalVoiceEqualization(AUDIO_EQUALIZATION_BAND_FREQUENCY bandFrequency, + int bandGain) override { + return 0; + } + int setLocalVoiceReverb(AUDIO_REVERB_TYPE reverbKey, int value) override { + return 0; + } + int setLocalVoiceChanger(VOICE_CHANGER_PRESET voiceChanger) override { + return 0; + } + int setLocalVoiceReverbPreset(AUDIO_REVERB_PRESET reverbPreset) override { + return 0; + } + int setVoiceBeautifierPreset(VOICE_BEAUTIFIER_PRESET preset) override { + return 0; + } + int setAudioEffectPreset(AUDIO_EFFECT_PRESET preset) override { return 0; } + int setVoiceConversionPreset(VOICE_CONVERSION_PRESET preset) override { + return 0; + } + int setAudioEffectParameters(AUDIO_EFFECT_PRESET preset, int param1, + int param2) override { + return 0; + } + int setVoiceBeautifierParameters(VOICE_BEAUTIFIER_PRESET preset, int param1, + int param2) override { + return 0; + } + int setLogFile(const char *filePath) override { return 0; } + int setLogWriter(agora::commons::ILogWriter *pLogWriter) override { + return 0; + } + int releaseLogWriter() override { return 0; } + int setLogFilter(unsigned int filter) override { return 0; } + int setLogFileSize(unsigned int fileSizeInKBytes) override { return 0; } + int uploadLogFile(agora::util::AString &requestId) override { return 0; } + int setLocalRenderMode(RENDER_MODE_TYPE renderMode) override { return 0; } + int setLocalRenderMode(RENDER_MODE_TYPE renderMode, + VIDEO_MIRROR_MODE_TYPE mirrorMode) override { + return 0; + } + int setRemoteRenderMode(uid_t userId, RENDER_MODE_TYPE renderMode) override { + return 0; + } + int setRemoteRenderMode(uid_t userId, RENDER_MODE_TYPE renderMode, + VIDEO_MIRROR_MODE_TYPE mirrorMode) override { + return 0; + } + int setLocalVideoMirrorMode(VIDEO_MIRROR_MODE_TYPE mirrorMode) override { + return 0; + } + int enableDualStreamMode(bool enabled) override { return 0; } + int setExternalAudioSource(bool enabled, int sampleRate, + int channels) override { + return 0; + } + int setExternalAudioSink(bool enabled, int sampleRate, + int channels) override { + return 0; + } + int setRecordingAudioFrameParameters(int sampleRate, int channel, + RAW_AUDIO_FRAME_OP_MODE_TYPE mode, + int samplesPerCall) override { + return 0; + } + int setPlaybackAudioFrameParameters(int sampleRate, int channel, + RAW_AUDIO_FRAME_OP_MODE_TYPE mode, + int samplesPerCall) override { + return 0; + } + int setMixedAudioFrameParameters(int sampleRate, + int samplesPerCall) override { + return 0; + } + int adjustRecordingSignalVolume(int volume) override { return 0; } + int adjustPlaybackSignalVolume(int volume) override { return 0; } + int adjustLoopbackRecordingSignalVolume(int volume) override { return 0; } + int enableWebSdkInteroperability(bool enabled) override { return 0; } + int setVideoQualityParameters(bool preferFrameRateOverImageQuality) override { + return 0; + } + int setLocalPublishFallbackOption(STREAM_FALLBACK_OPTIONS option) override { + return 0; + } + int setRemoteSubscribeFallbackOption( + STREAM_FALLBACK_OPTIONS option) override { + return 0; + } +#if defined(__ANDROID__) || (defined(__APPLE__) && TARGET_OS_IOS) + int switchCamera() override { return 0; } + int switchCamera(CAMERA_DIRECTION direction) override { return 0; } + int setDefaultAudioRouteToSpeakerphone(bool defaultToSpeaker) override { + return 0; + } + int setEnableSpeakerphone(bool speakerOn) override { return 0; } + int enableInEarMonitoring(bool enabled) override { return 0; } + int setInEarMonitoringVolume(int volume) override { return 0; } + bool isSpeakerphoneEnabled() override { return 0; } +#endif +#if (defined(__APPLE__) && TARGET_OS_IOS) + int setAudioSessionOperationRestriction( + AUDIO_SESSION_OPERATION_RESTRICTION restriction) override { + return 0; + } +#endif +#if (defined(__APPLE__) && TARGET_OS_MAC && !TARGET_OS_IPHONE) \ + || defined(_WIN32) + int enableLoopbackRecording(bool enabled, const char *deviceName) override { + return 0; + } + IScreenCaptureSourceList * + getScreenCaptureSources(const SIZE &thumbSize, const SIZE &iconSize, + const bool includeScreen) override { + return nullptr; + } + int startScreenCaptureByDisplayId( + unsigned int displayId, const Rectangle ®ionRect, + const ScreenCaptureParameters &captureParams) override { + return 0; + } +#if defined(_WIN32) + int startScreenCaptureByScreenRect( + const Rectangle &screenRect, const Rectangle ®ionRect, + const ScreenCaptureParameters &captureParams) override { + return 0; + } +#endif + int startScreenCaptureByWindowId( + view_t windowId, const Rectangle ®ionRect, + const ScreenCaptureParameters &captureParams) override { + return 0; + } + int setScreenCaptureContentHint(VideoContentHint contentHint) override { + return 0; + } + int updateScreenCaptureParameters( + const ScreenCaptureParameters &captureParams) override { + return 0; + } + int updateScreenCaptureRegion(const Rectangle ®ionRect) override { + return 0; + } + int stopScreenCapture() override { return 0; } + int startScreenCapture(WindowIDType windowId, int captureFreq, + const Rect *rect, int bitrate) override { + return 0; + } + int updateScreenCaptureRegion(const Rect *rect) override { return 0; } +#endif +#if defined(_WIN32) + bool setVideoSource(IVideoSource *source) override { return 0; } +#endif + int getCallId(agora::util::AString &callId) override { return 0; } + int rate(const char *callId, int rating, const char *description) override { + return 0; + } + int complain(const char *callId, const char *description) override { + return 0; + } + const char *getVersion(int *build) override { return 0; } + int enableLastmileTest() override { return 0; } + int disableLastmileTest() override { return 0; } + int startLastmileProbeTest(const LastmileProbeConfig &config) override { + return 0; + } + int stopLastmileProbeTest() override { return 0; } + const char *getErrorDescription(int code) override { return ""; } + int setEncryptionSecret(const char *secret) override { return 0; } + int setEncryptionMode(const char *encryptionMode) override { return 0; } + int enableEncryption(bool enabled, const EncryptionConfig &config) override { + return 0; + } + int registerPacketObserver(IPacketObserver *observer) override { return 0; } + virtual int createDataStream(int *streamId, bool reliable, bool ordered) override { + return 0; + } + virtual int createDataStream(int *streamId, DataStreamConfig &config) override { + return 0; + } + int sendStreamMessage(int streamId, const char *data, + size_t length) override { + return 0; + } + int addPublishStreamUrl(const char *url, bool transcodingEnabled) override { + return 0; + } + int removePublishStreamUrl(const char *url) override { return 0; } + int setLiveTranscoding(const LiveTranscoding &transcoding) override { + return 0; + } + int addVideoWatermark(const RtcImage &watermark) override { return 0; } + int addVideoWatermark(const char *watermarkUrl, + const WatermarkOptions &options) override { + return 0; + } + int clearVideoWatermarks() override { return 0; } + int setBeautyEffectOptions(bool enabled, BeautyOptions options) override { + return 0; + } + int enableVirtualBackground( + bool enabled, VirtualBackgroundSource backgroundSource) override { + return 0; + } + int addInjectStreamUrl(const char *url, + const InjectStreamConfig &config) override { + return 0; + } + int startChannelMediaRelay( + const ChannelMediaRelayConfiguration &configuration) override { + return 0; + } + int updateChannelMediaRelay( + const ChannelMediaRelayConfiguration &configuration) override { + return 0; + } + int pauseAllChannelMediaRelay() override { return 0; } + int resumeAllChannelMediaRelay() override { return 0; } + int stopChannelMediaRelay() override { return 0; } + int removeInjectStreamUrl(const char *url) override { return 0; } + virtual bool registerEventHandler(IRtcEngineEventHandler *eventHandler) override { + return 0; + } + bool unregisterEventHandler(IRtcEngineEventHandler *eventHandler) override { + return 0; + } + int sendCustomReportMessage(const char *id, const char *category, + const char *event, const char *label, + int value) override { + return 0; + } + CONNECTION_STATE_TYPE getConnectionState() override { + return CONNECTION_STATE_TYPE::CONNECTION_STATE_CONNECTED; + } + int enableRemoteSuperResolution(uid_t userId, bool enable) override { + return 0; + } + int registerMediaMetadataObserver( + IMetadataObserver *observer, + IMetadataObserver::METADATA_TYPE type) override { + return 0; + } + int setParameters(const char *parameters) override { return 0; } +#if defined(_WIN32) + int setLocalVideoRenderer(IVideoSink *videoSink) override { return 0; } + int setRemoteVideoRenderer(uid_t uid, IVideoSink *videoSink) override { + return 0; + } +#endif + int setLocalAccessPoint(const char **ips, int ipSize, + const char *domain) override { + return 0; + } +#if defined(__ANDROID__) || (defined(__APPLE__) && TARGET_OS_IOS) + int setCameraTorchOn(bool isOn) override { return 0; } + bool isCameraTorchSupported() override { return 0; } +#endif + int takeSnapshot(const char *channel, uid_t uid, + const char *filePath) override { + return 0; + } + int enableContentInspect(bool enabled, + const ContentInspectConfig &config) override { + return 0; + } +}; + +}// namespace rtc +}// namespace agora + +#endif// FAKE_RTC_ENGINE_INTERNAL_H_ diff --git a/integration_test_app/iris_integration_test/src/iris_rtc_engine_call_api_recorder.cc b/integration_test_app/iris_integration_test/src/iris_rtc_engine_call_api_recorder.cc new file mode 100644 index 000000000..3bb3e7095 --- /dev/null +++ b/integration_test_app/iris_integration_test/src/iris_rtc_engine_call_api_recorder.cc @@ -0,0 +1,114 @@ +#include "iris_rtc_engine_call_api_recorder.h" + +IrisRtcEngineCallApiRecoder::IrisRtcEngineCallApiRecoder() {} + +IrisRtcEngineCallApiRecoder::~IrisRtcEngineCallApiRecoder() {} + +void IrisRtcEngineCallApiRecoder::Clear() { + for (std::vector::iterator it = apiCallQueue_.begin(); + it != apiCallQueue_.end(); ++it) { + if (it->buffer) { free(it->buffer); } + } + apiCallQueue_.clear(); + + mockResultMap_.clear(); + mockReturnCodeMap_.clear(); +} + +void IrisRtcEngineCallApiRecoder::MockCallApiResult(unsigned int api_type, + const char *params, + const char *mockResult) { + MockResultKey key; + key.api_type = api_type; + if (params) { key.params = std::string(params); } + + mockResultMap_.insert(std::make_pair(key, std::string(mockResult))); +} + +void IrisRtcEngineCallApiRecoder::MockCallApiReturnCode(unsigned int api_type, + const char *params, + int mockReturnCode) { + MockResultKey key; + key.api_type = api_type; + if (params) { key.params = std::string(params); } + + mockReturnCodeMap_.insert(std::make_pair(key, mockReturnCode)); +} + +void IrisRtcEngineCallApiRecoder::SetExplicitBufferSize(unsigned int api_type, + const char *params, + int size) { + MockResultKey key; + key.api_type = api_type; + if (params) { key.params = std::string(params); } + explicitBufferSizeMap_.insert(std::make_pair(key, size)); +} + +bool IrisRtcEngineCallApiRecoder::ExpectCalledApi(unsigned int api_type, + const char *params, + void *buffer, + int buffer_size) { + for (std::vector::iterator it = apiCallQueue_.begin(); + it != apiCallQueue_.end(); ++it) { + if (it->api_type == api_type) { + bool isParamsEq = it->params == std::string(params); + bool isBufferEq = true; + if (buffer) { + isBufferEq = it->buffer_size == buffer_size + && memcmp(it->buffer, buffer, buffer_size) == 0; + } + + return isParamsEq && isBufferEq; + } + } + return false; +} + +int IrisRtcEngineCallApiRecoder::CallApi(int api_type, const char *params, + char result[kBasicResultLength]) { + // IRIS_LOG_D("IrisRtcEngineCallApiRecoder CallApi2 api_type {} params {}", + // api_type, params); + return CallApi(api_type, params, nullptr, 0, result); +} + +int IrisRtcEngineCallApiRecoder::CallApi(int api_type, const char *params, + void *buffer, unsigned int length, + char result[kBasicResultLength]) { + // IRIS_LOG_D("IrisRtcEngineCallApiRecoder CallApi3 api_type {} params {}", + // api_type, params); + + ApiCall apiCall; + apiCall.api_type = api_type; + apiCall.params = std::string(params); + + MockResultKey key; + key.api_type = api_type; + if (params) { key.params = std::string(params); } + + if (buffer) { + if (explicitBufferSizeMap_.find(key) != explicitBufferSizeMap_.end()) { + int bufferSize = explicitBufferSizeMap_[key]; + unsigned char *tmp = static_cast(buffer); + + unsigned char *copyBytes = (unsigned char *) malloc(bufferSize); + memcpy(copyBytes, tmp, bufferSize); + apiCall.buffer = copyBytes; + apiCall.buffer_size = bufferSize; + } + } else { + apiCall.buffer = nullptr; + apiCall.buffer_size = 0; + } + + apiCallQueue_.push_back(apiCall); + + if (mockResultMap_.find(key) != mockResultMap_.end()) { + strcpy(result, mockResultMap_[key].c_str()); + } + + if (mockReturnCodeMap_.find(key) != mockReturnCodeMap_.end()) { + return mockReturnCodeMap_[key]; + } + + return 0; +} \ No newline at end of file diff --git a/integration_test_app/iris_integration_test/src/iris_rtc_engine_call_api_recorder.h b/integration_test_app/iris_integration_test/src/iris_rtc_engine_call_api_recorder.h new file mode 100644 index 000000000..85f635fb5 --- /dev/null +++ b/integration_test_app/iris_integration_test/src/iris_rtc_engine_call_api_recorder.h @@ -0,0 +1,84 @@ +#ifndef IRIS_RTC_ENGINE_DELEGATE_MOCKS_H_ +#define IRIS_RTC_ENGINE_DELEGATE_MOCKS_H_ + +#include "IAgoraRtcEngine.h" +#include "iris_delegate.h" +#include "iris_event_handler.h" +#include "iris_rtc_engine.h" +#include +#include +#include + +// using namespace agora::iris::rtc; + +typedef struct ApiCall +{ + unsigned int api_type; + std::string params; + void *buffer; + unsigned int buffer_size; +} ApiCall; + +typedef struct MockResultKey +{ + unsigned int api_type; + std::string params; + + bool operator<(const MockResultKey &k) const + { + return api_type < k.api_type && params < k.params; + } +} MockResultKey; + +/** + * @brief A mock implementation of IrisProxy that help test the IrisRtcEngine call api + * function call on integration test. + */ +class IRIS_DEBUG_CPP_API IrisRtcEngineCallApiRecoder + : public agora::iris::IrisDelegate +{ + +public: + IrisRtcEngineCallApiRecoder(); + + ~IrisRtcEngineCallApiRecoder(); + + void SetEventHandler(agora::iris::IrisEventHandler *event_handler) override + { + // Do nothing + } + + agora::iris::IrisEventHandler *GetEventHandler() override + { + // Do nothing + return nullptr; + } + + int CallApi(int api_type, const char *params, + char result[kBasicResultLength]) override; + + int CallApi(int api_type, const char *params, void *buffer, + unsigned int length, char result[kBasicResultLength]) override; + + void Clear(); + + void MockCallApiResult(unsigned int api_type, const char *params, + const char *mockResult); + + void MockCallApiReturnCode(unsigned int api_type, const char *params, + int mockReturnCode); + + void SetExplicitBufferSize(unsigned int api_type, const char *params, + int size); + + bool ExpectCalledApi(unsigned int api_type, const char *params, void *buffer, + int buffer_size); + +private: + std::vector apiCallQueue_; + std::map mockResultMap_; + std::map mockReturnCodeMap_; + std::map explicitBufferSizeMap_; +}; + +#endif // IRIS_RTC_ENGINE_DELEGATE_MOCKS_H_ \ No newline at end of file diff --git a/integration_test_app/iris_integration_test/src/iris_rtc_engine_integration_test_delegate.cc b/integration_test_app/iris_integration_test/src/iris_rtc_engine_integration_test_delegate.cc new file mode 100644 index 000000000..620b3db48 --- /dev/null +++ b/integration_test_app/iris_integration_test/src/iris_rtc_engine_integration_test_delegate.cc @@ -0,0 +1,221 @@ +#include "iris_rtc_engine_integration_test_delegate.h" +#include "iris_rtc_engine.h" +#include +#include +#include + +using namespace agora::iris::rtc; + +IrisRtcChannelIntegrationTestDelegate::IrisRtcChannelIntegrationTestDelegate( + agora::iris::rtc::IIrisRtcChannel *delegate, + IrisRtcEngineCallApiRecoder *apiChannelRecorder) + : delegate_(delegate), apiChannelRecorder_(apiChannelRecorder) {} + +IrisRtcChannelIntegrationTestDelegate:: + ~IrisRtcChannelIntegrationTestDelegate() {} + +void IrisRtcChannelIntegrationTestDelegate::Initialize( + agora::rtc::IRtcEngine *engine) +{ + + delegate_->Initialize(engine); +} + +void IrisRtcChannelIntegrationTestDelegate::Release() { delegate_->Release(); } + +void IrisRtcChannelIntegrationTestDelegate::SetEventHandler( + agora::iris::IrisEventHandler *event_handler) +{ + delegate_->SetEventHandler(event_handler); +} + +agora::iris::IrisEventHandler * +IrisRtcChannelIntegrationTestDelegate::GetEventHandler() +{ + return delegate_->GetEventHandler(); +} + +void IrisRtcChannelIntegrationTestDelegate::RegisterEventHandler( + const char *channel_id, agora::iris::IrisEventHandler *event_handler) +{ + delegate_->RegisterEventHandler(channel_id, event_handler); +} + +void IrisRtcChannelIntegrationTestDelegate::UnRegisterEventHandler( + const char *channel_id) +{ + delegate_->UnRegisterEventHandler(channel_id); +} + +int IrisRtcChannelIntegrationTestDelegate::CallApi( + ApiTypeChannel api_type, const char *params, + char result[kBasicResultLength]) +{ + int ret = 0; + int mockReturn = 0; + ret = delegate_->CallApi(api_type, params, result); + + if (apiChannelRecorder_) + { + mockReturn = apiChannelRecorder_->CallApi(api_type, params, result); + } + // We always make the ApiTypeChannel::kChannelCreateChannel api call success + if (ret < 0 && api_type != ApiTypeChannel::kChannelCreateChannel) + return ret; + + return mockReturn; +} + +IRIS_DEPRECATED +int IrisRtcChannelIntegrationTestDelegate::CallApi( + ApiTypeChannel api_type, const char *params, void *buffer, + char result[kBasicResultLength]) +{ + int ret = 0; + ret = delegate_->CallApi(api_type, params, buffer, result); + if (ret < 0) + return ret; + + if (apiChannelRecorder_) + { + ret = apiChannelRecorder_->CallApi(api_type, params, buffer, 0, result); + } + return ret; +} + +int IrisRtcChannelIntegrationTestDelegate::CallApi(ApiTypeChannel api_type, + const char *params, + void *buffer, + unsigned int length, + char *result) +{ + int ret = 0; + ret = delegate_->CallApi(api_type, params, buffer, length, result); + if (ret < 0) + return ret; + + if (apiChannelRecorder_) + { + ret = + apiChannelRecorder_->CallApi(api_type, params, buffer, length, result); + } + + return ret; +} + +//////////////////////////////////////////////////////////////////////// +/// IrisRtcEngineIntegrationTestDelegate + +IrisRtcEngineIntegrationTestDelegate::IrisRtcEngineIntegrationTestDelegate( + agora::iris::rtc::IIrisRtcEngine *delegate, + IrisRtcEngineCallApiRecoder *apiEngineRecorder, + IrisRtcEngineCallApiRecoder *apiChannelRecorder) + : delegate_(delegate), apiEngineRecorder_(apiEngineRecorder), + apiChannelRecorder_(apiChannelRecorder) +{ + IrisRtcChannel *originChannel = + reinterpret_cast(delegate_->channel()); + + channelDelegate_ = new IrisRtcChannelIntegrationTestDelegate( + originChannel, apiChannelRecorder_); +} + +IrisRtcEngineIntegrationTestDelegate::~IrisRtcEngineIntegrationTestDelegate() +{ + if (apiEngineRecorder_) + { + delete apiEngineRecorder_; + } + if (apiChannelRecorder_) + { + delete apiChannelRecorder_; + } +} + +void IrisRtcEngineIntegrationTestDelegate::Initialize( + agora::rtc::IRtcEngine *rtc_engine) +{ + delegate_->Initialize(rtc_engine); + fakeRtcEngine_ = rtc_engine; +} + +void IrisRtcEngineIntegrationTestDelegate::SetEventHandler( + agora::iris::IrisEventHandler *event_handler) +{ + delegate_->SetEventHandler(event_handler); +} + +agora::iris::IrisEventHandler * +IrisRtcEngineIntegrationTestDelegate::GetEventHandler() +{ + return delegate_->GetEventHandler(); +} + +int IrisRtcEngineIntegrationTestDelegate::CallApi( + ApiTypeEngine api_type, const char *params, + char result[kBasicResultLength]) +{ + int ret = 0; + int mockReturn = 0; + ret = delegate_->CallApi(api_type, params, result); + + if (apiEngineRecorder_) + { + mockReturn = apiEngineRecorder_->CallApi(api_type, params, result); + } + + // We always make the ApiTypeEngine::kEngineInitialize api call success + if (ret < 0 && api_type != ApiTypeEngine::kEngineInitialize) + { + return ret; + } + + return mockReturn; +} + +IRIS_DEPRECATED +int IrisRtcEngineIntegrationTestDelegate::CallApi( + ApiTypeEngine api_type, const char *params, void *buffer, + char result[kBasicResultLength]) +{ + int ret = 0; + ret = delegate_->CallApi(api_type, params, buffer, result); + if (ret < 0) + return ret; + if (apiEngineRecorder_) + { + ret = apiEngineRecorder_->CallApi(api_type, params, buffer, 0, result); + } + + return ret; +} + +int IrisRtcEngineIntegrationTestDelegate::CallApi( + ApiTypeEngine api_type, const char *params, void *buffer, + unsigned int length, char result[kBasicResultLength]) +{ + int ret = 0; + ret = delegate_->CallApi(api_type, params, buffer, length, result); + if (ret < 0) + return ret; + if (apiEngineRecorder_) + { + ret = apiEngineRecorder_->CallApi(api_type, params, buffer, length, result); + } + return ret; +} + +IIrisRtcDeviceManager *IrisRtcEngineIntegrationTestDelegate::device_manager() +{ + return delegate_->device_manager(); +} + +IIrisRtcChannel *IrisRtcEngineIntegrationTestDelegate::channel() +{ + return channelDelegate_; +} + +IrisRtcRawData *IrisRtcEngineIntegrationTestDelegate::raw_data() +{ + return delegate_->raw_data(); +} \ No newline at end of file diff --git a/integration_test_app/iris_integration_test/src/iris_rtc_engine_integration_test_delegate.h b/integration_test_app/iris_integration_test/src/iris_rtc_engine_integration_test_delegate.h new file mode 100644 index 000000000..1a20e0946 --- /dev/null +++ b/integration_test_app/iris_integration_test/src/iris_rtc_engine_integration_test_delegate.h @@ -0,0 +1,94 @@ +#ifndef IRIS_RTC_ENGINE_INTEGRATION_TEST_DELEGATE_H_ +#define IRIS_RTC_ENGINE_INTEGRATION_TEST_DELEGATE_H_ + +// This file is mainly used on integration test +#include "iris_delegate.h" +#include "iris_event_handler.h" +#include "iris_rtc_engine.h" +#include "iris_rtc_engine_call_api_recorder.h" +#include "fake_rtc_engine.h" +#include +#include +#include + +class IRIS_DEBUG_CPP_API IrisRtcChannelIntegrationTestDelegate + : public agora::iris::rtc::IIrisRtcChannel +{ +private: + agora::iris::rtc::IIrisRtcChannel *delegate_; + IrisRtcEngineCallApiRecoder *apiChannelRecorder_; + +public: + IrisRtcChannelIntegrationTestDelegate( + agora::iris::rtc::IIrisRtcChannel *delegate, + IrisRtcEngineCallApiRecoder *delegateMock); + + ~IrisRtcChannelIntegrationTestDelegate(); + + void Initialize(agora::rtc::IRtcEngine *engine) override; + + void Release() override; + + void SetEventHandler(agora::iris::IrisEventHandler *event_handler) override; + + agora::iris::IrisEventHandler *GetEventHandler() override; + + void + RegisterEventHandler(const char *channel_id, + agora::iris::IrisEventHandler *event_handler) override; + + void UnRegisterEventHandler(const char *channel_id) override; + + int CallApi(ApiTypeChannel api_type, const char *params, + char result[kBasicResultLength]) override; + + IRIS_DEPRECATED + int CallApi(ApiTypeChannel api_type, const char *params, void *buffer, + char result[kBasicResultLength]) override; + + int CallApi(ApiTypeChannel api_type, const char *params, void *buffer, + unsigned int length, char *result) override; +}; + +class IRIS_DEBUG_CPP_API IrisRtcEngineIntegrationTestDelegate + : public agora::iris::rtc::IIrisRtcEngine +{ +private: + agora::iris::rtc::IIrisRtcEngine *delegate_; + IrisRtcEngineCallApiRecoder *apiEngineRecorder_; + IrisRtcEngineCallApiRecoder *apiChannelRecorder_; + agora::iris::rtc::IIrisRtcChannel *channelDelegate_; + +public: + agora::rtc::IRtcEngine *fakeRtcEngine_; + IrisRtcEngineIntegrationTestDelegate( + agora::iris::rtc::IIrisRtcEngine *delegate, + IrisRtcEngineCallApiRecoder *apiEngineRecorder, + IrisRtcEngineCallApiRecoder *apiChannelRecorder); + + ~IrisRtcEngineIntegrationTestDelegate(); + + void Initialize(agora::rtc::IRtcEngine *rtc_engine) override; + + void SetEventHandler(agora::iris::IrisEventHandler *event_handler) override; + + agora::iris::IrisEventHandler *GetEventHandler() override; + + int CallApi(ApiTypeEngine api_type, const char *params, + char result[kBasicResultLength]) override; + + IRIS_DEPRECATED + int CallApi(ApiTypeEngine api_type, const char *params, void *buffer, + char result[kBasicResultLength]) override; + + int CallApi(ApiTypeEngine api_type, const char *params, void *buffer, + unsigned int length, char result[kBasicResultLength]) override; + + agora::iris::rtc::IIrisRtcDeviceManager *device_manager() override; + + agora::iris::rtc::IIrisRtcChannel *channel() override; + + agora::iris::rtc::IrisRtcRawData *raw_data() override; +}; + +#endif // IRIS_RTC_ENGINE_INTEGRATION_TEST_DELEGATE_H_ diff --git a/integration_test_app/iris_integration_test/src/iris_rtc_engine_integration_test_helplers.cc b/integration_test_app/iris_integration_test/src/iris_rtc_engine_integration_test_helplers.cc new file mode 100644 index 000000000..9e6bd7c8c --- /dev/null +++ b/integration_test_app/iris_integration_test/src/iris_rtc_engine_integration_test_helplers.cc @@ -0,0 +1,114 @@ +// This file is mainly used on integration test +#include "iris_rtc_engine_integration_test_helplers.h" +#include "fake_rtc_engine.h" +#include "iris_rtc_engine.h" +#include "iris_rtc_engine_call_api_recorder.h" +#include "iris_rtc_engine_integration_test_delegate.h" +#include +#include +#include + +using namespace agora::iris::rtc; + +void *SetIrisRtcEngineCallApiRecorder(IrisRtcEnginePtr engine_ptr, + bool isMockChannel) +{ + IrisRtcEngine *originEngine = reinterpret_cast(engine_ptr); + IIrisRtcEngine *originDelegate = originEngine->GetDelegate(); + + IrisRtcEngineCallApiRecoder *callApiRecorder = + new IrisRtcEngineCallApiRecoder(); + + IIrisRtcEngine *delegate; + if (isMockChannel) + { + delegate = new IrisRtcEngineIntegrationTestDelegate(originDelegate, nullptr, + callApiRecorder); + } + else + { + delegate = new IrisRtcEngineIntegrationTestDelegate( + originDelegate, callApiRecorder, nullptr); + } + originEngine->SetDelegate(delegate); + + agora::rtc::FakeRtcEngine *fakeRtcEngine = new agora::rtc::FakeRtcEngine(); + originEngine->Initialize(fakeRtcEngine); + + return callApiRecorder; +} + +void ClearCallApiRecorder(void *call_api_recorder_ptr) +{ + auto *apiRecoder = + reinterpret_cast(call_api_recorder_ptr); + apiRecoder->Clear(); +} + +void MockCallApiResult(void *call_api_recorder_ptr, + unsigned int api_type, const char *params, + const char *mockResult) +{ + IrisRtcEngineCallApiRecoder *apiRecoder = + reinterpret_cast(call_api_recorder_ptr); + apiRecoder->MockCallApiResult(api_type, params, mockResult); +} + +void MockCallApiReturnCode(void *call_api_recorder_ptr, + unsigned int api_type, const char *params, + int mockReturnCode) +{ + IrisRtcEngineCallApiRecoder *apiRecoder = + reinterpret_cast(call_api_recorder_ptr); + apiRecoder->MockCallApiReturnCode(api_type, params, mockReturnCode); +} + +void SetExplicitBufferSize(void *call_api_recorder_ptr, + unsigned int api_type, const char *params, + int size) +{ + IrisRtcEngineCallApiRecoder *apiRecoder = + reinterpret_cast(call_api_recorder_ptr); + apiRecoder->SetExplicitBufferSize(api_type, params, size); +} + +bool ExpectCalledApi(void *call_api_recorder_ptr, + unsigned int api_type, const char *params, + void *buffer, int buffer_size) +{ + IrisRtcEngineCallApiRecoder *apiRecoder = + reinterpret_cast(call_api_recorder_ptr); + return apiRecoder->ExpectCalledApi(api_type, params, buffer, buffer_size); +} + +void CallIrisEventHandlerOnEvent(void *engine_ptr, bool isMockChannel, + const char *event, const char *data) +{ + IrisRtcEngine *engine = reinterpret_cast(engine_ptr); + if (isMockChannel) + { + engine->channel()->GetEventHandler()->OnEvent(event, data); + } + else + { + engine->GetEventHandler()->OnEvent(event, data); + } +} + +void CallIrisEventHandlerOnEventWithBuffer(void *engine_ptr, bool isMockChannel, + const char *event, const char *data, + const void *buffer, unsigned int length) +{ + IrisRtcEngine *engine = reinterpret_cast(engine_ptr); + + if (isMockChannel) + { + + engine->channel()->GetEventHandler()->OnEvent(event, data, buffer, length); + } + else + { + + engine->GetEventHandler()->OnEvent(event, data, buffer, length); + } +} diff --git a/integration_test_app/iris_integration_test/src/iris_rtc_engine_integration_test_helplers.h b/integration_test_app/iris_integration_test/src/iris_rtc_engine_integration_test_helplers.h new file mode 100644 index 000000000..e8c238626 --- /dev/null +++ b/integration_test_app/iris_integration_test/src/iris_rtc_engine_integration_test_helplers.h @@ -0,0 +1,111 @@ +// This file is mainly used on integration test +#ifndef IRIS_RTC_ENGINE_INTEGRATION_TEST_HELPERS_H_ +#define IRIS_RTC_ENGINE_INTEGRATION_TEST_HELPERS_H_ + +#include "iris_rtc_c_api.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Set a IrisRtcEngineCallApiRecoder to IrisRtcEngine to record api called + * on integration test + * + * @param engine_ptr The pointer of the IrisRtcEngine + * @param isMockChannel Whether mock for IrisRtcChannel + * @return The mock IrisRtcEngineCallApiRecoder object pointer + */ +IRIS_API void *SetIrisRtcEngineCallApiRecorder(IrisRtcEnginePtr engine_ptr, + bool isMockChannel); + +/** + * @brief Clear the IrisRtcEngineCallApiRecoder api call records which set by + * SetIrisRtcEngineCallApiRecorder function + * + * @param call_api_recorder_ptr The pointer of the IrisRtcEngineCallApiRecoder + */ +IRIS_API void ClearCallApiRecorder(void *call_api_recorder_ptr); + +/** + * @brief Mock IrisRtcEngine call api result + * + * @param call_api_recorder_ptr The mock IrisRtcEngineCallApiRecoder object pointer + * @param api_type The ApiTypeEngine or ApiTypeChannel + * @param params The params of call api + * @param mockResult The mock result that set in integration test + */ +IRIS_API void MockCallApiResult(void *call_api_recorder_ptr, + unsigned int api_type, const char *params, + const char *mockResult); + +/** + * @brief Mock IrisRtcEngine call api return code + * + * @param call_api_recorder_ptr The mock IrisRtcEngineCallApiRecoder object pointer + * @param api_type The ApiTypeEngine or ApiTypeChannel + * @param params The params of call api + * @param mockReturnCode The mock result that set in integration test + */ +IRIS_API void MockCallApiReturnCode(void *call_api_recorder_ptr, + unsigned int api_type, const char *params, + int mockReturnCode); + +/** + * @brief Set the buffer size of the buffer for specific call api + * + * @param call_api_recorder_ptr The mock IrisRtcEngineCallApiRecoder object pointer + * @param api_type The ApiTypeEngine or ApiTypeChannel + * @param params The params of call api + * @param size The buffer size + * @return IRIS_API + */ +IRIS_API void SetExplicitBufferSize(void *call_api_recorder_ptr, + unsigned int api_type, const char *params, + int size); + +/** + * @brief Verify whether the call api function be called + * + * @param call_api_recorder_ptr The mock IrisRtcEngineCallApiRecoder object pointer + * @param api_type The ApiTypeEngine or ApiTypeChannel + * @param params The params of call api + * @param buffer The buffer of call api + * @param buffer_size The buffer size of call api + * @return true if the call api with specific api_type, params, buffer, buffer_size be called + */ +IRIS_API bool ExpectCalledApi(void *call_api_recorder_ptr, + unsigned int api_type, const char *params, + void *buffer, int buffer_size); + +/** + * @brief Call the onEvent function of EventHandler, to fire a event + * callback directly in integration test + * + * @param engine_ptr The pointer of the IrisRtcEngine + * @param event The event parameter of onEvent function + * @param data The data parameter of onEvent function + */ +IRIS_API void CallIrisEventHandlerOnEvent(void *engine_ptr, bool isMockChannel, + const char *event, const char *data); + +/** + * @brief Call the onEvent function with buffer of EventHandler, to fire a event + * callback directly in integration test + * + * @param engine_ptr The pointer of the IrisRtcEngine + * @param event The event parameter of onEvent function + * @param data The data parameter of onEvent function + * @param buffer The buffer parameter of onEvent function + * @param length The length parameter of onEvent function + */ +IRIS_API void +CallIrisEventHandlerOnEventWithBuffer(void *engine_ptr, bool isMockChannel, + const char *event, const char *data, + const void *buffer, unsigned int length); + +#ifdef __cplusplus +} +#endif + +#endif// IRIS_RTC_ENGINE_INTEGRATION_TEST_HELPERS_H_ \ No newline at end of file diff --git a/integration_test_app/iris_integration_test/src/rtc_event_handler_test.cc b/integration_test_app/iris_integration_test/src/rtc_event_handler_test.cc new file mode 100644 index 000000000..1fefc6b29 --- /dev/null +++ b/integration_test_app/iris_integration_test/src/rtc_event_handler_test.cc @@ -0,0 +1,623 @@ +// +// Created by LXH on 2021/11/30. +// + +#include "rtc_event_handler_test.h" +#include "fake_rtc_engine.h" +#include "iris_rtc_channel.h" +#include "iris_rtc_engine.h" +#include "iris_rtc_engine_integration_test_delegate.h" +#include + +using namespace agora::rtc; +using namespace agora::iris::rtc; + +void CallRtcEngineEvents(IrisRtcEnginePtr engine_ptr, const char *event_name) +{ + IrisRtcEngine *irisRtcEngine = reinterpret_cast(engine_ptr); + IrisRtcEngineIntegrationTestDelegate *delegate = reinterpret_cast(irisRtcEngine->GetDelegate()); + FakeRtcEngine *fakeRtcEngine = reinterpret_cast(delegate->fakeRtcEngine_); + agora::rtc::IRtcEngineEventHandler *handler = fakeRtcEngine->event_handler_; + + if (event_name == nullptr || strcmp(event_name, "onWarning") == 0) + { + handler->onWarning(8, "123"); + } + if (event_name == nullptr || strcmp(event_name, "onError") == 0) + { + handler->onError(0, "123"); + } + if (event_name == nullptr || strcmp(event_name, "onJoinChannelSuccess") == 0) + { + handler->onJoinChannelSuccess("123", 123, 123); + } + if (event_name == nullptr || strcmp(event_name, "onRejoinChannelSuccess") == 0) + { + handler->onRejoinChannelSuccess("123", 123, 123); + } + if (event_name == nullptr || strcmp(event_name, "onLeaveChannel") == 0) + { + RtcStats stats; + handler->onLeaveChannel(stats); + } + if (event_name == nullptr || strcmp(event_name, "onClientRoleChanged") == 0) + { + handler->onClientRoleChanged(CLIENT_ROLE_TYPE::CLIENT_ROLE_AUDIENCE, + CLIENT_ROLE_TYPE::CLIENT_ROLE_BROADCASTER); + } + if (event_name == nullptr || strcmp(event_name, "onUserJoined") == 0) + { + handler->onUserJoined(123, 123); + } + if (event_name == nullptr || strcmp(event_name, "onUserOffline") == 0) + { + handler->onUserOffline( + 123, USER_OFFLINE_REASON_TYPE::USER_OFFLINE_BECOME_AUDIENCE); + } + if (event_name == nullptr || strcmp(event_name, "onLastmileQuality") == 0) + { + handler->onLastmileQuality(0); + } + if (event_name == nullptr || strcmp(event_name, "onLastmileProbeResult") == 0) + { + LastmileProbeResult result{}; + result.state = LASTMILE_PROBE_RESULT_STATE::LASTMILE_PROBE_RESULT_COMPLETE; + handler->onLastmileProbeResult(result); + } + if (event_name == nullptr || strcmp(event_name, "onConnectionInterrupted") == 0) + { + handler->onConnectionInterrupted(); + } + if (event_name == nullptr || strcmp(event_name, "onConnectionLost") == 0) + { + handler->onConnectionLost(); + } + if (event_name == nullptr || strcmp(event_name, "onConnectionBanned") == 0) + { + handler->onConnectionBanned(); + } + if (event_name == nullptr || strcmp(event_name, "onApiCallExecuted") == 0) + { + handler->onApiCallExecuted(0, "", ""); + } + if (event_name == nullptr || strcmp(event_name, "onRequestToken") == 0) + { + handler->onRequestToken(); + } + if (event_name == nullptr || strcmp(event_name, "onTokenPrivilegeWillExpire") == 0) + { + handler->onTokenPrivilegeWillExpire("123"); + } + if (event_name == nullptr || strcmp(event_name, "onAudioQuality") == 0) + { + handler->onAudioQuality(123, 123, 123, 123); + } + if (event_name == nullptr || strcmp(event_name, "onRtcStats") == 0) + { + RtcStats stats; + handler->onRtcStats(stats); + } + if (event_name == nullptr || strcmp(event_name, "onNetworkQuality") == 0) + { + handler->onNetworkQuality(123, 0, 0); + } + if (event_name == nullptr || strcmp(event_name, "onLocalVideoStats") == 0) + { + LocalVideoStats stats{}; + stats.qualityAdaptIndication = QUALITY_ADAPT_INDICATION::ADAPT_NONE; + stats.codecType = VIDEO_CODEC_TYPE::VIDEO_CODEC_H264; + stats.captureBrightnessLevel = CAPTURE_BRIGHTNESS_LEVEL_TYPE::CAPTURE_BRIGHTNESS_LEVEL_DARK; + handler->onLocalVideoStats(stats); + } + if (event_name == nullptr || strcmp(event_name, "onRemoteVideoStats") == 0) + { + RemoteVideoStats stats{}; + handler->onRemoteVideoStats(stats); + } + if (event_name == nullptr || strcmp(event_name, "onLocalAudioStats") == 0) + { + LocalAudioStats stats{}; + handler->onLocalAudioStats(stats); + } + if (event_name == nullptr || strcmp(event_name, "onRemoteAudioStats") == 0) + { + RemoteAudioStats stats{}; + handler->onRemoteAudioStats(stats); + } + if (event_name == nullptr || strcmp(event_name, "onLocalAudioStateChanged") == 0) + { + handler->onLocalAudioStateChanged( + LOCAL_AUDIO_STREAM_STATE::LOCAL_AUDIO_STREAM_STATE_ENCODING, + LOCAL_AUDIO_STREAM_ERROR::LOCAL_AUDIO_STREAM_ERROR_DEVICE_BUSY); + } + if (event_name == nullptr || strcmp(event_name, "onRemoteAudioStateChanged") == 0) + { + handler->onRemoteAudioStateChanged( + 123, REMOTE_AUDIO_STATE::REMOTE_AUDIO_STATE_DECODING, + REMOTE_AUDIO_STATE_REASON::REMOTE_AUDIO_REASON_INTERNAL, 123); + } + if (event_name == nullptr || strcmp(event_name, "onAudioPublishStateChanged") == 0) + { + handler->onAudioPublishStateChanged( + "123", STREAM_PUBLISH_STATE::PUB_STATE_IDLE, + STREAM_PUBLISH_STATE::PUB_STATE_IDLE, 123); + } + if (event_name == nullptr || strcmp(event_name, "onVideoPublishStateChanged") == 0) + { + handler->onVideoPublishStateChanged( + "123", STREAM_PUBLISH_STATE::PUB_STATE_IDLE, + STREAM_PUBLISH_STATE::PUB_STATE_IDLE, 123); + } + if (event_name == nullptr || strcmp(event_name, "onAudioSubscribeStateChanged") == 0) + { + handler->onAudioSubscribeStateChanged( + "123", 123, STREAM_SUBSCRIBE_STATE::SUB_STATE_IDLE, + STREAM_SUBSCRIBE_STATE::SUB_STATE_IDLE, 123); + } + if (event_name == nullptr || strcmp(event_name, "onVideoSubscribeStateChanged") == 0) + { + handler->onVideoSubscribeStateChanged( + "123", 123, STREAM_SUBSCRIBE_STATE::SUB_STATE_IDLE, + STREAM_SUBSCRIBE_STATE::SUB_STATE_IDLE, 123); + } + if (event_name == nullptr || strcmp(event_name, "onAudioVolumeIndication") == 0) + { + AudioVolumeInfo info{}; + info.channelId = "123"; + info.uid = 123; + info.vad = 123; + info.volume = 123; + AudioVolumeInfo speakers[1] = {info}; + handler->onAudioVolumeIndication(speakers, 1, 123); + } + if (event_name == nullptr || strcmp(event_name, "onActiveSpeaker") == 0) + { + handler->onActiveSpeaker(123); + } + if (event_name == nullptr || strcmp(event_name, "onVideoStopped") == 0) + { + handler->onVideoStopped(); + } + if (event_name == nullptr || strcmp(event_name, "onFirstLocalVideoFrame") == 0) + { + handler->onFirstLocalVideoFrame(123, 123, 123); + } + if (event_name == nullptr || strcmp(event_name, "onFirstLocalVideoFramePublished") == 0) + { + handler->onFirstLocalVideoFramePublished(123); + } + if (event_name == nullptr || strcmp(event_name, "onFirstRemoteVideoDecoded") == 0) + { + handler->onFirstRemoteVideoDecoded(123, 123, 123, 123); + } + if (event_name == nullptr || strcmp(event_name, "onFirstRemoteVideoFrame") == 0) + { + handler->onFirstRemoteVideoFrame(123, 123, 123, 123); + } + if (event_name == nullptr || strcmp(event_name, "onUserMuteAudio") == 0) + { + handler->onUserMuteAudio(123, true); + } + if (event_name == nullptr || strcmp(event_name, "onUserMuteVideo") == 0) + { + handler->onUserMuteVideo(123, true); + } + if (event_name == nullptr || strcmp(event_name, "onUserEnableVideo") == 0) + { + handler->onUserEnableVideo(123, true); + } + if (event_name == nullptr || strcmp(event_name, "onAudioDeviceStateChanged") == 0) + { + handler->onAudioDeviceStateChanged("123", MEDIA_DEVICE_TYPE::AUDIO_PLAYOUT_DEVICE, MEDIA_DEVICE_STATE_TYPE::MEDIA_DEVICE_STATE_IDLE); + } + if (event_name == nullptr || strcmp(event_name, "onAudioDeviceVolumeChanged") == 0) + { + handler->onAudioDeviceVolumeChanged( + MEDIA_DEVICE_TYPE::AUDIO_APPLICATION_PLAYOUT_DEVICE, 123, true); + } + if (event_name == nullptr || strcmp(event_name, "onCameraReady") == 0) + { + handler->onCameraReady(); + } + if (event_name == nullptr || strcmp(event_name, "onCameraFocusAreaChanged") == 0) + { + handler->onCameraFocusAreaChanged(123, 123, 123, 123); + } + if (event_name == nullptr || strcmp(event_name, "onFacePositionChanged") == 0) + { +#if defined(__ANDROID__) || (defined(__APPLE__) && TARGET_OS_IOS) + Rectangle rectangle; + Rectangle vecRectangle[1] = {rectangle}; + int vecDistance[1] = {123}; + handler->onFacePositionChanged(123, 123, vecRectangle, vecDistance, 1); +#endif + } + if (event_name == nullptr || strcmp(event_name, "onCameraExposureAreaChanged") == 0) + { + handler->onCameraExposureAreaChanged(123, 123, 123, 123); + } + if (event_name == nullptr || strcmp(event_name, "onAudioMixingFinished") == 0) + { + handler->onAudioMixingFinished(); + } + if (event_name == nullptr || strcmp(event_name, "onAudioMixingStateChanged") == 0) + { + handler->onAudioMixingStateChanged( + AUDIO_MIXING_STATE_TYPE::AUDIO_MIXING_STATE_FAILED, + AUDIO_MIXING_REASON_TYPE::AUDIO_MIXING_REASON_ALL_LOOPS_COMPLETED); + } + if (event_name == nullptr || strcmp(event_name, "onRemoteAudioMixingBegin") == 0) + { + handler->onRemoteAudioMixingBegin(); + } + if (event_name == nullptr || strcmp(event_name, "onRemoteAudioMixingEnd") == 0) + { + handler->onRemoteAudioMixingEnd(); + } + if (event_name == nullptr || strcmp(event_name, "onAudioEffectFinished") == 0) + { + handler->onAudioEffectFinished(123); + } + if (event_name == nullptr || strcmp(event_name, "onFirstRemoteAudioDecoded") == 0) + { + handler->onFirstRemoteAudioDecoded(123, 123); + } + if (event_name == nullptr || strcmp(event_name, "onVideoDeviceStateChanged") == 0) + { + handler->onVideoDeviceStateChanged("123", MEDIA_DEVICE_TYPE::AUDIO_PLAYOUT_DEVICE, MEDIA_DEVICE_STATE_TYPE::MEDIA_DEVICE_STATE_IDLE); + } + if (event_name == nullptr || strcmp(event_name, "onLocalVideoStateChanged") == 0) + { + handler->onLocalVideoStateChanged( + LOCAL_VIDEO_STREAM_STATE::LOCAL_VIDEO_STREAM_STATE_CAPTURING, + LOCAL_VIDEO_STREAM_ERROR::LOCAL_VIDEO_STREAM_ERROR_CAPTURE_FAILURE); + } + if (event_name == nullptr || strcmp(event_name, "onVideoSizeChanged") == 0) + { + handler->onVideoSizeChanged(123, 123, 123, 123); + } + if (event_name == nullptr || strcmp(event_name, "onRemoteVideoStateChanged") == 0) + { + handler->onRemoteVideoStateChanged( + 123, REMOTE_VIDEO_STATE::REMOTE_VIDEO_STATE_DECODING, + REMOTE_VIDEO_STATE_REASON::REMOTE_VIDEO_STATE_REASON_AUDIO_FALLBACK, + 123); + } + if (event_name == nullptr || strcmp(event_name, "onUserEnableLocalVideo") == 0) + { + handler->onUserEnableLocalVideo(123, true); + } + if (event_name == nullptr || strcmp(event_name, "onStreamMessage") == 0) + { + char data[1] = {'\0'}; + handler->onStreamMessage(123, 123, data, sizeof(data)); + } + if (event_name == nullptr || strcmp(event_name, "onStreamMessageError") == 0) + { + handler->onStreamMessageError(123, 123, 123, 123, 123); + } + if (event_name == nullptr || strcmp(event_name, "onMediaEngineLoadSuccess") == 0) + { + handler->onMediaEngineLoadSuccess(); + } + if (event_name == nullptr || strcmp(event_name, "onMediaEngineStartCallSuccess") == 0) + { + handler->onMediaEngineStartCallSuccess(); + } + if (event_name == nullptr || strcmp(event_name, "onUserSuperResolutionEnabled") == 0) + { + handler->onUserSuperResolutionEnabled( + 123, true, + SUPER_RESOLUTION_STATE_REASON::SR_STATE_REASON_DEVICE_NOT_SUPPORTED); + } + if (event_name == nullptr || strcmp(event_name, "onChannelMediaRelayStateChanged") == 0) + { + handler->onChannelMediaRelayStateChanged( + CHANNEL_MEDIA_RELAY_STATE::RELAY_STATE_CONNECTING, + CHANNEL_MEDIA_RELAY_ERROR::RELAY_ERROR_DEST_TOKEN_EXPIRED); + } + if (event_name == nullptr || strcmp(event_name, "onChannelMediaRelayEvent") == 0) + { + handler->onChannelMediaRelayEvent( + CHANNEL_MEDIA_RELAY_EVENT::RELAY_EVENT_NETWORK_CONNECTED); + } + if (event_name == nullptr || strcmp(event_name, "onFirstLocalAudioFrame") == 0) + { + handler->onFirstLocalAudioFrame(123); + } + if (event_name == nullptr || strcmp(event_name, "onFirstLocalAudioFramePublished") == 0) + { + handler->onFirstLocalAudioFramePublished(123); + } + if (event_name == nullptr || strcmp(event_name, "onFirstRemoteAudioFrame") == 0) + { + handler->onFirstRemoteAudioFrame(123, 123); + } + if (event_name == nullptr || strcmp(event_name, "onRtmpStreamingStateChanged") == 0) + { + handler->onRtmpStreamingStateChanged( + "123", RTMP_STREAM_PUBLISH_STATE::RTMP_STREAM_PUBLISH_STATE_CONNECTING, + RTMP_STREAM_PUBLISH_ERROR:: + RTMP_STREAM_PUBLISH_ERROR_CONNECTION_TIMEOUT); + } + if (event_name == nullptr || strcmp(event_name, "onRtmpStreamingEvent") == 0) + { + handler->onRtmpStreamingEvent( + "123", RTMP_STREAMING_EVENT::RTMP_STREAMING_EVENT_FAILED_LOAD_IMAGE); + } + if (event_name == nullptr || strcmp(event_name, "onStreamPublished") == 0) + { + handler->onStreamPublished("123", 123); + } + if (event_name == nullptr || strcmp(event_name, "onStreamUnpublished") == 0) + { + handler->onStreamUnpublished("123"); + } + if (event_name == nullptr || strcmp(event_name, "onTranscodingUpdated") == 0) + { + handler->onTranscodingUpdated(); + } + if (event_name == nullptr || strcmp(event_name, "onStreamInjectedStatus") == 0) + { + handler->onStreamInjectedStatus("123", 123, INJECT_STREAM_STATUS::INJECT_STREAM_STATUS_START_FAILED); + } + if (event_name == nullptr || strcmp(event_name, "onAudioRouteChanged") == 0) + { + handler->onAudioRouteChanged(AUDIO_ROUTE_TYPE::AUDIO_ROUTE_AIRPLAY); + } + if (event_name == nullptr || strcmp(event_name, "onLocalPublishFallbackToAudioOnly") == 0) + { + handler->onLocalPublishFallbackToAudioOnly(true); + } + if (event_name == nullptr || strcmp(event_name, "onRemoteSubscribeFallbackToAudioOnly") == 0) + { + handler->onRemoteSubscribeFallbackToAudioOnly(123, true); + } + if (event_name == nullptr || strcmp(event_name, "onRemoteAudioTransportStats") == 0) + { + handler->onRemoteAudioTransportStats(123, 123, 123, 123); + } + if (event_name == nullptr || strcmp(event_name, "onMicrophoneEnabled") == 0) + { + handler->onMicrophoneEnabled(true); + } + if (event_name == nullptr || strcmp(event_name, "onConnectionStateChanged") == 0) + { + handler->onConnectionStateChanged( + CONNECTION_STATE_TYPE::CONNECTION_STATE_CONNECTED, + CONNECTION_CHANGED_REASON_TYPE::CONNECTION_CHANGED_BANNED_BY_SERVER); + } + if (event_name == nullptr || strcmp(event_name, "onNetworkTypeChanged") == 0) + { + handler->onNetworkTypeChanged(NETWORK_TYPE::NETWORK_TYPE_DISCONNECTED); + } + if (event_name == nullptr || strcmp(event_name, "onLocalUserRegistered") == 0) + { + handler->onLocalUserRegistered(123, "123"); + } + if (event_name == nullptr || strcmp(event_name, "onUserInfoUpdated") == 0) + { + UserInfo info; + handler->onUserInfoUpdated(123, info); + } + if (event_name == nullptr || strcmp(event_name, "onUploadLogResult") == 0) + { + handler->onUploadLogResult("123", true, + UPLOAD_ERROR_REASON::UPLOAD_NET_ERROR); + } + if (event_name == nullptr || strcmp(event_name, "onAirPlayConnected") == 0) + { + handler->onAirPlayConnected(); + } + if (event_name == nullptr || strcmp(event_name, "onVirtualBackgroundSourceEnabled") == 0) + { + handler->onVirtualBackgroundSourceEnabled( + true, + VIRTUAL_BACKGROUND_SOURCE_STATE_REASON:: + VIRTUAL_BACKGROUND_SOURCE_STATE_REASON_COLOR_FORMAT_NOT_SUPPORTED); + } + if (event_name == nullptr || strcmp(event_name, "onRequestAudioFileInfo") == 0) + { + AudioFileInfo info{}; + info.filePath = "path"; + handler->onRequestAudioFileInfo( + info, AUDIO_FILE_INFO_ERROR::AUDIO_FILE_INFO_ERROR_FAILURE); + } + if (event_name == nullptr || strcmp(event_name, "onRemoteVideoTransportStats") == 0) + { + handler->onRemoteVideoTransportStats(123, 123, 123, 123); + } + if (event_name == nullptr || strcmp(event_name, "onAirPlayConnected") == 0) + { + handler->onAirPlayConnected(); + } + if (event_name == nullptr || strcmp(event_name, "onSnapshotTaken") == 0) + { + handler->onSnapshotTaken("123", 123, "path", 10, 10, 0); + } +} + +void CallRtcChannelEvents(IrisRtcEnginePtr engine_ptr, const char *event_name) +{ + IrisRtcEngine *irisRtcEngine = reinterpret_cast(engine_ptr); + IrisRtcEngineIntegrationTestDelegate *delegate = reinterpret_cast(irisRtcEngine->GetDelegate()); + FakeRtcEngine *fakeRtcEngine = reinterpret_cast(delegate->fakeRtcEngine_); + agora::rtc::IChannelEventHandler *handler = fakeRtcEngine->channel_->channel_event_handler_; + + IChannel *rtcChannel = fakeRtcEngine->channel_; + if (event_name == nullptr || strcmp(event_name, "onChannelWarning") == 0) + { + handler->onChannelWarning(rtcChannel, 8, "123"); + } + if (event_name == nullptr || strcmp(event_name, "onChannelError") == 0) + { + handler->onChannelError(rtcChannel, 0, "123"); + } + if (event_name == nullptr || strcmp(event_name, "onJoinChannelSuccess") == 0) + { + handler->onJoinChannelSuccess(rtcChannel, 123, 123); + } + if (event_name == nullptr || strcmp(event_name, "onRejoinChannelSuccess") == 0) + { + handler->onRejoinChannelSuccess(rtcChannel, 123, 123); + } + if (event_name == nullptr || strcmp(event_name, "onLeaveChannel") == 0) + { + RtcStats stats; + handler->onLeaveChannel(rtcChannel, stats); + } + if (event_name == nullptr || strcmp(event_name, "onClientRoleChanged") == 0) + { + handler->onClientRoleChanged(rtcChannel, + CLIENT_ROLE_TYPE::CLIENT_ROLE_BROADCASTER, + CLIENT_ROLE_TYPE::CLIENT_ROLE_AUDIENCE); + } + if (event_name == nullptr || strcmp(event_name, "onUserJoined") == 0) + { + handler->onUserJoined(rtcChannel, 123, 123); + } + if (event_name == nullptr || strcmp(event_name, "onUserOffline") == 0) + { + handler->onUserOffline( + rtcChannel, 123, + USER_OFFLINE_REASON_TYPE::USER_OFFLINE_BECOME_AUDIENCE); + } + if (event_name == nullptr || strcmp(event_name, "onConnectionLost") == 0) + { + handler->onConnectionLost(rtcChannel); + } + if (event_name == nullptr || strcmp(event_name, "onRequestToken") == 0) + { + handler->onRequestToken(rtcChannel); + } + if (event_name == nullptr || strcmp(event_name, "onTokenPrivilegeWillExpire") == 0) + { + handler->onTokenPrivilegeWillExpire(rtcChannel, "123"); + } + if (event_name == nullptr || strcmp(event_name, "onRtcStats") == 0) + { + RtcStats stats; + handler->onRtcStats(rtcChannel, stats); + } + if (event_name == nullptr || strcmp(event_name, "onNetworkQuality") == 0) + { + handler->onNetworkQuality(rtcChannel, 123, 0, 0); + } + if (event_name == nullptr || strcmp(event_name, "onRemoteVideoStats") == 0) + { + RemoteVideoStats stats{}; + handler->onRemoteVideoStats(rtcChannel, stats); + } + if (event_name == nullptr || strcmp(event_name, "onRemoteAudioStats") == 0) + { + RemoteAudioStats stats{}; + handler->onRemoteAudioStats(rtcChannel, stats); + } + if (event_name == nullptr || strcmp(event_name, "onRemoteAudioStateChanged") == 0) + { + handler->onRemoteAudioStateChanged( + rtcChannel, 123, REMOTE_AUDIO_STATE::REMOTE_AUDIO_STATE_DECODING, + REMOTE_AUDIO_STATE_REASON::REMOTE_AUDIO_REASON_INTERNAL, 123); + } + if (event_name == nullptr || strcmp(event_name, "onAudioPublishStateChanged") == 0) + { + handler->onAudioPublishStateChanged( + rtcChannel, STREAM_PUBLISH_STATE::PUB_STATE_IDLE, + STREAM_PUBLISH_STATE::PUB_STATE_IDLE, 123); + } + if (event_name == nullptr || strcmp(event_name, "onVideoPublishStateChanged") == 0) + { + handler->onVideoPublishStateChanged( + rtcChannel, STREAM_PUBLISH_STATE::PUB_STATE_IDLE, + STREAM_PUBLISH_STATE::PUB_STATE_IDLE, 123); + } + if (event_name == nullptr || strcmp(event_name, "onAudioSubscribeStateChanged") == 0) + { + handler->onAudioSubscribeStateChanged( + rtcChannel, 123, STREAM_SUBSCRIBE_STATE::SUB_STATE_IDLE, + STREAM_SUBSCRIBE_STATE::SUB_STATE_IDLE, 123); + } + if (event_name == nullptr || strcmp(event_name, "onVideoSubscribeStateChanged") == 0) + { + handler->onVideoSubscribeStateChanged( + rtcChannel, 123, STREAM_SUBSCRIBE_STATE::SUB_STATE_IDLE, + STREAM_SUBSCRIBE_STATE::SUB_STATE_IDLE, 123); + } + if (event_name == nullptr || strcmp(event_name, "onUserSuperResolutionEnabled") == 0) + { + handler->onUserSuperResolutionEnabled( + rtcChannel, 123, true, + SUPER_RESOLUTION_STATE_REASON::SR_STATE_REASON_DEVICE_NOT_SUPPORTED); + } + if (event_name == nullptr || strcmp(event_name, "onActiveSpeaker") == 0) + { + handler->onActiveSpeaker(rtcChannel, 123); + } + if (event_name == nullptr || strcmp(event_name, "onVideoSizeChanged") == 0) + { + handler->onVideoSizeChanged(rtcChannel, 123, 123, 123, 123); + } + if (event_name == nullptr || strcmp(event_name, "onRemoteVideoStateChanged") == 0) + { + handler->onRemoteVideoStateChanged( + rtcChannel, 123, REMOTE_VIDEO_STATE::REMOTE_VIDEO_STATE_DECODING, + REMOTE_VIDEO_STATE_REASON::REMOTE_VIDEO_STATE_REASON_AUDIO_FALLBACK, + 123); + } + if (event_name == nullptr || strcmp(event_name, "onStreamMessage") == 0) + { + char data[1] = {'\0'}; + handler->onStreamMessage(rtcChannel, 123, 123, data, sizeof(data)); + } + if (event_name == nullptr || strcmp(event_name, "onStreamMessageError") == 0) + { + handler->onStreamMessageError(rtcChannel, 123, 123, 123, 123, 123); + } + if (event_name == nullptr || strcmp(event_name, "onChannelMediaRelayStateChanged") == 0) + { + handler->onChannelMediaRelayStateChanged( + rtcChannel, CHANNEL_MEDIA_RELAY_STATE::RELAY_STATE_CONNECTING, + CHANNEL_MEDIA_RELAY_ERROR::RELAY_ERROR_DEST_TOKEN_EXPIRED); + } + if (event_name == nullptr || strcmp(event_name, "onChannelMediaRelayEvent") == 0) + { + handler->onChannelMediaRelayEvent( + rtcChannel, CHANNEL_MEDIA_RELAY_EVENT::RELAY_EVENT_NETWORK_CONNECTED); + } + if (event_name == nullptr || strcmp(event_name, "onRtmpStreamingStateChanged") == 0) + { + handler->onRtmpStreamingStateChanged( + rtcChannel, "123", + RTMP_STREAM_PUBLISH_STATE::RTMP_STREAM_PUBLISH_STATE_CONNECTING, + RTMP_STREAM_PUBLISH_ERROR:: + RTMP_STREAM_PUBLISH_ERROR_CONNECTION_TIMEOUT); + } + if (event_name == nullptr || strcmp(event_name, "onRtmpStreamingEvent") == 0) + { + handler->onRtmpStreamingEvent( + rtcChannel, "123", + RTMP_STREAMING_EVENT::RTMP_STREAMING_EVENT_FAILED_LOAD_IMAGE); + } + if (event_name == nullptr || strcmp(event_name, "onTranscodingUpdated") == 0) + { + handler->onTranscodingUpdated(rtcChannel); + } + if (event_name == nullptr || strcmp(event_name, "onStreamInjectedStatus") == 0) + { + handler->onStreamInjectedStatus(rtcChannel, "123", 123, INJECT_STREAM_STATUS::INJECT_STREAM_STATUS_START_SUCCESS); + } + if (event_name == nullptr || strcmp(event_name, "onLocalPublishFallbackToAudioOnly") == 0) + { + handler->onLocalPublishFallbackToAudioOnly(rtcChannel, true); + } + if (event_name == nullptr || strcmp(event_name, "onRemoteSubscribeFallbackToAudioOnly") == 0) + { + handler->onRemoteSubscribeFallbackToAudioOnly(rtcChannel, 123, true); + } + if (event_name == nullptr || strcmp(event_name, "onConnectionStateChanged") == 0) + { + handler->onConnectionStateChanged( + rtcChannel, CONNECTION_STATE_TYPE::CONNECTION_STATE_CONNECTED, + CONNECTION_CHANGED_REASON_TYPE::CONNECTION_CHANGED_BANNED_BY_SERVER); + } +} diff --git a/integration_test_app/iris_integration_test/src/rtc_event_handler_test.h b/integration_test_app/iris_integration_test/src/rtc_event_handler_test.h new file mode 100644 index 000000000..d99223658 --- /dev/null +++ b/integration_test_app/iris_integration_test/src/rtc_event_handler_test.h @@ -0,0 +1,25 @@ +// +// Created by LXH on 2021/11/30. +// + +#ifndef RTC_EVENT_HANDLER_TEST_H_ +#define RTC_EVENT_HANDLER_TEST_H_ + +#include "iris_base.h" +#include "iris_rtc_c_api.h" + +#ifdef __cplusplus +extern "C" { +#endif + +IRIS_API void CallRtcEngineEvents(IrisRtcEnginePtr engine, + const char *event_name); + +IRIS_API void CallRtcChannelEvents(IrisRtcChannelPtr channel, + const char *event_name); + +#ifdef __cplusplus +}; +#endif + +#endif//RTC_EVENT_HANDLER_TEST_H_ diff --git a/integration_test_app/iris_integration_test/third_party/agora/rtc/include/AgoraAudioFrame.h b/integration_test_app/iris_integration_test/third_party/agora/rtc/include/AgoraAudioFrame.h new file mode 100644 index 000000000..88a12efff --- /dev/null +++ b/integration_test_app/iris_integration_test/third_party/agora/rtc/include/AgoraAudioFrame.h @@ -0,0 +1,276 @@ +// +// AgoraAudioFrame.h +// AgoraRtcEngineKit +// +// Copyright (c) 2020 Agora. All rights reserved. +// + +#import + +/** The protocol of the raw audio data. + */ +@protocol AgoraAudioDataFrameProtocol +@required + +/** Occurs when the recorded audio frame of the local user is received. + + @since v3.4.5 + + After you successfully register the audio delegate, the SDK triggers the + `onRecordAudioFrame` callback every 10 ms by default, and the reported audio + frame format is the same as the recorded audio frame format. + + @note To ensure that the received audio frame has the expected format, you can + register the + [getRecordAudioParams]([AgoraAudioDataFrameProtocol getRecordAudioParams]) + callback when calling the + [setAudioDataFrame]([AgoraRtcEngineKit setAudioDataFrame:]) method and set the + audio recording format in the return value of `getRecordAudioParams`. The SDK + calculates the sample interval according to the `AgoraAudioParam` you set in + the return value of `getRecordAudioParams` and triggers the + `onRecordAudioFrame` callback at the sample interval. + + @param frame The raw audio data. See AgoraAudioFrame. + + @return - `YES`: Valid buffer in AgoraAudioFrame, and the audio frame is + sent out. +- `NO`: Invalid buffer in AgoraAudioFrame, and the audio frame is discarded. + */ +- (BOOL)onRecordAudioFrame:(AgoraAudioFrame* _Nonnull)frame; + +/** Occurs when the playback audio frame of all remote users is received. + + @since v3.4.5 + + After you successfully register the audio delegate, the SDK triggers the + `onPlaybackAudioFrame` callback every 10 ms by default, and the reported audio + frame format is the same as the playback audio frame format. + + @note To ensure that the received audio frame has the expected format, you can + register the + [getPlaybackAudioParams]([AgoraAudioDataFrameProtocol getPlaybackAudioParams]) + callback when calling the + [setAudioDataFrame]([AgoraRtcEngineKit setAudioDataFrame:]) method and set the + audio playback format in the return value of `getPlaybackAudioParams`. The SDK + calculates the sample interval according to the `AgoraAudioParam` you set in + the return value of `getPlaybackAudioParams` and triggers the + `onPlaybackAudioFrame` callback at the sample interval. + + @param frame The raw audio data. See AgoraAudioFrame. + + @return - `YES`: Valid buffer in AgoraAudioFrame, and the audio frame is + sent out. +- `NO`: Invalid buffer in AgoraAudioFrame, and the audio frame is discarded. + */ +- (BOOL)onPlaybackAudioFrame:(AgoraAudioFrame* _Nonnull)frame; + +/** Occurs when the mixed audio frame of the local user and all remote users + is received. + + @since v3.4.5 + + To trigger this callback, you need to register the + [getObservedAudioFramePosition]([AgoraAudioDataFrameProtocol getObservedAudioFramePosition]) + callback when calling the + [setAudioDataFrame]([AgoraRtcEngineKit setAudioDataFrame:]) method and set the + return value of `getObservedAudioFramePosition` as + `AgoraAudioFramePositionMixed (1 << 2)`. After the setting is successful, the + SDK triggers the `onMixedAudioFrame` callback every 10 ms by default, and the + reported audio frame format is the same as the mixed audio frame format. + + @note To ensure that the received audio frame has the expected format, you can + register the + [getMixedAudioParams]([AgoraAudioDataFrameProtocol getMixedAudioParams]) + callback when calling the `setAudioDataFrame` method and set the audio mixing + format in the return value of `getMixedAudioParams`. The SDK calculates the + sample interval according to the `AgoraAudioFrame` you set in the return value + of `getMixedAudioParams` and triggers the `onMixedAudioFrame` callback at + the sample interval. + + @param frame The raw audio data. See AgoraAudioFrame. + + @return - `YES`: Valid buffer in AgoraAudioFrame, and the audio frame is + sent out. +- `NO`: Invalid buffer in AgoraAudioFrame, and the audio frame is discarded. + */ +- (BOOL)onMixedAudioFrame:(AgoraAudioFrame* _Nonnull)frame; + +/** Occurs when the audio frame of a remote user is received before mixing. + + @since v3.4.5 + + To trigger this callback, you need to register the + [getObservedAudioFramePosition]([AgoraAudioDataFrameProtocol getObservedAudioFramePosition]) + callback when calling the + [setAudioDataFrame]([AgoraRtcEngineKit setAudioDataFrame:]) method and set the + return value of `getObservedAudioFramePosition` as + `AgoraAudioFramePositionBeforeMixing (1 << 3)`. After the setting is successful, + the SDK triggers the `onPlaybackAudioFrameBeforeMixing` callback every 10 ms + by default, and the reported audio frame format is the same as the playback + audio frame format. + + @param frame The raw audio data. See AgoraAudioFrame. + @param uid The user ID of the remote user. + + @return - `YES`: Valid buffer in AgoraAudioFrame, and the audio frame is + sent out. +- `NO`: Invalid buffer in AgoraAudioFrame, and the audio frame is discarded. + */ +- (BOOL)onPlaybackAudioFrameBeforeMixing:(AgoraAudioFrame* _Nonnull)frame uid:(NSUInteger)uid; + +/** Determines whether to receive raw audio data from multiple channels. + + @since v3.5.0 + + After you register the audio frame observer, the SDK triggers this callback + every time it captures an audio frame. + + In a multi-channel scenario, if you want to get audio data from multiple + channels, set the return value of this callback as `YES`, and set the return + value of [getObservedAudioFramePosition]([AgoraAudioDataFrameProtocol getObservedAudioFramePosition]) as + `AgoraAudioFramePositionBeforeMixing (1 << 3)`. After that, the SDK triggers + the [onPlaybackAudioFrameBeforeMixingEx]([AgoraAudioDataFrameProtocol onPlaybackAudioFrameBeforeMixingEx:channelId:uid:]) + callback to send you the before-mixing audio data from various channels. You + can also get the channel ID of each audio frame. + + **Note** + + - Once you set the return value of this callback as `YES`, the SDK triggers + only the `onPlaybackAudioFrameBeforeMixingEx` callback to send the + before-mixing audio frame. + [onPlaybackAudioFrameBeforeMixing]([AgoraAudioDataFrameProtocol onPlaybackAudioFrameBeforeMixing:uid:]) + is not triggered. In a multi-channel scenario, Agora recommends setting the + return value as `YES`. + - If you set the return value of this callback as `NO`, the SDK triggers only + the `onPlaybackAudioFrameBeforeMixing` callback to send the audio data. + + @return - `YES`: Receive audio data from multiple channels. + - `NO`: Do not receive audio data from multiple channels. + */ +- (BOOL)isMultipleChannelFrameWanted; + +/** Gets the audio frame of a remote user before mixing from one of the + multiple channels. + + @since v3.5.0 + + To trigger this callback, you need to register the following callbacks and + set their return values when calling the + [setAudioDataFrame]([AgoraRtcEngineKit setAudioDataFrame:]) method: + + - [getObservedAudioFramePosition]([AgoraAudioDataFrameProtocol getObservedAudioFramePosition]): + Set its return value as `AgoraAudioFramePositionBeforeMixing (1 << 3)`. + - [isMultipleChannelFrameWanted]([AgoraAudioDataFrameProtocol isMultipleChannelFrameWanted]): + Set its return value as `YES`. + + After the setting is successful, the SDK triggers the + `onPlaybackAudioFrameBeforeMixingEx` callback every 10 ms by default, and the + reported audio frame format is the same as the playback audio frame format. + + @param frame The raw audio data. See AgoraAudioFrame. + @param channelId The channel name. + @param uid The user ID of the remote user. + + @return - `YES`: Valid buffer in `AgoraAudioFrame`, and the audio frame is sent out. + - `NO`: Invalid buffer in `AgoraAudioFrame`, and the audio frame is discarded. + */ +- (BOOL)onPlaybackAudioFrameBeforeMixingEx:(AgoraAudioFrame* _Nonnull)frame channelId:(NSString* _Nonnull)channelId uid:(NSUInteger)uid; + +/** Sets the audio observation positions. + + @since v3.4.5 + + After you successfully register the audio delegate, the SDK uses the + [getObservedAudioFramePosition]([AgoraAudioDataFrameProtocol getObservedAudioFramePosition]) + callback to determine at each specific audio-frame processing node whether to + trigger the following callbacks: + + - [onRecordAudioFrame]([AgoraAudioDataFrameProtocol onRecordAudioFrame:]) + - [onPlaybackAudioFrame]([AgoraAudioDataFrameProtocol onPlaybackAudioFrame:]) + - [onMixedAudioFrame]([AgoraAudioDataFrameProtocol onMixedAudioFrame:]) + - [onPlaybackAudioFrameBeforeMixing]([AgoraAudioDataFrameProtocol onPlaybackAudioFrameBeforeMixing:uid:]) + or [onPlaybackAudioFrameBeforeMixingEx]([AgoraAudioDataFrameProtocol onPlaybackAudioFrameBeforeMixingEx:channelId:uid:]) + + You can set the positions that you want to observe by modifying the return + value of `getObservedAudioFramePosition` according to your scenario. + + **Note**: + + - To observe multiple positions, use `|` (the OR operator). + - The default return value of `getObservedAudioFramePosition` is + `AgoraAudioFramePositionPlayback (1 << 0)` and + `AgoraAudioFramePositionRecord (1 << 1)`. + - To conserve system resources, you can reduce the number of frame positions + that you want to observe. + + @return The bit mask that controls the audio observation positions. + See AgoraAudioFramePosition. + */ +- (AgoraAudioFramePosition)getObservedAudioFramePosition; + +/** Sets the audio mixing format for the + [onMixedAudioFrame]([AgoraAudioDataFrameProtocol onMixedAudioFrame:]) callback. + + @since v3.4.5 + + Register the `getMixedAudioParams` callback when calling the + [setAudioDataFrame]([AgoraRtcEngineKit setAudioDataFrame:]) method. After you + successfully register the audio delegate, the SDK triggers this callback. + You can set the audio mixing format in + the return value of this callback. + + @note The SDK calculates the sample interval according to the `AgoraAudioParam` + you set in the return value of this callback and triggers the + `onMixedAudioFrame` callback at the calculated sample interval. + Sample interval (seconds) = `samplesPerCall`/(`sampleRate` × `channel`). + Ensure that the value of sample interval is equal to or greater than 0.01. + + @return Sets the audio format. See AgoraAudioParam. + */ +- (AgoraAudioParam* _Nonnull)getMixedAudioParams; + +/** Sets the audio recording format for the + [onRecordAudioFrame]([AgoraAudioDataFrameProtocol onRecordAudioFrame:]) + callback. + + @since v3.4.5 + + Register the `getRecordAudioParams` callback when calling the + [setAudioDataFrame]([AgoraRtcEngineKit setAudioDataFrame:]) method. After you + successfully register the audio delegate, the SDK triggers this callback. + You can set the audio recording format in + the return value of this callback. + + @note The SDK calculates the sample interval according to the `AgoraAudioParam` + you set in the return value of this callback and triggers the + `onRecordAudioFrame` callback at the calculated sample interval. + Sample interval (seconds) = `samplesPerCall`/(`sampleRate` × `channel`). + Ensure that the value of sample interval is equal to or greater than 0.01. + + @return Sets the audio format. See AgoraAudioParam. + */ +- (AgoraAudioParam* _Nonnull)getRecordAudioParams; + +/** Sets the audio playback format for the + [onPlaybackAudioFrame]([AgoraAudioDataFrameProtocol onPlaybackAudioFrame:]) + callback. + + @since v3.4.5 + + Register the `getPlaybackAudioParams` callback when calling the + [setAudioDataFrame]([AgoraRtcEngineKit setAudioDataFrame:]) method. After you + successfully register the audio delegate, the SDK triggers this callback. + You can set the audio playback format in + the return value of this callback. + + @note The SDK calculates the sample interval according to the `AgoraAudioParam` + you set in the return value of this callback and triggers the + `onPlaybackAudioFrame` callback at the calculated sample interval. + Sample interval (seconds) = `samplesPerCall`/(`sampleRate` × `channel`). + Ensure that the value of sample interval is equal to or greater than 0.01. + + @return Sets the audio format. See AgoraAudioParam. + */ +- (AgoraAudioParam* _Nonnull)getPlaybackAudioParams; + +@end diff --git a/integration_test_app/iris_integration_test/third_party/agora/rtc/include/AgoraBase.h b/integration_test_app/iris_integration_test/third_party/agora/rtc/include/AgoraBase.h new file mode 100644 index 000000000..765ac44b4 --- /dev/null +++ b/integration_test_app/iris_integration_test/third_party/agora/rtc/include/AgoraBase.h @@ -0,0 +1,805 @@ +// Agora Engine SDK +// +// Copyright (c) 2019 Agora.io. All rights reserved. +// + +#ifndef AGORA_BASE_H +#define AGORA_BASE_H + +#include +#include +#include +#include +#include + +#if defined(_WIN32) +#ifndef WIN32_LEAN_AND_MEAN +#define WIN32_LEAN_AND_MEAN +#endif +#include +#define AGORA_CALL __cdecl +#if defined(AGORARTC_EXPORT) +#define AGORA_API extern "C" __declspec(dllexport) +#define AGORA_CPP_API __declspec(dllexport) +#else +#define AGORA_API extern "C" __declspec(dllimport) +#define AGORA_CPP_API __declspec(dllimport) +#endif +#elif defined(__APPLE__) +#include +#define AGORA_API __attribute__((visibility("default"))) extern "C" +#define AGORA_CPP_API __attribute__((visibility("default"))) +#define AGORA_CALL +#elif defined(__ANDROID__) || defined(__linux__) +#define AGORA_API extern "C" __attribute__((visibility("default"))) +#define AGORA_CPP_API __attribute__((visibility("default"))) +#define AGORA_CALL +#else +#define AGORA_API extern "C" +#define AGORA_CPP_API +#define AGORA_CALL +#endif + +#ifdef __GNUC__ +#define AGORA_GCC_VERSION_AT_LEAST(x, y) (__GNUC__ > (x) || __GNUC__ == (x) && __GNUC_MINOR__ >= (y)) +#else +#define AGORA_GCC_VERSION_AT_LEAST(x, y) 0 +#endif + +#if AGORA_GCC_VERSION_AT_LEAST(3, 1) +#define AGORA_DEPRECATED_ATTRIBUTE __attribute__((deprecated)) +#elif defined(_MSC_VER) +#define AGORA_DEPRECATED_ATTRIBUTE +#else +#define AGORA_DEPRECATED_ATTRIBUTE +#endif + +namespace agora { +namespace util { + +template +class AutoPtr { + typedef T value_type; + typedef T* pointer_type; + + public: + AutoPtr(pointer_type p = 0) : ptr_(p) {} + ~AutoPtr() { + if (ptr_) ptr_->release(); + } + operator bool() const { return ptr_ != (pointer_type)0; } + value_type& operator*() const { return *get(); } + + pointer_type operator->() const { return get(); } + + pointer_type get() const { return ptr_; } + + pointer_type release() { + pointer_type tmp = ptr_; + ptr_ = 0; + return tmp; + } + + void reset(pointer_type ptr = 0) { + if (ptr != ptr_ && ptr_) ptr_->release(); + ptr_ = ptr; + } + template + bool queryInterface(C1* c, C2 iid) { + pointer_type p = NULL; + if (c && !c->queryInterface(iid, (void**)&p)) { + reset(p); + } + return p != NULL; + } + + private: + AutoPtr(const AutoPtr&); + AutoPtr& operator=(const AutoPtr&); + + private: + pointer_type ptr_; +}; +class IString { + protected: + virtual ~IString() {} + + public: + virtual bool empty() const = 0; + virtual const char* c_str() = 0; + virtual const char* data() = 0; + virtual size_t length() = 0; + virtual void release() = 0; +}; +typedef AutoPtr AString; + +} // namespace util + +enum INTERFACE_ID_TYPE { + AGORA_IID_AUDIO_DEVICE_MANAGER = 1, + AGORA_IID_VIDEO_DEVICE_MANAGER = 2, + AGORA_IID_RTC_ENGINE_PARAMETER = 3, + AGORA_IID_MEDIA_ENGINE = 4, + AGORA_IID_SIGNALING_ENGINE = 8, +}; + +/** Warning code. + */ +enum WARN_CODE_TYPE { + /** 8: The specified view is invalid. Specify a view when using the video call function. + */ + WARN_INVALID_VIEW = 8, + /** 16: Failed to initialize the video function, possibly caused by a lack of resources. The users cannot see the video while the voice communication is not affected. + */ + WARN_INIT_VIDEO = 16, + /** 20: The request is pending, usually due to some module not being ready, and the SDK postponed processing the request. + */ + WARN_PENDING = 20, + /** 103: No channel resources are available. Maybe because the server cannot allocate any channel resource. + */ + WARN_NO_AVAILABLE_CHANNEL = 103, + /** 104: A timeout occurs when looking up the channel. When joining a channel, the SDK looks up the specified channel. This warning usually occurs when the network condition is too poor for the SDK to connect to the server. + */ + WARN_LOOKUP_CHANNEL_TIMEOUT = 104, + /** **DEPRECATED** 105: The server rejects the request to look up the channel. The server cannot process this request or the request is illegal. + + Deprecated as of v2.4.1. Use CONNECTION_CHANGED_REJECTED_BY_SERVER(10) in the \ref agora::rtc::IRtcEngineEventHandler::onConnectionStateChanged "onConnectionStateChanged" callback instead. + */ + WARN_LOOKUP_CHANNEL_REJECTED = 105, + /** 106: A timeout occurs when opening the channel. Once the specific channel is found, the SDK opens the channel. This warning usually occurs when the network condition is too poor for the SDK to connect to the server. + */ + WARN_OPEN_CHANNEL_TIMEOUT = 106, + /** 107: The server rejects the request to open the channel. The server cannot process this request or the request is illegal. + */ + WARN_OPEN_CHANNEL_REJECTED = 107, + + // sdk: 100~1000 + /** 111: A timeout occurs when switching to the live video. + */ + WARN_SWITCH_LIVE_VIDEO_TIMEOUT = 111, + /** 118: A timeout occurs when setting the client role in the interactive live streaming profile. + */ + WARN_SET_CLIENT_ROLE_TIMEOUT = 118, + /** 121: The ticket to open the channel is invalid. + */ + WARN_OPEN_CHANNEL_INVALID_TICKET = 121, + /** 122: Try connecting to another server. + */ + WARN_OPEN_CHANNEL_TRY_NEXT_VOS = 122, + /** 131: The channel connection cannot be recovered. + */ + WARN_CHANNEL_CONNECTION_UNRECOVERABLE = 131, + /** 132: The IP address has changed. + */ + WARN_CHANNEL_CONNECTION_IP_CHANGED = 132, + /** 133: The port has changed. + */ + WARN_CHANNEL_CONNECTION_PORT_CHANGED = 133, + /** 134: The socket error occurs, try to rejoin channel. + */ + WARN_CHANNEL_SOCKET_ERROR = 134, + /** 701: An error occurs in opening the audio mixing file. + */ + WARN_AUDIO_MIXING_OPEN_ERROR = 701, + /** 1014: Audio Device Module: A warning occurs in the playback device. + */ + WARN_ADM_RUNTIME_PLAYOUT_WARNING = 1014, + /** 1016: Audio Device Module: A warning occurs in the audio capturing device. + */ + WARN_ADM_RUNTIME_RECORDING_WARNING = 1016, + /** 1019: Audio Device Module: No valid audio data is captured. + */ + WARN_ADM_RECORD_AUDIO_SILENCE = 1019, + /** 1020: Audio device module: The audio playback frequency is abnormal, which may cause audio freezes. This abnormality is caused by high CPU usage. Agora recommends stopping other apps. + */ + WARN_ADM_PLAYOUT_MALFUNCTION = 1020, + /** 1021: Audio device module: the audio capturing frequency is abnormal, which may cause audio freezes. This abnormality is caused by high CPU usage. Agora recommends stopping other apps. + */ + WARN_ADM_RECORD_MALFUNCTION = 1021, + /** 1025: The audio playback or capturing is interrupted by system events (such as a phone call). + */ + WARN_ADM_CALL_INTERRUPTION = 1025, + /** 1029: During a call, the audio session category should be set to + * AVAudioSessionCategoryPlayAndRecord, and RtcEngine monitors this value. + * If the audio session category is set to other values, this warning code + * is triggered and RtcEngine will forcefully set it back to + * AVAudioSessionCategoryPlayAndRecord. + */ + WARN_ADM_IOS_CATEGORY_NOT_PLAYANDRECORD = 1029, + /** 1031: Audio Device Module: The captured audio voice is too low. + */ + WARN_ADM_RECORD_AUDIO_LOWLEVEL = 1031, + /** 1032: Audio Device Module: The playback audio voice is too low. + */ + WARN_ADM_PLAYOUT_AUDIO_LOWLEVEL = 1032, + /** 1033: Audio device module: The audio capturing device is occupied. + */ + WARN_ADM_RECORD_AUDIO_IS_ACTIVE = 1033, + /** 1040: Audio device module: An exception occurs with the audio drive. + * Solutions: + * - Disable or re-enable the audio device. + * - Re-enable your device. + * - Update the sound card drive. + */ + WARN_ADM_WINDOWS_NO_DATA_READY_EVENT = 1040, + /** 1042: Audio device module: The audio capturing device is different from the audio playback device, + * which may cause echoes problem. Agora recommends using the same audio device to capture and playback + * audio. + */ + WARN_ADM_INCONSISTENT_AUDIO_DEVICE = 1042, + /** 1051: (Communication profile only) Audio processing module: A howling sound is detected when capturing the audio data. + */ + WARN_APM_HOWLING = 1051, + /** 1052: Audio Device Module: The device is in the glitch state. + */ + WARN_ADM_GLITCH_STATE = 1052, + /** 1053: Audio Processing Module: A residual echo is detected, which may be caused by the belated scheduling of system threads or the signal overflow. + */ + WARN_APM_RESIDUAL_ECHO = 1053, + /** 1054: Audio Processing Module: AI NS is closed, this can be triggered by manual settings or by performance detection modules. + */ + WARN_APM_AINS_CLOSED = 1054, + /// @cond + WARN_ADM_WIN_CORE_NO_RECORDING_DEVICE = 1322, + /// @endcond + /** 1323: Audio device module: No available playback device. + * Solution: Plug in the audio device. + */ + WARN_ADM_WIN_CORE_NO_PLAYOUT_DEVICE = 1323, + /** Audio device module: The capture device is released improperly. + * Solutions: + * - Disable or re-enable the audio device. + * - Re-enable your device. + * - Update the sound card drive. + */ + WARN_ADM_WIN_CORE_IMPROPER_CAPTURE_RELEASE = 1324, + /** 1610: The original resolution of the remote user's video is beyond the range where super resolution can be applied. + */ + WARN_SUPER_RESOLUTION_STREAM_OVER_LIMITATION = 1610, + /** 1611: Super resolution is already being used to boost another remote user's video. + */ + WARN_SUPER_RESOLUTION_USER_COUNT_OVER_LIMITATION = 1611, + /** 1612: The device does not support using super resolution. + */ + WARN_SUPER_RESOLUTION_DEVICE_NOT_SUPPORTED = 1612, + /// @cond + WARN_RTM_LOGIN_TIMEOUT = 2005, + WARN_RTM_KEEP_ALIVE_TIMEOUT = 2009 + /// @endcond +}; + +/** Error code. + */ +enum ERROR_CODE_TYPE { + /** 0: No error occurs. + */ + ERR_OK = 0, + // 1~1000 + /** 1: A general error occurs (no specified reason). + */ + ERR_FAILED = 1, + /** 2: An invalid parameter is used. For example, the specific channel name includes illegal characters. + */ + ERR_INVALID_ARGUMENT = 2, + /** 3: The SDK module is not ready. Possible solutions: + + - Check the audio device. + - Check the completeness of the application. + - Re-initialize the RTC engine. + */ + ERR_NOT_READY = 3, + /** 4: The SDK does not support this function. + */ + ERR_NOT_SUPPORTED = 4, + /** 5: The request is rejected. + */ + ERR_REFUSED = 5, + /** 6: The buffer size is not big enough to store the returned data. + */ + ERR_BUFFER_TOO_SMALL = 6, + /** 7: The SDK is not initialized before calling this method. + */ + ERR_NOT_INITIALIZED = 7, + /** 9: No permission exists. Check if the user has granted access to the audio or video device. + */ + ERR_NO_PERMISSION = 9, + /** 10: An API method timeout occurs. Some API methods require the SDK to return the execution result, and this error occurs if the request takes too long (more than 10 seconds) for the SDK to process. + */ + ERR_TIMEDOUT = 10, + /** 11: The request is canceled. This is for internal SDK use only, and it does not return to the application through any method or callback. + */ + ERR_CANCELED = 11, + /** 12: The method is called too often. + */ + ERR_TOO_OFTEN = 12, + /** 13: The SDK fails to bind to the network socket. This is for internal SDK use only, and it does not return to the application through any method or callback. + */ + ERR_BIND_SOCKET = 13, + /** 14: The network is unavailable. This is for internal SDK use only, and it does not return to the application through any method or callback. + */ + ERR_NET_DOWN = 14, + /** 15: No network buffers are available. This is for internal SDK internal use only, and it does not return to the application through any method or callback. + */ + ERR_NET_NOBUFS = 15, + /** 17: The request to join the channel is rejected. + * + * - This error usually occurs when the user is already in the channel, and still calls the method to join the + * channel, for example, \ref agora::rtc::IRtcEngine::joinChannel "joinChannel". + * - This error usually occurs when the user tries to join a channel + * during \ref agora::rtc::IRtcEngine::startEchoTest "startEchoTest". Once you + * call \ref agora::rtc::IRtcEngine::startEchoTest "startEchoTest", you need to + * call \ref agora::rtc::IRtcEngine::stopEchoTest "stopEchoTest" before joining a channel. + * - The user tries to join the channel with a token that is expired. + */ + ERR_JOIN_CHANNEL_REJECTED = 17, + /** 18: The request to leave the channel is rejected. + + This error usually occurs: + + - When the user has left the channel and still calls \ref agora::rtc::IRtcEngine::leaveChannel "leaveChannel" to leave the channel. In this case, stop calling \ref agora::rtc::IRtcEngine::leaveChannel "leaveChannel". + - When the user has not joined the channel and still calls \ref agora::rtc::IRtcEngine::leaveChannel "leaveChannel" to leave the channel. In this case, no extra operation is needed. + */ + ERR_LEAVE_CHANNEL_REJECTED = 18, + /** 19: Resources are occupied and cannot be reused. + */ + ERR_ALREADY_IN_USE = 19, + /** 20: The SDK gives up the request due to too many requests. + */ + ERR_ABORTED = 20, + /** 21: In Windows, specific firewall settings can cause the SDK to fail to initialize and crash. + */ + ERR_INIT_NET_ENGINE = 21, + /** 22: The application uses too much of the system resources and the SDK fails to allocate the resources. + */ + ERR_RESOURCE_LIMITED = 22, + /** 101: The specified App ID is invalid. Please try to rejoin the channel with a valid App ID. + */ + ERR_INVALID_APP_ID = 101, + /** 102: The specified channel name is invalid. Please try to rejoin the channel with a valid channel name. + */ + ERR_INVALID_CHANNEL_NAME = 102, + /** 103: Fails to get server resources in the specified region. Please try to specify another region when calling \ref agora::rtc::IRtcEngine::initialize "initialize". + */ + ERR_NO_SERVER_RESOURCES = 103, + /** **DEPRECATED** 109: Deprecated as of v2.4.1. Use CONNECTION_CHANGED_TOKEN_EXPIRED(9) in the \ref agora::rtc::IRtcEngineEventHandler::onConnectionStateChanged "onConnectionStateChanged" callback instead. + + The token expired due to one of the following reasons: + + - Authorized Timestamp expired: The timestamp is represented by the number of seconds elapsed since 1/1/1970. The user can use the Token to access the Agora service within 24 hours after the Token is generated. If the user does not access the Agora service after 24 hours, this Token is no longer valid. + - Call Expiration Timestamp expired: The timestamp is the exact time when a user can no longer use the Agora service (for example, when a user is forced to leave an ongoing call). When a value is set for the Call Expiration Timestamp, it does not mean that the token will expire, but that the user will be banned from the channel. + */ + ERR_TOKEN_EXPIRED = 109, + /** **DEPRECATED** 110: Deprecated as of v2.4.1. Use CONNECTION_CHANGED_INVALID_TOKEN(8) in the \ref agora::rtc::IRtcEngineEventHandler::onConnectionStateChanged "onConnectionStateChanged" callback instead. + + The token is invalid due to one of the following reasons: + + - The App Certificate for the project is enabled in Console, but the user is still using the App ID. Once the App Certificate is enabled, the user must use a token. + - The uid is mandatory, and users must set the same uid as the one set in the \ref agora::rtc::IRtcEngine::joinChannel "joinChannel" method. + */ + ERR_INVALID_TOKEN = 110, + /** 111: The internet connection is interrupted. This applies to the Agora Web SDK only. + */ + ERR_CONNECTION_INTERRUPTED = 111, // only used in web sdk + /** 112: The internet connection is lost. This applies to the Agora Web SDK only. + */ + ERR_CONNECTION_LOST = 112, // only used in web sdk + /** 113: The user is not in the channel when calling the method. + */ + ERR_NOT_IN_CHANNEL = 113, + /** 114: The size of the sent data is over 1024 bytes when the user calls the \ref agora::rtc::IRtcEngine::sendStreamMessage "sendStreamMessage" method. + */ + ERR_SIZE_TOO_LARGE = 114, + /** 115: The bitrate of the sent data exceeds the limit of 6 Kbps when the user calls the \ref agora::rtc::IRtcEngine::sendStreamMessage "sendStreamMessage" method. + */ + ERR_BITRATE_LIMIT = 115, + /** 116: Too many data streams (over 5 streams) are created when the user calls the \ref agora::rtc::IRtcEngine::createDataStream "createDataStream" method. + */ + ERR_TOO_MANY_DATA_STREAMS = 116, + /** 117: The data stream transmission timed out. + */ + ERR_STREAM_MESSAGE_TIMEOUT = 117, + /** 119: Switching roles fail. Please try to rejoin the channel. + */ + ERR_SET_CLIENT_ROLE_NOT_AUTHORIZED = 119, + /** 120: Decryption fails. The user may have used a different encryption password to join the channel. Check your settings or try rejoining the channel. + */ + ERR_DECRYPTION_FAILED = 120, + /** 123: The user is banned by the server. This error occurs when the user is kicked out the channel from the server. + */ + ERR_CLIENT_IS_BANNED_BY_SERVER = 123, + /** 124: Incorrect watermark file parameter. + */ + ERR_WATERMARK_PARAM = 124, + /** 125: Incorrect watermark file path. + */ + ERR_WATERMARK_PATH = 125, + /** 126: Incorrect watermark file format. + */ + ERR_WATERMARK_PNG = 126, + /** 127: Incorrect watermark file information. + */ + ERR_WATERMARKR_INFO = 127, + /** 128: Incorrect watermark file data format. + */ + ERR_WATERMARK_ARGB = 128, + /** 129: An error occurs in reading the watermark file. + */ + ERR_WATERMARK_READ = 129, + /** 130: Encryption is enabled when the user calls the \ref agora::rtc::IRtcEngine::addPublishStreamUrl "addPublishStreamUrl" method (CDN live streaming does not support encrypted streams). + */ + ERR_ENCRYPTED_STREAM_NOT_ALLOWED_PUBLISH = 130, + /** 134: The user account is invalid. */ + ERR_INVALID_USER_ACCOUNT = 134, + + /** 151: CDN related errors. Remove the original URL address and add a new one by calling the \ref agora::rtc::IRtcEngine::removePublishStreamUrl "removePublishStreamUrl" and \ref agora::rtc::IRtcEngine::addPublishStreamUrl "addPublishStreamUrl" methods. + */ + ERR_PUBLISH_STREAM_CDN_ERROR = 151, + /** 152: The host publishes more than 10 URLs. Delete the unnecessary URLs before adding new ones. + */ + ERR_PUBLISH_STREAM_NUM_REACH_LIMIT = 152, + /** 153: The host manipulates other hosts' URLs. Check your app logic. + */ + ERR_PUBLISH_STREAM_NOT_AUTHORIZED = 153, + /** 154: An error occurs in Agora's streaming server. Call the addPublishStreamUrl method to publish the streaming again. + */ + ERR_PUBLISH_STREAM_INTERNAL_SERVER_ERROR = 154, + /** 155: The server fails to find the stream. + */ + ERR_PUBLISH_STREAM_NOT_FOUND = 155, + /** 156: The format of the RTMP or RTMPS stream URL is not supported. Check whether the URL format is correct. + */ + ERR_PUBLISH_STREAM_FORMAT_NOT_SUPPORTED = 156, + /** 157: The necessary dynamical library is not integrated. For example, if you call + * the \ref agora::rtc::IRtcEngine::enableDeepLearningDenoise "enableDeepLearningDenoise" but do not integrate the dynamical + * library for the deep-learning noise reduction into your project, the SDK reports this error code. + * + */ + ERR_MODULE_NOT_FOUND = 157, + + /** 160: The client is already recording audio. To start a new recording, + * call \ref agora::rtc::IRtcEngine::stopAudioRecording "stopAudioRecording" to stop + * the current recording first, and then + * call \ref agora::rtc::IRtcEngine::startAudioRecording(const AudioRecordingConfiguration&) "startAudioRecording". + * + * @since v3.4.0 + */ + ERR_ALREADY_IN_RECORDING = 160, + + // signaling: 400~600 + ERR_LOGOUT_OTHER = 400, // + ERR_LOGOUT_USER = 401, // logout by user + ERR_LOGOUT_NET = 402, // network failure + ERR_LOGOUT_KICKED = 403, // login in other device + ERR_LOGOUT_PACKET = 404, // + ERR_LOGOUT_TOKEN_EXPIRED = 405, // token expired + ERR_LOGOUT_OLDVERSION = 406, // + ERR_LOGOUT_TOKEN_WRONG = 407, + ERR_LOGOUT_ALREADY_LOGOUT = 408, + ERR_LOGIN_OTHER = 420, + ERR_LOGIN_NET = 421, + ERR_LOGIN_FAILED = 422, + ERR_LOGIN_CANCELED = 423, + ERR_LOGIN_TOKEN_EXPIRED = 424, + ERR_LOGIN_OLD_VERSION = 425, + ERR_LOGIN_TOKEN_WRONG = 426, + ERR_LOGIN_TOKEN_KICKED = 427, + ERR_LOGIN_ALREADY_LOGIN = 428, + ERR_JOIN_CHANNEL_OTHER = 440, + ERR_SEND_MESSAGE_OTHER = 440, + ERR_SEND_MESSAGE_TIMEOUT = 441, + ERR_QUERY_USERNUM_OTHER = 450, + ERR_QUERY_USERNUM_TIMEOUT = 451, + ERR_QUERY_USERNUM_BYUSER = 452, + ERR_LEAVE_CHANNEL_OTHER = 460, + ERR_LEAVE_CHANNEL_KICKED = 461, + ERR_LEAVE_CHANNEL_BYUSER = 462, + ERR_LEAVE_CHANNEL_LOGOUT = 463, + ERR_LEAVE_CHANNEL_DISCONNECTED = 464, + ERR_INVITE_OTHER = 470, + ERR_INVITE_REINVITE = 471, + ERR_INVITE_NET = 472, + ERR_INVITE_PEER_OFFLINE = 473, + ERR_INVITE_TIMEOUT = 474, + ERR_INVITE_CANT_RECV = 475, + + // 1001~2000 + /** 1001: Fails to load the media engine. + */ + ERR_LOAD_MEDIA_ENGINE = 1001, + /** 1002: Fails to start the call after enabling the media engine. + */ + ERR_START_CALL = 1002, + /** **DEPRECATED** 1003: Fails to start the camera. + + Deprecated as of v2.4.1. Use LOCAL_VIDEO_STREAM_ERROR_CAPTURE_FAILURE(4) in the \ref agora::rtc::IRtcEngineEventHandler::onConnectionStateChanged "onConnectionStateChanged" callback instead. + */ + ERR_START_CAMERA = 1003, + /** 1004: Fails to start the video rendering module. + */ + ERR_START_VIDEO_RENDER = 1004, + /** 1005: A general error occurs in the Audio Device Module (no specified reason). Check if the audio device is used by another application, or try rejoining the channel. + */ + ERR_ADM_GENERAL_ERROR = 1005, + /** 1006: Audio Device Module: An error occurs in using the Java resources. + */ + ERR_ADM_JAVA_RESOURCE = 1006, + /** 1007: Audio Device Module: An error occurs in setting the sampling frequency. + */ + ERR_ADM_SAMPLE_RATE = 1007, + /** 1008: Audio Device Module: An error occurs in initializing the playback device. + */ + ERR_ADM_INIT_PLAYOUT = 1008, + /** 1009: Audio Device Module: An error occurs in starting the playback device. + */ + ERR_ADM_START_PLAYOUT = 1009, + /** 1010: Audio Device Module: An error occurs in stopping the playback device. + */ + ERR_ADM_STOP_PLAYOUT = 1010, + /** 1011: Audio Device Module: An error occurs in initializing the capturing device. + */ + ERR_ADM_INIT_RECORDING = 1011, + /** 1012: Audio Device Module: An error occurs in starting the capturing device. + */ + ERR_ADM_START_RECORDING = 1012, + /** 1013: Audio Device Module: An error occurs in stopping the capturing device. + */ + ERR_ADM_STOP_RECORDING = 1013, + /** 1015: Audio Device Module: A playback error occurs. Check your playback device and try rejoining the channel. + */ + ERR_ADM_RUNTIME_PLAYOUT_ERROR = 1015, + /** 1017: Audio Device Module: A capturing error occurs. + */ + ERR_ADM_RUNTIME_RECORDING_ERROR = 1017, + /** 1018: Audio Device Module: Fails to record. + */ + ERR_ADM_RECORD_AUDIO_FAILED = 1018, + /** 1022: Audio Device Module: An error occurs in initializing the + * loopback device. + */ + ERR_ADM_INIT_LOOPBACK = 1022, + /** 1023: Audio Device Module: An error occurs in starting the loopback + * device. + */ + ERR_ADM_START_LOOPBACK = 1023, + /** 1027: Audio Device Module: No recording permission exists. Check if the + * recording permission is granted. + */ + ERR_ADM_NO_PERMISSION = 1027, + /** 1033: Audio device module: The device is occupied. + */ + ERR_ADM_RECORD_AUDIO_IS_ACTIVE = 1033, + /** 1101: Audio device module: A fatal exception occurs. + */ + ERR_ADM_ANDROID_JNI_JAVA_RESOURCE = 1101, + /** 1108: Audio device module: The capturing frequency is lower than 50. + * 0 indicates that the capturing is not yet started. We recommend + * checking your recording permission. + */ + ERR_ADM_ANDROID_JNI_NO_RECORD_FREQUENCY = 1108, + /** 1109: The playback frequency is lower than 50. 0 indicates that the + * playback is not yet started. We recommend checking if you have created + * too many AudioTrack instances. + */ + ERR_ADM_ANDROID_JNI_NO_PLAYBACK_FREQUENCY = 1109, + /** 1111: Audio device module: AudioRecord fails to start up. A ROM system + * error occurs. We recommend the following options to debug: + * - Restart your App. + * - Restart your cellphone. + * - Check your recording permission. + */ + ERR_ADM_ANDROID_JNI_JAVA_START_RECORD = 1111, + /** 1112: Audio device module: AudioTrack fails to start up. A ROM system + * error occurs. We recommend the following options to debug: + * - Restart your App. + * - Restart your cellphone. + * - Check your playback permission. + */ + ERR_ADM_ANDROID_JNI_JAVA_START_PLAYBACK = 1112, + /** 1115: Audio device module: AudioRecord returns error. The SDK will + * automatically restart AudioRecord. */ + ERR_ADM_ANDROID_JNI_JAVA_RECORD_ERROR = 1115, + /** **DEPRECATED** */ + ERR_ADM_ANDROID_OPENSL_CREATE_ENGINE = 1151, + /** **DEPRECATED** */ + ERR_ADM_ANDROID_OPENSL_CREATE_AUDIO_RECORDER = 1153, + /** **DEPRECATED** */ + ERR_ADM_ANDROID_OPENSL_START_RECORDER_THREAD = 1156, + /** **DEPRECATED** */ + ERR_ADM_ANDROID_OPENSL_CREATE_AUDIO_PLAYER = 1157, + /** **DEPRECATED** */ + ERR_ADM_ANDROID_OPENSL_START_PLAYER_THREAD = 1160, + /** 1201: Audio device module: The current device does not support audio + * input, possibly because you have mistakenly configured the audio session + * category, or because some other app is occupying the input device. We + * recommend terminating all background apps and re-joining the channel. */ + ERR_ADM_IOS_INPUT_NOT_AVAILABLE = 1201, + /** 1206: Audio device module: Cannot activate the Audio Session.*/ + ERR_ADM_IOS_ACTIVATE_SESSION_FAIL = 1206, + /** 1210: Audio device module: Fails to initialize the audio device, + * normally because the audio device parameters are wrongly set.*/ + ERR_ADM_IOS_VPIO_INIT_FAIL = 1210, + /** 1213: Audio device module: Fails to re-initialize the audio device, + * normally because the audio device parameters are wrongly set.*/ + ERR_ADM_IOS_VPIO_REINIT_FAIL = 1213, + /** 1214: Fails to re-start up the Audio Unit, possibly because the audio + * session category is not compatible with the settings of the Audio Unit. + */ + ERR_ADM_IOS_VPIO_RESTART_FAIL = 1214, + + ERR_ADM_IOS_SET_RENDER_CALLBACK_FAIL = 1219, + + /** **DEPRECATED** */ + ERR_ADM_IOS_SESSION_SAMPLERATR_ZERO = 1221, + /** 1301: Audio device module: An audio driver abnormality or a + * compatibility issue occurs. Solutions: Disable and restart the audio + * device, or reboot the system.*/ + ERR_ADM_WIN_CORE_INIT = 1301, + /** 1303: Audio device module: A recording driver abnormality or a + * compatibility issue occurs. Solutions: Disable and restart the audio + * device, or reboot the system. */ + ERR_ADM_WIN_CORE_INIT_RECORDING = 1303, + /** 1306: Audio device module: A playout driver abnormality or a + * compatibility issue occurs. Solutions: Disable and restart the audio + * device, or reboot the system. */ + ERR_ADM_WIN_CORE_INIT_PLAYOUT = 1306, + /** 1307: Audio device module: No audio device is available. Solutions: + * Plug in a proper audio device. */ + ERR_ADM_WIN_CORE_INIT_PLAYOUT_NULL = 1307, + /** 1309: Audio device module: An audio driver abnormality or a + * compatibility issue occurs. Solutions: Disable and restart the audio + * device, or reboot the system. */ + ERR_ADM_WIN_CORE_START_RECORDING = 1309, + /** 1311: Audio device module: Insufficient system memory or poor device + * performance. Solutions: Reboot the system or replace the device. + */ + ERR_ADM_WIN_CORE_CREATE_REC_THREAD = 1311, + /** 1314: Audio device module: An audio driver abnormality occurs. + * Solutions: + * - Disable and then re-enable the audio device. + * - Reboot the system. + * - Upgrade your audio card driver.*/ + ERR_ADM_WIN_CORE_CAPTURE_NOT_STARTUP = 1314, + /** 1319: Audio device module: Insufficient system memory or poor device + * performance. Solutions: Reboot the system or replace the device. */ + ERR_ADM_WIN_CORE_CREATE_RENDER_THREAD = 1319, + /** 1320: Audio device module: An audio driver abnormality occurs. + * Solutions: + * - Disable and then re-enable the audio device. + * - Reboot the system. + * - Replace the device. */ + ERR_ADM_WIN_CORE_RENDER_NOT_STARTUP = 1320, + /** 1322: Audio device module: No audio sampling device is available. + * Solutions: Plug in a proper capturing device. */ + ERR_ADM_WIN_CORE_NO_RECORDING_DEVICE = 1322, + /** 1323: Audio device module: No audio playout device is available. + * Solutions: Plug in a proper playback device.*/ + ERR_ADM_WIN_CORE_NO_PLAYOUT_DEVICE = 1323, + /** 1351: Audio device module: An audio driver abnormality or a + * compatibility issue occurs. Solutions: + * - Disable and then re-enable the audio device. + * - Reboot the system. + * - Upgrade your audio card driver. */ + ERR_ADM_WIN_WAVE_INIT = 1351, + /** 1353: Audio device module: An audio driver abnormality occurs. + * Solutions: + * - Disable and then re-enable the audio device. + * - Reboot the system. + * - Upgrade your audio card driver. */ + ERR_ADM_WIN_WAVE_INIT_RECORDING = 1353, + /** 1354: Audio device module: An audio driver abnormality occurs. + * Solutions: + * - Disable and then re-enable the audio device. + * - Reboot the system. + * - Upgrade your audio card driver. */ + ERR_ADM_WIN_WAVE_INIT_MICROPHONE = 1354, + /** 1355: Audio device module: An audio driver abnormality occurs. + * Solutions: + * - Disable and then re-enable the audio device. + * - Reboot the system. + * - Upgrade your audio card driver. */ + ERR_ADM_WIN_WAVE_INIT_PLAYOUT = 1355, + /** 1356: Audio device module: An audio driver abnormality occurs. + * Solutions: + * - Disable and then re-enable the audio device. + * - Reboot the system. + * - Upgrade your audio card driver. */ + ERR_ADM_WIN_WAVE_INIT_SPEAKER = 1356, + /** 1357: Audio device module: An audio driver abnormality occurs. + * Solutions: + * - Disable and then re-enable the audio device. + * - Reboot the system. + * - Upgrade your audio card driver. */ + ERR_ADM_WIN_WAVE_START_RECORDING = 1357, + /** 1358: Audio device module: An audio driver abnormality occurs. + * Solutions: + * - Disable and then re-enable the audio device. + * - Reboot the system. + * - Upgrade your audio card driver.*/ + ERR_ADM_WIN_WAVE_START_PLAYOUT = 1358, + /** 1359: Audio Device Module: No capturing device exists. + */ + ERR_ADM_NO_RECORDING_DEVICE = 1359, + /** 1360: Audio Device Module: No playback device exists. + */ + ERR_ADM_NO_PLAYOUT_DEVICE = 1360, + + // VDM error code starts from 1500 + /// @cond + /** 1500: Video Device Module: There is no camera device. + */ + ERR_VDM_CAMERA_NO_DEVICE = 1500, + /// @endcond + + /** 1501: Video Device Module: The camera is unauthorized. + */ + ERR_VDM_CAMERA_NOT_AUTHORIZED = 1501, + + /** **DEPRECATED** 1502: Video Device Module: The camera in use. + Deprecated as of v2.4.1. Use LOCAL_VIDEO_STREAM_ERROR_DEVICE_BUSY(3) in the \ref agora::rtc::IRtcEngineEventHandler::onLocalVideoStateChanged "onLocalVideoStateChanged" callback instead. + */ + ERR_VDM_WIN_DEVICE_IN_USE = 1502, + + // VCM error code starts from 1600 + /** 1600: Video Device Module: An unknown error occurs. + */ + ERR_VCM_UNKNOWN_ERROR = 1600, + /** 1601: Video Device Module: An error occurs in initializing the video encoder. + */ + ERR_VCM_ENCODER_INIT_ERROR = 1601, + /** 1602: Video Device Module: An error occurs in encoding. + */ + ERR_VCM_ENCODER_ENCODE_ERROR = 1602, + /** 1603: Video Device Module: An error occurs in setting the video encoder. + */ + ERR_VCM_ENCODER_SET_ERROR = 1603, + /** 1735: (Windows only) The Windows Audio service is disabled. You need to + * either enable the Windows Audio service or restart the device. + * + * @since v3.5.0 + */ + ERR_ADM_WIN_CORE_SERVRE_SHUT_DOWN = 1735, +}; + +/** Output log filter level. */ +enum LOG_FILTER_TYPE { + /** 0: Do not output any log information. */ + LOG_FILTER_OFF = 0, + /** 0x080f: Output all log information. + Set your log filter as debug if you want to get the most complete log file. */ + LOG_FILTER_DEBUG = 0x080f, + /** 0x000f: Output CRITICAL, ERROR, WARNING, and INFO level log information. + We recommend setting your log filter as this level. + */ + LOG_FILTER_INFO = 0x000f, + /** 0x000e: Outputs CRITICAL, ERROR, and WARNING level log information. + */ + LOG_FILTER_WARN = 0x000e, + /** 0x000c: Outputs CRITICAL and ERROR level log information. */ + LOG_FILTER_ERROR = 0x000c, + /** 0x0008: Outputs CRITICAL level log information. */ + LOG_FILTER_CRITICAL = 0x0008, + /// @cond + LOG_FILTER_MASK = 0x80f, + /// @endcond +}; +/** The output log level of the SDK. + * + * @since v3.3.0 + */ +enum class LOG_LEVEL { + /** 0x0000: Do not output any log. */ + LOG_LEVEL_NONE = 0x0000, + /** 0x0001: (Default) Output logs of the FATAL, ERROR, WARN and INFO level. We recommend setting your log filter as this level. + */ + LOG_LEVEL_INFO = 0x0001, + /** 0x0002: Output logs of the FATAL, ERROR and WARN level. + */ + LOG_LEVEL_WARN = 0x0002, + /** 0x0004: Output logs of the FATAL and ERROR level. */ + LOG_LEVEL_ERROR = 0x0004, + /** 0x0008: Output logs of the FATAL level. */ + LOG_LEVEL_FATAL = 0x0008, +}; +} // namespace agora + +#endif diff --git a/integration_test_app/iris_integration_test/third_party/agora/rtc/include/AgoraConstants.h b/integration_test_app/iris_integration_test/third_party/agora/rtc/include/AgoraConstants.h new file mode 100644 index 000000000..4dddea916 --- /dev/null +++ b/integration_test_app/iris_integration_test/third_party/agora/rtc/include/AgoraConstants.h @@ -0,0 +1,91 @@ +// +// AgoraConstants.h +// AgoraRtcEngineKit +// +// Copyright (c) 2018 Agora. All rights reserved. +// +#import +#if defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE +#import +#elif defined(TARGET_OS_MAC) && TARGET_OS_MAC +#import +#endif + +/** The standard bitrate set in [setVideoEncoderConfiguration]([AgoraRtcEngineKit setVideoEncoderConfiguration:]). + +(Recommended) The standard bitrate mode. In this mode, the bitrate under the interactive live streaming and communication profiles differs: + + - Communication profile: The video bitrate is the same as the base bitrate. + - Interactive live streaming profile: The video bitrate is twice the base bitrate. + */ +extern NSInteger const AgoraVideoBitrateStandard; + +/** The compatible bitrate set in [setVideoEncoderConfiguration]([AgoraRtcEngineKit setVideoEncoderConfiguration:]). + +The compatible bitrate mode. In this mode, the bitrate stays the same regardless of the channel profile. In the interactive live streaming channel, if you choose this mode, the video frame rate may be lower than the set value. + */ +extern NSInteger const AgoraVideoBitrateCompatible; + +/** Use the default minimum bitrate. + */ +extern NSInteger const AgoraVideoBitrateDefaultMin; + +/** 120 * 120 + */ +extern CGSize const AgoraVideoDimension120x120; +/** 160 * 120 + */ +extern CGSize const AgoraVideoDimension160x120; +/** 180 * 180 + */ +extern CGSize const AgoraVideoDimension180x180; +/** 240 * 180 + */ +extern CGSize const AgoraVideoDimension240x180; +/** 320 * 180 + */ +extern CGSize const AgoraVideoDimension320x180; +/** 240 * 240 + */ +extern CGSize const AgoraVideoDimension240x240; +/** 320 * 240 + */ +extern CGSize const AgoraVideoDimension320x240; +/** 424 * 240 + */ +extern CGSize const AgoraVideoDimension424x240; +/** 360 * 360 + */ +extern CGSize const AgoraVideoDimension360x360; +/** 480 * 360 + */ +extern CGSize const AgoraVideoDimension480x360; +/** 640 * 360 + */ +extern CGSize const AgoraVideoDimension640x360; +/** 480 * 480 + */ +extern CGSize const AgoraVideoDimension480x480; +/** 640 * 480 + */ +extern CGSize const AgoraVideoDimension640x480; +/** 840 * 480 + */ +extern CGSize const AgoraVideoDimension840x480; +/** 960 * 720 (Hardware dependent) + */ +extern CGSize const AgoraVideoDimension960x720; +/** 1280 * 720 (Hardware dependent) + */ +extern CGSize const AgoraVideoDimension1280x720; +#if TARGET_OS_MAC && !TARGET_OS_IPHONE +/** 1920 * 1080 (Hardware dependent, macOS only) + */ +extern CGSize const AgoraVideoDimension1920x1080; +/** Reserved for future use. + */ +extern CGSize const AgoraVideoDimension2540x1440; +/** Reserved for future use. + */ +extern CGSize const AgoraVideoDimension3840x2160; +#endif diff --git a/integration_test_app/iris_integration_test/third_party/agora/rtc/include/AgoraEnumerates.h b/integration_test_app/iris_integration_test/third_party/agora/rtc/include/AgoraEnumerates.h new file mode 100644 index 000000000..35c07036e --- /dev/null +++ b/integration_test_app/iris_integration_test/third_party/agora/rtc/include/AgoraEnumerates.h @@ -0,0 +1,2354 @@ +// +// AgoraEnumerates.h +// AgoraRtcEngineKit +// +// Copyright (c) 2018 Agora. All rights reserved. +// + +#import + +/** Warning code. + +Warning codes occur when the SDK encounters an error that may be recovered automatically. These are only notifications, and can generally be ignored. For example, when the SDK loses connection to the server, the SDK reports the AgoraWarningCodeOpenChannelTimeout(106) warning and tries to reconnect automatically. +*/ +typedef NS_ENUM(NSInteger, AgoraWarningCode) { + /** 8: The specified view is invalid. Specify a view when using the video call function. */ + AgoraWarningCodeInvalidView = 8, + /** 16: Failed to initialize the video function, possibly caused by a lack of resources. The users cannot see the video while the voice communication is not affected. */ + AgoraWarningCodeInitVideo = 16, + /** 20: The request is pending, usually due to some module not being ready, and the SDK postpones processing the request. */ + AgoraWarningCodePending = 20, + /** 103: No channel resources are available. Maybe because the server cannot allocate any channel resource. */ + AgoraWarningCodeNoAvailableChannel = 103, + /** 104: A timeout occurs when looking up the channel. When joining a channel, the SDK looks up the specified channel. The warning usually occurs when the network condition is too poor for the SDK to connect to the server. */ + AgoraWarningCodeLookupChannelTimeout = 104, + /** 105: The server rejects the request to look up the channel. The server cannot process this request or the request is illegal. +

        DEPRECATED as of v2.4.1. Use AgoraConnectionChangedRejectedByServer(10) in the `reason` parameter of [connectionChangedToState]([AgoraRtcEngineDelegate rtcEngine:connectionChangedToState:reason:]).

        + */ + AgoraWarningCodeLookupChannelRejected = 105, + /** 106: The server rejects the request to look up the channel. The server cannot process this request or the request is illegal. */ + AgoraWarningCodeOpenChannelTimeout = 106, + /** 107: The server rejects the request to open the channel. The server cannot process this request or the request is illegal. */ + AgoraWarningCodeOpenChannelRejected = 107, + /** 111: A timeout occurs when switching to the live video. */ + AgoraWarningCodeSwitchLiveVideoTimeout = 111, + /** 118: A timeout occurs when setting the client role in the interactive live streaming profile. */ + AgoraWarningCodeSetClientRoleTimeout = 118, + /** 119: The client role is unauthorized. */ + AgoraWarningCodeSetClientRoleNotAuthorized = 119, + /** 121: The ticket to open the channel is invalid. */ + AgoraWarningCodeOpenChannelInvalidTicket = 121, + /** 122: Try connecting to another server. */ + AgoraWarningCodeOpenChannelTryNextVos = 122, + /** 701: An error occurs in opening the audio mixing file. */ + AgoraWarningCodeAudioMixingOpenError = 701, + /** 1014: Audio Device Module: a warning occurs in the playback device. */ + AgoraWarningCodeAdmRuntimePlayoutWarning = 1014, + /** 1016: Audio Device Module: a warning occurs in the sampling device. */ + AgoraWarningCodeAdmRuntimeRecordingWarning = 1016, + /** 1019: Audio device module: No valid audio data is sampled. */ + AgoraWarningCodeAdmRecordAudioSilence = 1019, + /** 1020: Audio Device Module: a playback device fails. */ + AgoraWarningCodeAdmPlaybackMalfunction = 1020, + /** 1021: Audio Device Module: a sampling device fails. */ + AgoraWarningCodeAdmRecordMalfunction = 1021, + /** 1025: Call is interrupted by system events such as phone call or siri etc. */ + AgoraWarningCodeAdmInterruption = 1025, + /** 1029: During a call, `AudioSessionCategory` should be set to `AVAudioSessionCategoryPlayAndRecord`, and the SDK monitors this value. If the `AudioSessionCategory` is set to other values, this warning code is triggered and the SDK will forcefully set it back to `AVAudioSessionCategoryPlayAndRecord`.*/ + AgoraWarningCodeAdmCategoryNotPlayAndRecord = 1029, + /** 1031: Audio Device Module: the sampled audio is too low. */ + AgoraWarningCodeAdmRecordAudioLowlevel = 1031, + /** 1032: Audio Device Module: the playback audio is too low. */ + AgoraWarningCodeAdmPlayoutAudioLowlevel = 1032, + /** 1040: Audio device module: An error occurs in the audio driver. Solution:
      1. Restart your audio device.
      2. Restart your device where the app runs.
      3. Upgrade the sound card drive.
      4. */ + AgoraWarningCodeAdmNoDataReadyCallback = 1040, + /** 1042: Audio device module: The audio sampling device is different from the audio playback device, which may cause echoes problem. Agora recommends using the same audio device to sample and playback audio. */ + AgoraWarningCodeAdmInconsistentDevices = 1042, + /** 1051: (Communication profile only) Audio Processing Module: A howling sound is detected when sampling the audio data */ + AgoraWarningCodeApmHowling = 1051, + /** 1052: Audio Device Module: the device is in the glitch state. */ + AgoraWarningCodeAdmGlitchState = 1052, + /** 1053: Audio Processing Module: A residual echo is detected, which may be caused by the belated scheduling of system threads or the signal overflow. */ + AgoraWarningCodeApmResidualEcho = 1053, + /** 1610: Super-resolution warning: The original resolution of the remote user's video is beyond the range where super resolution can be applied. */ + AgoraWarningCodeSuperResolutionStreamOverLimitation = 1610, + /** 1611: Super-resolution warning: Super resolution is already being used to boost another remote user's video. */ + AgoraWarningCodeSuperResolutionUserCountOverLimitation = 1611, + /** 1612: Super-resolution warning: The device does not support using super resolution. */ + AgoraWarningCodeSuperResolutionDeviceNotSupported = 1612, +}; + +/** Error code. + +Error codes occur when the SDK encounters an error that cannot be recovered automatically without any app intervention. For example, the SDK reports the `AgoraErrorCodeStartCall` = `1002` error if it fails to start a call, and reminds the user to call the [leaveChannel]([AgoraRtcEngineKit leaveChannel:]) method. +*/ +typedef NS_ENUM(NSInteger, AgoraErrorCode) { + /** 0: No error occurs. */ + AgoraErrorCodeNoError = 0, + /** 1: A general error occurs (no specified reason). */ + AgoraErrorCodeFailed = 1, + /** 2: An invalid parameter is used. For example, the specific channel name includes illegal characters. */ + AgoraErrorCodeInvalidArgument = 2, + /** 3: The SDK module is not ready. +

        Possible solutions: +

        • Check the audio device.
        • +
        • Check the completeness of the app.
        • +
        • Re-initialize the SDK.

        + */ + AgoraErrorCodeNotReady = 3, + /** 4: The current state of the SDK does not support this function. */ + AgoraErrorCodeNotSupported = 4, + /** 5: The request is rejected. This is for internal SDK use only, and is not returned to the app through any method or callback. */ + AgoraErrorCodeRefused = 5, + /** 6: The buffer size is not big enough to store the returned data. */ + AgoraErrorCodeBufferTooSmall = 6, + /** 7: The SDK is not initialized before calling this method. */ + AgoraErrorCodeNotInitialized = 7, + /** 9: No permission exists. Check if the user has granted access to the audio or video device. */ + AgoraErrorCodeNoPermission = 9, + /** 10: An API method timeout occurs. Some API methods require the SDK to return the execution result, and this error occurs if the request takes too long (over 10 seconds) for the SDK to process. */ + AgoraErrorCodeTimedOut = 10, + /** 11: The request is canceled. This is for internal SDK use only, and is not returned to the app through any method or callback. */ + AgoraErrorCodeCanceled = 11, + /** 12: The method is called too often. This is for internal SDK use only, and is not returned to the app through any method or callback. */ + AgoraErrorCodeTooOften = 12, + /** 13: The SDK fails to bind to the network socket. This is for internal SDK use only, and is not returned to the app through any method or callback. */ + AgoraErrorCodeBindSocket = 13, + /** 14: The network is unavailable. This is for internal SDK use only, and is not returned to the app through any method or callback. */ + AgoraErrorCodeNetDown = 14, + /** 15: No network buffers are available. This is for internal SDK use only, and is not returned to the app through any method or callback. */ + AgoraErrorCodeNoBufs = 15, + /** 17: The request to join the channel is rejected. +

        Possible reasons are: +

        • The user is already in the channel, and still calls the API method to join the channel, for example, [joinChannelByToken]([AgoraRtcEngineKit joinChannelByToken:channelId:info:uid:joinSuccess:]).
        • +
        • The user tries to join a channel during a call test ([startEchoTestWithInterval]([AgoraRtcEngineKit startEchoTestWithInterval:successBlock:])). Once you call `startEchoTestWithInterval`, you need to call [stopEchoTest]([AgoraRtcEngineKit stopEchoTest]) before joining a channel.
        • +
        • The user tries to join the channel with a token that is expired.

        + */ + AgoraErrorCodeJoinChannelRejected = 17, + /** 18: The request to leave the channel is rejected. +

        Possible reasons are: +

        • The user left the channel and still calls the API method to leave the channel, for example, [leaveChannel]([AgoraRtcEngineKit leaveChannel:]).
        • +
        • The user has not joined the channel and calls the API method to leave the channel.

        + */ + AgoraErrorCodeLeaveChannelRejected = 18, + /** 19: The resources are occupied and cannot be used. */ + AgoraErrorCodeAlreadyInUse = 19, + /** 20: The SDK gave up the request due to too many requests. */ + AgoraErrorCodeAbort = 20, + /** 21: In Windows, specific firewall settings cause the SDK to fail to initialize and crash. */ + AgoraErrorCodeInitNetEngine = 21, + /** 22: The app uses too much of the system resources and the SDK fails to allocate the resources. */ + AgoraErrorCodeResourceLimited = 22, + /** 101: The specified App ID is invalid. Please try to rejoin the channel with a valid App ID.*/ + AgoraErrorCodeInvalidAppId = 101, + /** 102: The specified channel name is invalid. Please try to rejoin the channel with a valid channel name. */ + AgoraErrorCodeInvalidChannelId = 102, + /** 103: Fails to get server resources in the specified region. Please try to specify another region when calling [sharedEngineWithConfig]([AgoraRtcEngineKit sharedEngineWithConfig:delegate:]). */ + AgoraErrorCodeNoServerResources = 103, + /** 109: The token expired. +

        DEPRECATED as of v2.4.1. Use AgoraConnectionChangedTokenExpired(9) in the `reason` parameter of [connectionChangedToState]([AgoraRtcEngineDelegate rtcEngine:connectionChangedToState:reason:]).

        +

        Possible reasons are: +

        • Authorized Timestamp expired: The timestamp is represented by the number of seconds elapsed since 1/1/1970. The user can use the token to access the Agora service within 24 hours after the token is generated. If the user does not access the Agora service after 24 hours, this token is no longer valid.
        • +
        • Call Expiration Timestamp expired: The timestamp is the exact time when a user can no longer use the Agora service (for example, when a user is forced to leave an ongoing call). When a value is set for the Call Expiration Timestamp, it does not mean that the token will expire, but that the user will be banned from the channel.

        + */ + AgoraErrorCodeTokenExpired = 109, + /** 110: The token is invalid. +

        DEPRECATED as of v2.4.1. Use AgoraConnectionChangedInvalidToken(8) in the `reason` parameter of [connectionChangedToState]([AgoraRtcEngineDelegate rtcEngine:connectionChangedToState:reason:]).

        +

        Possible reasons are: +

        • The App Certificate for the project is enabled in Console, but the user is using the App ID. Once the App Certificate is enabled, the user must use a token.
        • +
        • The uid is mandatory, and users must set the same uid as the one set in the [joinChannelByToken]([AgoraRtcEngineKit joinChannelByToken:channelId:info:uid:joinSuccess:]) method.

        + */ + AgoraErrorCodeInvalidToken = 110, + /** 111: The Internet connection is interrupted. This applies to the Agora Web SDK only. */ + AgoraErrorCodeConnectionInterrupted = 111, + /** 112: The Internet connection is lost. This applies to the Agora Web SDK only. */ + AgoraErrorCodeConnectionLost = 112, + /** 113: The user is not in the channel when calling the method. */ + AgoraErrorCodeNotInChannel = 113, + /** 114: The size of the sent data is over 1024 bytes when the user calls the [sendStreamMessage]([AgoraRtcEngineKit sendStreamMessage:data:]) method. */ + AgoraErrorCodeSizeTooLarge = 114, + /** 115: The bitrate of the sent data exceeds the limit of 6 Kbps when the user calls the [sendStreamMessage]([AgoraRtcEngineKit sendStreamMessage:data:]) method. */ + AgoraErrorCodeBitrateLimit = 115, + /** 116: Too many data streams (over five streams) are created when the user calls the [createDataStream]([AgoraRtcEngineKit createDataStream:reliable:ordered:]) method. */ + AgoraErrorCodeTooManyDataStreams = 116, + /** 120: Decryption fails. The user may have used a different encryption password to join the channel. Check your settings or try rejoining the channel. */ + AgoraErrorCodeDecryptionFailed = 120, + /** 124: Incorrect watermark file parameter. */ + AgoraErrorCodeWatermarkParam = 124, + /** 125: Incorrect watermark file path. */ + AgoraErrorCodeWatermarkPath = 125, + /** 126: Incorrect watermark file format. */ + AgoraErrorCodeWatermarkPng = 126, + /** 127: Incorrect watermark file information. */ + AgoraErrorCodeWatermarkInfo = 127, + /** 128: Incorrect watermark file data format. */ + AgoraErrorCodeWatermarkAGRB = 128, + /** 129: An error occurs in reading the watermark file. */ + AgoraErrorCodeWatermarkRead = 129, + /** 130: The encrypted stream is not allowed to publish. */ + AgoraErrorCodeEncryptedStreamNotAllowedPublish = 130, + /** 134: The user account is invalid. */ + AgoraErrorCodeInvalidUserAccount = 134, + + /** 151: CDN related errors. Remove the original URL address and add a new one by calling the [removePublishStreamUrl]([AgoraRtcEngineKit removePublishStreamUrl:]) and [addPublishStreamUrl]([AgoraRtcEngineKit addPublishStreamUrl:transcodingEnabled:]) methods. */ + AgoraErrorCodePublishStreamCDNError = 151, + /** 152: The host publishes more than 10 URLs. Delete the unnecessary URLs before adding new ones. */ + AgoraErrorCodePublishStreamNumReachLimit = 152, + /** 153: The host manipulates other hosts' URLs. Check your app logic. */ + AgoraErrorCodePublishStreamNotAuthorized = 153, + /** 154: An error occurs in Agora's streaming server. Call the [addPublishStreamUrl]([AgoraRtcEngineKit addPublishStreamUrl:transcodingEnabled:]) method to publish the stream again. */ + AgoraErrorCodePublishStreamInternalServerError = 154, + /** 155: The server fails to find the stream. */ + AgoraErrorCodePublishStreamNotFound = 155, + /** 156: The format of the RTMP stream URL is not supported. Check whether the URL format is correct. */ + AgoraErrorCodePublishStreamFormatNotSuppported = 156, + /** 157: The extension library is not integrated, such as the library for enabling deep-learning noise reduction. */ + AgoraErrorCodeModuleNotFound = 157, + /** 160: The client is already recording audio. To start a new recording, call [stopAudioRecording]([AgoraRtcEngineKit stopAudioRecording]) + to stop the current recording first, and then call [startAudioRecordingWithConfig]([AgoraRtcEngineKit startAudioRecordingWithConfig:]). + + @since v3.4.0 + */ + AgoraErrorCodeAlreadyInRecording = 160, + /** 1001: Fails to load the media engine. */ + AgoraErrorCodeLoadMediaEngine = 1001, + /** 1002: Fails to start the call after enabling the media engine. */ + AgoraErrorCodeStartCall = 1002, + /** 1003: Fails to start the camera. +

        DEPRECATED as of v2.4.1. Use AgoraLocalVideoStreamErrorCaptureFailure(4) in the `error` parameter of [connectionChangedToState]([AgoraRtcEngineDelegate rtcEngine:connectionChangedToState:reason:]).

        + */ + AgoraErrorCodeStartCamera = 1003, + /** 1004: Fails to start the video rendering module. */ + AgoraErrorCodeStartVideoRender = 1004, + /** 1005: A general error occurs in the Audio Device Module (the reason is not classified specifically). Check if the audio device is used by another app, or try rejoining the channel. */ + AgoraErrorCodeAdmGeneralError = 1005, + /** 1006: Audio Device Module: An error occurs in using the Java resources. */ + AgoraErrorCodeAdmJavaResource = 1006, + /** 1007: Audio Device Module: An error occurs in setting the sampling frequency. */ + AgoraErrorCodeAdmSampleRate = 1007, + /** 1008: Audio Device Module: An error occurs in initializing the playback device. */ + AgoraErrorCodeAdmInitPlayout = 1008, + /** 1009: Audio Device Module: An error occurs in starting the playback device. */ + AgoraErrorCodeAdmStartPlayout = 1009, + /** 1010: Audio Device Module: An error occurs in stopping the playback device. */ + AgoraErrorCodeAdmStopPlayout = 1010, + /** 1011: Audio Device Module: An error occurs in initializing the sampling device. */ + AgoraErrorCodeAdmInitRecording = 1011, + /** 1012: Audio Device Module: An error occurs in starting the sampling device. */ + AgoraErrorCodeAdmStartRecording = 1012, + /** 1013: Audio Device Module: An error occurs in stopping the sampling device. */ + AgoraErrorCodeAdmStopRecording = 1013, + /** 1015: Audio Device Module: A playback error occurs. Check your playback device, or try rejoining the channel. */ + AgoraErrorCodeAdmRuntimePlayoutError = 1015, + /** 1017: Audio Device Module: A sampling error occurs. */ + AgoraErrorCodeAdmRuntimeRecordingError = 1017, + /** 1018: Audio Device Module: Fails to sample the audio data. */ + AgoraErrorCodeAdmRecordAudioFailed = 1018, + /** 1020: Audio Device Module: The audio playback frequency is abnormal, which may cause audio freezes. This abnormality is caused by high CPU usage. Agora recommends stopping other apps. */ + AgoraErrorCodeAdmPlayAbnormalFrequency = 1020, + /** 1021: Audio Device Module: The audio sampling frequency is abnormal, which may cause audio freezes. This abnormality is caused by high CPU usage. Agora recommends stopping other apps. */ + AgoraErrorCodeAdmRecordAbnormalFrequency = 1021, + /** 1022: Audio Device Module: An error occurs in initializing the loopback device. */ + AgoraErrorCodeAdmInitLoopback = 1022, + /** 1023: Audio Device Module: An error occurs in starting the loopback device. */ + AgoraErrorCodeAdmStartLoopback = 1023, + /** 1027: Audio Device Module: An error occurs in no audio sampling permission. */ + AgoraErrorCodeAdmNoPermission = 1027, + /** 1206: Audio device module: Cannot activate the Audio Session.*/ + AgoraErrorCodeAdmActivateSessionFail = 1206, + /** 1359: No sampling device is available. Check whether the sampling device is connected or whether it is already in use by another app. */ + AgoraErrorCodeAdmNoRecordingDevice = 1359, + /** 1360: No playback device exists. */ + AgoraErrorCodeAdmNoPlayoutDevice = 1360, + /** 1501: Video Device Module: The camera is unauthorized. */ + AgoraErrorCodeVdmCameraNotAuthorized = 1501, + /** 1600: Video Device Module: An unknown error occurs. */ + AgoraErrorCodeVcmUnknownError = 1600, + /** 1601: Video Device Module: An error occurs in initializing the video encoder. */ + AgoraErrorCodeVcmEncoderInitError = 1601, + /** 1602: Video Device Module: An error occurs in video encoding. */ + AgoraErrorCodeVcmEncoderEncodeError = 1602, + /** 1603: Video Device Module: An error occurs in setting the video encoder. +

        DEPRECATED

        + */ + AgoraErrorCodeVcmEncoderSetError = 1603, +}; + +/** The current music file playback state. Reports in the [localAudioMixingStateDidChanged]([AgoraRtcEngineDelegate rtcEngine:localAudioMixingStateDidChanged:reason:]) callback. */ +typedef NS_ENUM(NSInteger, AgoraAudioMixingStateCode) { + /** 710: The music file is playing. +

        This state comes with one of the following associated reasons:

        +
      5. AgoraAudioMixingReasonStartedByUser(720)
      6. +
      7. AgoraAudioMixingReasonOneLoopCompleted(721)
      8. +
      9. AgoraAudioMixingReasonStartNewLoop(722)
      10. +
      11. AgoraAudioMixingReasonResumedByUser(726)
      12. + */ + AgoraAudioMixingStatePlaying = 710, + /** 711: The music file pauses playing. +

        This state comes with AgoraAudioMixingReasonPausedByUser(725).

        + */ + AgoraAudioMixingStatePaused = 711, + /** 713: The music file stops playing. +

        This state comes with one of the following associated reasons:

        +
      13. AgoraAudioMixingReasonAllLoopsCompleted(723)
      14. +
      15. AgoraAudioMixingReasonStoppedByUser(724)
      16. + */ + AgoraAudioMixingStateStopped = 713, + /** 714: An exception occurs during the playback of the music file. +

        This state comes with one of the following associated reasons:

        +
      17. AgoraAudioMixingReasonCanNotOpen(701)
      18. +
      19. AgoraAudioMixingReasonTooFrequentCall(702)
      20. +
      21. AgoraAudioMixingReasonInterruptedEOF(703)
      22. + */ + AgoraAudioMixingStateFailed = 714, +}; + +/** Audio Mixing Error Code.

        **Deprecated** from v3.4.0. Use AgoraAudioMixingReasonCode instead.

        */ +typedef NS_ENUM(NSInteger, AgoraAudioMixingErrorCode) { + /** 701: The SDK cannot open the audio mixing file. */ + AgoraAudioMixingErrorCanNotOpen __deprecated_enum_msg("AgoraAudioMixingErrorCanNotOpen is deprecated.") = 701, + /** 702: The SDK opens the audio mixing file too frequently. */ + AgoraAudioMixingErrorTooFrequentCall __deprecated_enum_msg("AgoraAudioMixingErrorTooFrequentCall is deprecated.") = 702, + /** 703: The opening of the audio mixing file is interrupted. */ + AgoraAudioMixingErrorInterruptedEOF __deprecated_enum_msg("AgoraAudioMixingErrorInterruptedEOF is deprecated.") = 703, + /** 0: No error. */ + AgoraAudioMixingErrorOK __deprecated_enum_msg("AgoraAudioMixingErrorOK is deprecated.") = 0, +}; + +/** The reason for the change of the music file playback state. Reports in the [localAudioMixingStateDidChanged]([AgoraRtcEngineDelegate rtcEngine:localAudioMixingStateDidChanged:reason:]) callback. + + @since 3.4.0 + */ +typedef NS_ENUM(NSInteger, AgoraAudioMixingReasonCode) { + /** 701: The SDK cannot open the music file. Possible causes include the local music file does not exist, the SDK + does not support the file format, or the SDK cannot access the music file URL. + */ + AgoraAudioMixingReasonCanNotOpen = 701, + /** 702: The SDK opens the music file too frequently. If you need to call + [startAudioMixing]([AgoraRtcEngineKit startAudioMixing:loopback:replace:cycle:startPos:]) multiple times, ensure that the call + interval is longer than 500 ms. + */ + AgoraAudioMixingReasonTooFrequentCall = 702, + /** 703: The music file playback is interrupted. + */ + AgoraAudioMixingReasonInterruptedEOF = 703, + /** 720: Successfully calls [startAudioMixing]([AgoraRtcEngineKit startAudioMixing:loopback:replace:cycle:startPos:]) to play a music file. + */ + AgoraAudioMixingReasonStartedByUser = 720, + /** 721: The music file completes a loop playback. + */ + AgoraAudioMixingReasonOneLoopCompleted = 721, + /** 722: The music file starts a new loop playback. + */ + AgoraAudioMixingReasonStartNewLoop = 722, + /** 723: The music file completes all loop playback. + */ + AgoraAudioMixingReasonAllLoopsCompleted = 723, + /** 724: Successfully calls [stopAudioMixing]([AgoraRtcEngineKit stopAudioMixing]) to stop playing the music file. + */ + AgoraAudioMixingReasonStoppedByUser = 724, + /** 725: Successfully calls [pauseAudioMixing]([AgoraRtcEngineKit pauseAudioMixing]) to pause playing the music file. + */ + AgoraAudioMixingReasonPausedByUser = 725, + /** 726: Successfully calls [resumeAudioMixing]([AgoraRtcEngineKit resumeAudioMixing]) to resume playing the music file. + */ + AgoraAudioMixingReasonResumedByUser = 726, +}; + +/** Video profile. + +**DEPRECATED** + +Please use `AgoraVideoEncoderConfiguration`. + +iPhones do not support resolutions above 720p. +*/ +typedef NS_ENUM(NSInteger, AgoraVideoProfile) { + /** Invalid profile. */ + AgoraVideoProfileInvalid = -1, + /** Resolution 160 * 120, frame rate 15 fps, bitrate 65 Kbps. */ + AgoraVideoProfileLandscape120P = 0, + /** (iOS only) Resolution 120 * 120, frame rate 15 fps, bitrate 50 Kbps. */ + AgoraVideoProfileLandscape120P_3 = 2, + /** (iOS only) Resolution 320 * 180, frame rate 15 fps, bitrate 140 Kbps. */ + AgoraVideoProfileLandscape180P = 10, + /** (iOS only) Resolution 180 * 180, frame rate 15 fps, bitrate 100 Kbps. */ + AgoraVideoProfileLandscape180P_3 = 12, + /** Resolution 240 * 180, frame rate 15 fps, bitrate 120 Kbps. */ + AgoraVideoProfileLandscape180P_4 = 13, + /** Resolution 320 * 240, frame rate 15 fps, bitrate 200 Kbps. */ + AgoraVideoProfileLandscape240P = 20, + /** (iOS only) Resolution 240 * 240, frame rate 15 fps, bitrate 140 Kbps. */ + AgoraVideoProfileLandscape240P_3 = 22, + /** Resolution 424 * 240, frame rate 15 fps, bitrate 220 Kbps. */ + AgoraVideoProfileLandscape240P_4 = 23, + /** Resolution 640 * 360, frame rate 15 fps, bitrate 400 Kbps. */ + AgoraVideoProfileLandscape360P = 30, + /** (iOS only) Resolution 360 * 360, frame rate 15 fps, bitrate 260 Kbps. */ + AgoraVideoProfileLandscape360P_3 = 32, + /** Resolution 640 * 360, frame rate 30 fps, bitrate 600 Kbps. */ + AgoraVideoProfileLandscape360P_4 = 33, + /** Resolution 360 * 360, frame rate 30 fps, bitrate 400 Kbps. */ + AgoraVideoProfileLandscape360P_6 = 35, + /** Resolution 480 * 360, frame rate 15 fps, bitrate 320 Kbps. */ + AgoraVideoProfileLandscape360P_7 = 36, + /** Resolution 480 * 360, frame rate 30 fps, bitrate 490 Kbps. */ + AgoraVideoProfileLandscape360P_8 = 37, + /** Resolution 640 * 360, frame rate 15 fps, bitrate 800 Kbps. +

        Note: This profile applies to the interactive live streaming channel profile only.

        + */ + AgoraVideoProfileLandscape360P_9 = 38, + /** Resolution 640 * 360, frame rate 24 fps, bitrate 800 Kbps. +

        >Note: This profile applies to the interactive live streaming channel profile only.

        + */ + AgoraVideoProfileLandscape360P_10 = 39, + /** Resolution 640 * 360, frame rate 24 fps, bitrate 1000 Kbps. +

        Note: This profile applies to the interactive live streaming channel profile only.

        + */ + AgoraVideoProfileLandscape360P_11 = 100, + /** Resolution 640 * 480, frame rate 15 fps, bitrate 500 Kbps. */ + AgoraVideoProfileLandscape480P = 40, + /** (iOS only) Resolution 480 * 480, frame rate 15 fps, bitrate 400 Kbps. */ + AgoraVideoProfileLandscape480P_3 = 42, + /** Resolution 640 * 480, frame rate 30 fps, bitrate 750 Kbps. */ + AgoraVideoProfileLandscape480P_4 = 43, + /** Resolution 480 * 480, frame rate 30 fps, bitrate 600 Kbps. */ + AgoraVideoProfileLandscape480P_6 = 45, + /** Resolution 848 * 480, frame rate 15 fps, bitrate 610 Kbps. */ + AgoraVideoProfileLandscape480P_8 = 47, + /** Resolution 848 * 480, frame rate 30 fps, bitrate 930 Kbps. */ + AgoraVideoProfileLandscape480P_9 = 48, + /** Resolution 640 * 480, frame rate 10 fps, bitrate 400 Kbps. */ + AgoraVideoProfileLandscape480P_10 = 49, + /** Resolution 1280 * 720, frame rate 15 fps, bitrate 1130 Kbps. */ + AgoraVideoProfileLandscape720P = 50, + /** Resolution 1280 * 720, frame rate 30 fps, bitrate 1710 Kbps. */ + AgoraVideoProfileLandscape720P_3 = 52, + /** Resolution 960 * 720, frame rate 15 fps, bitrate 910 Kbps. */ + AgoraVideoProfileLandscape720P_5 = 54, + /** Resolution 960 * 720, frame rate 30 fps, bitrate 1380 Kbps. */ + AgoraVideoProfileLandscape720P_6 = 55, + /** (macOS only) Resolution 1920 * 1080, frame rate 15 fps, bitrate 2080 Kbps. */ + AgoraVideoProfileLandscape1080P = 60, + /** (macOS only) Resolution 1920 * 1080, frame rate 30 fps, bitrate 3150 Kbps. */ + AgoraVideoProfileLandscape1080P_3 = 62, + /** (macOS only) Resolution 1920 * 1080, frame rate 60 fps, bitrate 4780 Kbps. */ + AgoraVideoProfileLandscape1080P_5 = 64, + /** Reserved for future use. */ + AgoraVideoProfileLandscape1440P = 66, + /** Reserved for future use. */ + AgoraVideoProfileLandscape1440P_2 = 67, + /** Reserved for future use. */ + AgoraVideoProfileLandscape4K = 70, + /** Reserved for future use. */ + AgoraVideoProfileLandscape4K_3 = 72, + + /** Resolution 120 * 160, frame rate 15 fps, bitrate 65 Kbps. */ + AgoraVideoProfilePortrait120P = 1000, + /** (iOS only) Resolution 120 * 120, frame rate 15 fps, bitrate 50 Kbps. */ + AgoraVideoProfilePortrait120P_3 = 1002, + /** (iOS only) Resolution 180 * 320, frame rate 15 fps, bitrate 140 Kbps. */ + AgoraVideoProfilePortrait180P = 1010, + /** (iOS only) Resolution 180 * 180, frame rate 15 fps, bitrate 100 Kbps. */ + AgoraVideoProfilePortrait180P_3 = 1012, + /** Resolution 180 * 240, frame rate 15 fps, bitrate 120 Kbps. */ + AgoraVideoProfilePortrait180P_4 = 1013, + /** Resolution 240 * 320, frame rate 15 fps, bitrate 200 Kbps. */ + AgoraVideoProfilePortrait240P = 1020, + /** (iOS only) Resolution 240 * 240, frame rate 15 fps, bitrate 140 Kbps. */ + AgoraVideoProfilePortrait240P_3 = 1022, + /** Resolution 240 * 424, frame rate 15 fps, bitrate 220 Kbps. */ + AgoraVideoProfilePortrait240P_4 = 1023, + /** Resolution 360 * 640, frame rate 15 fps, bitrate 400 Kbps. */ + AgoraVideoProfilePortrait360P = 1030, + /** (iOS only) Resolution 360 * 360, frame rate 15 fps, bitrate 260 Kbps. */ + AgoraVideoProfilePortrait360P_3 = 1032, + /** Resolution 360 * 640, frame rate 30 fps, bitrate 600 Kbps. */ + AgoraVideoProfilePortrait360P_4 = 1033, + /** Resolution 360 * 360, frame rate 30 fps, bitrate 400 Kbps. */ + AgoraVideoProfilePortrait360P_6 = 1035, + /** Resolution 360 * 480, frame rate 15 fps, bitrate 320 Kbps. */ + AgoraVideoProfilePortrait360P_7 = 1036, + /** Resolution 360 * 480, frame rate 30 fps, bitrate 490 Kbps. */ + AgoraVideoProfilePortrait360P_8 = 1037, + /** Resolution 360 * 640, frame rate 15 fps, bitrate 600 Kbps. */ + AgoraVideoProfilePortrait360P_9 = 1038, + /** Resolution 360 * 640, frame rate 24 fps, bitrate 800 Kbps. */ + AgoraVideoProfilePortrait360P_10 = 1039, + /** Resolution 360 * 640, frame rate 24 fps, bitrate 800 Kbps. */ + AgoraVideoProfilePortrait360P_11 = 1100, + /** Resolution 480 * 640, frame rate 15 fps, bitrate 500 Kbps. */ + AgoraVideoProfilePortrait480P = 1040, + /** (iOS only) Resolution 480 * 480, frame rate 15 fps, bitrate 400 Kbps. */ + AgoraVideoProfilePortrait480P_3 = 1042, + /** Resolution 480 * 640, frame rate 30 fps, bitrate 750 Kbps. */ + AgoraVideoProfilePortrait480P_4 = 1043, + /** Resolution 480 * 480, frame rate 30 fps, bitrate 600 Kbps. */ + AgoraVideoProfilePortrait480P_6 = 1045, + /** Resolution 480 * 848, frame rate 15 fps, bitrate 610 Kbps. */ + AgoraVideoProfilePortrait480P_8 = 1047, + /** Resolution 480 * 848, frame rate 30 fps, bitrate 930 Kbps. */ + AgoraVideoProfilePortrait480P_9 = 1048, + /** Resolution 480 * 640, frame rate 10 fps, bitrate 400 Kbps. */ + AgoraVideoProfilePortrait480P_10 = 1049, + /** Resolution 720 * 1280, frame rate 15 fps, bitrate 1130 Kbps. */ + AgoraVideoProfilePortrait720P = 1050, + /** Resolution 720 * 1280, frame rate 30 fps, bitrate 1710 Kbps. */ + AgoraVideoProfilePortrait720P_3 = 1052, + /** Resolution 720 * 960, frame rate 15 fps, bitrate 910 Kbps. */ + AgoraVideoProfilePortrait720P_5 = 1054, + /** Resolution 720 * 960, frame rate 30 fps, bitrate 1380 Kbps. */ + AgoraVideoProfilePortrait720P_6 = 1055, + /** (macOS only) Resolution 1080 * 1920, frame rate 15 fps, bitrate 2080 Kbps. */ + AgoraVideoProfilePortrait1080P = 1060, + /** (macOS only) Resolution 1080 * 1920, frame rate 30 fps, bitrate 3150 Kbps. */ + AgoraVideoProfilePortrait1080P_3 = 1062, + /** (macOS only) Resolution 1080 * 1920, frame rate 60 fps, bitrate 4780 Kbps. */ + AgoraVideoProfilePortrait1080P_5 = 1064, + /** Reserved for future use. */ + AgoraVideoProfilePortrait1440P = 1066, + /** Reserved for future use. */ + AgoraVideoProfilePortrait1440P_2 = 1067, + /** Reserved for future use. */ + AgoraVideoProfilePortrait4K = 1070, + /** Reserved for future use. */ + AgoraVideoProfilePortrait4K_3 = 1072, + /** (Default) Resolution 640 * 360, frame rate 15 fps, bitrate 400 Kbps. */ + AgoraVideoProfileDEFAULT = AgoraVideoProfileLandscape360P, +}; + +/** The camera capture preference. */ +typedef NS_ENUM(NSInteger, AgoraCameraCaptureOutputPreference) { + /** (default) Self-adapts the camera output parameters to the system performance and network conditions to balance CPU consumption and video preview quality. */ + AgoraCameraCaptureOutputPreferenceAuto = 0, + /** Prioritizes the system performance. The SDK chooses the dimension and frame rate of the local camera capture closest to those set by [setVideoEncoderConfiguration]([AgoraRtcEngineKit setVideoEncoderConfiguration:]). */ + AgoraCameraCaptureOutputPreferencePerformance = 1, + /** Prioritizes the local preview quality. The SDK chooses higher camera output parameters to improve the local video preview quality. This option requires extra CPU and RAM usage for video pre-processing. */ + AgoraCameraCaptureOutputPreferencePreview = 2, + /** Allows you to customize the width and height of the video image captured by the local camera. */ + AgoraCameraCaptureOutputPreferenceManual = 3, + /** Internal use only */ + AgoraCameraCaptureOutputPreferenceUnkown = 4 +}; + +#if defined(TARGET_OS_IOS) && TARGET_OS_IOS +/** The camera direction. */ +typedef NS_ENUM(NSInteger, AgoraCameraDirection) { + /** The rear camera. */ + AgoraCameraDirectionRear = 0, + /** The front camera. */ + AgoraCameraDirectionFront = 1, +}; +#endif + +/** Video frame rate */ +typedef NS_ENUM(NSInteger, AgoraVideoFrameRate) { + /** 1 fps. */ + AgoraVideoFrameRateFps1 = 1, + /** 7 fps. */ + AgoraVideoFrameRateFps7 = 7, + /** 10 fps. */ + AgoraVideoFrameRateFps10 = 10, + /** 15 fps. */ + AgoraVideoFrameRateFps15 = 15, + /** 24 fps. */ + AgoraVideoFrameRateFps24 = 24, + /** 30 fps. */ + AgoraVideoFrameRateFps30 = 30, + /** 60 fps (macOS only). */ + AgoraVideoFrameRateFps60 = 60, +}; + +/** Video output orientation mode. + + **Note:** When a custom video source is used, if you set AgoraVideoOutputOrientationMode as AgoraVideoOutputOrientationModeFixedLandscape(1) or AgoraVideoOutputOrientationModeFixedPortrait(2), when the rotated video image has a different orientation than the specified output orientation, the video encoder first crops it and then encodes it. + */ +typedef NS_ENUM(NSInteger, AgoraVideoOutputOrientationMode) { + /** Adaptive mode (Default). +

        The video encoder adapts to the orientation mode of the video input device. When you use a custom video source, the output video from the encoder inherits the orientation of the original video. +

        • If the width of the captured video from the SDK is greater than the height, the encoder sends the video in landscape mode. The encoder also sends the rotational information of the video, and the receiver uses the rotational information to rotate the received video.
        • +
        • If the original video is in portrait mode, the output video from the encoder is also in portrait mode. The encoder also sends the rotational information of the video to the receiver.

        + */ + AgoraVideoOutputOrientationModeAdaptative = 0, + /** Landscape mode. +

        The video encoder always sends the video in landscape mode. The video encoder rotates the original video before sending it and the rotational information is 0. This mode applies to scenarios involving CDN live streaming.

        + */ + AgoraVideoOutputOrientationModeFixedLandscape = 1, + /** Portrait mode. +

        The video encoder always sends the video in portrait mode. The video encoder rotates the original video before sending it and the rotational information is 0. This mode applies to scenarios involving CDN live streaming.

        + */ + AgoraVideoOutputOrientationModeFixedPortrait = 2, +}; + +/** Channel profile. */ +typedef NS_ENUM(NSInteger, AgoraChannelProfile) { + /** 0: Communication. +

        This profile applies to scenarios such as an audio call or video call, where all users can publish and subscribe to streams.

        + */ + AgoraChannelProfileCommunication = 0, + /** 1: Interactive live streaming. +

        In this profile, uses have roles, namely, host and audience (default). A host both publishes and subscribes to streams, while an audience subscribes to streams only. This profile applies to scenarios such as a chat room or interactive video streaming.

        + */ + AgoraChannelProfileLiveBroadcasting = 1, + /** Agora recommends not using this profile. + */ + AgoraChannelProfileGame = 2, +}; + +/** The role of a user in a interactive live streaming. */ +typedef NS_ENUM(NSInteger, AgoraClientRole) { + /** 1: Host. A host can both send and receive streams. + If you set this user role in the channel, the SDK automatically calls + [muteLocalAudioStream(NO)]([AgoraRtcEngineKit muteLocalAudioStream:]) and + [muteLocalVideoStream(NO)]([AgoraRtcEngineKit muteLocalVideoStream:]). + */ + AgoraClientRoleBroadcaster = 1, + /** 2: (Default) Audience. An audience member can only receive streams. + If you set this user role in the channel, the SDK automatically calls + [muteLocalAudioStream(YES)]([AgoraRtcEngineKit muteLocalAudioStream:]) and + [muteLocalVideoStream(YES)]([AgoraRtcEngineKit muteLocalVideoStream:]). + */ + AgoraClientRoleAudience = 2, +}; + +/** The latency level of an audience member in a interactive live streaming.

        **Note**:

        Takes effect only when the user role is + `AgoraClientRoleAudience`.

        */ +typedef NS_ENUM(NSInteger, AgoraAudienceLatencyLevelType) { + /** 1: Low latency. */ + AgoraAudienceLatencyLevelLowLatency = 1, + /** 2: (Default) Ultra low latency. */ + AgoraAudienceLatencyLevelUltraLowLatency = 2, +}; + +/** The brightness level of the video image captured by the local camera. */ +typedef NS_ENUM(NSInteger, AgoraCaptureBrightnessLevelType) { + /** -1: The SDK does not detect the brightness level of the video image. + Wait a few seconds to get the brightness level in the next callback. + */ + AgoraCaptureBrightnessLevelInvalid = -1, + /** 0: The brightness level of the video image is normal. + */ + AgoraCaptureBrightnessLevelNormal = 0, + /** 1: The brightness level of the video image is too bright. + */ + AgoraCaptureBrightnessLevelBright = 1, + /** 2: The brightness level of the video image is too dark. + */ + AgoraCaptureBrightnessLevelDark = 2, +}; + +/** Media type. */ +typedef NS_ENUM(NSInteger, AgoraMediaType) { + /** No audio and video. */ + AgoraMediaTypeNone = 0, + /** Audio only. */ + AgoraMediaTypeAudioOnly = 1, + /** Video only. */ + AgoraMediaTypeVideoOnly = 2, + /** Audio and video. */ + AgoraMediaTypeAudioAndVideo = 3, +}; + +/** Encryption mode. Agora recommends using either the + `AgoraEncryptionModeAES128GCM2` or `AgoraEncryptionModeAES256GCM2` encryption + mode, both of which support adding a salt and are more secure. + */ +typedef NS_ENUM(NSInteger, AgoraEncryptionMode) { + /** 0: **Deprecated** as of v3.4.5. */ + AgoraEncryptionModeNone __deprecated_enum_msg("AgoraEncryptionModeNone is deprecated.") = 0, + /** 1: 128-bit AES encryption, XTS mode. */ + AgoraEncryptionModeAES128XTS = 1, + /** 2: 128-bit AES encryption, ECB mode. */ + AgoraEncryptionModeAES128ECB = 2, + /** 3: 256-bit AES encryption, XTS mode. */ + AgoraEncryptionModeAES256XTS = 3, + /** 4: Reserved parameter. */ + AgoraEncryptionModeSM4128ECB = 4, + /** 5: 128-bit AES encryption, GCM mode. + + @since v3.3.1 + */ + AgoraEncryptionModeAES128GCM = 5, + /** 6: 256-bit AES encryption, GCM mode. + + @since v3.3.1 + */ + AgoraEncryptionModeAES256GCM = 6, + /** 7: (Default) 128-bit AES encryption, GCM mode. Compared to + `AgoraEncryptionModeAES128GCM` encryption mode, + `AgoraEncryptionModeAES128GCM2` encryption mode is more secure and requires + you to set the salt (`encryptionKdfSalt`). + + @since v3.4.5 + */ + AgoraEncryptionModeAES128GCM2 = 7, + /** 8: 256-bit AES encryption, GCM mode. Compared to + `AgoraEncryptionModeAES256GCM` encryption mode, + `AgoraEncryptionModeAES256GCM2` encryption mode is more secure and requires + you to set the salt (`encryptionKdfSalt`). + + @since v3.4.5 + */ + AgoraEncryptionModeAES256GCM2 = 8, + /** Enumerator boundary */ + AgoraEncryptionModeEnd, +}; + +/** Reason for the user being offline. */ +typedef NS_ENUM(NSUInteger, AgoraUserOfflineReason) { + /** The user left the current channel. */ + AgoraUserOfflineReasonQuit = 0, + /** The SDK timed out and the user dropped offline because no data packet is received within a certain period of time. If a user quits the call and the message is not passed to the SDK (due to an unreliable channel), the SDK assumes the user dropped offline. */ + AgoraUserOfflineReasonDropped = 1, + /** (Interactive live streaming only.) The client role switched from the host to the audience. */ + AgoraUserOfflineReasonBecomeAudience = 2, +}; + +/** The RTMP or RTMPS streaming state. */ +typedef NS_ENUM(NSUInteger, AgoraRtmpStreamingState) { + /** The RTMP or RTMPS streaming has not started or has ended. This state is also triggered after you remove an RTMP or RTMPS stream from the CDN by calling [removePublishStreamUrl]([AgoraRtcEngineKit removePublishStreamUrl:]).*/ + AgoraRtmpStreamingStateIdle = 0, + /** The SDK is connecting to Agora's streaming server and the CDN server. This state is triggered after you call the [addPublishStreamUrl]([AgoraRtcEngineKit addPublishStreamUrl:transcodingEnabled:]) method. */ + AgoraRtmpStreamingStateConnecting = 1, + /** The RTMP or RTMPS streaming is being published. The SDK successfully publishes the RTMP or RTMPS streaming and returns this state. */ + AgoraRtmpStreamingStateRunning = 2, + /** The RTMP or RTMPS streaming is recovering. When exceptions occur to the CDN, or the streaming is interrupted, the SDK attempts to resume RTMP or RTMPS streaming and returns this state. +
      23. If the SDK successfully resumes the streaming, `AgoraRtmpStreamingStateRunning(2)` returns. +
      24. If the streaming does not resume within 60 seconds or server errors occur, AgoraRtmpStreamingStateFailure(4) returns. You can also reconnect to the server by calling the [removePublishStreamUrl]([AgoraRtcEngineKit removePublishStreamUrl:]) and [addPublishStreamUrl]([AgoraRtcEngineKit addPublishStreamUrl:transcodingEnabled:]) methods. */ + AgoraRtmpStreamingStateRecovering = 3, + /** The RTMP or RTMPS streaming fails. See the errorCode parameter for the detailed error information. You can also call the [addPublishStreamUrl]([AgoraRtcEngineKit addPublishStreamUrl:transcodingEnabled:]) method to publish the RTMP or RTMPS streaming again. */ + AgoraRtmpStreamingStateFailure = 4, +}; + +/** The detailed error information for streaming. */ +typedef NS_ENUM(NSUInteger, AgoraRtmpStreamingErrorCode) { + /** The RTMP or RTMPS streaming publishes successfully. */ + AgoraRtmpStreamingErrorCodeOK = 0, + /** Invalid argument used. If, for example, you do not call the [setLiveTranscoding]([AgoraRtcEngineKit setLiveTranscoding:]) method to configure the LiveTranscoding parameters before calling the [addPublishStreamUrl]([AgoraRtcEngineKit addPublishStreamUrl:transcodingEnabled:]) method, the SDK returns this error. Check whether you set the parameters in the setLiveTranscoding method properly. */ + AgoraRtmpStreamingErrorCodeInvalidParameters = 1, + /** The RTMP or RTMPS streaming is encrypted and cannot be published. */ + AgoraRtmpStreamingErrorCodeEncryptedStreamNotAllowed = 2, + /** Timeout for the RTMP or RTMPS streaming. Call the [addPublishStreamUrl]([AgoraRtcEngineKit addPublishStreamUrl:transcodingEnabled:]) method to publish the streaming again. */ + AgoraRtmpStreamingErrorCodeConnectionTimeout = 3, + /** An error occurs in Agora's streaming server. Call the [addPublishStreamUrl]([AgoraRtcEngineKit addPublishStreamUrl:transcodingEnabled:]) method to publish the streaming again. */ + AgoraRtmpStreamingErrorCodeInternalServerError = 4, + /** An error occurs in the CDN server. */ + AgoraRtmpStreamingErrorCodeRtmpServerError = 5, + /** The RTMP or RTMPS streaming publishes too frequently. */ + AgoraRtmpStreamingErrorCodeTooOften = 6, + /** The host publishes more than 10 URLs. Delete the unnecessary URLs before adding new ones. */ + AgoraRtmpStreamingErrorCodeReachLimit = 7, + /** The host manipulates other hosts' URLs. Check your app logic. */ + AgoraRtmpStreamingErrorCodeNotAuthorized = 8, + /** Agora's server fails to find the RTMP or RTMPS streaming. */ + AgoraRtmpStreamingErrorCodeStreamNotFound = 9, + /** The format of the RTMP or RTMPS streaming URL is not supported. Check whether the URL format is correct. */ + AgoraRtmpStreamingErrorCodeFormatNotSupported = 10, + /** The streaming has been stopped normally. After you call + [removePublishStreamUrl]([AgoraRtcEngineKit removePublishStreamUrl:]) to + stop streaming, the SDK returns this value. + + @since v3.4.5 + */ + AgoraRtmpStreamingErrorCodeUnpublishOK = 100, +}; + +/** Events during the RTMP or RTMPS streaming. */ +typedef NS_ENUM(NSUInteger, AgoraRtmpStreamingEvent) { + /** 1: An error occurs when you add a background image or a watermark image + to the RTMP stream. + */ + AgoraRtmpStreamingEventFailedLoadImage = 1, + /** 2: The streaming URL is already being used for CDN live streaming. If you + want to start new streaming, use a new streaming URL. + + @since v3.4.5 + */ + AgoraRtmpStreamingEventUrlAlreadyInUse = 2, +}; + +/** State of importing an external video stream in the interactive live streaming. */ +typedef NS_ENUM(NSUInteger, AgoraInjectStreamStatus) { + /** The external video stream imported successfully. */ + AgoraInjectStreamStatusStartSuccess = 0, + /** The external video stream already exists. */ + AgoraInjectStreamStatusStartAlreadyExists = 1, + /** The external video stream import is unauthorized. */ + AgoraInjectStreamStatusStartUnauthorized = 2, + /** Import external video stream timeout. */ + AgoraInjectStreamStatusStartTimedout = 3, + /** The external video stream failed to import. */ + AgoraInjectStreamStatusStartFailed = 4, + /** The external video stream imports successfully. */ + AgoraInjectStreamStatusStopSuccess = 5, + /** No external video stream is found. */ + AgoraInjectStreamStatusStopNotFound = 6, + /** The external video stream is stopped from being unauthorized. */ + AgoraInjectStreamStatusStopUnauthorized = 7, + /** Importing the external video stream timeout. */ + AgoraInjectStreamStatusStopTimedout = 8, + /** Importing the external video stream failed. */ + AgoraInjectStreamStatusStopFailed = 9, + /** The external video stream import is interrupted. */ + AgoraInjectStreamStatusBroken = 10, +}; + +/** Output log filter level. */ +typedef NS_ENUM(NSUInteger, AgoraLogFilter) { + /** Do not output any log information. */ + AgoraLogFilterOff = 0, + /** Output all log information. Set your log filter as debug if you want to get the most complete log file. */ + AgoraLogFilterDebug = 0x080f, + /** Output CRITICAL, ERROR, WARNING, and INFO level log information. We recommend setting your log filter as this level. */ + AgoraLogFilterInfo = 0x000f, + /** Outputs CRITICAL, ERROR, and WARNING level log information. */ + AgoraLogFilterWarning = 0x000e, + /** Outputs CRITICAL and ERROR level log information. */ + AgoraLogFilterError = 0x000c, + /** Outputs CRITICAL level log information. */ + AgoraLogFilterCritical = 0x0008, +}; + +/** Audio recording quality, which is set in [startAudioRecordingWithConfig]([AgoraRtcEngineKit startAudioRecordingWithConfig:]). */ +typedef NS_ENUM(NSInteger, AgoraAudioRecordingQuality) { + /** 0: Low quality. For example, the size of an AAC file with a sample rate of 32,000 Hz and a 10-minute recording is approximately 1.2 MB. */ + AgoraAudioRecordingQualityLow = 0, + /** 1: (Default) Medium quality. For example, the size of an AAC file with a sample rate of 32,000 Hz and a 10-minute recording is approximately 2 MB. */ + AgoraAudioRecordingQualityMedium = 1, + /** 2: High quality. For example, the size of an AAC file with a sample rate of 32,000 Hz and a 10-minute recording is approximately 3.75 MB. */ + AgoraAudioRecordingQualityHigh = 2 +}; + +/** Recording content, which is set in [startAudioRecordingWithConfig]([AgoraRtcEngineKit startAudioRecordingWithConfig:]). */ +typedef NS_ENUM(NSInteger, AgoraAudioRecordingPosition) { + /** 0: (Default) Records the mixed audio of the local user and all remote users. */ + AgoraAudioRecordingPositionMixedRecordingAndPlayback = 0, + /** 1: Records the audio of the local user only. */ + AgoraAudioRecordingPositionRecording = 1, + /** 2: Records the audio of all remote users only. */ + AgoraAudioRecordingPositionMixedPlayback = 2 +}; + +/** Lifecycle of the CDN live video stream. + +**DEPRECATED** +*/ +typedef NS_ENUM(NSInteger, AgoraRtmpStreamLifeCycle) { + /** Bound to the channel lifecycle. If all hosts leave the channel, the CDN live streaming stops after 30 seconds. */ + AgoraRtmpStreamLifeCycleBindToChannel = 1, + /** Bound to the owner of the RTMP stream. If the owner leaves the channel, the CDN live streaming stops immediately. */ + AgoraRtmpStreamLifeCycleBindToOwnner = 2, +}; + +/** Network quality. */ +typedef NS_ENUM(NSUInteger, AgoraNetworkQuality) { + /** The network quality is unknown. */ + AgoraNetworkQualityUnknown = 0, + /** The network quality is excellent. */ + AgoraNetworkQualityExcellent = 1, + /** The network quality is quite good, but the bitrate may be slightly lower than excellent. */ + AgoraNetworkQualityGood = 2, + /** Users can feel the communication slightly impaired. */ + AgoraNetworkQualityPoor = 3, + /** Users can communicate only not very smoothly. */ + AgoraNetworkQualityBad = 4, + /** The network quality is so bad that users can hardly communicate. */ + AgoraNetworkQualityVBad = 5, + /** The network is disconnected and users cannot communicate at all. */ + AgoraNetworkQualityDown = 6, + /** Users cannot detect the network quality. (Not in use.) */ + AgoraNetworkQualityUnsupported = 7, + /** Detecting the network quality. */ + AgoraNetworkQualityDetecting = 8, +}; + +/** Quality of experience (QoE) of the local user when receiving a remote audio stream. + + @since v3.3.0 + */ +typedef NS_ENUM(NSUInteger, AgoraExperienceQuality) { + /** QoE of the local user is good. */ + AgoraExperienceQualityGood = 0, + /** QoE of the local user is poor. */ + AgoraExperienceQualityBad = 1, +}; + +/** The reason for poor QoE of the local user when receiving a remote audio stream. + + @since v3.3.0 + */ +typedef NS_ENUM(NSUInteger, AgoraExperiencePoorReason) { + /** None, indicating good QoE of the local user. */ + AgoraExperienceReasonNone = 0, + /** The remote user's network quality is poor. */ + AgoraRemoteNetworkPoor = 1, + /** The local user's network quality is poor. */ + AgoraLocalNetworkPoor = 2, + /** The local user's Wi-Fi or mobile network signal is weak. */ + AgoraWirelessSignalPoor = 4, + /** he local user enables both Wi-Fi and bluetooth, and their signals interfere with each other. As a result, audio transmission quality is undermined. */ + AgoraWifiBluetoothCoexist = 8, +}; + +/** API for future use. + */ +typedef NS_ENUM(NSInteger, AgoraUploadErrorReason) { + AgoraUploadErrorReasonSuccess = 0, + AgoraUploadErrorReasonNetError = 1, + AgoraUploadErrorReasonServerError = 2, +}; + +/** Video stream type. */ +typedef NS_ENUM(NSInteger, AgoraVideoStreamType) { + /** High-bitrate, high-resolution video stream. */ + AgoraVideoStreamTypeHigh = 0, + /** Low-bitrate, low-resolution video stream. */ + AgoraVideoStreamTypeLow = 1, +}; + +/** The priority of the remote user. */ +typedef NS_ENUM(NSInteger, AgoraUserPriority) { + /** The user's priority is high. */ + AgoraUserPriorityHigh = 50, + /** (Default) The user's priority is normal. */ + AgoraUserPriorityNormal = 100, +}; + +/** Quality change of the local video in terms of target frame rate and target bit rate since last count. */ +typedef NS_ENUM(NSInteger, AgoraVideoQualityAdaptIndication) { + /** The quality of the local video stays the same. */ + AgoraVideoQualityAdaptNone = 0, + /** The quality improves because the network bandwidth increases. */ + AgoraVideoQualityAdaptUpBandwidth = 1, + /** The quality worsens because the network bandwidth decreases. */ + AgoraVideoQualityAdaptDownBandwidth = 2, +}; + +/** Video display mode. */ +typedef NS_ENUM(NSUInteger, AgoraVideoRenderMode) { + /** Hidden(1): Uniformly scale the video until it fills the visible boundaries (cropped). One dimension of the video may have clipped contents. */ + AgoraVideoRenderModeHidden = 1, + + /** Fit(2): Uniformly scale the video until one of its dimension fits the boundary (zoomed to fit). Areas that are not filled due to the disparity in the aspect ratio are filled with black. */ + AgoraVideoRenderModeFit = 2, + + /** Adaptive(3):This mode is deprecated. */ + AgoraVideoRenderModeAdaptive __deprecated_enum_msg("AgoraVideoRenderModeAdaptive is deprecated.") = 3, + + /** Fill(4): The fill mode. In this mode, the SDK stretches or zooms the video to fill the display window. */ + AgoraVideoRenderModeFill = 4, +}; + +/** Self-defined video codec profile. */ +typedef NS_ENUM(NSInteger, AgoraVideoCodecProfileType) { + /** 66: Baseline video codec profile. Generally used in video calls on mobile phones. */ + AgoraVideoCodecProfileTypeBaseLine = 66, + /** 77: Main video codec profile. Generally used in mainstream electronics, such as MP4 players, portable video players, PSP, and iPads. */ + AgoraVideoCodecProfileTypeMain = 77, + /** 100: (Default) High video codec profile. Generally used in high-resolution interactive live streaming or television. */ + AgoraVideoCodecProfileTypeHigh = 100 +}; + +/** The video codec type. (iOS only) */ +typedef NS_ENUM(NSInteger, AgoraVideoCodecType) { + /** 1: VP8 */ + AgoraVideoCodecTypeVP8 = 1, + /** 2: (Default) H.264 */ + AgoraVideoCodecTypeH264 = 2, + /** 3: Enhanced VP8 */ + AgoraVideoCodecTypeEVP = 3, + /** 4: Enhanced H.264 */ + AgoraVideoCodecTypeE264 = 4, +}; + +/** The video codec type of the output video stream. + + @since v3.2.0 + */ +typedef NS_ENUM(NSInteger, AgoraVideoCodecTypeForStream) { + /** 1: (Default) H.264 */ + AgoraVideoCodecTypeH264ForStream = 1, + /** 2: H.265 */ + AgoraVideoCodecTypeH265ForStream = 2, +}; + +/** Video mirror mode. */ +typedef NS_ENUM(NSUInteger, AgoraVideoMirrorMode) { + /** 0: (Default) The SDK determines the mirror mode. + */ + AgoraVideoMirrorModeAuto = 0, + /** 1: Enables mirror mode. */ + AgoraVideoMirrorModeEnabled = 1, + /** 2: Disables mirror mode. */ + AgoraVideoMirrorModeDisabled = 2, +}; + +/** The publishing state */ +typedef NS_ENUM(NSUInteger, AgoraStreamPublishState) { + /** 0: The initial publishing state after joining the channel. + */ + AgoraStreamPublishIdle = 0, + /** 1: Fails to publish the local stream. Possible reasons: +
      25. The local user calls [muteLocalAudioStream(YES)]([AgoraRtcEngineKit muteLocalAudioStream:]) or [muteLocalVideoStream(YES)]([AgoraRtcEngineKit muteLocalVideoStream:]) to stop sending local streams.
      26. +
      27. The local user calls [disableAudio]([AgoraRtcEngineKit disableAudio]) or [disableVideo]([AgoraRtcEngineKit disableVideo]) to disable the entire audio or video module.
      28. +
      29. The local user calls [enableLocalAudio(NO)]([AgoraRtcEngineKit enableLocalAudio:]) or [enableLocalVideo(NO)]([AgoraRtcEngineKit enableLocalVideo:]) to disable the local audio sampling or video capturing.
      30. +
      31. The role of the local user is AgoraClientRoleAudience.
      32. + */ + AgoraStreamPublishNoPublished = 1, + /** 2: Publishing. + */ + AgoraStreamPublishPublishing = 2, + /** 3: Publishes successfully. + */ + AgoraStreamPublishPublished = 3, +}; + +/** The subscribing state. */ +typedef NS_ENUM(NSUInteger, AgoraStreamSubscribeState) { + /** 0: The initial subscribing state after joining the channel. + */ + AgoraStreamSubscribeIdle = 0, + /** 1: Fails to subscribe to the remote stream. Possible reasons: +
      33. The remote user:
      34. +
        • Calls [muteLocalAudioStream(YES)]([AgoraRtcEngineKit muteLocalAudioStream:]) or [muteLocalVideoStream(YES)]([AgoraRtcEngineKit muteLocalVideoStream:]) to stop sending local streams.
        +
        • The local user calls [disableAudio]([AgoraRtcEngineKit disableAudio]) or [disableVideo]([AgoraRtcEngineKit disableVideo]) to disable the entire audio or video module.
        +
        • The local user calls [enableLocalAudio(NO)]([AgoraRtcEngineKit enableLocalAudio:]) or [enableLocalVideo(NO)]([AgoraRtcEngineKit enableLocalVideo:]) to disable the local audio sampling or video capturing.
        +
        • The role of the local user is AgoraClientRoleAudience.
        +
      35. The local user calls the following methods to stop receiving remote streams:
      36. +
        • Calls [muteRemoteAudioStream(YES)]([AgoraRtcEngineKit muteRemoteAudioStream:mute:]), [muteAllRemoteAudioStreams(YES)]([AgoraRtcEngineKit muteAllRemoteAudioStreams:]), or [setDefaultMuteAllRemoteAudioStreams(YES)]([AgoraRtcEngineKit setDefaultMuteAllRemoteAudioStreams:]) to stop receiving remote audio streams.
        +
        • Calls [muteRemoteVideoStream(YES)]([AgoraRtcEngineKit muteRemoteVideoStream:mute:]), [muteAllRemoteVideoStreams(YES)]([AgoraRtcEngineKit muteAllRemoteVideoStreams:]), or [setDefaultMuteAllRemoteVideoStreams(YES)]([AgoraRtcEngineKit setDefaultMuteAllRemoteVideoStreams:]) to stop receiving remote video streams.
        + */ + AgoraStreamSubscribeNoSubscribed = 1, + /** 2: Subscribing. + */ + AgoraStreamSubscribeSubscribing = 2, + /** 3: Subscribes to and receives the remote stream successfully. + */ + AgoraStreamSubscribeSubscribed = 3, +}; + +/** The content hint for screen sharing. */ +typedef NS_ENUM(NSUInteger, AgoraVideoContentHint) { + /** 0: (Default) No content hint. */ + AgoraVideoContentHintNone = 0, + /** 1: Motion-intensive content. Choose this option if you prefer smoothness or when you are sharing a video clip, movie, or video game. */ + AgoraVideoContentHintMotion = 1, + /** 2: Motionless content. Choose this option if you prefer sharpness or when you are sharing a picture, PowerPoint slide, or text. */ + AgoraVideoContentHintDetails = 2, +}; + +/** The state of the remote video. */ +typedef NS_ENUM(NSUInteger, AgoraVideoRemoteState) { + /** 0: The remote video is in the default state, probably due to `AgoraVideoRemoteStateReasonLocalMuted(3)`, `AgoraVideoRemoteStateReasonRemoteMuted(5)`, or `AgoraVideoRemoteStateReasonRemoteOffline(7)`. + */ + AgoraVideoRemoteStateStopped = 0, + /** 1: The first remote video packet is received. + */ + AgoraVideoRemoteStateStarting = 1, + /** 2: The remote video stream is decoded and plays normally, probably due to `AgoraVideoRemoteStateReasonNetworkRecovery(2)`, `AgoraVideoRemoteStateReasonLocalUnmuted(4)`, `AgoraVideoRemoteStateReasonRemoteUnmuted(6)`, or `AgoraVideoRemoteStateReasonAudioFallbackRecovery(9)`. + */ + AgoraVideoRemoteStateDecoding = 2, + /** 3: The remote video is frozen, probably due to `AgoraVideoRemoteStateReasonNetworkCongestion(1)` or `AgoraVideoRemoteStateReasonAudioFallback(8)`. + */ + AgoraVideoRemoteStateFrozen = 3, + /** 4: The remote video fails to start, probably due to `AgoraVideoRemoteStateReasonInternal(0)`. + */ + AgoraVideoRemoteStateFailed = 4, +}; + +/** The reason for the remote video state change. */ +typedef NS_ENUM(NSUInteger, AgoraVideoRemoteStateReason) { + /** 0: The SDK reports this reason when the video state changes. */ + AgoraVideoRemoteStateReasonInternal = 0, + /** 1: Network congestion. */ + AgoraVideoRemoteStateReasonNetworkCongestion = 1, + /** 2: Network recovery. */ + AgoraVideoRemoteStateReasonNetworkRecovery = 2, + /** 3: The local user stops receiving the remote video stream or disables the video module. */ + AgoraVideoRemoteStateReasonLocalMuted = 3, + /** 4: The local user resumes receiving the remote video stream or enables the video module. */ + AgoraVideoRemoteStateReasonLocalUnmuted = 4, + /** 5: The remote user stops sending the video stream or disables the video module. */ + AgoraVideoRemoteStateReasonRemoteMuted = 5, + /** 6: The remote user resumes sending the video stream or enables the video module. */ + AgoraVideoRemoteStateReasonRemoteUnmuted = 6, + /** 7: The remote user leaves the channel. */ + AgoraVideoRemoteStateReasonRemoteOffline = 7, + /** 8: The remote audio-and-video stream falls back to the audio-only stream due to poor network conditions. */ + AgoraVideoRemoteStateReasonAudioFallback = 8, + /** 9: The remote audio-only stream switches back to the audio-and-video stream after the network conditions improve. */ + AgoraVideoRemoteStateReasonAudioFallbackRecovery = 9, +}; + +/** The reason why super resolution is not successfully enabled or the message + that confirms success. + + @since v3.5.1 + */ +typedef NS_ENUM(NSUInteger, AgoraSuperResolutionStateReason) { + /** 0: Super resolution is successfully enabled. */ + AgoraSRStateReasonSuccess = 0, + /** 1: The original resolution of the remote video is beyond the range where + super resolution can be applied. + */ + AgoraSRStateReasonStreamOverLimitation = 1, + /** 2: Super resolution is already being used to boost another remote user's video. */ + AgoraSRStateReasonUserCountOverLimitation = 2, + /** 3: The device does not support using super resolution. */ + AgoraSRStateReasonDeviceNotSupported = 3, +}; + +/** The reason why the virtual background is not successfully enabled or the + message that confirms success. + @since v3.4.5 + */ +typedef NS_ENUM(NSUInteger, AgoraVirtualBackgroundSourceStateReason) { + /** 0: The virtual background is successfully enabled.*/ + AgoraVBSStateReasonSuccess = 0, + /** 1: The custom background image does not exist. Please check the value of + `source` in AgoraVirtualBackgroundSource. + */ + AgoraVBSStateReasonImageNotExist = 1, + /** 2: The color format of the custom background image is invalid. Please + check the value of `color` in AgoraVirtualBackgroundSource. + */ + AgoraVBSStateReasonColorFormatNotSupported = 2, + /** 3: The device does not support using the virtual background.*/ + AgoraVBSStateReasonDeviceNotSupported = 3, +}; + +/** Stream fallback option. */ +typedef NS_ENUM(NSInteger, AgoraStreamFallbackOptions) { + /** No fallback behavior for the local/remote video stream when the uplink/downlink network condition is unreliable. The quality of the stream is not guaranteed. */ + AgoraStreamFallbackOptionDisabled = 0, + /** Under unreliable downlink network conditions, the remote video stream falls back to the low-stream (low resolution and low bitrate) video. You can only set this option in the [setRemoteSubscribeFallbackOption]([AgoraRtcEngineKit setRemoteSubscribeFallbackOption:]) method. Nothing happens when you set this in the [setLocalPublishFallbackOption]([AgoraRtcEngineKit setLocalPublishFallbackOption:]) method. */ + AgoraStreamFallbackOptionVideoStreamLow = 1, + /** Under unreliable uplink network conditions, the published video stream falls back to audio only. Under unreliable downlink network conditions, the remote video stream first falls back to the low-stream (low resolution and low bitrate) video; and then to an audio-only stream if the network condition deteriorates. */ + AgoraStreamFallbackOptionAudioOnly = 2, +}; + +/** Audio sample rate. */ +typedef NS_ENUM(NSInteger, AgoraAudioSampleRateType) { + /** 32 kHz. */ + AgoraAudioSampleRateType32000 = 32000, + /** 44.1 kHz. */ + AgoraAudioSampleRateType44100 = 44100, + /** 48 kHz. */ + AgoraAudioSampleRateType48000 = 48000, +}; + +/** Audio profile. */ +typedef NS_ENUM(NSInteger, AgoraAudioProfile) { + /** 0: Default audio profile. +
      37. In the Communication profile: A sample rate of 32 KHz, audio encoding, mono, and a bitrate of up to 18 Kbps. +
      38. In the interactive live streaming profile: A sample rate of 48 KHz, music encoding, mono, and a bitrate of up to 64 Kbps.
      39. */ + AgoraAudioProfileDefault = 0, + /** 1: A sample rate of 32 KHz, audio encoding, mono, and a bitrate of up to 18 Kbps. */ + AgoraAudioProfileSpeechStandard = 1, + /** 2: A sample rate of 48 KHz, music encoding, mono, and a bitrate of up to 64 Kbps. */ + AgoraAudioProfileMusicStandard = 2, + /** 3: A sample rate of 48 KHz, music encoding, stereo, and a bitrate of up to 80 Kbps. */ + AgoraAudioProfileMusicStandardStereo = 3, + /** 4: A sample rate of 48 KHz, music encoding, mono, and a bitrate of up to 96 Kbps. */ + AgoraAudioProfileMusicHighQuality = 4, + /** 5: A sample rate of 48 KHz, music encoding, stereo, and a bitrate of up to 128 Kbps. */ + AgoraAudioProfileMusicHighQualityStereo = 5, +}; + +/** Audio scenario. */ +typedef NS_ENUM(NSInteger, AgoraAudioScenario) { + /** 0: Default audio scenario. +

        Note: If you run the iOS app on an M1 Mac, due to the hardware + differences between M1 Macs, iPhones, and iPads, the default audio scenario + of the Agora iOS SDK is the same as that of the Agora macOS SDK.

        + */ + AgoraAudioScenarioDefault = 0, + /** 1: Entertainment scenario where users need to frequently switch the user role. */ + AgoraAudioScenarioChatRoomEntertainment = 1, + /** 2: Education scenario where users want smoothness and stability. */ + AgoraAudioScenarioEducation = 2, + /** 3: High-quality audio chatroom scenario where hosts mainly play music.*/ + AgoraAudioScenarioGameStreaming = 3, + /** 4: Showroom scenario where a single host wants high-quality audio. */ + AgoraAudioScenarioShowRoom = 4, + /** 5: Gaming scenario for group chat that only contains the human voice. */ + AgoraAudioScenarioChatRoomGaming = 5, + /** 6: IoT (Internet of Things) scenario where users use IoT devices with low power consumption. */ + AgoraAudioScenarioIot = 6, + /** Communication scenario.*/ + AgoraAudioScenarioCommunication = 7, + /** 8: Meeting scenario that mainly contains the human voice. + + @since v3.2.0 + */ + AgoraAudioScenarioMeeting = 8, +}; + +/** The current audio route. Reports in the [didAudioRouteChanged]([AgoraRtcEngineDelegate rtcEngine:didAudioRouteChanged:]) callback. */ +typedef NS_ENUM(NSInteger, AgoraAudioOutputRouting) { + /** -1: Default audio route. */ + AgoraAudioOutputRoutingDefault = -1, + /** 0: The audio route is a headset with a microphone.*/ + AgoraAudioOutputRoutingHeadset = 0, + /** 1: The audio route is an earpiece. */ + AgoraAudioOutputRoutingEarpiece = 1, + /** 2: The audio route is a headset without a microphone. */ + AgoraAudioOutputRoutingHeadsetNoMic = 2, + /** 3: The audio route is the speaker that comes with the device. */ + AgoraAudioOutputRoutingSpeakerphone = 3, + /** 4: The audio route is a Bluetooth headset. */ + AgoraAudioOutputRoutingLoudspeaker = 4, + /** 5: Bluetooth headset. */ + AgoraAudioOutputRoutingHeadsetBluetooth = 5, + /** 6: (macOS only) The audio route is a USB peripheral device. */ + AgoraAudioOutputRoutingUsb = 6, + /** 7: (macOS only) The audio route is an HDMI peripheral device. */ + AgoraAudioOutputRoutingHdmi = 7, + /** 8: (macOS only) The audio route is a DisplayPort peripheral device. */ + AgoraAudioOutputRoutingDisplayPort = 8, + /** 9: The audio route is Apple AirPlay. */ + AgoraAudioOutputRoutingAirPlay = 9 +}; + +/** The use mode of the audio data. */ +typedef NS_ENUM(NSInteger, AgoraAudioRawFrameOperationMode) { + /** 0: (Default) Read-only mode, in which users can only read the + AgoraAudioFrame without modifying anything. For example, this mode + applies when users acquire data with the Agora SDK and then push the + RTMP or RTMPS streams. + */ + AgoraAudioRawFrameOperationModeReadOnly = 0, + /** 1: Write-only mode, in which users replace the AgoraAudioFrame with their + own data and then pass it to the SDK for encoding. For example, this mode + applies when users need the Agora SDK to encode and transmit their custom + audio data. + */ + AgoraAudioRawFrameOperationModeWriteOnly = 1, + /** 2: Read and write mode, in which users read the AgoraAudioFrame, + modify it, and then play it. For example, this mode applies when users + have their own sound-effect processing module to pre-process the audio + (such as a voice changer). + */ + AgoraAudioRawFrameOperationModeReadWrite = 2, +}; + +/** Audio equalization band frequency. */ +typedef NS_ENUM(NSInteger, AgoraAudioEqualizationBandFrequency) { + /** 31 Hz. */ + AgoraAudioEqualizationBand31 = 0, + /** 62 Hz. */ + AgoraAudioEqualizationBand62 = 1, + /** 125 Hz. */ + AgoraAudioEqualizationBand125 = 2, + /** 250 Hz. */ + AgoraAudioEqualizationBand250 = 3, + /** 500 Hz */ + AgoraAudioEqualizationBand500 = 4, + /** 1 kHz. */ + AgoraAudioEqualizationBand1K = 5, + /** 2 kHz. */ + AgoraAudioEqualizationBand2K = 6, + /** 4 kHz. */ + AgoraAudioEqualizationBand4K = 7, + /** 8 kHz. */ + AgoraAudioEqualizationBand8K = 8, + /** 16 kHz. */ + AgoraAudioEqualizationBand16K = 9, +}; + +/** Audio reverberation type. */ +typedef NS_ENUM(NSInteger, AgoraAudioReverbType) { + /** The level of the dry signal (dB). The value ranges between -20 and 10. */ + AgoraAudioReverbDryLevel = 0, + /** The level of the early reflection signal (wet signal) in dB. The value ranges between -20 and 10. */ + AgoraAudioReverbWetLevel = 1, + /** The room size of the reverberation. A larger room size means a stronger reverberation. The value ranges between 0 and 100. */ + AgoraAudioReverbRoomSize = 2, + /** The length of the initial delay of the wet signal (ms). The value ranges between 0 and 200. */ + AgoraAudioReverbWetDelay = 3, + /** The reverberation strength. The value ranges between 0 and 100. */ + AgoraAudioReverbStrength = 4, +}; + +/** **DEPRECATED** from v3.2.0. The preset audio voice configuration used to change the voice effect. */ +typedef NS_ENUM(NSInteger, AgoraAudioVoiceChanger) { + /** Turn off the local voice changer, that is, to use the original voice. */ + AgoraAudioVoiceChangerOff __deprecated_enum_msg("AgoraAudioVoiceChangerOff is deprecated.") = 0x00000000, + /** The voice of an old man. */ + AgoraAudioVoiceChangerOldMan __deprecated_enum_msg("AgoraAudioVoiceChangerOldMan is deprecated.") = 0x00000001, + /** The voice of a little boy. */ + AgoraAudioVoiceChangerBabyBoy __deprecated_enum_msg("AgoraAudioVoiceChangerBabyBoy is deprecated.") = 0x00000002, + /** The voice of a little girl. */ + AgoraAudioVoiceChangerBabyGirl __deprecated_enum_msg("AgoraAudioVoiceChangerBabyGirl is deprecated.") = 0x00000003, + /** The voice of Zhu Bajie, a character in Journey to the West who has a voice like that of a growling bear. */ + AgoraAudioVoiceChangerZhuBaJie __deprecated_enum_msg("AgoraAudioVoiceChangerZhuBaJie is deprecated.") = 0x00000004, + /** The ethereal voice. */ + AgoraAudioVoiceChangerEthereal __deprecated_enum_msg("AgoraAudioVoiceChangerEthereal is deprecated.") = 0x00000005, + /** The voice of Hulk. */ + AgoraAudioVoiceChangerHulk __deprecated_enum_msg("AgoraAudioVoiceChangerHulk is deprecated.") = 0x00000006, + /** A more vigorous voice. */ + AgoraAudioVoiceBeautyVigorous __deprecated_enum_msg("AgoraAudioVoiceBeautyVigorous is deprecated.") = 0x00100001, + /** A deeper voice. */ + AgoraAudioVoiceBeautyDeep __deprecated_enum_msg("AgoraAudioVoiceBeautyDeep is deprecated.") = 0x00100002, + /** A mellower voice. */ + AgoraAudioVoiceBeautyMellow __deprecated_enum_msg("AgoraAudioVoiceBeautyMellow is deprecated.") = 0x00100003, + /** Falsetto. */ + AgoraAudioVoiceBeautyFalsetto __deprecated_enum_msg("AgoraAudioVoiceBeautyFalsetto is deprecated.") = 0x00100004, + /** A fuller voice. */ + AgoraAudioVoiceBeautyFull __deprecated_enum_msg("AgoraAudioVoiceBeautyFull is deprecated.") = 0x00100005, + /** A clearer voice. */ + AgoraAudioVoiceBeautyClear __deprecated_enum_msg("AgoraAudioVoiceBeautyClear is deprecated.") = 0x00100006, + /** A more resounding voice. */ + AgoraAudioVoiceBeautyResounding __deprecated_enum_msg("AgoraAudioVoiceBeautyResounding is deprecated.") = 0x00100007, + /** A more ringing voice. */ + AgoraAudioVoiceBeautyRinging __deprecated_enum_msg("AgoraAudioVoiceBeautyRinging is deprecated.") = 0x00100008, + /** A more spatially resonant voice. */ + AgoraAudioVoiceBeautySpacial __deprecated_enum_msg("AgoraAudioVoiceBeautySpacial is deprecated.") = 0x00100009, + /** (For male only) A more magnetic voice. Do not use it when the speaker is a female; otherwise, voice distortion occurs. */ + AgoraAudioGeneralBeautyVoiceMaleMagnetic __deprecated_enum_msg("AgoraAudioGeneralBeautyVoiceMaleMagnetic is deprecated.") = 0x00200001, + /** (For female only) A fresher voice. Do not use it when the speaker is a male; otherwise, voice distortion occurs. */ + AgoraAudioGeneralBeautyVoiceFemaleFresh __deprecated_enum_msg("AgoraAudioGeneralBeautyVoiceFemaleFresh is deprecated.") = 0x00200002, + /** (For female only) A more vital voice. Do not use it when the speaker is a male; otherwise, voice distortion occurs. */ + AgoraAudioGeneralBeautyVoiceFemaleVitality __deprecated_enum_msg("AgoraAudioGeneralBeautyVoiceFemaleVitality is deprecated.") = 0x00200003, +}; + +/** **DEPRECATED** from v3.2.0. The preset local voice reverberation option. */ +typedef NS_ENUM(NSInteger, AgoraAudioReverbPreset) { + /** Turn off local voice reverberation, that is, to use the original voice. */ + AgoraAudioReverbPresetOff __deprecated_enum_msg("AgoraAudioReverbPresetOff is deprecated.") = 0x00000000, + /** The reverberation style typical of a KTV venue (enhanced). */ + AgoraAudioReverbPresetFxKTV __deprecated_enum_msg("AgoraAudioReverbPresetFxKTV is deprecated.") = 0x00100001, + /** The reverberation style typical of a concert hall (enhanced). */ + AgoraAudioReverbPresetFxVocalConcert __deprecated_enum_msg("AgoraAudioReverbPresetFxVocalConcert is deprecated.") = 0x00100002, + /** The reverberation style typical of an uncle's voice. */ + AgoraAudioReverbPresetFxUncle __deprecated_enum_msg("AgoraAudioReverbPresetFxUncle is deprecated.") = 0x00100003, + /** The reverberation style typical of a sister's voice. */ + AgoraAudioReverbPresetFxSister __deprecated_enum_msg("AgoraAudioReverbPresetFxSister is deprecated.") = 0x00100004, + /** The reverberation style typical of a recording studio (enhanced). */ + AgoraAudioReverbPresetFxStudio __deprecated_enum_msg("AgoraAudioReverbPresetFxStudio is deprecated.") = 0x00100005, + /** The reverberation style typical of popular music (enhanced). */ + AgoraAudioReverbPresetFxPopular __deprecated_enum_msg("AgoraAudioReverbPresetFxPopular is deprecated.") = 0x00100006, + /** The reverberation style typical of R&B music (enhanced). */ + AgoraAudioReverbPresetFxRNB __deprecated_enum_msg("AgoraAudioReverbPresetFxRNB is deprecated.") = 0x00100007, + /** The reverberation style typical of the vintage phonograph. */ + AgoraAudioReverbPresetFxPhonograph __deprecated_enum_msg("AgoraAudioReverbPresetFxPhonograph is deprecated.") = 0x00100008, + /** The reverberation style typical of popular music. */ + AgoraAudioReverbPresetPopular __deprecated_enum_msg("AgoraAudioReverbPresetPopular is deprecated.") = 0x00000001, + /** The reverberation style typical of R&B music. */ + AgoraAudioReverbPresetRnB __deprecated_enum_msg("AgoraAudioReverbPresetRnB is deprecated.") = 0x00000002, + /** The reverberation style typical of rock music. */ + AgoraAudioReverbPresetRock __deprecated_enum_msg("AgoraAudioReverbPresetRock is deprecated.") = 0x00000003, + /** The reverberation style typical of hip-hop music. */ + AgoraAudioReverbPresetHipHop __deprecated_enum_msg("AgoraAudioReverbPresetHipHop is deprecated.") = 0x00000004, + /** The reverberation style typical of a concert hall. */ + AgoraAudioReverbPresetVocalConcert __deprecated_enum_msg("AgoraAudioReverbPresetVocalConcert is deprecated.") = 0x00000005, + /** The reverberation style typical of a KTV venue. */ + AgoraAudioReverbPresetKTV __deprecated_enum_msg("AgoraAudioReverbPresetKTV is deprecated.") = 0x00000006, + /** The reverberation style typical of a recording studio. */ + AgoraAudioReverbPresetStudio __deprecated_enum_msg("AgoraAudioReverbPresetStudio is deprecated.") = 0x00000007, + /** The reverberation of the virtual stereo. The virtual stereo is an effect that renders the monophonic audio as the stereo audio, so that all users in the channel can hear the stereo voice effect. To achieve better virtual stereo reverberation, Agora recommends setting the `profile` parameter in `setAudioProfile` as `AgoraAudioProfileMusicHighQualityStereo(5)`. */ + AgoraAudioReverbPresetVirtualStereo __deprecated_enum_msg("AgoraAudioReverbPresetVirtualStereo is deprecated.") = 0x00200001, + /** The reverberation of the Electronic Voice */ + AgoraAudioReverbPresetElectronicVoice __deprecated_enum_msg("AgoraAudioReverbPresetElectronicVoice is deprecated.") = 0x00300001, + /** 3D Voice */ + AgoraAudioReverbPresetThreeDimVoice __deprecated_enum_msg("AgoraAudioReverbPresetThreeDimVoice is deprecated.") = 0x00400001 + +}; + +/** The options for SDK preset voice beautifier effects. */ +typedef NS_ENUM(NSInteger, AgoraVoiceBeautifierPreset) { + /** Turn off voice beautifier effects and use the original voice. */ + AgoraVoiceBeautifierOff = 0x00000000, + /** A more magnetic voice.

        **Note**

        Agora recommends using this enumerator to process a male-sounding voice; otherwise, you + may experience vocal distortion.

        + */ + AgoraChatBeautifierMagnetic = 0x01010100, + /** A fresher voice.

        **Note**

        Agora recommends using this enumerator to process a female-sounding voice; otherwise, you + may experience vocal distortion.

        + */ + AgoraChatBeautifierFresh = 0x01010200, + /** A more vital voice.

        **Note**

        Agora recommends using this enumerator to process a female-sounding voice; otherwise, you + may experience vocal distortion.

        + */ + AgoraChatBeautifierVitality = 0x01010300, + /** Singing beautifier effect. +
      40. If you call [setVoiceBeautifierPreset(AgoraSingingBeautifier)]([AgoraRtcEngineKit setVoiceBeautifierPreset:]), + you can beautify a male-sounding voice and add a reverberation effect that + sounds like singing in a small room. Agora recommends not using + setVoiceBeautifierPreset(AgoraSingingBeautifier) to process a + female-sounding voice; otherwise, you may experience vocal distortion.
      41. +
      42. If you call [setVoiceBeautifierParameters(AgoraSingingBeautifier, param1, param2)]([AgoraRtcEngineKit setVoiceBeautifierParameters:param1:param2:]), + you can beautify a male- or female-sounding voice and add a reverberation + effect.
      43. + + @since v3.3.0 + */ + AgoraSingingBeautifier = 0x01020100, + /** A more vigorous voice. */ + AgoraTimbreTransformationVigorous = 0x01030100, + /** A deeper voice. */ + AgoraTimbreTransformationDeep = 0x01030200, + /** A mellower voice. */ + AgoraTimbreTransformationMellow = 0x01030300, + /** A falsetto voice. */ + AgoraTimbreTransformationFalsetto = 0x01030400, + /** A fuller voice. */ + AgoraTimbreTransformationFull = 0x01030500, + /** A clearer voice. */ + AgoraTimbreTransformationClear = 0x01030600, + /** A more resounding voice. */ + AgoraTimbreTransformationResounding = 0x01030700, + /** A more ringing voice. */ + AgoraTimbreTransformationRinging = 0x01030800 +}; + +/** The options for SDK preset audio effects. */ +typedef NS_ENUM(NSInteger, AgoraAudioEffectPreset) { + /** Turn off audio effects and use the original voice. */ + AgoraAudioEffectOff = 0x00000000, + /** An audio effect typical of a KTV venue. +

        **Note**

        +

        To achieve better audio effect quality, Agora recommends calling [setAudioProfile]([AgoraRtcEngineKit setAudioProfile:scenario:]) + and setting the `profile` parameter to `AgoraAudioProfileMusicHighQuality(4)` or `AgoraAudioProfileMusicHighQualityStereo(5)` + before setting this enumerator.

        + */ + AgoraRoomAcousticsKTV = 0x02010100, + /** An audio effect typical of a concert hall. +

        **Note**

        +

        To achieve better audio effect quality, Agora recommends calling [setAudioProfile]([AgoraRtcEngineKit setAudioProfile:scenario:]) + and setting the `profile` parameter to `AgoraAudioProfileMusicHighQuality(4)` or `AgoraAudioProfileMusicHighQualityStereo(5)` + before setting this enumerator.

        + */ + AgoraRoomAcousticsVocalConcert = 0x02010200, + /** An audio effect typical of a recording studio. +

        **Note**

        +

        To achieve better audio effect quality, Agora recommends calling [setAudioProfile]([AgoraRtcEngineKit setAudioProfile:scenario:]) + and setting the `profile` parameter to `AgoraAudioProfileMusicHighQuality(4)` or `AgoraAudioProfileMusicHighQualityStereo(5)` + before setting this enumerator.

        + */ + AgoraRoomAcousticsStudio = 0x02010300, + /** An audio effect typical of a vintage phonograph. +

        **Note**

        +

        To achieve better audio effect quality, Agora recommends calling [setAudioProfile]([AgoraRtcEngineKit setAudioProfile:scenario:]) + and setting the `profile` parameter to `AgoraAudioProfileMusicHighQuality(4)` or `AgoraAudioProfileMusicHighQualityStereo(5)` + before setting this enumerator.

        + */ + AgoraRoomAcousticsPhonograph = 0x02010400, + /** A virtual stereo effect that renders monophonic audio as stereo audio. +

        **Note**

        +

        Call [setAudioProfile]([AgoraRtcEngineKit setAudioProfile:scenario:]) and set the `profile` parameter to + `AgoraAudioProfileMusicStandardStereo(3)` or `AgoraAudioProfileMusicHighQualityStereo(5)` before setting this enumerator; + otherwise, the enumerator setting does not take effect.

        + */ + AgoraRoomAcousticsVirtualStereo = 0x02010500, + /** A more spatial audio effect. +

        **Note**

        +

        To achieve better audio effect quality, Agora recommends calling [setAudioProfile]([AgoraRtcEngineKit setAudioProfile:scenario:]) + and setting the `profile` parameter to `AgoraAudioProfileMusicHighQuality(4)` or `AgoraAudioProfileMusicHighQualityStereo(5)` + before setting this enumerator.

        + */ + AgoraRoomAcousticsSpacial = 0x02010600, + /** A more ethereal audio effect. +

        **Note**

        +

        To achieve better audio effect quality, Agora recommends calling [setAudioProfile]([AgoraRtcEngineKit setAudioProfile:scenario:]) + and setting the `profile` parameter to `AgoraAudioProfileMusicHighQuality(4)` or `AgoraAudioProfileMusicHighQualityStereo(5)` + before setting this enumerator.

        + */ + AgoraRoomAcousticsEthereal = 0x02010700, + /** A 3D voice effect that makes the voice appear to be moving around the user. The default cycle period of the 3D voice effect is + 10 seconds. To change the cycle period, call [setAudioEffectParameters]([AgoraRtcEngineKit setAudioEffectParameters:param1:param2:]) + after this method. +

        **Note**

        +
      44. Call [setAudioProfile]([AgoraRtcEngineKit setAudioProfile:scenario:]) and set the `profile` parameter to + `AgoraAudioProfileMusicStandardStereo(3)` or `AgoraAudioProfileMusicHighQualityStereo(5)` before setting this enumerator; + otherwise, the enumerator setting does not take effect.
      45. +
      46. If the 3D voice effect is enabled, users need to use stereo audio playback devices to hear the anticipated voice effect.
      47. + */ + AgoraRoomAcoustics3DVoice = 0x02010800, + /** The voice of a middle-aged man. +

        **Note**

        +
      48. Agora recommends using this enumerator to process a male-sounding voice; otherwise, you may not hear the anticipated voice + effect.
      49. +
      50. To achieve better audio effect quality, Agora recommends calling [setAudioProfile]([AgoraRtcEngineKit setAudioProfile:scenario:]) + and setting the `profile` parameter to `AgoraAudioProfileMusicHighQuality(4)` or `AgoraAudioProfileMusicHighQualityStereo(5)` + before setting this enumerator.
      51. + */ + AgoraVoiceChangerEffectUncle = 0x02020100, + /** The voice of an old man. +

        **Note**

        +
      52. Agora recommends using this enumerator to process a male-sounding voice; otherwise, you may not hear the anticipated voice + effect.
      53. +
      54. To achieve better audio effect quality, Agora recommends calling [setAudioProfile]([AgoraRtcEngineKit setAudioProfile:scenario:]) + and setting the `profile` parameter to `AgoraAudioProfileMusicHighQuality(4)` or `AgoraAudioProfileMusicHighQualityStereo(5)` + before setting this enumerator.
      55. + */ + AgoraVoiceChangerEffectOldMan = 0x02020200, + /** The voice of a boy. +

        **Note**

        +
      56. Agora recommends using this enumerator to process a male-sounding voice; otherwise, you may not hear the anticipated voice + effect.
      57. +
      58. To achieve better audio effect quality, Agora recommends calling [setAudioProfile]([AgoraRtcEngineKit setAudioProfile:scenario:]) + and setting the `profile` parameter to `AgoraAudioProfileMusicHighQuality(4)` or `AgoraAudioProfileMusicHighQualityStereo(5)` + before setting this enumerator.
      59. + */ + AgoraVoiceChangerEffectBoy = 0x02020300, + /** The voice of a young woman. +

        **Note**

        +
      60. Agora recommends using this enumerator to process a female-sounding voice; otherwise, you may not hear the anticipated voice + effect.
      61. +
      62. To achieve better audio effect quality, Agora recommends calling [setAudioProfile]([AgoraRtcEngineKit setAudioProfile:scenario:]) + and setting the `profile` parameter to `AgoraAudioProfileMusicHighQuality(4)` or `AgoraAudioProfileMusicHighQualityStereo(5)` + before setting this enumerator.
      63. + */ + AgoraVoiceChangerEffectSister = 0x02020400, + /** The voice of a girl. +

        **Note**

        +
      64. Agora recommends using this enumerator to process a female-sounding voice; otherwise, you may not hear the anticipated voice + effect.
      65. +
      66. To achieve better audio effect quality, Agora recommends calling [setAudioProfile]([AgoraRtcEngineKit setAudioProfile:scenario:]) + and setting the `profile` parameter to `AgoraAudioProfileMusicHighQuality(4)` or `AgoraAudioProfileMusicHighQualityStereo(5)` + before setting this enumerator.
      67. + */ + AgoraVoiceChangerEffectGirl = 0x02020500, + /** The voice of Pig King, a character in Journey to the West who has a voice like a growling bear. +

        **Note**

        +

        To achieve better audio effect quality, Agora recommends calling [setAudioProfile]([AgoraRtcEngineKit setAudioProfile:scenario:]) + and setting the `profile` parameter to `AgoraAudioProfileMusicHighQuality(4)` or `AgoraAudioProfileMusicHighQualityStereo(5)` + before setting this enumerator.

        + */ + AgoraVoiceChangerEffectPigKing = 0x02020600, + /** The voice of Hulk. +

        **Note**

        +

        To achieve better audio effect quality, Agora recommends calling [setAudioProfile]([AgoraRtcEngineKit setAudioProfile:scenario:]) + and setting the `profile` parameter to `AgoraAudioProfileMusicHighQuality(4)` or `AgoraAudioProfileMusicHighQualityStereo(5)` + before setting this enumerator.

        + */ + AgoraVoiceChangerEffectHulk = 0x02020700, + /** An audio effect typical of R&B music. +

        **Note**

        +

        Call [setAudioProfile]([AgoraRtcEngineKit setAudioProfile:scenario:]) and set the `profile` parameter to + `AgoraAudioProfileMusicHighQuality(4)` or `AgoraAudioProfileMusicHighQualityStereo(5)` before setting this enumerator; + otherwise, the enumerator setting does not take effect.

        + */ + AgoraStyleTransformationRnB = 0x02030100, + /** An audio effect typical of popular music. +

        **Note**

        +

        Call [setAudioProfile]([AgoraRtcEngineKit setAudioProfile:scenario:]) and set the `profile` parameter to + `AgoraAudioProfileMusicHighQuality(4)` or `AgoraAudioProfileMusicHighQualityStereo(5)` before setting this enumerator; + otherwise, the enumerator setting does not take effect.

        + */ + AgoraStyleTransformationPopular = 0x02030200, + /** A pitch correction effect that corrects the user's pitch based on the pitch of the natural C major scale. To change the basic + mode and tonic pitch, call [setAudioEffectParameters]([AgoraRtcEngineKit setAudioEffectParameters:param1:param2:]) after this method. +

        **Note**

        +

        To achieve better audio effect quality, Agora recommends calling [setAudioProfile]([AgoraRtcEngineKit setAudioProfile:scenario:]) + and setting the `profile` parameter to `AgoraAudioProfileMusicHighQuality(4)` or `AgoraAudioProfileMusicHighQualityStereo(5)` + before setting this enumerator.

        + */ + AgoraPitchCorrection = 0x02040100 +}; + +/** The options for SDK preset voice conversion effects. + + @since v3.3.1 + */ +typedef NS_ENUM(NSInteger, AgoraVoiceConversionPreset) { + /** Turn off voice conversion effects and use the original voice. */ + AgoraVoiceConversionOff = 0x00000000, + /** A gender-neutral voice. To avoid audio distortion, ensure that you use this enumerator to process a female-sounding voice. */ + AgoraVoiceChangerNeutral = 0x03010100, + /** A sweet voice. To avoid audio distortion, ensure that you use this enumerator to process a female-sounding voice. */ + AgoraVoiceChangerSweet = 0x03010200, + /** A steady voice. To avoid audio distortion, ensure that you use this enumerator to process a male-sounding voice. */ + AgoraVoiceChangerSolid = 0x03010300, + /** A deep voice. To avoid audio distortion, ensure that you use this enumerator to process a male-sounding voice. */ + AgoraVoiceChangerBass = 0x03010400 +}; + +/** The operational permission of the SDK on the audio session. */ +typedef NS_OPTIONS(NSUInteger, AgoraAudioSessionOperationRestriction) { + /** No restriction; the SDK can change the audio session. */ + AgoraAudioSessionOperationRestrictionNone = 0, + /** The SDK cannot change the audio session category. */ + AgoraAudioSessionOperationRestrictionSetCategory = 1, + /** The SDK cannot change the audio session category, mode, or categoryOptions. */ + AgoraAudioSessionOperationRestrictionConfigureSession = 1 << 1, + /** The SDK keeps the audio session active when the user leaves the channel, for example, to play an audio file in the background. */ + AgoraAudioSessionOperationRestrictionDeactivateSession = 1 << 2, + /** Completely restricts the operational permission of the SDK on the audio session; the SDK cannot change the audio session. */ + AgoraAudioSessionOperationRestrictionAll = 1 << 7 +}; + +/** Audio codec profile. */ +typedef NS_ENUM(NSInteger, AgoraAudioCodecProfileType) { + /** (Default) LC-AAC, the low-complexity audio codec profile. */ + AgoraAudioCodecProfileLCAAC = 0, + /** HE-AAC, the high-efficiency audio codec profile. */ + AgoraAudioCodecProfileHEAAC = 1 +}; + +/** The state of the remote audio. */ +typedef NS_ENUM(NSUInteger, AgoraAudioRemoteState) { + /** 0: The remote audio is in the default state, probably due to `AgoraAudioRemoteReasonLocalMuted(3)`, `AgoraAudioRemoteReasonRemoteMuted(5)`, or `AgoraAudioRemoteReasonRemoteOffline(7)`. */ + AgoraAudioRemoteStateStopped = 0, + /** 1: The first remote audio packet is received. */ + AgoraAudioRemoteStateStarting = 1, + /** 2: The remote audio stream is decoded and plays normally, probably due to `AgoraAudioRemoteReasonNetworkRecovery(2)`, `AgoraAudioRemoteReasonLocalUnmuted(4)`, or `AgoraAudioRemoteReasonRemoteUnmuted(6)`. */ + AgoraAudioRemoteStateDecoding = 2, + /** 3: The remote audio is frozen, probably due to `AgoraAudioRemoteReasonNetworkCongestion(1)`. */ + AgoraAudioRemoteStateFrozen = 3, + /** 4: The remote audio fails to start, probably due to `AgoraAudioRemoteReasonInternal(0)`. */ + AgoraAudioRemoteStateFailed = 4, +}; + +/** The reason of the remote audio state change. */ +typedef NS_ENUM(NSUInteger, AgoraAudioRemoteStateReason) { + /** 0: The SDK reports this reason when the audio state changes. */ + AgoraAudioRemoteReasonInternal = 0, + /** 1: Network congestion. */ + AgoraAudioRemoteReasonNetworkCongestion = 1, + /** 2: Network recovery. */ + AgoraAudioRemoteReasonNetworkRecovery = 2, + /** 3: The local user stops receiving the remote audio stream or disables the audio module. */ + AgoraAudioRemoteReasonLocalMuted = 3, + /** 4: The local user resumes receiving the remote audio stream or enables the audio module. */ + AgoraAudioRemoteReasonLocalUnmuted = 4, + /** 5: The remote user stops sending the audio stream or disables the audio module. */ + AgoraAudioRemoteReasonRemoteMuted = 5, + /** 6: The remote user resumes sending the audio stream or enables the audio module. */ + AgoraAudioRemoteReasonRemoteUnmuted = 6, + /** 7: The remote user leaves the channel. */ + AgoraAudioRemoteReasonRemoteOffline = 7, +}; + +/** The state of the local audio. */ +typedef NS_ENUM(NSUInteger, AgoraAudioLocalState) { + /** 0: The local audio is in the initial state. */ + AgoraAudioLocalStateStopped = 0, + /** 1: The audio sampling device starts successfully. */ + AgoraAudioLocalStateRecording = 1, + /** 2: The first audio frame encodes successfully. */ + AgoraAudioLocalStateEncoding = 2, + /** 3: The local audio fails to start. */ + AgoraAudioLocalStateFailed = 3, +}; + +/** The error information of the local audio. */ +typedef NS_ENUM(NSUInteger, AgoraAudioLocalError) { + /** 0: The local audio is normal. */ + AgoraAudioLocalErrorOk = 0, + /** 1: No specified reason for the local audio failure. */ + AgoraAudioLocalErrorFailure = 1, + /** 2: No permission to use the local audio sampling device. */ + AgoraAudioLocalErrorDeviceNoPermission = 2, + /** 3: The audio sampling device is in use. */ + AgoraAudioLocalErrorDeviceBusy = 3, + /** 4: The local audio sampling fails. Check whether the sampling device is working properly. */ + AgoraAudioLocalErrorRecordFailure = 4, + /** 5: The local audio encoding fails. */ + AgoraAudioLocalErrorEncodeFailure = 5, +}; + +/** The information acquisition state. This enum is reported in + [didRequestAudioFileInfo]([AgoraRtcEngineDelegate rtcEngine:didRequestAudioFileInfo:error:]). + + @since v3.5.1 + */ +typedef NS_ENUM(NSUInteger, AgoraAudioFileInfoError) { + /** 0: Successfully get the information of an audio file. */ + AgoraAudioFileInfoErrorOk = 0, + /** 1: Fail to get the information of an audio file. */ + AgoraAudioFileInfoErrorFailure = 1 +}; + +/** Media device type. */ +typedef NS_ENUM(NSInteger, AgoraMediaDeviceType) { + /** Unknown device. */ + AgoraMediaDeviceTypeAudioUnknown = -1, + /** Audio playback device. */ + AgoraMediaDeviceTypeAudioPlayout = 0, + /** Audio sampling device. */ + AgoraMediaDeviceTypeAudioRecording = 1, + /** Video render device. */ + AgoraMediaDeviceTypeVideoRender = 2, + /** Video capture device. */ + AgoraMediaDeviceTypeVideoCapture = 3, +}; + +/** Connection states. */ +typedef NS_ENUM(NSInteger, AgoraConnectionStateType) { + /**

        1: The SDK is disconnected from Agora's edge server.

        +
      68. This is the initial state before [joinChannelByToken]([AgoraRtcEngineKit joinChannelByToken:channelId:info:uid:joinSuccess:]). +
      69. The SDK also enters this state when the app calls [leaveChannel]([AgoraRtcEngineKit leaveChannel:]). + */ + AgoraConnectionStateDisconnected = 1, + /**

        2: The SDK is connecting to Agora's edge server. +

        When the app calls [joinChannelByToken]([AgoraRtcEngineKit joinChannelByToken:channelId:info:uid:joinSuccess:]), the SDK starts to establish a connection to the specified channel, triggers the [connectionChangedToState]([AgoraRtcEngineDelegate rtcEngine:connectionChangedToState:reason:]) callback, and switches to the `AgoraConnectionStateConnecting` state. +

        When the SDK successfully joins the channel, the SDK triggers the [connectionChangedToState]([AgoraRtcEngineDelegate rtcEngine:connectionChangedToState:reason:]) callback and switches to the `AgoraConnectionStateConnected` state. +

        After the SDK joins the channel and when it finishes initializing the media engine, the SDK triggers the [didJoinChannel]([AgoraRtcEngineDelegate rtcEngine:didJoinChannel:withUid:elapsed:]) callback. +*/ + AgoraConnectionStateConnecting = 2, + /**

        3: The SDK is connected to Agora's edge server and joins a channel. You can now publish or subscribe to a media stream in the channel.

        +If the connection to the channel is lost because, for example, the network is down or switched, the SDK automatically tries to reconnect and triggers: +
      70. The [rtcEngineConnectionDidInterrupted]([AgoraRtcEngineDelegate rtcEngineConnectionDidInterrupted:])(deprecated) callback +
      71. The [connectionChangedToState]([AgoraRtcEngineDelegate rtcEngine:connectionChangedToState:reason:]) callback, and switches to the `AgoraConnectionStateReconnecting` state. + */ + AgoraConnectionStateConnected = 3, + /**

        4: The SDK keeps rejoining the channel after being disconnected from a joined channel because of network issues.

        +
      72. If the SDK cannot rejoin the channel within 10 seconds after being disconnected from Agora's edge server, the SDK triggers the [rtcEngineConnectionDidLost]([AgoraRtcEngineDelegate rtcEngineConnectionDidLost:]) callback, stays in the `AgoraConnectionStateReconnecting` state, and keeps rejoining the channel. +
      73. If the SDK fails to rejoin the channel 20 minutes after being disconnected from Agora's edge server, the SDK triggers the [connectionChangedToState]([AgoraRtcEngineDelegate rtcEngine:connectionChangedToState:reason:]) callback, switches to the `AgoraConnectionStateFailed` state, and stops rejoining the channel. + */ + AgoraConnectionStateReconnecting = 4, + /**

        5: The SDK fails to connect to Agora's edge server or join the channel.

        +
      74. You must call [leaveChannel]([AgoraRtcEngineKit leaveChannel:]) to leave this state, and call [joinChannelByToken]([AgoraRtcEngineKit joinChannelByToken:channelId:info:uid:joinSuccess:]) again to rejoin the channel. +
      75. If the SDK is banned from joining the channel by Agora's edge server (through the RESTful API), the SDK triggers the [rtcEngineConnectionDidBanned]([AgoraRtcEngineDelegate rtcEngineConnectionDidBanned:])(deprecated) and [connectionChangedToState]([AgoraRtcEngineDelegate rtcEngine:connectionChangedToState:reason:]) callbacks. + */ + AgoraConnectionStateFailed = 5, +}; + +/** Reasons for the connection state change. */ +typedef NS_ENUM(NSUInteger, AgoraConnectionChangedReason) { + /** 0: The SDK is connecting to Agora's edge server. */ + AgoraConnectionChangedConnecting = 0, + /** 1: The SDK has joined the channel successfully. */ + AgoraConnectionChangedJoinSuccess = 1, + /** 2: The connection between the SDK and Agora's edge server is interrupted. */ + AgoraConnectionChangedInterrupted = 2, + /** 3: The user is banned by the server. This error occurs when the user is kicked out the channel from the server. */ + AgoraConnectionChangedBannedByServer = 3, + /** 4: The SDK fails to join the channel for more than 20 minutes and stops reconnecting to the channel. */ + AgoraConnectionChangedJoinFailed = 4, + /** 5: The SDK has left the channel. */ + AgoraConnectionChangedLeaveChannel = 5, + /** 6: The specified App ID is invalid. Try to rejoin the channel with a valid App ID. */ + AgoraConnectionChangedInvalidAppId = 6, + /** 7: The specified channel name is invalid. Try to rejoin the channel with a valid channel name. */ + AgoraConnectionChangedInvalidChannelName = 7, + /** 8: The generated token is invalid probably due to the following reasons: +
      76. The App Certificate for the project is enabled in Console, but you do not use Token when joining the channel. If you enable the App Certificate, you must use a token to join the channel. +
      77. The uid that you specify in the [joinChannelByToken]([AgoraRtcEngineKit joinChannelByToken:channelId:info:uid:joinSuccess:]) method is different from the uid that you pass for generating the token. + */ + AgoraConnectionChangedInvalidToken = 8, + /** 9: The token has expired. Generate a new token from your server. */ + AgoraConnectionChangedTokenExpired = 9, + /** 10: The user is banned by the server. This error usually occurs in the following situations: +
      78. When the user is already in the channel, and still calls the method to join the channel, for example, [joinChannelByToken]([AgoraRtcEngineKit joinChannelByToken:channelId:info:uid:joinSuccess:]).
      79. +
      80. When the user tries to join a channel during a call test ([startEchoTestWithInterval]([AgoraRtcEngineKit startEchoTestWithInterval:successBlock:])). Once you call `startEchoTest`, you need to call [stopEchoTest]([AgoraRtcEngineKit stopEchoTest]) before joining a channel.
      81. + */ + AgoraConnectionChangedRejectedByServer = 10, + /** 11: The SDK tries to reconnect after setting a proxy server. */ + AgoraConnectionChangedSettingProxyServer = 11, + /** 12: The token renews. */ + AgoraConnectionChangedRenewToken = 12, + /** 13: The client IP address has changed, probably due to a change of the network type, IP address, or network port. */ + AgoraConnectionChangedClientIpAddressChanged = 13, + /** 14: Timeout for the keep-alive of the connection between the SDK and Agora's edge server. The connection state changes to `AgoraConnectionStateReconnecting(4)`. */ + AgoraConnectionChangedKeepAliveTimeout = 14, + /** 15: */ + AgoraConnectionChangedProxyServerInterrupted = 15, +}; + +/** The state code in AgoraChannelMediaRelayState. + */ +typedef NS_ENUM(NSInteger, AgoraChannelMediaRelayState) { + /** 0: The initial state. After you successfully stop the channel media relay by calling + [stopChannelMediaRelay]([AgoraRtcEngineKit stopChannelMediaRelay]), the + [channelMediaRelayStateDidChange]([AgoraRtcEngineDelegate rtcEngine:channelMediaRelayStateDidChange:error:]) callback + returns this state. + */ + AgoraChannelMediaRelayStateIdle = 0, + /** 1: The SDK tries to relay the media stream to the destination channel. + */ + AgoraChannelMediaRelayStateConnecting = 1, + /** 2: The SDK successfully relays the media stream to the destination channel. + */ + AgoraChannelMediaRelayStateRunning = 2, + /** 3: A failure occurs. See the details in `error`. + */ + AgoraChannelMediaRelayStateFailure = 3, +}; + +/** The event code in AgoraChannelMediaRelayEvent. + */ +typedef NS_ENUM(NSInteger, AgoraChannelMediaRelayEvent) { + /** 0: The user disconnects from the server due to poor network connections. + */ + AgoraChannelMediaRelayEventDisconnect = 0, + /** 1: The network reconnects. + */ + AgoraChannelMediaRelayEventConnected = 1, + /** 2: The user joins the source channel. + */ + AgoraChannelMediaRelayEventJoinedSourceChannel = 2, + /** 3: The user joins the destination channel. + */ + AgoraChannelMediaRelayEventJoinedDestinationChannel = 3, + /** 4: The SDK starts relaying the media stream to the destination channel. + */ + AgoraChannelMediaRelayEventSentToDestinationChannel = 4, + /** 5: The server receives the video stream from the source channel. + */ + AgoraChannelMediaRelayEventReceivedVideoPacketFromSource = 5, + /** 6: The server receives the audio stream from the source channel. + */ + AgoraChannelMediaRelayEventReceivedAudioPacketFromSource = 6, + /** 7: The destination channel is updated. + */ + AgoraChannelMediaRelayEventUpdateDestinationChannel = 7, + /** 8: The destination channel update fails due to internal reasons. + */ + AgoraChannelMediaRelayEventUpdateDestinationChannelRefused = 8, + /** 9: The destination channel does not change, which means that the destination channel fails to be updated. + */ + AgoraChannelMediaRelayEventUpdateDestinationChannelNotChange = 9, + /** 10: The destination channel name is `nil`. + */ + AgoraChannelMediaRelayEventUpdateDestinationChannelIsNil = 10, + /** 11: The video profile is sent to the server. + */ + AgoraChannelMediaRelayEventVideoProfileUpdate = 11, + /** 12: The SDK successfully pauses relaying the media stream to destination channels. + + @since v3.5.1 + */ + AgoraChannelMediaRelayEventPauseSendPacketToDestChannelSuccess = 12, + /** 13: The SDK fails to pause relaying the media stream to destination channels. + + @since v3.5.1 + */ + AgoraChannelMediaRelayEventPauseSendPacketToDestChannelFailed = 13, + /** 14: The SDK successfully resumes relaying the media stream to destination channels. + + @since v3.5.1 + */ + AgoraChannelMediaRelayEventResumeSendPacketToDestChannelSuccess = 14, + /** 15: The SDK fails to resume relaying the media stream to destination channels. + + @since v3.5.1 + */ + AgoraChannelMediaRelayEventResumeSendPacketToDestChannelFailed = 15, + +}; + +/** The error code in AgoraChannelMediaRelayError. + */ +typedef NS_ENUM(NSInteger, AgoraChannelMediaRelayError) { + /** 0: The state is normal. + */ + AgoraChannelMediaRelayErrorNone = 0, + /** 1: An error occurs in the server response. + */ + AgoraChannelMediaRelayErrorServerErrorResponse = 1, + /** 2: No server response. This error can also occur if your project has not enabled co-host token authentication. Contact support@agora.io to enable the co-host token authentication service before starting a channel media relay. + */ + AgoraChannelMediaRelayErrorServerNoResponse = 2, + /** 3: The SDK fails to access the service, probably due to limited resources of the server. + */ + AgoraChannelMediaRelayErrorNoResourceAvailable = 3, + /** 4: Fails to send the relay request. + */ + AgoraChannelMediaRelayErrorFailedJoinSourceChannel = 4, + /** 5: Fails to accept the relay request. + */ + AgoraChannelMediaRelayErrorFailedJoinDestinationChannel = 5, + /** 6: The server fails to receive the media stream. + */ + AgoraChannelMediaRelayErrorFailedPacketReceivedFromSource = 6, + /** 7: The server fails to send the media stream. + */ + AgoraChannelMediaRelayErrorFailedPacketSentToDestination = 7, + /** 8: The SDK disconnects from the server due to poor network connections. You can call the [leaveChannel]([AgoraRtcEngineKit leaveChannel:]) method to leave the channel. + */ + AgoraChannelMediaRelayErrorServerConnectionLost = 8, + /** 9: An internal error occurs in the server. + */ + AgoraChannelMediaRelayErrorInternalError = 9, + /** 10: The token of the source channel has expired. + */ + AgoraChannelMediaRelayErrorSourceTokenExpired = 10, + /** 11: The token of the destination channel has expired. + */ + AgoraChannelMediaRelayErrorDestinationTokenExpired = 11, +}; + +/** Network type. */ +typedef NS_ENUM(NSInteger, AgoraNetworkType) { + /** -1: The network type is unknown. */ + AgoraNetworkTypeUnknown = -1, + /** 0: The SDK disconnects from the network. */ + AgoraNetworkTypeDisconnected = 0, + /** 1: The network type is LAN. */ + AgoraNetworkTypeLAN = 1, + /** 2: The network type is Wi-Fi (including hotspots). */ + AgoraNetworkTypeWIFI = 2, + /** 3: The network type is mobile 2G. */ + AgoraNetworkTypeMobile2G = 3, + /** 4: The network type is mobile 3G. */ + AgoraNetworkTypeMobile3G = 4, + /** 5: The network type is mobile 4G. */ + AgoraNetworkTypeMobile4G = 5, + /** 6: The network type is mobile 5G. + + @since v3.5.1 + */ + AgoraNetworkTypeMobile5G = 6, +}; + +/** The video encoding degradation preference under limited bandwidth. */ +typedef NS_ENUM(NSInteger, AgoraDegradationPreference) { + /** (Default) Prefers to reduce the video frame rate while maintaining video quality during video encoding under + limited bandwidth. This degradation preference is suitable for scenarios where video quality is prioritized. + + @note In the `Communication` channel profile, the resolution of the video sent may change, so remote users need to + handle this issue. See [videoSizeChangedOfUid]([AgoraRtcEngineDelegate rtcEngine:videoSizeChangedOfUid:size:rotation:]). + */ + AgoraDegradationMaintainQuality = 0, + /** Prefers to reduce the video quality while maintaining the video frame rate during video encoding under limited + bandwidth. This degradation preference is suitable for scenarios where smoothness is prioritized and video quality + is allowed to be reduced. + */ + AgoraDegradationMaintainFramerate = 1, + /** Reduces the video frame rate and video quality simultaneously during video encoding under limited bandwidth. + `AgoraDegradationBalanced` has a lower reduction than `AgoraDegradationMaintainQuality` and `AgoraDegradationMaintainFramerate`, + and this preference is suitable for scenarios where both smoothness and video quality are a priority. + + @note The resolution of the video sent may change, so remote users need to handle this issue. See [videoSizeChangedOfUid]([AgoraRtcEngineDelegate rtcEngine:videoSizeChangedOfUid:size:rotation:]). + */ + AgoraDegradationBalanced = 2, +}; +/** The lightening contrast level. */ +typedef NS_ENUM(NSUInteger, AgoraLighteningContrastLevel) { + /** Low contrast level. */ + AgoraLighteningContrastLow = 0, + /** (Default) Normal contrast level. */ + AgoraLighteningContrastNormal = 1, + /** High contrast level. */ + AgoraLighteningContrastHigh = 2, +}; + +/** The type of the custom background image. + @since v3.4.5 + */ +typedef NS_ENUM(NSUInteger, AgoraVirtualBackgroundSourceType) { + /** 1: (Default) The background image is a solid color.*/ + AgoraVirtualBackgroundColor = 1, + /** 2: The background image is a file in PNG or JPG format.*/ + AgoraVirtualBackgroundImg = 2, + /** 3: The background image is blurred. + + @since v3.5.1 + */ + AgoraVirtualBackgroundBlur = 3, +}; + +/** The degree of blurring applied to the custom background image. + @since v3.5.1 + */ +typedef NS_ENUM(NSUInteger, AgoraBlurDegree) { + /** 1: The degree of blurring applied to the custom background image is low. + The user can almost see the background clearly. + */ + AgoraBlurLow = 1, + /** 2: The degree of blurring applied to the custom background image is + medium. It is difficult for the user to recognize details in the background. + */ + AgoraBlurMedium = 2, + /** 3: (Default) The degree of blurring applied to the custom background + image is high. The user can barely see any distinguishing features in the + background. + */ + AgoraBlurHigh = 3, +}; + +/** The state of the probe test result. */ +typedef NS_ENUM(NSUInteger, AgoraLastmileProbeResultState) { + /** 1: The last-mile network probe test is complete. */ + AgoraLastmileProbeResultComplete = 1, + /** 2: The last-mile network probe test is incomplete and the bandwidth estimation is not available, probably due to limited test resources. */ + AgoraLastmileProbeResultIncompleteNoBwe = 2, + /** 3: The last-mile network probe test is not carried out, probably due to poor network conditions. */ + AgoraLastmileProbeResultUnavailable = 3, +}; + +/** The state of the local video stream. */ +typedef NS_ENUM(NSInteger, AgoraLocalVideoStreamState) { + /** 0: The local video is in the initial state. */ + AgoraLocalVideoStreamStateStopped = 0, + /** 1: The local video capturing device starts successfully. The SDK also reports this state when you share a maximized window by calling [startScreenCaptureByWindowId]([AgoraRtcEngineKit startScreenCaptureByWindowId:rectangle:parameters:]). + + @since v3.1.0 + */ + AgoraLocalVideoStreamStateCapturing = 1, + /** 2: The first local video frame encodes successfully. */ + AgoraLocalVideoStreamStateEncoding = 2, + /** 3: The local video fails to start. */ + AgoraLocalVideoStreamStateFailed = 3, +}; + +/** The detailed error information of the local video. */ +typedef NS_ENUM(NSInteger, AgoraLocalVideoStreamError) { + /** 0: The local video is normal. */ + AgoraLocalVideoStreamErrorOK = 0, + /** 1: No specified reason for the local video failure. */ + AgoraLocalVideoStreamErrorFailure = 1, + /** 2: No permission to use the local video device. */ + AgoraLocalVideoStreamErrorDeviceNoPermission = 2, + /** 3: The local video capturer is in use. */ + AgoraLocalVideoStreamErrorDeviceBusy = 3, + /** 4: The local video capture fails. Check whether the capturer is working properly. */ + AgoraLocalVideoStreamErrorCaptureFailure = 4, + /** 5: The local video encoding fails. */ + AgoraLocalVideoStreamErrorEncodeFailure = 5, + /** 6: (iOS only) The application is in the background. + + @since v3.3.0 + */ + AgoraLocalVideoStreamErrorCaptureInBackGround = 6, + /** 7: (iOS only) The application is running in Slide Over, Split View, or Picture in Picture mode. + + @since v3.3.0 + */ + AgoraLocalVideoStreamErrorCaptureMultipleForegroundApps = 7, + /** 8: The SDK cannot find the local video capture device. + + @since v3.4.0 + */ + AgoraLocalVideoStreamErrorCaptureNoDeviceFound = 8, + /** 9: (macOS only) The external camera currently in use is disconnected + (such as being unplugged). + + @since v3.5.0 + */ + AgoraLocalVideoStreamErrorCaptureDeviceDisconnected = 9, + /** 10: (macOS only) The SDK cannot find the video device in the video device list. Check whether the ID of the video device is valid. + + @since v3.5.0 + */ + AgoraLocalVideoStreamErrorCaptureDeviceInvalidId = 10, + /** 11: (macOS only) The shared window is minimized when you call + [startScreenCaptureByWindowId]([AgoraRtcEngineKit startScreenCaptureByWindowId:rectangle:parameters:]) to share a window. + + @since v3.1.0 + */ + AgoraLocalVideoStreamErrorScreenCaptureWindowMinimized = 11, + /** 12: (macOS only) The error code indicates that a window shared by the window ID has been closed, or a full-screen + window shared by the window ID has exited full-screen mode. After exiting + full-screen mode, remote users cannot see the shared window. To prevent remote users from seeing a black screen, Agora recommends + that you immediately stop screen sharing. +

        Common scenarios for reporting this error code:

        +
      82. When the local user closes the shared window, the SDK reports this error code.
      83. t +
      84. The local user shows some slides in full-screen mode first, and then shares the windows of the slides. After the user exits full-screen + mode, the SDK reports this error code.
      85. +
      86. The local user watches web video or reads web document in full-screen mode first, and then shares the window of the web video or + document. After the user exits full-screen mode, the SDK reports this error code.
      87. + + @since v3.2.0 + */ + AgoraLocalVideoStreamErrorScreenCaptureWindowClosed = 12, +}; +/** Regions for connection + */ +typedef NS_ENUM(NSUInteger, AgoraAreaCode) { + /** Mainland China + */ + AgoraAreaCodeCN = 0x00000001, + /** North America + */ + AgoraAreaCodeNA = 0x00000002, + /** Europe + */ + AgoraAreaCodeEU = 0x00000004, + /** Asia, excluding Mainland China + */ + AgoraAreaCodeAS = 0x00000008, + /** Japan + */ + AgoraAreaCodeJP = 0x00000010, + /** India + */ + AgoraAreaCodeIN = 0x00000020, + /** (Default) Global + */ + AgoraAreaCodeGLOB = 0xFFFFFFFF +}; + +/** The output log level of the SDK + */ +typedef NS_ENUM(NSInteger, AgoraLogLevel) { + /** Do not output any log. + */ + AgoraLogLevelNone = 0x0000, + /** (Default) Output logs of the `AgoraLogLevelFatal`, `AgoraLogLevelError`, + `AgoraLogLevelWarn` and `AgoraLogLevelInfo` level. We recommend setting + your log filter as this level. + */ + AgoraLogLevelInfo = 0x0001, + /** Output logs of the `AgoraLogLevelFatal`, `AgoraLogLevelError` and + `AgoraLogLevelWarn` level. + */ + AgoraLogLevelWarn = 0x0002, + /** Output logs of the `AgoraLogLevelFatal` and `AgoraLogLevelError` level. + */ + AgoraLogLevelError = 0x0004, + /** Output logs of the `AgoraLogLevelFatal` level. + */ + AgoraLogLevelFatal = 0x0008 +}; +/** The cloud proxy type. + */ +typedef NS_ENUM(NSUInteger, AgoraCloudProxyType) { + /** 0: Do not use the cloud proxy. + */ + AgoraNoneProxy = 0, + /** 1: The cloud proxy for the UDP protocol. + */ + AgoraUdpProxy = 1, + /** 2: Reserved parameter. + */ + AgoraTcpProxy = 2, +}; + +/** The channel mode. Set in + [setAudioMixingDualMonoMode]([AgoraRtcEngineKit setAudioMixingDualMonoMode:]). + + @since v3.5.1 + */ +typedef NS_ENUM(NSUInteger, AgoraAudioMixingDualMonoMode) { + /** 0: Original mode. + */ + AgoraAudioMixingDualMonoAuto, + /** 1: Left channel mode. This mode replaces the audio of the right channel + with the audio of the left channel, which means the user can only hear + the audio of the left channel. + */ + AgoraAudioMixingDualMonoL, + /** 2: Right channel mode. This mode replaces the audio of the left channel + with the audio of the right channel, which means the user can only hear the + audio of the right channel. + */ + AgoraAudioMixingDualMonoR, + /** 3: Mixed channel mode. This mode mixes the audio of the left channel and + the right channel, which means the user can hear the audio of the left + channel and the right channel at the same time. + */ + AgoraAudioMixingDualMonoMix +}; + +/** + The type of the shared target. + + @since v3.5.2 + */ +typedef NS_ENUM(NSInteger, AgoraScreenCaptureSourceType) { + /** -1: Unknown type. */ + AgoraScreenCaptureSourceTypeUnknown = -1, + /** 0: The shared target is a window. */ + AgoraScreenCaptureSourceTypeWindow = 0, + /** 1: The shared target is a screen of a particular monitor. */ + AgoraScreenCaptureSourceTypeScreen = 1, + /** 2: Reserved parameter. */ + AgoraScreenCaptureSourceTypeCustom = 2, +}; + +/** The clockwise rotation angle of the video frame. (iOS only) + + @since v3.4.5 + */ +typedef NS_ENUM(NSInteger, AgoraVideoRotation) { + /** 0: No rotation */ + AgoraVideoRotationNone = 0, + /** 1: 90 degrees */ + AgoraVideoRotation90 = 1, + /** 2: 180 degrees */ + AgoraVideoRotation180 = 2, + /** 3: 270 degrees */ + AgoraVideoRotation270 = 3, +}; + +/** The color video format. (iOS only) + + @since v3.4.5 + */ +typedef NS_ENUM(NSUInteger, AgoraVideoFrameType) { + /** 0: (Default) YUV 420 + */ + AgoraVideoFrameTypeYUV420 = 0, // YUV 420 format + /** 1: YUV422 + */ + AgoraVideoFrameTypeYUV422 = 1, // YUV 422 format + /** 2: RGBA + */ + AgoraVideoFrameTypeRGBA = 2, // RGBA format +}; + +/** The video frame type. (iOS only) + + @since v3.4.5 + */ +typedef NS_ENUM(NSUInteger, AgoraVideoEncodeType) { + /** 0: (Default) A black frame + */ + AgoraVideoEncodeTypeBlankFrame = 0, + /** 3: The keyframe + */ + AgoraVideoEncodeTypeKeyFrame = 3, + /** 4: The delta frame + */ + AgoraVideoEncodeTypeDetaFrame = 4, + /** 5: The B-frame + */ + AgoraVideoEncodeTypeBFrame = 5, + +}; + +/** The bit mask of the observation positions. (iOS only) + + @since v3.4.5 + */ +typedef NS_ENUM(NSUInteger, AgoraVideoFramePosition) { + /** (Default) The position to observe the video data captured by the local + camera, which corresponds to the + [onCaptureVideoFrame]([AgoraVideoDataFrameProtocol onCaptureVideoFrame:]) + callback. + */ + AgoraVideoFramePositionPostCapture = 1 << 0, + /** (Default) The position to observe the incoming remote video data, + which corresponds to the + [onRenderVideoFrame]([AgoraVideoDataFrameProtocol onRenderVideoFrame:forUid:]) or + [onRenderVideoFrameEx]([AgoraVideoDataFrameProtocol onRenderVideoFrameEx:forUid:inChannel:]) + callback. + */ + AgoraVideoFramePositionPreRenderer = 1 << 1, + /** The position to observe the local pre-encoded video data, which + corresponds to the + [onPreEncodeVideoFrame]([AgoraVideoDataFrameProtocol onPreEncodeVideoFrame:]) + callback. + */ + AgoraVideoFramePositionPreEncoder = 1 << 2, +}; + +/** The bit mask that controls the audio observation positions. (iOS only) + + @since v3.4.5 + */ +typedef NS_ENUM(NSUInteger, AgoraAudioFramePosition) { + /** The position for observing the playback audio of all remote users after + mixing, which enables the SDK to trigger the + [onPlaybackAudioFrame]([AgoraAudioDataFrameProtocol onPlaybackAudioFrame:]) + callback. + */ + AgoraAudioFramePositionPlayback = 1 << 0, + /** The position for observing the recorded audio of the local user, which + enables the SDK to trigger the + [onRecordAudioFrame]([AgoraAudioDataFrameProtocol onRecordAudioFrame:]) + callback. + */ + AgoraAudioFramePositionRecord = 1 << 1, + /** The position for observing the mixed audio of the local user and all + remote users, which enables the SDK to trigger the + [onMixedAudioFrame]([AgoraAudioDataFrameProtocol onMixedAudioFrame:]) + callback. + */ + AgoraAudioFramePositionMixed = 1 << 2, + /** The position for observing the audio of a single remote user before + mixing, which enables the SDK to trigger the + [onPlaybackAudioFrameBeforeMixing]([AgoraAudioDataFrameProtocol onPlaybackAudioFrameBeforeMixing:uid:]) + callback. + S-54718: add mutiplechannel and beforeMixingEx for audioDataFrameProtocol) + */ + AgoraAudioFramePositionBeforeMixing = 1 << 3, +}; + +/** API for future use. + */ +typedef NS_ENUM(NSInteger, AgoraContentInspectType) { + AgoraContentInspectTypeInvalid = 0, + AgoraContentInspectTypeModeration = 1, + AgoraContentInspectTypeSupervise = 2, +}; + +/** The push position of the external audio frame. Set in + [pushExternalAudioFrameRawData]([AgoraRtcEngineKit pushExternalAudioFrameRawData:frame:]), + [pushExternalAudioFrameSampleBuffer]([AgoraRtcEngineKit pushExternalAudioFrameSampleBuffer:sampleBuffer:]), + or [setExternalAudioSourceVolume]([AgoraRtcEngineKit setExternalAudioSourceVolume:volume:]). + + @since v3.5.1 + */ +typedef NS_ENUM(NSUInteger, AgoraAudioExternalSourcePos) { + /** 0: The position before local playback. If you need to play the external + audio frame on the local client, set this position. + */ + AgoraAudioExternalPlayoutSource = 0, + /** 1: The position after audio capture and before audio pre-processing. + If you need the audio module of the SDK to process the external audio frame, + set this position. + */ + AgoraAudioExternalRecordSourcePreProcess = 1, + /** 2: The position after audio pre-processing and before audio encoding. + If you do not need the audio module of the SDK to process the external audio + frame, set this position. + */ + AgoraAudioExternalRecordSourcePostProcess = 2, +}; +/** API for future use. + */ +typedef NS_ENUM(NSUInteger, AgoraContentInspectResult) { + AgoraContentInspectNeutral = 1, + AgoraContentInspectSexy = 2, + AgoraContentInspectPorn = 3, +}; + +/** + The current recording state. + + @since v3.5.2 + */ +typedef NS_ENUM(NSInteger, AgoraMediaRecorderState) { + /** -1: An error occurs during the recording. See `error` for the reason. */ + AgoraMediaRecorderStateError = -1, + /** 2: The audio and video recording is started. */ + AgoraMediaRecorderStateStarted = 2, + /** 3: The audio and video recording is stopped. */ + AgoraMediaRecorderStateStopped = 3, +}; +/** + The reason for the state change. + + @since v3.5.2 + */ +typedef NS_ENUM(NSInteger, AgoraMediaRecorderErrorCode) { + /** 0: No error occurs. */ + AgoraMediaRecorderErrorCodeNoError = 0, + /** 1: The SDK fails to write the recorded data to a file. */ + AgoraMediaRecorderErrorCodeWriteFailed = 1, + /** 2: The SDK does not detect audio and video streams to be recorded, or audio and video streams are interrupted for more than five seconds during recording. */ + AgoraMediaRecorderErrorCodeNoStream = 2, + /** 3: The recording duration exceeds the upper limit. */ + AgoraMediaRecorderErrorCodeOverMaxDuration = 3, + /** 4: The recording configuration changes. */ + AgoraMediaRecorderErrorCodeConfigChange = 4, + /** 5: The SDK detects audio and video streams from users using versions of the SDK earlier than v3.0.0 in the `Communication` channel profile. */ + AgoraMediaRecorderErrorCustomStreamDetected = 5, +}; +/** + The recording content. + + @since v3.5.2 + */ +typedef NS_ENUM(NSInteger, AgoraMediaRecorderStreamType) { + /** 1: Only audio. */ + AgoraMediaRecorderStreamTypeAudio = 1, + /** 2: Only video. */ + AgoraMediaRecorderStreamTypeVideo = 2, + /** 3: (Default) Audio and video. */ + AgoraMediaRecorderStreamTypeBoth = 3, +}; +/** + The format of the recording file. + + @since v3.5.2 + */ +typedef NS_ENUM(NSInteger, AgoraMediaRecorderContainerFormat) { + /** 1: MP4 */ + AgoraMediaRecorderContainerFormatMP4 = 1, +}; diff --git a/integration_test_app/iris_integration_test/third_party/agora/rtc/include/AgoraLogWriter.h b/integration_test_app/iris_integration_test/third_party/agora/rtc/include/AgoraLogWriter.h new file mode 100644 index 000000000..a515cf0a6 --- /dev/null +++ b/integration_test_app/iris_integration_test/third_party/agora/rtc/include/AgoraLogWriter.h @@ -0,0 +1,33 @@ +// +// AgoraLogWriter.h +// AgoraRtcEngineKit +// +// Copyright © 2020 Agora. All rights reserved. +// + +#ifndef AgoraLogWriter_h +#define AgoraLogWriter_h + +/** The definition of AgoraLogWriterDelegate + +@note Implement the callback in this protocol in the critical thread. We recommend avoiding any time-consuming operation in the critical thread. +*/ +@protocol AgoraLogWriterDelegate +@required + +/** user defined log Write function + +@param message log message of agorasdk,encrypted by xxtea + +@param length length of message + +@return + - 0: success + + - <0: failure + */ +- (NSInteger)writeLog:(const NSData*)message Length:(unsigned short)length; + +@end + +#endif /* AgoraLogWriter_h */ diff --git a/integration_test_app/iris_integration_test/third_party/agora/rtc/include/AgoraMediaIO.h b/integration_test_app/iris_integration_test/third_party/agora/rtc/include/AgoraMediaIO.h new file mode 100644 index 000000000..4b7ba1bdd --- /dev/null +++ b/integration_test_app/iris_integration_test/third_party/agora/rtc/include/AgoraMediaIO.h @@ -0,0 +1,301 @@ +// +// AgoraMediaIO.h +// AgoraRtcEngineKit +// +// Copyright (c) 2018 Agora. All rights reserved. +// + +#import +#import +#import "AgoraEnumerates.h" +#import "AgoraObjects.h" + +/** Video pixel format. + + This enumeration defines the pixel format of the video frame. Agora supports three pixel formats on iOS: I420, BGRA, and NV12. For information on the YVU format, see: + + * [FourCC YUV Pixel Formats](http://www.fourcc.org/yuv.php) + * [Recommended 8-Bit YUV Formats for Video Rendering](https://docs.microsoft.com/zh-cn/windows/desktop/medfound/recommended-8-bit-yuv-formats-for-video-rendering) + */ +typedef NS_ENUM(NSUInteger, AgoraVideoPixelFormat) { + /** I420 */ + AgoraVideoPixelFormatI420 = 1, + /** BGRA */ + AgoraVideoPixelFormatBGRA = 2, + /** NV12 */ + AgoraVideoPixelFormatNV12 = 8, +}; + +/** Video buffer type */ +typedef NS_ENUM(NSInteger, AgoraVideoBufferType) { + /** Use a pixel buffer to transmit the video data. */ + AgoraVideoBufferTypePixelBuffer = 1, + /** Use raw data to transmit the video data. */ + AgoraVideoBufferTypeRawData = 2, +}; + +/** The capture type of the custom video source. */ +typedef NS_ENUM(NSInteger, AgoraVideoCaptureType) { + /** Unknown type. */ + AgoraVideoCaptureTypeUnknown = 0, + /** (Default) Video captured by the camera. */ + AgoraVideoCaptureTypeCamera = 1, + /** Video for screen sharing. */ + AgoraVideoCaptureTypeScreen = 2, +}; + +/** An object supporting video data in two formats; pixel buffer and raw data. + + When the video source is initialized, the media engine passes this object to you and you need to reserve it, and then pass the video frame to the media engine through this object once the video source is initialized. + Call [bufferType]([AgoraVideoSinkProtocol bufferType]) to specify a buffer type. The video data can only be transmitted in the corresponding type. + */ +@protocol AgoraVideoFrameConsumer + +/** Uses the video information in the pixel buffer. + + @param pixelBuffer Buffer type + @param timestamp Timestamp (ms) of the video frame. For each video frame, you need to set a timestamp. + @param rotation AgoraVideoRotation + */ +- (void)consumePixelBuffer:(CVPixelBufferRef _Nonnull)pixelBuffer withTimestamp:(CMTime)timestamp rotation:(AgoraVideoRotation)rotation; + +/** Uses the video information in the raw data. + + @param rawData Raw data of the video frame. + @param timestamp Timestamp (ms) of the video frame. + @param format AgoraVideoPixelFormat + @param size Size of the raw video data. + @param rotation AgoraVideoRotation + */ +- (void)consumeRawData:(void* _Nonnull)rawData withTimestamp:(CMTime)timestamp format:(AgoraVideoPixelFormat)format size:(CGSize)size rotation:(AgoraVideoRotation)rotation; +@end + +/** Defines a set of protocols to implement the custom video source and pass it to the underlying media engine to replace the default video source. + + `AgoraVideoSourceProtocol` allows you to take the ownership of the video source and manipulate it. + By default, when enabling real-time communications, the Agora SDK enables the default video input device (built-in camera) to start video streaming. + By calling [setVideoSource]([AgoraRtcEngineKit setVideoSource:]), you can change the default video input device, control it, and send the video source from the specified input device to the Agora Media Engine to handle the remaining video processes; such as video filtering and publishing the video to the RTC connection. + Once you have implemented this interface, the Agora Media Engine automatically releases the ownership of the current video input device and passes the ownership to you, so that you can use the same video input device to capture the video stream. + `AgoraVideoSourceProtocol` consists of the following methods: + + * Initializes the Video Source ([shouldInitialize](shouldInitialize)) + * Enables the Video Source ([shouldStart](shouldStart)) + * Disables the Video Source ([shouldStop](shouldStop)) + * Releases the Video Source ([shouldDispose](shouldDispose)) + * Gets the Buffer Type (AgoraVideoBufferType) + * Gets the capture type of the custom video source (AgoraVideoCaptureType) + * Gets the content hint of the custom video source (AgoraVideoContentHint) + + Note: + + * All methods in `AgoraVideoSourceProtocol` are callbacks. The media engine maintains a finite state machine and uses these methods at the right time. Do not use these methods directly in the app. + * These methods are synchronized. + * If the media engine restarts during the process, these methods can be repeated for a couple of times. + * These methods are not in the primary thread. + + When using the `AgoraVideoSourceProtocol`, call AgoraVideoBufferType, AgoraVideoPixelFormat, and AgoraVideoRotation to set the buffer type, pixel format, and rotation angle of the transmitted video. + */ +@protocol AgoraVideoSourceProtocol +@required +/** An AgoraVideoFrameConsumer object that the SDK passes to you. You need to reserve this object and use it to send the video frame to + the SDK once the custom video source is started. See [AgoraVideoFrameConsumer](AgoraVideoFrameConsumer). + + @note The SDK does not support the alpha channel, and discards any alpha value passed to the SDK. + */ +@property(strong) id _Nullable consumer; +/** Initializes the video source. + + The media engine calls this method to initialize the video source. You can also initialize the video source before this method is called and return YES to the media engine in this method. You need to pass YES or NO in this method to tell the media engine if the video source is initialized. + When the video source is initialized, the media engine initializes the AgoraVideoFrameConsumer pointer in AgoraVideoSourceProtocol, then the video source sends the video frame to the media engine through the AgoraVideoFrameConsumer method. + + @return * YES: If the external video source is initialized. + * NO: If the external video source is not ready or fails to initialize, the media engine stops and reports the error. + */ +- (BOOL)shouldInitialize; + +/** Enables the video source. + + Call this method when the media engine is ready to start video streaming. You should start the video source to capture the video frame. Once the frame is ready, use AgoraVideoFrameConsumer to consume the video frame. + Pass one of the following return values to the media engine: + + * YES: If the external video source is enabled and AgoraVideoFrameConsumer is called to receive video frames. + * NO: If the external video source is not ready or fails to enable, the media engine stops and reports the error. + + After YES is returned, video frames can be passed to the media engine through the preset AgoraVideoFrameConsumer interface method. + */ +- (void)shouldStart; + +/** Disables the video source. + + Call this method when the media engine stops streaming. You should then stop capturing the video frame and consuming it. After this method is called, the video frames are discarded by the media engine. + */ +- (void)shouldStop; + +/** Releases the video source. + +Call this method when AgoraVideoFrameConsumer is released by the media engine. You can now release the video source as well as AgoraVideoFrameConsumer. + */ +- (void)shouldDispose; + +/** Gets the buffer type. + + Passes the buffer type previously set in `AgoraVideoBufferType` to the media engine. This buffer type is used to set up the correct media engine environment. + + @return return AgoraVideoBufferType + */ +- (AgoraVideoBufferType)bufferType; + +/** Gets the capture type of the custom video source. + + @since v3.1.0 + + Before you initialize the custom video source, the SDK triggers this callback to query the capture type + of the video source. You must specify the capture type in the return value and then pass it to the SDK. + The SDK enables the corresponding video processing algorithm according to the capture type after + receiving the video frame. + + @return AgoraVideoCaptureType + */ +- (AgoraVideoCaptureType)captureType; + +/** Gets the content hint of the custom video source. + + @since v3.1.0 + + If you specify the custom video source as a screen-sharing video, the SDK triggers this callback to query + the content hint of the video source before you initialize the video source. You must specify the content + hint in the return value and then pass it to the SDK. The SDK enables the corresponding video processing + algorithm according to the content hint after receiving the video frame. + + @return AgoraVideoContentHint + */ +- (AgoraVideoContentHint)contentHint; +@end + +/** Defines a set of protocols to implement the custom video sink and pass it to the underlying media engine to replace the default video sink. + + AgoraVideoSinkProtocol allows you to implement the custom video source. + By default, when you try to enable real-time communications, the Agora SDK enables the default video sink to start video rendering. By calling [setLocalVideoRenderer]([AgoraRtcEngineKit setLocalVideoRenderer:]) and [setRemoteVideoRenderer]([AgoraRtcEngineKit setRemoteVideoRenderer:forUserId:]), you can change the default video sink. + Once you implement this interface, you receive callbacks from the media engine to indicate the state of the custom video sink, the underlying media engine, and enable their synchronization. Follow each callback to handle the resource allocation, and to release and receive the video frame from the media engine. + AgoraVideoSinkProtocol defines a set of protocols to create a customized video sink. The AgoraVideoFrameConsumer interface passes the video frames to the media engine, which then passes them to the renderer. + After a customized video sink is created, the app passes it to the media engine, see [setLocalVideoRenderer]([AgoraRtcEngineKit setLocalVideoRenderer:]) and [setRemoteVideoRenderer]([AgoraRtcEngineKit setRemoteVideoRenderer:forUserId:]). + AgoraVideoSinkProtocol consists of the following methods: + + * Initializes the Video Sink ([shouldInitialize](shouldInitialize)) + * Enables the Video Sink ([shouldStart](shouldStart)) + * Disables the Video Sink ([shouldStop](shouldStop)) + * Releases the Video Sink ([shouldDispose](shouldDispose)) + * Gets the Buffer Type ([bufferType](bufferType)) + * Gets the Pixel Format ([pixelFormat](pixelFormat)) + * (Optional) Outputs the Video in the Pixel Buffer ([renderPixelBuffer](renderPixelBuffer:rotation:)) + * (Optional) Outputs the Video in the Raw Data ([renderRawData](renderRawData:size:rotation:)) + + Note: All methods defined in AgoraVideoSinkProtocol are callbacks. The media engine uses these methods to inform the customized renderer of its internal changes. + An example is shown in the following steps to customize the video sink: + + 1. Call bufferType and AgoraVideoPixelFormat to set the buffer type and pixel format of the video frame. + 2. Implement [shouldInitialize](shouldInitialize), [shouldStart](shouldStart), [shouldStop](shouldStop), and [shouldDispose](shouldDispose) to manage the customized video sink. + 3. Implement the buffer type and pixel format as specified in AgoraVideoFrameConsumer. + 4. Create the customized video sink object. + 5. Call the [setLocalVideoRenderer]([AgoraRtcEngineKit setLocalVideoRenderer:]) and [setRemoteVideoRenderer]([AgoraRtcEngineKit setRemoteVideoRenderer:forUserId:]) methods to set the local and remote renderers. + 6. The media engine calls functions in AgoraVideoSinkProtocol according to its internal state. + */ +@protocol AgoraVideoSinkProtocol +@required +/** Initializes the video sink. + + You can also initialize the video sink before this method is called and return YES in this method. + + @return * YES: If the video sink is initialized. + * NO: If the video sink is not ready or fails to initialize, the media engine stops and reports the error. + */ +- (BOOL)shouldInitialize; + +/** Enables the video sink. + + Call this method when the media engine starts streaming. + + * YES: If the video sink is ready. The media engine provides the video frame to the custom video sink by calling the AgoraVideoFrameConsumer interface. + * NO: If the video sink is not ready. + */ +- (void)shouldStart; + +/** Disables the video sink. + + Call this method when the media engine stops video streaming. You should then stop the video sink. + */ +- (void)shouldStop; + +/** Releases the video sink. + + Call this method when the media engine wants to release the video sink resources. + */ +- (void)shouldDispose; + +/** Gets the buffer type and passes the buffer type specified in `AgoraVideoBufferType` to the media engine. + + @return bufferType AgoraVideoBufferType + */ +- (AgoraVideoBufferType)bufferType; + +/** Gets the pixel format and passes it to the media engine. + + @return pixelFormat AgoraVideoPixelFormat + */ +- (AgoraVideoPixelFormat)pixelFormat; + +@optional +/** (Optional) Outputs the video in the pixel buffer. + + @param pixelBuffer Video in the pixel buffer. + @param rotation Clockwise rotating angle of the video frame. See AgoraVideoRotation. + */ +- (void)renderPixelBuffer:(CVPixelBufferRef _Nonnull)pixelBuffer rotation:(AgoraVideoRotation)rotation; + +/** (Optional) Outputs the video in the raw data. + + @param rawData Raw video data. + @param size Size of the raw video. + @param rotation Clockwise rotating angle of the video frame. See AgoraVideoRotation. + */ +- (void)renderRawData:(void* _Nonnull)rawData size:(CGSize)size rotation:(AgoraVideoRotation)rotation; +@end + +#pragma mark - Agora Default Media IO +/** Default camera position */ +typedef NS_ENUM(NSInteger, AgoraRtcDefaultCameraPosition) { + /** Front camera */ + AgoraRtcDefaultCameraPositionFront = 0, + /** Rear camera */ + AgoraRtcDefaultCameraPositionBack = 1, +}; + +__attribute__((visibility("default"))) @interface AgoraRtcDefaultCamera : NSObject +#if defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE +@property(nonatomic, assign) AgoraRtcDefaultCameraPosition position; +- (instancetype _Nonnull)initWithPosition:(AgoraRtcDefaultCameraPosition)position; +#endif +@end + +#if (!(TARGET_OS_IPHONE) && (TARGET_OS_MAC)) +__attribute__((visibility("default"))) @interface AgoraRtcScreenCapture : NSObject +@property(nonatomic, assign, readonly) BOOL ifWindowShare; +@property(nonatomic, assign, readonly) NSUInteger displayId; +@property(nonatomic, assign, readonly) NSUInteger windowId; +@property(nonatomic, assign, readonly) CGRect rect; +@property(nonatomic, assign, readonly) CGSize dimensions; +@property(nonatomic, assign, readonly) NSInteger frameRate; +@property(nonatomic, assign, readonly) NSInteger bitrate; +@property(nonatomic, assign, readonly) BOOL captureMouseCursor; +@property(nonatomic, assign, readonly) BOOL windowFocus; + ++ (instancetype _Nonnull)screenCaptureWithId:(NSUInteger)displayId rect:(CGRect)rect dimensions:(CGSize)dimensions frameRate:(NSInteger)frameRate bitrate:(NSInteger)bitrate captureMouseCursor:(BOOL)captureMouseCursor; ++ (instancetype _Nonnull)windowCaptureWithId:(NSUInteger)windowId rect:(CGRect)rect dimensions:(CGSize)dimensions frameRate:(NSInteger)frameRate bitrate:(NSInteger)bitrate captureMouseCursor:(BOOL)captureMouseCursor windowFocus:(BOOL)windowFocus; +@end +#endif + +__attribute__((visibility("default"))) @interface AgoraRtcDefaultRenderer : NSObject +@property(nonatomic, strong, readonly) VIEW_CLASS* _Nonnull view; +@property(nonatomic, assign) AgoraVideoRenderMode mode; +- (instancetype _Nonnull)initWithView:(VIEW_CLASS* _Nonnull)view renderMode:(AgoraVideoRenderMode)mode; +@end diff --git a/integration_test_app/iris_integration_test/third_party/agora/rtc/include/AgoraMediaMetadata.h b/integration_test_app/iris_integration_test/third_party/agora/rtc/include/AgoraMediaMetadata.h new file mode 100644 index 000000000..39b12cb30 --- /dev/null +++ b/integration_test_app/iris_integration_test/third_party/agora/rtc/include/AgoraMediaMetadata.h @@ -0,0 +1,68 @@ +// +// AgoraMediaMetadata.h +// AgoraRtcEngineKit +// +// Copyright (c) 2018 Agora. All rights reserved. +// + +#import + +/** The metadata type. */ +typedef NS_ENUM(NSInteger, AgoraMetadataType) { + /** -1: the metadata type is unknown. */ + AgoraMetadataTypeUnknown = -1, + /** 0: the metadata type is video. */ + AgoraMetadataTypeVideo = 0, +}; + +/** The definition of the AgoraMediaMetadataDataSource protocol. + +@note Implement all the callbacks in this protocol in the critical thread. We recommend avoiding any time-consuming operation in the critical thread. +*/ +@protocol AgoraMediaMetadataDataSource +@required + +/** Occurs when the SDK requests the maximum size of the metadata. + +The SDK triggers this callback after you successfully calling the [setMediaMetadataDataSource]([AgoraRtcEngineKit setMediaMetadataDataSource:withType:]) method. You need to specify the maximum size of the metadata in the return value of this callback. + +This callback is returned multiple times, and you can update the maximum metadata size in the new callbacks. +@return The maximum size of the buffer of the metadata (see the return value of [readyToSendMetadataAtTimestamp]([AgoraMediaMetadataDataSource readyToSendMetadataAtTimestamp:])) that you want to use. The highest value is 1024 bytes. Ensure that you set the return value. + */ +- (NSInteger)metadataMaxSize; + +/** Occurs when the SDK is ready to receive and send metadata. + +You need to specify the metadata in the return value of this method. + +@note Ensure that the size of the metadata that you specify in this callback does not exceed the value set in the maxMetadataSize callback. + @param timestamp The timestamp (ms) of the current metadata. + @return The metadata that you want to send in the format of NSData, including the following parameters: + + - `uid`: ID of the user who sends the metadata. + - `size`: The size of the sent or received metadata. + - `buffer`: The sent or received metadata. + - `timeStampMs`: The timestamp of the metadata. + + Ensure that you set the return value. + */ +- (NSData* _Nullable)readyToSendMetadataAtTimestamp:(NSTimeInterval)timestamp; + +@end + +/** The definition of AgoraMediaMetadataDelegate + +@note Implement the callback in this protocol in the critical thread. We recommend avoiding any time-consuming operation in the critical thread. +*/ +@protocol AgoraMediaMetadataDelegate +@required + +/** Occurs when the local user receives the metadata. + + @param data The received metadata. + @param uid The ID of the user who sends the metadata. + @param timestamp The timestamp (ms) of the received metadata. + */ +- (void)receiveMetadata:(NSData* _Nonnull)data fromUser:(NSInteger)uid atTimestamp:(NSTimeInterval)timestamp; + +@end diff --git a/integration_test_app/iris_integration_test/third_party/agora/rtc/include/AgoraObjects.h b/integration_test_app/iris_integration_test/third_party/agora/rtc/include/AgoraObjects.h new file mode 100644 index 000000000..66f6648fa --- /dev/null +++ b/integration_test_app/iris_integration_test/third_party/agora/rtc/include/AgoraObjects.h @@ -0,0 +1,1947 @@ +// +// AgoraObjects.h +// AgoraRtcEngineKit +// +// Copyright (c) 2018 Agora. All rights reserved. +// + +#import +#import +#import "AgoraEnumerates.h" + +#if defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE +#import +typedef UIView VIEW_CLASS; +typedef UIColor COLOR_CLASS; +#elif defined(TARGET_OS_MAC) && TARGET_OS_MAC +#import +typedef NSView VIEW_CLASS; +typedef NSColor COLOR_CLASS; +#endif + +/** The AgoraAudioFrame interface. (iOS only) + + @since v3.4.5 + + After you successfully register the audio delegate, the SDK triggers the + following callbacks to report the observed audio data: + + - [onRecordAudioFrame]([AgoraAudioDataFrameProtocol onRecordAudioFrame:]) + - [onPlaybackAudioFrame]([AgoraAudioDataFrameProtocol onPlaybackAudioFrame:]) + - [onMixedAudioFrame]([AgoraAudioDataFrameProtocol onMixedAudioFrame:]) + - [onPlaybackAudioFrameBeforeMixing]([AgoraAudioDataFrameProtocol onPlaybackAudioFrameBeforeMixing:uid:]) + */ +__attribute__((visibility("default"))) @interface AgoraAudioFrame : NSObject +/** The number of samples per channel. + */ +@property(assign, nonatomic) NSInteger samplesPerChannel; +/** The number of bytes per audio sample. For example, each PCM audio sample + usually takes up 16 bits (2 bytes). + */ +@property(assign, nonatomic) NSInteger bytesPerSample; +/** The number of audio channels. If the channel uses stereo, the data is + interleaved. + +- 1: Mono. +- 2: Stereo. + */ +@property(assign, nonatomic) NSInteger channels; +/** The sample rate. + */ +@property(assign, nonatomic) NSInteger samplesPerSec; +/** The buffer of the sample audio data. When the audio frame uses a stereo + channel, the data buffer is interleaved. The size of the data buffer is as + follows: `buffer` = `samplesPerChannel` × `channels` × `bytesPerSample`. + */ +@property(assign, nonatomic) void* _Nullable buffer; +/** The timestamp of the external audio frame. You can use this parameter for + the following purposes: + +- Restore the order of the captured audio frame. +- Synchronize audio and video frames in video-related scenarios, including +where external video sources are used. + */ +@property(assign, nonatomic) int64_t renderTimeMs; +/** Reserved for future use. + */ +@property(assign, nonatomic) NSInteger avSyncType; +@end + +/** The AgoraAudioParam interface. (iOS only) + + @since v3.4.5 + + You can pass the `AgoraAudioParam` object in the return value of the following + callbacks to set the audio data format for the corresponding callbacks: + + - [getRecordAudioParams]([AgoraAudioDataFrameProtocol getRecordAudioParams]): + Sets the audio recording format for the + [onRecordAudioFrame]([AgoraAudioDataFrameProtocol onRecordAudioFrame:]) + callback. + - [getPlaybackAudioParams]([AgoraAudioDataFrameProtocol getPlaybackAudioParams]): + Sets the audio playback format for the + [onPlaybackAudioFrame]([AgoraAudioDataFrameProtocol onPlaybackAudioFrame:]) + callback. + - [getMixedAudioParams]([AgoraAudioDataFrameProtocol getMixedAudioParams]): + Sets the audio mixing format for the + [onMixedAudioFrame]([AgoraAudioDataFrameProtocol onMixedAudioFrame:]) callback. + + @note The SDK calculates the sample interval according to the + `samplesPerCall`, `sampleRate`, and `channel` values in the + `AgoraAudioParam` interface and triggers the following callbacks at the + calculated sample interval: + + - [onRecordAudioFrame]([AgoraAudioDataFrameProtocol onRecordAudioFrame:]) + - [onPlaybackAudioFrame]([AgoraAudioDataFrameProtocol onPlaybackAudioFrame:]) + - [onMixedAudioFrame]([AgoraAudioDataFrameProtocol onMixedAudioFrame:]) + + Sample interval (seconds) = `samplesPerCall`/(`sampleRate` × `channel`). + Ensure that the value of sample interval is equal to or greater than 0.01. + */ +__attribute__((visibility("default"))) @interface AgoraAudioParam : NSObject + +/** The audio sample rate (Hz), which can be set as one of the following values: + + - `8000` + - `16000` (Default) + - `32000` + - `44100 ` + - `48000` + */ +@property(assign, nonatomic) NSInteger sampleRate; + +/* The number of audio channels, which can be set as either of the following values: + + - `1`: Mono (Default) + - `2`: Stereo + */ +@property(assign, nonatomic) NSInteger channel; + +/* The use mode of the audio data. See AgoraAudioRawFrameOperationMode. + */ +@property(assign, nonatomic) AgoraAudioRawFrameOperationMode mode; + +/** The number of samples. For example, set it as 1024 for RTMP or RTMPS + streaming. + */ +@property(assign, nonatomic) NSInteger samplesPerCall; + +@end + +/** Properties of the video canvas object. + */ +__attribute__((visibility("default"))) @interface AgoraRtcVideoCanvas : NSObject +/** The video display view. + + VIEW_CLASS is a general name for this property. See the following definitions for iOS and macOS: + + - iOS: UIView + - MacOS: NSView + */ +@property(strong, nonatomic) VIEW_CLASS* _Nullable view; +/** The rendering mode of the video view. See [AgoraVideoRenderMode](AgoraVideoRenderMode). + */ +@property(assign, nonatomic) AgoraVideoRenderMode renderMode; +/** The unique channel name for the Agora RTC session in the string format. The string length must be less than 64 bytes. Supported character scopes are: + + - All lowercase English letters: a to z. + - All uppercase English letters: A to Z. + - All numeric characters: 0 to 9. + - The space character. + - Punctuation characters and other symbols, including: "!", "#", "$", "%", "&", "(", ")", "+", "-", ":", ";", "<", "=", ".", ">", "?", "@", "[", "]", "^", "_", "{", "}", "|", "~", ",". +

        **Note**

        + + - The default value is the empty string "". Use the default value if the user joins the channel using the [joinChannelByToken]([AgoraRtcEngineKit joinChannelByToken:channelId:info:uid:joinSuccess:]) method in the [AgoraRtcEngineKit](AgoraRtcEngineKit) class. The `AgoraRtcVideoCanvas` struct defines the video canvas of the user in the channel. + - If the user joins the channel using the [joinChannelByToken]([AgoraRtcChannel joinChannelByToken:info:uid:options:]) method in the [AgoraRtcChannel](AgoraRtcChannel) class, set this parameter as the `channelID` of the `AgoraRtcChannel` object. The `AgoraRtcVideoCanvas` struct defines the video canvas of the user in the channel with the specified channel ID. + */ +@property(copy, nonatomic) NSString* _Nullable channelId; +/** User ID of the view. + */ +@property(assign, nonatomic) NSUInteger uid; +/** The mirror mode of the video view. See [AgoraVideoMirrorMode](AgoraVideoMirrorMode). + + **Note** + + - For the mirror mode of the local video view: If you use a front camera, the SDK enables the mirror mode by default; if you use a rear camera, the SDK disables the mirror mode by default. + - + */ +@property(assign, nonatomic) AgoraVideoMirrorMode mirrorMode; +@end + +/** The configurations of the last-mile network probe test. */ +__attribute__((visibility("default"))) @interface AgoraLastmileProbeConfig : NSObject +/** Sets whether to test the uplink network. Some users, for example, the audience in the interactive live streaming channel, do not need such a test. + +- NO: disables the test. +- YES: enables the test. +*/ +@property(assign, nonatomic) BOOL probeUplink; +/** Sets whether to test the downlink network. + +- NO: disables the test. +- YES: enables the test. +*/ +@property(assign, nonatomic) BOOL probeDownlink; +/** The expected maximum sending bitrate (bps) of the local user. + +The value ranges between 100000 and 5000000. We recommend setting this parameter according to the bitrate value set by [setVideoEncoderConfiguration]([AgoraRtcEngineKit setVideoEncoderConfiguration:]). */ +@property(assign, nonatomic) NSUInteger expectedUplinkBitrate; +/** The expected maximum receiving bitrate (bps) of the local user. + +The value ranges between 100000 and 5000000. +*/ +@property(assign, nonatomic) NSUInteger expectedDownlinkBitrate; +@end + +/** The last-mile network probe test result in one direction (uplink or downlink). */ +__attribute__((visibility("default"))) @interface AgoraLastmileProbeOneWayResult : NSObject +/** The packet loss rate (%). */ +@property(assign, nonatomic) NSUInteger packetLossRate; +/** The network jitter (ms). */ +@property(assign, nonatomic) NSUInteger jitter; +/** The estimated available bandwidth (Kbps). */ +@property(assign, nonatomic) NSUInteger availableBandwidth; +@end + +/** The uplink and downlink last-mile network probe test result. */ +__attribute__((visibility("default"))) @interface AgoraLastmileProbeResult : NSObject +/* The state of the probe test. + +See [AgoraLastmileProbeResultState](AgoraLastmileProbeResultState). +*/ +@property(assign, nonatomic) AgoraLastmileProbeResultState state; +/** The round-trip delay time (ms). */ +@property(assign, nonatomic) NSUInteger rtt; +/** The uplink last-mile network report + +See [AgoraLastmileProbeOneWayResult](AgoraLastmileProbeOneWayResult). +*/ +@property(strong, nonatomic) AgoraLastmileProbeOneWayResult* _Nonnull uplinkReport; +/** The downlink last-mile network report + +See [AgoraLastmileProbeOneWayResult](AgoraLastmileProbeOneWayResult). +*/ +@property(strong, nonatomic) AgoraLastmileProbeOneWayResult* _Nonnull downlinkReport; +@end + +/** Statistics of the local video stream. + */ +__attribute__((visibility("default"))) @interface AgoraRtcLocalVideoStats : NSObject +/** Bitrate (Kbps) sent in the reported interval, which does not include the bitrate of the retransmission video after packet loss. */ +@property(assign, nonatomic) NSUInteger sentBitrate; +/** Frame rate (fps) sent in the reported interval, which does not include the frame rate of the retransmission video after packet loss. */ +@property(assign, nonatomic) NSUInteger sentFrameRate; +/** The encoder output frame rate (fps) of the local video. */ +@property(assign, nonatomic) NSUInteger encoderOutputFrameRate; +/** The renderer output frame rate (fps) of the local video. */ +@property(assign, nonatomic) NSUInteger rendererOutputFrameRate; +/** The target bitrate (Kbps) of the current encoder. This value is estimated by the SDK based on the current network conditions. */ +@property(assign, nonatomic) NSUInteger sentTargetBitrate; +/** The target frame rate (fps) of the current encoder. */ +@property(assign, nonatomic) NSUInteger sentTargetFrameRate; +/** Quality change of the local video in terms of target frame rate and target bit rate in this reported interval, see [AgoraVideoQualityAdaptIndication](AgoraVideoQualityAdaptIndication). */ +@property(assign, nonatomic) AgoraVideoQualityAdaptIndication qualityAdaptIndication; +/** The encoding bitrate (Kbps), which does not include the bitrate of the re-transmission video after packet loss. + */ +@property(assign, nonatomic) NSUInteger encodedBitrate; +/** The width of the encoding frame (px). + */ +@property(assign, nonatomic) NSUInteger encodedFrameWidth; +/** The height of the encoding frame (px). + */ +@property(assign, nonatomic) NSUInteger encodedFrameHeight; +/** The value of the sent frames, represented by an aggregate value. + */ +@property(assign, nonatomic) NSUInteger encodedFrameCount; +/** The codec type of the local video: + + - `AgoraVideoCodecTypeVP8` = 1: VP8. + - `AgoraVideoCodecTypeH264` = 2: (Default) H.264. + */ +@property(assign, nonatomic) AgoraVideoCodecType codecType; + +/** The video packet loss rate (%) from the local client to the Agora edge server before applying the anti-packet loss strategies. + + @since v3.1.0 + */ +@property(assign, nonatomic) NSInteger txPacketLossRate; + +/** The capture frame rate (fps) of the local video. + + @since v3.1.0 + */ +@property(assign, nonatomic) NSInteger captureFrameRate; + +/** The brightness level of the video image captured by the local camera. See + AgoraCaptureBrightnessLevelType. + + @since v3.3.0 + */ +@property(assign, nonatomic) AgoraCaptureBrightnessLevelType captureBrightnessLevel; +@end + +/** Statistics of the remote video stream. + */ +__attribute__((visibility("default"))) @interface AgoraRtcRemoteVideoStats : NSObject +/** User ID of the user sending the video streams. + */ +@property(assign, nonatomic) NSUInteger uid; +/** Time delay (ms). **DEPRECATED** In scenarios where audio and video is synchronized, you can use the value of `networkTransportDelay` and `jitterBufferDelay` in AgoraRtcRemoteAudioStats to know the delay statistics of the remote video. + */ +@property(assign, nonatomic) NSUInteger __deprecated delay; +/** Width (pixels) of the video stream. + */ +@property(assign, nonatomic) NSUInteger width; +/** Height (pixels) of the video stream. + */ +@property(assign, nonatomic) NSUInteger height; +/** The average bitrate (Kbps) of the received video stream. + */ +@property(assign, nonatomic) NSUInteger receivedBitrate; +/** The decoder output frame rate (fps) of the remote video. + */ +@property(assign, nonatomic) NSUInteger decoderOutputFrameRate; +/** The renderer output frame rate (fps) of the remote video. + */ +@property(assign, nonatomic) NSUInteger rendererOutputFrameRate; +/** Packet loss rate (%) of the remote video stream after using the anti-packet-loss method. + */ +@property(assign, nonatomic) NSUInteger packetLossRate; +/** Video stream type (high-stream or low-stream). + */ +@property(assign, nonatomic) AgoraVideoStreamType rxStreamType; +/** The total freeze time (ms) of the remote video stream after the remote user joins the channel. In a video session where the frame rate is set to no less than 5 fps, video freeze occurs when the time interval between two adjacent renderable video frames is more than 500 ms. + */ +@property(assign, nonatomic) NSUInteger totalFrozenTime; +/** The total video freeze time as a percentage (%) of the total time when the video is available. + */ +@property(assign, nonatomic) NSUInteger frozenRate; +/** The total time (ms) when the remote user in the Communication profile or the remote host in the interactive live streaming profile neither stops sending the video stream nor disables the video module after joining the channel. + */ +@property(assign, nonatomic) NSUInteger totalActiveTime; +/** The total publish duration (ms) of the remote video stream. + */ +@property(assign, nonatomic) NSInteger publishDuration; +@end + +/** The statistics of the local audio stream. + */ +__attribute__((visibility("default"))) @interface AgoraRtcLocalAudioStats : NSObject +/** The number of channels. + */ +@property(assign, nonatomic) NSUInteger numChannels; +/** The sample rate (Hz). + */ +@property(assign, nonatomic) NSUInteger sentSampleRate; +/** The average sending bitrate (Kbps). + */ +@property(assign, nonatomic) NSUInteger sentBitrate; +/** The audio packet loss rate (%) from the local client to the Agora edge server before applying the anti-packet loss strategies. + + @since v3.1.0 + */ +@property(assign, nonatomic) NSUInteger txPacketLossRate; +@end + +/** The statistics of the remote audio stream. + */ +__attribute__((visibility("default"))) @interface AgoraRtcRemoteAudioStats : NSObject +/** User ID of the user sending the audio stream. + */ +@property(assign, nonatomic) NSUInteger uid; +/** Audio quality received by the user. + */ +@property(assign, nonatomic) NSUInteger quality; +/** Network delay (ms) from the sender to the receiver. + */ +@property(assign, nonatomic) NSUInteger networkTransportDelay; +/** Network delay (ms) from the receiver to the jitter buffer. + @note When the receiver is an audience member and `AgoraAudienceLatencyLevelType` is `1`, this parameter does not take effect. + */ +@property(assign, nonatomic) NSUInteger jitterBufferDelay; +/** The audio frame loss rate in the reported interval. + */ +@property(assign, nonatomic) NSUInteger audioLossRate; +/** The number of channels. + */ +@property(assign, nonatomic) NSUInteger numChannels; +/** The sample rate (Hz) of the received audio stream in the reported interval. + */ +@property(assign, nonatomic) NSUInteger receivedSampleRate; +/** The average bitrate (Kbps) of the received audio stream in the reported interval. + */ +@property(assign, nonatomic) NSUInteger receivedBitrate; +/** The total freeze time (ms) of the remote audio stream after the remote user joins the channel. + */ +@property(assign, nonatomic) NSUInteger totalFrozenTime; +/** The total audio freeze time as a percentage (%) of the total time when the audio is available. + */ +@property(assign, nonatomic) NSUInteger frozenRate; +/** The total time (ms) when the remote user in the Communication profile or the remote host in the interactive live streaming profile neither stops sending the audio stream nor disables the audio module after joining the channel. + */ +@property(assign, nonatomic) NSUInteger totalActiveTime; +/** The total publish duration (ms) of the remote audio stream. + + @since v3.1.0 + */ +@property(assign, nonatomic) NSInteger publishDuration; +/** Quality of experience (QoE) of the local user when receiving a remote + audio stream. See AgoraExperienceQuality. + + @since v3.3.0 + */ +@property(assign, nonatomic) NSUInteger qoeQuality; +/** The reason for poor QoE of the local user when receiving a remote + audio stream. See AgoraExperiencePoorReason. + + @since v3.3.0 + */ +@property(assign, nonatomic) NSUInteger qualityChangedReason; +/** The quality of the remote audio stream as determined by the Agora real-time + audio MOS (Mean Opinion Score) measurement method in the reported interval. + The return value ranges from 0 to 500. Dividing the return value by 100 gets + the MOS score, which ranges from 0 to 5. The higher the score, the better the audio quality. + + @since v3.3.1 + + The subjective perception of audio quality corresponding to the Agora real-time audio MOS scores is as follows: + +| MOS score | Perception of audio quality | +| :------------- | :----------------------------------------------------------- | +| Greater than 4 | Excellent. The audio sounds clear and smooth. | +| From 3.5 to 4 | Good. The audio has some perceptible impairment, but still sounds clear. | +| From 3 to 3.5 | Fair. The audio freezes occasionally and requires attentive listening. | +| From 2.5 to 3 | Poor. The audio sounds choppy and requires considerable effort to understand. | +| From 2 to 2.5 | Bad. The audio has occasional noise. Consecutive audio dropouts occur, resulting in some information loss. The users can communicate only with difficulty. | +| Less than 2 | Very bad. The audio has persistent noise. Consecutive audio dropouts are frequent, resulting in severe information loss. Communication is nearly impossible. | + */ +@property(assign, nonatomic) NSInteger mosValue; +@end + +/** Properties of the audio volume information. + */ +__attribute__((visibility("default"))) @interface AgoraRtcAudioVolumeInfo : NSObject +/** The user ID. + + - In the local user's callback, `uid` = 0. + - In the remote users' callback, `uid` is the ID of a remote user whose instantaneous volume is one of the three highest. + */ +@property(assign, nonatomic) NSUInteger uid; +/** The volume of each user after audio mixing. The value ranges between 0 (lowest volume) and 255 (highest volume). In + * the local user's callback, `volume` = `totalVolume`. + */ +@property(assign, nonatomic) NSUInteger volume; +/** Voice activity status of the local user. + + - 0: The local user is not speaking. + - 1: The local user is speaking. + + **Note** + + - The `vad` parameter cannot report the voice activity status of the remote users. In the remote users' callback, `vad` is always 1. + - To use this parameter, you must set the `report_vad` parameter to `YES` when calling + [enableAudioVolumeIndication]([AgoraRtcEngineKit enableAudioVolumeIndication:smooth:report_vad:]). + */ +@property(assign, nonatomic) NSUInteger vad; +/** The name of the channel where the user is in. + */ +@property(copy, nonatomic) NSString* _Nonnull channelId; +@end + +/** **Since** v3.5.1. The information of an audio file. This struct is reported in + [didRequestAudioFileInfo]([AgoraRtcEngineDelegate rtcEngine:didRequestAudioFileInfo:error:]). + */ +__attribute__((visibility("default"))) @interface AgoraRtcAudioFileInfo : NSObject +/** The file path. + */ +@property(copy, nonatomic) NSString* _Nonnull filePath; +/** The file duration (ms). + */ +@property(assign, nonatomic) NSUInteger durationMs; +@end + +/** **Since** v3.4.0. The metronome configuration, which is set in [startRhythmPlayer]([AgoraRtcEngineKit startRhythmPlayer:sound2:config:]) or [configRhythmPlayer]([AgoraRtcEngineKit configRhythmPlayer:]). */ +__attribute__((visibility("default"))) @interface AgoraRtcRhythmPlayerConfig : NSObject +/** The number of beats per measure. The range is 1 to 9. The default value is 4, which means that each measure + contains one downbeat and three upbeats. + */ +@property(assign, nonatomic) NSUInteger beatsPerMeasure; +/** Tempo (beats per minute). The range is 60 to 360. The default value is 60, which means that the metronome plays 60 + beats in one minute. + */ +@property(assign, nonatomic) NSUInteger beatsPerMinute; +/** Whether to publish the sound of the metronome to remote users: + + - `YES`: (Default) Publish. Both the local user and remote users can hear the metronome. + - `NO`: Do not publish. Only the local user can hear the metronome. + */ +@property(assign, nonatomic) BOOL publish; +@end + +/** Statistics of the channel + */ +__attribute__((visibility("default"))) @interface AgoraChannelStats : NSObject +/** Call duration of the local user in seconds, represented by an aggregate value. + */ +@property(assign, nonatomic) NSInteger duration; +/** Total number of bytes transmitted, represented by an aggregate value. + */ +@property(assign, nonatomic) NSInteger txBytes; +/** Total number of bytes received, represented by an aggregate value. + */ +@property(assign, nonatomic) NSInteger rxBytes; +/** Total number of audio bytes sent (bytes), represented by an aggregate value. + */ +@property(assign, nonatomic) NSInteger txAudioBytes; +/** Total number of video bytes sent (bytes), represented by an aggregate value. + */ +@property(assign, nonatomic) NSInteger txVideoBytes; +/** Total number of audio bytes received (bytes), represented by an aggregate value. + */ +@property(assign, nonatomic) NSInteger rxAudioBytes; +/** Total number of video bytes received (bytes), represented by an aggregate value. + */ +@property(assign, nonatomic) NSInteger rxVideoBytes; +/** Total packet transmission bitrate (Kbps), represented by an instantaneous value. + */ +@property(assign, nonatomic) NSInteger txKBitrate; +/** Total receive bitrate (Kbps), represented by an instantaneous value. + */ +@property(assign, nonatomic) NSInteger rxKBitrate; +/** Audio packet transmission bitrate (Kbps), represented by an instantaneous value. + */ +@property(assign, nonatomic) NSInteger txAudioKBitrate; +/** Audio receive bitrate (Kbps), represented by an instantaneous value. + */ +@property(assign, nonatomic) NSInteger rxAudioKBitrate; +/** Video transmission bitrate (Kbps), represented by an instantaneous value. + */ +@property(assign, nonatomic) NSInteger txVideoKBitrate; +/** Video receive bitrate (Kbps), represented by an instantaneous value. + */ +@property(assign, nonatomic) NSInteger rxVideoKBitrate; +/** Client-server latency (ms) + */ +@property(assign, nonatomic) NSInteger lastmileDelay; +/** The packet loss rate (%) from the local client to Agora's edge server, before using the anti-packet-loss method. + */ +@property(assign, nonatomic) NSInteger txPacketLossRate; +/** The packet loss rate (%) from Agora's edge server to the local client, before using the anti-packet-loss method. + */ +@property(assign, nonatomic) NSInteger rxPacketLossRate; +/** Number of users in the channel. + +- Communication profile: The number of users in the channel. +- Interactive live streaming profile: + + - If the local user is an audience: The number of users in the channel = The number of hosts in the channel + 1. + - If the user is a host: The number of users in the channel = The number of hosts in the channel. + */ +@property(assign, nonatomic) NSInteger userCount; +/** Application CPU usage (%). + This property reported in the [didLeaveChannelWithStats]([AgoraRtcEngineDelegate rtcEngine:didLeaveChannelWithStats:]) callback is always `0`. + */ +@property(assign, nonatomic) double cpuAppUsage; +/** System CPU usage (%). + This property reported in the [didLeaveChannelWithStats]([AgoraRtcEngineDelegate rtcEngine:didLeaveChannelWithStats:]) callback is always `0`. + */ +@property(assign, nonatomic) double cpuTotalUsage; +/** The round-trip time delay (ms) from the client to the local router. + + @note (iOS only) As of v3.3.0, this property is disabled on devices running iOS 14 or later, and enabled on devices running versions earlier than iOS 14 by default. To enable this property on devices running iOS 14 or later, contact [support@agora.io](mailto:support@agora.io). See [FAQ](https://docs.agora.io/en/faq/local_network_privacy) for details. + */ +@property(assign, nonatomic) NSInteger gatewayRtt; +/** The memory usage ratio of the app (%). + + @note This value is for reference only. Due to system limitations, you may not get the value of this member. + */ +@property(assign, nonatomic) double memoryAppUsageRatio; +/** The memory usage ratio of the system (%). + + @note This value is for reference only. Due to system limitations, you may not get the value of this member. + */ +@property(assign, nonatomic) double memoryTotalUsageRatio; +/** The memory usage of the app (KB). + + @note This value is for reference only. Due to system limitations, you may not get the value of this member. + */ +@property(assign, nonatomic) NSInteger memoryAppUsageInKbytes; +@end + +/** Properties of the video encoder configuration. + */ +__attribute__((visibility("default"))) @interface AgoraVideoEncoderConfiguration : NSObject +/** The video frame dimension (px) used to specify the video quality in the total number of pixels along a frame's width and height. The default value is 640 * 360. + +You can customize the dimension, or select from the following list: + + - AgoraVideoDimension120x120 + - AgoraVideoDimension160x120 + - AgoraVideoDimension180x180 + - AgoraVideoDimension240x180 + - AgoraVideoDimension320x180 + - AgoraVideoDimension240x240 + - AgoraVideoDimension320x240 + - AgoraVideoDimension424x240 + - AgoraVideoDimension360x360 + - AgoraVideoDimension480x360 + - AgoraVideoDimension640x360 + - AgoraVideoDimension480x480 + - AgoraVideoDimension640x480 + - AgoraVideoDimension840x480 + - AgoraVideoDimension960x720 + - AgoraVideoDimension1280x720 + - AgoraVideoDimension1920x1080 (macOS only) + + Note: + + - The dimension does not specify the orientation mode of the output ratio. For how to set the video orientation, see [AgoraVideoOutputOrientationMode](AgoraVideoOutputOrientationMode). + - Whether 720p can be supported depends on the device. If the device cannot support 720p, the frame rate will be lower than the one listed in the table. Agora optimizes the video in lower-end devices. + - iPhones do not support video frame dimensions above 720p. + */ +@property(assign, nonatomic) CGSize dimensions; + +/** The frame rate of the video (fps). + + You can either set the frame rate manually or choose from the following options. The default value is 15. We do not recommend setting this to a value greater than 30. + + * AgoraVideoFrameRateFps1(1): 1 fps + * AgoraVideoFrameRateFps7(7): 7 fps + * AgoraVideoFrameRateFps10(10): 10 fps + * AgoraVideoFrameRateFps15(15): 15 fps + * AgoraVideoFrameRateFps24(24): 24 fps + * AgoraVideoFrameRateFps30(30): 30 fps + * AgoraVideoFrameRateFps60(30): 60 fps (macOS only) + */ +@property(assign, nonatomic) NSInteger frameRate; + +/** The minimum video encoder frame rate (fps). + +The default value is DEFAULT_MIN_BITRATE(-1) (the SDK uses the lowest encoder frame rate). For information on scenarios and considerations, see *Set the Video Profile*. +*/ +@property(assign, nonatomic) NSInteger minFrameRate; + +/** The bitrate of the video. + + Sets the video bitrate (Kbps). Refer to the table below and set your bitrate. If you set a bitrate beyond the proper range, the SDK automatically adjusts it to a value within the range. You can also choose from the following options: + + - AgoraVideoBitrateStandard: (recommended) the standard bitrate mode. In this mode, the bitrates differ between the interactive live streaming and Communication profiles: + + - Communication profile: the video bitrate is the same as the base bitrate. + - Interactive live streaming profile: the video bitrate is twice the base bitrate. + + - AgoraVideoBitrateCompatible: the compatible bitrate mode. In this mode, the bitrate stays the same regardless of the profile. In the interactive live streaming profile, if you choose this mode, the video frame rate may be lower than the set value. + +Agora uses different video codecs for different profiles to optimize the user experience. For example, the Communication profile prioritizes the smoothness while the interactive live streaming profile prioritizes the video quality (a higher bitrate). Therefore, Agora recommends setting this parameter as AgoraVideoBitrateStandard. + +**Video Bitrate Table** + +| Resolution | Frame Rate (fps) | Base Bitrate (Kbps, for Communication) | Live Bitrate (Kbps, for Live Broadcast) | +|-------------------|------------------|----------------------------------------|-----------------------------------------| +| 160 * 120 | 15 | 65 | 130 | +| 120 * 120 | 15 | 50 | 100 | +| 320 * 180 | 15 | 140 | 280 | +| 180 * 180 | 15 | 100 | 200 | +| 240 * 180 | 15 | 120 | 240 | +| 320 * 240 | 15 | 200 | 400 | +| 240 * 240 | 15 | 140 | 280 | +| 424 * 240 | 15 | 220 | 440 | +| 640 * 360 | 15 | 400 | 800 | +| 360 * 360 | 15 | 260 | 520 | +| 640 * 360 | 30 | 600 | 1200 | +| 360 * 360 | 30 | 400 | 800 | +| 480 * 360 | 15 | 320 | 640 | +| 480 * 360 | 30 | 490 | 980 | +| 640 * 480 | 15 | 500 | 1000 | +| 480 * 480 | 15 | 400 | 800 | +| 640 * 480 | 30 | 750 | 1500 | +| 480 * 480 | 30 | 600 | 1200 | +| 848 * 480 | 15 | 610 | 1220 | +| 848 * 480 | 30 | 930 | 1860 | +| 640 * 480 | 10 | 400 | 800 | +| 1280 * 720 | 15 | 1130 | 2260 | +| 1280 * 720 | 30 | 1710 | 3420 | +| 960 * 720 | 15 | 910 | 1820 | +| 960 * 720 | 30 | 1380 | 2760 | +| 1920 * 1080 | 15 | 2080 | 4160 | +| 1920 * 1080 | 30 | 3150 | 6300 | +| 1920 * 1080 | 60 | 4780 | 6500 | + + +**Note:** + +The base bitrate in this table applies to the Communication profile. The interactive live streaming profile generally requires a higher bitrate for better video quality. Agora recommends setting the bitrate mode as AgoraVideoBitrateStandard. You can also set the bitrate as twice the base bitrate. + + +*/ +@property(assign, nonatomic) NSInteger bitrate; + +/** The minimum encoding bitrate. + +Sets the minimum encoding bitrate (Kbps). + +The Agora SDK automatically adjusts the encoding bitrate to adapt to network conditions. Using a value greater than the default value forces the video encoder to output high-quality images but may cause more packet loss and hence sacrifice the smoothness of the video transmission. Unless you have special requirements for image quality, Agora does not recommend changing this value. + +**Note:** + +This parameter applies only to the interactive live streaming profile.*/ +@property(assign, nonatomic) NSInteger minBitrate; + +/** The video orientation mode of the video: AgoraVideoOutputOrientationMode. + + * AgoraVideoOutputOrientationModeAdaptative(0): (Default) The output video always follows the orientation of the captured video, because the receiver takes the rotational information passed on from the video encoder. + - If the captured video is in landscape mode, the output video is in landscape mode. + - If the captured video is in portrait mode, the output video is in portrait mode. + * AgoraVideoOutputOrientationModeFixedLandscape(1): The output video is always in landscape mode. If the captured video is in portrait mode, the video encoder crops it to fit the output. This applies to situations where the receiver cannot process the rotational information. For example, CDN live streaming. + * AgoraVideoOutputOrientationModeFixedPortrait(2): The output video is always in portrait mode. If the captured video is in landscape mode, the video encoder crops it to fit the output. This applies to situations where the receiver cannot process the rotational information. For example, CDN live streaming. + +For scenarios with video rotation, Agora provides *Rotate the Video* to guide users on how to set this parameter to get the preferred video orientation. + + */ +@property(assign, nonatomic) AgoraVideoOutputOrientationMode orientationMode; + +/** The video encoding degradation preference under limited bandwidth. + +AgoraDegradationPreference: + +* AgoraDegradationMaintainQuality(0): (Default) Degrades the frame rate to guarantee the video quality. +* AgoraDegradationMaintainFramerate(1): Degrades the video quality to guarantee the frame rate. +*/ +@property(assign, nonatomic) AgoraDegradationPreference degradationPreference; + +/** Sets the mirror mode of the published local video stream. It only affects the video that the remote user sees. See [AgoraVideoMirrorMode](AgoraVideoMirrorMode). + + **Note** + + The SDK disables the mirror mode by default. + */ +@property(assign, nonatomic) AgoraVideoMirrorMode mirrorMode; + +/** Initializes and returns a newly allocated AgoraVideoEncoderConfiguration object with the specified video resolution. + + @param size Video resolution. + @param frameRate Video frame rate. + @param bitrate Video bitrate. + @param orientationMode AgoraVideoOutputOrientationMode. + @return An initialized `AgoraVideoEncoderConfiguration` object. + */ +- (instancetype _Nonnull)initWithSize:(CGSize)size frameRate:(AgoraVideoFrameRate)frameRate bitrate:(NSInteger)bitrate orientationMode:(AgoraVideoOutputOrientationMode)orientationMode; + +/** Initializes and returns a newly allocated AgoraVideoEncoderConfiguration object with the specified video width and height. + + @param width Width of the video. + @param height Height of the video. + @param frameRate Video frame rate. + @param bitrate Video bitrate. + @param orientationMode AgoraVideoOutputOrientationMode. + @return An initialized `AgoraVideoEncoderConfiguration` object. + */ +- (instancetype _Nonnull)initWithWidth:(NSInteger)width height:(NSInteger)height frameRate:(AgoraVideoFrameRate)frameRate bitrate:(NSInteger)bitrate orientationMode:(AgoraVideoOutputOrientationMode)orientationMode; +@end + +/** Properties of the screen sharing encoding parameters. + */ +__attribute__((visibility("default"))) @interface AgoraScreenCaptureParameters : NSObject +/** The maximum encoding dimensions for screen sharing. + +The default value is 1920 * 1080 pixels, that is, 2073600 pixels. Agora uses the value of this parameter to calculate the charges. + +If the aspect ratio is different between the encoding dimensions and screen dimensions, Agora applies the following algorithms for encoding. Suppose the encoding dimensions are 1920 * 1080: + +- If the value of the screen dimensions is lower than that of the encoding dimensions, for example, 1000 * 1000, the SDK uses 1000 * 1000 for encoding. +- If the value of the screen dimensions is higher than that of the encoding dimensions, for example, 2000 * 1500, the SDK uses the maximum value under 1920 * 1080 with the aspect ratio of the screen dimension (4:3) for encoding, that is, 1440 * 1080. + +In either case, Agora uses the value of this parameter to calculate the charges. + */ +@property(assign, nonatomic) CGSize dimensions; + +/** The frame rate (fps) of the shared region. The default value is 5. We do not recommend setting this to a value greater than 15. + */ +@property(assign, nonatomic) NSInteger frameRate; + +/** The bitrate (Kbps) of the shared region. The default value is 0 (the SDK works out a bitrate according to the dimensions of the current screen). + */ +@property(assign, nonatomic) NSInteger bitrate; + +/** Sets whether to capture the mouse for screen sharing. + +- YES: (Default) Capture the mouse. +- NO: Do not capture the mouse. + */ +@property(assign, nonatomic) BOOL captureMouseCursor; + +/** Whether to bring the window to the front when calling [startScreenCaptureByWindowId]([AgoraRtcEngineKit startScreenCaptureByWindowId:rectangle:parameters:]) to share the window: + + - YES: Bring the window to the front. + - NO: (Default) Do not bring the window to the front. + + @since v3.1.0 + */ +@property(assign, nonatomic) BOOL windowFocus; + +/** A list of IDs of windows to be blocked. + + When calling [startScreenCaptureByDisplayId]([AgoraRtcEngineKit startScreenCaptureByDisplayId:rectangle:parameters:]) + and pass `0` in the `displayId` parameter to start sharing a main screen, you can use this parameter to block the specified windows. When calling + [updateScreenCaptureParameters]([AgoraRtcEngineKit updateScreenCaptureParameters:]) to update the configuration for the main screen sharing, you can use this + parameter to dynamically block the specified windows during the main screen sharing. + + @since v3.1.0 + */ +@property(copy, nonatomic) NSArray* _Nullable excludeWindowList; + +@end + +/** A class for providing user-specific CDN live audio/video transcoding settings. + */ +__attribute__((visibility("default"))) @interface AgoraLiveTranscodingUser : NSObject +/** User ID of the CDN live host. + */ +@property(assign, nonatomic) NSUInteger uid; +/** Size and the position of the video frame relative to the top left corner. + */ +@property(assign, nonatomic) CGRect rect; +/** The layer index of the video frame. + + From v2.3.0, the Agora SDK supports setting zOrder as 0. + + An integer. The value range is [0,100]. + + - 0: (Default) Bottom layer. + - 100: Top layer. + + Note: If the value is set lower than 0 or higher than 100, the `AgoraErrorCodeInvalidArgument` error occurs. + */ +@property(assign, nonatomic) NSInteger zOrder; +/** The transparency level of the user's video. + + The value ranges between 0.0 and 1.0: + + * 0.0: Completely transparent. + * 1.0: (Default) Opaque. + */ +@property(assign, nonatomic) double alpha; +/** The audio channel of the sound. + + The default value is 0: + + - 0: (Default) Supports dual channels. Depends on the upstream of the host. + - 1: The audio stream of the host uses the FL audio channel. If the upstream of the host uses multiple audio channels, these channels will be mixed into mono first. + - 2: The audio stream of the host uses the FC audio channel. If the upstream of the host uses multiple audio channels, these channels will be mixed into mono first. + - 3: The audio stream of the host uses the FR audio channel. If the upstream of the host uses multiple audio channels, these channels will be mixed into mono first. + - 4: The audio stream of the host uses the BL audio channel. If the upstream of the host uses multiple audio channels, these channels will be mixed into mono first. + - 5: The audio stream of the host uses the BR audio channel. If the upstream of the host uses multiple audio channels, these channels will be mixed into mono first. + +Note: If your setting is not 0, you may need a specialized player. + */ +@property(assign, nonatomic) NSInteger audioChannel; +@end + +/** The advanced feature for high-quality video with a lower bitrate. */ +extern NSString* _Nonnull const LBHQ; +/** The advanced feature for the optimized video encoder. */ +extern NSString* _Nonnull const VEO; + +__attribute__((visibility("default"))) @interface AgoraLiveStreamAdvancedFeature : NSObject + +@property(copy, nonatomic) NSString* _Nullable featureName; + +@property(assign, nonatomic) BOOL opened; +@end + +/** Image properties. + + A class for setting the properties of the watermark and background images in live broadcasting. + */ +__attribute__((visibility("default"))) @interface AgoraImage : NSObject +/** URL address of the image on the broadcasting video. + +The maximum length of this parameter is 1024 bytes. + */ +@property(strong, nonatomic) NSURL* _Nonnull url; +/** Position and size of the image on the broadcasting video in CGRect. + */ +@property(assign, nonatomic) CGRect rect; +@end + +/** The options of the watermark image to be added. + */ +__attribute__((visibility("default"))) @interface WatermarkOptions : NSObject +/** Sets whether or not the watermark image is visible in the local video preview: + + - YES: (Default) The watermark image is visible in preview. + - NO: The watermark image is not visible in preview. + */ +@property(assign, nonatomic) BOOL visibleInPreview; +/** The watermark position in landscape mode of *Rotate the Video*. This parameter contains the following members: + + - `x`: The horizontal offset of the watermark from the top-left corner. + - `y`: The vertical offset of the watermark from the top-left corner. + - `width`: The width (pixel) of the watermark region. + - `height`: The height (pixel) of the watermark region. + */ +@property(assign, nonatomic) CGRect positionInLandscapeMode; +/** The watermark position in portrait mode of *Rotate the Video*. This parameter contains the following members: + + - `x`: The horizontal offset of the watermark from the top-left corner. + - `y`: The vertical offset of the watermark from the top-left corner. + - `width`: The width (pixel) of the watermark region. + - `height`: The height (pixel) of the watermark region. + */ +@property(assign, nonatomic) CGRect positionInPortraitMode; +@end + +/** A class for managing user-specific CDN live audio/video transcoding settings. + */ +__attribute__((visibility("default"))) @interface AgoraLiveTranscoding : NSObject +/** The size of the video (width and height in pixels). + +- When pushing video streams to the CDN, note the following: + + - The value range of the width is [64,1920]. If the value is less than 64, + Agora server automatically adjusts it to 64; if the value is greater than + 1920, Agora server automatically adjusts it to 1920. + - The value range of the height is [64,1080]. If the value is less than 64, + Agora server automatically adjusts it to 64; if the value is greater than + 1080, Agora server automatically adjusts it to 1080. + +- When pushing audio streams to the CDN, set the width and height as 0. + */ +@property(assign, nonatomic) CGSize size; +/** Bitrate of the CDN live output video stream. + +The default value is 400 Kbps. + +Set this parameter according to the Video Bitrate Table. If you set a bitrate beyond the proper range, the SDK automatically adapts it to a value within the range. + */ +@property(assign, nonatomic) NSInteger videoBitrate; +/** Frame rate of the CDN live output video stream. + +The default value is 15 fps, and the value range is (0,30]. + + @note The Agora server adjusts any value over 30 to 30. + */ +@property(assign, nonatomic) NSInteger videoFramerate; +/** Latency mode. **DEPRECATED** from v2.8.0 + + * YES: Low latency with unassured quality. + * NO:(Default)High latency with assured quality. + */ +@property(assign, nonatomic) BOOL lowLatency; +/** Video GOP in frames. The default value is 30 fps. */ +@property(assign, nonatomic) NSInteger videoGop; +/** Video codec profile type + +Set it as 66, 77, or 100 (default), see [AgoraVideoCodecProfileType](AgoraVideoCodecProfileType). + +If you set this parameter to other values, Agora adjusts it to the default value of 100. + */ +@property(assign, nonatomic) AgoraVideoCodecProfileType videoCodecProfile; + +/** The video codec type of the output video stream. See AgoraVideoCodecTypeForStream. + + @since v3.2.0 + */ +@property(assign, nonatomic) AgoraVideoCodecTypeForStream videoCodecType; + +/** An AgoraLiveTranscodingUser object managing the user layout configuration in the CDN live stream. Agora supports a maximum of 17 transcoding users in a CDN live stream channel. See AgoraLiveTranscodingUser. + */ +@property(copy, nonatomic) NSArray* _Nullable transcodingUsers; + +/** Reserved property. Extra user-defined information to send SEI for the H.264/H.265 video stream to the CDN live client. Maximum length: 4096 bytes. For more information on SEI, see [SEI-related questions](https://docs.agora.io/en/faq/sei). + */ +@property(copy, nonatomic) NSString* _Nullable transcodingExtraInfo; +/** The watermark image added to the CDN live publishing stream. + +The audience of the CDN live publishing stream can see the watermark. Ensure that the format of the image is PNG. + +See AgoraImage for the definition of the watermark. + */ +@property(strong, nonatomic) AgoraImage* _Nullable watermark; +/** The background image added to the CDN live publishing stream. + +The audience of the CDN live publishing stream can see the background image. See AgoraImage for the definition of the background image. + */ +@property(strong, nonatomic) AgoraImage* _Nullable backgroundImage; +/** The background color in RGB hex. + +Value only. Do not include a preceding #. For example, 0xFFB6C1 (light pink). The default value is 0x000000 (black). + +COLOR_CLASS is a general name for the type: + +* iOS: UIColor +* macOS: NSColor + */ +@property(strong, nonatomic) COLOR_CLASS* _Nullable backgroundColor; + +/** Self-defined audio sample rate: AgoraAudioSampleRateType. + */ +@property(assign, nonatomic) AgoraAudioSampleRateType audioSampleRate; +/** Bitrate (Kbps) of the CDN live audio output stream. The default value is 48, and the highest value is 128. + */ +@property(assign, nonatomic) NSInteger audioBitrate; +/** The number of audio channels for the CDN live stream. + + Agora recommends choosing 1 (mono), or 2 (stereo) audio channels. Special players are required if you choose 3, 4, or 5. + + * 1: (Default) Mono + * 2: Stereo + * 3: Three audio channels + * 4: Four audio channels + * 5: Five audio channels + */ +@property(assign, nonatomic) NSInteger audioChannels; +/** + Audio codec profile. See AgoraAudioCodecProfileType. + + The default value is AgoraAudioCodecProfileLCAAC(0). + */ +@property(assign, nonatomic) AgoraAudioCodecProfileType audioCodecProfile; + +/** Creates a default transcoding object. + + @return Default AgoraLiveTranscoding object. + */ ++ (AgoraLiveTranscoding* _Nonnull)defaultTranscoding; + +/** Adds a user displaying the video in CDN live. + + @param user The transcoding user. See AgoraLiveTranscodingUser. + + @return - 0: Success. + - < 0: Failure. + */ +- (int)addUser:(AgoraLiveTranscodingUser* _Nonnull)user; + +/** Removes a user from CDN live. + + @param uid The user ID of the user to remove from CDN live. + + @return - 0: Success. + - < 0: Failure. + */ +- (int)removeUser:(NSUInteger)uid; + +- (void)setAdvancedFeatures:(NSString* _Nonnull)featureName opened:(BOOL)opened; + +- (NSArray* _Nullable)getAdvancedFeatures; + +@end + +/** Configuration of the imported interactive live streaming. + */ +__attribute__((visibility("default"))) @interface AgoraLiveInjectStreamConfig : NSObject +/** Size of the added stream to the interactive live streaming. + +The default value is 0; same size as the original stream. + */ +@property(assign, nonatomic) CGSize size; +/** Video GOP of the added stream to the interactive live streaming. + +The default value is 30 fps. + */ +@property(assign, nonatomic) NSInteger videoGop; +/** Video frame rate of the added stream to the interactive live streaming. + +The default value is 15 fps. + */ +@property(assign, nonatomic) NSInteger videoFramerate; +/** Video bitrate of the added stream to the interactive live streaming. + +The default value is 400 Kbps. + +The setting of the video bitrate is closely linked to the resolution. If the video bitrate you set is beyond a reasonable range, the SDK will set it within a reasonable range instead. + */ +@property(assign, nonatomic) NSInteger videoBitrate; + +/** Audio sample rate of the added stream to the interactive live streaming. + +The default value is 48000 Hz. See AgoraAudioSampleRateType for details. + +**Note:** + +Agora recommends using the default value. + */ +@property(assign, nonatomic) AgoraAudioSampleRateType audioSampleRate; +/** Audio bitrate of the added stream to the interactive live streaming. + +The default value is 48 Kbps. + +**Note:** + +Agora recommends using the default value. + */ +@property(assign, nonatomic) NSInteger audioBitrate; +/** Number of audio channels to add to the interactive live streaming. The values are 1 and 2. + +The default value is 1. + +**Note:** + +Agora recommends using the default value. + */ +@property(assign, nonatomic) NSInteger audioChannels; + +/** Creates a default stream configuration object. + + @return Default stream configuration object. + */ ++ (AgoraLiveInjectStreamConfig* _Nonnull)defaultConfig; + +@end + +/** The configuration of camera capturer. + */ +__attribute__((visibility("default"))) @interface AgoraCameraCapturerConfiguration : NSObject +/** This preference will balance the performance and preview quality by adjusting camera output frame size. See AgoraCameraCaptureOutputPreference. + */ +@property(assign, nonatomic) AgoraCameraCaptureOutputPreference preference; +/** The width (px) of the video image captured by the local camera. To + customize the width of the video image, set preference as + `AgoraCameraCaptureOutputPreferenceManual(3)` first, and then use this parameter. + + @since v3.3.0 + */ +@property(assign, nonatomic) int captureWidth; +/** The height (px) of the video image captured by the local camera. To + customize the height of the video image, set preference as + `AgoraCameraCaptureOutputPreferenceManual(3)` first, and then use this parameter. + + @since v3.3.0 + */ +@property(assign, nonatomic) int captureHeight; + +#if defined(TARGET_OS_IOS) && TARGET_OS_IOS +/** The camera direction. See AgoraCameraDirection: + + - AgoraCameraDirectionRear: The rear camera. + - AgoraCameraDirectionFront: The front camera. + + @note This method applies to iOS only. + */ +@property(assign, nonatomic) AgoraCameraDirection cameraDirection; + +/** Sets the local camera capture behavior. + + Before calling this method, ensure that you have called + [setCameraCapturerConfiguration]([AgoraRtcEngineKit setCameraCapturerConfiguration:]) + to set the camera capture configuration as `AgoraCameraCaptureOutputPreferenceManual(3)`. + + @note This method applies to iOS only. + + @param size The size of the video image captured by the local camera. + @param facing The camera direction. See AgoraCameraDirection. + + @return An initialized AgoraCameraCapturerConfiguration object. + */ +- (instancetype _Nonnull)initWithSize:(CGSize)size facing:(AgoraCameraDirection)facing; + +/** Sets the local camera capture behavior. + + Before calling this method, ensure that you have called + [setCameraCapturerConfiguration]([AgoraRtcEngineKit setCameraCapturerConfiguration:]) + to set the camera capture configuration as `AgoraCameraCaptureOutputPreferenceManual(3)`. + + @note This method applies to iOS only. + + @param width The width (px) of the video image captured by the local camera. + @param height The height (px) of the video image captured by the local camera. + @param facing The camera direction. See AgoraCameraDirection. + + @return An initialized AgoraCameraCapturerConfiguration object. + */ +- (instancetype _Nonnull)initWithWidth:(NSInteger)width height:(NSInteger)height facing:(AgoraCameraDirection)facing; +#endif + +#if (!(TARGET_OS_IPHONE) && (TARGET_OS_MAC)) +/** Sets the local camera capture behavior. + + Before calling this method, ensure that you have called + [setCameraCapturerConfiguration]([AgoraRtcEngineKit setCameraCapturerConfiguration:]) + to set the camera capture configuration as `AgoraCameraCaptureOutputPreferenceManual(3)`. + + @note This method applies to macOS only. + + @param size The size of the video image captured by the local camera. + + @return An initialized `AgoraCameraCapturerConfiguration` object. + */ +- (instancetype _Nonnull)initWithSize:(CGSize)size; + +/** Sets the local camera capture behavior. + + Before calling this method, ensure that you have called + [setCameraCapturerConfiguration]([AgoraRtcEngineKit setCameraCapturerConfiguration:]) + to set the camera capture configuration as `AgoraCameraCaptureOutputPreferenceManual(3)`. + + @note This method applies to macOS only. + + @param width The width (px) of the video image captured by the local camera. + @param height The height (px) of the video image captured by the local camera. + + @return An initialized `AgoraCameraCapturerConfiguration` object. + */ +- (instancetype _Nonnull)initWithWidth:(NSInteger)width height:(NSInteger)height; +#endif + +@end + +#if (!(TARGET_OS_IPHONE) && (TARGET_OS_MAC)) + +/** AgoraRtcDeviceInfo array. (macOS only) + */ +__attribute__((visibility("default"))) @interface AgoraRtcDeviceInfo : NSObject +@property(assign, nonatomic) int __deprecated index; + +/** Device type: AgoraMediaDeviceType. + */ +@property(assign, nonatomic) AgoraMediaDeviceType type; + +/** Device ID. + */ +@property(copy, nonatomic) NSString* _Nullable deviceId; + +/** Device name. + */ +@property(copy, nonatomic) NSString* _Nullable deviceName; +@end + +/** The image content of the thumbnail or icon. (macOS only) + + @since v3.5.2 + + @note The default image is in the RGBA format. If you need to use another + format, you need to convert the image on your own. + */ +__attribute__((visibility("default"))) @interface AgoraThumbImageBuffer : NSObject +/** + The NSImage of the thumbnail or icon. + */ +@property(strong, nonatomic, readonly) NSImage* _Nonnull image; +/** + The buffer of the thumbnail or icon. + */ +@property(copy, nonatomic) NSData* _Nonnull buffer; +/** + The buffer length (bytes) of the thumbnail or icon. + */ +@property(assign, nonatomic) NSUInteger length; +/** + The actual width (px) of the thumbnail or icon. + */ +@property(assign, nonatomic) NSUInteger width; +/** + The actual height (px) of the thumbnail or icon. + */ +@property(assign, nonatomic) NSUInteger height; + +@end +/** + The AgoraScreenCaptureSourceInfo interface. (macOS only) + + @since v3.5.2 + */ +__attribute__((visibility("default"))) @interface AgoraScreenCaptureSourceInfo : NSObject +/** The type of the shared target. See ScreenCaptureSourceType. */ +@property(assign, nonatomic) AgoraScreenCaptureSourceType type; +/** The window ID for a window or the display ID for a screen. */ +@property(assign, nonatomic) CGWindowID sourceId; +/** The name of the window or screen. UTF-8 encoding. */ +@property(copy, nonatomic) NSString* _Nonnull sourceName; +/** The image content of the thumbnail. See AgoraThumbImageBuffer. */ +@property(strong, nonatomic) AgoraThumbImageBuffer* _Nonnull thumbImage; +/** The image content of the icon. See AgoraThumbImageBuffer. */ +@property(strong, nonatomic) AgoraThumbImageBuffer* _Nullable iconImage; +/** The process to which the window belongs. UTF-8 encoding. */ +@property(copy, nonatomic) NSString* _Nonnull processPath; +/** The title of the window. UTF-8 encoding. */ +@property(copy, nonatomic) NSString* _Nonnull sourceTitle; +/** Determines whether the screen is the primary display: + + - YES: The screen is the primary display. + - NO: The screen is not the primary display. + */ +@property(assign, nonatomic) BOOL primaryMonitor; + +@end + +#endif + +/** Video frame containing the Agora SDK's encoded video data. + */ +__attribute__((visibility("default"))) @interface AgoraVideoFrame : NSObject +/** Video format: + + * 1: I420 + * 2: BGRA + * 3: NV21 + * 4: RGBA + * 5: IMC2 + * 7: ARGB + * 8: NV12 + * 12: iOS texture (CVPixelBufferRef) + * 16: I422 + */ +@property(assign, nonatomic) NSInteger format; + +/** Timestamp of the incoming video frame (ms). + +An incorrect timestamp results in frame loss or unsynchronized audio and video. + + */ +@property(assign, nonatomic) CMTime time; // Time for this frame. + +@property(assign, nonatomic) int stride DEPRECATED_MSG_ATTRIBUTE("use strideInPixels instead"); + +/** Line spacing of the incoming video frame, which must be in pixels instead of bytes. For textures, it is the width of the texture. + */ +@property(assign, nonatomic) int strideInPixels; // Number of pixels between two consecutive rows. Note: in pixel, not byte. Not used for iOS textures. + +/** Height of the incoming video frame + */ +@property(assign, nonatomic) int height; // Number of rows of pixels. Not used for iOS textures. + +/** CVPixelBuffer + */ +@property(assign, nonatomic) CVPixelBufferRef _Nullable textureBuf; + +/** Raw data buffer + */ +@property(strong, nonatomic) NSData* _Nullable dataBuf; // Raw data buffer. Not used for iOS textures. + +/** (Optional) The number of pixels trimmed from the left. The default value is 0. + */ +@property(assign, nonatomic) int cropLeft; // Number of pixels to crop on the left boundary. +/** (Optional) The number of pixels trimmed from the top. The default value is 0. + */ +@property(assign, nonatomic) int cropTop; // Number of pixels to crop on the top boundary. +/** (Optional) The number of pixels trimmed from the right. The default value is 0. + */ +@property(assign, nonatomic) int cropRight; // Number of pixels to crop on the right boundary. +/** (Optional) The number of pixels trimmed from the bottom. The default value is 0. + */ +@property(assign, nonatomic) int cropBottom; // Number of pixels to crop on the bottom boundary. +/** (Optional) The clockwise rotation of the incoming video frame. + +Optional values: 0, 90, 180, or 270. The default value is 0. + */ +@property(assign, nonatomic) int rotation; // 0, 90, 180, 270. See document for rotation calculation. +/* Note + * 1. strideInPixels + * Stride is in pixels, not bytes. + * 2. About the frame width and height. + * No field is defined for the width. However, it can be deduced by: + * croppedWidth = (strideInPixels - cropLeft - cropRight) + * And + * croppedHeight = (height - cropTop - cropBottom) + * 3. About crop. + * _________________________________________________________________..... + * | ^ | ^ + * | | | | + * | cropTop | | + * | | | | + * | v | | + * | ________________________________ | | + * | | | | | + * | | | | | + * |<-- cropLeft -->| valid region |<- cropRight ->| + * | | | | height + * | | | | + * | |_____________________________ | | | + * | ^ | | + * | | | | + * | cropBottom | | + * | | | | + * | v | v + * _________________________________________________________________...... + * | | + * |<---------------- strideInPixels ----------------------------->| + * + * If your buffer contains garbage data, you can crop them. For example, if the frame size is + * 360 * 640, often the buffer stride is 368, that is, the extra 8 pixels on the + * right are for padding, and should be removed. In this case, you can set: + * strideInPixels = 368; + * height = 640; + * cropRight = 8; + * // cropLeft, cropTop, cropBottom are set to a default of 0 + */ +@end + +/** The definition of AgoraChannelMediaRelayInfo. + */ +__attribute__((visibility("default"))) @interface AgoraChannelMediaRelayInfo : NSObject +/** The token that enables the user to join the channel. + */ +@property(copy, nonatomic) NSString* _Nullable token; +/** The channel name. + */ +@property(copy, nonatomic) NSString* _Nullable channelName; +/** The user ID. + */ +@property(assign, nonatomic) NSUInteger uid; +/** Initializes the AgoraChannelMediaRelayInfo object + + @param token The token that enables the user to join the channel. + */ +- (instancetype _Nonnull)initWithToken:(NSString* _Nullable)token; +@end + +/** The configurations for the data stream. + + The following table shows the relationship between the `syncWithAudio` + parameter and the `ordered` parameter: + + | `syncWithAudio` | `ordered` | SDK behaviors | + | :-------------- | :-------- | :----------------------------------------------------------- | + | `NO` | `NO` | The SDK triggers the `receiveStreamMessageFromUid` callback immediately after the receiver receives a data packet. | + | `YES` | `NO` |
      88. If the data packet delay is within the audio delay, the SDK triggers the `receiveStreamMessageFromUid` callback when the synchronized audio packet is played out.
      89. If the data packet delay exceeds the audio delay, the SDK triggers the `receiveStreamMessageFromUid` callback as soon as the data packet is received. In this case, the data packet is not synchronized with the audio packet.
      90. | + | `NO` | `YES` |
      91. If the delay of a data packet is within five seconds, the SDK corrects the order of the data packet.
      92. If the delay of a data packet exceeds five seconds, the SDK discards the data packet.
      93. | + | `YES` | `YES` |
      94. If the delay of a data packet is within the audio delay, the SDK corrects the order of the data packet.
      95. If the delay of a data packet exceeds the audio delay, the SDK discards this data packet.
      96. | + */ +__attribute__((visibility("default"))) @interface AgoraDataStreamConfig : NSObject + +/** Whether the SDK guarantees that the receiver receives the data in the sent + order. + + - `YES`: Guarantee that the receiver receives the data in the sent order. + - `NO`: Do not guarantee that the receiver receives the data in the sent order. + + Do not set this parameter to `YES` if you need the receiver to receive + the data immediately. + */ +@property(assign, nonatomic) BOOL ordered; + +/** Whether to synchronize the data packet with the published audio packet. + + - `YES`: Synchronize the data packet with the audio packet. + - `NO`: Do not synchronize the data packet with the audio packet. + + When you set the data packet to synchronize with the audio, then if the data + packet delay is within the audio delay range, the SDK triggers the `receiveStreamMessageFromUid` + callback when the synchronized audio packet is played out. Do not set this + parameter as `YES` if you need the receiver to receive the data packet + immediately. Agora recommends that you set this parameter to `YES` only + when you need to implement specific functions, for example lyric + synchronization. + */ +@property(assign, nonatomic) BOOL syncWithAudio; +@end + +/** The definition of AgoraChannelMediaRelayConfiguration. + + */ +__attribute__((visibility("default"))) @interface AgoraChannelMediaRelayConfiguration : NSObject +/** The information of the destination channel: AgoraChannelMediaRelayInfo. It contains the following members: + + - `channelName`: The name of the destination channel. + - `uid`: The unique ID to identify the relay stream in the destination channel. The value ranges from 0 to (232-1). Do not set this parameter as the `uid` of the host in the destination channel, and ensure that this `uid` is different from any other `uid` in the channel. The default value is 0, which means the SDK generates a random UID. + - `token`: The token for joining the destination channel. It is generated with the `channelName` and `uid` you set in `destinationInfos`. + + - If you have not enabled the App Certificate, set this parameter as the default value `nil`, which means the SDK applies the App ID. + - If you have enabled the App Certificate, you must use the `token` generated with the `channelName` and `uid`. + */ +@property(strong, nonatomic, readonly) NSDictionary* _Nullable destinationInfos; +/** The information of the source channel: AgoraChannelMediaRelayInfo. It contains the following members: + + - `channelName`: The name of the source channel. The default value is `nil`, which means the SDK applies the name of the current channel. + - `uid`: The unique ID to identify the relay stream in the source channel. The default value is 0, which means the SDK generates a random UID. You must set it as 0. + - `token`: The token for joining the source channel. It is generated with the `channelName` and `uid` you set in `sourceInfo`. + + - If you have not enabled the App Certificate, set this parameter as the default value `nil`, which means the SDK applies the App ID. + - If you have enabled the App Certificate, you must use the `token` generated with the `channelName` and `uid`, and the `uid` must be set as 0. + */ +@property(strong, nonatomic) AgoraChannelMediaRelayInfo* _Nonnull sourceInfo; +/** Sets the information of the destination channel. + + If you want to relay the media stream to multiple channels, call this method as many times (at most four). + + @param destinationInfo The information of the destination channel: AgoraChannelMediaRelayInfo. It contains the following members: + + - `channelName`: The name of the destination channel. + - `uid`: The unique ID to identify the relay stream in the destination channel. The value ranges from 0 to (232-1). Do not set this parameter as the `uid` of the host in the destination channel, and ensure that this `uid` is different from any other `uid` in the channel. The default value is 0, which means the SDK generates a random UID. + - `token`: The token for joining the destination channel. It is generated with the `channelName` and `uid` you set in `destinationInfo`. + + - If you have not enabled the App Certificate, set this parameter as the default value `nil`, which means the SDK applies the App ID. + - If you have enabled the App Certificate, you must use the `token` generated with the `channelName` and `uid`. + + @param channelName The name of the destination channel. Ensure that the value of this parameter is the same as that of the `channelName` member in `destinationInfo`. + + @return - YES: Success. + - NO: Failure. + */ +- (BOOL)setDestinationInfo:(AgoraChannelMediaRelayInfo* _Nonnull)destinationInfo forChannelName:(NSString* _Nonnull)channelName; +/** Removes the destination channel. + + @param channelName The name of the destination channel. + + @return - YES: Success. + - NO: Failure. + */ +- (BOOL)removeDestinationInfoForChannelName:(NSString* _Nonnull)channelName; +@end + +/** The image enhancement options in [setBeautyEffectOptions]([AgoraRtcEngineKit setBeautyEffectOptions:options:]). */ +__attribute__((visibility("default"))) @interface AgoraBeautyOptions : NSObject + +/** The lightening contrast level + +[AgoraLighteningContrastLevel](AgoraLighteningContrastLevel), used with the lighteningLevel property: + +- 0: Low contrast level. +- 1: (Default) Normal contrast level. +- 2: High contrast level. +*/ +@property(nonatomic, assign) AgoraLighteningContrastLevel lighteningContrastLevel; + +/** The brightness level. + +The default value is 0.7. The value ranges from 0.0 (original) to 1.0. + */ +@property(nonatomic, assign) float lighteningLevel; + +/** The sharpness level. + +The default value is 0.5. The value ranges from 0.0 (original) to 1.0. This parameter is usually used to remove blemishes. + */ +@property(nonatomic, assign) float smoothnessLevel; + +/** The redness level. + +The default value is 0.1. The value ranges from 0.0 (original) to 1.0. This parameter adjusts the red saturation level. +*/ +@property(nonatomic, assign) float rednessLevel; + +@end + +/** Since v3.4.5. The custom background image. + */ +__attribute__((visibility("default"))) @interface AgoraVirtualBackgroundSource : NSObject + +/** The type of the custom background image. See AgoraVirtualBackgroundSourceType. + */ +@property(nonatomic, assign) AgoraVirtualBackgroundSourceType backgroundSourceType; + +/** The color of the custom background image. The format is a hexadecimal + integer defined by RGB, without the # sign, such as `0xFFB6C1` for light pink. + The default value is `0xFFFFFF`, which signifies white. The value range is + [0x000000,0xFFFFFF]. If the value is invalid, the SDK replaces the original + background image with a white background image. +

        Note: This parameter takes effect only when the type of the custom + background image is AgoraVirtualBackgroundColor.

        + */ +@property(nonatomic, assign) NSUInteger color; + +/** The local absolute path of the custom background image. PNG and JPG formats + are supported. If the path is invalid, the SDK replaces the original + background image with a white background image. +

        Note: This parameter takes effect only when the type of the custom + background image is AgoraVirtualBackgroundImg.

        + */ +@property(nonatomic, copy) NSString* _Nullable source; + +/** The degree of blurring applied to the custom background image. See AgoraBlurDegree. +

        Note: This parameter takes effect only when the type of the custom + background image is AgoraVirtualBackgroundBlur.

        + + @since v3.5.1 + */ +@property(nonatomic, assign) AgoraBlurDegree blur_degree; + +@end + +/** The user information, including the user ID and user account. */ +__attribute__((visibility("default"))) @interface AgoraUserInfo : NSObject +/** The user ID of a user. + */ +@property(nonatomic, assign) NSUInteger uid; +/** The user account of a user. + */ +@property(copy, nonatomic) NSString* _Nullable userAccount; +@end + +/** The channel media options. + */ +__attribute__((visibility("default"))) @interface AgoraRtcChannelMediaOptions : NSObject +/** Determines whether to automatically subscribe to all remote audio streams + when the user joins a channel. + + - YES: (Default) Subscribe. + - NO: Do not subscribe. + + This member variable serves a similar function to the `muteAllRemoteAudioStreams` + method. After joining the channel, you can call the + `muteAllRemoteAudioStreams` method to set whether to subscribe to all remote + audio streams in the channel. + */ +@property(nonatomic, assign) BOOL autoSubscribeAudio; +/** Determines whether to automatically subscribe to all remote video streams + when the user joins a channel. + + - YES: (Default) Subscribe. + - NO: Do not subscribe. + + This member variable serves a similar function to the `muteAllRemoteVideoStreams` + method. After joining the channel, you can call the + `muteAllRemoteVideoStreams` method to set whether to subscribe to all remote + video streams in the channel. + */ +@property(nonatomic, assign) BOOL autoSubscribeVideo; +/** Sets whether to publish the local audio stream when the user joins a channel: + + - `YES`: (Default) Publish. + - `NO`: Do not publish. + + This member serves a similar function to the `muteLocalAudioStream` method. + After the user joins the channel, you can call the `muteLocalAudioStream` + method to set whether to publish the local audio stream in the channel. + + @since v3.4.5 + */ +@property(nonatomic, assign) BOOL publishLocalAudio; +/** Sets whether to publish the local video stream when the user joins a channel: + + - `YES`: (Default) Publish. + - `NO`: Do not publish. + + This member serves a similar function to the `muteLocalVideoStream` method. + After the user joins the channel, you can call the `muteLocalVideoStream` + method to set whether to publish the local video stream in the channel. + + @since v3.4.5 + */ +@property(nonatomic, assign) BOOL publishLocalVideo; +@end + +/** AgoraFacePositionInfo array. + */ +__attribute__((visibility("default"))) @interface AgoraFacePositionInfo : NSObject + +/** The x coordinate (px) of the human face in the local video. Taking the top left corner of the captured video as the origin, the x coordinate represents the relative lateral displacement of the top left corner of the human face to the origin. + */ +@property(assign, nonatomic) NSInteger x; + +/** The y coordinate (px) of the human face in the local video. Taking the top left corner of the captured video as the origin, the y coordinate represents the relative longitudinal displacement of the top left corner of the human face to the origin. + */ +@property(assign, nonatomic) NSInteger y; + +/** The width (px) of the human face in the captured video. + */ +@property(assign, nonatomic) NSInteger width; + +/** The height (px) of the human face in the captured video. + */ +@property(assign, nonatomic) NSInteger height; + +/** The distance (cm) between the human face and the screen. + */ +@property(assign, nonatomic) NSInteger distance; +@end + +/** **Since** v3.4.0. Recording configuration, which is set in [startAudioRecordingWithConfig]([AgoraRtcEngineKit startAudioRecordingWithConfig:]). */ +__attribute__((visibility("default"))) @interface AgoraAudioRecordingConfiguration : NSObject + +/** The absolute path (including the filename extensions) of the recording file. For example: `/var/mobile/Containers/Data/audio.aac`. + + @note Ensure that the path you specify exists and is writable. + */ +@property(copy, nonatomic) NSString* _Nullable filePath; + +/** Audio recording quality. See AgoraAudioRecordingQuality. + + @note This parameter applies for AAC files only. + */ +@property(assign, nonatomic) AgoraAudioRecordingQuality recordingQuality; + +/** Recording content. See AgoraAudioRecordingPosition. + */ +@property(assign, nonatomic) AgoraAudioRecordingPosition recordingPosition; + +/** Recording sample rate (Hz). The following values are supported: + + - 16000 + - (Default) 32000 + - 44100 + - 48000 + + @note If this parameter is set to `44100` or `48000`, for better recording effects, Agora recommends recording WAV + files or AAC files whose `recordingQuality` is `AgoraAudioRecordingQualityMedium` or `AgoraAudioRecordingQualityHigh`. + */ +@property(assign, nonatomic) NSInteger recordingSampleRate; +@end + +//__attribute__((visibility("default"))) @interface AgoraRtcChannelInfo : NSObject +// +//@property (nonatomic, copy) NSString * _Nonnull channelId; +// +//@end +/** The configuration of the log files that the SDK outputs. + */ +__attribute__((visibility("default"))) @interface AgoraLogConfig : NSObject +/** The absolute path of log files. + + @since v3.3.0 + + Ensure that the directory for the log + files exists and is writable. The default file path is as follows: + + - iOS: `App Sandbox/Library/caches/agorasdk.log` + - macOS: + - Sandbox enabled: `App Sandbox/Library/Logs/agorasdk.log`, such as + `/Users//Library/Containers//Data/Library/Logs/agorasdk.log` + - Sandbox disabled: `~/Library/Logs/agorasdk.log` + */ +@property(copy, nonatomic) NSString* _Nullable filePath; +/** The size (KB) of a log file. + + @since v3.3.0 + + The default value is 1024 KB. If you set + this parameter to 1024 KB, the SDK outputs at most 5 MB log files; if + you set it to less than 1024 KB, the setting is invalid, and the maximum + size of a log file is still 1024 KB. + */ +@property(assign, nonatomic) NSInteger fileSize; +/** The output log level of the SDK. See details in AgoraLogLevel. + + @since v3.3.0 + + For example, if you set the log level to `AgoraLogLevelWarn`, the SDK outputs the logs + within levels `AgoraLogLevelFatal`, `AgoraLogLevelError`, and `AgoraLogLevelWarn`. + */ +@property(assign, nonatomic) AgoraLogLevel level; +@end +/** Configurations for the AgoraRtcEngineKit instance. + */ +__attribute__((visibility("default"))) @interface AgoraRtcEngineConfig : NSObject +/** The App ID issued to you by Agora. See [How to get the App ID](https://docs.agora.io/en/Agora%20Platform/token#get-an-app-id). Only users in apps with the same App ID can join the same channel and communicate with each other. Use an App ID to create only one AgoraRtcEngineKit instance. To change your App ID, call [destroy]([AgoraRtcEngineKit destroy]) to `destroy` the current AgoraRtcEngineKit instance, and after `destroy` returns 0, call [sharedEngineWithConfig]([AgoraRtcEngineKit sharedEngineWithConfig:delegate:]) to create an AgoraRtcEngineKit instance with the new App ID. + */ +@property(copy, nonatomic) NSString* _Nullable appId; +/** The region for connection. This advanced feature applies to scenarios that have regional restrictions.

        For the regions that Agora supports, see AgoraAreaCode. The area codes support bitwise operation. After specifying the region, the SDK connects to the Agora servers within that region.

        + */ +@property(nonatomic, assign) NSUInteger areaCode; +/** The configuration of the log files that the SDK outputs. See AgoraLogConfig. + +@since v3.3.0. + +By default, the SDK outputs five log files, `agorasdk.log`, `agorasdk_1.log`, +`agorasdk_2.log`, `agorasdk_3.log`, `agorasdk_4.log`, each with a default +size of 1024 KB. These log files are encoded in UTF-8. The SDK writes the +latest logs in `agorasdk.log`. When `agorasdk.log` is full, the SDK deletes +the log file with the earliest modification time among the other four, +renames `agorasdk.log` to the name of the deleted log file, and creates a +new `agorasdk.log` to record latest logs. + */ +@property(strong, nonatomic) AgoraLogConfig* _Nullable logConfig; +@end + +/** Configurations of built-in encryption schemas. + */ +__attribute__((visibility("default"))) @interface AgoraEncryptionConfig : NSObject + +/** Encryption mode. The default encryption mode is `AgoraEncryptionModeAES128GCM2`. See AgoraEncryptionMode. + */ +@property(assign, nonatomic) AgoraEncryptionMode encryptionMode; + +/** Encryption key in string type with unlimited length. Agora recommends + using a 32-byte key. + +**Note** + +If you do not set an encryption key or set it as `nil`, you cannot use the built-in encryption, and the SDK returns `-2` (`AgoraErrorCodeInvalidArgument`). + */ +@property(copy, nonatomic) NSString* _Nullable encryptionKey; +/** The salt with the length of 32 bytes. Agora recommends using OpenSSL to generate the salt on your + server. For details, see *Media Stream Encryption*. +

        Note: This parameter is only valid when you set the encryption mode + as AgoraEncryptionModeAES128GCM2 or + AgoraEncryptionModeAES256GCM2. In this case, ensure that this + parameter is not nil or 0, and the data length is + 32 bytes.

        + */ +@property(strong, nonatomic) NSData* _Nullable encryptionKdfSalt; +@end + +/** The detailed options of a user. + */ +__attribute__((visibility("default"))) @interface AgoraClientRoleOptions : NSObject + +/** The latency level of an audience member in a interactive live streaming. See [AgoraAudienceLatencyLevelType](AgoraAudienceLatencyLevelType). + */ +@property(assign, nonatomic) AgoraAudienceLatencyLevelType audienceLatencyLevel; +@end +/** + Information for the recording file. + + @since v3.5.2 + */ +__attribute__((visibility("default"))) @interface AgoraMediaRecorderInfo : NSObject + +/** The absolute path of the recording file. + */ +@property(copy, nonatomic) NSString* _Nonnull recorderFileName; +/** The recording duration, in milliseconds. + */ +@property(assign, nonatomic) NSUInteger durationMs; +/** The size in bytes of the recording file. + */ +@property(assign, nonatomic) NSUInteger fileSize; + +@end +/** + Configurations for the local audio and video recording. + + @since v3.5.2 + */ +__attribute__((visibility("default"))) @interface AgoraMediaRecorderConfiguration : NSObject + +/** The absolute path (including the filename extensions) of the recording file. For example, `/App Sandbox/Library/Caches/example.mp4` + on iOS and `/Library/Logs/example.mp4` on macOS. + + @note Ensure that the specified path exists and is writable. + */ +@property(copy, nonatomic) NSString* _Nonnull storagePath; +/** The format of the recording file. See AgoraMediaRecorderContainerFormat. + */ +@property(assign, nonatomic) AgoraMediaRecorderContainerFormat containerFormat; +/** The recording content. See AgoraMediaRecorderStreamType. + */ +@property(assign, nonatomic) AgoraMediaRecorderStreamType streamType; +/** The maximum recording duration, in milliseconds. The default value is 120000. + */ +@property(assign, nonatomic) NSUInteger maxDurationMs; +/** The interval (ms) of updating the recording information. The value range is [1000,10000]. + Based on the set value of `recorderInfoUpdateInterval`, the SDK triggers the [informationDidUpdated]([AgoraMediaRecorderDelegate mediaRecorder:informationDidUpdated:]) + callback to report the updated recording information. + */ +@property(assign, nonatomic) NSUInteger recorderInfoUpdateInterval; + +@end + +/** The local encoded video frame. (iOS only) + + @since v3.4.5 + */ +__attribute__((visibility("default"))) @interface AgoraVideoEncodedFrame : NSObject + +/** The video codec type. See AgoraVideoCodecType. + */ +@property(assign, nonatomic) AgoraVideoCodecType codecType; +/** The width (px) of the video. */ +@property(assign, nonatomic) NSInteger width; +/** The height (px) of the video. */ +@property(assign, nonatomic) NSInteger height; +/** The video buffer. */ +@property(assign, nonatomic) void* _Nullable buffer; +/** The length (in bytes) of the video buffer.*/ +@property(assign, nonatomic) NSUInteger length; +/** The video frame type. See AgoraVideoEncodeType. */ +@property(assign, nonatomic) AgoraVideoEncodeType frameType; +/** The clockwise rotation angle of the video frame. See AgoraVideoRotation. */ +@property(assign, nonatomic) AgoraVideoRotation rotation; +/** The Unix timestamp (ms) when the video frame is rendered. This timestamp + can be used to guide the rendering of the video frame. This parameter is + required. + */ +@property(assign, nonatomic) int64_t renderTimeMs; + +@end + +/** The video frame. (iOS only) + + @since v3.4.5 + */ +__attribute__((visibility("default"))) @interface AgoraVideoDataFrame : NSObject +/** The color video format. See AgoraVideoFrameType. + */ +@property(assign, nonatomic) AgoraVideoFrameType frameType; +/** The width (px) of the video. + */ +@property(assign, nonatomic) NSInteger width; // width of video frame +/** The height (px) of the video. + */ +@property(assign, nonatomic) NSInteger height; // height of video frame +/** For YUV data, the line span of the Y buffer; for RGBA data, the total + data length. + */ +@property(assign, nonatomic) NSInteger yStride; // stride of Y data buffer +/** For YUV data, the line span of the U buffer; for RGBA data, the value is 0. + */ +@property(assign, nonatomic) NSInteger uStride; // stride of U data buffer +/** For YUV data, the line span of the V buffer; for RGBA data, the value is 0. + */ +@property(assign, nonatomic) NSInteger vStride; // stride of V data buffer +/** For YUV data, the pointer to the Y buffer; for RGBA data, the data buffer. + */ +@property(assign, nonatomic) void* _Nullable yBuffer; // Y data buffer +/** For YUV data, the pointer to the U buffer; for RGBA data, the value is 0. + */ +@property(assign, nonatomic) void* _Nullable uBuffer; // U data buffer +/** For YUV data, the pointer to the V buffer; for RGBA data, the value is 0. + */ +@property(assign, nonatomic) void* _Nullable vBuffer; // V data buffer +/** The clockwise rotation angle of the video frame. + See AgoraVideoRotation. + */ +@property(assign, nonatomic) AgoraVideoRotation rotation; // rotation of this frame (0, 90, 180, 270) +/** The Unix timestamp (ms) when the video frame is rendered. This timestamp + can be used to guide the rendering of the video frame. This parameter is + required. + */ +@property(assign, nonatomic) int64_t renderTimeMs; +/** Reserved parameter. + */ +@property(assign, nonatomic) NSInteger avsync_type; + +@end +/** + The configuration of the audio and video call loop test. + + @since v3.5.2 + */ +__attribute__((visibility("default"))) @interface AgoraEchoTestConfiguration : NSObject +/** The view used to render the local user's video. + This property is only applicable to scenarios testing video devices, that is, when `enableVideo` is YES. + + @note For iOS, the data type of this property is UIView; for macOS, the data type of this property is NSView. + */ +@property(strong, nonatomic) VIEW_CLASS* _Nullable view; +/** Whether to enable the audio device for the call loop test: + + - YES: (Default) Enables the audio device. To test the audio device, set this property as `YES`. + - NO: Disables the audio device. + */ +@property(assign, nonatomic) BOOL enableAudio; +/** Whether to enable the video device for the call loop test: + + - YES: (Default) Enables the video device. To test the video device, set this property as `YES`. + - NO: Disables the video device. + */ +@property(assign, nonatomic) BOOL enableVideo; +/** The token used to secure the audio and video call loop test. If you do not enable App Certificate in Agora Console, + you do not need to pass a value in this parameter; if you have enabled App Certificate in Agora Console, you must pass + a token in this property, the `uid` used when you generate the token must be 0xFFFFFFFF, and the channel name used must + be the channel name that identifies each audio and video call loop tested. For server-side token generation, + see [Authenticate Your Users with Tokens](https://docs.agora.io/en/Interactive%20Broadcast/token_server?platform=All%20Platforms). + */ +@property(copy, nonatomic) NSString* _Nullable token; +/** The channel name that identifies each audio and video call loop. To ensure proper loop test functionality, + the channel name passed in to identify each loop test cannot be the same when users of the same project (App ID) perform + audio and video call loop tests on different devices. + */ +@property(copy, nonatomic) NSString* _Nonnull channelId; +@end + +__attribute__((visibility("default"))) @interface AgoraContentInspectModule : NSObject + +@property(assign, nonatomic) AgoraContentInspectType type; + +@property(assign, nonatomic) NSInteger interval NS_SWIFT_NAME(interval); + +@end + +__attribute__((visibility("default"))) @interface AgoraContentInspectConfig : NSObject + +@property(nonatomic, copy) NSString* _Nullable extraInfo; + +@property(copy, nonatomic) NSArray* _Nullable modules; +@end diff --git a/integration_test_app/iris_integration_test/third_party/agora/rtc/include/AgoraRtcChannel.h b/integration_test_app/iris_integration_test/third_party/agora/rtc/include/AgoraRtcChannel.h new file mode 100644 index 000000000..1e9374559 --- /dev/null +++ b/integration_test_app/iris_integration_test/third_party/agora/rtc/include/AgoraRtcChannel.h @@ -0,0 +1,1604 @@ +// +// AgoraRtcChannel.h +// AgoraRtcChannel +// +// Copyright (c) 2019 Agora. All rights reserved. +// + +#import "AgoraRtcEngineKit.h" + +@class AgoraRtcChannelMediaOptions; +@protocol AgoraRtcChannelDelegate; +@interface AgoraRtcEngineKit () + +/** Creates and gets an AgoraRtcChannel instance. + +To join more than one channel, call this method multiple times to create as many AgoraRtcChannel objects as needed, and call the [joinChannelByToken]([AgoraRtcChannel joinChannelByToken:info:uid:options:]) method of each created AgoraRtcChannel instance. + +After joining multiple channels, you can simultaneously subscribe to streams of all the channels, but publish a stream in only one channel at one time. + +@param channelId The unique channel name for an Agora RTC session. It must be in the string format and not exceed 64 bytes in length. Supported character scopes are: + +- All lowercase English letters: a to z. +- All uppercase English letters: A to Z. +- All numeric characters: 0 to 9. +- The space character. +- Punctuation characters and other symbols, including: "!", "#", "$", "%", "&", "(", ")", "+", "-", ":", ";", "<", "=", ".", ">", "?", "@", "[", "]", "^", "_", "{", "}", "|", "~", ",". + +**Note** + +- This parameter does not have a default value. You must set it. +- Do not set it as the empty string "". Otherwise, the SDK returns `AgoraErrorCodeRefused`(-5). + +@return - A pointer to the AgoraRtcChannel instance, if the method call succeeds. +- An empty pointer `nil`, if the method call fails. +- `AgoraErrorCodeRefused`(-5), if you set `channelId` as the empty string "". + */ +- (AgoraRtcChannel* _Nullable)createRtcChannel:(NSString* _Nonnull)channelId; + +@end + +/** The AgoraRtcChannel class. + + **Since** v3.0.0. + */ +__attribute__((visibility("default"))) @interface AgoraRtcChannel : NSObject + +/** Destroys the AgoraRtcChannel instance. + + @return - 0: Success. + - < 0: Failure. + + - `AgoraErrorCodeNotInitialized`(-7): The AgoraRtcChannel instance is not initialized before calling this method. + */ +- (int)destroy; +/** Sets the channel delegate. + + After setting the channel delegate, you can listen for channel events and receive the statistics of the corresponding AgoraRtcChannel instance. + + @param channelDelegate The delegate of the AgoraRtcChannel instance. For details, see AgoraRtcChannelDelegate. + */ +- (void)setRtcChannelDelegate:(id _Nullable)channelDelegate; + +/** Gets the channel ID of the current AgoraRtcChannel instance. + + @return - The channel ID of the current AgoraRtcChannel instance, if the method call succeeds. + - The empty string "", if the method call fails. + */ +- (NSString* _Nullable)getChannelId; + +/** Gets the current call ID. + + @note Ensure that you call this method after joining a channel. + + @return - The current call ID, if the method call succeeds. + - The empty string "", if the method call fails. + */ +- (NSString* _Nullable)getCallId; +/** Gets the connection state of the SDK. + + You can call this method either before or after joining a channel. + + @return The connection state, see [AgoraConnectionStateType](AgoraConnectionStateType): + + - `AgoraConnectionStateDisconnected`(1): The SDK is disconnected from Agora's edge server. + - `AgoraConnectionStateConnecting`(2): The SDK is connecting to Agora's edge server. + - `AgoraConnectionStateConnected`(3): The SDK joined a channel and is connected to Agora's edge server. You can now publish or subscribe to a media stream in the channel. + - `AgoraConnectionStateReconnecting`(4): The SDK keeps rejoining the channel after being disconnected from a joined channel because of network issues. + - `AgoraConnectionStateFailed`(5): The SDK fails to join the channel. + */ +- (AgoraConnectionStateType)getConnectionState; + +/** Joins the channel with a user ID. + + Compared with the + [joinChannelByToken]([AgoraRtcEngineKit joinChannelByToken:channelId:info:uid:options:]) + method in the `AgoraRtcEngineKit` class, this method supports joining multiple + channels at a time by creating multiple `AgoraRtcChannel`objects and then + calling `joinChannelByToken` in each `AgoraRtcChannel` object. + + Once the user joins the channel, the user publishes the local audio and video + streams and automatically subscribes to the audio and video streams of all the + other users in the channel by default. Subscribing incurs all associated usage + costs. To unsubscribe, set the `options` parameter or call the `mute` + methods accordingly. + + **Note** + + - If you are already in a channel, you cannot rejoin it with the same `uid`. + - We recommend using different `uid` for different channels. + - If you want to join the same channel from different devices, ensure that the `uid` in all devices are different. + - Ensure that the app ID you use to generate the token is the same with the app ID used when creating the AgoraRtcEngineKit instance. + + @param token The token generated at your server. See [Authenticate Your Users with Tokens](https://docs.agora.io/en/Interactive%20Broadcast/token_server?platform=All%20Platforms). + @param info (Optional) Additional information about the channel. This parameter can be set as `nil`. Other users in the channel do not receive this information. + @param uid The user ID. A 32-bit unsigned integer with a value ranging from 1 to (232-1). This parameter must be unique. If `uid` is not assigned (or set as 0), the SDK assigns a `uid` and reports it in the [rtcChannelDidJoinChannel]([AgoraRtcChannelDelegate rtcChannelDidJoinChannel:withUid:elapsed:]) callback. The app must maintain this user ID. + @param options The channel media options: AgoraRtcChannelMediaOptions + + @return - `0`(`AgoraErrorCodeNoError`): Success. +- < `0`: Failure. + + - `-2`(`AgoraErrorCodeInvalidArgument`): The parameter is invalid. + - `-3`(`AgoraErrorCodeNotReady`): The SDK fails to be initialized. You can try re-initializing the SDK. + - `-5`(`AgoraErrorCodeRefused`): The request is rejected. This may be caused by the following: + + - You have created an `AgoraRtcChannel` object with the same channel name. + - You have joined and published a stream in a channel created by the `AgoraRtcChannel` object. + + - `-7`(`AgoraErrorCodeNotInitialized`): The SDK is not initialized before calling this method. + - `-17`(`AgoraErrorCodeJoinChannelRejected`): The request to join the channel is rejected. The SDK does not support joining the + same AgoraRtcChannel channel repeatedly. Therefore, the SDK returns this error code when a user who has already + joined an AgoraRtcChannel channel calls the joining channel method of this AgoraRtcChannel object. + */ +- (int)joinChannelByToken:(NSString* _Nullable)token info:(NSString* _Nullable)info uid:(NSUInteger)uid options:(AgoraRtcChannelMediaOptions* _Nonnull)options; + +/** Joins a channel with the user account. + + This method differs from the [joinChannelByUserAccount]([AgoraRtcEngineKit joinChannelByUserAccount:token:channelId:joinSuccess:])1 method in the AgoraRtcEngineKit class in the following aspects: + +| [AgoraRtcChannel joinChannelByUserAccount]([AgoraRtcChannel joinChannelByUserAccount:token:options:]) | [AgoraRtcEngineKit joinChannelByUserAccount]([AgoraRtcEngineKit joinChannelByUserAccount:token:channelId:joinSuccess:])1 | +|------------------------------------------------------------------------------------------------------------------------------------------------|--------------------------------------------------------------------------------------------------------------| +| Does not contain the `channelId` parameter, because `channelId` is specified when creating the AgoraRtcChannel instance. | Contains the `channelId` parameter, which specifies the channel to join. | +| Contains the `options` parameter, which decides whether to subscribe to all streams before joining the channel. | Does not contain the `options` parameter. By default, users subscribe to all streams when joining the channel. To configure media subscribing options when joining the channel, use [joinChannelByUserAccount]([AgoraRtcEngineKit joinChannelByUserAccount:token:channelId:options:])2 instead. | +| Users can join multiple channels simultaneously by creating multiple AgoraRtcChannel instances and calling the `joinChannelByUserAccount` method of each instance. | Users can join only one channel. | +| By default, the SDK does not publish any stream after the user joins the channel. You need to call the [publish]([AgoraRtcChannel publish]) method to do that. | By default, the SDK publishes streams once the user joins the channel. | + + **Note** + + - Before using a String user name, ensure that you read [How can I use string user names](https://docs.agora.io/en/faq/string) for getting details about the limitations and implementation steps. + - If you are already in a channel, you cannot rejoin it with the same `uid`. + - We recommend using different `uid` for different channels. + - If you want to join the same channel from different devices, ensure that the `uid` in all devices are different. + - Ensure that the app ID you use to generate the token is the same with the app ID used when creating the AgoraRtcEngineKit instance. + + @param userAccount The user account. The maximum length of this parameter is 255 bytes. Ensure that you set this parameter and do not set it as `nil`. + + - All lowercase English letters: a to z. + - All uppercase English letters: A to Z. + - All numeric characters: 0 to 9. + - The space character. + - Punctuation characters and other symbols, including: "!", "#", "$", "%", "&", "(", ")", "+", "-", ":", ";", "<", "=", ".", ">", "?", "@", "[", "]", "^", "_", "{", "}", "|", "~", ",". + @param token The token generated at your server. See [Authenticate Your Users with Tokens](https://docs.agora.io/en/Interactive%20Broadcast/token_server?platform=All%20Platforms). + @param options The channel media options: AgoraRtcChannelMediaOptions + + @return - 0: Success. + - < 0: Failure. + + - `AgoraErrorCodeInvalidArgument`(-2) + - `AgoraErrorCodeNotReady`(-3) + - `AgoraErrorCodeRefused`(-5) + - `AgoraErrorCodeJoinChannelRejected`(-17): The request to join the channel is rejected. The SDK does not support joining the + same AgoraRtcChannel channel repeatedly. Therefore, the SDK returns this error code when a user who has already + joined an AgoraRtcChannel channel calls the joining channel method of this AgoraRtcChannel object. + */ +- (int)joinChannelByUserAccount:(NSString* _Nonnull)userAccount token:(NSString* _Nullable)token options:(AgoraRtcChannelMediaOptions* _Nonnull)options; + +/** Leaves the current channel. + + A successful `leaveChannel` method call triggers the following callbacks: + + - The local client: [rtcChannelDidLeaveChannel]([AgoraRtcChannelDelegate rtcChannelDidLeaveChannel:withStats:]). + - The remote client: [didOfflineOfUid]([AgoraRtcChannelDelegate rtcChannel:didOfflineOfUid:reason:]), if the user leaving the channel is in a Communication channel, or is a host in a Live-Broadcast channel. + + @return - `0`(`AgoraErrorCodeNoError`): Success. +- < `0`: Failure. + + - `-1`(`AgoraErrorCodeFailed`): A general error occurs (no specified reason). + - `-2`(`AgoraErrorCodeInvalidArgument`): The parameter is invalid. + - `-7`(`AgoraErrorCodeNotInitialized`): The SDK is not initialized. + */ +- (int)leaveChannel; + +/** Stops or resumes publishing the local audio stream. + + @since v3.4.5 + + This method only sets the publishing state of the audio stream in the channel + of `AgoraRtcChannel`. + + A successful method call triggers the + [remoteAudioStateChangedOfUid]([AgoraRtcChannelDelegate rtcChannel:remoteAudioStateChangedOfUid:state:reason:elapsed:]) + callback on the remote client. + + You can only publish the local stream in one channel at a time. If you create + multiple channels, ensure that you only call `muteLocalAudioStream(NO)` in + one channel; otherwise, the method call fails, and the SDK returns + `-5 (AgoraErrorCodeRefused)`. + + **Note**: + + - This method does not change the usage status of the audio-capturing device. + - Whether this method call takes effect is affected by the + [joinChannelByToken]([AgoraRtcChannel joinChannelByToken:info:uid:options:]) + and [setClientRole]([AgoraRtcChannel setClientRole:]) methods. For details, + see *Set the Publishing State*. + + @param mute Sets whether to stop publishing the local audio stream. + + * YES: Stop publishing the local audio stream. + * NO: Resume publishing the local audio stream. + + @return * 0: Success. +* < 0: Failure. + + - `-5` (`AgoraErrorCodeRefused`): The request is rejected. + */ +- (int)muteLocalAudioStream:(BOOL)mute; + +/** Stops or resumes publishing the local video stream. + + @since v3.4.5 + + This method only sets the publishing state of the video stream in the channel + of `AgoraRtcChannel`. + + A successful method call triggers the + [remoteVideoStateChangedOfUid]([AgoraRtcChannelDelegate rtcChannel:remoteVideoStateChangedOfUid:state:reason:elapsed:]) + callback on the remote client. + + You can only publish the local stream in one channel at a time. If you create + multiple channels, ensure that you only call `muteLocalVideoStream(NO)` in + one channel; otherwise, the method call fails, and the SDK returns + `-5 (AgoraErrorCodeRefused)`. + + **Note**: + + - This method does not change the usage state of the video-capturing device. + - Whether this method call takes effect is affected by the + [joinChannelByToken]([AgoraRtcChannel joinChannelByToken:info:uid:options:]) + and [setClientRole]([AgoraRtcChannel setClientRole:]) methods. For details, + see *Set the Publishing State*. + + @param mute Sets whether to stop publishing the local video stream. + + * YES: Stop publishing the local video stream. + * NO: Resume publishing the local video stream. + + @return * 0: Success. +* < 0: Failure. + + - `-5` (`AgoraErrorCodeRefused`): The request is rejected. + */ +- (int)muteLocalVideoStream:(BOOL)mute; + +/** Publishes the local stream to the channel. + + **Deprecated** This method is deprecated as of v3.4.5. Use + [muteLocalAudioStream]([AgoraRtcChannel muteLocalAudioStream:])`(NO)` or + [muteLocalVideoStream]([AgoraRtcChannel muteLocalVideoStream:])`(NO)` instead. + + You must keep the following restrictions in mind when calling this method. Otherwise, the SDK returns the AgoraErrorCodeRefused(-5): + + - This method publishes one stream only to the channel corresponding to the current AgoraRtcChannel instance. + - You can publish a stream to only one channel at a time. For details, see the advanced guide *Join Multiple Channels*. + + @return - 0: Success. + - < 0: Failure. + + - `AgoraErrorCodeRefused`(-5): The method call is refused. + */ +- (int)publish; + +/** Stops publishing a stream to the channel. + + **Deprecated** This method is deprecated as of v3.4.5. Use + [muteLocalAudioStream]([AgoraRtcChannel muteLocalAudioStream:])`(YES)` or + [muteLocalVideoStream]([AgoraRtcChannel muteLocalVideoStream:])`(YES)` instead. + + If you call this method in a channel where you are not publishing streams, the SDK returns AgoraErrorCodeRefused(-5). + + @return - 0: Success. + - < 0: Failure. + + - `AgoraErrorCodeRefused`(-5): The method call is refused. + */ +- (int)unpublish; + +/** Sets the role of the user in interactive live streaming. + + After calling [setChannelProfile(AgoraChannelProfileLiveBroadcasting)]([AgoraRtcEngineKit setChannelProfile:]), + the SDK sets the user role as audience by default. You can call + `setClientRole` to set the user role as host. + + You can call this method either before or after joining a channel. + If you call this method to switch the user role after joining a channel, + the SDK automatically does the following: + + - Calls [muteLocalAudioStream]([AgoraRtcChannel muteLocalAudioStream:]) and + [muteLocalVideoStream]([AgoraRtcChannel muteLocalVideoStream:]) to change + the publishing state. + - Triggers [didClientRoleChanged]([AgoraRtcChannelDelegate rtcChannel:didClientRoleChanged:newRole:]) + on the local client. + - Triggers [didJoinedOfUid]([AgoraRtcChannelDelegate rtcChannel:didJoinedOfUid:elapsed:]) + or [didOfflineOfUid(AgoraUserOfflineReasonBecomeAudience)]([AgoraRtcChannelDelegate rtcChannel:didOfflineOfUid:reason:]) + on the remote client. + + @note This method applies to the `AgoraChannelProfileLiveBroadcasting` profile + only (when the `profile` parameter in `setChannelProfile` is set as + `AgoraChannelProfileLiveBroadcasting`). + + @param role The role of a user in interactive live streaming. + See [AgoraClientRole](AgoraClientRole). + + @return - 0(`AgoraErrorCodeNoError`): Success. + - < 0: Failure. + + - -1(`AgoraErrorCodeFailed`): A general error occurs (no specified reason). + - -2(`AgoraErrorCodeInvalidArgument`): The parameter is invalid. + - -7(`AgoraErrorCodeNotInitialized`): The SDK is not initialized. + - -5 (`AgoraErrorCodeRefused`): The request is rejected. In multichannel + scenarios, if you have set any of the following in one channel, the SDK + returns this error code when the user switches the user role to host + in another channel: + + - Call [joinChannelByToken]([AgoraRtcChannel joinChannelByToken:info:uid:options:]) + with the `options` parameter and use the default settings + `publishLocalAudio = YES` or `publishLocalVideo = YES`. + - Call `setClientRole` to set the user role as host. + - Call `muteLocalAudioStream(NO)` or `muteLocalVideoStream(NO)`. + */ +- (int)setClientRole:(AgoraClientRole)role; + +/** Sets the role of the user in interactive live streaming. + + @since v3.2.0 + + After calling [setChannelProfile(AgoraChannelProfileLiveBroadcasting)]([AgoraRtcEngineKit setChannelProfile:]), + the SDK sets the user role as audience by default. You can call + `setClientRole` to set the user role as host. + + You can call this method either before or after joining a channel. + If you call this method to switch the user role after joining a channel, + the SDK automatically does the following: + + - Calls [muteLocalAudioStream]([AgoraRtcChannel muteLocalAudioStream:]) and + [muteLocalVideoStream]([AgoraRtcChannel muteLocalVideoStream:]) to change + the publishing state. + - Triggers [didClientRoleChanged]([AgoraRtcChannelDelegate rtcChannel:didClientRoleChanged:newRole:]) + on the local client. + - Triggers [didJoinedOfUid]([AgoraRtcChannelDelegate rtcChannel:didJoinedOfUid:elapsed:]) + or [didOfflineOfUid(AgoraUserOfflineReasonBecomeAudience)]([AgoraRtcChannelDelegate rtcChannel:didOfflineOfUid:reason:]) + on the remote client. + + **Note** + + -This method applies to the `AgoraChannelProfileLiveBroadcasting` profile + only (when the `profile` parameter in `setChannelProfile` is set as + `AgoraChannelProfileLiveBroadcasting`). + - The difference between this method and + [setClientRole]([AgoraRtcEngineKit setClientRole:])1 is that this method can + set the user level in addition to the user role. + + - The user role determines the permissions that the SDK grants to a user, + such as permission to send local streams, receive remote + streams, and push streams to a CDN address. + - The user level determines the level of services that a user can enjoy + within the permissions of the user's role. For example, an audience member + can choose to receive remote streams with low latency or ultra low latency. + **User level affects the pricing of services**. + + @param role The role of a user in interactive live streaming. + See [AgoraClientRole](AgoraClientRole). + @param options The detailed options of a user, including user level. + See [AgoraClientRoleOptions](AgoraClientRoleOptions). + + @return - 0(`AgoraErrorCodeNoError`): Success. + - < 0: Failure. + + - -1(`AgoraErrorCodeFailed`): A general error occurs (no specified reason). + - -2(`AgoraErrorCodeInvalidArgument`): The parameter is invalid. + - -7(`AgoraErrorCodeNotInitialized`): The SDK is not initialized. + - -5 (`AgoraErrorCodeRefused`): The request is rejected. In multichannel + scenarios, if you have set any of the following in one channel, the SDK + returns this error code when the user switches the user role to host + in another channel: + + - Call [joinChannelByToken]([AgoraRtcChannel joinChannelByToken:info:uid:options:]) + with the `options` parameter and use the default settings + `publishLocalAudio = YES` or `publishLocalVideo = YES`. + - Call `setClientRole` to set the user role as host. + - Call `muteLocalAudioStream(NO)` or `muteLocalVideoStream(NO)`. + */ +- (int)setClientRole:(AgoraClientRole)role options:(AgoraClientRoleOptions* _Nullable)options; +/** Renews the token when the current token expires. + + In the following situations, the SDK decides that the current token has expired: + + - The SDK triggers the [tokenPrivilegeWillExpire]([AgoraRtcChannelDelegate rtcChannel:tokenPrivilegeWillExpire:]) callback, or + - The [connectionChangedToState]([AgoraRtcChannelDelegate rtcChannel:connectionChangedToState:reason:]) callback reports the AgoraConnectionChangedTokenExpired(9) error. + + You should get a new token from your server and call this method to renew it. Failure to do so results in the SDK disconnecting from the Agora server. + + **Note** + + Agora recommends using the [rtcChannelRequestToken]([AgoraRtcChannelDelegate rtcChannelRequestToken:]) callback to report the AgoraErrorCodeTokenExpired(-109) error, not using the [didOccurError]([AgoraRtcChannelDelegate rtcChannel:didOccurError:]) callback. + + @param token The new token. + + @return - `0`(`AgoraErrorCodeNoError`): Success. +- < `0`: Failure. + + - `-1`(`AgoraErrorCodeFailed`): A general error occurs (no specified reason). + - `-2`(`AgoraErrorCodeInvalidArgument`): The parameter is invalid. + - `-7`(`AgoraErrorCodeNotInitialized`): The SDK is not initialized. + */ +- (int)renewToken:(NSString* _Nonnull)token; + +/** Enables built-in encryption with an encryption password before joining a channel. + + **DEPRECATED** from v3.1.0. Use [enableEncryption]([AgoraRtcEngineKit enableEncryption:encryptionConfig:]) instead. + + All users in a channel must set the same encryption password. The encryption password is automatically cleared once a user leaves the channel. + + If the encryption password is not specified or set to empty, the encryption functionality is disabled. + + **Note** + + - Do not use this method for CDN live streaming. + - For optimal transmission, ensure that the encrypted data size does not exceed the original data size + 16 bytes. 16 bytes is the maximum padding size for AES encryption. + + @param secret Encryption password. + + @return - 0: Success. + - < 0: Failure. + */ +- (int)setEncryptionSecret:(NSString* _Nullable)secret; + +/** Sets the built-in encryption mode. + + **DEPRECATED** from v3.1.0. Use [enableEncryption]([AgoraRtcEngineKit enableEncryption:encryptionConfig:]) instead. + + The SDK supports built-in encryption, which is set to the "aes-128-xts" mode by default. Call this method to use other encryption modes. + + All users in the same channel must use the same encryption mode and password. + + Refer to the information related to the AES encryption algorithm on the differences between the encryption modes. + + **Note** + + - Call the [setEncryptionSecret]([AgoraRtcChannel setEncryptionSecret:]) method to enable the built-in encryption function before calling this method. + - Do not use this method for CDN live streaming. + + @param encryptionMode Sets the encryption mode. + + - "aes-128-xts": (default) 128-bit AES encryption, XTS mode. + - "aes-256-xts": 256-bit AES encryption, XTS mode. + - "aes-128-ecb": 128-bit AES encryption, ECB mode. + - "": (Default) When encryptionMode is set as the empty string, the encryption is in “aes-128-xts” by default. + + @return - 0: Success. + - < 0: Failure. + */ +- (int)setEncryptionMode:(NSString* _Nullable)encryptionMode; +/** Enables/Disables the built-in encryption. + + @since v3.1.0 + + In scenarios requiring high security, Agora recommends calling + `enableEncryption` to enable the built-in encryption before joining a channel. + + After a user leaves the channel, the SDK automatically disables the built-in + encryption. To re-enable the built-in encryption, call this method before the + user joins the channel again. + + As of v3.4.5, Agora recommends using either the `AgoraEncryptionModeAES128GCM2` + or `AgoraEncryptionModeAES256GCM2` encryption mode, both of which support + adding a salt and are more secure. For details, see *Media Stream Encryption*. + + @warning All users in the same channel must use the same encryption mode, + encryption key, and salt; otherwise, users cannot communicate with each other. + + **Note**: + + - If you enable the built-in encryption, you cannot use the RTMP or RTMPS + streaming function. + - To enhance security, Agora recommends using a new key and salt every time + you enable the media stream encryption. + + @param enabled Whether to enable the built-in encryption: + + - YES: Enable the built-in encryption. + - NO: Disable the built-in encryption. + + @param config Configurations of built-in encryption schemas. See AgoraEncryptionConfig. + + @return - 0: Success. + - < 0: Failure. + + - -2 (`AgoraErrorCodeInvalidArgument`): An invalid parameter is used. Set the parameter with a valid value. + - -7 (`AgoraErrorCodeNotInitialized`): The SDK is not initialized. Initialize the `AgoraRtcEngineKit` instance before calling this method. + - -4 (`AgoraErrorCodeNotSupported`): The encryption mode is incorrect or the SDK fails to load the external encryption library. Check the enumeration or reload the external encryption library. + */ +- (int)enableEncryption:(bool)enabled encryptionConfig:(AgoraEncryptionConfig* _Nonnull)config; + +/** Sets the priority of a remote user’s stream. + + The SDK ensures the high-priority user gets the best possible stream quality. + + **Note** + + The SDK supports setting userPriority as high for one user only. + + @param uid The ID of the remote user. + @param userPriority The priority of the remote user, see AgoraUserPriority. + + @return - 0: Success. + - < 0: Failure. + */ +- (int)setRemoteUserPriority:(NSUInteger)uid type:(AgoraUserPriority)userPriority; +/** Sets the sound position and gain of a remote user. + + When the local user calls this method to set the sound position of a remote user, the sound difference between the left and right channels allows the local user to track the real-time position of the remote user, creating a real sense of space. This method applies to massively multiplayer online games, such as Battle Royale games. + + **Note** + + - Ensure that you call this method after joining a channel. For this method to work, enable stereo panning for remote users by calling [enableSoundPositionIndication]([AgoraRtcEngineKit enableSoundPositionIndication:]) before joining a channel. This method requires hardware support. + - For the best effect, we recommend using the following audio output devices: + + - (iOS) A wired headset. + - (macOS) A stereo loudspeaker. + + @param uid The ID of the remote user. + @param pan The sound position of the remote user. The value ranges from -1.0 to 1.0: + + - 0.0: (Default) The remote sound comes from the front. + - -1.0: The remote sound comes from the left. + - 1.0: The remote sound comes from the right. + @param gain Gain of the remote user. The value ranges from 0.0 to 100.0. The default value is 100.0 (the original gain of the remote user). The smaller the value, the less the gain. + + @return - 0: Success. + - < 0: Failure. + */ +- (int)setRemoteVoicePosition:(NSUInteger)uid pan:(double)pan gain:(double)gain; +/** Updates the display mode of the video view of a remote user. + + After initializing the video view of a remote user, you can call this method to update its rendering and mirror modes. This method affects only the video view that the local user sees. + + **Note** + + - Ensure that you have called [setupRemoteVideo]([AgoraRtcEngineKit setupRemoteVideo:]) to initialize the remote video view before calling this method. + - During a call, you can call this method as many times as necessary to update the display mode of the video view of a remote user. + + @param uid The ID of the remote user. + @param renderMode The rendering mode of the remote video view. See [AgoraVideoRenderMode](AgoraVideoRenderMode). + @param mirrorMode The mirror mode of the remote video view. See [AgoraVideoMirrorMode](AgoraVideoMirrorMode). + + **Note** + + The SDK disables the mirror mode by default. + + @return - 0: Success. + - < 0: Failure. + */ +- (int)setRemoteRenderMode:(NSUInteger)uid renderMode:(AgoraVideoRenderMode)renderMode mirrorMode:(AgoraVideoMirrorMode)mirrorMode; + +/** Stops or resumes subscribing to the audio streams of all remote users by default. + + **Deprecated** This method is deprecated from v3.3.0. + + Call this method after joining a channel. After successfully calling this + method, the local user stops or resumes subscribing to the audio streams of + all subsequent users. + + **Note** + + If you need to resume subscribing to the audio streams of remote users + in the channel after calling `setDefaultMuteAllRemoteAudioStreams(YES)`, do + the following: + + - If you need to resume subscribing to the audio stream of a specified user, + call [muteRemoteAudioStream(NO)]([AgoraRtcChannel muteRemoteAudioStream:mute:]), and specify the user ID. + - If you need to resume subscribing to the audio streams of multiple remote + users, call `muteRemoteAudioStream(NO)` multiple times. + + @param mute Sets whether to stop subscribing to the audio streams of all + remote users by default. + + * YES: Stop subscribing to the audio streams of all + remote users by default. + * NO: (Default) Resume subscribing to the audio streams of all remote users + by default. + + @return * 0: Success. +* < 0: Failure. + */ +- (int)setDefaultMuteAllRemoteAudioStreams:(BOOL)mute; + +/** Stops or resumes subscribing to the video streams of all remote users by default. + + **Deprecated** This method is deprecated from v3.3.0. + + Call this method after joining a channel. After successfully calling this + method, the local user stops or resumes subscribing to the video streams of + all subsequent users. + + **Note** + + If you need to resume subscribing to the video streams of remote users + in the channel after calling `setDefaultMuteAllRemoteVideoStreams(YES)`, do + the following: + + - If you need to resume subscribing to the video stream of a specified user, + call [muteRemoteVideoStream(NO)]([AgoraRtcChannel muteRemoteVideoStream:mute:]), and specify the user ID. + - If you need to resume subscribing to the video streams of multiple remote + users, call `muteRemoteVideoStream(NO)` multiple times. + + @param mute Sets whether to stop subscribing to the video streams of all + remote users by default. + + * YES: Stop subscribing to the video streams of all + remote users by default. + * NO: (Default) Resume subscribing to the video streams of all remote users + by default. + + @return * 0: Success. +* < 0: Failure. + */ +- (int)setDefaultMuteAllRemoteVideoStreams:(BOOL)mute; + +/** Stops or resumes subscribing to the audio stream of a specified user. + + **Note:** + + - Call this method after joining a channel. + - See recommended settings in *Set the Subscribing State*. + + @param uid The user ID of the specified remote user. + @param mute Sets whether to stop subscribing to the audio stream of a + specified user. + + * YES: Stop subscribing to the audio stream of a specified user. + * NO: (Default) Resume subscribing to the audio stream of a specified user. + + @return * 0: Success. +* < 0: Failure. + */ +- (int)muteRemoteAudioStream:(NSUInteger)uid mute:(BOOL)mute; +/** Adjust the playback signal volume of a specified remote user. + + You can call this method as many times as necessary to adjust the playback volume of different remote users, or to repeatedly adjust the playback volume of the same remote user. + + **Note** + + - Call this method after joining a channel. + - The playback volume here refers to the mixed volume of a specified remote user. + - This method can only adjust the playback volume of one specified remote user at a time. To adjust the playback volume of different remote users, call the method as many times, once for each remote user. + + @param uid The ID of the remote user. + @param volume The playback volume of the specified remote user. The value + ranges between 0 and 400, including the following: + + - 0: Mute. + - 100: (Default) Original volume. + - 400: Four times the original volume with signal-clipping protection. + + @return - 0: Success. + - < 0: Failure. + */ +- (int)adjustUserPlaybackSignalVolume:(NSUInteger)uid volume:(int)volume; + +/** Stops or resumes subscribing to the audio streams of all remote users. + + After successfully calling this method, the local user stops or + resumes subscribing to the audio streams of all remote users, including all + subsequent users. + + **Note** + + - Call this method after joining a channel. + - As of v3.3.0, this method contains the function of + [setDefaultMuteAllRemoteAudioStreams]([AgoraRtcChannel setDefaultMuteAllRemoteAudioStreams:]). + Agora recommends not calling `muteAllRemoteAudioStreams` and + `setDefaultMuteAllRemoteAudioStreams` together; otherwise, the settings may + not take effect. See *Set the Subscribing State*. + + @param mute Sets whether to stop subscribing to the audio streams of all + remote users. + + * YES: Stop subscribing to the audio streams of all remote users. + * NO: (Default) Resume subscribing to the audio streams of all remote users. + + @return * 0: Success. +* < 0: Failure. + */ +- (int)muteAllRemoteAudioStreams:(BOOL)mute; + +/** Stops or resumes subscribing to the video stream of a specified user. + + **Note:** + + - Call this method after joining a channel. + - See recommended settings in *Set the Subscribing State*. + + @param uid The user ID of the specified remote user. + @param mute Sets whether to stop subscribing to the video stream of a + specified user. + + * YES: Stop subscribing to the video stream of a specified user. + * NO: (Default) Resume subscribing to the video stream of a specified user. + + @return * 0: Success. +* < 0: Failure. + */ +- (int)muteRemoteVideoStream:(NSUInteger)uid mute:(BOOL)mute; + +/** Stops or resumes subscribing to the video streams of all remote users. + + After successfully calling this method, the local user stops or + resumes subscribing to the video streams of all remote users, including all + subsequent users. + + **Note** + + - Call this method after joining a channel. + - As of v3.3.0, this method contains the function of + [setDefaultMuteAllRemoteAudioStreams]([AgoraRtcChannel setDefaultMuteAllRemoteAudioStreams:]). + Agora recommends not calling `muteAllRemoteAudioStreams` and + `setDefaultMuteAllRemoteAudioStreams` together; otherwise, the settings may + not take effect. See *Set the Subscribing State*. + + @param mute Sets whether to stop subscribing to the video streams of all + remote users. + + * YES: Stop subscribing to the video streams of all remote users. + * NO: (Default) Resume subscribing to the video streams of all remote users. + + @return * 0: Success. +* < 0: Failure. + */ +- (int)muteAllRemoteVideoStreams:(BOOL)mute; +/** Sets the stream type of the remote video. + + Under limited network conditions, if the publisher has not disabled the dual-stream mode using [enableDualStreamMode(NO)]([AgoraRtcEngineKit enableDualStreamMode:])enableDualStreamMode(NO), the receiver can choose to receive either the high-quality video stream (the high resolution, and high bitrate video stream) or the low-quality video stream (the low resolution, and low bitrate video stream). + + By default, users receive the high-quality video stream. Call this method if you want to switch to the low-quality video stream. This method allows the app to adjust the corresponding video stream type based on the size of the video window to reduce the bandwidth and resources. + + The aspect ratio of the low-quality video stream is the same as the high-quality video stream. Once the resolution of the high-quality video stream is set, the system automatically sets the resolution, frame rate, and bitrate of the low-quality video stream. + + The SDK reports the result of calling this method in the [didApiCallExecute]([AgoraRtcEngineDelegate rtcEngine:didApiCallExecute:api:result:]) callback. + + @note You can call this method either before or after joining a channel. If you call both `setRemoteVideoStream` and [setRemoteDefaultVideoStreamType]([AgoraRtcEngineKit setRemoteDefaultVideoStreamType:]), the SDK applies the settings in the `setRemoteVideoStream` method. + + @param uid ID of the remote user sending the video stream. + @param streamType Sets the video-stream type. See AgoraVideoStreamType. + + @return * 0: Success. +* < 0: Failure. + */ +- (int)setRemoteVideoStream:(NSUInteger)uid type:(AgoraVideoStreamType)streamType; +/** Sets the default video-stream type for the video received by the local user when the remote user sends dual streams. + + @note You can call this method either before or after joining a channel. If you call both `setRemoteDefaultVideoStreamType` and [setRemoteVideoStream]([AgoraRtcEngineKit setRemoteVideoStream:type:]), the SDK applies the settings in the `setRemoteDefaultVideoStreamType` method. + + @param streamType Sets the default video-stream type. See AgoraVideoStreamType. + + @return - 0: Success. + - < 0: Failure. + */ +- (int)setRemoteDefaultVideoStreamType:(AgoraVideoStreamType)streamType; +/** Adds a voice or video stream CDN streaming URL to the interactive live streaming. + + If this method call is successful, the server pulls the voice or video stream and injects it into a live channel. This is applicable to scenarios where all audience members in the channel can watch a live show and interact with each other. + + The `addInjectStreamUrl` method call triggers the following callbacks: + + - The local client: + + - [streamInjectedStatusOfUrl]([AgoraRtcChannelDelegate rtcChannel:streamInjectedStatusOfUrl:uid:status:]), with the state of the injecting the online stream. + - [didJoinedOfUid]([AgoraRtcChannelDelegate rtcChannel:didJoinedOfUid:elapsed:])(uid: 666), if the method call is successful and the online media stream is injected into the channel. + + - The remote client: + + - [didJoinedOfUid]([AgoraRtcChannelDelegate rtcChannel:didJoinedOfUid:elapsed:])(uid: 666), if the method call is successful and the online media stream is injected into the channel. + + + @warning Agora will soon stop the service for injecting online media streams on the client. If you have not implemented this service, Agora recommends that you do not use it. + + **Note:** + + - Ensure that you call this method after joining a channel. + - You can inject only one media stream into the channel at the same time. + - Ensure that you enable the RTMP Converter service before using this function. See [Prerequisites](https://docs.agora.io/en/Interactive%20Broadcast/cdn_streaming_apple?platform=iOS#prerequisites). + - This method applies to the Native SDK v2.4.1 and later. + + @param url URL address to be added to the ongoing interactive live streaming. Valid protocols are RTMP, HLS, and HTTP-FLV. + +- Supported audio codec type: AAC. +- Supported video codec type: H264 (AVC). + @param config AgoraLiveInjectStreamConfig object which contains the configuration information for the added voice or video stream. + +@return * 0: Success. +* < 0: Failure. + + - `AgoraErrorCodeInvalidArgument`(-2): The injected URL does not exist. Call this method again to inject the stream and ensure that the URL is valid. + - `AgoraErrorCodeNotReady`(-3): The user is not in the channel. + - `AgoraErrorCodeNotSupported`(-4): The channel profile is not Live Broadcast. + - `AgoraErrorCodeNotInitialized`(-7): The SDK is not initialized. Ensure that the AgoraRtcChannel object is initialized before using this method. + */ +- (int)addInjectStreamUrl:(NSString* _Nonnull)url config:(AgoraLiveInjectStreamConfig* _Nonnull)config; +/** Removes the voice or video stream CDN streaming URL from the interactive live streaming. + + This method removes the URL address (added by the [addInjectStreamUrl]([AgoraRtcChannel addInjectStreamUrl:config:]) method) from the interactive live streaming. + + If this method call is successful, the SDK triggers the [didOfflineOfUid]([AgoraRtcChannelDelegate rtcChannel:didOfflineOfUid:reason:]) callback and returns a stream uid of 666. + + @warning Agora will soon stop the service for injecting online media streams on the client. If you have not implemented this service, Agora recommends that you do not use it. + + @param url URL address of the added stream to be removed. + + @return * 0: Success. + * < 0: Failure. + */ +- (int)removeInjectStreamUrl:(NSString* _Nonnull)url; +/** Publishes the local stream to the CDN. + + After calling this method, you can push media streams in RTMP or RTMPS protocol to the CDN. The SDK triggers the [rtmpStreamingChangedToState]([AgoraRtcChannelDelegate rtcChannel:rtmpStreamingChangedToState:state:errorCode:]) callback on the local client to report the state of adding a local stream to the CDN. + + **Note:** + + - This method applies to the interactive live streaming profile only. + - Ensure that the user joins the channel before calling this method. + - Ensure that you enable the RTMP Converter service before using this function. See [Prerequisites](https://docs.agora.io/en/Interactive%20Broadcast/cdn_streaming_apple?platform=iOS#prerequisites). + - This method adds only one stream URL each time it is called. + - Agora supports pushing media streams in RTMPS protocol to the CDN only when you enable transcoding. + + @param url The CDN streaming URL in the RTMP or RTMPS format. The maximum length of this parameter is 1024 bytes. The CDN streaming URL must not contain special characters, such as Chinese language characters. + @param transcodingEnabled Sets whether transcoding is enabled/disabled: + + - YES: Enable transcoding. To [transcode](https://docs.agora.io/en/Agora%20Platform/terms?platform=All%20Platforms#transcoding) the audio or video streams when publishing them to CDN live, often used for combining the audio and video streams of multiple hosts in CDN live. If you set this parameter as `YES`, ensure that you call the [setLiveTranscoding]([AgoraRtcChannel setLiveTranscoding:]) method before this method. + - NO: Disable transcoding. + + @return * 0: Success. + * < 0: Failure. + + - `AgoraErrorCodeInvalidArgument`(-2): Invalid parameter. The URL is nil or the string length is 0. + - `AgoraErrorCodeNotInitialized`(-7): You have not initialized the RTC Engine when publishing the stream. + */ +- (int)addPublishStreamUrl:(NSString* _Nonnull)url transcodingEnabled:(BOOL)transcodingEnabled; +/** Removes an RTMP or RTMPS stream from the CDN. + +This method removes the CDN streaming URL added by the [addPublishStreamUrl]([AgoraRtcChannel addPublishStreamUrl:transcodingEnabled:]) method from a CDN live stream. + +This method call triggers the [rtmpStreamingChangedToState]([AgoraRtcChannelDelegate rtcChannel:rtmpStreamingChangedToState:state:errorCode:]) callback on the local client to report the state of removing an RTMP or RTMPS stream from the CDN. + + **Note:** + + * This method applies to the interactive live streaming profile only. + * This method removes only one URL each time it is called. + * The URL must not contain special characters, such as Chinese language characters. + + @param url The CDN streaming URL to be removed. The maximum length of this parameter is 1024 bytes. + + @return * 0: Success. + * < 0: Failure. + */ +- (int)removePublishStreamUrl:(NSString* _Nonnull)url; +/** Sets the video layout and audio settings for CDN live. (CDN live only.) + + The SDK triggers the [rtcEngineTranscodingUpdated]([AgoraRtcEngineDelegate rtcEngineTranscodingUpdated:]) callback when you call the `setLiveTranscoding` method to update the transcoding setting. + + **Note** + + - Ensure that you call this method after joining a channel. + - This method applies to the interactive live streaming profile only. + - Ensure that you enable the RTMP Converter service before using this function. See [Prerequisites](https://docs.agora.io/en/Interactive%20Broadcast/cdn_streaming_apple?platform=iOS#prerequisites). + - If you call the `setLiveTranscoding` method to update the transcoding setting for the first time, the SDK does not trigger the `rtcEngineTranscodingUpdated` callback. + - Agora supports pushing media streams in RTMPS protocol to the CDN only when you enable transcoding. + + @param transcoding Sets the CDN live audio/video transcoding settings. See AgoraLiveTranscoding. + + @return * 0: Success. + * < 0: Failure. + */ +- (int)setLiveTranscoding:(AgoraLiveTranscoding* _Nullable)transcoding; +/** Creates a data stream. + + **Deprecated** This method is deprecated from v3.3.0. Use the + [createDataStream]([AgoraRtcChannel createDataStream:config:])2 method + instead. + + Each user can create up to five data streams during the lifecycle of the [AgoraRtcChannel](AgoraRtcChannel). + + **Note:** + + - Ensure that you call this method after joining a channel. + - Do not set `reliable` as `YES` while setting `ordered` as `NO`. + + @param streamId (Output parameter) The ID of the created data stream. + @param reliable Sets whether or not the recipients are guaranteed to receive the data stream from the sender within five seconds: + + * YES: The recipients receive the data stream from the sender within five seconds. If the recipient does not receive the data stream within five seconds, an error is reported to the app. + * NO: There is no guarantee that the recipients receive the data stream within five seconds and no error message is reported for any delay or missing data stream. + + @param ordered Sets whether or not the recipients receive the data stream in the sent order: + + * YES: The recipients receive the data stream in the sent order. + * NO: The recipients do not receive the data stream in the sent order. + + @return * 0: Success. +* < 0: Failure. + */ +- (int)createDataStream:(NSInteger* _Nonnull)streamId reliable:(BOOL)reliable ordered:(BOOL)ordered; +/** Creates a data stream. + + @since v3.3.0 + + Each user can create up to five data streams in a single channel. + + This method does not support data reliability. If the receiver receives a data + packet five seconds or more after it was sent, the SDK directly discards + the data. + + @param streamId ID of the created data stream. + @param config The configurations for the data stream: AgoraDataStreamConfig. + + @return * Returns the stream ID if you successfully create the data stream. +* < 0: Fails to create the data stream. + */ +- (int)createDataStream:(NSInteger* _Nonnull)streamId config:(AgoraDataStreamConfig* _Nonnull)config; +/** Sends data stream messages to all users in a channel. + +The SDK has the following restrictions on this method: + +* Up to 30 packets can be sent per second in a channel with each packet having a maximum size of 1 kB. +* Each client can send up to 6 kB of data per second. +* Each user can have up to five data streams simultaneously. + +A successful `sendStreamMessage` method call triggers the [receiveStreamMessageFromUid]([AgoraRtcChannelDelegate rtcChannel:receiveStreamMessageFromUid:streamId:data:]) callback on the remote client, from which the remote user gets the stream message. + +A failed `sendStreamMessage` method call triggers the [didOccurStreamMessageErrorFromUid]([AgoraRtcChannelDelegate rtcChannel:didOccurStreamMessageErrorFromUid:streamId:error:missed:cached:]) callback on the remote client. + + **Note** + + * This method applies only to the Communication profile or to the hosts in the interactive live streaming profile. If an audience in the interactive live streaming profile calls this method, the audience role may be changed to a host. + * Ensure that you have created the data stream using [createDataStream](createDataStream:reliable:ordered:) before calling this method. + + @param streamId ID of the sent data stream returned in the [createDataStream]([AgoraRtcChannel createDataStream:reliable:ordered:]) method. + @param data Sent data. + + @return * 0: Success. + * < 0: Failure. + */ +- (int)sendStreamMessage:(NSInteger)streamId data:(NSData* _Nonnull)data; +/** Starts to relay media streams across channels. + + After a successful method call, the SDK triggers the [channelMediaRelayStateDidChange]([AgoraRtcChannelDelegate rtcChannel:channelMediaRelayStateDidChange:error:]) and [didReceiveChannelMediaRelayEvent]([AgoraRtcChannelDelegate rtcChannel:didReceiveChannelMediaRelayEvent:]) callbacks, and these callbacks return the state and events of the media stream relay. + + - If the `channelMediaRelayStateDidChange` callback returns AgoraChannelMediaRelayStateRunning(2) and AgoraChannelMediaRelayStateIdle(0), and the `didReceiveChannelMediaRelayEvent` callback returns AgoraChannelMediaRelayEventSentToDestinationChannel(4), the SDK starts relaying media streams between the original and the destination channel. + - If the `channelMediaRelayStateDidChange` callback returns AgoraChannelMediaRelayStateFailure(3), an exception occurs during the media stream relay. + + **Note** + + - Call this method after the [joinChannelByToken]([AgoraRtcChannel joinChannelByToken:info:uid:options:]) method. + - This method takes effect only when you are a host in the interactive live streaming channel. + - After a successful method call, if you want to call this method again, ensure that you call the [stopChannelMediaRelay]([AgoraRtcChannel stopChannelMediaRelay]) method to quit the current relay. + - Contact support@agora.io before implementing this function. + - We do not support string user accounts in this API. + + @param config The configuration of the media stream relay: [AgoraChannelMediaRelayConfiguration](AgoraChannelMediaRelayConfiguration). + + @return - 0: Success. + - < 0: Failure. + */ +- (int)startChannelMediaRelay:(AgoraChannelMediaRelayConfiguration* _Nonnull)config; +/** Updates the channels for media stream relay. + + After the channel media relay starts, if you want to relay the media stream to more channels, or leave the current relay channel, you can call the `updateChannelMediaRelay` method. + + After a successful method call, the SDK triggers the [didReceiveChannelMediaRelayEvent]([AgoraRtcChannelDelegate rtcChannel:didReceiveChannelMediaRelayEvent:]) callback with the AgoraChannelMediaRelayEventUpdateDestinationChannel(7) state code. + + **Note** + + - Call this method after successfully calling the + [startChannelMediaRelay]([AgoraRtcChannel startChannelMediaRelay:]) method + and receiving the [channelMediaRelayStateDidChange]([AgoraRtcChannelDelegate rtcChannel:channelMediaRelayStateDidChange:error:]) + `(AgoraChannelMediaRelayStateRunning, AgoraChannelMediaRelayErrorNone)` callback; + otherwise, this method call fails. + - This method supports adding at most four destination channels in the relay. If there are already four destination channels in the relay, remove the unnecessary ones with the `removeDestinationInfoForChannelName` method in channelMediaRelayConfiguration before calling this method. + + @param config The media stream relay configuration: [AgoraChannelMediaRelayConfiguration](AgoraChannelMediaRelayConfiguration). + + @return - 0: Success. + - < 0: Failure. + */ +- (int)updateChannelMediaRelay:(AgoraChannelMediaRelayConfiguration* _Nonnull)config; + +/** Pauses the media stream relay to all destination channels. + + @since v3.5.1 + + After the cross-channel media stream relay starts, you can call this method to + pause relaying media streams to all destination channels; after the pause, + if you want to resume the relay, call + [resumeAllChannelMediaRelay]([AgoraRtcChannel resumeAllChannelMediaRelay]). + + After a successful method call, the SDK triggers the + [didReceiveChannelMediaRelayEvent]([AgoraRtcChannelDelegate rtcChannel:didReceiveChannelMediaRelayEvent:]) + callback to report whether the media stream relay is successfully paused. + + @note Call this method after the + [startChannelMediaRelay]([AgoraRtcChannel startChannelMediaRelay:]) method. + + @return - 0: Success. + - < 0: Failure. + */ +- (int)pauseAllChannelMediaRelay; + +/** Resumes the media stream relay to all destination channels. + + @since v3.5.1 + + After calling the [pauseAllChannelMediaRelay]([AgoraRtcChannel pauseAllChannelMediaRelay]) + method, you can call this method to resume relaying media streams to all + destination channels. + + After a successful method call, the SDK triggers the + [didReceiveChannelMediaRelayEvent]([AgoraRtcChannelDelegate rtcChannel:didReceiveChannelMediaRelayEvent:]) + callback to report whether the media stream relay is successfully resumed. + + @note Call this method after the `pauseAllChannelMediaRelay` method. + + @return - 0: Success. + - < 0: Failure. + */ +- (int)resumeAllChannelMediaRelay; + +/** Stops the media stream relay. + + Once the relay stops, the host quits all the destination channels. + + After a successful method call, the SDK triggers the [channelMediaRelayStateDidChange]([AgoraRtcChannelDelegate rtcChannel:channelMediaRelayStateDidChange:error:]) callback. If the callback returns AgoraChannelMediaRelayStateIdle(0) and AgoraChannelMediaRelayErrorNone(0), the host successfully stops the relay. + + @note If the method call fails, the SDK triggers the `channelMediaRelayStateDidChange` callback with the AgoraChannelMediaRelayErrorServerNoResponse(2) or AgoraChannelMediaRelayEventUpdateDestinationChannelRefused(8) state code. You can leave the channel by calling the [leaveChannel]([AgoraRtcChannel leaveChannel]) method, and the media stream relay automatically stops. + + @note If the method call fails, the SDK triggers the `channelMediaRelayStateDidChange` callback with the `AgoraChannelMediaRelayErrorServerNoResponse(2)` or `AgoraChannelMediaRelayEventUpdateDestinationChannelRefused(8)` error code. You can leave the channel by calling the [leaveChannel]([AgoraRtcChannel leaveChannel]) method, and the media stream relay automatically stops. + + @return - 0: Success. + - < 0: Failure. + */ +- (int)stopChannelMediaRelay; + +#if defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE +/** Enables/Disables the super resolution feature for a remote user's video. (beta feature) + + @since v3.5.1 + + This feature effectively boosts the resolution of a remote user's video seen + by the local user. If the original resolution of a remote user's video is a × b, + the local user's device can render the remote video at a resolution of 2a × 2b + after you enable this feature. + + After calling this method, the SDK triggers the + [superResolutionEnabledOfUid]([AgoraRtcChannelDelegate rtcChannel:superResolutionEnabledOfUid:enabled:reason:]) + callback to report whether you have successfully enabled super resolution. + + **Warnings** + + The super resolution feature requires extra system resources. To balance the + visual experience and system consumption, the SDK poses the following restrictions: + + - This feature can only be enabled for a single remote user. + - The original resolution of the remote user's video cannot exceed 640 × 480 pixels. + + If you exceed these limitations, the SDK triggers the + [didOccurWarning]([AgoraRtcChannelDelegate rtcChannel:didOccurWarning:]) + callback and returns the corresponding warning codes: + + - `AgoraWarningCodeSuperResolutionStreamOverLimitation(1610)`: + The original resolution of the remote user's video is beyond the range where + super resolution can be applied. + - `AgoraWarningCodeSuperResolutionUserCountOverLimitation(1611)`: Super + resolution is already being used to boost another remote user's video. + - `AgoraWarningCodeSuperResolutionDeviceNotSupported(1612)`: The device does + not support using super resolution. + + **Notes** + + - This method is for iOS only. + - Before calling this method, ensure that you have integrated the + `AgoraSuperResolutionExtension.xcframework` dynamic library into your project. + - Because this method has certain system performance requirements, Agora + recommends that you use the following iOS devices (iOS 12.0 or later) or better: + + - iPhone XR + - iPhone XS + - iPhone XS Max + - iPhone 11 + - iPhone 11 Pro + - iPhone 11 Pro Max + - iPhone 12 + - iPhone 12 mini + - iPhone 12 Pro + - iPhone 12 Pro Max + - iPhone 12 SE (2nd generation) + - iPad Pro 11-inch (3rd generation) + - iPad Pro 12.9-inch (3rd generation) + - iPad Air (3rd generation) + - iPad Air (4th generation) + + @param uid The user ID of the remote user. + @param enabled Determines whether to enable super resolution for the remote user's video: + + - `YES`: Enable super-resolution. + - `NO`: Do not enable super resolution. + + @return - 0: Success. + - < 0: Failure. + + - -157(`AgoraErrorCodeModuleNotFound`): The dynamic library for super resolution is not integrated. + */ +- (int)enableRemoteSuperResolution:(NSUInteger)uid enabled:(BOOL)enabled; +#endif + +/** Customizes the remote video renderer for the AgoraRtcChannel object. + + During real-time engagements, the Agora SDK enables the default video sink to render the video. In the multi-channel scenario, if you want to customize the video renderer, you can create a customized video sink using AgoraVideoSinkProtocol, and call `setRemoteVideoRenderer` to add the customized sink into the AgoraRtcChannel object. + + You can call this method either before or after joining a channel. If you call it before joining a channel, you need to maintain the `uid` of the remote user on your app level. + + @param videoRenderer The customized remote video renderer: AgoraVideoSinkProtocol. + @param userId The ID of the remote user. + */ +- (void)setRemoteVideoRenderer:(id _Nullable)videoRenderer forUserId:(NSUInteger)userId; + +/** Gets the customized remote video renderer for the AgoraRtcChannel object. + + @param userId The ID of the remote user. + + @return The customized remote video renderer: AgoraVideoSourceProtocol. +*/ +- (id _Nullable)remoteVideoRendererOfUserId:(NSUInteger)userId; + +/** Sets the data source of the metadata. + + You need to implement the [AgoraMediaMetadataDataSource](AgoraMediaMetadataDataSource) protocol and specify the type of metadata in this method. + + Use this method with the [setMediaMetadataDelegate]([AgoraRtcChannel setMediaMetadataDelegate:withType:]) method to add synchronized metadata in the video stream. You can create more diversified interactive live streaming interactions, such as sending shopping links, digital coupons, and online quizzes. + + **Note** + + - Call this method before the [joinChannelByToken]([AgoraRtcChannel joinChannelByToken:info:uid:options:]) method. + - This method applies to the interactive live streaming channel profile only. + + @param metadataDataSource The AgoraMediaMetadataDataSource protocol. + @param type The metadata type. See [AgoraMetadataType](AgoraMetadataType). Currently, the SDK supports video metadata only. + + @return * YES: Success. + * NO: Failure. + */ +- (BOOL)setMediaMetadataDataSource:(id _Nullable)metadataDataSource withType:(AgoraMetadataType)type; +/** Sets the delegate of the metadata. + + You need to implement the AgoraMediaMetadataDelegate protocol and specify the type of metadata in this method. + + **Note** + + - Call this method before the [joinChannelByToken]([AgoraRtcChannel joinChannelByToken:info:uid:options:]) method. + - This method applies to the interactive live streaming channel profile only. + + @param metadataDelegate The AgoraMediaMetadataDelegate protocol. + @param type The metadata type. See [AgoraMetadataType](AgoraMetadataType). Currently, the SDK supports video metadata only. + + @return * YES: Success. + * NO: Failure. + */ +- (BOOL)setMediaMetadataDelegate:(id _Nullable)metadataDelegate withType:(AgoraMetadataType)type; + +@end +/** The AgoraRtcChannelDelegate class. + + **Since** v3.0.0. + */ +@protocol AgoraRtcChannelDelegate +@optional +/** Reports a warning during SDK runtime. + + In most cases, the app can ignore the warning reported by the SDK because the SDK can usually fix the issue and resume running. + + For instance, the SDK may report an AgoraWarningCodeOpenChannelTimeout(106) warning upon disconnection from the server and attempts to reconnect. + + See [AgoraWarningCode](AgoraWarningCode). + + @param rtcChannel AgoraRtcChannel + @param warningCode Warning code: AgoraWarningCode + */ +- (void)rtcChannel:(AgoraRtcChannel* _Nonnull)rtcChannel didOccurWarning:(AgoraWarningCode)warningCode; +/** Reports an error during SDK runtime. + +In most cases, the SDK cannot fix the issue and resume running. The SDK requires the app to take action or informs the user about the issue. + +For example, the SDK reports an AgoraErrorCodeStartCall = 1002 error when failing to initialize a call. The app informs the user that the call initialization failed and invokes the [leaveChannel]([AgoraRtcChannel leaveChannel]) method to leave the channel. + +See [AgoraErrorCode](AgoraErrorCode). + + @param rtcChannel AgoraRtcChannel + @param errorCode Error code: AgoraErrorCode + */ +- (void)rtcChannel:(AgoraRtcChannel* _Nonnull)rtcChannel didOccurError:(AgoraErrorCode)errorCode; +/** Occurs when the local user joins a specified channel. + + @param rtcChannel AgoraRtcChannel + @param uid User ID. If the `uid` is specified in the [joinChannelByToken]([AgoraRtcChannel joinChannelByToken:info:uid:options:]) method, the specified user ID is returned. If the user ID is not specified when the `joinChannelByToken` method is called, the server automatically assigns a `uid`. + @param elapsed Time elapsed (ms) from the user calling the `joinChannelByToken` method until the SDK triggers this callback. + */ +- (void)rtcChannelDidJoinChannel:(AgoraRtcChannel* _Nonnull)rtcChannel withUid:(NSUInteger)uid elapsed:(NSInteger)elapsed; +/** Occurs when the local user rejoins a channel. + + If the client loses connection with the server because of network problems, the SDK automatically attempts to reconnect and then triggers this callback upon reconnection, indicating that the user rejoins the channel with the assigned channel ID and user ID. + + @param rtcChannel AgoraRtcChannel + @param uid User ID. If the `uid` is specified in the [joinChannelByToken]([AgoraRtcChannel joinChannelByToken:info:uid:options:]) method, the specified user ID is returned. If the user ID is not specified when the `joinChannelByToken` method is called, the server automatically assigns a `uid`. + @param elapsed Time elapsed (ms) from starting to reconnect to a successful reconnection. + */ +- (void)rtcChannelDidRejoinChannel:(AgoraRtcChannel* _Nonnull)rtcChannel withUid:(NSUInteger)uid elapsed:(NSInteger)elapsed; +/** Occurs when the local user leaves a channel. + + When the app calls the [leaveChannel]([AgoraRtcChannel leaveChannel]) method, this callback notifies the app that a user leaves a channel. + + With this callback, the app gets information, such as the call duration and the statistics. + + @param rtcChannel AgoraRtcChannel + @param stats Statistics of the call: [AgoraChannelStats](AgoraChannelStats). + */ +- (void)rtcChannelDidLeaveChannel:(AgoraRtcChannel* _Nonnull)rtcChannel withStats:(AgoraChannelStats* _Nonnull)stats; +/** Occurs when the local user role switches in the interactive live streaming. + +The SDK triggers this callback when the local user switches the user role by calling the [setClientRole]([AgoraRtcChannel setClientRole:]) method after joining the channel. + + @param rtcChannel AgoraRtcChannel + @param oldRole Role that the user switches from: AgoraClientRole. + @param newRole Role that the user switches to: AgoraClientRole. + */ +- (void)rtcChannel:(AgoraRtcChannel* _Nonnull)rtcChannel didClientRoleChanged:(AgoraClientRole)oldRole newRole:(AgoraClientRole)newRole; +/** Occurs when a remote user or host joins a channel. + + - Communication profile: This callback notifies the app that another user joins the channel. If other users are already in the channel, the SDK also reports to the app on the existing users. + - Interactive live streaming profile: This callback notifies the app that a host joins the channel. If other hosts are already in the channel, the SDK also reports to the app on the existing hosts. Agora recommends limiting the number of hosts to 17. + + The SDK triggers this callback under one of the following circumstances: + - A remote user/host joins the channel by calling the [joinChannelByToken]([AgoraRtcChannel joinChannelByToken:info:uid:options:]) method. + - A remote user switches the user role to the host by calling the [setClientRole]([AgoraRtcChannel setClientRole:]) method after joining the channel. + - A remote user/host rejoins the channel after a network interruption. + - A host injects an online media stream into the channel by calling the [addInjectStreamUrl]([AgoraRtcChannel addInjectStreamUrl:config:]) method. + + **Note** + + Interactive live streaming profile: + + * The host receives this callback when another host joins the channel. + * The audience in the channel receives this callback when a new host joins the channel. + * When a web application joins the channel, the SDK triggers this callback as long as the web application publishes streams. + + @param rtcChannel AgoraRtcChannel + @param uid ID of the user or host who joins the channel. If the `uid` is specified in the `joinChannelByToken` method, the specified user ID is returned. If the `uid` is not specified in the `joinChannelByToken` method, the Agora server automatically assigns a `uid`. + @param elapsed Time elapsed (ms) from the local user calling the `joinChannelByToken` method until the SDK triggers this callback. + */ +- (void)rtcChannel:(AgoraRtcChannel* _Nonnull)rtcChannel didJoinedOfUid:(NSUInteger)uid elapsed:(NSInteger)elapsed; +/** Occurs when a remote user (Communication)/host (Live Broadcast) leaves a channel. + +There are two reasons for users to be offline: + +- Leave a channel: When the user/host leaves a channel, the user/host sends a goodbye message. When the message is received, the SDK assumes that the user/host leaves a channel. +- Drop offline: When no data packet of the user or host is received for a certain period of time (20 seconds for the Communication profile, and more for the interactive live streaming profile), the SDK assumes that the user/host drops offline. Unreliable network connections may lead to false detections, so Agora recommends using the [Agora RTM SDK](https://docs.agora.io/en/Real-time-Messaging/product_rtm?platform=All%20Platforms) for more reliable offline detection. + + @param rtcChannel AgoraRtcChannel + @param uid ID of the user or host who leaves a channel or goes offline. + @param reason Reason why the user goes offline, see AgoraUserOfflineReason. + */ +- (void)rtcChannel:(AgoraRtcChannel* _Nonnull)rtcChannel didOfflineOfUid:(NSUInteger)uid reason:(AgoraUserOfflineReason)reason; +/** Occurs when the network connection state changes. + +The SDK triggers this callback to report on the current network connection state when it changes, and the reason of the change. + +@param rtcChannel AgoraRtcChannel +@param state The current network connection state, see AgoraConnectionStateType. +@param reason The reason of the connection state change, see AgoraConnectionChangedReason. + */ +- (void)rtcChannel:(AgoraRtcChannel* _Nonnull)rtcChannel connectionChangedToState:(AgoraConnectionStateType)state reason:(AgoraConnectionChangedReason)reason; +/** Occurs when the SDK cannot reconnect to Agora's edge server 10 seconds after its connection to the server is interrupted. + +The SDK triggers this callback when it cannot connect to the server 10 seconds after calling the [joinChannelByToken]([AgoraRtcChannel joinChannelByToken:info:uid:options:]) method, regardless of whether it is in the channel or not. + +If the SDK fails to rejoin the channel 20 minutes after being disconnected from Agora's edge server, the SDK stops rejoining the channel. + +@param rtcChannel AgoraRtcChannel + */ +- (void)rtcChannelDidLost:(AgoraRtcChannel* _Nonnull)rtcChannel; +/** Occurs when the token expires in 30 seconds. + + The user becomes offline if the `token` used in the [joinChannelByToken]([AgoraRtcChannel joinChannelByToken:info:uid:options:]) method expires. The SDK triggers this callback 30 seconds before the `token` expires to remind the app to get a new `token`. + Upon receiving this callback, generate a new `token` on the server and call the [renewToken]([AgoraRtcChannel renewToken:]) method to pass the new `token` to the SDK. + + @param rtcChannel AgoraRtcChannel + @param token The `token` that expires in 30 seconds. + */ +- (void)rtcChannel:(AgoraRtcChannel* _Nonnull)rtcChannel tokenPrivilegeWillExpire:(NSString* _Nonnull)token; +/** Occurs when the token expires. + + After a `token` is specified by calling the [joinChannelByToken]([AgoraRtcChannel joinChannelByToken:info:uid:options:]) method, if the SDK losses connection to the Agora server due to network issues, the `token` may expire after a certain period of time and a new `token` may be required to reconnect to the server. + + Once you receive this callback, generate a new token on your app server, and call [renewToken]([AgoraRtcChannel renewToken:]) to pass the new token to the SDK. + + @param rtcChannel AgoraRtcChannel + */ +- (void)rtcChannelRequestToken:(AgoraRtcChannel* _Nonnull)rtcChannel; +/** Occurs when the most active remote speaker is detected. + + After a successful call of [enableAudioVolumeIndication]([AgoraRtcEngineKit enableAudioVolumeIndication:smooth:report_vad:]), + the SDK continuously detects which remote user has the loudest volume. During the current period, the remote user, + who is detected as the loudest for the most times, is the most active user. + + When the number of users is more than or equal to two and an active speaker exists, the SDK triggers this callback and reports the `uid` of the most active speaker. + + - If the most active speaker is always the same user, the SDK triggers this callback only once. + - If the most active speaker changes to another user, the SDK triggers this callback again and reports the `uid` of the new active speaker. + + @param rtcChannel AgoraRtcChannel + @param speakerUid The user ID of the most active remote speaker. + */ +- (void)rtcChannel:(AgoraRtcChannel* _Nonnull)rtcChannel activeSpeaker:(NSUInteger)speakerUid; +/** Occurs when the video size or rotation of a specific remote user changes. + + @param rtcChannel AgoraRtcChannel + @param uid User ID of the remote user or local user (0) whose video size or rotation changes. + @param size New video size. + @param rotation New rotation of the video. The value ranges between 0 and 360. + */ +- (void)rtcChannel:(AgoraRtcChannel* _Nonnull)rtcChannel videoSizeChangedOfUid:(NSUInteger)uid size:(CGSize)size rotation:(NSInteger)rotation; +/** Occurs when the remote video state changes. + + @param rtcChannel AgoraRtcChannel + @param uid ID of the remote user whose video state changes. + @param state The state of the remote video. See [AgoraVideoRemoteState](AgoraVideoRemoteState). + @param reason The reason of the remote video state change. See [AgoraVideoRemoteStateReason](AgoraVideoRemoteStateReason). + @param elapsed The time elapsed (ms) from the local user calling the [joinChannelByToken]([AgoraRtcChannel joinChannelByToken:info:uid:options:]) method until the SDK triggers this callback. + */ +- (void)rtcChannel:(AgoraRtcChannel* _Nonnull)rtcChannel remoteVideoStateChangedOfUid:(NSUInteger)uid state:(AgoraVideoRemoteState)state reason:(AgoraVideoRemoteStateReason)reason elapsed:(NSInteger)elapsed; +; + +/** Reports whether the super resolution feature is successfully enabled. (beta feature) + + @since v3.5.1 + + After calling [enableRemoteSuperResolution]([AgoraRtcChannel enableRemoteSuperResolution:enabled:]), + the SDK triggers this callback to report whether super resolution is successfully enabled. + If it is not successfully enabled, use `reason` for troubleshooting. + + @param rtcChannel AgoraRtcChannel + @param uid The user ID of the remote user. + @param enabled Whether super resolution is successfully enabled: + + - `YES`: Super resolution is successfully enabled. + - `NO`: Super resolution is not successfully enabled. + @param reason The reason why super resolution is not successfully enabled or + the message that confirms success. See [AgoraSuperResolutionStateReason](AgoraSuperResolutionStateReason). + */ +- (void)rtcChannel:(AgoraRtcChannel* _Nonnull)rtcChannel superResolutionEnabledOfUid:(NSUInteger)uid enabled:(BOOL)enabled reason:(AgoraSuperResolutionStateReason)reason; + +/** Occurs when the local audio state changes. + + This callback indicates the state change of the local audio stream, including the state of the audio sampling and encoding, and allows you to troubleshoot issues when exceptions occur. + + @param rtcChannel AgoraRtcChannel + @param uid ID of the remote user whose audio state changes. + @param state State of the remote audio. See [AgoraAudioRemoteState](AgoraAudioRemoteState). + @param reason The reason of the remote audio state change. See [AgoraAudioRemoteStateReason](AgoraAudioRemoteStateReason). + @param elapsed Time elapsed (ms) from the local user calling the [joinChannelByToken]([AgoraRtcChannel joinChannelByToken:info:uid:options:]) method until the SDK triggers this callback. + */ +- (void)rtcChannel:(AgoraRtcChannel* _Nonnull)rtcChannel remoteAudioStateChangedOfUid:(NSUInteger)uid state:(AgoraAudioRemoteState)state reason:(AgoraAudioRemoteStateReason)reason elapsed:(NSInteger)elapsed; +/** Occurs when the published video stream falls back to an audio-only stream due to unreliable network conditions or switches back to the video when the network conditions improve. + + If you call the [setLocalPublishFallbackOption]([AgoraRtcEngineKit setLocalPublishFallbackOption:]) method and set `option` as AgoraStreamFallbackOptionAudioOnly, the SDK triggers this callback when the published stream falls back to audio-only mode due to unreliable uplink conditions, or when the audio stream switches back to the video when the uplink network condition improves. + + **Note** + + Once the published stream falls back to audio only, the remote app receives the [userMuteVideoBlock]([AgoraRtcEngineKit userMuteVideoBlock:]) callback. + + @param rtcChannel AgoraRtcChannel + @param isFallbackOrRecover Whether the published stream falls back to audio-only or switches back to the video: + + * YES: The published stream falls back to audio-only due to unreliable network conditions. + * NO: The published stream switches back to the video after the network conditions improve. + */ +- (void)rtcChannel:(AgoraRtcChannel* _Nonnull)rtcChannel didLocalPublishFallbackToAudioOnly:(BOOL)isFallbackOrRecover; +/** Occurs when the remote video stream falls back to an audio-only stream due to unreliable network conditions or switches back to the video after the network conditions improve. + + If you call [setRemoteSubscribeFallbackOption]([AgoraRtcEngineKit setRemoteSubscribeFallbackOption:]) and set `option` as `AgoraStreamFallbackOptionAudioOnly`, the SDK triggers this callback when the remote media stream falls back to audio only due to poor downlink conditions or switches back to the video after the downlink network condition improves. + + **Note:** + + Once the remote media stream is switched to the low stream due to unreliable network conditions, you can monitor the stream switch between a high stream and low stream in the [remoteVideoStats]([AgoraRtcChannelDelegate rtcChannel:remoteVideoStats:]) callback. + + @param rtcChannel AgoraRtcChannel + @param isFallbackOrRecover Whether the remote media stream falls back to audio-only or switches back to the video: + + * YES: The remote media stream falls back to audio-only due to unreliable network conditions. + * NO: The remote media stream switches back to the video stream after the network conditions improve. + @param uid ID of the remote user sending the stream. + */ +- (void)rtcChannel:(AgoraRtcChannel* _Nonnull)rtcChannel didRemoteSubscribeFallbackToAudioOnly:(BOOL)isFallbackOrRecover byUid:(NSUInteger)uid; +/** Reports the statistics of the current call. The SDK triggers this callback once every two seconds after the user joins the channel. + + @param rtcChannel AgoraRtcChannel + @param stats Statistics of the AgoraRtcEngineKit: [AgoraChannelStats](AgoraChannelStats). + */ +- (void)rtcChannel:(AgoraRtcChannel* _Nonnull)rtcChannel reportRtcStats:(AgoraChannelStats* _Nonnull)stats; +/** Reports the last mile network quality of each user in the channel once every two seconds. + + Last mile refers to the connection between the local device and Agora's edge server. The SDK triggers this callback once every two seconds to report the last mile network conditions of each user in the channel. If a channel includes multiple users, the SDK triggers this callback as many times. + + @note `txQuality` is `Unknown` when the user is not sending a stream; `rxQuality` is `Unknown` when the user is not receiving a stream. + + @param rtcChannel AgoraRtcChannel + @param uid User ID. The network quality of the user with this `uid` is reported. If `uid` is 0, the local network quality is reported. + @param txQuality Uplink transmission quality of the user in terms of the transmission bitrate, packet loss rate, average RTT (Round-Trip Time), and jitter of the uplink network. `txQuality` is a quality rating helping you understand how well the current uplink network conditions can support the selected AgoraVideoEncoderConfiguration. For example, a 1000-Kbps uplink network may be adequate for video frames with a resolution of 640 * 480 and a frame rate of 15 fps in the interactive live streaming profile, but may be inadequate for resolutions higher than 1280 * 720. See AgoraNetworkQuality. + @param rxQuality Downlink network quality rating of the user in terms of packet loss rate, average RTT, and jitter of the downlink network. See AgoraNetworkQuality. + */ +- (void)rtcChannel:(AgoraRtcChannel* _Nonnull)rtcChannel networkQuality:(NSUInteger)uid txQuality:(AgoraNetworkQuality)txQuality rxQuality:(AgoraNetworkQuality)rxQuality; +/** Reports the statistics of the video stream from each remote user/host. + + The SDK triggers this callback once every two seconds for each remote user/host. If a channel includes multiple remote users, the SDK triggers this callback as many times. + + This callback reports the statistics more closely linked to the real-user experience of the video transmission quality than the statistics that the [videoTransportStatsOfUid]([AgoraRtcEngineDelegate rtcEngine:videoTransportStatsOfUid:delay:lost:rxKBitRate:]) callback reports. This callback reports more about media layer statistics such as the frame loss rate, while the `videoTransportStatsOfUid` callback reports more about the transport layer statistics such as the packet loss rate. + +Schemes such as FEC (Forward Error Correction) or retransmission counter the frame loss rate. Hence, users may find the overall video quality acceptable even when the packet loss rate is high. + + @param rtcChannel AgoraRtcChannel + @param stats Statistics of the received remote video streams. See [AgoraRtcRemoteVideoStats](AgoraRtcRemoteVideoStats). + */ +- (void)rtcChannel:(AgoraRtcChannel* _Nonnull)rtcChannel remoteVideoStats:(AgoraRtcRemoteVideoStats* _Nonnull)stats; +/** Reports the statistics of the audio stream from each remote user/host. + + The SDK triggers this callback once every two seconds for each remote user/host. If a channel includes multiple remote users, the SDK triggers this callback as many times. + + This callback reports the statistics more closely linked to the real-user experience of the audio transmission quality than the statistics that the [audioTransportStatsOfUid]([AgoraRtcEngineDelegate rtcEngine:audioTransportStatsOfUid:delay:lost:rxKBitRate:]) callback reports. This callback reports more about media layer statistics such as the frame loss rate, while the `audioTransportStatsOfUid` callback reports more about the transport layer statistics such as the packet loss rate. + +Schemes such as FEC (Forward Error Correction) or retransmission counter the frame loss rate. Hence, users may find the overall audio quality acceptable even when the packet loss rate is high. + + @param rtcChannel AgoraRtcChannel + @param stats Statistics of the received remote audio streams. See AgoraRtcRemoteAudioStats. + */ +- (void)rtcChannel:(AgoraRtcChannel* _Nonnull)rtcChannel remoteAudioStats:(AgoraRtcRemoteAudioStats* _Nonnull)stats; +/** Occurs when the state of the RTMP or RTMPS streaming changes. + +The SDK triggers this callback to report the result of the local user calling the [addPublishStreamUrl]([AgoraRtcChannel addPublishStreamUrl:transcodingEnabled:]) or [removePublishStreamUrl]([AgoraRtcChannel removePublishStreamUrl:]) method. + +This callback returns the URL and its current streaming state. + +This callback indicates the state of the RTMP or RTMPS streaming. When exceptions occur, you can troubleshoot issues by referring to the detailed error descriptions in the `errorCode` parameter. + +@param rtcChannel AgoraRtcChannel +@param url The CDN streaming URL. +@param state The RTMP or RTMPS streaming state: AgoraRtmpStreamingState. +@param errorCode The detailed error information for streaming: AgoraRtmpStreamingErrorCode. + */ +- (void)rtcChannel:(AgoraRtcChannel* _Nonnull)rtcChannel rtmpStreamingChangedToState:(NSString* _Nonnull)url state:(AgoraRtmpStreamingState)state errorCode:(AgoraRtmpStreamingErrorCode)errorCode; + +/** Reports events during the RTMP or RTMPS streaming. + + @since v3.1.0 + + @param rtcChannel AgoraRtcChannel + @param url The RTMP or RTMPS streaming URL. + @param eventCode The event code. See AgoraRtmpStreamingEvent. + */ +- (void)rtcChannel:(AgoraRtcChannel* _Nonnull)rtcChannel rtmpStreamingEventWithUrl:(NSString* _Nonnull)url eventCode:(AgoraRtmpStreamingEvent)eventCode; + +/** Occurs when the CDN live streaming settings are updated. + + When the `LiveTranscoding` class in the [setLiveTranscoding]([AgoraRtcChannel setLiveTranscoding:]) method updates, the SDK triggers the `rtcChannelTranscodingUpdated` callback to report the update information to the local host. + + **Note:** + + If you call the `setLiveTranscoding` method to set the `LiveTranscoding` class for the first time, the SDK does not trigger the `rtcChannelTranscodingUpdated` callback. + + @param rtcChannel AgoraRtcChannel + */ +- (void)rtcChannelTranscodingUpdated:(AgoraRtcChannel* _Nonnull)rtcChannel; + +#pragma mark Inject Stream URL Delegate Methods +/** Reports the status of injecting an online stream to the interactive live streaming. + + @warning Agora will soon stop the service for injecting online media streams on the client. If you have not implemented this service, Agora recommends that you do not use it. + + @param rtcChannel AgoraRtcChannel + @param url URL address of the externally injected stream. + @param uid User ID. + @param status Status of the externally injected stream. See AgoraInjectStreamStatus. + */ +- (void)rtcChannel:(AgoraRtcChannel* _Nonnull)rtcChannel streamInjectedStatusOfUrl:(NSString* _Nonnull)url uid:(NSUInteger)uid status:(AgoraInjectStreamStatus)status; + +#pragma mark Stream Message Delegate Methods + +/** Occurs when the local user receives the data stream from a remote user within five seconds. + +The SDK triggers this callback when the local user receives the stream message that the remote user sends by calling the [sendStreamMessage]([AgoraRtcChannel sendStreamMessage:data:]) method. + + @param rtcChannel AgoraRtcChannel + @param uid User ID of the remote user sending the message. + @param streamId Stream ID. + @param data Data received by the local user. + */ +- (void)rtcChannel:(AgoraRtcChannel* _Nonnull)rtcChannel receiveStreamMessageFromUid:(NSUInteger)uid streamId:(NSInteger)streamId data:(NSData* _Nonnull)data; +/** Occurs when the local user does not receive the data stream from the remote user within five seconds. + + The SDK triggers this callback when the local user fails to receive the stream message that the remote user sends by calling the [sendStreamMessage]([AgoraRtcChannel sendStreamMessage:data:]) method. + + @param rtcChannel AgoraRtcChannel + @param uid User ID of the remote user sending the message. + @param streamId Stream ID. + @param error Error code. See AgoraErrorCode. + @param missed Number of lost messages. + @param cached Number of incoming cached messages when the data stream is interrupted. + */ +- (void)rtcChannel:(AgoraRtcChannel* _Nonnull)rtcChannel didOccurStreamMessageErrorFromUid:(NSUInteger)uid streamId:(NSInteger)streamId error:(NSInteger)error missed:(NSInteger)missed cached:(NSInteger)cached; +/** Occurs when the state of the media stream relay changes. + + The SDK reports the state of the current media relay and possible error messages in this callback. + + @param rtcChannel AgoraRtcChannel + @param state The state code in [AgoraChannelMediaRelayState](AgoraChannelMediaRelayState). + @param error The error code in [AgoraChannelMediaRelayError](AgoraChannelMediaRelayError). + */ +- (void)rtcChannel:(AgoraRtcChannel* _Nonnull)rtcChannel channelMediaRelayStateDidChange:(AgoraChannelMediaRelayState)state error:(AgoraChannelMediaRelayError)error; +/** Reports events during the media stream relay. + + @param rtcChannel AgoraRtcChannel + @param event The event code in [AgoraChannelMediaRelayEvent](AgoraChannelMediaRelayEvent). + */ +- (void)rtcChannel:(AgoraRtcChannel* _Nonnull)rtcChannel didReceiveChannelMediaRelayEvent:(AgoraChannelMediaRelayEvent)event; +/** Occurs when the audio publishing state changes. + + @since v3.1.0 + + This callback indicates the publishing state change of the local audio stream. + + @param rtcChannel AgoraRtcChannel + @param oldState The previous publishing state. For details, see AgoraStreamPublishState. + @param newState The current publishing state. For details, see AgoraStreamPublishState. + @param elapseSinceLastState The time elapsed (ms) from the previous state to the current state. + */ +- (void)rtcChannel:(AgoraRtcChannel* _Nonnull)rtcChannel didAudioPublishStateChange:(AgoraStreamPublishState)oldState newState:(AgoraStreamPublishState)newState elapseSinceLastState:(NSInteger)elapseSinceLastState; + +/** Occurs when the video publishing state changes. + + @since v3.1.0 + + This callback indicates the publishing state change of the local video stream. + + @param rtcChannel AgoraRtcChannel + @param oldState The previous publishing state. For details, see AgoraStreamPublishState. + @param newState The current publishing state. For details, see AgoraStreamPublishState. + @param elapseSinceLastState The time elapsed (ms) from the previous state to the current state. + */ +- (void)rtcChannel:(AgoraRtcChannel* _Nonnull)rtcChannel didVideoPublishStateChange:(AgoraStreamPublishState)oldState newState:(AgoraStreamPublishState)newState elapseSinceLastState:(NSInteger)elapseSinceLastState; + +/** Occurs when the audio subscribing state changes. + + @since v3.1.0 + + This callback indicates the subscribing state change of a remote audio stream. + + @param rtcChannel AgoraRtcChannel + @param uid The ID of the remote user. + @param oldState The previous subscribing state. For details, see AgoraStreamSubscribeState. + @param newState The current subscribing state. For details, see AgoraStreamSubscribeState. + @param elapseSinceLastState The time elapsed (ms) from the previous state to the current state. + */ +- (void)rtcChannel:(AgoraRtcChannel* _Nonnull)rtcChannel didAudioSubscribeStateChange:(NSUInteger)uid oldState:(AgoraStreamSubscribeState)oldState newState:(AgoraStreamSubscribeState)newState elapseSinceLastState:(NSInteger)elapseSinceLastState; + +/** Occurs when the video subscribing state changes. + + @since v3.1.0 + + This callback indicates the subscribing state change of a remote video stream. + + @param rtcChannel AgoraRtcChannel + @param uid The ID of the remote user. + @param oldState The previous subscribing state. For details, see AgoraStreamSubscribeState. + @param newState The current subscribing state. For details, see AgoraStreamSubscribeState. + @param elapseSinceLastState The time elapsed (ms) from the previous state to the current state. + */ +- (void)rtcChannel:(AgoraRtcChannel* _Nonnull)rtcChannel didVideoSubscribeStateChange:(NSUInteger)uid oldState:(AgoraStreamSubscribeState)oldState newState:(AgoraStreamSubscribeState)newState elapseSinceLastState:(NSInteger)elapseSinceLastState; + +@end diff --git a/integration_test_app/iris_integration_test/third_party/agora/rtc/include/AgoraRtcEngineKit.h b/integration_test_app/iris_integration_test/third_party/agora/rtc/include/AgoraRtcEngineKit.h new file mode 100644 index 000000000..67e542ebf --- /dev/null +++ b/integration_test_app/iris_integration_test/third_party/agora/rtc/include/AgoraRtcEngineKit.h @@ -0,0 +1,6727 @@ +// +// AgoraRtcEngineKit.h +// AgoraRtcEngineKit +// +// Copyright (c) 2018 Agora. All rights reserved. +// + +#import +#import "AgoraConstants.h" +#import "AgoraObjects.h" +#import "AgoraMediaIO.h" +#import "AgoraMediaMetadata.h" +#import "AgoraLogWriter.h" +#import "AgoraAudioFrame.h" +#import "AgoraVideoFrame.h" + +/** Agora provides ensured quality of experience (QoE) for worldwide Internet-based voice and video communications through a virtual global network optimized for real-time web and mobile-to-mobile applications. + + The AgoraRtcEngineKit class is the entry point of the SDK providing API methods for apps to easily start voice and video communication. + */ +@class AgoraRtcEngineKit; +/** The AgoraRtcChannel class. + */ +@class AgoraRtcChannel; + +/** The AgoraRtcEngineDelegate protocol enables callbacks to your app. + + The SDK uses delegate callbacks in the AgoraRtcEngineDelegate protocol to report runtime events to the app. + From v1.1, some block callbacks in the SDK are replaced with delegate callbacks. The old block callbacks are therefore deprecated, but can still be used in the current version. However, Agora recommends replacing block callbacks with delegate callbacks. The SDK calls the block callback if a callback is defined in both the block and delegate callbacks. + */ +@protocol AgoraRtcEngineDelegate +@optional + +#pragma mark Core Delegate Methods + +/**----------------------------------------------------------------------------- + * @name Core Delegate Methods + * ----------------------------------------------------------------------------- + */ + +/** Reports a warning during SDK runtime. + + In most cases, the app can ignore the warning reported by the SDK because the SDK can usually fix the issue and resume running. + + For instance, the SDK may report an AgoraWarningCodeOpenChannelTimeout(106) warning upon disconnection from the server and attempts to reconnect. + + See [AgoraWarningCode](AgoraWarningCode). + + @param engine AgoraRtcEngineKit object + @param warningCode Warning code: AgoraWarningCode + */ +- (void)rtcEngine:(AgoraRtcEngineKit* _Nonnull)engine didOccurWarning:(AgoraWarningCode)warningCode; + +/** Reports an error during SDK runtime. + +In most cases, the SDK cannot fix the issue and resume running. The SDK requires the app to take action or informs the user about the issue. + +For example, the SDK reports an AgoraErrorCodeStartCall = 1002 error when failing to initialize a call. The app informs the user that the call initialization failed and invokes the [leaveChannel]([AgoraRtcEngineKit leaveChannel:]) method to leave the channel. + +See [AgoraErrorCode](AgoraErrorCode). + + @param engine AgoraRtcEngineKit object + @param errorCode Error code: AgoraErrorCode + */ +- (void)rtcEngine:(AgoraRtcEngineKit* _Nonnull)engine didOccurError:(AgoraErrorCode)errorCode; + +/** Occurs when a method is executed by the SDK. + + @param engine AgoraRtcEngineKit object. + @param error The error code (AgoraErrorCode) returned by the SDK when the method call fails. If the SDK returns 0, then the method call succeeds. + @param api The method executed by the SDK. + @param result The result of the method call. + */ +- (void)rtcEngine:(AgoraRtcEngineKit* _Nonnull)engine didApiCallExecute:(NSInteger)error api:(NSString* _Nonnull)api result:(NSString* _Nonnull)result; + +/** Occurs when the local user joins a specified channel. + + Same as `joinSuccessBlock` in the [joinChannelByToken]([AgoraRtcEngineKit joinChannelByToken:channelId:info:uid:joinSuccess:]) method. + + @param engine AgoraRtcEngineKit object. + @param channel Channel name. + @param uid User ID. If the `uid` is specified in the [joinChannelByToken]([AgoraRtcEngineKit joinChannelByToken:channelId:info:uid:joinSuccess:]) method, the specified user ID is returned. If the user ID is not specified when the joinChannel method is called, the server automatically assigns a `uid`. + @param elapsed Time elapsed (ms) from the user calling the [joinChannelByToken]([AgoraRtcEngineKit joinChannelByToken:channelId:info:uid:joinSuccess:]) method until the SDK triggers this callback. + */ +- (void)rtcEngine:(AgoraRtcEngineKit* _Nonnull)engine didJoinChannel:(NSString* _Nonnull)channel withUid:(NSUInteger)uid elapsed:(NSInteger)elapsed; + +/** Occurs when the local user rejoins a channel. + + If the client loses connection with the server because of network problems, the SDK automatically attempts to reconnect and then triggers this callback upon reconnection, indicating that the user rejoins the channel with the assigned channel ID and user ID. + + @param engine AgoraRtcEngineKit object. + @param channel Channel name. + @param uid User ID. If the `uid` is specified in the [joinChannelByToken]([AgoraRtcEngineKit joinChannelByToken:channelId:info:uid:joinSuccess:]) method, the specified user ID is returned. If the user ID is not specified when the joinChannel method is called, the server automatically assigns a `uid`. + @param elapsed Time elapsed (ms) from starting to reconnect to a successful reconnection. + */ +- (void)rtcEngine:(AgoraRtcEngineKit* _Nonnull)engine didRejoinChannel:(NSString* _Nonnull)channel withUid:(NSUInteger)uid elapsed:(NSInteger)elapsed; + +/** Occurs when the local user leaves a channel. + + When the app calls the [leaveChannel]([AgoraRtcEngineKit leaveChannel:]) method, this callback notifies the app that a user leaves a channel. + + With this callback, the app gets information, such as the call duration and the statistics of the received/transmitted data reported by the [audioQualityOfUid]([AgoraRtcEngineDelegate rtcEngine:audioQualityOfUid:quality:delay:lost:]) callback. + + @param engine AgoraRtcEngineKit object. + @param stats Statistics of the call: [AgoraChannelStats](AgoraChannelStats). + */ +- (void)rtcEngine:(AgoraRtcEngineKit* _Nonnull)engine didLeaveChannelWithStats:(AgoraChannelStats* _Nonnull)stats; + +/** Occurs when the local user successfully registers a user account by calling the [registerLocalUserAccount]([AgoraRtcEngineKit registerLocalUserAccount:appId:]) or [joinChannelByUserAccount]([AgoraRtcEngineKit joinChannelByUserAccount:token:channelId:joinSuccess:]) method. + +This callback reports the user ID and user account of the local user. + +@param engine AgoraRtcEngineKit object. +@param userAccount The user account of the local user. +@param uid The ID of the local user. +*/ +- (void)rtcEngine:(AgoraRtcEngineKit* _Nonnull)engine didRegisteredLocalUser:(NSString* _Nonnull)userAccount withUid:(NSUInteger)uid; + +/** Occurs when the SDK gets the user ID and user account of the remote user. + +After a remote user joins the channel, the SDK gets the user ID and user account of the remote user, caches them in a mapping table object (`userInfo`), and triggers this callback on the local client. + +@param engine AgoraRtcEngineKit object. +@param userInfo The [AgoraUserInfo](AgoraUserInfo) object that contains the user ID and user account of the remote user. +@param uid The ID of the remote user. +*/ +- (void)rtcEngine:(AgoraRtcEngineKit* _Nonnull)engine didUpdatedUserInfo:(AgoraUserInfo* _Nonnull)userInfo withUid:(NSUInteger)uid; + +/** Occurs when the local user role switches in the interactive live streaming. + +The SDK triggers this callback when the local user switches the user role by calling the [setClientRole]([AgoraRtcEngineKit setClientRole:]) method after joining the channel. + + @param engine AgoraRtcEngineKit object. + @param oldRole Role that the user switches from: AgoraClientRole. + @param newRole Role that the user switches to: AgoraClientRole. + */ +- (void)rtcEngine:(AgoraRtcEngineKit* _Nonnull)engine didClientRoleChanged:(AgoraClientRole)oldRole newRole:(AgoraClientRole)newRole; + +/** Occurs when a remote user or host joins a channel. Same as [userJoinedBlock]([AgoraRtcEngineKit userJoinedBlock:]). + + - Communication profile: This callback notifies the app that another user joins the channel. If other users are already in the channel, the SDK also reports to the app on the existing users. + - Interactive live streaming profile: This callback notifies the app that a host joins the channel. If other hosts are already in the channel, the SDK also reports to the app on the existing hosts. Agora recommends limiting the number of hosts to 17. + + The SDK triggers this callback under one of the following circumstances: + - A remote user/host joins the channel by calling the [joinChannelByToken]([AgoraRtcEngineKit joinChannelByToken:channelId:info:uid:joinSuccess:]) method. + - A remote user switches the user role to the host by calling the [setClientRole]([AgoraRtcEngineKit setClientRole:]) method after joining the channel. + - A remote user/host rejoins the channel after a network interruption. + - A host injects an online media stream into the channel by calling the [addInjectStreamUrl]([AgoraRtcEngineKit addInjectStreamUrl:config:]) method. + + **Note:** + + Interactive live streaming profile: + + * The host receives this callback when another host joins the channel. + * The audience in the channel receives this callback when a new host joins the channel. + * When a web application joins the channel, the SDK triggers this callback as long as the web application publishes streams. + + @param engine AgoraRtcEngineKit object. + @param uid ID of the user or host who joins the channel. If the `uid` is specified in the [joinChannelByToken]([AgoraRtcEngineKit joinChannelByToken:channelId:info:uid:joinSuccess:]) method, the specified user ID is returned. If the `uid` is not specified in the joinChannelByToken method, the Agora server automatically assigns a `uid`. + @param elapsed Time elapsed (ms) from the local user calling the [joinChannelByToken]([AgoraRtcEngineKit joinChannelByToken:channelId:info:uid:joinSuccess:]) or [setClientRole]([AgoraRtcEngineKit setClientRole:]) method until the SDK triggers this callback. + */ +- (void)rtcEngine:(AgoraRtcEngineKit* _Nonnull)engine didJoinedOfUid:(NSUInteger)uid elapsed:(NSInteger)elapsed; + +/** Occurs when a remote user (Communication)/host (Live Broadcast) leaves a channel. Same as [userOfflineBlock]([AgoraRtcEngineKit userOfflineBlock:]). + +There are two reasons for users to be offline: + +- Leave a channel: When the user/host leaves a channel, the user/host sends a goodbye message. When the message is received, the SDK assumes that the user/host leaves a channel. +- Drop offline: When no data packet of the user or host is received for a certain period of time (20 seconds for the Communication profile, and more for the interactive live streaming profile), the SDK assumes that the user/host drops offline. Unreliable network connections may lead to NO detections, so Agora recommends using the [Agora RTM SDK](https://docs.agora.io/en/Real-time-Messaging/product_rtm?platform=All%20Platforms) for more reliable offline detection. + + @param engine AgoraRtcEngineKit object. + @param uid ID of the user or host who leaves a channel or goes offline. + @param reason Reason why the user goes offline, see AgoraUserOfflineReason. + */ +- (void)rtcEngine:(AgoraRtcEngineKit* _Nonnull)engine didOfflineOfUid:(NSUInteger)uid reason:(AgoraUserOfflineReason)reason; + +/** Occurs when the network connection state changes. + +The SDK triggers this callback to report on the current network connection state when it changes, and the reason of the change. + +@param engine AgoraRtcEngineKit object. +@param state The current network connection state, see AgoraConnectionStateType. +@param reason The reason of the connection state change, see AgoraConnectionChangedReason. +*/ +- (void)rtcEngine:(AgoraRtcEngineKit* _Nonnull)engine connectionChangedToState:(AgoraConnectionStateType)state reason:(AgoraConnectionChangedReason)reason; + +/** Occurs when the local network type changes. + +When the network connection is interrupted, this callback indicates whether the interruption is caused by a network type change or poor network conditions. + +@param engine AgoraRtcEngineKit object. +@param type The network type, see AgoraNetworkType. +*/ +- (void)rtcEngine:(AgoraRtcEngineKit* _Nonnull)engine networkTypeChangedToType:(AgoraNetworkType)type; + +/** Occurs when the SDK cannot reconnect to Agora's edge server 10 seconds after its connection to the server is interrupted. + +The SDK triggers this callback when it cannot connect to the server 10 seconds after calling the [joinChannelByToken]([AgoraRtcEngineKit joinChannelByToken:channelId:info:uid:joinSuccess:]) method, regardless of whether it is in the channel or not. + +This callback is different from [rtcEngineConnectionDidInterrupted]([AgoraRtcEngineDelegate rtcEngineConnectionDidInterrupted:]): + +- The SDK triggers the [rtcEngineConnectionDidInterrupted]([AgoraRtcEngineDelegate rtcEngineConnectionDidInterrupted:]) callback when it loses connection with the server for more than four seconds after it successfully joins the channel. +- The SDK triggers the [rtcEngineConnectionDidLost]([AgoraRtcEngineDelegate rtcEngineConnectionDidLost:]) callback when it loses connection with the server for more than 10 seconds, regardless of whether it joins the channel or not. + +If the SDK fails to rejoin the channel 20 minutes after being disconnected from Agora's edge server, the SDK stops rejoining the channel. + +@param engine AgoraRtcEngineKit object. + */ +- (void)rtcEngineConnectionDidLost:(AgoraRtcEngineKit* _Nonnull)engine; + +/** Occurs when the token expires in 30 seconds. + + The user becomes offline if the `token` used in the [joinChannelByToken]([AgoraRtcEngineKit joinChannelByToken:channelId:info:uid:joinSuccess:]) method expires. The SDK triggers this callback 30 seconds before the `token` expires to remind the app to get a new `token`. + Upon receiving this callback, generate a new `token` on the server and call the [renewToken]([AgoraRtcEngineKit renewToken:]) method to pass the new `token` to the SDK. + + @param engine AgoraRtcEngineKit object. + @param token The `token` that expires in 30 seconds. + */ +- (void)rtcEngine:(AgoraRtcEngineKit* _Nonnull)engine tokenPrivilegeWillExpire:(NSString* _Nonnull)token; + +/** Occurs when the token expires. + + After a `token` is specified by calling the [joinChannelByToken]([AgoraRtcEngineKit joinChannelByToken:channelId:info:uid:joinSuccess:]) method, if the SDK losses connection to the Agora server due to network issues, the `token` may expire after a certain period of time and a new `token` may be required to reconnect to the server. + + This callback notifies the app to generate a new token and call `joinChannelByToken` to rejoin the channel with the new token. + + @param engine AgoraRtcEngineKit object. + */ +- (void)rtcEngineRequestToken:(AgoraRtcEngineKit* _Nonnull)engine; + +#pragma mark Media Delegate Methods + +/**----------------------------------------------------------------------------- + * @name Media Delegate Methods + * ----------------------------------------------------------------------------- + */ + +/** Reports the volume information of users. + + By default, this callback is disabled. You can enable it by calling [enableAudioVolumeIndication]([AgoraRtcEngineKit enableAudioVolumeIndication:smooth:report_vad:]). + Once this callback is enabled and users send streams in the channel, the SDK triggers the `reportAudioVolumeIndicationOfSpeakers` + callback at the time interval set in `enableAudioVolumeIndication`. + + The SDK triggers two independent `reportAudioVolumeIndicationOfSpeakers` callbacks simultaneously, which separately report + the volume information of the local user who sends a stream and the remote users (up to three) whose instantaneous volumes + are the highest. + + @note After you enable this callback, calling [muteLocalAudioStream]([AgoraRtcEngineKit muteLocalAudioStream:]) affects + the SDK's behavior as follows: + + - If the local user calls `muteLocalAudioStream`, the SDK stops triggering the local user’s callback. + - 20 seconds after a remote user whose volume is one of the three highest calls `muteLocalAudioStream` method, the + remote users' callback excludes this remote user's information; 20 seconds after all remote users call `muteLocalAudioStream`, + the SDK stops triggering the remote users' callback. + + @param engine AgoraRtcEngineKit object. + @param speakers The volume information of users. See AgoraRtcAudioVolumeInfo.

        An empty `speakers` array in the + callback indicates that no remote user is in the channel or sending a stream at the moment.

        + @param totalVolume Total volume after audio mixing. The value ranges between 0 (lowest volume) and 255 (highest volume). + + - In the local user's callback, `totalVolume` is the volume of the local user who sends a stream. + - In the remote speakers' callback, `totalVolume` is the sum of the volume of all remote users (up to three) whose + instantaneous volumes are the highest. + + If the user calls [startAudioMixing]([AgoraRtcEngineKit startAudioMixing:loopback:replace:cycle:startPos:]), `totalVolume` is + the sum of the voice volume and audio-mixing volume. + */ +- (void)rtcEngine:(AgoraRtcEngineKit* _Nonnull)engine reportAudioVolumeIndicationOfSpeakers:(NSArray* _Nonnull)speakers totalVolume:(NSInteger)totalVolume; + +/** Occurs when the most active remote speaker is detected. + + After a successful call of [enableAudioVolumeIndication]([AgoraRtcEngineKit enableAudioVolumeIndication:smooth:report_vad:]), + the SDK continuously detects which remote user has the loudest volume. During the current period, the remote user, + who is detected as the loudest for the most times, is the most active user. + + When the number of users is more than or equal to two and an active speaker exists, the SDK triggers this callback and reports the `uid` of the most active speaker. + + - If the most active speaker is always the same user, the SDK triggers this callback only once. + - If the most active speaker changes to another user, the SDK triggers this callback again and reports the `uid` of the new active speaker. + + @param engine AgoraRtcEngineKit object. + @param speakerUid The user ID of the most active remote speaker. + */ +- (void)rtcEngine:(AgoraRtcEngineKit* _Nonnull)engine activeSpeaker:(NSUInteger)speakerUid; + +/** Occurs when the first audio frame is published. + + @since v3.1.0 + + The SDK triggers this callback under one of the following circumstances: + + - The local client enables the audio module and calls [joinChannelByToken]([AgoraRtcEngineKit joinChannelByToken:channelId:info:uid:joinSuccess:]) successfully. + - The local client calls [muteLocalAudioStream(YES)]([AgoraRtcEngineKit muteLocalAudioStream:]) and `muteLocalAudioStream(NO)` in sequence. + - The local client calls [disableAudio]([AgoraRtcEngineKit disableAudio]) and [enableAudio]([AgoraRtcEngineKit enableAudio]) in sequence. + - The local client calls [pushExternalAudioFrameRawData]([AgoraRtcEngineKit pushExternalAudioFrameRawData:samples:timestamp:]) + or [pushExternalAudioFrameSampleBuffer]([AgoraRtcEngineKit pushExternalAudioFrameSampleBuffer:]) to successfully push the audio frame to the SDK. + + @param engine AgoraRtcEngineKit object. + @param elapsed The time elapsed (ms) from the local client calling `joinChannelByToken` until the SDK triggers this callback. + */ +- (void)rtcEngine:(AgoraRtcEngineKit* _Nonnull)engine firstLocalAudioFramePublished:(NSInteger)elapsed; + +/** Occurs when the first local video frame is displayed/rendered on the local video view. + +Same as [firstLocalVideoFrameBlock]([AgoraRtcEngineKit firstLocalVideoFrameBlock:]). +@param engine AgoraRtcEngineKit object. +@param size Size of the first local video frame (width and height). +@param elapsed Time elapsed (ms) from the local user calling the [joinChannelByToken]([AgoraRtcEngineKit joinChannelByToken:channelId:info:uid:joinSuccess:]) method until the SDK calls this callback.

        If the [startPreview]([AgoraRtcEngineKit startPreview]) method is called before the [joinChannelByToken]([AgoraRtcEngineKit joinChannelByToken:channelId:info:uid:joinSuccess:]) method, then `elapsed` is the time elapsed from calling the [startPreview]([AgoraRtcEngineKit startPreview]) method until the SDK triggers this callback.

        +*/ +- (void)rtcEngine:(AgoraRtcEngineKit* _Nonnull)engine firstLocalVideoFrameWithSize:(CGSize)size elapsed:(NSInteger)elapsed; + +/** Occurs when the first video frame is published. + + @since v3.1.0 + + The SDK triggers this callback under one of the following circumstances: + + - The local client enables the video module and calls [joinChannelByToken]([AgoraRtcEngineKit joinChannelByToken:channelId:info:uid:joinSuccess:]) successfully. + - The local client calls [muteLocalVideoStream(YES)]([AgoraRtcEngineKit muteLocalVideoStream:]) and `muteLocalVideoStream(NO)` in sequence. + - The local client calls [disableVideo]([AgoraRtcEngineKit disableVideo]) and [enableVideo]([AgoraRtcEngineKit enableVideo]) in sequence. + - The local client calls [pushExternalVideoFrame]([AgoraRtcEngineKit pushExternalVideoFrame:]) to successfully push the video frame to the SDK. + + @param engine AgoraRtcEngineKit object. + @param elapsed The time elapsed (ms) from the local client calling `joinChannelByToken` until the SDK triggers this callback. + */ +- (void)rtcEngine:(AgoraRtcEngineKit* _Nonnull)engine firstLocalVideoFramePublished:(NSInteger)elapsed; + +/** Occurs when the video size or rotation of a specific remote user changes. + + @param engine AgoraRtcEngineKit object. + @param uid User ID of the remote user or local user (0) whose video size or rotation changes. + @param size New video size. + @param rotation New rotation of the video. The value ranges between 0 and 360. + */ +- (void)rtcEngine:(AgoraRtcEngineKit* _Nonnull)engine videoSizeChangedOfUid:(NSUInteger)uid size:(CGSize)size rotation:(NSInteger)rotation; + +/** Occurs when the remote video state changes. + + @note This callback can be inaccurate when the number of users (in the + communication profile) or hosts (in the interactive live streaming profile) in a channel exceeds 17. + + @param engine AgoraRtcEngineKit object. + @param uid ID of the remote user whose video state changes. + @param state The state of the remote video. See [AgoraVideoRemoteState](AgoraVideoRemoteState). + @param reason The reason of the remote video state change. See [AgoraVideoRemoteStateReason](AgoraVideoRemoteStateReason). + @param elapsed The time elapsed (ms) from the local user calling the [joinChannel]([AgoraRtcEngineKit joinChannelByToken:channelId:info:uid:joinSuccess:]) method until the SDK triggers this callback. + */ +- (void)rtcEngine:(AgoraRtcEngineKit* _Nonnull)engine remoteVideoStateChangedOfUid:(NSUInteger)uid state:(AgoraVideoRemoteState)state reason:(AgoraVideoRemoteStateReason)reason elapsed:(NSInteger)elapsed; + +/** Reports whether the super resolution feature is successfully enabled. (beta feature) + + @since v3.5.1 + + After calling [enableRemoteSuperResolution]([AgoraRtcEngineKit enableRemoteSuperResolution:enabled:]), + the SDK triggers this callback to report whether super resolution is successfully enabled. + If it is not successfully enabled, use `reason` for troubleshooting. + + @param engine AgoraRtcEngineKit object. + @param uid The user ID of the remote user. + @param enabled Whether super resolution is successfully enabled: + + - `YES`: Super resolution is successfully enabled. + - `NO`: Super resolution is not successfully enabled. + @param reason The reason why super resolution is not successfully enabled or + the message that confirms success. See [AgoraSuperResolutionStateReason](AgoraSuperResolutionStateReason). + */ +- (void)rtcEngine:(AgoraRtcEngineKit* _Nonnull)engine superResolutionEnabledOfUid:(NSUInteger)uid enabled:(BOOL)enabled reason:(AgoraSuperResolutionStateReason)reason; + +/** Reports whether the virtual background is successfully enabled. (beta feature) + + @since Support for macOS as of v3.4.5 and iOS as of v3.5.0. + + After you call [enableVirtualBackground]([AgoraRtcEngineKit enableVirtualBackground:backData:]), + the SDK triggers this callback to report whether the virtual background is + successfully enabled. + + @note If the background image customized in the virtual background is in PNG + or JPG format, the triggering of this callback is delayed until the image is + read. + + @param engine AgoraRtcEngineKit object. + @param enabled Whether the virtual background is successfully enabled: + + - `YES`: The virtual background is successfully enabled. + - `NO`: The virtual background is not successfully enabled. + @param reason The reason why the virtual background is not successfully + enabled or the message that confirms success. + See AgoraVirtualBackgroundSourceStateReason. + */ +- (void)rtcEngine:(AgoraRtcEngineKit* _Nonnull)engine virtualBackgroundSourceEnabled:(BOOL)enabled reason:(AgoraVirtualBackgroundSourceStateReason)reason; + +- (void)rtcEngine:(AgoraRtcEngineKit* _Nonnull)engine contentInspectResult:(AgoraContentInspectResult)result; +/** + Reports the result of taking a video snapshot. + + @since v3.5.2 + + After a successful [takeSnapshot]([AgoraRtcEngineKit takeSnapshot:uid:filePath:]) method call, the SDK triggers this + callback to report whether the snapshot is successfully taken as well as the details for the snapshot taken. + + @param engine AgoraRtcEngineKit + @param channel The channel name. + @param uid The user ID of the user. A `uid` of 0 indicates the local user. + @param filePath The local path of the snapshot. + @param width The width (px) of the snapshot. + @param height The height (px) of the snapshot. + @param errCode The message that confirms success or the reason why the snapshot is not successfully taken: + + - 0: Success. + - < 0: Failure: + + - -1: The SDK fails to write data to a file or encode a JPEG image. + - -2: The SDK does not find the video stream of the specified user within one second after the [takeSnapshot]([AgoraRtcEngineKit takeSnapshot:uid:filePath:]) method call succeeds. + */ +- (void)rtcEngine:(AgoraRtcEngineKit* _Nonnull)engine snapshotTaken:(NSString* _Nonnull)channel uid:(NSUInteger)uid filePath:(NSString* _Nonnull)filePath width:(NSInteger)width height:(NSInteger)height errCode:(NSInteger)errCode; + +/** Occurs when the local video stream state changes. + + The SDK reports the current video state in this callback. + + The SDK triggers the `localVideoStateChange(AgoraLocalVideoStreamStateFailed, AgoraLocalVideoStreamErrorCaptureFailure)` + callback in the following situations: + + - The application exits to the background, and the system recycles the camera. + - The camera starts normally, but the captured video is not output for four seconds. + + When the camera outputs the captured video frames, if all the video frames are + the same for 15 consecutive frames, the SDK triggers the `localVideoStateChange(AgoraLocalVideoStreamStateCapturing, AgoraLocalVideoStreamErrorCaptureFailure)` + callback. Note that the video frame duplication detection is only available for + video frames with a resolution greater than 200 × 200, a frame rate greater + than or equal to 10 fps, and a bitrate less than 20 Kbps. + + @param engine AgoraRtcEngineKit object. + @param state The local video state, see AgoraLocalVideoStreamState. + @param error The detailed error information of the local video, see AgoraLocalVideoStreamError. + */ +- (void)rtcEngine:(AgoraRtcEngineKit* _Nonnull)engine localVideoStateChange:(AgoraLocalVideoStreamState)state error:(AgoraLocalVideoStreamError)error; + +/** Occurs when the local audio state changes. + + This callback indicates the state change of the local audio stream, including the state of the audio sampling and encoding, and allows you to troubleshoot issues when exceptions occur. + + @note This callback can be inaccurate when the number of users (in the + communication profile) or hosts (in the interactive live streaming profile) in a channel exceeds 17. + + @param engine See AgoraRtcEngineKit. + @param uid ID of the remote user whose audio state changes. + @param state State of the remote audio. See [AgoraAudioRemoteState](AgoraAudioRemoteState). + @param reason The reason of the remote audio state change. See [AgoraAudioRemoteStateReason](AgoraAudioRemoteStateReason). + @param elapsed Time elapsed (ms) from the local user calling the [joinChannel]([AgoraRtcEngineKit joinChannelByToken:channelId:info:uid:joinSuccess:]) method until the SDK triggers this callback. + */ +- (void)rtcEngine:(AgoraRtcEngineKit* _Nonnull)engine remoteAudioStateChangedOfUid:(NSUInteger)uid state:(AgoraAudioRemoteState)state reason:(AgoraAudioRemoteStateReason)reason elapsed:(NSInteger)elapsed; + +/** Occurs when the local audio state changes. + + This callback indicates the state change of the local audio stream, including the state of the audio sampling and encoding, and allows you to troubleshoot issues when exceptions occur. + + @param engine See AgoraRtcEngineKit. + @param state The state of the local audio. See [AgoraAudioLocalState](AgoraAudioLocalState). + @param error The error information of the local audio. See [AgoraAudioLocalError](AgoraAudioLocalError). + + @note When the state is AgoraAudioLocalStateFailed(3), see the `error` parameter for details. + */ +- (void)rtcEngine:(AgoraRtcEngineKit* _Nonnull)engine localAudioStateChange:(AgoraAudioLocalState)state error:(AgoraAudioLocalError)error; + +/** Occurs when the first remote video frame is rendered. + + Same as [firstRemoteVideoFrameBlock]([AgoraRtcEngineKit firstRemoteVideoFrameBlock:]). + + @param engine AgoraRtcEngineKit object. + @param uid User ID of the remote user sending the video stream. + @param size Size of the video frame (width and height). + @param elapsed Time elapsed (ms) from the local user calling the [joinChannelByToken]([AgoraRtcEngineKit joinChannelByToken:channelId:info:uid:joinSuccess:]) method until the SDK triggers this callback. + */ +- (void)rtcEngine:(AgoraRtcEngineKit* _Nonnull)engine firstRemoteVideoFrameOfUid:(NSUInteger)uid size:(CGSize)size elapsed:(NSInteger)elapsed; + +/** Occurs when the audio publishing state changes. + + @since v3.1.0 + + This callback indicates the publishing state change of the local audio stream. + + @param engine AgoraRtcEngineKit object. + @param channel The channel name. + @param oldState The previous publishing state. For details, see AgoraStreamPublishState. + @param newState The current publishing state. For details, see AgoraStreamPublishState. + @param elapseSinceLastState The time elapsed (ms) from the previous state to the current state. + */ +- (void)rtcEngine:(AgoraRtcEngineKit* _Nonnull)engine didAudioPublishStateChange:(NSString* _Nonnull)channel oldState:(AgoraStreamPublishState)oldState newState:(AgoraStreamPublishState)newState elapseSinceLastState:(NSInteger)elapseSinceLastState; + +/** Occurs when the video publishing state changes. + + @since v3.1.0 + + This callback indicates the publishing state change of the local video stream. + + @param engine AgoraRtcEngineKit object. + @param channel The channel name. + @param oldState The previous publishing state. For details, see AgoraStreamPublishState. + @param newState The current publishing state. For details, see AgoraStreamPublishState. + @param elapseSinceLastState The time elapsed (ms) from the previous state to the current state. + */ +- (void)rtcEngine:(AgoraRtcEngineKit* _Nonnull)engine didVideoPublishStateChange:(NSString* _Nonnull)channel oldState:(AgoraStreamPublishState)oldState newState:(AgoraStreamPublishState)newState elapseSinceLastState:(NSInteger)elapseSinceLastState; + +/** Occurs when the audio subscribing state changes. + + @since v3.1.0 + + This callback indicates the subscribing state change of a remote audio stream. + + @param engine AgoraRtcEngineKit object. + @param channel The channel name. + @param uid The ID of the remote user. + @param oldState The previous subscribing state. For details, see AgoraStreamSubscribeState. + @param newState The current subscribing state. For details, see AgoraStreamSubscribeState. + @param elapseSinceLastState The time elapsed (ms) from the previous state to the current state. + */ +- (void)rtcEngine:(AgoraRtcEngineKit* _Nonnull)engine didAudioSubscribeStateChange:(NSString* _Nonnull)channel withUid:(NSUInteger)uid oldState:(AgoraStreamSubscribeState)oldState newState:(AgoraStreamSubscribeState)newState elapseSinceLastState:(NSInteger)elapseSinceLastState; + +/** Occurs when the video subscribing state changes. + + @since v3.1.0 + + This callback indicates the subscribing state change of a remote video stream. + + @param engine AgoraRtcEngineKit object. + @param channel The channel name. + @param uid The ID of the remote user. + @param oldState The previous subscribing state. For details, see AgoraStreamSubscribeState. + @param newState The current subscribing state. For details, see AgoraStreamSubscribeState. + @param elapseSinceLastState The time elapsed (ms) from the previous state to the current state. + */ +- (void)rtcEngine:(AgoraRtcEngineKit* _Nonnull)engine didVideoSubscribeStateChange:(NSString* _Nonnull)channel withUid:(NSUInteger)uid oldState:(AgoraStreamSubscribeState)oldState newState:(AgoraStreamSubscribeState)newState elapseSinceLastState:(NSInteger)elapseSinceLastState; + +/** Occurs when a remote user's audio stream is muted/unmuted. + + You can also use the [remoteAudioStateChangedOfUid]([AgoraRtcEngineDelegate rtcEngine:remoteAudioStateChangedOfUid:state:reason:elapsed:]) callback with the following parameters instead: + + - `AgoraAudioRemoteStateStopped(0)` and `AgoraAudioRemoteReasonRemoteMuted(5)`. + - `AgoraAudioRemoteStateDecoding(2)` and `AgoraAudioRemoteReasonRemoteUnmuted(6)`. + + The SDK triggers this callback when the remote user stops or resumes sending the audio stream by calling the [muteLocalAudioStream]([AgoraRtcEngineKit muteLocalAudioStream:]) method. + + @note This callback can be inaccurate when the number of users (in the + communication profile) or hosts (in the interactive live streaming profile) in a channel exceeds 17. + + @param engine AgoraRtcEngineKit object. + @param muted Whether the remote user's audio stream is muted/unmuted: + + * YES: Muted. + * NO: Unmuted. + @param uid ID of the remote user. + */ +- (void)rtcEngine:(AgoraRtcEngineKit* _Nonnull)engine didAudioMuted:(BOOL)muted byUid:(NSUInteger)uid; + +/** Occurs when a remote user stops or resumes publishing the video stream. + + Same as [userMuteVideoBlock]([AgoraRtcEngineKit userMuteVideoBlock:]). + + When a remote user calls [muteLocalVideoStream]([AgoraRtcEngineKit muteLocalVideoStream:]) + to stop or resume publishing the video stream, the SDK triggers this callback + to report the state of the remote user's publishing stream to the local user. + + @note This callback can be inaccurate when the number of users (in the + communication profile) or hosts (in the interactive live streaming profile) in a channel exceeds 17. + + @param engine AgoraRtcEngineKit object. + @param muted A remote user's video stream playback pauses/resumes: + + * YES: Pause. + * NO: Resume. + + @param uid User ID of the remote user. + */ +- (void)rtcEngine:(AgoraRtcEngineKit* _Nonnull)engine didVideoMuted:(BOOL)muted byUid:(NSUInteger)uid; + +/** Occurs when a specific remote user enables/disables the video module. + + Once the video module is disabled, the remote user can only use a voice call. The remote user cannot send or receive any video from other users. + + The SDK triggers this callback when the remote user enables or disables the video module by calling the [enableVideo]([AgoraRtcEngineKit enableVideo]) or [disableVideo]([AgoraRtcEngineKit disableVideo]) method. + + @param engine AgoraRtcEngineKit object. + @param enabled Whether the remote user enables/disables the video module: + + * YES: Enable. The remote user can enter a video session. + * NO: Disable. The remote user can only enter a voice session, and cannot send or receive any video stream. + + @param uid User ID of the remote user. + */ +- (void)rtcEngine:(AgoraRtcEngineKit* _Nonnull)engine didVideoEnabled:(BOOL)enabled byUid:(NSUInteger)uid; + +/** Occurs when a specific remote user enables/disables the local video capturing function. + + This callback is only applicable to the scenario when the user only wants to watch the remote video without sending any video stream to the other user. + + @param engine AgoraRtcEngineKit object. + @param enabled Whether the specific remote user enables/disables the local video capturing function: + + * YES: Enable. Other users in the channel can see the video of this remote user. + * NO: Disable. Other users in the channel do not receive the video stream from this remote user, while this remote user can still receive the video streams from other users. + + @param uid User ID of the remote user. + */ +- (void)rtcEngine:(AgoraRtcEngineKit* _Nonnull)engine didLocalVideoEnabled:(BOOL)enabled byUid:(NSUInteger)uid; + +/** Occurs when the first remote video frame is received and decoded. + + You can also use AgoraVideoRemoteStateStarting(1) or AgoraVideoRemoteStateDecoding(2) in the [remoteVideoStateChangedOfUid]([AgoraRtcEngineDelegate rtcEngine:remoteVideoStateChangedOfUid:state:reason:elapsed:]) callback instead. + + Same as [firstRemoteVideoDecodedBlock]([AgoraRtcEngineKit firstRemoteVideoDecodedBlock:]). + + This callback is triggered in either of the following scenarios: + + - The remote user joins the channel and sends the video stream. + - The remote user stops sending the video stream and re-sends it after 15 seconds. Possible reasons include: + + - The remote user leaves channel. + - The remote user drops offline. + - The remote user calls [muteLocalVideoStream]([AgoraRtcEngineKit muteLocalVideoStream:]). + - The remote user calls [disableVideo]([AgoraRtcEngineKit disableVideo]). + + @param engine AgoraRtcEngineKit object. + @param uid User ID of the remote user sending the video stream. + @param size Size of the video frame (width and height). + @param elapsed Time elapsed (ms) from the local user calling the [joinChannelByToken]([AgoraRtcEngineKit joinChannelByToken:channelId:info:uid:joinSuccess:]) method until the SDK triggers this callback. + */ +- (void)rtcEngine:(AgoraRtcEngineKit* _Nonnull)engine firstRemoteVideoDecodedOfUid:(NSUInteger)uid size:(CGSize)size elapsed:(NSInteger)elapsed; + +#pragma mark Fallback Delegate Methods + +/**----------------------------------------------------------------------------- + * @name Fallback Delegate Methods + * ----------------------------------------------------------------------------- + */ + +/** Occurs when the published video stream falls back to an audio-only stream due to unreliable network conditions or switches back to the video when the network conditions improve. + + If you call the [setLocalPublishFallbackOption]([AgoraRtcEngineKit setLocalPublishFallbackOption:]) method and set `option` as AgoraStreamFallbackOptionAudioOnly, the SDK triggers this callback when the published stream falls back to audio-only mode due to unreliable uplink conditions, or when the audio stream switches back to the video when the uplink network condition improves. + + **Note:** + + Once the published stream falls back to audio only, the remote app receives the [userMuteVideoBlock]([AgoraRtcEngineKit userMuteVideoBlock:]) callback. + + @param engine AgoraRtcEngineKit object. + @param isFallbackOrRecover Whether the published stream falls back to audio-only or switches back to the video: + + * YES: The published stream falls back to audio-only due to unreliable network conditions. + * NO: The published stream switches back to the video after the network conditions improve. + */ +- (void)rtcEngine:(AgoraRtcEngineKit* _Nonnull)engine didLocalPublishFallbackToAudioOnly:(BOOL)isFallbackOrRecover; + +/** Occurs when the remote video stream falls back to an audio-only stream due to unreliable network conditions or switches back to the video after the network conditions improve. + +If you call [setRemoteSubscribeFallbackOption]([AgoraRtcEngineKit setRemoteSubscribeFallbackOption:]) and set `option` as `AgoraStreamFallbackOptionAudioOnly`, the SDK triggers this callback when the remote media stream falls back to audio only due to poor downlink conditions or switches back to the video after the downlink network condition improves. + +**Note:** + +Once the remote media stream is switched to the low stream due to unreliable network conditions, you can monitor the stream switch between a high stream and low stream in the [remoteVideoStats]([AgoraRtcEngineDelegate rtcEngine:remoteVideoStats:]) callback. + +@param engine AgoraRtcEngineKit object. +@param isFallbackOrRecover Whether the remote media stream falls back to audio-only or switches back to the video: + +* YES: The remote media stream falls back to audio-only due to unreliable network conditions. +* NO: The remote media stream switches back to the video stream after the network conditions improve. +@param uid ID of the remote user sending the stream. +*/ +- (void)rtcEngine:(AgoraRtcEngineKit* _Nonnull)engine didRemoteSubscribeFallbackToAudioOnly:(BOOL)isFallbackOrRecover byUid:(NSUInteger)uid; + +/**----------------------------------------------------------------------------- + * @name Face Detection Delegate Methods + * ----------------------------------------------------------------------------- + */ + +/** Reports the face detection result of the local user. (iOS only) + + **Since:** v3.0.1. + + Once you enable face detection by calling [enableFaceDetection]([AgoraRtcEngineKit enableFaceDetection:]), you can get the following information on the local user in real-time: + + - The width and height of the local video. + - The position of the human face in the local video. + - The distance between the human face and the device screen. This value is based on the fitting calculation of the local video size and the position of the human face. + + **Note** + + - If the SDK does not detect a face, it reduces the frequency of this callback to reduce power consumption on the local device. + - The SDK stops triggering this callback when a human face is in close proximity to the screen. + + @param engine AgoraRtcEngineKit object. + @param width The width (px) of the local video. + @param height The height (px) of the local video. + @param faces An AgoraFacePositionInfo array, which contains the information of the detected human face. + + The number of the AgoraFacePositionInfo array depends on the number of human faces detected. If the array length is 0, it means that no human face is detected. + */ +- (void)rtcEngine:(AgoraRtcEngineKit* _Nonnull)engine facePositionDidChangeWidth:(int)width previewHeight:(int)height faces:(NSArray* _Nullable)faces; + +#pragma mark Device Delegate Methods + +/**----------------------------------------------------------------------------- + * @name Device Delegate Methods + * ----------------------------------------------------------------------------- + */ + +#if (!(TARGET_OS_IPHONE) && (TARGET_OS_MAC)) + +/** Occurs when the device state changes. (macOS only.) + + @param engine AgoraRtcEngineKit object. + @param deviceId Device ID. + @param deviceType Device type: AgoraMediaDeviceType. + @param state The state of the device: + + - `0`: The device is connected but not in use. + - `8`: The device is not connected. + */ +- (void)rtcEngine:(AgoraRtcEngineKit* _Nonnull)engine device:(NSString* _Nonnull)deviceId type:(AgoraMediaDeviceType)deviceType stateChanged:(NSInteger)state; + +#endif + +/** Occurs when the local audio route changes. + + @param engine AgoraRtcEngineKit object. + @param routing The current audio route: AgoraAudioOutputRouting. + */ +- (void)rtcEngine:(AgoraRtcEngineKit* _Nonnull)engine didAudioRouteChanged:(AgoraAudioOutputRouting)routing; + +#if defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE + +/** Occurs when a camera focus area changes. (iOS only.) + +The SDK triggers this callback when the local user changes the camera focus position by calling the [setCameraFocusPositionInPreview](setCameraFocusPositionInPreview:) method. + + @param engine AgoraRtcEngineKit object. + @param rect Rectangular area in the camera zoom specifying the focus area. + */ +- (void)rtcEngine:(AgoraRtcEngineKit* _Nonnull)engine cameraFocusDidChangedToRect:(CGRect)rect; + +#endif + +#if defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE +/** Occurs when the camera exposure area changes. (iOS only) + +The SDK triggers this callback when the local user changes the camera exposure position by calling the [setCameraExposurePosition](setCameraExposurePosition:) method. + +@param engine AgoraRtcEngineKit object. +@param rect Rectangular area in the camera zoom specifying the exposure area. + */ +- (void)rtcEngine:(AgoraRtcEngineKit* _Nonnull)engine cameraExposureDidChangedToRect:(CGRect)rect; +#endif + +#pragma mark Statistics Delegate Methods + +/**----------------------------------------------------------------------------- + * @name Statistics Delegate Methods + * ----------------------------------------------------------------------------- + */ + +/** Reports the statistics of the current call. The SDK triggers this callback once every two seconds after the user joins the channel. + + @param engine AgoraRtcEngineKit object. + @param stats Statistics of the AgoraRtcEngineKit: [AgoraChannelStats](AgoraChannelStats). + */ +- (void)rtcEngine:(AgoraRtcEngineKit* _Nonnull)engine reportRtcStats:(AgoraChannelStats* _Nonnull)stats; + +/** Reports the last mile network quality of the local user once every two seconds before the user joins a channel. + +Last mile refers to the connection between the local device and Agora's edge server. After the app calls the [enableLastmileTest]([AgoraRtcEngineKit enableLastmileTest]) method, the SDK triggers this callback once every two seconds to report the uplink and downlink last mile network conditions of the local user before the user joins the channel. + + @param engine AgoraRtcEngineKit object. + @param quality The last mile network quality based on the uplink and dowlink packet loss rate and jitter. See AgoraNetworkQuality. + */ +- (void)rtcEngine:(AgoraRtcEngineKit* _Nonnull)engine lastmileQuality:(AgoraNetworkQuality)quality; + +/** Reports the last mile network quality of each user in the channel once every two seconds. + + Last mile refers to the connection between the local device and Agora's edge server. The SDK triggers this callback once every two seconds to report the last mile network conditions of each user in the channel. If a channel includes multiple users, the SDK triggers this callback as many times. + + @note `txQuality` is `Unknown` when the user is not sending a stream; `rxQuality` is `Unknown` when the user is not receiving a stream. + + @param engine AgoraRtcEngineKit object. + @param uid User ID. The network quality of the user with this `uid` is reported. If `uid` is 0, the local network quality is reported. + @param txQuality Uplink transmission quality of the user in terms of the transmission bitrate, packet loss rate, average RTT (Round-Trip Time), and jitter of the uplink network. `txQuality` is a quality rating helping you understand how well the current uplink network conditions can support the selected AgoraVideoEncoderConfiguration. For example, a 1000-Kbps uplink network may be adequate for video frames with a resolution of 640 * 480 and a frame rate of 15 fps in the interactive live streaming profile, but may be inadequate for resolutions higher than 1280 * 720. See AgoraNetworkQuality. + @param rxQuality Downlink network quality rating of the user in terms of packet loss rate, average RTT, and jitter of the downlink network. See AgoraNetworkQuality. + */ +- (void)rtcEngine:(AgoraRtcEngineKit* _Nonnull)engine networkQuality:(NSUInteger)uid txQuality:(AgoraNetworkQuality)txQuality rxQuality:(AgoraNetworkQuality)rxQuality; + +/** Reports the last-mile network probe result. + +The SDK triggers this callback within 30 seconds after the app calls the [startLastmileProbeTest]([AgoraRtcEngineKit startLastmileProbeTest:]) method. + + @param engine AgoraRtcEngineKit object. + @param result The uplink and downlink last-mile network probe test result, see [AgoraLastmileProbeResult](AgoraLastmileProbeResult). + */ +- (void)rtcEngine:(AgoraRtcEngineKit* _Nonnull)engine lastmileProbeTestResult:(AgoraLastmileProbeResult* _Nonnull)result; + +/** Reports the statistics of the uploading local video streams once every two seconds. Same as [localVideoStatBlock]([AgoraRtcEngineKit localVideoStatBlock:]). + + @param engine AgoraRtcEngineKit object. + @param stats Statistics of the uploading local video streams. See [AgoraRtcLocalVideoStats](AgoraRtcLocalVideoStats). + */ +- (void)rtcEngine:(AgoraRtcEngineKit* _Nonnull)engine localVideoStats:(AgoraRtcLocalVideoStats* _Nonnull)stats; + +/** Reports the statistics of the local audio stream. + + The SDK triggers this callback once every two seconds. + + @param engine See AgoraRtcEngineKit. + @param stats The statistics of the local audio stream. See [AgoraRtcLocalAudioStats](AgoraRtcLocalAudioStats). + */ +- (void)rtcEngine:(AgoraRtcEngineKit* _Nonnull)engine localAudioStats:(AgoraRtcLocalAudioStats* _Nonnull)stats; + +/** Reports the statistics of the video stream from each remote user/host. + +The SDK triggers this callback once every two seconds for each remote user/host. If a channel includes multiple remote users, the SDK triggers this callback as many times. + + This callback reports the statistics more closely linked to the real-user experience of the video transmission quality than the statistics that the [videoTransportStatsOfUid]([AgoraRtcEngineDelegate rtcEngine:videoTransportStatsOfUid:delay:lost:rxKBitRate:]) callback reports. This callback reports more about media layer statistics such as the frame loss rate, while the [videoTransportStatsOfUid]([AgoraRtcEngineDelegate rtcEngine:videoTransportStatsOfUid:delay:lost:rxKBitRate:]) callback reports more about the transport layer statistics such as the packet loss rate. + +Schemes such as FEC (Forward Error Correction) or retransmission counter the frame loss rate. Hence, users may find the overall video quality acceptable even when the packet loss rate is high. + + + @param engine AgoraRtcEngineKit object. + @param stats Statistics of the received remote video streams. See [AgoraRtcRemoteVideoStats](AgoraRtcRemoteVideoStats). + */ +- (void)rtcEngine:(AgoraRtcEngineKit* _Nonnull)engine remoteVideoStats:(AgoraRtcRemoteVideoStats* _Nonnull)stats; + +/** Reports the statistics of the audio stream from each remote user/host. + + This callback replaces the [audioQualityOfUid]([AgoraRtcEngineDelegate rtcEngine:audioQualityOfUid:quality:delay:lost:]) callback. + + The SDK triggers this callback once every two seconds for each remote user/host. If a channel includes multiple remote users, the SDK triggers this callback as many times. + + This callback reports the statistics more closely linked to the real-user experience of the audio transmission quality than the statistics that the [audioTransportStatsOfUid]([AgoraRtcEngineDelegate rtcEngine:audioTransportStatsOfUid:delay:lost:rxKBitRate:]) callback reports. This callback reports more about media layer statistics such as the frame loss rate, while the [audioTransportStatsOfUid]([AgoraRtcEngineDelegate rtcEngine:audioTransportStatsOfUid:delay:lost:rxKBitRate:]) callback reports more about the transport layer statistics such as the packet loss rate. + +Schemes such as FEC (Forward Error Correction) or retransmission counter the frame loss rate. Hence, users may find the overall audio quality acceptable even when the packet loss rate is high. + + @param engine AgoraRtcEngineKit object. + @param stats Statistics of the received remote audio streams. See AgoraRtcRemoteAudioStats. + */ +- (void)rtcEngine:(AgoraRtcEngineKit* _Nonnull)engine remoteAudioStats:(AgoraRtcRemoteAudioStats* _Nonnull)stats; + +#pragma mark Audio Player Delegate Methods + +/**----------------------------------------------------------------------------- + * @name Audio Player Delegate Methods + * ----------------------------------------------------------------------------- + */ + +/** Occurs when the audio mixing file playback finishes. + +You can start an audio mixing file playback by calling the [startAudioMixing]([AgoraRtcEngineKit startAudioMixing:loopback:replace:cycle:startPos:]) method. The SDK triggers this callback when the audio mixing file playback finishes. + + If the [startAudioMixing]([AgoraRtcEngineKit startAudioMixing:loopback:replace:cycle:startPos:]) method call fails, a warning code, AgoraWarningCodeAudioMixingOpenError, returns in the [didOccurWarning]([AgoraRtcEngineDelegate rtcEngine:didOccurWarning:]) callback. + + @param engine AgoraRtcEngineKit object. + */ +- (void)rtcEngineLocalAudioMixingDidFinish:(AgoraRtcEngineKit* _Nonnull)engine; + +/** Occurs when the playback state of the local user's music file changes. + +When the playback state of the local user's music file changes, the SDK triggers this callback and reports the +current playback state and the reason for the change. + +@since v3.4.0 + +@param engine AgoraRtcEngineKit object. +@param state The current music file playback state. See AgoraAudioMixingStateCode. +@param reason The reason for the change of the music file playback state. See AgoraAudioMixingReasonCode. +*/ +- (void)rtcEngine:(AgoraRtcEngineKit* _Nonnull)engine localAudioMixingStateDidChanged:(AgoraAudioMixingStateCode)state reason:(AgoraAudioMixingReasonCode)reason; + +/** Occurs when a remote user starts audio mixing. + + The SDK triggers this callback when a remote user calls the [startAudioMixing]([AgoraRtcEngineKit startAudioMixing:loopback:replace:cycle:startPos:]) method. + + @param engine AgoraRtcEngineKit object. + */ +- (void)rtcEngineRemoteAudioMixingDidStart:(AgoraRtcEngineKit* _Nonnull)engine; + +/** Occurs when a remote user finishes audio mixing. + + @param engine AgoraRtcEngineKit object. + */ +- (void)rtcEngineRemoteAudioMixingDidFinish:(AgoraRtcEngineKit* _Nonnull)engine; + +/** Occurs when the local audio effect playback finishes. + + You can start a local audio effect playback by calling the [playEffect]([AgoraRtcEngineKit playEffect:filePath:loopCount:pitch:pan:gain:publish:startPos:]) method. The SDK triggers this callback when the local audio effect file playback finishes. + + @param engine AgoraRtcEngineKit object. + @param soundId ID of the local audio effect. Each local audio effect has a unique ID. + */ +- (void)rtcEngineDidAudioEffectFinish:(AgoraRtcEngineKit* _Nonnull)engine soundId:(NSInteger)soundId; + +- (void)rtcEngineAirPlayIsConnected:(AgoraRtcEngineKit* _Nonnull)engine; + +#pragma mark CDN Publisher Delegate Methods + +/**----------------------------------------------------------------------------- + * @name CDN Live Streaming Delegate Methods + * ----------------------------------------------------------------------------- + */ + +/** Occurs when the state of the RTMP or RTMPS streaming changes. + +The SDK triggers this callback to report the result of the local user calling the [addPublishStreamUrl](addPublishStreamUrl:transcodingEnabled:) or [removePublishStreamUrl](removePublishStreamUrl:) method. + +This callback returns the URL and its current streaming state. + +This callback indicates the state of the RTMP or RTMPS streaming. When exceptions occur, you can troubleshoot issues by referring to the detailed error descriptions in the `errorCode` parameter. + +@param engine AgoraRtcEngineKit object. +@param url The CDN streaming URL. +@param state The RTMP or RTMPS streaming state: AgoraRtmpStreamingState. +@param errorCode The detailed error information for streaming: AgoraRtmpStreamingErrorCode. + */ +- (void)rtcEngine:(AgoraRtcEngineKit* _Nonnull)engine rtmpStreamingChangedToState:(NSString* _Nonnull)url state:(AgoraRtmpStreamingState)state errorCode:(AgoraRtmpStreamingErrorCode)errorCode; + +/** Reports events during the RTMP or RTMPS streaming. + + @since v3.1.0 + + @param engine AgoraRtcEngineKit object. + @param url The RTMP or RTMPS streaming URL. + @param eventCode The event code. See AgoraRtmpStreamingEvent. + */ +- (void)rtcEngine:(AgoraRtcEngineKit* _Nonnull)engine rtmpStreamingEventWithUrl:(NSString* _Nonnull)url eventCode:(AgoraRtmpStreamingEvent)eventCode; + +/** Occurs when the CDN live streaming settings are updated. + + When the `LiveTranscoding` class in the [setLiveTranscoding]([AgoraRtcEngineKit setLiveTranscoding:]) method updates, the SDK triggers the rtcEngineTranscodingUpdated callback to report the update information to the local host. + + **Note:** + + If you call the `setLiveTranscoding` method to set the `LiveTranscoding` class for the first time, the SDK does not trigger the `rtcEngineTranscodingUpdated` callback. + + @param engine AgoraRtcEngineKit object. + */ +- (void)rtcEngineTranscodingUpdated:(AgoraRtcEngineKit* _Nonnull)engine; + +#pragma mark Inject Stream URL Delegate Methods + +/**----------------------------------------------------------------------------- + * @name Inject Online Stream Delegate Methods + * ----------------------------------------------------------------------------- + */ + +/** Reports the status of injecting an online stream to the interactive live streaming. + + @warning Agora will soon stop the service for injecting online media streams on the client. If you have not implemented this service, Agora recommends that you do not use it. + + @param engine AgoraRtcEngineKit object. + @param url URL address of the externally injected stream. + @param uid User ID. + @param status Status of the externally injected stream. See AgoraInjectStreamStatus. + */ +- (void)rtcEngine:(AgoraRtcEngineKit* _Nonnull)engine streamInjectedStatusOfUrl:(NSString* _Nonnull)url uid:(NSUInteger)uid status:(AgoraInjectStreamStatus)status; + +#pragma mark Stream Message Delegate Methods + +/**----------------------------------------------------------------------------- + * @name Stream Message Delegate Methods + * ----------------------------------------------------------------------------- + */ + +/** Occurs when the local user receives the data stream from a remote user within five seconds. + +The SDK triggers this callback when the local user receives the stream message that the remote user sends by calling the [sendStreamMessage](sendStreamMessage:data:) method. + + @param engine AgoraRtcEngineKit object. + @param uid User ID of the remote user sending the message. + @param streamId Stream ID. + @param data Data received by the local user. + */ +- (void)rtcEngine:(AgoraRtcEngineKit* _Nonnull)engine receiveStreamMessageFromUid:(NSUInteger)uid streamId:(NSInteger)streamId data:(NSData* _Nonnull)data; + +/** Occurs when the local user does not receive the data stream from the remote user within five seconds. + + The SDK triggers this callback when the local user fails to receive the stream message that the remote user sends by calling the [sendStreamMessage](sendStreamMessage:data:) method. + + @param engine AgoraRtcEngineKit object. + @param uid User ID of the remote user sending the message. + @param streamId Stream ID. + @param error Error code. See AgoraErrorCode. + @param missed Number of lost messages. + @param cached Number of incoming cached messages when the data stream is interrupted. + */ +- (void)rtcEngine:(AgoraRtcEngineKit* _Nonnull)engine didOccurStreamMessageErrorFromUid:(NSUInteger)uid streamId:(NSInteger)streamId error:(NSInteger)error missed:(NSInteger)missed cached:(NSInteger)cached; + +#pragma mark Miscellaneous Delegate Methods + +/**----------------------------------------------------------------------------- + * @name Miscellaneous Delegate Methods + * ----------------------------------------------------------------------------- + */ + +/** Reports the information of an audio file. + + @since v3.5.1 + + After successfully calling [getAudioFileInfo]([AgoraRtcEngineKit getAudioFileInfo:]), + the SDK triggers this callback to report the information of the audio file, + such as the file path and duration. + + @param engine AgoraRtcEngineKit object. + @param info The information of an audio file. See AgoraRtcAudioFileInfo. + @param error The information acquisition state. See AgoraAudioFileInfoError. + */ +- (void)rtcEngine:(AgoraRtcEngineKit* _Nonnull)engine didRequestAudioFileInfo:(AgoraRtcAudioFileInfo* _Nonnull)info error:(AgoraAudioFileInfoError)error; + +- (void)rtcEngine:(AgoraRtcEngineKit* _Nonnull)engine uploadLogResultRequestId:(NSString* _Nonnull)requestId success:(BOOL)success reason:(AgoraUploadErrorReason)reason; + +/** Occurs when the media engine loads. + + @param engine AgoraRtcEngineKit object. + */ +- (void)rtcEngineMediaEngineDidLoaded:(AgoraRtcEngineKit* _Nonnull)engine; + +/** Occurs when the media engine call starts. + + @param engine AgoraRtcEngineKit object. + */ +- (void)rtcEngineMediaEngineDidStartCall:(AgoraRtcEngineKit* _Nonnull)engine; + +/** Occurs when the state of the media stream relay changes. + + The SDK reports the state of the current media relay and possible error messages in this callback. + + @param engine AgoraRtcEngineKit object. + @param state The state code in [AgoraChannelMediaRelayState](AgoraChannelMediaRelayState). + @param error The error code in [AgoraChannelMediaRelayError](AgoraChannelMediaRelayError). + */ +- (void)rtcEngine:(AgoraRtcEngineKit* _Nonnull)engine channelMediaRelayStateDidChange:(AgoraChannelMediaRelayState)state error:(AgoraChannelMediaRelayError)error; + +/** Reports events during the media stream relay. + + @param engine AgoraRtcEngineKit object. + @param event The event code in [AgoraChannelMediaRelayEvent](AgoraChannelMediaRelayEvent). + */ +- (void)rtcEngine:(AgoraRtcEngineKit* _Nonnull)engine didReceiveChannelMediaRelayEvent:(AgoraChannelMediaRelayEvent)event; + +#pragma mark Deprecated Delegates + +/**----------------------------------------------------------------------------- + * @name Deprecated Delegates + * ----------------------------------------------------------------------------- + */ +/** Occurs when the engine sends the first local audio frame. + +**Deprecated** from v3.1.0. Use [firstLocalAudioFramePublished]([AgoraRtcEngineDelegate rtcEngine:firstLocalAudioFramePublished:]) instead. + + @param engine AgoraRtcEngineKit object. + @param elapsed Time elapsed (ms) from the local user calling the [joinChannelByToken]([AgoraRtcEngineKit joinChannelByToken:channelId:info:uid:joinSuccess:]) method until the SDK triggers this callback. + */ +- (void)rtcEngine:(AgoraRtcEngineKit* _Nonnull)engine firstLocalAudioFrame:(NSInteger)elapsed; + +/** Occurs when the engine receives the first audio frame from a specified remote user. + + **Deprecated** from v3.0.0. Use `AgoraAudioRemoteStateStarting(1)` in the [remoteAudioStateChangedOfUid]([AgoraRtcEngineDelegate rtcEngine:remoteAudioStateChangedOfUid:state:reason:elapsed:]) callback. + + This callback is triggered in either of the following scenarios: + + - The remote user joins the channel and sends the audio stream. + - The remote user stops sending the audio stream and re-sends it after 15 seconds. Possible reasons include: + + - The remote user leaves channel. + - The remote user drops offline. + - The remote user calls [muteLocalAudioStream]([AgoraRtcEngineKit muteLocalAudioStream:]). + - The remote user calls [disableAudio]([AgoraRtcEngineKit disableAudio]). + + @param engine AgoraRtcEngineKit object. + @param uid User ID of the remote user. + @param elapsed Time elapsed (ms) from the local user calling the [joinChannelByToken]([AgoraRtcEngineKit joinChannelByToken:channelId:info:uid:joinSuccess:]) method until the SDK triggers this callback. + */ +- (void)rtcEngine:(AgoraRtcEngineKit* _Nonnull)engine firstRemoteAudioFrameOfUid:(NSUInteger)uid elapsed:(NSInteger)elapsed; + +/** Occurs when the SDK decodes the first remote audio frame for playback. + + **Deprecated** from v3.0.0. Use `AgoraAudioRemoteStateDecoding(2)` in the [remoteAudioStateChangedOfUid]([AgoraRtcEngineDelegate rtcEngine:remoteAudioStateChangedOfUid:state:reason:elapsed:]) callback instead. + + This callback is triggered in either of the following scenarios: + + - The remote user joins the channel and sends the audio stream. + - The remote user stops sending the audio stream and re-sends it after 15 seconds. Reasons for such an interruption include: + + - The remote user leaves channel. + - The remote user drops offline. + - The remote user calls the [muteLocalAudioStream]([AgoraRtcEngineKit muteLocalAudioStream:]) method to stop sending the local audio stream. + - The remote user calls the [disableAudio]([AgoraRtcEngineKit disableAudio]) method to disable audio. + + @param engine AgoraRtcEngineKit object. + @param uid User ID of the remote user sending the audio stream. + @param elapsed The time elapsed (ms) from the local user calling the joinChannel method until the SDK triggers this callback. + */ +- (void)rtcEngine:(AgoraRtcEngineKit* _Nonnull)engine firstRemoteAudioFrameDecodedOfUid:(NSUInteger)uid elapsed:(NSInteger)elapsed; + +/** Reports the result of calling the [addPublishStreamUrl]([AgoraRtcEngineKit addPublishStreamUrl:transcodingEnabled:]) method. + + **Deprecated** from v3.0.0. Use the [rtmpStreamingChangedToState]([AgoraRtcEngineDelegate rtcEngine:rtmpStreamingChangedToState:state:errorCode:]) callback instead. + + @param engine AgoraRtcEngineKit object. + @param url The CDN streaming URL. + @param errorCode Error code: [AgoraErrorCode](AgoraErrorCode). Main errors include: + + - AgoraErrorCodeNoError(0): The publishing succeeds. + - AgoraErrorCodeFailed(1): The publishing fails. + - AgoraErrorCodeInvalidArgument(2): Invalid argument used. If, for example, you do not call the [setLiveTranscoding]([AgoraRtcEngineKit setLiveTranscoding:]) method to configure AgoraLiveTranscoding before calling the [addPublishStreamUrl]([AgoraRtcEngineKit addPublishStreamUrl:transcodingEnabled:]) method, the SDK reports this error. + - AgoraErrorCodeTimedOut(10): The publishing times out. + - AgoraErrorCodeAlreadyInUse(19): The CDN streaming URL is already in use for CDN live streaming. + - AgoraErrorCodeEncryptedStreamNotAllowedPublish(130): You cannot publish an encrypted stream. + - AgoraErrorCodePublishStreamCDNError(151): CDN related errors. Remove the original URL address and add a new one by calling the [removePublishStreamUrl]([AgoraRtcEngineKit removePublishStreamUrl:]) and [addPublishStreamUrl]([AgoraRtcEngineKit addPublishStreamUrl:transcodingEnabled:]) methods. + - AgoraErrorCodePublishStreamNumReachLimit(152): The host publishes more than 10 URLs. Delete the unnecessary URLs before adding new ones. + - AgoraErrorCodePublishStreamNotAuthorized(153): The host manipulates other hosts' URLs. Check your app logic. + - AgoraErrorCodePublishStreamInternalServerError(154): An error occurs in Agora's streaming server. Call the [addPublishStreamUrl]([AgoraRtcEngineKit addPublishStreamUrl:transcodingEnabled:]) method to publish the streaming again. + - AgoraErrorCodePublishStreamFormatNotSuppported(156): The format of the RTMP stream URL is not supported. Check whether the URL format is correct. + */ +- (void)rtcEngine:(AgoraRtcEngineKit* _Nonnull)engine streamPublishedWithUrl:(NSString* _Nonnull)url errorCode:(AgoraErrorCode)errorCode; + +/** Reports the result of calling the [removePublishStreamUrl]([AgoraRtcEngineKit removePublishStreamUrl:]) method. + + **Deprecated** from v3.0.0. Use the [rtmpStreamingChangedToState]([AgoraRtcEngineDelegate rtcEngine:rtmpStreamingChangedToState:state:errorCode:]) callback instead. + + This callback indicates whether you have successfully removed an RTMP stream from the CDN. + + @param engine AgoraRtcEngineKit object. + @param url The CDN streaming URL. + */ +- (void)rtcEngine:(AgoraRtcEngineKit* _Nonnull)engine streamUnpublishedWithUrl:(NSString* _Nonnull)url; + +/** Reports the transport-layer statistics of each remote audio stream. + + **Deprecated** from v2.9.0. Use the [remoteAudioStats]([AgoraRtcEngineDelegate rtcEngine:remoteAudioStats:]) callback instead. + + This callback reports the transport-layer statistics, such as the packet loss rate and network time delay, once every two seconds after the local user receives an audio packet from a remote user. + + @param engine AgoraRtcEngineKit object. + @param uid User ID of the remote user sending the audio packet. + @param delay Network time delay (ms) from the remote user sending the audio packet to the local user. + @param lost Packet loss rate (%) of the audio packet sent from the remote user. + @param rxKBitRate Received bitrate (Kbps) of the audio packet sent from the remote user. + */ +- (void)rtcEngine:(AgoraRtcEngineKit* _Nonnull)engine audioTransportStatsOfUid:(NSUInteger)uid delay:(NSUInteger)delay lost:(NSUInteger)lost rxKBitRate:(NSUInteger)rxKBitRate; + +/** Reports the transport-layer statistics of each remote video stream. + + **Deprecated** from v2.9.0. Use the [remoteVideoStats]([AgoraRtcEngineDelegate rtcEngine:remoteVideoStats:]) callback instead. + + This callback reports the transport layer statistics, such as the packet loss rate and network time delay, once every two seconds after the local user receives a video packet from a remote user. + + @param engine AgoraRtcEngineKit object. + @param uid User ID of the remote user sending the video packet. + @param delay Network time delay (ms) from the remote user sending the video packet to the local user. + @param lost Packet loss rate (%) of the video packet sent from the remote user. + @param rxKBitRate Received bitrate (Kbps) of the video packet sent from the remote user. + */ +- (void)rtcEngine:(AgoraRtcEngineKit* _Nonnull)engine videoTransportStatsOfUid:(NSUInteger)uid delay:(NSUInteger)delay lost:(NSUInteger)lost rxKBitRate:(NSUInteger)rxKBitRate; + +/** Occurs when the microphone is enabled/disabled. + + **Deprecated** from v2.9.0. Use AgoraAudioLocalStateStopped(0) or AgoraAudioLocalStateRecording(1) in the [localAudioStateChange]([AgoraRtcEngineDelegate rtcEngine:localAudioStateChange:error:]) callback instead. + + The SDK triggers this callback when the local user resumes or stops capturing the local audio stream by calling the [enableLocalAudio]([AgoraRtcEngineKit enableLocalAudio:]) method. + + @param engine AgoraRtcEngineKit object. + @param enabled Whether the microphone is enabled/disabled: + + * YES: Enabled. + * NO: Disabled. + */ +- (void)rtcEngine:(AgoraRtcEngineKit* _Nonnull)engine didMicrophoneEnabled:(BOOL)enabled; + +/** Occurs when the connection between the SDK and the server is interrupted. + +**Deprecated** from v2.3.2. Use `AgoraConnectionStateReconnecting(4)` and `AgoraConnectionChangedInterrupted(2)` of the [connectionChangedToState]([AgoraRtcEngineDelegate rtcEngine:connectionChangedToState:reason:]) callback instead. + +The SDK triggers this callback when it loses connection with the server for more than four seconds after a connection is established. + +After triggering this callback, the SDK tries reconnecting to the server. You can use this callback to implement pop-up reminders. + +This callback is different from [rtcEngineConnectionDidLost]([AgoraRtcEngineDelegate rtcEngineConnectionDidLost:]): + +- The SDK triggers the [rtcEngineConnectionDidInterrupted]([AgoraRtcEngineDelegate rtcEngineConnectionDidInterrupted:]) callback when it loses connection with the server for more than four seconds after it joins the channel. +- The SDK triggers the [rtcEngineConnectionDidLost]([AgoraRtcEngineDelegate rtcEngineConnectionDidLost:]) callback when it loses connection with the server for more than 10 seconds, regardless of whether it joins the channel or not. + +If the SDK fails to rejoin the channel 20 minutes after being disconnected from Agora's edge server, the SDK stops rejoining the channel. + + @param engine AgoraRtcEngineKit object. + */ +- (void)rtcEngineConnectionDidInterrupted:(AgoraRtcEngineKit* _Nonnull)engine; + +/** Occurs when your connection is banned by the Agora server. + +**Deprecated** from v2.3.2. Use `AgoraConnectionStateFailed(5)` and `AgoraConnectionChangedBannedByServer(3)` of [connectionChangedToState]([AgoraRtcEngineDelegate rtcEngine:connectionChangedToState:reason:]) callback instead. + +@param engine AgoraRtcEngineKit object + */ +- (void)rtcEngineConnectionDidBanned:(AgoraRtcEngineKit* _Nonnull)engine; + +/** Reports the audio quality of the remote user. + +Same as [audioQualityBlock]([AgoraRtcEngineKit audioQualityBlock:]). + +**Deprecated** from v2.3.2. Use [remoteAudioStats]([AgoraRtcEngineDelegate rtcEngine:remoteAudioStats:]) instead. + +The SDK triggers this callback once every two seconds. This callback reports the audio quality of each remote user/host sending an audio stream. If a channel has multiple users/hosts sending audio streams, then the SDK triggers this callback as many times. + + @see See [remoteAudioStats]([AgoraRtcEngineDelegate rtcEngine:remoteAudioStats:]) + @param engine AgoraRtcEngineKit object. + @param uid User ID of the speaker. + @param quality Audio quality of the user, see AgoraNetworkQuality. + @param delay Time delay (ms) of the audio packet sent from the sender to the receiver, including the time delay from audio sampling pre-processing, transmission, and the jitter buffer. + @param lost Packet loss rate (%) of the audio packet sent from the sender to the receiver. + */ +- (void)rtcEngine:(AgoraRtcEngineKit* _Nonnull)engine audioQualityOfUid:(NSUInteger)uid quality:(AgoraNetworkQuality)quality delay:(NSUInteger)delay lost:(NSUInteger)lost; + +/** Occurs when the camera turns on and is ready to capture video. + +**Deprecated** from v2.4.1. Use AgoraLocalVideoStreamStateCapturing(1) in the `state` parameter of [localVideoStateChange]([AgoraRtcEngineDelegate rtcEngine:localVideoStateChange:error:]) instead. + + Same as [cameraReadyBlock]([AgoraRtcEngineKit cameraReadyBlock:]). + + @see [localVideoStateChange]([AgoraRtcEngineDelegate rtcEngine:localVideoStateChange:error:]) + @param engine AgoraRtcEngineKit object. + */ +- (void)rtcEngineCameraDidReady:(AgoraRtcEngineKit* _Nonnull)engine; + +/** Occurs when the video stops playing. + +**Deprecated** from v2.4.1. Use AgoraLocalVideoStreamStateStopped(0) in the `state` parameter of [localVideoStateChange]([AgoraRtcEngineDelegate rtcEngine:localVideoStateChange:error:]) instead + + The app can use this callback to change the configuration of the view (for example, to display other screens in the view) after the video stops. + + @see [localVideoStateChange]([AgoraRtcEngineDelegate rtcEngine:localVideoStateChange:error:]) + @param engine AgoraRtcEngineKit object. + */ +- (void)rtcEngineVideoDidStop:(AgoraRtcEngineKit* _Nonnull)engine; + +@end + +#pragma mark - AgoraRtcEngineKit + +/** The AgoraRtcEngineKit class provides all methods invoked by your app. + + Agora provides ensured quality of experience (QoE) for worldwide Internet-based voice and video communications through a virtual global network optimized for real-time web and mobile-to-mobile apps. + + AgoraRtcEngineKit is the basic interface class of the SDK. Creating an AgoraRtcEngineKit object and then calling the methods of this object enables the use of the SDK’s communication functionality. +*/ +__attribute__((visibility("default"))) @interface AgoraRtcEngineKit : NSObject + +#pragma mark Core Service + +/**----------------------------------------------------------------------------- + * @name Core Service + * ----------------------------------------------------------------------------- + */ + +/** Creates an AgoraRtcEngineKit instance. + + Unless otherwise specified, all the methods provided by the AgoraRtcEngineKit instance are executed asynchronously. Agora recommends calling these methods in the same thread. + + **Note:** + + - You must create an AgoraRtcEngineKit instance before calling any other method. + - You can create an AgoraRtcEngineKit instance either by calling this method or by calling [sharedEngineWithConfig]([AgoraRtcEngineKit sharedEngineWithConfig:delegate:]). The difference between `sharedEngineWithConfig` and this method is that `sharedEngineWithConfig` enables you to specify the region for connection. + - The Agora RTC Native SDK supports creating only one AgoraRtcEngineKit instance for an app for now. + + @param appId The App ID issued to you by Agora. See [How to get the App ID](https://docs.agora.io/en/Agora%20Platform/token#get-an-app-id). Only users in apps with the same App ID can join the same channel and communicate with each other. Use an App ID to create only one AgoraRtcEngineKit instance. To change your App ID, call [destroy]([AgoraRtcEngineKit destroy]) to `destroy` the current AgoraRtcEngineKit instance, and after `destroy` returns 0, call `sharedEngineWithAppId` to create an AgoraRtcEngineKit instance with the new App ID. + @param delegate AgoraRtcEngineDelegate. + + @return - The AgoraRtcEngineKit instance, if this method call succeeds. + - The error code, if this method call fails. + + - `-1`(`AgoraErrorCodeFailed`): A general error occurs (no specified reason). + - `-2`(`AgoraErrorCodeInvalidArgument`): No `AgoraRtcEngineDelegate` object is specified. + - `-7`(`AgoraErrorCodeNotInitialized`): The SDK is not initialized. + - `-101`(`AgoraErrorCodeInvalidAppId`): The App ID is invalid. + */ ++ (instancetype _Nonnull)sharedEngineWithAppId:(NSString* _Nonnull)appId delegate:(id _Nullable)delegate; + +/** Creates an AgoraRtcEngineKit instance. + + Unless otherwise specified, all the methods provided by the AgoraRtcEngineKit instance are executed asynchronously. Agora recommends calling these methods in the same thread. + + **Note:** + + - You must create the AgoraRtcEngineKit instance before calling any other method. + - You can create an AgoraRtcEngineKit instance either by calling this method or by calling [sharedEngineWithAppId]([AgoraRtcEngineKit sharedEngineWithAppId:delegate:]). The difference between `sharedEngineWithAppId` and this method is that this method enables you to specify the region for connection. + - The Agora RTC Native SDK supports creating only one AgoraRtcEngineKit instance for an app for now. + + @param config Configurations for the AgoraRtcEngineKit instance. For details, see AgoraRtcEngineConfig. + @param delegate AgoraRtcEngineDelegate. + + @return - The AgoraRtcEngineKit instance, if this method call succeeds. + - The error code, if this method call fails. + + - `-1`(`AgoraErrorCodeFailed`): A general error occurs (no specified reason). + - `-2`(`AgoraErrorCodeInvalidArgument`): No `AgoraRtcEngineDelegate` object is specified. + - `-7`(`AgoraErrorCodeNotInitialized`): The SDK is not initialized. + - `-101`(`AgoraErrorCodeInvalidAppId`): The App ID is invalid. + */ ++ (instancetype _Nonnull)sharedEngineWithConfig:(AgoraRtcEngineConfig* _Nonnull)config delegate:(id _Nullable)delegate; + +/** Destroys the `AgoraRtcEngineKit` instance and releases all resources used by the Agora SDK. + + Use this method for apps in which users occasionally make voice or video calls. When users do not make calls, you can free up resources + for other operations. Once you call `destroy` to destroy the created `AgoraRtcEngineKit` instance, you cannot use any method or callback + in the SDK any more. If you want to use the real-time communication functions again, you must call + [sharedEngineWithappId]([AgoraRtcEngineKit sharedEngineWithAppId:delegate:]) to create a new `AgoraRtcEngineKit` instance. + + **Note:** + + - Because `destroy` is a synchronous method and the app cannot move on to another task until the execution completes, Agora suggests + calling this method in a sub-thread to avoid congestion in the main thread. Besides, you **cannot** call `destroy` in any method or + callback of the SDK. Otherwise, the SDK cannot release the resources occupied by the `AgoraRtcEngineKit` instance until the callbacks + return results, which may result in a deadlock. + - If you want to create a new `AgoraRtcEngineKit` instance after destroying the current one, ensure that you wait till the `destroy` method completes executing. + */ ++ (void)destroy; + +/** Sets the channel profile of the AgoraRtcEngineKit. + + After initialization, the SDK uses the communication channel profile by default. + You can call `setChannelProfile` to set the channel profile. + The `AgoraRtcEngineKit` differentiates channel profiles and applies optimization + algorithms accordingly. For example, it prioritizes smoothness and low latency + for a video call, and prioritizes video quality for the interactive live video streaming. + + **Note:** + + - To ensure the quality of real-time communication, we recommend that all users in a channel use the same channel profile. + - Call this method before calling [joinChannelByToken]([AgoraRtcEngineKit joinChannelByToken:channelId:info:uid:joinSuccess:]). You cannot set the channel profile once you have joined the channel. + - The default audio route and video encoding bitrate are different in different channel profiles. For details, see [setDefaultAudioRouteToSpeakerphone]([AgoraRtcEngineKit setDefaultAudioRouteToSpeakerphone:]) and [setVideoEncoderConfiguration]([AgoraRtcEngineKit setVideoEncoderConfiguration:]). + + @param profile The channel profile of the AgoraRtcEngineKit: [AgoraChannelProfile](AgoraChannelProfile). + + @return - `0`(`AgoraErrorCodeNoError`): Success. +- < `0`: Failure. + + - `-2`(`AgoraErrorCodeInvalidArgument`): The parameter is invalid. + - `-7`(`AgoraErrorCodeNotInitialized`): The SDK is not initialized. + */ +- (int)setChannelProfile:(AgoraChannelProfile)profile; + +/** Sets the role of the user in interactive live streaming. + + After calling [setChannelProfile(AgoraChannelProfileLiveBroadcasting)]([AgoraRtcEngineKit setChannelProfile:]), + the SDK sets the user role as audience by default. You can call + `setClientRole` to set the user role as host. + + You can call this method either before or after joining a channel. + If you call this method to switch the user role after joining a channel, + the SDK automatically does the following: + + - Calls [muteLocalAudioStream]([AgoraRtcEngineKit muteLocalAudioStream:]) and + [muteLocalVideoStream]([AgoraRtcEngineKit muteLocalVideoStream:]) to change + the publishing state. + - Triggers [didClientRoleChanged]([AgoraRtcEngineDelegate rtcEngine:didClientRoleChanged:newRole:]) + on the local client. + - Triggers [didJoinedOfUid]([AgoraRtcEngineDelegate rtcEngine:didJoinedOfUid:elapsed:]) + or [didOfflineOfUid(AgoraUserOfflineReasonBecomeAudience)]([AgoraRtcEngineDelegate rtcEngine:didOfflineOfUid:reason:]) + on the remote client. + + @note This method applies to the `AgoraChannelProfileLiveBroadcasting` profile + only (when the `profile` parameter in `setChannelProfile` is set as + `AgoraChannelProfileLiveBroadcasting`). + + @param role The role of a user in interactive live streaming. + See [AgoraClientRole](AgoraClientRole). + + @return - 0(`AgoraErrorCodeNoError`): Success. + - < 0: Failure. + + - -1(`AgoraErrorCodeFailed`): A general error occurs (no specified reason). + - -2(`AgoraErrorCodeInvalidArgument`): The parameter is invalid. + - -7(`AgoraErrorCodeNotInitialized`): The SDK is not initialized. + - -5 (`AgoraErrorCodeRefused`): The request is rejected. In multichannel + scenarios, if you have set any of the following in one channel, the SDK + returns this error code when the user switches the user role to host + in another channel: + + - Call [joinChannelByToken]([AgoraRtcEngineKit joinChannelByToken:channelId:info:uid:options:]) + with the `options` parameter and use the default settings + `publishLocalAudio = YES` or `publishLocalVideo = YES`. + - Call `setClientRole` to set the user role as host. + - Call `muteLocalAudioStream(NO)` or `muteLocalVideoStream(NO)`. + */ +- (int)setClientRole:(AgoraClientRole)role; + +/** Sets the role of the user in interactive live streaming. + + @since v3.2.0 + + After calling [setChannelProfile(AgoraChannelProfileLiveBroadcasting)]([AgoraRtcEngineKit setChannelProfile:]), + the SDK sets the user role as audience by default. You can call + `setClientRole` to set the user role as host. + + You can call this method either before or after joining a channel. + If you call this method to switch the user role after joining a channel, + the SDK automatically does the following: + + - Calls [muteLocalAudioStream]([AgoraRtcEngineKit muteLocalAudioStream:]) and + [muteLocalVideoStream]([AgoraRtcEngineKit muteLocalVideoStream:]) to change + the publishing state. + - Triggers [didClientRoleChanged]([AgoraRtcEngineDelegate rtcEngine:didClientRoleChanged:newRole:]) + on the local client. + - Triggers [didJoinedOfUid]([AgoraRtcEngineDelegate rtcEngine:didJoinedOfUid:elapsed:]) + or [didOfflineOfUid(AgoraUserOfflineReasonBecomeAudience)]([AgoraRtcEngineDelegate rtcEngine:didOfflineOfUid:reason:]) + on the remote client. + + **Note** + + -This method applies to the `AgoraChannelProfileLiveBroadcasting` profile + only (when the `profile` parameter in `setChannelProfile` is set as + `AgoraChannelProfileLiveBroadcasting`). + - The difference between this method and + [setClientRole]([AgoraRtcEngineKit setClientRole:])1 is that this method can + set the user level in addition to the user role. + + - The user role determines the permissions that the SDK grants to a user, + such as permission to send local streams, receive remote + streams, and push streams to a CDN address. + - The user level determines the level of services that a user can enjoy + within the permissions of the user's role. For example, an audience member + can choose to receive remote streams with low latency or ultra low latency. + **User level affects the pricing of services**. + + @param role The role of a user in interactive live streaming. + See [AgoraClientRole](AgoraClientRole). + @param options The detailed options of a user, including user level. + See [AgoraClientRoleOptions](AgoraClientRoleOptions). + + @return - 0(`AgoraErrorCodeNoError`): Success. + - < 0: Failure. + + - -1(`AgoraErrorCodeFailed`): A general error occurs (no specified reason). + - -2(`AgoraErrorCodeInvalidArgument`): The parameter is invalid. + - -7(`AgoraErrorCodeNotInitialized`): The SDK is not initialized. + - -5 (`AgoraErrorCodeRefused`): The request is rejected. In multichannel + scenarios, if you have set any of the following in one channel, the SDK + returns this error code when the user switches the user role to host + in another channel: + + - Call [joinChannelByToken]([AgoraRtcEngineKit joinChannelByToken:channelId:info:uid:options:]) + with the `options` parameter and use the default settings + `publishLocalAudio = YES` or `publishLocalVideo = YES`. + - Call `setClientRole` to set the user role as host. + - Call `muteLocalAudioStream(NO)` or `muteLocalVideoStream(NO)`. + */ +- (int)setClientRole:(AgoraClientRole)role options:(AgoraClientRoleOptions* _Nullable)options; +/** Joins a channel with the user ID. + +Users in the same channel can talk to each other, and multiple users in the same channel can start a group chat. Users with different App IDs cannot call each other even if they join the same channel. + +You must call the [leaveChannel]([AgoraRtcEngineKit leaveChannel:]) method to exit the current call before entering another channel. This method call is asynchronous; therefore, you can call this method in the main user interface thread. + +The SDK uses the iOS's AVAudioSession shared object for audio sampling and playback. Using this object may affect the SDK’s audio functions. + +If the [joinChannelByToken]([AgoraRtcEngineKit joinChannelByToken:channelId:info:uid:joinSuccess:]) method call succeeds, the SDK triggers`joinSuccessBlock`. If you implement both `joinSuccessBlock` and [didJoinChannel]([AgoraRtcEngineDelegate rtcEngine:didJoinChannel:withUid:elapsed:]), `joinSuccessBlock` takes higher priority than [didJoinChannel]([AgoraRtcEngineDelegate rtcEngine:didJoinChannel:withUid:elapsed:]). + +We recommend you set `joinSuccessBlock` as nil to use [didJoinChannel]([AgoraRtcEngineDelegate rtcEngine:didJoinChannel:withUid:elapsed:]). + +A successful joinChannel method call triggers the following callbacks: + +- The local client: [didJoinChannel]([AgoraRtcEngineDelegate rtcEngine:didJoinChannel:withUid:elapsed:]) +- The remote client: [didJoinedOfUid]([AgoraRtcEngineDelegate rtcEngine:didJoinedOfUid:elapsed:]), if the user joining the channel is in the Communication profile, or is a host in the Live Broadcast profile. + +Once the user joins the channel, the user subscribes to the audio and video streams of all the other users in the channel by default, giving rise to usage and billing calculation. If you do not want to subscribe to a specified stream or all remote streams, call the `mute` methods accordingly. + +When the connection between the client and Agora's server is interrupted due to poor network conditions, the SDK tries reconnecting to the server. When the local client successfully rejoins the channel, the SDK triggers the [didRejoinChannel]([AgoraRtcEngineDelegate rtcEngine:didRejoinChannel:withUid:elapsed:]) callback on the local client. + +**Note:** + +- A channel does not accept duplicate UIDs, such as two users with the same `uid`. If you set `uid` as 0, the system automatically assigns a `uid`. If you want to join the same channel on different devices, ensure that different uids are used for each device. +- When joining a channel, the SDK calls `setCategory(AVAudioSessionCategoryPlayAndRecord)` to set `AVAudioSession` to `PlayAndRecord` mode. When `AVAudioSession` is set to `PlayAndRecord` mode, the sound played (for example a ringtone) is interrupted. The app should not set `AVAudioSession` to any other mode. + + @param token The token generated at your server. See [Authenticate Your Users with Tokens](https://docs.agora.io/en/Interactive%20Broadcast/token_server?platform=All%20Platforms). + @param channelId Unique channel name for the Agora RTC session in the string format. The string length must be less than 64 bytes. + Supported character scopes are: + + * All lowercase English letters: a to z. + * All uppercase English letters: A to Z. + * All numeric characters: 0 to 9. + * The space character. + * Punctuation characters and other symbols, including: "!", "#", "$", "%", "&", "(", ")", "+", "-", ":", ";", "<", "=", ".", ">", "?", "@", "[", "]", "^", "_", "{", "}", "|", "~", ",". + +@param info (Optional) Additional information about the channel. This parameter can be set to nil or contain channel related information. Other users in the channel do not receive this message. +@param uid User ID. A 32-bit unsigned integer with a value ranging from 1 to (232-1). The `uid` must be unique. If a `uid` is not assigned (or set to 0), the SDK assigns and returns a `uid` in `joinSuccessBlock`. Your app must record and maintain the returned `uid` since the SDK does not do so. +@param joinSuccessBlock Occurs when the local user joins a specified channel. +If you implement both `joinSuccessBlock` and `didJoinChannel`, `joinSuccessBlock` +takes higher priority than `didJoinChannel`. Agora recommends setting `joinSuccessBlock` as `nil` to use `didJoinChannel`. + +@return - `0`(`AgoraErrorCodeNoError`): Success. +- < `0`: Failure. + + - `-2`(`AgoraErrorCodeInvalidArgument`): The parameter is invalid. + - `-3`(`AgoraErrorCodeNotReady`): The SDK fails to be initialized. You can try re-initializing the SDK. + - `-5`(`AgoraErrorCodeRefused`): The request is rejected. This may be caused by the following: + - `-7`(`AgoraErrorCodeNotInitialized`): The SDK is not initialized. + + - You have created an `AgoraRtcChannel` object with the same channel name. + - You have joined and published a stream in a channel created by the `AgoraRtcChannel` object. When you join a channel created by `AgoraRtcEngineKit`, the SDK publishes the local audio and video streams to that channel by default. Because the SDK does not support publishing a local stream to more than one channel simultaneously, an error occurs in this occasion. + + - `-17`(`AgoraErrorCodeJoinChannelRejected`): The request to join the channel is rejected. + The SDK supports joining only one AgoraRtcEngineKit channel at a time. Therefore, the SDK returns this error + code when a user who has already joined an AgoraRtcEngineKit channel calls the joining channel method of the + AgoraRtcEngineKit class with a valid channel name. +*/ +- (int)joinChannelByToken:(NSString* _Nullable)token channelId:(NSString* _Nonnull)channelId info:(NSString* _Nullable)info uid:(NSUInteger)uid joinSuccess:(void (^_Nullable)(NSString* _Nonnull channel, NSUInteger uid, NSInteger elapsed))joinSuccessBlock; + +/** Joins a channel with the user ID, and configures whether to publish or + automatically subscribe to the audio or video streams. + + @since v3.3.0 + + Users in the same channel can talk to each other, and multiple users in the + same channel can start a group chat. Users with different App IDs cannot call + each other. + + You must call the [leaveChannel]([AgoraRtcEngineKit leaveChannel:]) method to + exit the current call before entering another channel. + + A successful `joinChannelByToken` method call triggers the following + callbacks: + + - The local client: [didJoinChannel]([AgoraRtcEngineDelegate rtcEngine:didJoinChannel:withUid:elapsed:]) + - The remote client: [didJoinedOfUid]([AgoraRtcEngineDelegate rtcEngine:didJoinedOfUid:elapsed:]), + if the user joining the channel is in the Communication profile, or is a + host in the Live Broadcast profile. + + When the connection between the client and the Agora server is interrupted + due to poor network conditions, the SDK tries reconnecting to the server. + When the local client successfully rejoins the channel, the SDK triggers + the [didRejoinChannel]([AgoraRtcEngineDelegate rtcEngine:didRejoinChannel:withUid:elapsed:]) + callback on the local client. + + **Note** + + - Compared with [joinChannelByToken]([AgoraRtcEngineKit joinChannelByToken:channelId:info:uid:joinSuccess:])1, + this method has the `options` parameter which configures whether the user publishes or + automatically subscribes to the audio and video streams in the channel + when joining the channel. By default, the user publishes the local audio and + video streams and automatically subscribes to the audio and + video streams of all the other users in the channel. Subscribing incurs all + associated usage costs. To unsubscribe, set the `options` parameter or call + the `mute` methods accordingly. + - Ensure that the App ID used for generating the token is the same App ID used + in the [sharedEngineWithAppId]([AgoraRtcEngineKit sharedEngineWithAppId:delegate:]) + method for generating an `AgoraRtcEngineKit` object. + + @param token The token generated at your server. For details, see [Generate a token](https://docs.agora.io/en/Interactive%20Broadcast/token_server?platform=All%20Platforms). + @param channelId The unique channel name for the Agora RTC session in the string format. The string length must be less than 64 bytes. + Supported character scopes are: + + * All lowercase English letters: a to z. + * All uppercase English letters: A to Z. + * All numeric characters: 0 to 9. + * The space character. + * Punctuation characters and other symbols, including: "!", "#", "$", "%", "&", "(", ")", "+", "-", ":", ";", "<", "=", ".", ">", "?", "@", "[", "]", "^", "_", "{", "}", "|", "~", ",". + + @param info (Optional) Additional information about the channel. This parameter can be set to nil or contain channel related information. Other users in the channel do not receive this message. + @param uid (Optional) User ID. A 32-bit unsigned integer with a value ranging + from 1 to (232-1). The `uid` must be unique. If a `uid` is not + assigned (or set to `0`), the SDK assigns and returns a `uid` in the + `didJoinChannel` callback. Your application must record and maintain the + returned `uid`, because the SDK does not do so. + + **Note**: The ID of each user in the channel should be unique. If you want to join + the same channel from different devices, ensure that the user IDs in all + devices are different. + @param options The channel media options: AgoraRtcChannelMediaOptions. + + @return - `0`(`AgoraErrorCodeNoError`): Success. + - < `0`: Failure. + + - `-2`(`AgoraErrorCodeInvalidArgument`): The parameter is invalid. + - `-3`(`AgoraErrorCodeNotReady`): The SDK fails to be initialized. You can try re-initializing the SDK. + - `-5`(`AgoraErrorCodeRefused`): The request is rejected. This may be caused by the following: + + - You have created an `AgoraRtcChannel` object with the same channel name. + - You have joined and published a stream in a channel created by the `AgoraRtcChannel` object. When you join a channel created by `AgoraRtcEngineKit`, the SDK publishes the local audio and video streams to that channel by default. Because the SDK does not support publishing a local stream to more than one channel simultaneously, an error occurs in this occasion. + + - `-7`(`AgoraErrorCodeNotInitialized`): The SDK is not initialized before calling this method. + - `-17`(`AgoraErrorCodeJoinChannelRejected`): The request to join the channel is rejected. + The SDK supports joining only one AgoraRtcEngineKit channel at a time. Therefore, the SDK returns this error + code when a user who has already joined an AgoraRtcEngineKit channel calls the joining channel method of the + AgoraRtcEngineKit class with a valid channel name. +*/ +- (int)joinChannelByToken:(NSString* _Nullable)token channelId:(NSString* _Nonnull)channelId info:(NSString* _Nullable)info uid:(NSUInteger)uid options:(AgoraRtcChannelMediaOptions* _Nonnull)options; + +/** Joins the channel with a user account. + +After the user successfully joins the channel, the SDK triggers the following callbacks: + +- On the local client: [didRegisteredLocalUser]([AgoraRtcEngineDelegate rtcEngine:didRegisteredLocalUser:withUid:]) and [didJoinChannel]([AgoraRtcEngineDelegate rtcEngine:didJoinChannel:withUid:elapsed:]). +- On the remote client: [didJoinedOfUid]([AgoraRtcEngineDelegate rtcEngine:didJoinedOfUid:elapsed:]) and [didUpdatedUserInfo]([AgoraRtcEngineDelegate rtcEngine:didUpdatedUserInfo:withUid:]), if the user joining the channel is in the Communication profile, or is a host in the Live Broadcast profile. + +Once the user joins the channel, the user subscribes to the audio and video streams of all the other users in the channel by default, giving rise to usage and billing calculation. If you do not want to subscribe to a specified stream or all remote streams, call the `mute` methods accordingly. + + **Note** + + - Before using a String user name, ensure that you read [How can I use string user names](https://docs.agora.io/en/faq/string) for getting details about the limitations and implementation steps. + - To ensure smooth communication, use the same parameter type to identify the user. For example, if a user joins the channel with a user ID, then ensure all the other users use the user ID too. The same applies to the user account. If a user joins the channel with the Agora Web SDK, ensure that the uid of the user is set to the same parameter type. + +@param userAccount The user account. The maximum length of this parameter is 255 bytes. Ensure that you set this parameter and do not set it as `nil`. Supported character scopes are: + +- All lowercase English letters: a to z. +- All uppercase English letters: A to Z. +- All numeric characters: 0 to 9. +- The space character. +- Punctuation characters and other symbols, including: "!", "#", "$", "%", "&", "(", ")", "+", "-", ":", ";", "<", "=", ".", ">", "?", "@", "[", "]", "^", "_", "{", "}", "|", "~", ",". +@param token The token generated at your server. See [Authenticate Your Users with Tokens](https://docs.agora.io/en/Interactive%20Broadcast/token_server?platform=All%20Platforms). +@param channelId The channel name. The maximum length of this parameter is 64 bytes. Supported character scopes are: + +- All lowercase English letters: a to z. +- All uppercase English letters: A to Z. +- All numeric characters: 0 to 9. +- The space character. +- Punctuation characters and other symbols, including: "!", "#", "$", "%", "&", "(", ")", "+", "-", ":", ";", "<", "=", ".", ">", "?", "@", "[", "]", "^", "_", "{", "}", "|", "~", ",". +@param joinSuccessBlock Occurs when the local user joins a specified channel. +If you implement both `joinSuccessBlock` and `didJoinChannel`, `joinSuccessBlock` +takes higher priority than `didJoinChannel`. Agora recommends setting `joinSuccessBlock` as `nil` to use `didJoinChannel`. + +@return * 0: Success. +* < 0: Failure. + + - `AgoraErrorCodeInvalidArgument`(-2) + - `AgoraErrorCodeNotReady`(-3) + - `AgoraErrorCodeRefused`(-5) + - `AgoraErrorCodeSDKNotInitialized`(-7) + - `AgoraErrorCodeJoinChannelRejected`(-17): The request to join the channel is rejected. + The SDK supports joining only one AgoraRtcEngineKit channel at a time. Therefore, the SDK returns this error + code when a user who has already joined an AgoraRtcEngineKit channel calls the joining channel method of the + AgoraRtcEngineKit class with a valid channel name. +*/ +- (int)joinChannelByUserAccount:(NSString* _Nonnull)userAccount token:(NSString* _Nullable)token channelId:(NSString* _Nonnull)channelId joinSuccess:(void (^_Nullable)(NSString* _Nonnull channel, NSUInteger uid, NSInteger elapsed))joinSuccessBlock; + +/** Joins the channel with a user account, and configures whether to + automatically subscribe to audio or video streams after joining the channel. + + @since v3.3.0 + + After the user successfully joins the channel, the SDK triggers the following + callbacks: + + - On the local client: [didRegisteredLocalUser]([AgoraRtcEngineDelegate rtcEngine:didRegisteredLocalUser:withUid:]) + and [didJoinChannel]([AgoraRtcEngineDelegate rtcEngine:didJoinChannel:withUid:elapsed:]). + - On the remote client: [didJoinedOfUid]([AgoraRtcEngineDelegate rtcEngine:didJoinedOfUid:elapsed:]) + and [didUpdatedUserInfo]([AgoraRtcEngineDelegate rtcEngine:didUpdatedUserInfo:withUid:]), + if the user joining the channel is in the Communication profile, or is a host in the Live Broadcast profile. + + **Note** + + - Before using a String user name, ensure that you read + [How can I use string user names](https://docs.agora.io/en/faq/string) + for getting details about the limitations and implementation steps. + - Compared with [joinChannelByUserAccount]([AgoraRtcEngineKit joinChannelByUserAccount:token:channelId:joinSuccess:])1, + this method has the `options` parameter to configure whether the end user + automatically subscribes to all remote audio and video streams in a channel + when joining the channel. By default, the user subscribes to the audio and + video streams of all the other users in the channel, thus incurring all + associated usage costs. To unsubscribe, set the `options` parameter or call + the `mute` methods accordingly. + - To ensure smooth communication, use the same parameter type to identify the + user. For example, if a user joins the channel with a user ID, then ensure + all the other users use the user ID too. The same applies to the user + account. If a user joins the channel with the Agora Web SDK, ensure that + the user ID is set to the same parameter type. + + @param userAccount The user account. The maximum length of this parameter is 255 bytes. Ensure that the user account is unique and do not set it as `nil`. Supported character scopes are: + + - All lowercase English letters: a to z. + - All uppercase English letters: A to Z. + - All numeric characters: 0 to 9. + - The space character. + - Punctuation characters and other symbols, including: "!", "#", "$", "%", "&", "(", ")", "+", "-", ":", ";", "<", "=", ".", ">", "?", "@", "[", "]", "^", "_", "{", "}", "|", "~", ",". + @param token The token generated at your server. For details, see [Generate a token](https://docs.agora.io/en/Interactive%20Broadcast/token_server?platform=All%20Platforms). + @param channelId The channel name. The maximum length of this parameter is 64 bytes. Supported character scopes are: + + - All lowercase English letters: a to z. + - All uppercase English letters: A to Z. + - All numeric characters: 0 to 9. + - The space character. + - Punctuation characters and other symbols, including: "!", "#", "$", "%", "&", "(", ")", "+", "-", ":", ";", "<", "=", ".", ">", "?", "@", "[", "]", "^", "_", "{", "}", "|", "~", ",". + @param options The channel media options: AgoraRtcChannelMediaOptions. + + @return * 0: Success. + * < 0: Failure. + + - `AgoraErrorCodeInvalidArgument`(-2) + - `AgoraErrorCodeNotReady`(-3) + - `AgoraErrorCodeRefused`(-5) + - `AgoraErrorCodeSDKNotInitialized`(-7) + - `AgoraErrorCodeJoinChannelRejected`(-17): The request to join the channel is rejected. + The SDK supports joining only one AgoraRtcEngineKit channel at a time. Therefore, the SDK returns this error + code when a user who has already joined an AgoraRtcEngineKit channel calls the joining channel method of the + AgoraRtcEngineKit class with a valid channel name. +*/ +- (int)joinChannelByUserAccount:(NSString* _Nonnull)userAccount token:(NSString* _Nullable)token channelId:(NSString* _Nonnull)channelId options:(AgoraRtcChannelMediaOptions* _Nonnull)options; + +/** Registers a user account. + +Once registered, the user account can be used to identify the local user when the user joins the channel. After the user successfully registers a user account, the SDK triggers the [didRegisteredLocalUser]([AgoraRtcEngineDelegate rtcEngine:didRegisteredLocalUser:withUid:]) callback on the local client, reporting the user ID and user account of the local user. + +To join a channel with a user account, you can choose either of the following: + +- Call the [registerLocalUserAccount]([AgoraRtcEngineKit registerLocalUserAccount:appId:]) method to create a user account, and then the [joinChannelByUserAccount]([AgoraRtcEngineKit joinChannelByUserAccount:token:channelId:joinSuccess:]) method to join the channel. +- Call the [joinChannelByUserAccount]([AgoraRtcEngineKit joinChannelByUserAccount:token:channelId:joinSuccess:]) method to join the channel. + +The difference between the two is that for the former, the time elapsed between calling the [joinChannelByUserAccount]([AgoraRtcEngineKit joinChannelByUserAccount:token:channelId:joinSuccess:]) method and joining the channel is shorter than the latter. + +**Note:** + +- Ensure that you set the `userAccount` parameter. Otherwise, this method does not take effect. +- Ensure that the value of the `userAccount` parameter is unique in the channel. +- To ensure smooth communication, use the same parameter type to identify the user. For example, if a user joins the channel with a user ID, then ensure that all the other users use the user ID too. The same applies to the user account. If a user joins the channel with the Agora Web SDK, ensure that the `uid` of the user is set to the same parameter type. + +@param userAccount The user account. The maximum length of this parameter is 255 bytes. Ensure that you set this parameter and do not set it as `nil`. Supported character scopes are: + +- All lowercase English letters: a to z. +- All uppercase English letters: A to Z. +- All numeric characters: 0 to 9. +- The space character. +- Punctuation characters and other symbols, including: "!", "#", "$", "%", "&", "(", ")", "+", "-", ":", ";", "<", "=", ".", ">", "?", "@", "[", "]", "^", "_", "{", "}", "|", "~", ",". +@param appId The App ID of your project. + +@return * 0: Success. +* < 0: Failure. +*/ +- (int)registerLocalUserAccount:(NSString* _Nonnull)userAccount appId:(NSString* _Nonnull)appId; + +/** Gets the user information by passing in the user account. + +After a remote user joins the channel, the SDK gets the user ID and user account of the remote user, caches them in a mapping table object (`AgoraUserInfo`), and triggers the [didUpdatedUserInfo]([AgoraRtcEngineDelegate rtcEngine:didUpdatedUserInfo:withUid:]) callback on the local client. + +After receiving the [didUpdatedUserInfo]([AgoraRtcEngineDelegate rtcEngine:didUpdatedUserInfo:withUid:]) callback, you can call this method to get the user ID of the remote user from the `userInfo` object by passing in the user account. + +@param userAccount The user account of the user. Ensure that you set this parameter. +@param error The pointer to [AgoraErrorCode](AgoraErrorCode). It can be set as nil. + +@return An [AgoraUserInfo](AgoraUserInfo) object that contains the user account and user ID of the user. +*/ +- (AgoraUserInfo* _Nullable)getUserInfoByUserAccount:(NSString* _Nonnull)userAccount withError:(AgoraErrorCode* _Nullable)error; + +/** Gets the user information by passing in the user ID. + +After a user joins the channel, the SDK gets the user ID and user account of the remote user, caches them in a mapping table object (`AgoraUserInfo`), and triggers the [didUpdatedUserInfo]([AgoraRtcEngineDelegate rtcEngine:didUpdatedUserInfo:withUid:]) callback on the local client. + +After receiving the [didUpdatedUserInfo]([AgoraRtcEngineDelegate rtcEngine:didUpdatedUserInfo:withUid:]) callback, you can call this method to get the user account of the user from the `userInfo` object by passing in the user ID. + +@param uid The user ID of the user. Ensure that you set this parameter. +@param error The pointer to [AgoraErrorCode](AgoraErrorCode). It can be set as nil. + +@return An [AgoraUserInfo](AgoraUserInfo) object that contains the user account and user ID of the user. +*/ +- (AgoraUserInfo* _Nullable)getUserInfoByUid:(NSUInteger)uid withError:(AgoraErrorCode* _Nullable)error; + +/** Switches to a different channel. + + This method allows the audience of the interactive live streaming channel to switch to a different channel. + + After the user successfully switches to another channel, the [didLeaveChannelWithStats]([AgoraRtcEngineDelegate rtcEngine:didLeaveChannelWithStats:]) and [didJoinChannel]([AgoraRtcEngineDelegate rtcEngine:didJoinChannel:withUid:elapsed:]) callbacks are triggered to indicate that the user has left the original channel and joined a new one. + + Once the user switches to another channel, the user subscribes to the audio and video streams of all the other users in the channel by default, giving rise to usage and billing calculation. If you do not want to subscribe to a specified stream or all remote streams, call the `mute` methods accordingly. + + @param token The token generated at your server. See [Authenticate Your Users with Tokens](https://docs.agora.io/en/Interactive%20Broadcast/token_server?platform=All%20Platforms). + @param channelId Unique channel name for the Agora RTC session in the string format. The string length must be less than 64 bytes. Supported character scopes are: + + - All lowercase English letters: a to z. + - All uppercase English letters: A to Z. + - All numeric characters: 0 to 9. + - The space character. + - Punctuation characters and other symbols, including: "!", "#", "$", "%", "&", "(", ")", "+", "-", ":", ";", "<", "=", ".", ">", "?", "@", "[", "]", "^", "_", "{", "}", "|", "~", ",". + @param joinSuccessBlock Returns that the user joins the specified channel. Same as [didJoinChannel]([AgoraRtcEngineDelegate rtcEngine:didJoinChannel:withUid:elapsed:]). If `joinSuccessBlock` is nil, the SDK triggers the [didJoinChannel]([AgoraRtcEngineDelegate rtcEngine:didJoinChannel:withUid:elapsed:]) callback. + + @note This method applies to the audience role in the interactive live streaming channel only. + + @return - `0`(`AgoraErrorCodeNoError`): Success. +- < `0`: Failure. + + - `-1`(`AgoraErrorCodeFailed`): A general error occurs (no specified reason). + - `-2`(`AgoraErrorCodeInvalidArgument`): The parameter is invalid. + - `-5`(`AgoraErrorCodeRefused`): The request is rejected, probably because the user is not an audience. + - `-7`(`AgoraErrorCodeNotInitialized`): The SDK is not initialized. + - `-102`(`AgoraErrorCodeInvalidChannelId`): The channel ID is invalid. + - `-113`(`AgoraErrorCodeNotInChannel`): The user is not in the channel. + */ +- (int)switchChannelByToken:(NSString* _Nullable)token channelId:(NSString* _Nonnull)channelId joinSuccess:(void (^_Nullable)(NSString* _Nonnull channel, NSUInteger uid, NSInteger elapsed))joinSuccessBlock; + +/** Switches to a different channel, and configures whether to automatically + subscribe to audio or video streams in the target channel. + + @since v3.3.0 + + This method allows the audience of the interactive live streaming channel to + switch to a different channel. + + After the user successfully switches to another channel, the + [didLeaveChannelWithStats]([AgoraRtcEngineDelegate rtcEngine:didLeaveChannelWithStats:]) + and [didJoinChannel]([AgoraRtcEngineDelegate rtcEngine:didJoinChannel:withUid:elapsed:]) + callbacks are triggered to indicate that the user has left the original + channel and joined a new one. + + **Note** + + - This method applies to the audience role in the interactive live streaming + channel only. + - The difference between this method and [switchChannelByToken]([AgoraRtcEngineKit switchChannelByToken:channelId:joinSuccess:])1 + is that the former adds the `options` parameter to configure whether the end + user automatically subscribes to all remote audio and video streams in the + target channel. By default, the user subscribes to the audio and video streams + of all the other users in the target channel, thus incurring all associated + usage costs. To unsubscribe, set the `options` parameter or call the `mute` methods accordingly. + + @param token The token generated at your server. For details, see [Generate a token](https://docs.agora.io/en/Interactive%20Broadcast/token_server?platform=All%20Platforms). + @param channelId The unique channel name for the Agora RTC session in the string format. The string length must be less than 64 bytes. Supported character scopes are: + + - All lowercase English letters: a to z. + - All uppercase English letters: A to Z. + - All numeric characters: 0 to 9. + - The space character. + - Punctuation characters and other symbols, including: "!", "#", "$", "%", "&", "(", ")", "+", "-", ":", ";", "<", "=", ".", ">", "?", "@", "[", "]", "^", "_", "{", "}", "|", "~", ",". + @param options The channel media options: AgoraRtcChannelMediaOptions. + + @return - `0`(`AgoraErrorCodeNoError`): Success. +- < `0`: Failure. + + - `-1`(`AgoraErrorCodeFailed`): A general error occurs (no specified reason). + - `-2`(`AgoraErrorCodeInvalidArgument`): The parameter is invalid. + - `-5`(`AgoraErrorCodeRefused`): The request is rejected, probably because the user is not an audience. + - `-7`(`AgoraErrorCodeNotInitialized`): The SDK is not initialized. + - `-102`(`AgoraErrorCodeInvalidChannelId`): The channel ID is invalid. + - `-113`(`AgoraErrorCodeNotInChannel`): The user is not in the channel. + */ +- (int)switchChannelByToken:(NSString* _Nullable)token channelId:(NSString* _Nonnull)channelId options:(AgoraRtcChannelMediaOptions* _Nonnull)options; + +/** Allows a user to leave a channel, such as hanging up or exiting a call. + +After joining a channel, the user must call the leaveChannel method to end the call before joining another channel. + +This method returns 0 if the user leaves the channel and releases all resources related to the call. + +This method call is asynchronous, and the user has not exited the channel when the method call returns. + +A successful leaveChannel method call triggers the following callbacks: + +- The local client: [didLeaveChannelWithStats]([AgoraRtcEngineDelegate rtcEngine:didLeaveChannelWithStats:]) +- The remote client: [didOfflineOfUid(AgoraUserOfflineReasonBecomeAudience)]([AgoraRtcEngineDelegate rtcEngine:didOfflineOfUid:reason:]), if the user leaving the channel is in the Communication channel, or is a host in the Live Broadcast profile. + +**Note:** + +- If you call [destroy](destroy) immediately after leaveChannel, the leaveChannel process interrupts, and the SDK does not trigger the [didLeaveChannelWithStats]([AgoraRtcEngineDelegate rtcEngine:didLeaveChannelWithStats:]) callback. +- If you call this method during CDN live streaming, the SDK triggers the [removePublishStreamUrl](removePublishStreamUrl:) method. +- When you call this method, the SDK deactivates the audio session on iOS by default, and may affect other apps. If you do not want this default behavior, use [setAudioSessionOperationRestriction](setAudioSessionOperationRestriction:) to set `AgoraAudioSessionOperationRestrictionDeactivateSession` so that when you call the [leaveChannel]([AgoraRtcEngineKit leaveChannel:]) method, the SDK does not deactivate the audio session. + + @param leaveChannelBlock This callback indicates that a user leaves a channel, and provides the statistics of the call. See [AgoraChannelStats](AgoraChannelStats). + + @return - `0`(`AgoraErrorCodeNoError`): Success. +- < `0`: Failure. + + - `-1`(`AgoraErrorCodeFailed`): A general error occurs (no specified reason). + - `-2`(`AgoraErrorCodeInvalidArgument`): The parameter is invalid. + - `-7`(`AgoraErrorCodeNotInitialized`): The SDK is not initialized. + */ +- (int)leaveChannel:(void (^_Nullable)(AgoraChannelStats* _Nonnull stat))leaveChannelBlock; + +/** Gets a new token when the current token expires after a period of time. + +The `token` expires after a period of time once the token schema is enabled when: + + - The SDK triggers the [tokenPrivilegeWillExpire]([AgoraRtcEngineDelegate rtcEngine:tokenPrivilegeWillExpire:]) callback, or + - [connectionChangedToState]([AgoraRtcEngineDelegate rtcEngine:connectionChangedToState:reason:]) reports AgoraConnectionChangedTokenExpired(9) in the`reason` parameter. + + **Note:** + + Agora recommends using the [rtcEngineRequestToken]([AgoraRtcEngineDelegate rtcEngineRequestToken:]) callback to report the AgoraErrorCodeTokenExpired(-109) error, not using the [didOccurError]([AgoraRtcEngineDelegate rtcEngine:didOccurError:]) callback. + + The app should call this method to get the `token`. Failure to do so results in the SDK disconnecting from the server. + + @param token The new token. + + @return - `0`(`AgoraErrorCodeNoError`): Success. +- < `0`: Failure. + + - `-1`(`AgoraErrorCodeFailed`): A general error occurs (no specified reason). + - `-2`(`AgoraErrorCodeInvalidArgument`): The parameter is invalid. + - `-7`(`AgoraErrorCodeNotInitialized`): The SDK is not initialized. + */ +- (int)renewToken:(NSString* _Nonnull)token; + +/** Gets the connection state of the app. + + You can call this method either before or after joining a channel. + + @return The connection state, see [AgoraConnectionStateType](AgoraConnectionStateType). +*/ +- (AgoraConnectionStateType)getConnectionState; + +/** Starts to relay media streams across channels. + + After a successful method call, the SDK triggers the [channelMediaRelayStateDidChange]([AgoraRtcEngineDelegate rtcEngine:channelMediaRelayStateDidChange:error:]) and [didReceiveChannelMediaRelayEvent]([AgoraRtcEngineDelegate rtcEngine:didReceiveChannelMediaRelayEvent:]) callbacks, and these callbacks return the state and events of the media stream relay. + + - If the `channelMediaRelayStateDidChange` callback returns AgoraChannelMediaRelayStateRunning(2) and AgoraChannelMediaRelayStateIdle(0), and the `didReceiveChannelMediaRelayEvent` callback returns AgoraChannelMediaRelayEventSentToDestinationChannel(4), the SDK starts relaying media streams between the original and the destination channel. + - If the `channelMediaRelayStateDidChange` callback returns AgoraChannelMediaRelayStateFailure(3), an exception occurs during the media stream relay. + + **Note** + + - Call this method after the [joinChannel]([AgoraRtcEngineKit joinChannelByToken:channelId:info:uid:joinSuccess:]) method. + - This method takes effect only when you are a host in the interactive live streaming channel. + - After a successful method call, if you want to call this method again, ensure that you call the [stopChannelMediaRelay]([AgoraRtcEngineKit stopChannelMediaRelay]) method to quit the current relay. + - Contact support@agora.io before implementing this function. + - We do not support string user accounts in this API. + + @param config The configuration of the media stream relay: [AgoraChannelMediaRelayConfiguration](AgoraChannelMediaRelayConfiguration). + + @return - 0: Success. + - < 0: Failure. + */ +- (int)startChannelMediaRelay:(AgoraChannelMediaRelayConfiguration* _Nonnull)config; + +/** Updates the channels for media stream relay. + + After the channel media relay starts, if you want to relay the media stream to more channels, or leave the current relay channel, you can call the `updateChannelMediaRelay` method. + + After a successful method call, the SDK triggers the [didReceiveChannelMediaRelayEvent]([AgoraRtcEngineDelegate rtcEngine:didReceiveChannelMediaRelayEvent:]) callback with the AgoraChannelMediaRelayEventUpdateDestinationChannel(7) state code. + + **Note** + + - Call this method after successfully calling the + [startChannelMediaRelay]([AgoraRtcEngineKit startChannelMediaRelay:]) method + and receiving the [channelMediaRelayStateDidChange]([AgoraRtcChannelDelegate rtcChannel:channelMediaRelayStateDidChange:error:]) + `(AgoraChannelMediaRelayStateRunning, AgoraChannelMediaRelayErrorNone)` callback; + otherwise, this method call fails. + - This method supports adding at most four destination channels in the relay. If there are already four destination channels in the relay, remove the unnecessary ones with the `removeDestinationInfoForChannelName` method in channelMediaRelayConfiguration before calling this method. + + @param config The media stream relay configuration: [AgoraChannelMediaRelayConfiguration](AgoraChannelMediaRelayConfiguration). + + @return - 0: Success. + - < 0: Failure. + */ +- (int)updateChannelMediaRelay:(AgoraChannelMediaRelayConfiguration* _Nonnull)config; + +/** Pauses the media stream relay to all destination channels. + + @since v3.5.1 + + After the cross-channel media stream relay starts, you can call this method to + pause relaying media streams to all destination channels; after the pause, + if you want to resume the relay, call + [resumeAllChannelMediaRelay]([AgoraRtcEngineKit resumeAllChannelMediaRelay]). + + After a successful method call, the SDK triggers the + [didReceiveChannelMediaRelayEvent]([AgoraRtcEngineDelegate rtcEngine:didReceiveChannelMediaRelayEvent:]) + callback to report whether the media stream relay is successfully paused. + + @note Call this method after the + [startChannelMediaRelay]([AgoraRtcEngineKit startChannelMediaRelay:]) method. + + @return - 0: Success. + - < 0: Failure. + */ +- (int)pauseAllChannelMediaRelay; + +/** Resumes the media stream relay to all destination channels. + + @since v3.5.1 + + After calling the [pauseAllChannelMediaRelay]([AgoraRtcEngineKit pauseAllChannelMediaRelay]) + method, you can call this method to resume relaying media streams to all + destination channels. + + After a successful method call, the SDK triggers the + [didReceiveChannelMediaRelayEvent]([AgoraRtcEngineDelegate rtcEngine:didReceiveChannelMediaRelayEvent:]) + callback to report whether the media stream relay is successfully resumed. + + @note Call this method after the `pauseAllChannelMediaRelay` method. + + @return - 0: Success. + - < 0: Failure. + */ +- (int)resumeAllChannelMediaRelay; + +/** Stops the media stream relay. + + Once the relay stops, the host quits all the destination channels. + + After a successful method call, the SDK triggers the [channelMediaRelayStateDidChange]([AgoraRtcEngineDelegate rtcEngine:channelMediaRelayStateDidChange:error:]) callback. If the callback returns AgoraChannelMediaRelayStateIdle(0) and AgoraChannelMediaRelayErrorNone(0), the host successfully stops the relay. + + @note If the method call fails, the SDK triggers the [channelMediaRelayStateDidChange]([AgoraRtcEngineDelegate rtcEngine:channelMediaRelayStateDidChange:error:]) callback with the AgoraChannelMediaRelayErrorServerNoResponse(2) or AgoraChannelMediaRelayEventUpdateDestinationChannelRefused(8) state code. You can leave the channel by calling the [leaveChannel]([AgoraRtcEngineKit leaveChannel:]) method, and the media stream relay automatically stops. + + @return - 0: Success. + - < 0: Failure. + */ +- (int)stopChannelMediaRelay; + +/** Sets the Agora cloud proxy service. + + @since v3.3.0 + + When the user's firewall restricts the IP address and port, refer to + *Use Cloud Proxy* to add the specific IP addresses and ports to the firewall + whitelist; then, call this method to enable the cloud proxy and set the cloud + proxy type with the `proxyType` parameter as `AgoraUdpProxy(1)`, which is the + cloud proxy for the UDP protocol. + + After a successfully cloud proxy connection, the SDK triggers the + [connectionChangedToState(AgoraConnectionStateConnecting, AgoraConnectionChangedSettingProxyServer)]([AgoraRtcEngineDelegate rtcEngine:connectionChangedToState:reason:]) + callback. + + To disable the cloud proxy that has been set, call `setCloudProxy(AgoraNoneProxy)`. + To change the cloud proxy type that has been set, call `setCloudProxy(AgoraNoneProxy)` + first, and then call `setCloudProxy`, and pass the value that you expect in + `proxyType`. + + **Note** + + - Agora recommends that you call this method before joining the channel or + after leaving the channel. + - For the SDK v3.3.x, the services for pushing streams to CDN and co-hosting + across channels are not available when you use the cloud proxy for the UDP + protocol. For the SDK v3.4.0 and later, the services for pushing streams to + CDN and co-hosting across channels are not available when the user is in a + network environment with a firewall and uses the cloud proxy for the UDP protocol. + + @param proxyType The cloud proxy type, see AgoraCloudProxyType. This + parameter is required, and the SDK reports an error if you do not pass in a value. + + @return - 0: Success. +- < 0: Failure. + + - `-2(AgoraErrorCodeInvalidArgument)`: The parameter is invalid. + - `-7(AgoraErrorCodeNotInitialized)`: The SDK is not initialized. + */ +- (int)setCloudProxy:(AgoraCloudProxyType)proxyType; + +#pragma mark Core Audio + +/**----------------------------------------------------------------------------- + * @name Core Audio + * ----------------------------------------------------------------------------- + */ + +/** Enables the audio module. + + The audio module is enabled by default. + + **Note:** + +- This method affects the audio module and can be called after the [leaveChannel]([AgoraRtcEngineKit leaveChannel:]) method. You can call this method either before or after joining a channel. +- This method enables the audio module and takes some time to take effect. Agora recommends using the following API methods to control the audio engine modules separately: + + * [enableLocalAudio]([AgoraRtcEngineKit enableLocalAudio:]): Whether to enable the microphone to create the local audio stream. + * [muteLocalAudioStream]([AgoraRtcEngineKit muteLocalAudioStream:]): Whether to publish the local audio stream. + * [muteRemoteAudioStream]([AgoraRtcEngineKit muteRemoteAudioStream:mute:]): Whether to subscribe to and play the remote audio stream. + * [muteAllRemoteAudioStreams]([AgoraRtcEngineKit muteAllRemoteAudioStreams:]): Whether to subscribe to and play all remote audio streams. + + @return * 0: Success. +* < 0: Failure. + */ +- (int)enableAudio; + +/** Disables the audio module. + + **Note:** + +- This method affects the audio module and can be called after the [leaveChannel]([AgoraRtcEngineKit leaveChannel:]) method. You can call this method either before or after joining a channel. +- This method disables the audio module and takes some time to take effect. Agora recommends using the following API methods to control the audio engine modules separately: + + * [enableLocalAudio]([AgoraRtcEngineKit enableLocalAudio:]): Whether to enable the microphone to create the local audio stream. + * [muteLocalAudioStream]([AgoraRtcEngineKit muteLocalAudioStream:]): Whether to publish the local audio stream. + * [muteRemoteAudioStream]([AgoraRtcEngineKit muteRemoteAudioStream:mute:]): Whether to subscribe to and play the remote audio stream. + * [muteAllRemoteAudioStreams]([AgoraRtcEngineKit muteAllRemoteAudioStreams:]): Whether to subscribe to and play all remote audio streams. + + @return * 0: Success. +* < 0: Failure. + */ +- (int)disableAudio; + +/** Sets the audio parameters and application scenarios. + + **Note:** + + * You must call this method before the [joinChannelByToken]([AgoraRtcEngineKit joinChannelByToken:channelId:info:uid:joinSuccess:]) method. + * In the Communication profile, you can set the `profile` but not the `scenario`. + * In the Communication and interactive live streaming profiles, the bitrates may be different from your settings due to network self-adaptation. + * In scenarios requiring high-quality audio, we recommend setting `profile` as `AgoraAudioProfileMusicHighQuality(4)` and `scenario` as `AgoraAudioScenarioGameStreaming(3)`. For example, for music education scenarios. + + @param profile Sets the sample rate, bitrate, encoding mode, and the number of channels. See [AgoraAudioProfile](AgoraAudioProfile). + @param scenario Sets the audio application scenario. See [AgoraAudioScenario](AgoraAudioScenario). Under different audio scenarios, the device uses different volume types. For details, see [What is the difference between the in-call volume and the media volume?](https://docs.agora.io/en/faq/system_volume). + + @return * 0: Success. +* < 0: Failure. + */ +- (int)setAudioProfile:(AgoraAudioProfile)profile scenario:(AgoraAudioScenario)scenario; + +/** Adjusts the volume of the signal captured by the microphone. + + You can call this method either before or after joining a channel. + + @param volume The volume of the signal captured by the microphone. The value + ranges between 0 and 400, including the following: + + - 0: Mute. + - 100: (Default) Original volume. + - 400: Four times the original volume with signal-clipping protection. + + @return * 0: Success. +* < 0: Failure. + */ +- (int)adjustRecordingSignalVolume:(NSInteger)volume; + +/** Adjusts the volume of the signal captured by the sound card. (macOS only) + + @since v3.4.0 + + After calling [enableLoopbackRecording]([AgoraRtcEngineKit enableLoopbackRecording:deviceName:]) to enable loopback + audio capturing, you can call this method to adjust the volume of the signal captured by the sound card. + + @param volume The volume of the signal captured by the sound card. The value + ranges between 0 and 400, including the following: + + - 0: Mute. + - 100: (Default) Original volume. + - 400: Four times the original volume with signal-clipping protection. + + @return - 0: Success. + - < 0: Failure. + */ +- (int)adjustLoopbackRecordingSignalVolume:(NSInteger)volume; + +/** Adjusts the playback signal volume of all remote users. + + You can call this method either before or after joining a channel. + + **Note** + + - This method adjusts the playback volume which is mixed volume of all remote users. + - Since v2.3.2, to mute the local audio playback, call both `adjustPlaybackSignalVolume` and [adjustAudioMixingVolume]([AgoraRtcEngineKit adjustAudioMixingVolume:]), and set `volume` as 0. + + @param volume The playback volume. The value + ranges between 0 and 400, including the following: + + - 0: Mute. + - 100: (Default) Original volume. + - 400: Four times the original volume with signal-clipping protection. + + @return * 0: Success. + * < 0: Failure. + */ +- (int)adjustPlaybackSignalVolume:(NSInteger)volume; + +/** Enables the reporting of users' volume indication. + + This method enables the SDK to regularly report the volume information of the local user who sends a stream and remote users + (up to three) whose instantaneous volumes are the highest to the app. Once you call this method and users send streams in + the channel, the SDK triggers the + [reportAudioVolumeIndicationOfSpeakers]([AgoraRtcEngineDelegate rtcEngine:reportAudioVolumeIndicationOfSpeakers:totalVolume:]) + callback at the time interval set in this method. + + You can call this method either before or after joining a channel. + + @param interval Sets the time interval between two consecutive volume indications: + + * ≤ 0: Disables the volume indication. + * > 0: The time interval (ms) between two consecutive volume indications. Agora recommends setting `interval` ≥ 200 ms. + + @param smooth The smoothing factor sets the sensitivity of the audio volume indicator. The value ranges between 0 and 10. The greater the value, the more sensitive the indicator. The recommended value is 3. + @param report_vad - YES: Enable the voice activity detection of the local user. Once it is enabled, the `vad` parameter of the [reportAudioVolumeIndicationOfSpeakers]([AgoraRtcEngineDelegate rtcEngine:reportAudioVolumeIndicationOfSpeakers:totalVolume:]) callback reports the voice activity status of the local user. + - NO: (Default) Disable the voice activity detection of the local user. Once it is disabled, the `vad` parameter of the [reportAudioVolumeIndicationOfSpeakers]([AgoraRtcEngineDelegate rtcEngine:reportAudioVolumeIndicationOfSpeakers:totalVolume:]) callback does not report the voice activity status of the local user, except for the scenario where the engine automatically detects the voice activity of the local user. + + @return * 0: Success. +* < 0: Failure. + */ +- (int)enableAudioVolumeIndication:(NSInteger)interval smooth:(NSInteger)smooth report_vad:(BOOL)report_vad; + +/** Enables/Disables the local audio capture. + +When an app joins a channel, the audio module is enabled by default. This method disables or re-enables the local audio capture, that is, to stop or restart local audio capturing and processing. + +This method does not affect receiving the remote audio streams, and `enableLocalAudio(NO)` is applicable to scenarios where the user wants to receive remote audio streams without sending any audio stream to other users in the channel. + +Once the local audio function is disabled or re-enabled, the SDK triggers the [localAudioStateChange]([AgoraRtcEngineDelegate rtcEngine:localAudioStateChange:error:]) callback, which reports `AgoraAudioLocalStateStopped(0)` or `AgoraAudioLocalStateRecording(1)`. + +**Note:** + +- This method can be called either before or after you join a channel. Calling +it before you join a channel can set the device state only, and it takes effect +immediately after you join the channel. +- This method is different from the [muteLocalAudioStream]([AgoraRtcEngineKit muteLocalAudioStream:]) method: + + - [enableLocalAudio]([AgoraRtcEngineKit enableLocalAudio:]): Disables/Re-enables the local audio capturing and processing. If you disable or re-enable local audio sampling using the `enableLocalAudio` method, the local user may hear a pause in the remote audio playback. + - [muteLocalAudioStream]([AgoraRtcEngineKit muteLocalAudioStream:]): Sends/Stops sending the local audio stream. + + @param enabled * YES: (Default) Enable the local audio module, that is, to start local audio capturing and processing. + * NO: Disable the local audio module, that is, to stop local audio capturing and processing. + @return * 0: Success. +* < 0: Failure. + */ +- (int)enableLocalAudio:(BOOL)enabled; + +/** Stops or resumes publishing the local audio stream. + + As of v3.4.5, this method only sets the publishing status of the audio stream + in the channel of `AgoraRtcEngineKit`. + + A successful method call triggers the + [didAudioMuted]([AgoraRtcEngineDelegate rtcEngine:didAudioMuted:byUid:]) + callback on the remote client. + + You can only publish the local stream in one channel at a time. If you create + multiple channels, ensure that you only call `muteLocalAudioStream(NO)` in + one channel; otherwise, the method call fails, and the SDK returns + `-5 (AgoraErrorCodeRefused)`. + + **Note:** + + - This method does not change the usage status of the audio-capturing device. + - Whether this method call takes effect is affected by the + [joinChannelByToken]([AgoraRtcEngineKit joinChannelByToken:channelId:info:uid:options:]) + and [setClientRole]([AgoraRtcEngineKit setClientRole:]) methods. For details, + see *Set the Publishing State*. + + @param mute Sets whether to stop publishing the local audio stream. + + * YES: Stop publishing the local audio stream. + * NO: Resume publishing the local audio stream. + + @return * 0: Success. +* < 0: Failure. + + - `-5` (`AgoraErrorCodeRefused`): The request is rejected. + */ +- (int)muteLocalAudioStream:(BOOL)mute; + +/** Stops or resumes subscribing to the audio stream of a specified user. + + **Note:** + + - Call this method after joining a channel. + - See recommended settings in *Set the Subscribing State*. + + @param uid The user ID of the specified remote user. + @param mute Sets whether to stop subscribing to the audio stream of a + specified user. + + * YES: Stop subscribing to the audio stream of a specified user. + * NO: (Default) Resume subscribing to the audio stream of a specified user. + + @return * 0: Success. +* < 0: Failure. + */ +- (int)muteRemoteAudioStream:(NSUInteger)uid mute:(BOOL)mute; + +/** Stops or resumes subscribing to the audio streams of all remote users. + + After successfully calling this method, the local user stops or + resumes subscribing to the audio streams of all remote users, including all + subsequent users. + + **Note** + + - Call this method after joining a channel. + - As of v3.3.0, this method contains the function of + [setDefaultMuteAllRemoteAudioStreams]([AgoraRtcEngineKit setDefaultMuteAllRemoteAudioStreams:]). + Agora recommends not calling `muteAllRemoteAudioStreams` and + `setDefaultMuteAllRemoteAudioStreams` together; otherwise, the settings may + not take effect. See *Set the Subscribing State*. + + @param mute Sets whether to stop subscribing to the audio streams of all + remote users. + + * YES: Stop subscribing to the audio streams of all remote users. + * NO: (Default) Resume subscribing to the audio streams of all remote users. + + @return * 0: Success. +* < 0: Failure. + */ +- (int)muteAllRemoteAudioStreams:(BOOL)mute; + +/** Adjust the playback signal volume of a specified remote user. + + **Since** v3.0.0. + + You can call this method as many times as necessary to adjust the playback volume of different remote users, or to repeatedly adjust the playback volume of the same remote user. + + **Note** + + - Call this method after joining a channel. + - The playback volume here refers to the mixed volume of a specified remote user. + - This method can only adjust the playback volume of one specified remote user at a time. To adjust the playback volume of different remote users, call the method as many times, once for each remote user. + + @param uid The ID of the remote user. + @param volume The playback volume of the specified remote user. The value + ranges between 0 and 400, including the following: + + - 0: Mute. + - 100: (Default) Original volume. + - 400: Four times the original volume with signal-clipping protection. + + @return - 0: Success. + - < 0: Failure. + */ +- (int)adjustUserPlaybackSignalVolume:(NSUInteger)uid volume:(int)volume; + +#pragma mark Core Video + +/**----------------------------------------------------------------------------- + * @name Core Video + * ----------------------------------------------------------------------------- + */ + +/** Enables the video module. + +You can call this method either before entering a channel or during a call. If you call this method before entering a channel, the service starts in the video mode. If you call this method during an audio call, the audio mode switches to the video mode. + +A successful enableVideo method call triggers the [didVideoEnabled(YES)]([AgoraRtcEngineDelegate rtcEngine:didVideoEnabled:byUid:]) callback on the remote client. + + +To disable the video, call the disableVideo method. + +**Note:** + +- This method affects the internal engine and can be called after the [leaveChannel]([AgoraRtcEngineKit leaveChannel:]) method. +- This method resets the internal engine and takes some time to take effect. Agora recommends using the following API methods to control the video engine modules separately: + + * [enableLocalVideo]([AgoraRtcEngineKit enableLocalVideo:]): Whether to enable the camera to create the local video stream. + * [muteLocalVideoStream]([AgoraRtcEngineKit muteLocalVideoStream:]): Whether to publish the local video stream. + * [muteRemoteVideoStream]([AgoraRtcEngineKit muteRemoteVideoStream:mute:]): Whether to subscribe to and play the remote video stream. + * [muteAllRemoteVideoStreams]([AgoraRtcEngineKit muteAllRemoteVideoStreams:]): Whether to subscribe to and play all remote video streams. + + @return * 0: Success. +* < 0: Failure. + */ +- (int)enableVideo; + +/** Disables the video module. + + You can call this method before entering a channel or during a call. If you call this method before entering a channel, the service starts in the audio mode. If you call this method during a video call, the video mode switches to the audio mode. To enable the video module, call the [enableVideo]([AgoraRtcEngineKit enableVideo]) method. + + A successful disableVideo method call triggers the [didVideoEnabled(NO)]([AgoraRtcEngineDelegate rtcEngine:didVideoEnabled:byUid:]) callback on the remote client. + + **Note:** + +- This method affects the internal engine and can be called after the [leaveChannel]([AgoraRtcEngineKit leaveChannel:]) method. +- This method resets the internal engine and takes some time to take effect. Agora recommends using the following API methods to control the video engine modules separately: + + * [enableLocalVideo]([AgoraRtcEngineKit enableLocalVideo:]): Whether to enable the camera to create the local video stream. + * [muteLocalVideoStream]([AgoraRtcEngineKit muteLocalVideoStream:]): Whether to publish the local video stream. + * [muteRemoteVideoStream]([AgoraRtcEngineKit muteRemoteVideoStream:mute:]): Whether to subscribe to and play the remote video stream. + * [muteAllRemoteVideoStreams]([AgoraRtcEngineKit muteAllRemoteVideoStreams:]): Whether to subscribe to and play all remote video streams. + + @return * 0: Success. +* < 0: Failure. + */ +- (int)disableVideo; + +/** Sets the video encoder configuration. + + Each video encoder configuration corresponds to a set of video parameters, including the resolution, frame rate, bitrate, and video orientation. + + The parameters specified in this method are the maximum values under ideal network conditions. If the video engine cannot render the video using the specified parameters due to unreliable network conditions, the parameters further down the list are considered until a successful configuration is found. + + If you do not need to set the video encoder configuration after joining a channel, you can call this method before calling the enableVideo method to reduce the render time of the first video frame. + + You can call this method either before or after joining a channel. + + **Note:** + + From v2.3.0, the following API methods are deprecated: + + - [setVideoProfile](setVideoProfile:swapWidthAndHeight:) + - [setVideoResolution](setVideoResolution:andFrameRate:bitrate:) + + @param config Video encoder configuration: AgoraVideoEncoderConfiguration + @return * 0: Success. +* < 0: Failure. + */ +- (int)setVideoEncoderConfiguration:(AgoraVideoEncoderConfiguration* _Nonnull)config; + +/** Initializes the local video view. + + This method initializes the video view of the local stream on the local device. It affects only the video view that the local user sees, not the published local video stream. + + Call this method to bind the local video stream to a video view and to set the rendering and mirror modes of the video view. To unbind the `view`, set the `view` in AgoraRtcVideoCanvas to `nil`. + + You can call this method either before or after joining a channel. + + **Note** + + To update the rendering or mirror mode of the local video view during a call, use [setLocalRenderMode]([AgoraRtcEngineKit setLocalRenderMode:mirrorMode:]). + + @param local Sets the local video view and settings. See AgoraRtcVideoCanvas. + + @return * 0: Success. +* < 0: Failure. + */ +- (int)setupLocalVideo:(AgoraRtcVideoCanvas* _Nullable)local; + +/** Initializes the video view of a remote user. + + This method initializes the video view of a remote stream on the local device. It affects only the video view that the local user sees. + + Call this method to bind the remote video stream to a video view and to set the rendering and mirror modes of the video view. + + The app specifies the `uid` of the remote video in this method call before the user joins a channel. + + If the remote `uid` is unknown to the app, set it after the app receives the [userJoinedBlock]([AgoraRtcEngineKit userJoinedBlock:]) callback. + + If the Video Recording function is enabled, the Video Recording Service joins the channel as a dummy client, causing other clients to also receive the [didJoinedOfUid]([AgoraRtcEngineDelegate rtcEngine:didJoinedOfUid:elapsed:]) callback. Do not bind the dummy client to the app view because the dummy client does not send any video streams. If your app does not recognize the dummy client, bind the remote user to the view when the SDK triggers the [firstRemoteVideoDecodedOfUid]([AgoraRtcEngineDelegate rtcEngine:firstRemoteVideoDecodedOfUid:size:elapsed:]) callback. + + To unbind the remote user from the view, set the `view` in AgoraRtcVideoCanvas as nil. Once the remote user leaves the channel, the SDK unbinds the remote user. + + @note To update the rendering or mirror mode of the remote video view during a call, use [setRemoteRenderMode]([AgoraRtcEngineKit setRemoteRenderMode:renderMode:mirrorMode:]). + + @param remote Sets the remote video view and settings. See AgoraRtcVideoCanvas. + + @return * 0: Success. +* < 0: Failure. + */ +- (int)setupRemoteVideo:(AgoraRtcVideoCanvas* _Nonnull)remote; + +/** Updates the display mode of the local video view. + + **Since** v3.0.0. + + After initializing the local video view, you can call this method to update its rendering and mirror modes. It affects only the video view that the local user sees, not the published local video stream. + + **Note** + + - Ensure that you have called [setupLocalVideo]([AgoraRtcEngineKit setupLocalVideo:]) to initialize the local video view before calling this method. + - During a call, you can call this method as many times as necessary to update the display mode of the local video view. + + @param renderMode The rendering mode of the local video view. See [AgoraVideoRenderMode](AgoraVideoRenderMode). + @param mirrorMode The mirror mode of the local video view. See [AgoraVideoMirrorMode](AgoraVideoMirrorMode). + + **Note** + + If you use a front camera, the SDK enables the mirror mode by default; if you use a rear camera, the SDK disables the mirror mode by default. + + @return * 0: Success. + * < 0: Failure. + */ +- (int)setLocalRenderMode:(AgoraVideoRenderMode)renderMode mirrorMode:(AgoraVideoMirrorMode)mirrorMode; + +/** Updates the display mode of the video view of a remote user. + + **Since** v3.0.0. + + After initializing the video view of a remote user, you can call this method to update its rendering and mirror modes. This method affects only the video view that the local user sees. + + **Note** + + - Ensure that you have called [setupRemoteVideo]([AgoraRtcEngineKit setupRemoteVideo:]) to initialize the remote video view before calling this method. + - During a call, you can call this method as many times as necessary to update the display mode of the video view of a remote user. + + @param uid The ID of the remote user. + @param renderMode The rendering mode of the remote video view. See [AgoraVideoRenderMode](AgoraVideoRenderMode). + @param mirrorMode The mirror mode of the remote video view. See [AgoraVideoMirrorMode](AgoraVideoMirrorMode). + + **Note** + + The SDK disables the mirror mode by default. + + @return * 0: Success. + * < 0: Failure. + */ +- (int)setRemoteRenderMode:(NSUInteger)uid renderMode:(AgoraVideoRenderMode)renderMode mirrorMode:(AgoraVideoMirrorMode)mirrorMode; + +/** Starts the local video preview before joining a channel. + +By default, the local preview enables the mirror mode. + +Before calling this method, you must: + + - Call the [setupLocalVideo]([AgoraRtcEngineKit setupLocalVideo:]) method to set up the local preview window and configure the attributes. + - Call the [enableVideo]([AgoraRtcEngineKit enableVideo]) method to enable video. + +**Note:** + + Once you call this method to start the local video preview, if you leave the channel by calling the [leaveChannel]([AgoraRtcEngineKit leaveChannel:]) method, the local video preview remains until you call the stopPreview method to disable it. + + @return * 0: Success. +* < 0: Failure. + */ +- (int)startPreview; + +/** Stops the local video preview. + + After calling [startPreview]([AgoraRtcEngineKit startPreview]), if you want to + stop the local video preview, call `stopPreview`. + + @note Call this method before you join the channel or after you leave the channel. + + @return * 0: Success. +* < 0: Failure. + */ +- (int)stopPreview; + +/** Disables the local video. + + This method disables or re-enables the local video capturer, and does not affect receiving the remote video stream. + + After you call the [enableVideo]([AgoraRtcEngineKit enableVideo]) method, the local video capturer is enabled by default. You can call [enableLocalVideo(NO)]([AgoraRtcEngineKit enableLocalVideo:]) to disable the local video capturer. If you want to re-enable it, call [enableLocalVideo(YES)]([AgoraRtcEngineKit enableLocalVideo:]). + + After the local video capturer is successfully disabled or re-enabled, the SDK triggers the [remoteVideoStateChangedOfUid]([AgoraRtcEngineDelegate rtcEngine:remoteVideoStateChangedOfUid:state:reason:elapsed:]) callback on the remote client. + + You can call this method either before or after joining a channel. + + **Note:** + + This method enables the internal engine and can be called after calling the [leaveChannel]([AgoraRtcEngineKit leaveChannel:]) method. + + @param enabled Sets whether to enable/disable the local video, including the capturer, renderer, and sender: + + * YES: (Default) Enable the local video. + * NO: Disable the local video. Once the local video is disabled, the remote users can no longer receive the video stream of this user, while this user can still receive the video streams of other remote users. + + @return * 0: Success. +* < 0: Failure. + */ +- (int)enableLocalVideo:(BOOL)enabled; + +/** Stops or resumes publishing the local video stream. + + As of v3.4.5, this method only sets the publishing state of the video stream + in the channel of `AgoraRtcEngineKit`. + + A successful method call triggers the + [didVideoMuted]([AgoraRtcEngineDelegate rtcEngine:didVideoMuted:byUid:]) + callback on the remote client. + + You can only publish the local stream in one channel at a time. If you create + multiple channels, ensure that you only call `muteLocalVideoStream(NO)` in + one channel; otherwise, the method call fails, and the SDK returns + `-5 (AgoraErrorCodeRefused)`. + + **Note:** + + - This method does not change the usage state of the video-capturing device. + - Whether this method call takes effect is affected by the + [joinChannelByToken]([AgoraRtcEngineKit joinChannelByToken:channelId:info:uid:options:]) + and [setClientRole]([AgoraRtcEngineKit setClientRole:]) methods. For details, + see *Set the Publishing State*. + + @param mute Sets whether to stop publishing the local video stream. + + * YES: Stop publishing the local video stream. + * NO: Resume publishing the local video stream. + + @return * 0: Success. +* < 0: Failure. + + - `-5` (`AgoraErrorCodeRefused`): The request is rejected. + */ +- (int)muteLocalVideoStream:(BOOL)mute; + +/** Stops or resumes subscribing to the video streams of all remote users. + + After successfully calling this method, the local user stops or + resumes subscribing to the video streams of all remote users, including all + subsequent users. + + **Note** + + - Call this method after joining a channel. + - As of v3.3.0, this method contains the function of + [setDefaultMuteAllRemoteAudioStreams]([AgoraRtcEngineKit setDefaultMuteAllRemoteAudioStreams:]). + Agora recommends not calling `muteAllRemoteAudioStreams` and + `setDefaultMuteAllRemoteAudioStreams` together; otherwise, the settings may + not take effect. See *Set the Subscribing State*. + + @param mute Sets whether to stop subscribing to the video streams of all + remote users. + + * YES: Stop subscribing to the video streams of all remote users. + * NO: (Default) Resume subscribing to the video streams of all remote users. + + @return * 0: Success. +* < 0: Failure. + */ +- (int)muteAllRemoteVideoStreams:(BOOL)mute; + +/** Stops or resumes subscribing to the video stream of a specified user. + + **Note:** + + - Call this method after joining a channel. + - See recommended settings in *Set the Subscribing State*. + + @param uid The user ID of the specified remote user. + @param mute Sets whether to stop subscribing to the video stream of a + specified user. + + * YES: Stop subscribing to the video stream of a specified user. + * NO: (Default) Resume subscribing to the video stream of a specified user. + + @return * 0: Success. +* < 0: Failure. + */ +- (int)muteRemoteVideoStream:(NSUInteger)uid mute:(BOOL)mute; + +#pragma mark Video Pre-Process and Post-Process +/**----------------------------------------------------------------------------- + * @name Video Pre-Process and Post-Process + * ----------------------------------------------------------------------------- + */ + +/** Enables/Disables image enhancement and sets the options. + +@note Call this method after calling the [enableVideo]([AgoraRtcEngineKit enableVideo]) method. + +@param enable Sets whether to enable image enhancement: + +- `YES`: Enable image enhancement. +- `NO`: Disable image enhancement. +@param options The image enhancement options, see AgoraBeautyOptions. + +@return * 0: Success. +* < 0: Failure. +*/ +- (int)setBeautyEffectOptions:(BOOL)enable options:(AgoraBeautyOptions* _Nullable)options; + +/** Enables/Disables the virtual background. (beta feature) + + @since Support for macOS as of v3.4.5 and iOS as of v3.5.0. + + After enabling the virtual background feature, you can replace the original + background image of the local user with a custom background image. After the + replacement, all users in the channel can see the custom background image. You + can find out from the [virtualBackgroundSourceEnabled]([AgoraRtcEngineDelegate rtcEngine:virtualBackgroundSourceEnabled:reason:]) + callback whether the virtual background is successfully enabled or the cause + of any errors. + + **Note**: + + - Before calling this method, ensure that you have integrated the + `AgoraVideoSegmentationExtension.framework` (macOS) or + `AgoraVideoSegmentationExtension.xcframework`(iOS) dynamic library into + the project folder. + - Call this method after [enableVideo]([AgoraRtcEngineKit enableVideo]). + - The virtual background feature does not support video in the Texture + format or video obtained from custom video capture by the Push method. + - This feature requires a high-performance device. Agora recommends that + you use this feature on the following devices: + + - macOS: Devices with an i5 CPU and better + - iOS: Devices with an A9 chip and better, as follows: + + - iPhone 6S and later + - iPad Air (3rd generation) and later + - iPad (5th generation) and later + - iPad Pro (1st generation) and later + - iPad mini (5th generation) and later + + @param enable Sets whether to enable the virtual background: + + - `YES`: Enable. + - `NO`: Disable. + @param backData The custom background image. See AgoraVirtualBackgroundSource. +

        Note: To adapt the resolution of the custom background image to the + resolution of the SDK capturing video, the SDK scales and crops the custom + background image while ensuring that the content of the custom background + image is not distorted.

        + + @return * 0: Success. +* < 0: Failure. + */ +- (int)enableVirtualBackground:(BOOL)enable backData:(AgoraVirtualBackgroundSource* _Nullable)backData; + +#if defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE +/** Enables/Disables the super resolution feature for a remote user's video. (beta feature) + + @since v3.5.1 + + This feature effectively boosts the resolution of a remote user's video seen + by the local user. If the original resolution of a remote user's video is a × b, + the local user's device can render the remote video at a resolution of 2a × 2b + after you enable this feature. + + After calling this method, the SDK triggers the + [superResolutionEnabledOfUid]([AgoraRtcEngineDelegate rtcEngine:superResolutionEnabledOfUid:enabled:reason:]) + callback to report whether you have successfully enabled super resolution. + + **Warnings** + + The super resolution feature requires extra system resources. To balance the + visual experience and system consumption, the SDK poses the following restrictions: + + - This feature can only be enabled for a single remote user. + - The original resolution of the remote user's video cannot exceed 640 × 480 pixels. + + If you exceed these limitations, the SDK triggers the + [didOccurWarning]([AgoraRtcEngineDelegate rtcEngine:didOccurWarning:]) + callback and returns the corresponding warning codes: + + - `AgoraWarningCodeSuperResolutionStreamOverLimitation(1610)`: + The original resolution of the remote user's video is beyond the range where + super resolution can be applied. + - `AgoraWarningCodeSuperResolutionUserCountOverLimitation(1611)`: Super + resolution is already being used to boost another remote user's video. + - `AgoraWarningCodeSuperResolutionDeviceNotSupported(1612)`: The device does + not support using super resolution. + + **Notes** + + - This method is for iOS only. + - Before calling this method, ensure that you have integrated the + `AgoraSuperResolutionExtension.xcframework` dynamic library into your project. + - Because this method has certain system performance requirements, Agora + recommends that you use the following iOS devices (iOS 12.0 or later) or better: + + - iPhone XR + - iPhone XS + - iPhone XS Max + - iPhone 11 + - iPhone 11 Pro + - iPhone 11 Pro Max + - iPhone 12 + - iPhone 12 mini + - iPhone 12 Pro + - iPhone 12 Pro Max + - iPhone 12 SE (2nd generation) + - iPad Pro 11-inch (3rd generation) + - iPad Pro 12.9-inch (3rd generation) + - iPad Air (3rd generation) + - iPad Air (4th generation) + + @param uid The user ID of the remote user. + @param enabled Determines whether to enable super resolution for the remote user's video: + + - `YES`: Enable super-resolution. + - `NO`: Do not enable super resolution. + + @return - 0: Success. + - < 0: Failure. + + - -157(`AgoraErrorCodeModuleNotFound`): The dynamic library for super resolution is not integrated. + */ +- (int)enableRemoteSuperResolution:(NSUInteger)uid enabled:(BOOL)enabled; +#endif + +/**----------------------------------------------------------------------------- + * @name Face Detection + * ----------------------------------------------------------------------------- + */ + +/** Enables/Disables face detection for the local user. (iOS only) + + **Since:** v3.0.1. + + Once face detection is enabled, the SDK triggers the [facePositionDidChangeWidth]([AgoraRtcEngineDelegate rtcEngine:facePositionDidChangeWidth:previewHeight:faces:]) callback to report the face information of the local user, which includes the following aspects: + + - The width and height of the local video. + - The position of the human face in the local video. + - The distance between the human face and the device screen. + + You can call this method either before or after joining a channel. + + @param enable Determines whether to enable the face detection function for the local user: + + - YES: Enable face detection. + - NO: Disable face detection. + + @return - 0: Success. + - < 0: Failure. + */ +- (int)enableFaceDetection:(bool)enable; + +#pragma mark Audio Routing Controller + +/**----------------------------------------------------------------------------- + * @name Audio Routing Controller + * ----------------------------------------------------------------------------- + */ + +#if defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE +/** Sets the default audio route. + + If the default audio route of the SDK (see *Set the Audio Route*) cannot meet + your requirements, you can call this method to switch the default audio route. + After successfully switching the audio route, the SDK triggers the + [didAudioRouteChanged]([AgoraRtcEngineDelegate rtcEngine:didAudioRouteChanged:]) + callback to indicate the changes. + + **Note** + + - This method applies to iOS only. + - Call this method before calling + [joinChannelByToken]([AgoraRtcEngineKit joinChannelByToken:channelId:info:uid:options:]). + If you need to switch the audio route after joining a channel, call + [setEnableSpeakerphone]([AgoraRtcEngineKit setEnableSpeakerphone:]). + - If the user uses an external audio playback device such as a Bluetooth or + wired headset, this method does not take effect, and the SDK plays audio + through the external device. When the user uses multiple external devices, + the SDK plays audio through the last connected device. + + @param defaultToSpeaker Sets the default audio route as follows: + + - `YES`: Set to the speakerphone. + - `NO`: Set to the earpiece. + + @return - 0: Success. + - < 0: Failure. + */ +- (int)setDefaultAudioRouteToSpeakerphone:(BOOL)defaultToSpeaker; + +/** Enables/Disables the audio route to the speakerphone. + + If the default audio route of the SDK (see *Set the Audio Route*) or the + setting in + [setDefaultAudioRouteToSpeakerphone]([AgoraRtcEngineKit setDefaultAudioRouteToSpeakerphone:]) + cannot meet your requirements, you can call this method to switch the current + audio route. After successfully switching the audio route, the SDK triggers + the + [didAudioRouteChanged]([AgoraRtcEngineDelegate rtcEngine:didAudioRouteChanged:]) + callback to indicate the changes. + + This method only sets the audio route in the current channel and does not + influence the default audio route. If the user leaves the current channel and + joins another channel, the default audio route is used. + + **Notes** + + - This method applies to iOS only. + - Call this method after calling + [joinChannelByToken]([AgoraRtcEngineKit joinChannelByToken:channelId:info:uid:options:]). + - If the user uses an external audio playback device such as a Bluetooth or + wired headset, this method does not take effect, and the SDK plays audio + through the external device. When the user uses multiple external devices, + the SDK plays audio through the last connected device. + + @param enableSpeaker Sets whether to enable the speakerphone or earpiece: + + - `YES`: Enable the speakerphone. The audio route is the speakerphone. + - `NO`: Disable the speakerphone. The audio route is the earpiece. + + @return * 0: Success. + * < 0: Failure. + */ +- (int)setEnableSpeakerphone:(BOOL)enableSpeaker; + +/** Checks whether the speakerphone is enabled. (iOS only.) + + You can call this method either before or after joining a channel. + + @return * YES: The speakerphone is enabled, and the audio plays from the speakerphone. + * NO: The speakerphone is not enabled, and the audio plays from devices other than the speakerphone. For example, the headset or earpiece. + */ +- (BOOL)isSpeakerphoneEnabled; +#endif + +#pragma mark In Ear Monitor + +/**----------------------------------------------------------------------------- + * @name In-ear Monitor + * ----------------------------------------------------------------------------- + */ + +#if defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE + +/** Enables in-ear monitoring. (iOS only.) + + You can call this method either before or after joining a channel. + + @note Users must use wired earphones to hear their own voices. + + @param enabled Sets whether to enable/disable in-ear monitoring. + + * YES: Enable. + * NO: (Default) Disable. + + @return * 0: Success. +* < 0: Failure. + */ +- (int)enableInEarMonitoring:(BOOL)enabled; + +/** Sets the volume of the in-ear monitor. (iOS only.) + + You can call this method either before or after joining a channel. + + @note Users must use wired earphones to hear their own voices. + + @param volume Sets the volume of the in-ear monitor. The value ranges between 0 and 100 (default). + + @return * 0: Success. +* < 0: Failure. + */ +- (int)setInEarMonitoringVolume:(NSInteger)volume; +#endif + +#pragma mark Audio Sound Effect + +/**----------------------------------------------------------------------------- + * @name Set the Voice Effect + * ----------------------------------------------------------------------------- + */ + +/** Changes the voice pitch of the local speaker. + + You can call this method either before or after joining a channel. + + @param pitch Sets the voice pitch. The value ranges between 0.5 and 2.0. The lower the value, the lower the voice pitch. The default value is 1.0 (no change to the local voice pitch). + + @return * 0: Success. +* < 0: Failure. + */ +- (int)setLocalVoicePitch:(double)pitch; + +/** Sets the local voice equalization effect. + + You can call this method either before or after joining a channel. + + @param bandFrequency Sets the band frequency. The value ranges between 0 and 9, representing the respective 10-band center frequencies of the voice effects, including 31, 62, 125, 250, 500, 1k, 2k, 4k, 8k, and 16k Hz. See AgoraAudioEqualizationBandFrequency. + @param gain Sets the gain of each band (dB). The value ranges between -15 and 15. The default value is 0. + + @return * 0: Success. +* < 0: Failure. +*/ +- (int)setLocalVoiceEqualizationOfBandFrequency:(AgoraAudioEqualizationBandFrequency)bandFrequency withGain:(NSInteger)gain; + +/** Sets the local voice reverberation. + + As of v3.2.0, the SDK provides a more convenient method [setAudioEffectPreset]([AgoraRtcEngineKit setAudioEffectPreset:]), + which directly implements the popular music, R&B music, KTV and other preset reverb effects. + + You can call this method either before or after joining a channel. + + @param reverbType Sets the reverberation type. See AgoraAudioReverbType. + @param value Sets the effect of the reverberation type. See AgoraAudioReverbType for the value range. + + @return * 0: Success. +* < 0: Failure. + */ +- (int)setLocalVoiceReverbOfType:(AgoraAudioReverbType)reverbType withValue:(NSInteger)value; + +/** Sets an SDK preset voice beautifier effect. + + @since v3.2.0 + + Call this method to set an SDK preset voice beautifier effect for the local user who sends an audio stream. After setting a voice + beautifier effect, all users in the channel can hear the effect. + + You can set different voice beautifier effects for different scenarios. See *Set the Voice Effect*. + + To achieve better audio effect quality, Agora recommends calling [setAudioProfile]([AgoraRtcEngineKit setAudioProfile:scenario:]) and + setting the `scenario` parameter to `AgoraAudioScenarioGameStreaming(3)` and the `profile` parameter to + `AgoraAudioProfileMusicHighQuality(4)` or `AgoraAudioProfileMusicHighQualityStereo(5)` before calling this method. + + **Note** + + - You can call this method either before or after joining a channel. + - Do not set the `profile` parameter of `setAudioProfile` to `AgoraAudioProfileSpeechStandard(1)`; otherwise, this method call does not take effect. + - This method works best with the human voice. Agora does not recommend using this method for audio containing music. + - After calling this method, Agora recommends not calling the following methods, because they can override `setVoiceBeautifierPreset`: + + - [setAudioEffectPreset]([AgoraRtcEngineKit setAudioEffectPreset:]) + - [setAudioEffectParameters]([AgoraRtcEngineKit setAudioEffectParameters:param1:param2:]) + - [setVoiceBeautifierParameters]([AgoraRtcEngineKit setVoiceBeautifierParameters:param1:param2:]) + - [setVoiceConversionPreset]([AgoraRtcEngineKit setVoiceConversionPreset:]) + - [setLocalVoiceReverbPreset]([AgoraRtcEngineKit setLocalVoiceReverbPreset:]) + - [setLocalVoiceChanger]([AgoraRtcEngineKit setLocalVoiceChanger:]) + - [setLocalVoicePitch]([AgoraRtcEngineKit setLocalVoicePitch:]) + - [setLocalVoiceEqualizationOfBandFrequency]([AgoraRtcEngineKit setLocalVoiceEqualizationOfBandFrequency:withGain:]) + - [setLocalVoiceReverbOfType]([AgoraRtcEngineKit setLocalVoiceReverbOfType:withValue:]) + + @param preset The options for SDK preset voice beautifier effects: [AgoraVoiceBeautifierPreset](AgoraVoiceBeautifierPreset). + + @return - 0: Success. +- < 0: Failure. + */ +- (int)setVoiceBeautifierPreset:(AgoraVoiceBeautifierPreset)preset; + +/** Sets parameters for SDK preset voice beautifier effects. + + @since v3.3.0 + + Call this method to set a gender characteristic and a reverberation effect + for the singing beautifier effect. This method sets parameters for the local + user who sends an audio stream. + + After you call this method successfully, all users in the channel can hear + the relevant effect. + + To achieve better audio effect quality, before you call this method, Agora + recommends calling [setAudioProfile]([AgoraRtcEngineKit setAudioProfile:scenario:]), and + setting the `scenario` parameter to `AgoraAudioScenarioGameStreaming(3)` and + the `profile` parameter to `AgoraAudioProfileMusicHighQuality(4)` or + `AgoraAudioProfileMusicHighQualityStereo(5)`. + + **Note** + + - You can call this method either before or after joining a channel. + - Do not set the `profile` parameter of `setAudioProfile` to + `AgoraAudioProfileSpeechStandard(1)`; otherwise, this method call does not + take effect. + - This method works best with the human voice. Agora does not recommend using + this method for audio containing music. + - After calling this method, Agora recommends not calling the following + methods, because they can override `setVoiceBeautifierParameters`: + + - [setAudioEffectPreset]([AgoraRtcEngineKit setAudioEffectPreset:]) + - [setAudioEffectParameters]([AgoraRtcEngineKit setAudioEffectParameters:param1:param2:]) + - [setVoiceBeautifierPreset]([AgoraRtcEngineKit setVoiceBeautifierPreset:]) + - [setVoiceConversionPreset]([AgoraRtcEngineKit setVoiceConversionPreset:]) + - [setLocalVoiceReverbPreset]([AgoraRtcEngineKit setLocalVoiceReverbPreset:]) + - [setLocalVoiceChanger]([AgoraRtcEngineKit setLocalVoiceChanger:]) + - [setLocalVoicePitch]([AgoraRtcEngineKit setLocalVoicePitch:]) + - [setLocalVoiceEqualizationOfBandFrequency]([AgoraRtcEngineKit setLocalVoiceEqualizationOfBandFrequency:withGain:]) + - [setLocalVoiceReverbOfType]([AgoraRtcEngineKit setLocalVoiceReverbOfType:withValue:]) + + @param preset The options for SDK preset voice beautifier effects: + + - `AgoraSingingBeautifier`: Singing beautifier effect. + @param param1 The gender characteristics options for the singing voice: + + - `1`: A male-sounding voice. + - `2`: A female-sounding voice. + @param param2 The reverberation effects options: + + - `1`: The reverberation effect sounds like singing in a small room. + - `2`: The reverberation effect sounds like singing in a large room. + - `3`: The reverberation effect sounds like singing in a hall. + + @return - 0: Success. +- < 0: Failure. + */ +- (int)setVoiceBeautifierParameters:(AgoraVoiceBeautifierPreset)preset param1:(int)param1 param2:(int)param2; + +/** Sets an SDK preset audio effect. + + @since v3.2.0 + + Call this method to set an SDK preset audio effect for the local user who sends an audio stream. This audio effect does not change the + gender characteristics of the original voice. After setting an audio effect, all users in the channel can hear the effect. + + You can set different audio effects for different scenarios. See *Set the Voice Effect*. + + To achieve better audio effect quality, Agora recommends calling [setAudioProfile]([AgoraRtcEngineKit setAudioProfile:scenario:]) + and setting the `scenario` parameter to `AgoraAudioScenarioGameStreaming(3)` before calling this method. + + **Note**: + + - You can call this method either before or after joining a channel. + - Do not set the `profile` parameter of `setAudioProfile` to `AgoraAudioProfileSpeechStandard(1)`; otherwise, this method call does not take effect. + - This method works best with the human voice. Agora does not recommend using this method for audio containing music. + - If you call this method and set the preset parameter to enumerators except `AgoraRoomAcoustics3DVoice` or `AgoraPitchCorrection`, + do not call [setAudioEffectParameters]([AgoraRtcEngineKit setAudioEffectParameters:param1:param2:]); otherwise, + `setAudioEffectParameters` overrides this method. + - After calling this method, Agora recommends not calling the following methods, because they can override `setAudioEffectPreset`: + + - [setVoiceBeautifierPreset]([AgoraRtcEngineKit setVoiceBeautifierPreset:]) + - [setVoiceBeautifierParameters]([AgoraRtcEngineKit setVoiceBeautifierParameters:param1:param2:]) + - [setVoiceConversionPreset]([AgoraRtcEngineKit setVoiceConversionPreset:]) + - [setLocalVoiceReverbPreset]([AgoraRtcEngineKit setLocalVoiceReverbPreset:]) + - [setLocalVoiceChanger]([AgoraRtcEngineKit setLocalVoiceChanger:]) + - [setLocalVoicePitch]([AgoraRtcEngineKit setLocalVoicePitch:]) + - [setLocalVoiceEqualizationOfBandFrequency]([AgoraRtcEngineKit setLocalVoiceEqualizationOfBandFrequency:withGain:]) + - [setLocalVoiceReverbOfType]([AgoraRtcEngineKit setLocalVoiceReverbOfType:withValue:]) + + @param preset The options for SDK preset audio effects: [AgoraAudioEffectPreset](AgoraAudioEffectPreset). + + @return - 0: Success. +- < 0: Failure. + */ +- (int)setAudioEffectPreset:(AgoraAudioEffectPreset)preset; +/** Sets an SDK preset voice conversion effect. + + @since v3.3.1 + + Call this method to set an SDK preset voice conversion effect for the local user who sends an audio stream. + After setting a voice conversion effect, all users in the channel can hear the effect. + + You can set different voice conversion effects for different scenarios. See *Set the Voice Effect*. + + To achieve better voice effect quality, Agora recommends calling [setAudioProfile]([AgoraRtcEngineKit setAudioProfile:scenario:]) + and setting the `profile` parameter to `AgoraAudioProfileMusicHighQuality(4)` or `AgoraAudioProfileMusicHighQualityStereo(5)` and + the `scenario` parameter to `AgoraAudioScenarioGameStreaming(3)` before calling this method. + + **Note**: + + - You can call this method either before or after joining a channel. + - Do not set the `profile` parameter of `setAudioProfile` to `AgoraAudioProfileSpeechStandard(1)`; otherwise, this method call does not take effect. + - This method works best with the human voice. Agora does not recommend using this method for audio containing music. + - After calling this method, Agora recommends not calling the following methods, because they can override `setVoiceConversionPreset`: + + - [setAudioEffectPreset]([AgoraRtcEngineKit setAudioEffectPreset:]) + - [setAudioEffectParameters]([AgoraRtcEngineKit setAudioEffectParameters:param1:param2:]) + - [setVoiceBeautifierPreset]([AgoraRtcEngineKit setVoiceBeautifierPreset:]) + - [setVoiceBeautifierParameters]([AgoraRtcEngineKit setVoiceBeautifierParameters:param1:param2:]) + - [setLocalVoiceReverbPreset]([AgoraRtcEngineKit setLocalVoiceReverbPreset:]) + - [setLocalVoiceChanger]([AgoraRtcEngineKit setLocalVoiceChanger:]) + - [setLocalVoicePitch]([AgoraRtcEngineKit setLocalVoicePitch:]) + - [setLocalVoiceEqualizationOfBandFrequency]([AgoraRtcEngineKit setLocalVoiceEqualizationOfBandFrequency:withGain:]) + - [setLocalVoiceReverbOfType]([AgoraRtcEngineKit setLocalVoiceReverbOfType:withValue:]) + + @param preset The options for SDK preset voice conversion effects: [AgoraVoiceConversionPreset](AgoraVoiceConversionPreset). + + @return - 0: Success. +- < 0: Failure. + */ +- (int)setVoiceConversionPreset:(AgoraVoiceConversionPreset)preset; + +/** Sets parameters for SDK preset audio effects. + + @since v3.2.0 + + Call this method to set the following parameters for the local user who sends an audio stream: + + - 3D voice effect: Sets the cycle period of the 3D voice effect. + - Pitch correction effect: Sets the basic mode and tonic pitch of the pitch correction effect. Different songs have different modes and + tonic pitches. Agora recommends bounding this method with interface elements to enable users to adjust the pitch correction interactively. + + After setting parameters, all users in the channel can hear the relevant effect. + + **Note**: + + - You can call this method either before or after joining a channel. + - To achieve better audio effect quality, Agora recommends calling [setAudioProfile]([AgoraRtcEngineKit setAudioProfile:scenario:]) and + setting the scenario parameter to `AgoraAudioScenarioGameStreaming(3)` before calling this method. + - Do not set the `profile` parameter of `setAudioProfile` to `AgoraAudioProfileSpeechStandard(1)`; otherwise, this method call does not take effect. + - This method works best with the human voice. Agora does not recommend using this method for audio containing music. + - After calling this method, Agora recommends not calling the following methods, because they can override `setAudioEffectParameters`: + + - [setAudioEffectPreset]([AgoraRtcEngineKit setAudioEffectPreset:]) + - [setVoiceBeautifierPreset]([AgoraRtcEngineKit setVoiceBeautifierPreset:]) + - [setVoiceBeautifierParameters]([AgoraRtcEngineKit setVoiceBeautifierParameters:param1:param2:]) + - [setVoiceConversionPreset]([AgoraRtcEngineKit setVoiceConversionPreset:]) + - [setLocalVoiceReverbPreset]([AgoraRtcEngineKit setLocalVoiceReverbPreset:]) + - [setLocalVoiceChanger]([AgoraRtcEngineKit setLocalVoiceChanger:]) + - [setLocalVoicePitch]([AgoraRtcEngineKit setLocalVoicePitch:]) + - [setLocalVoiceEqualizationOfBandFrequency]([AgoraRtcEngineKit setLocalVoiceEqualizationOfBandFrequency:withGain:]) + - [setLocalVoiceReverbOfType]([AgoraRtcEngineKit setLocalVoiceReverbOfType:withValue:]) + + @param preset The options for SDK preset audio effects: + + - 3D voice effect: `AgoraRoomAcoustics3DVoice`. + + - Call `setAudioProfile` and set the `profile` parameter to + `AgoraAudioProfileMusicStandardStereo(3)` or `AgoraAudioProfileMusicHighQualityStereo(5)` before setting this enumerator; + otherwise, the enumerator setting does not take effect. + - If the 3D voice effect is enabled, users need to use stereo audio playback devices to hear the anticipated voice effect. + + - Pitch correction effect: `AgoraPitchCorrection`. To achieve better audio effect quality, Agora recommends calling + `setAudioProfile` and setting the `profile` parameter to `AgoraAudioProfileMusicHighQuality(4)` or + `AgoraAudioProfileMusicHighQualityStereo(5)` before setting this enumerator. + @param param1 - If you set `preset` to `AgoraRoomAcoustics3DVoice`, the `param1` sets the cycle period of the 3D voice effect. + The value range is [1,60] and the unit is a second. The default value is 10 seconds, indicating that the voice moves around + you every 10 seconds. + - If you set `preset` to `AgoraPitchCorrection`, `param1` sets the basic mode of the pitch correction effect: + + - `1`: (Default) Natural major scale. + - `2`: Natural minor scale. + - `3`: Japanese pentatonic scale. + @param param2 - If you set `preset` to `AgoraRoomAcoustics3DVoice`, you need to set `param2` to `0`. +- If you set`preset` to `AgoraPitchCorrection`, `param2` sets the tonic pitch of the pitch correction effect: + + - `1`: A + - `2`: A# + - `3`: B + - `4`: (Default) C + - `5`: C# + - `6`: D + - `7`: D# + - `8`: E + - `9`: F + - `10`: F# + - `11`: G + - `12`: G# + + @return - 0: Success. +- < 0: Failure. + */ +- (int)setAudioEffectParameters:(AgoraAudioEffectPreset)preset param1:(int)param1 param2:(int)param2; + +#pragma mark Sound Position Indication + +/**----------------------------------------------------------------------------- + * @name Sound Position Indication + * ----------------------------------------------------------------------------- + */ +/** Enables/Disables stereo panning for remote users. + +If you need to use the [setRemoteVoicePosition]([AgoraRtcEngineKit setRemoteVoicePosition:pan:gain:]) method, ensure that you call this method before joining a channel to enable stereo panning for remote users. + + @param enabled Sets whether to enable stereo panning for remote users: + + - `YES`: enables stereo panning. + - `NO`: disables stereo panning. + + @return * 0: Success. + * < 0: Failure. + */ +- (int)enableSoundPositionIndication:(BOOL)enabled; + +/** Sets the sound position and gain of a remote user. + + When the local user calls this method to set the sound position of a remote user, the sound difference between the left and right channels allows the local user to track the real-time position of the remote user, creating a real sense of space. This method applies to massively multiplayer online games, such as Battle Royale games. + +**Note:** + +- Ensure that you call this method after joining a channel. For this method to work, enable stereo panning for remote users by calling [enableSoundPositionIndication]([AgoraRtcEngineKit enableSoundPositionIndication:]) before joining a channel. +This method requires hardware support. +- For the best effect, we recommend using the following audio output devices: + - (iOS) A wired headset. + - (macOS) A stereo loudspeaker. + @param uid The ID of the remote user. + @param pan The sound position of the remote user. The value ranges from -1.0 to 1.0: + + * 0.0: (default) the remote sound comes from the front. + * -1.0: the remote sound comes from the left. + * 1.0: the remote sound comes from the right. + + @param gain Gain of the remote user. The value ranges from 0.0 to 100.0. The default value is 100.0 (the original gain of the remote user). The smaller the value, the less the gain. + + @return * 0: Success. +* < 0: Failure. + */ +- (int)setRemoteVoicePosition:(NSUInteger)uid pan:(double)pan gain:(double)gain; + +#pragma mark Music File Playback and Mixing + +/**----------------------------------------------------------------------------- + * @name Music File Playback and Mixing + * ----------------------------------------------------------------------------- + */ + +/** Starts playing and mixing the music file. + + @since v3.4.0 + + This method supports mixing or replacing local or online music file and audio collected by a microphone. After + successfully playing the music file, the SDK triggers + [localAudioMixingStateDidChanged]([AgoraRtcEngineDelegate rtcEngine:localAudioMixingStateDidChanged:reason:])`(AgoraAudioMixingStatePlaying, AgoraAudioMixingReasonStartedByUser)`. + After completing playing the music file, the SDK triggers `localAudioMixingStateDidChanged(AgoraAudioMixingStateStopped, AgoraAudioMixingReasonAllLoopsCompleted)`. + + **Note:** + + - To avoid blocking, as of v3.4.5, this method changes from a synchronous call + to an asynchronous call. + - If you need to call `startAudioMixing` multiple times, ensure that the + call interval is longer than 500 ms. + - If the local music file does not exist, or if the SDK does not support the file format or cannot access the music + file URL, the SDK returns `AgoraWarningCodeAudioMixingOpenError(701)`. + - For the audio file formats supported by this method, see + [What formats of audio files does the Agora RTC SDK support](https://docs.agora.io/en/faq/audio_format). + + @param filePath The absolute path or URL address (including the filename extensions) of the music file. For example: + `/var/mobile/Containers/Data/audio.mp4`. + @param loopback Whether to only play the music file on the local client: + + * YES: Only play the music file on the local client so that only the local user can hear the music. + * NO: Publish the music file to remote clients so that both the local user and remote users can hear the music. + + @param replace Whether to replace the audio collected by the microphone with a music file: + + * YES: Replace. Users can only hear music. + * NO: Do not replace. Users can hear both music and audio collected by the microphone. + + @param cycle The number of times the music file plays. + + * ≥ `0`: The number of playback times. For example, 0 means that the SDK does not play the music file, while 1 means + that the SDK plays the music file once. + * `-1`:Play the music in an indefinite loop. + + @param startPos The playback position (ms) of the music file. + + @return * 0: Success. +* < 0: Failure. + */ +- (int)startAudioMixing:(NSString* _Nonnull)filePath loopback:(BOOL)loopback replace:(BOOL)replace cycle:(NSInteger)cycle startPos:(NSInteger)startPos; + +/** Sets the playback speed of the current music file. + + @since v3.5.1 + + @note Call this method after calling + [startAudioMixing]([AgoraRtcEngineKit startAudioMixing:loopback:replace:cycle:startPos:]) + and receiving the + [localAudioMixingStateDidChanged]([AgoraRtcEngineDelegate rtcEngine:localAudioMixingStateDidChanged:reason:]) + (`AgoraAudioMixingStatePlaying`) callback. + + @param speed The playback speed. Agora recommends that you limit this value to + between 50 and 400, defined as follows: + + - 50: Half the original speed. + - 100: The original speed. + - 400: 4 times the original speed. + + @return * 0: Success. + * < 0: Failure. + */ +- (int)setAudioMixingPlaybackSpeed:(int)speed; + +/** Stops audio mixing. + + Call this method when you are in a channel. + + @return * 0: Success. +* < 0: Failure. + */ +- (int)stopAudioMixing; + +/** Pauses audio mixing. + + Call this method when you are in a channel. + + @return * 0: Success. +* < 0: Failure. + */ +- (int)pauseAudioMixing; + +/** Resumes audio mixing. + + Call this method when you are in a channel. + + @return * 0: Success. +* < 0: Failure. + */ +- (int)resumeAudioMixing; + +/** Specifies the playback track of the current music file. + + @since v3.5.1 + + After getting the audio track index of the current music file, call this + method to specify any audio track to play. For example, if different tracks of + a multitrack file store songs in different languages, you can call this method + to set the language of the music file to play. + + **Notes** + + - Call this method after calling + [startAudioMixing]([AgoraRtcEngineKit startAudioMixing:loopback:replace:cycle:startPos:]) + and receiving the + [localAudioMixingStateDidChanged]([AgoraRtcEngineDelegate rtcEngine:localAudioMixingStateDidChanged:reason:]) + (`AgoraAudioMixingStatePlaying`) callback. + - This method applies to iOS only. + - For the audio file formats supported by this method, see + [What formats of audio files does the Agora RTC SDK support](https://docs.agora.io/en/faq/audio_format). + + @param index The specified playback track. This parameter must be less than or + equal to the return value of [getAudioTrackCount]([AgoraRtcEngineKit getAudioTrackCount]). + + @return - 0: Success. + - < 0: Failure. + */ +- (int)selectAudioTrack:(NSInteger)index; + +/** Gets the audio track index of the current music file. + + @since v3.5.1 + + **Notes** + + - Call this method after calling + [startAudioMixing]([AgoraRtcEngineKit startAudioMixing:loopback:replace:cycle:startPos:]) + and receiving the + [localAudioMixingStateDidChanged]([AgoraRtcEngineDelegate rtcEngine:localAudioMixingStateDidChanged:reason:]) + (`AgoraAudioMixingStatePlaying`) callback. + - This method applies to iOS only. + - For the audio file formats supported by this method, see + [What formats of audio files does the Agora RTC SDK support](https://docs.agora.io/en/faq/audio_format). + + @return - ≥ 0: The audio track index of the current music file, if this method call succeeds. + - < 0: Failure. + */ +- (int)getAudioTrackCount; + +/** Sets the channel mode of the current music file. + + @since v3.5.1 + + In a stereo music file, the left and right channels can store different audio + data. According to your needs, you can set the channel mode to original mode, + left channel mode, right channel mode, or mixed channel mode. For example, + in the KTV scenario, the left channel of the music file stores the musical + accompaniment, and the right channel stores the singing voice. If you only + need to listen to the accompaniment, call this method to set the channel + mode of the music file to left channel mode; if you need to listen to the + accompaniment and the singing voice at the same time, call this method to + set the channel mode to mixed channel mode. + + **Notes** + + - Call this method after calling + [startAudioMixing]([AgoraRtcEngineKit startAudioMixing:loopback:replace:cycle:startPos:]) + and receiving the + [localAudioMixingStateDidChanged]([AgoraRtcEngineDelegate rtcEngine:localAudioMixingStateDidChanged:reason:]) + (`AgoraAudioMixingStatePlaying`) callback. + - This method only applies to stereo audio files. + + @param mode The channel mode. See AgoraAudioMixingDualMonoMode. + + @return - 0: Success. + - < 0: Failure. + */ +- (int)setAudioMixingDualMonoMode:(AgoraAudioMixingDualMonoMode)mode; + +/** Adjusts the volume of audio mixing. + + Ensure that this method is called after [startAudioMixing]([AgoraRtcEngineKit startAudioMixing:loopback:replace:cycle:startPos:]). + + **Note:** + + Calling this method does not affect the volume of audio effect file playback invoked by the [playEffect]([AgoraRtcEngineKit playEffect:filePath:loopCount:pitch:pan:gain:publish:startPos:]) method. + + @param volume Audio mixing volume. The value ranges between 0 and 100 (default). + @return * 0: Success. +* < 0: Failure. + */ +- (int)adjustAudioMixingVolume:(NSInteger)volume; + +/** Adjusts the volume of audio mixing for local playback. + + Ensure that this method is called after [startAudioMixing]([AgoraRtcEngineKit startAudioMixing:loopback:replace:cycle:startPos:]). + + @param volume Audio mixing volume for local playback. The value ranges between 0 and 100 (default). + @return * 0: Success. + * < 0: Failure. + */ +- (int)adjustAudioMixingPlayoutVolume:(NSInteger)volume; + +/** Adjusts the volume of audio mixing for publishing (sending to other users). + + Ensure that this method is called after [startAudioMixing]([AgoraRtcEngineKit startAudioMixing:loopback:replace:cycle:startPos:]). + + @param volume Audio mixing volume for publishing. The value ranges between 0 and 100 (default). + @return * 0: Success. + * < 0: Failure. + */ +- (int)adjustAudioMixingPublishVolume:(NSInteger)volume; + +/** Gets the audio mixing volume for publishing. + + This method helps troubleshoot audio volume related issues. + + @note Call this method after calling [startAudioMixing]([AgoraRtcEngineKit startAudioMixing:loopback:replace:cycle:startPos:]) +and receiving the [localAudioMixingStateDidChanged]([AgoraRtcEngineDelegate rtcEngine:localAudioMixingStateDidChanged:reason:])(`AgoraAudioMixingStatePlaying`) callback. + + @return * ≥ 0: The audio mixing volume for publishing, if this method call is successful. The value ranges between 0 to 100. +* < 0: Failure. +*/ +- (int)getAudioMixingPublishVolume; + +/** Gets the audio mixing volume for local playback. + + This method helps troubleshoot audio volume related issues. + + @note Call this method after calling [startAudioMixing]([AgoraRtcEngineKit startAudioMixing:loopback:replace:cycle:startPos:]) +and receiving the [localAudioMixingStateDidChanged]([AgoraRtcEngineDelegate rtcEngine:localAudioMixingStateDidChanged:reason:])(`AgoraAudioMixingStatePlaying`) callback. + + @return * ≥ 0: The audio mixing volume for local playback, if this method call is successful. The value ranges between 0 to 100. +* < 0: Failure. +*/ +- (int)getAudioMixingPlayoutVolume; + +/** Gets the playback position (ms) of the audio mixing file. + + **Note**: + + - Call this method after calling [startAudioMixing]([AgoraRtcEngineKit startAudioMixing:loopback:replace:cycle:startPos:]) + and receiving the [localAudioMixingStateDidChanged]([AgoraRtcEngineDelegate rtcEngine:localAudioMixingStateDidChanged:reason:])(`AgoraAudioMixingStatePlaying`) callback. + - If you need to call `getAudioMixingCurrentPosition` multiple times, ensure that the call interval is longer than 500 ms. + + @return * ≥ 0: The current playback position (ms) of the music file, if this method call succeeds. 0 represents that the current music file does not start playing. + +* < 0: Failure. + */ +- (int)getAudioMixingCurrentPosition; + +/** Sets the playback position of the audio mixing file to a different starting position (the default plays from the beginning). + + Ensure that this method is called after [startAudioMixing]([AgoraRtcEngineKit startAudioMixing:loopback:replace:cycle:startPos:]). + + @param pos The playback starting position (ms) of the audio mixing file. + + @return * 0: Success. +* < 0: Failure. + */ +- (int)setAudioMixingPosition:(NSInteger)pos; + +/** Sets the pitch of the local music file. + + **Since:** v3.0.1. + + When a local music file is mixed with a local human voice, call this method to set the pitch of the local music file only. + + @note Call this method after calling [startAudioMixing]([AgoraRtcEngineKit startAudioMixing:loopback:replace:cycle:startPos:]). + + @param pitch Sets the pitch of the local music file by chromatic scale. The default value is 0, which means keeping the original pitch. The value ranges from -12 to 12, and the pitch value between consecutive values is a chromatic value. The greater the absolute value of this parameter, the higher or lower the pitch of the local music file. + + @return * 0: Success. + * < 0: Failure. + */ +- (int)setAudioMixingPitch:(NSInteger)pitch; + +#pragma mark Audio Effect File Playback + +/**----------------------------------------------------------------------------- + * @name Audio Effect File Playback + * ----------------------------------------------------------------------------- + */ + +/** Gets the volume of the audio effects. + + Ensure that this method is called after [playEffect]([AgoraRtcEngineKit playEffect:filePath:loopCount:pitch:pan:gain:publish:startPos:]). + + The value ranges between 0.0 and 100.0. + + @return * ≥ 0: Volume of the audio effects, if this method call is successful. + +* < 0: Failure. + */ +- (double)getEffectsVolume; + +/** Sets the volume of the audio effects. + + Ensure that this method is called after [playEffect]([AgoraRtcEngineKit playEffect:filePath:loopCount:pitch:pan:gain:publish:startPos:]). + + @param volume Volume of the audio effects. The value ranges between 0.0 and 100.0 (default). + + @return * 0: Success. +* < 0: Failure. + */ +- (int)setEffectsVolume:(double)volume; + +/** Sets the volume of a specified audio effect. + + Ensure that this method is called after [playEffect]([AgoraRtcEngineKit playEffect:filePath:loopCount:pitch:pan:gain:publish:startPos:]). + + @param soundId ID of the audio effect. Each audio effect has a unique ID. + @param volume Volume of the audio effect. The value ranges between 0.0 and 100.0 (default). + + @return * 0: Success. +* < 0: Failure. + */ +- (int)setVolumeOfEffect:(int)soundId withVolume:(double)volume; + +/** Plays a specified local or online audio effect file. + + To play multiple audio effect files at the same time, call this method multiple times with different `soundId` and `filePath` values. + For the best user experience, Agora recommends playing no more than three audio effect files at the same time. + + After completing playing an audio effect file, the SDK triggers the [rtcEngineDidAudioEffectFinish]([AgoraRtcEngineDelegate rtcEngineDidAudioEffectFinish:soundId:]) callback. + + **Note** + + - Call this method after joining a channel. + - For the audio file formats supported by this method, see + [What formats of audio files does the Agora RTC SDK support](https://docs.agora.io/en/faq/audio_format). + + @param soundId Audio effect ID. The ID of each audio effect file is unique. If you preloaded an audio effect into + memory by calling [preloadEffect](preloadEffect:filePath:), ensure that this parameter is set to the same value as in `preloadEffect`. + @param filePath The absolute path or URL address (including the filename extensions) of the audio effect file. + For example: `/var/mobile/Containers/Data/audio.mp4`. + If you preloaded an audio effect into memory by calling `preloadEffect`, ensure that this parameter is set to the same + value as in `preloadEffect`. + @param loopCount The number of times the audio effect loops: + + - ≥ `0`: The number of loops. For example, `1` means loop one time, which means play the audio effect two times in total. + - `-1`: Play the audio effect in an indefinite loop. + + @param pitch The pitch of the audio effect. The range is `0.5` to `2.0`. The default value is `1.0`, which means the + original pitch. The lower the value, the lower the pitch. + @param pan The spatial position of the audio effect. The range is `-1.0` to `1.0`. For example: + + - `-1.0`: The audio effect occurs on the left. + - `0.0`: The audio effect occurs in the front. + - `1.0`: The audio effect occurs on the right. + + @param gain The volume of the audio effect. The range is `0.0` to `100.0`. The default value is 100.0, which means the + original volume. The smaller the value, the less the gain. + @param publish Whether to publish the audio effect to the remote users: + +- `YES`: Publish. Both the local user and remote users can hear the audio effect. +- `NO`: Do not publish. Only the local user can hear the audio effect. + + @param startPos The playback position (ms) of the audio effect file. + + @return * 0: Success. +* < 0: Failure. + */ +- (int)playEffect:(int)soundId filePath:(NSString* _Nullable)filePath loopCount:(int)loopCount pitch:(double)pitch pan:(double)pan gain:(double)gain publish:(BOOL)publish startPos:(int)startPos; + +/** Stops playing a specified audio effect. + + @param soundId ID of the audio effect. Each audio effect has a unique ID. + + @return * 0: Success. +* < 0: Failure. + */ +- (int)stopEffect:(int)soundId; + +/** Stops playing all audio effects. + */ +- (int)stopAllEffects; + +/** Preloads a specified audio effect file into the memory. + + To ensure smooth communication, limit the size of the audio effect file. Agora recommends using this method to preload the audio effect before calling the [joinChannelByToken]([AgoraRtcEngineKit joinChannelByToken:channelId:info:uid:joinSuccess:]) method. + + **Note** + + - This method does not support online audio effect files. + - For the audio file formats supported by this method, see + [What formats of audio files does the Agora RTC SDK support](https://docs.agora.io/en/faq/audio_format). + + @param soundId ID of the audio effect. Each audio effect has a unique ID. + @param filePath Absolute path of the audio effect file. + + @return * 0: Success. +* < 0: Failure. + */ +- (int)preloadEffect:(int)soundId filePath:(NSString* _Nullable)filePath; + +/** Releases a specified preloaded audio effect from the memory. + + @param soundId ID of the audio effect. Each audio effect has a unique ID. + + @return * 0: Success. +* < 0: Failure. + */ +- (int)unloadEffect:(int)soundId; + +/** Pauses a specified audio effect. + + @param soundId ID of the audio effect. Each audio effect has a unique ID. + + @return * 0: Success. +* < 0: Failure. + */ +- (int)pauseEffect:(int)soundId; + +/** Pauses all audio effects. + + @return * 0: Success. +* < 0: Failure. + */ +- (int)pauseAllEffects; + +/** Resumes playing a specified audio effect. + + @param soundId ID of the audio effect. Each audio effect has a unique ID. + + @return * 0: Success. +* < 0: Failure. + */ +- (int)resumeEffect:(int)soundId; + +/** Resumes playing all audio effects. + + @return * 0: Success. +* < 0: Failure. + */ +- (int)resumeAllEffects; + +/** Gets the playback position of the audio effect file. + + @since v3.4.0 + + @note Call this method after [playEffect]([AgoraRtcEngineKit playEffect:filePath:loopCount:pitch:pan:gain:publish:startPos:]). + + @param soundId Audio effect ID. Ensure that this parameter is set to the same value as in `playEffect`. + @return - ≥ 0: A successful method call. Returns the playback position (ms) of the specified audio effect file. +- < 0: Failure. + + - `-22(AgoraErrorCodeResourceLimited)`: Cannot find the audio effect file. Please set a correct `soundId`. + */ +- (int)getEffectCurrentPosition:(int)soundId; + +/** Sets the playback position of an audio effect file. + + @since v3.4.0 + + After a successful setting, the local audio effect file starts playing at the specified position. + + @note Call this method after [playEffect]([AgoraRtcEngineKit playEffect:filePath:loopCount:pitch:pan:gain:publish:startPos:]). + + @param soundId Audio effect ID. Ensure that this parameter is set to the same value as in `playEffect`. + @param pos The playback position (ms) of the audio effect file. + + @return - 0: Success. +- < 0: Failure. + + - `-22(AgoraErrorCodeResourceLimited)`: Cannot find the audio effect file. Please set a correct `soundId`. + */ +- (int)setEffectPosition:(int)soundId pos:(NSInteger)pos; + +/** Gets the duration of the audio effect file. + + @since v3.4.0 + + **Note** + + - Call this method after joining a channel. + - For the audio file formats supported by this method, see + [What formats of audio files does the Agora RTC SDK support](https://docs.agora.io/en/faq/audio_format). + + @param filePath The absolute path (including the filename extensions) of the local audio effect file. For example: + `/var/mobile/Containers/Data/audio.mp4`. + @return - ≥ 0: A successful method call. Returns the total duration (ms) of the specified audio effect file. +- < 0: Failure. + + - `-22(AgoraErrorCodeResourceLimited)`: Cannot find the audio effect file. Please set a correct `filePath`. + */ +- (int)getEffectDuration:(NSString* _Nonnull)filePath; + +/**----------------------------------------------------------------------------- + * @name Virtual metronome + * ----------------------------------------------------------------------------- + */ + +/** Enables the virtual metronome (iOS only). + + @since v3.4.0 + + In music education, physical education, and other scenarios, teachers often need to use a metronome so that students + can practice at the correct tempo. A meter is composed of a downbeat and some number of upbeats (including zero). The + first beat of each measure is called the downbeat, and the rest are called the upbeats. In this method, you need to set + the paths of the upbeat and downbeat files, the number of beats per measure, the tempo, and whether to send the sound of the metronome to remote users. + + **Note** + + - After enabling the virtual metronome, the SDK plays the specified files from the beginning and controls the beat + duration according to the value you set in [beatsPerMinute](AgoraRtcRhythmPlayerConfig). If the file duration exceeds + the beat duration, the SDK only plays the audio within the beat duration. + - For the audio file formats supported by this method, see + [What formats of audio files does the Agora RTC SDK support](https://docs.agora.io/en/faq/audio_format). + + @param sound1 The absolute path or URL address (including the filename extensions) of the file for the downbeat. For + example: `/var/mobile/Containers/Data/audio.mp4`. + @param sound2 The absolute path or URL address (including the filename extensions) of the file for the upbeats. For + example: `/var/mobile/Containers/Data/audio.mp4`. + @param config The metronome configuration. See [AgoraRtcRhythmPlayerConfig](AgoraRtcRhythmPlayerConfig). + @return - 0: Success. +- < 0: Failure. + + - `-22(AgoraErrorCodeResourceLimited)`: Cannot find audio effect files. Please set the correct paths for `sound1` and `sound2`. + */ +- (int)startRhythmPlayer:(NSString* _Nonnull)sound1 sound2:(NSString* _Nonnull)sound2 config:(AgoraRtcRhythmPlayerConfig* _Nonnull)config; +/** Disables the virtual metronome (iOS only). + + @since v3.4.0 + + After calling [startRhythmPlayer]([AgoraRtcEngineKit startRhythmPlayer:sound2:config:]), you can call this method to + disable the virtual metronome. + + @return - 0: Success. +- < 0: Failure. + */ +- (int)stopRhythmPlayer; +/** Configures the virtual metronome (iOS only). + + @since v3.4.0 + + After calling [startRhythmPlayer]([AgoraRtcEngineKit startRhythmPlayer:sound2:config:]), you can call this method to + reconfigure the virtual metronome. + + @note After reconfiguring the virtual metronome, the SDK plays the specified files from the beginning and controls the + beat duration according to the value you set in [beatsPerMinute](AgoraRtcRhythmPlayerConfig). If the file duration + exceeds the beat duration, the SDK only plays the audio within the beat duration. + + @param config The metronome configuration. See [AgoraRtcRhythmPlayerConfig](AgoraRtcRhythmPlayerConfig). + @return - 0: Success. +- < 0: Failure. + */ +- (int)configRhythmPlayer:(AgoraRtcRhythmPlayerConfig* _Nonnull)config; + +#pragma mark Audio Recorder + +/**----------------------------------------------------------------------------- + * @name Audio Recorder + * ----------------------------------------------------------------------------- + */ + +/** Starts an audio recording on the client. + + @since v3.4.0 + + The SDK allows recording audio during a call. After successfully calling this method, you can record the audio of + users in the channel and get an audio recording file. Supported file formats are as follows: + + - WAV: High-fidelity files with typically larger file sizes. For example, if the sample rate is 32,000 Hz, the file + size for a 10-minute recording is approximately 73 MB. + - AAC: Low-fidelity files with typically smaller file sizes. For example, if the sample rate is 32,000 Hz and the + recording quality is `AgoraAudioRecordingQualityMedium`, the file size for a 10-minute recording is approximately 2 MB. + + Once the user leaves the channel, the recording automatically stops. + + @note Call this method after joining a channel. + + @param config Recording configuration. See AgoraAudioRecordingConfiguration. + + @return - 0: Success. + - < 0: Failure. + + -160(`AgoraErrorCodeAlreadyInRecording`): The client is already recording audio. To start a new recording, call + [stopAudioRecording]([AgoraRtcEngineKit stopAudioRecording]) to stop the current recording first, and then call + `startAudioRecordingWithConfig`. + */ +- (int)startAudioRecordingWithConfig:(AgoraAudioRecordingConfiguration* _Nonnull)config; + +/** Stops an audio recording on the client. + + @return * 0: Success. +* < 0: Failure. + */ +- (int)stopAudioRecording; + +#pragma mark Loopback Recording + +/**----------------------------------------------------------------------------- + * @name Loopback Sampling + * ----------------------------------------------------------------------------- + */ + +#if (!(TARGET_OS_IPHONE) && (TARGET_OS_MAC)) +/** Enables loopback sampling. (macOS only) + + If you enable loopback sampling, the output of the sound card is mixed into the audio stream sent to the other end. + + You can call this method either before or after joining a channel. + + **Note:** + + macOS does not support loopback sampling of the default sound card. If you need to use this method, please use a virtual sound card and pass its name to the `deviceName` parameter. Agora has tested and recommends using soundflower. + + @param enabled Sets whether to enable/disable loopback sampling. + + * YES: Enable loopback sampling. + * NO: (Default) Disable loopback sampling. + + @param deviceName Pointer to the device name of the sound card. The default value is nil (default sound card). If you use a virtual sound card like "Soundflower", set this parameter as the name of the sound card, "Soundflower", and the SDK will find the corresponding sound card and start capturing. + @return * 0: Success. +* < 0: Failure. + */ +- (int)enableLoopbackRecording:(BOOL)enabled deviceName:(NSString* _Nullable)deviceName; +#endif + +#pragma mark Miscellaneous Audio Control + +/**----------------------------------------------------------------------------- + * @name Miscellaneous Audio Control + * ----------------------------------------------------------------------------- + */ + +#if defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE +/** Sets the operational permission of the SDK on the audio session. (iOS only) + + The SDK and the app can both configure the audio session by default. If you need to only use the app to configure the audio session, this method restricts the operational permission of the SDK on the audio session. + + You can call this method either before or after joining a channel. Once you call this method to restrict the operational permission of the SDK on the audio session, the restriction takes effect when the SDK needs to change the audio session. + + @note This method does not restrict the operational permission of the app on the audio session. + + @param restriction The operational permission of the SDK on the audio session. See [AgoraAudioSessionOperationRestriction](AgoraAudioSessionOperationRestriction). This parameter is in bit mask format, and each bit corresponds to a permission. + */ +- (void)setAudioSessionOperationRestriction:(AgoraAudioSessionOperationRestriction)restriction; +#endif + +/** Enables or disables deep-learning noise reduction. + + The SDK enables traditional noise reduction mode by default to reduce most + of the stationary background noise. If you need to reduce most of the + non-stationary background noise, Agora recommends enabling deep-learning + noise reduction as follows: + + 1. Ensure that the following library is integrated in your project: + + - iOS: `AgoraAIDenoiseExtension.xcframework` + - macOS: `AgoraAIDenoiseExtension.framework` + 2. Call `enableDeepLearningDenoise(YES)`. + + Deep-learning noise reduction requires high-performance devices. The + following devices and later models are known to support deep-learning noise + reduction: + + - iPhone 6S + - MacBook Pro 2015 + - iPad Pro (2nd generation) + - iPad mini (5th generation) + - iPad Air (3rd generation) + + After successfully enabling deep-learning noise reduction, if the SDK detects + that the device performance is not sufficient, it automatically disables + deep-learning noise reduction and enables traditional noise reduction. + + If you call `enableDeepLearningDenoise(NO)` or the SDK automatically + disables deep-learning noise reduction in the channel, when you need to + re-enable deep-learning noise reduction, you need to call [leaveChannel]([AgoraRtcEngineKit leaveChannel:]) + first, and then call `enableDeepLearningDenoise(YES)`. + + **Note** + + - This method dynamically loads the `AgoraAIDenoiseExtension` library, so + Agora recommends calling this method before joining a channel. + - This method works best with the human voice. Agora does not recommend + using this method for audio containing music. + + @param enabled Sets whether to enable deep-learning noise reduction. + + - `YES`: (Default) Enables deep-learning noise reduction. + - `NO`: Disables deep-learning noise reduction. + + @return * 0: Success. + * < 0: Failure. + * -`157`(`AgoraErrorCodeModuleNotFound`): The library for enabling deep-learning noise reduction is not integrated. + */ +- (int)enableDeepLearningDenoise:(BOOL)enabled; + +#pragma mark Network-related Test + +/**----------------------------------------------------------------------------- + * @name Network-related Test + * ----------------------------------------------------------------------------- + */ + +/** Starts an audio call test. + +This method starts an audio call test to determine whether the audio devices (for example, headset and speaker) and the network connection are working properly. + +In the audio call test, the SDK samples your voice. If the sampled audio data plays back within the set time interval, the audio devices and the network connection are working properly. + +**Note:** + +- Call this method before joining a channel. + +- After calling this method, call the stopEchoTest method to end the test. Otherwise, the app cannot run the next echo test, or join a channel. + +- In the interactive live streaming profile, only a host can call this method. + +@param interval The time interval (s) between when you speak and when the sampled audio data plays back. +@param successBlock The SDK triggers the `successBlock` callback if this method call is successful. + +@return * 0: Success. +* < 0: Failure. +*/ +- (int)startEchoTestWithInterval:(NSInteger)interval successBlock:(void (^_Nullable)(NSString* _Nonnull channel, NSUInteger uid, NSInteger elapsed))successBlock; + +/** + Starts an audio and video call loop test. + + @since v3.5.2 + + Before joining a channel, to test whether the user's local sending and receiving streams are normal, you can call this + method to perform an audio and video call loop test, which tests whether the audio and video devices and the user's upstream and downstream networks are working properly. + + After starting the test, the user needs to make a sound or face the camera. The audio or video is output after about two seconds. + If the audio playback is normal, the audio device and the user's upstream and downstream networks are working properly; + if the video playback is normal, the video device and the user's upstream and downstream networks are working properly. + + **Notes:** + + - Call this method before joining a channel. + - After calling this method, call [stopEchoTest]([AgoraRtcEngineKit stopEchoTest]) to end the test; otherwise, the user cannot perform the next audio and video call loop test and cannot join the channel. + - In the `LiveBroadcasting` profile, only a host can call this method. + + @param config The configuration of the audio and video call loop test. See AgoraEchoTestConfiguration. + + @return - 0: Success. + - < 0: Failure. + */ +- (int)startEchoTestWithConfig:(AgoraEchoTestConfiguration* _Nonnull)config; + +/** Stops call loop test. + +After calling [startEchoTestWithInterval]([AgoraRtcEngineKit startEchoTestWithInterval:successBlock:]) +or [startEchoTestWithConfig]([AgoraRtcEngineKit startEchoTestWithConfig:]), call this method if you want to stop the call loop test. + + @return * 0: Success. +* < 0: Failure. For example, AgoraErrorCodeRefused(-5):Failed to stop the echo test. The echo test may not be running. + */ +- (int)stopEchoTest; + +- (int)setLocalAccessPoint:(NSArray* _Nonnull)ips domain:(NSString* _Nonnull)domain; + +/** Enables the network connection quality test. + + This method tests the quality of the user’s network connection and is disabled by default. + + Before users join a channel or before an audience switches to a host, call this method to check the uplink network quality. + + This method consumes additional network traffic, which may affect the communication quality. We do not recommend calling this method together with [startLastmileProbeTest]([AgoraRtcEngineKit startLastmileProbeTest:]). + + Call the [disableLastmileTest](disableLastmileTest) method to disable this test after receiving the [lastmileQuality]([AgoraRtcEngineDelegate rtcEngine:lastmileQuality:]) callback, and before the user joins the channel or switches the user role. + + **Note:** + + - Do not call any other methods before receiving the [lastmileQuality]([AgoraRtcEngineDelegate rtcEngine:lastmileQuality:]) callback. Otherwise, the callback may be interrupted by other methods and may not execute. + + - In the interactive live streaming profile, a host should not call this method after joining a channel. + - If you call this method to test the last mile quality, the SDK consumes the bandwidth of a video stream, whose bitrate corresponds to the bitrate you set in the [setVideoEncoderConfiguration]([AgoraRtcEngineKit setVideoEncoderConfiguration:]) method. After you join the channel, whether you have called the `disableLastmileTest` method or not, the SDK automatically stops consuming the bandwidth. + + @return * 0: Success. +* < 0: Failure. + */ +- (int)enableLastmileTest; + +/** Disables the network connection quality test. + + @return * 0: Success. +* < 0: Failure. + */ +- (int)disableLastmileTest; + +/** Starts the last-mile network probe test. + + +Starts the last-mile network probe test before joining a channel to get the uplink and downlink last-mile network statistics, including the bandwidth, packet loss, jitter, and round-trip time (RTT). + +Call this method to check the uplink network quality before users join a channel or before an audience switches to a host. + +Once this method is enabled, the SDK returns the following callbacks: + +- [lastmileQuality]([AgoraRtcEngineDelegate rtcEngine:lastmileQuality:]): the SDK triggers this callback within two seconds depending on the network conditions. This callback rates the network conditions and is more closely linked to the user experience. +- [lastmileProbeResult]([AgoraRtcEngineDelegate rtcEngine:lastmileProbeTestResult:])the SDK triggers this callback within 30 seconds depending on the network conditions. This callback returns the real-time statistics of the network conditions and is more objective. + +**Note:** + +- This method consumes extra network traffic and may affect communication quality. We do not recommend calling this method together with [enableLastmileTest]([AgoraRtcEngineKit enableLastmileTest]). +- Do not call other methods before receiving the [lastmileQuality]([AgoraRtcEngineDelegate rtcEngine:lastmileQuality:]) and [lastmileProbeResult]([AgoraRtcEngineDelegate rtcEngine:lastmileProbeTestResult:]) callbacks. Otherwise, the callbacks may be interrupted. +- In the interactive live streaming profile, a host should not call this method after joining a channel. + +@param config The configurations of the last-mile network probe test, see [AgoraLastmileProbeConfig](AgoraLastmileProbeConfig). + +@return * 0: Success. +* < 0: Failure. +*/ +- (int)startLastmileProbeTest:(AgoraLastmileProbeConfig* _Nullable)config; + +/** Stops the last-mile network probe test. + +@return * 0: Success. +* < 0: Failure. +*/ +- (int)stopLastmileProbeTest; + +#pragma mark Custom Video Module + +/**----------------------------------------------------------------------------- + * @name Custom Video Module + * ----------------------------------------------------------------------------- + */ + +/** Sets the video source. + + In real-time communications, the SDK uses the default video input source (the built-in camera) to publish streams. To use an external video source, call AgoraVideoSourceProtocol to set the custom video source and then use this method to add the external video source into the SDK. + + You can call this method either before or after joining a channel. + + @param videoSource AgoraVideoSourceProtocol + */ +- (void)setVideoSource:(id _Nullable)videoSource; + +/** Sets the local video renderer. + + In real-time communications, the SDK uses the default video renderer to render the video. To use an external video renderer, call AgoraVideoSinkProtocol to set the custom local video renderer and then use this method to add the external renderer into the SDK. + + You can call this method either before or after joining a channel. + + @param videoRenderer Sets the local video renderer. See AgoraVideoSinkProtocol. + */ +- (void)setLocalVideoRenderer:(id _Nullable)videoRenderer; + +/** Sets the remote video renderer. + + This method sets the remote renderer. In real-time communications, the SDK uses the default video renderer to render the video. To use an external video renderer, call AgoraVideoSinkProtocol to set the custom remote video renderer and then use this method to add the external renderer into the SDK. + + You can call this method either before or after joining a channel. If you call it before joining a channel, you need to maintain the `uid` of the remote user on your app level. + + @param videoRenderer Sets the video renderer of the remote user. See AgoraVideoSinkProtocol. + @param userId ID of the remote user. + */ +- (void)setRemoteVideoRenderer:(id _Nullable)videoRenderer forUserId:(NSUInteger)userId; + +/** Gets the video source. + + @return Video source. See AgoraVideoSourceProtocol. + */ +- (id _Nullable)videoSource; + +/** Gets the local video renderer. + + @return Local video renderer. See AgoraVideoSinkProtocol. + */ +- (id _Nullable)localVideoRenderer; + +/** Gets the video renderer of a specified remote user. + + @param userId ID of the remote user. + @return Video renderer of the remote user. See AgoraVideoSinkProtocol. + */ +- (id _Nullable)remoteVideoRendererOfUserId:(NSUInteger)userId; + +/** Registers a raw video frame protocol. + + @since v3.4.5 + + After you successfully register the raw video frame protocol, the SDK triggers + the callbacks that you have implemented in AgoraVideoDataFrameProtocol each + time a video frame is received. + + **Note**: + + - This method applies to iOS only. + - Ensure that you call this method before joining a channel. + - The width and height of the video obtained through the protocol may change + due to poor network conditions and user-adjusted resolution. + + @param videoData The raw video frame. See AgoraVideoDataFrameProtocol. If + `nil` is passed, the protocol registration is canceled. + */ +- (void)setVideoDataFrame:(id _Nullable)videoData; + +/** Registers a local encoded video frame protocol. + + @since v3.4.5 + + After you successfully register the local encoded video frame protocol, the + SDK triggers the callbacks that you have implemented in + AgoraVideoEncodedFrameProtocol each time a video frame is received. + + **Note**: + + - This method applies to iOS only. + - Ensure that you call this method before joining a channel. + - The width and height of the video obtained through the protocol may change + due to poor network conditions and user-adjusted resolution. + + @param videoEncode The local encoded video frame protocol. + See AgoraVideoEncodedFrameProtocol. If `nil` is passed, the protocol + registration is canceled. + */ +- (void)setVideoEncodedFrame:(id _Nullable)videoEncode; + +#pragma mark External Audio Data + +/**----------------------------------------------------------------------------- + * @name External Audio Sink + * ----------------------------------------------------------------------------- + */ + +/** Enables the external audio sink. + + This method applies to scenarios where you want to use external audio data for playback. After enabling the external audio sink, you can call the [pullPlaybackAudioFrameRawData]([AgoraRtcEngineKit pullPlaybackAudioFrameRawData:lengthInByte:]) / [pullPlaybackAudioFrameSampleBufferByLengthInByte]([AgoraRtcEngineKit pullPlaybackAudioFrameSampleBufferByLengthInByte:]) method to pull the remote audio data, process it, and play it with the audio effects that you want. + + Ensure that you call this method before joining a channel. + + @param sampleRate Sets the sample rate (Hz) of the external audio sink. You can set this parameter as 16000, 32000, 44100 or 48000. + @param channels Sets the number of audio channels of the external audio sink: + + - 1: Mono + - 2: Stereo + + @note Once you enable the external audio sink, the app will not retrieve any audio data from the `onPlaybackAudioFrame` callback. + */ +- (void)enableExternalAudioSink:(NSUInteger)sampleRate channels:(NSUInteger)channels; + +/** Disables the external audio sink. + */ +- (void)disableExternalAudioSink; + +/** Pulls the remote audio data in the RawData format. + + Before calling this method, call the [enableExternalAudioSink]([AgoraRtcEngineKit enableExternalAudioSink:channels:]) method to enable and set the external audio sink. + + After a successful method call, the app pulls the decoded and mixed audio data for playback. + + **Note** + + - Ensure that you call this method after joining a channel. Once you call the [pullPlaybackAudioFrameRawData]([AgoraRtcEngineKit pullPlaybackAudioFrameRawData:lengthInByte:]) method successfully, the app will not retrieve any audio data from the `onPlaybackAudioFrame` callback. + - The difference between the `onPlaybackAudioFrame` callback and the `pullPlaybackAudioFrameRawData` method is as follows: + - `onPlaybackAudioFrame`: The SDK sends the audio data to the app through this callback. Any delay in processing the audio frames may result in audio jitter. + - `pullPlaybackAudioFrameRawData`: The app pulls the remote audio data autonomously. After setting the audio data parameters, the SDK adjusts the frame buffer and avoids problems caused by jitter in the external audio playback. + + @param data The audio data that you want to pull. The data format is in byte[]. + @param lengthInByte The data length (byte) of the external audio data. The value of this parameter is related to the audio duration, and the values of the `sampleRate` and `channels` parameters that you set in [enableExternalAudioSink]([AgoraRtcEngineKit enableExternalAudioSink:channels:]). Agora recommends setting the audio duration no shorter than 10 ms. The formula for `lengthInByte` is as follows: `lengthInByte` = `sampleRate` / 1000 × 2 × `channels` × audio duration (ms). + + @return - YES: Success. + - NO: Failure. + */ +- (BOOL)pullPlaybackAudioFrameRawData:(void* _Nonnull)data lengthInByte:(NSUInteger)lengthInByte; + +/** Pulls the remote audio data in the SampleBuffer format. + + Before calling this method, call the [enableExternalAudioSink]([AgoraRtcEngineKit enableExternalAudioSink:channels:]) method to enable and set the external audio sink. + + After a successful method call, the app pulls the decoded and mixed audio data for playback. + + **Note** + + - Ensure that you call this method after joining a channel. Once you call the [pullPlaybackAudioFrameSampleBufferByLengthInByte]([AgoraRtcEngineKit pullPlaybackAudioFrameSampleBufferByLengthInByte:]) method successfully, the app will not retrieve any audio data from the `onPlaybackAudioFrame` callback. + - The difference between the `onPlaybackAudioFrame` callback and the `pullPlaybackAudioFrameSampleBufferByLengthInByte` method is as follows: + - `onPlaybackAudioFrame`: The SDK sends the audio data to the app through this callback. Any delay in processing the audio frames may result in audio jitter. + - `pullPlaybackAudioFrameSampleBufferByLengthInByte`: The app pulls the remote audio data. After setting the audio data parameters, the SDK adjusts the frame buffer and avoids problems caused by jitter in the external audio playback. + + @param lengthInByte The data length (byte) of the external audio data. The value of this parameter is related to the audio duration, and the values of the `sampleRate` and `channels` parameters that you set in [enableExternalAudioSink]([AgoraRtcEngineKit enableExternalAudioSink:channels:]). This parameter should be divisible by the value of `sampleRate`, and Agora recommends setting the audio duration no shorter than 10 ms. The formula for `lengthInByte` is as follows: `lengthInByte` = `sampleRate` / 1000 × 2 × `channels` × audio duration (ms). + - This parameter should be divisible by the value of sampleRate. + + @return - YES: Success. + - NO: Failure. + */ +- (CMSampleBufferRef _Nullable)pullPlaybackAudioFrameSampleBufferByLengthInByte:(NSUInteger)lengthInByte; + +/**----------------------------------------------------------------------------- + * @name External Audio Data (push-mode only) + * ----------------------------------------------------------------------------- + */ + +/** Enables the external audio source. + + Call this method before [joinChannelByToken]([AgoraRtcEngineKit joinChannelByToken:channelId:info:uid:joinSuccess:]) and [startPreview]([AgoraRtcEngineKit startPreview]). + + @param sampleRate Sets the sample rate (Hz) of the external audio source: 8000, 16000, 44100, or 48000 Hz. + @param channelsPerFrame Sets the number of external audio source channels: + + - 1: Mono. + - 2: Stereo. + */ +- (void)enableExternalAudioSourceWithSampleRate:(NSUInteger)sampleRate channelsPerFrame:(NSUInteger)channelsPerFrame; + +/** Disables the external audio source. + */ +- (void)disableExternalAudioSource; + +/** Sets the volume of the external audio frame in the specified position. + + @since v3.5.1 + + You can call this method multiple times to set the volume of external audio + frames in different positions. The volume setting takes effect for all + external audio frames that are pushed to the specified position. + + @note Call this method after joining a channel. + + @param sourcePos The push position of the external audio frame. See AgoraAudioExternalSourcePos. + @param volume The volume of the external audio frame. + The value range is [0,100]. The default value is 100, which + represents the original value. +*/ +- (void)setExternalAudioSourceVolume:(AgoraAudioExternalSourcePos)sourcePos volume:(NSUInteger)volume; + +/** Pushes the external raw audio frame to a specified position. + + @since v3.5.1 + + According to your needs, you can push the external audio frame to one of three + positions: after audio capture, before audio encoding, or before local playback. + You can call this method multiple times to push one audio frame to multiple + positions or multiple audio frames to different positions. For example, in + the KTV scenario, you can push the singing voice to after audio capture, so + that the singing voice can be processed by the SDK audio module and you can + obtain a high-quality audio experience; you can also push the accompaniment to + before audio encoding, so that the accompaniment is not affected by the audio + module of the SDK. + + @note Call this method after joining a channel. + + @param sourcePos The push position of the external audio frame. + See AgoraAudioExternalSourcePos. + @param frame The audio frame. See AgoraAudioFrame. The value range of the + audio frame length (ms) is [10,60]. + + @return * 0: Success. + * < 0: Failure. + + - -2 (`AgoraErrorCodeInvalidArgument`): The parameter is invalid. + - -12 (`AgoraErrorCodeTooOften`): The call frequency is too high, causing the + internal buffer to overflow. Call this method again after 30-50 ms. + */ +- (int)pushExternalAudioFrameRawData:(AgoraAudioExternalSourcePos)sourcePos frame:(AgoraAudioFrame* _Nonnull)frame; + +/** Pushes the external CMSampleBuffer audio frame to a specified position. + + @since v3.5.1 + + According to your needs, you can push the external audio frame to one of three + positions: after audio capture, before audio encoding, or before local playback. + You can call this method multiple times to push one audio frame to multiple + positions or multiple audio frames to different positions. For example, in + the KTV scenario, you can push the singing voice to after audio capture, so + that the singing voice can be processed by the SDK audio module and you can + obtain a high-quality audio experience; you can also push the accompaniment to + before audio encoding, so that the accompaniment is not affected by the audio + module of the SDK. + + @note Call this method after joining a channel. + + @param sourcePos The push position of the external audio frame. + See AgoraAudioExternalSourcePos. + @param sampleBuffer The sample buffer. The value range of the + sample buffer length (ms) is [10,60]. + + @return * 0: Success. + * < 0: Failure. + + - -2 (`AgoraErrorCodeInvalidArgument`): The parameter is invalid. + - -12 (`AgoraErrorCodeTooOften`): The call frequency is too high, causing the + internal buffer to overflow. Call this method again after 30-50 ms. + */ +- (int)pushExternalAudioFrameSampleBuffer:(AgoraAudioExternalSourcePos)sourcePos sampleBuffer:(CMSampleBufferRef _Nonnull)sampleBuffer; + +#pragma mark External Video Data + +/**----------------------------------------------------------------------------- + * @name External Video Data (push-mode only) + * ----------------------------------------------------------------------------- + */ + +/** Configures the external video source. + + @note Call this method before joining a channel. + + @param enable Sets whether to use an external video source: + + * YES: Use an external video source. + * NO: (Default) Do not use an external video source. + + @param useTexture Sets whether to use texture as an input: + + * YES: Use texture as an input. + * NO: Do not use texture as an input. + + @param pushMode Sets whether or not the external video source needs to call the [pushExternalVideoFrame](pushExternalVideoFrame:) method to send the video frame to the SDK: + + * YES: Use the push mode. + * NO: Use the pull mode (not supported yet). + */ +- (void)setExternalVideoSource:(BOOL)enable useTexture:(BOOL)useTexture pushMode:(BOOL)pushMode; + +/** Pushes the external video frame. + + This method pushes the video frame using the AgoraVideoFrame class and passes the video frame to the SDK with the `format` parameter found in AgoraVideoFrame. + Call the [setExternalVideoSource](setExternalVideoSource:useTexture:pushMode:) method and set the `pushMode` parameter as `YES` before calling this method. Otherwise, a failure returns after calling this method. + + @note The SDK does not support the alpha channel, and discards any alpha value passed to the SDK. + + @param frame Video frame containing the SDK's encoded video data to be pushed. See AgoraVideoFrame. + @return * YES: The frame is pushed successfully. + * NO: Fails to push the frame. + */ +- (BOOL)pushExternalVideoFrame:(AgoraVideoFrame* _Nonnull)frame; + +#pragma mark Raw Audio Data + +/**----------------------------------------------------------------------------- + * @name Raw Audio Data + * ----------------------------------------------------------------------------- + */ + +/** Sets the audio sampling format. + +This method sets the audio format of the `onRecordAudioFrame` callback. See *Raw Audio Data*. + +Ensure that you call this method before joining a channel. + +@note The SDK calculates the sample interval according to the value of the `sampleRate`, `channel`, and `samplesPerCall` parameters you set in this method. Sample interval (sec) = `samplePerCall`/(`sampleRate` * `channel`). Ensure that the value of sample interval is no less than 0.01. The SDK triggers the `onRecordAudioFrame` callback according to the sample interval. + + @param sampleRate Sets the audio sample rate (`samplesPerSec`) returned in the `onRecordAudioFrame` callback, which can be set as 8000, 16000, 32000, 44100, or 48000 Hz. + @param channel Sets the number of audio channels (`channels`) returned in the `onRecordAudioFrame` callback, which can be set as 1 or 2: + +- 1: Mono +- 2: Stereo + @param mode Sets the use mode of the `onRecordAudioFrame` callback. See AgoraAudioRawFrameOperationMode. + @param samplesPerCall Sets the number of samples the `onRecordAudioFrame` callback returns. Set it as 1024 for RTMP or RTMPS streaming. + + + @return * 0: Success. + * < 0: Failure. + */ +- (int)setRecordingAudioFrameParametersWithSampleRate:(NSInteger)sampleRate channel:(NSInteger)channel mode:(AgoraAudioRawFrameOperationMode)mode samplesPerCall:(NSInteger)samplesPerCall; +/** Sets the audio playback format. + +This method sets the audio format of the `onPlaybackAudioFrame` callback. See *Raw Audio Data*. + +Ensure that you call this method before joining a channel. + +@note The SDK calculates the sample interval according to the value of the `sampleRate`, `channel`, and `samplesPerCall` parameters you set in this method. Sample interval (sec) = `samplePerCall`/(`sampleRate` * `channel`). Ensure that the value of sample interval is no less than 0.01. The SDK triggers the `onPlaybackAudioFrame` callback according to the sample interval. + + @param sampleRate Sets the sample rate (`samplesPerSec`) returned in the `onPlaybackAudioFrame` callback, which can be set as 8000, 16000, 32000, 44100, or 48000 Hz. + @param channel Sets the number of audio channels (`channels`) returned in the `onPlaybackAudioFrame` callback, which can be set as 1 or 2: + + * 1: Mono + * 2: Stereo + @param mode Sets the use mode of the `onPlaybackAudioFrame` callback. See AgoraAudioRawFrameOperationMode. + @param samplesPerCall Sets the number of samples the `onPlaybackAudioFrame` callback returns. Set it as 1024 for RTMP or RTMPS streaming. + + @return * 0: Success. + * < 0: Failure. + */ +- (int)setPlaybackAudioFrameParametersWithSampleRate:(NSInteger)sampleRate channel:(NSInteger)channel mode:(AgoraAudioRawFrameOperationMode)mode samplesPerCall:(NSInteger)samplesPerCall; + +/** Sets the format of the mixed sampled and playback audio frame. + +This method sets the audio format of the `onMixedAudioFrame` callback. See *Raw Audio Data*. + +Ensure that you call this method before joining a channel. + +@note The SDK calculates the sample interval according to the value of the `sampleRate`, `channel`, and `samplesPerCall` parameters you set in this method. Sample interval (sec) = `samplePerCall`/(`sampleRate` * `channel`). Ensure that the value of sample interval is no less than 0.01. The SDK triggers the `onMixedAudioFrame` callback according to the sample interval. + + @param sampleRate Sets the sample rate (`samplesPerSec`) returned in the `onMixedAudioFrame` callback, which can be set as 8000, 16000, 32000, 44100, or 48000 Hz. + @param samplesPerCall Sets the number of samples the `onMixedAudioFrame` callback returns. Set it as 1024 for RTMP or RTMPS streaming. + + @return * 0: Success. +* < 0: Failure. + */ +- (int)setMixedAudioFrameParametersWithSampleRate:(NSInteger)sampleRate samplesPerCall:(NSInteger)samplesPerCall; + +/** Registers the raw audio data protocol. + + @since v3.4.5 + + For the SDK to trigger the callbacks that provide the raw audio data, call this + method to register the audio frame delegate. You need to implement + `AgoraAudioDataFrameProtocol` in this method. + + **Note** + + - Ensure that you call this method before joining a channel. + - To release the audio frame delegate, pass `nil` in the `delegate` parameter. + Agora recommends calling `setAudioDataFrame(nil)` after + receiving the + [didLeaveChannelWithStats]([AgoraRtcEngineDelegate rtcEngine:didLeaveChannelWithStats:]) callback. + + @param delegate The delegate of the audio frame. See AgoraAudioDataFrameProtocol. + + @return * YES: Success. + * NO: Failure. + */ +- (BOOL)setAudioDataFrame:(id _Nullable)delegate; + +#pragma mark Watermark + +/**----------------------------------------------------------------------------- + * @name Watermark + * ----------------------------------------------------------------------------- + */ + +/** Adds a watermark image to the local video. + + This method adds a PNG watermark image to the local video in the interactive live streaming. Once the watermark image is added, all the audience in the channel (CDN audience included), and the capturing device can see and capture it. Agora supports adding only one watermark image onto the local video, and the newly watermark image replaces the previous one. + + The watermark position depends on the settings in the [setVideoEncoderConfiguration]([AgoraRtcEngineKit setVideoEncoderConfiguration:]) method: + + - If the orientation mode of the encoding video is AgoraVideoOutputOrientationModeFixedLandscape, or the landscape mode in AgoraVideoOutputOrientationModeAdaptative, the watermark uses the landscape orientation. + - If the orientation mode of the encoding video is AgoraVideoOutputOrientationModeFixedPortrait, or the portrait mode in AgoraVideoOutputOrientationModeAdaptative, the watermark uses the portrait orientation. + - When setting the watermark position, the region must be less than the dimensions set in the [setVideoEncoderConfiguration]([AgoraRtcEngineKit setVideoEncoderConfiguration:]) method. Otherwise, the watermark image will be cropped. + + **Note** + + - Ensure that you have called the [enableVideo]([AgoraRtcEngineKit enableVideo]) method to enable the video module before calling this method. + - If you only want to add a watermark image to the local video for the audience in the CDN live streaming channel to see and capture, you can call this method or the [setLiveTranscoding]([AgoraRtcEngineKit setLiveTranscoding:]) method. + - This method supports adding a watermark image in the PNG file format only. Supported pixel formats of the PNG image are RGBA, RGB, Palette, Gray, and Alpha_gray. + - If the dimensions of the PNG image differ from your settings in this method, the image will be cropped or zoomed to conform to your settings. + - If you have enabled the local video preview by calling the [startPreview]([AgoraRtcEngineKit startPreview]) method, you can use the `visibleInPreview` member in the WatermarkOptions class to set whether or not the watermark is visible in preview. + - If you have enabled the mirror mode for the local video, the watermark on the local video is also mirrored. To avoid mirroring the watermark, Agora recommends that you do not use the mirror and watermark functions for the local video at the same time. You can implement the watermark function in your application layer. + + @param url The local file path of the watermark image to be added. This method supports adding a watermark image from the local file path. If the watermark image to be added is in the project file, you need to change the image's Type from PNG image to Data in the Xcode property, otherwise, the Agora Native SDK cannot recognize the image. + @param options The options of the watermark image to be added. See WatermarkOptions. + + @return * 0: Success. + * < 0: Failure. + */ +- (int)addVideoWatermark:(NSURL* _Nonnull)url options:(WatermarkOptions* _Nonnull)options; + +/** Removes the watermark image from the video stream added by [addVideoWatermark]([AgoraRtcEngineKit addVideoWatermark:options:]). + + @return * 0: Success. +* < 0: Failure. + */ +- (int)clearVideoWatermarks; + +#pragma mark Stream Fallback + +/**----------------------------------------------------------------------------- + * @name Stream Fallback + * ----------------------------------------------------------------------------- + */ + +/** Sets the priority of a remote user's stream. + +The SDK ensures the high-priority user gets the best possible stream quality. + +**Note:** + +The SDK supports setting userPriority as high for one user only. + + @param uid The ID of the remote user. + @param userPriority The priority of the remote user, see [AgoraUserPriority](AgoraUserPriority). + @return * 0: Success. + * <0: Failure. + */ +- (int)setRemoteUserPriority:(NSUInteger)uid type:(AgoraUserPriority)userPriority; + +/** Sets the fallback option for the locally published video stream based on the network conditions. + +The default setting for `option` is `AgoraStreamFallbackOptionDisabled`, where there is no fallback behavior for the locally published video stream when the uplink network conditions are unreliable. + +If `option` is set as `AgoraStreamFallbackOptionAudioOnly`, the SDK will: + + * Disable the upstream video but enable audio only when the network conditions deteriorate and cannot support both video and audio. + * Re-enable the video when the network conditions improve. + + When the published video stream falls back to audio only or when the audio-only stream switches back to the video, the SDK triggers the [didLocalPublishFallbackToAudioOnly]([AgoraRtcEngineDelegate rtcEngine:didLocalPublishFallbackToAudioOnly:]) callback. + + Ensure that you call this method before joining a channel. + + **Note:** + + Agora does not recommend using this method for CDN live streaming, because the remote CDN live user will have a noticeable lag when the published video stream falls back to audio-only. + + @param option Sets the fallback option for the published video stream. The default value is AgoraStreamFallbackOptionDisabled. See AgoraStreamFallbackOptions. + @return * 0: Success. +* < 0: Failure. + */ +- (int)setLocalPublishFallbackOption:(AgoraStreamFallbackOptions)option; + +/** Sets the fallback option for the remotely subscribed video stream based on the network conditions. + +The default setting for `option` is `AgoraStreamFallbackOptionVideoStreamLow`, where the remotely subscribed video stream falls back to the low-stream (low resolution and low bitrate) video under unreliable downlink network conditions. + +If `option` is set as `AgoraStreamFallbackOptionAudioOnly`, the SDK automatically switches the video from a high stream to a low stream, or disables the video when the downlink network conditions cannot support both audio and video to guarantee the quality of the audio. The SDK monitors the network quality and re-enables the video stream when the network conditions improve. + When the remotely subscribed video stream falls back to audio only or when the audio-only stream switches back to the video, the SDK triggers the [didRemoteSubscribeFallbackToAudioOnly]([AgoraRtcEngineDelegate rtcEngine:didRemoteSubscribeFallbackToAudioOnly:byUid:]) callback. + +Ensure that you call this method before joining a channel. + + @param option Sets the fallback option for the remotely subscribed video stream. The default value is `AgoraStreamFallbackOptionVideoStreamLow`. See AgoraStreamFallbackOptions. + @return * 0: Success. +* < 0: Failure. + */ +- (int)setRemoteSubscribeFallbackOption:(AgoraStreamFallbackOptions)option; + +#pragma mark Dual-stream Mode + +/**----------------------------------------------------------------------------- + * @name Dual-stream Mode + * ----------------------------------------------------------------------------- + */ + +/** Enables/Disables dual-stream mode. (Interactive live streaming only.) + +If dual-stream mode is enabled, the receiver can choose to receive the high-stream (high-resolution high-bitrate) or low-stream (low-resolution low-bitrate) video. + +You can call this method either before or after joining a channel. + + @param enabled Sets the stream mode: + + * YES: Dual-stream mode. + * NO: Single-stream mode. + + @return * 0: Success. +* < 0: Failure. + */ +- (int)enableDualStreamMode:(BOOL)enabled; + +/** Sets the stream type of the remote video. + + Under limited network conditions, if the publisher has not disabled the dual-stream mode using [enableDualStreamMode(NO)]([AgoraRtcEngineKit enableDualStreamMode:])enableDualStreamMode(NO), the receiver can choose to receive either the high-quality video stream (the high resolution, and high bitrate video stream) or the low-quality video stream (the low resolution, and low bitrate video stream). + + By default, users receive the high-quality video stream. Call this method if you want to switch the remote stream type to reduce the bandwidth and resources. + + The aspect ratio of the low-quality video stream is the same as the high-quality video stream. Once the resolution of the high-quality video stream is set, the system automatically sets the resolution, frame rate, and bitrate of the low-quality video stream. + + The SDK reports the result of calling this method in the [didApiCallExecute]([AgoraRtcEngineDelegate rtcEngine:didApiCallExecute:api:result:]) callback. + + @note You can call this method either before or after joining a channel. If you call both `setRemoteVideoStream` and [setRemoteDefaultVideoStreamType]([AgoraRtcEngineKit setRemoteDefaultVideoStreamType:]), the SDK applies the settings in the `setRemoteVideoStream` method. + + @param uid ID of the remote user sending the video stream. + @param streamType Sets the video-stream type. See AgoraVideoStreamType. + + @return * 0: Success. +* < 0: Failure. + */ +- (int)setRemoteVideoStream:(NSUInteger)uid type:(AgoraVideoStreamType)streamType; + +/** Sets the default video-stream type for the video received by the local user when the remote user sends dual streams. + + @note You can call this method either before or after joining a channel. If you call both `setRemoteDefaultVideoStreamType` and [setRemoteVideoStream]([AgoraRtcEngineKit setRemoteVideoStream:type:]), the SDK applies the settings in the `setRemoteDefaultVideoStreamType` method. + + @param streamType Sets the default video-stream type. See AgoraVideoStreamType. + + @return * 0: Success. +* < 0: Failure. + */ +- (int)setRemoteDefaultVideoStreamType:(AgoraVideoStreamType)streamType; + +#pragma mark Encryption + +/**----------------------------------------------------------------------------- + * @name Encryption + * ----------------------------------------------------------------------------- + */ + +/** Enables/Disables the built-in encryption. + + @since v3.1.0 + + In scenarios requiring high security, Agora recommends calling + `enableEncryption` to enable the built-in encryption before joining a channel. + + After a user leaves the channel, the SDK automatically disables the built-in + encryption. To re-enable the built-in encryption, call this method before the + user joins the channel again. + + As of v3.4.5, Agora recommends using either the `AgoraEncryptionModeAES128GCM2` + or `AgoraEncryptionModeAES256GCM2` encryption mode, both of which support + adding a salt and are more secure. For details, see *Media Stream Encryption*. + + @warning All users in the same channel must use the same encryption mode, + encryption key, and salt; otherwise, users cannot communicate with each other. + + **Note**: + + - If you enable the built-in encryption, you cannot use the RTMP or RTMPS + streaming function. + - To enhance security, Agora recommends using a new key and salt every time + you enable the media stream encryption. + + @param enabled Whether to enable the built-in encryption: + + - YES: Enable the built-in encryption. + - NO: Disable the built-in encryption. + + @param config Configurations of built-in encryption schemas. See AgoraEncryptionConfig. + + @return - 0: Success. + - < 0: Failure. + + - -2 (`AgoraErrorCodeInvalidArgument`): An invalid parameter is used. Set the parameter with a valid value. + - -7 (`AgoraErrorCodeNotInitialized`): The SDK is not initialized. Initialize the `AgoraRtcEngineKit` instance before calling this method. + - -4 (`AgoraErrorCodeNotSupported`): The encryption mode is incorrect or the SDK fails to load the external encryption library. Check the enumeration or reload the external encryption library. + */ +- (int)enableEncryption:(bool)enabled encryptionConfig:(AgoraEncryptionConfig* _Nonnull)config; + +#pragma mark Inject an Online Media Stream + +/**----------------------------------------------------------------------------- + * @name Inject an Online Media Stream + * ----------------------------------------------------------------------------- + */ + +/** Adds a voice or video stream CDN streaming URL to the interactive live streaming. + + The [streamPublishedWithUrl]([AgoraRtcEngineDelegate rtcEngine:streamPublishedWithUrl:errorCode:]) callback returns the inject stream status. + + If this method call is successful, the server pulls the voice or video stream and injects it into a live channel. This is applicable to scenarios where all audience members in the channel can watch a live show and interact with each other. + + The `addInjectStreamUrl` method call triggers the following callbacks: + + - The local client: + + - [streamInjectedStatusOfUrl]([AgoraRtcEngineDelegate rtcEngine:streamInjectedStatusOfUrl:uid:status:]), with the state of the injecting the online stream. + - [didJoinedOfUid]([AgoraRtcEngineDelegate rtcEngine:didJoinedOfUid:elapsed:])(uid: 666), if the method call is successful and the online media stream is injected into the channel. + + - The remote client: + + - [didJoinedOfUid]([AgoraRtcEngineDelegate rtcEngine:didJoinedOfUid:elapsed:])(uid: 666), if the method call is successful and the online media stream is injected into the channel. + + + @warning Agora will soon stop the service for injecting online media streams on the client. If you have not implemented this service, Agora recommends that you do not use it. + + **Note:** + + - Ensure that you call this method after joining a channel. + - You can inject only one media stream into the channel at the same time. + - Ensure that you enable the RTMP Converter service before using this function. See [Prerequisites](https://docs.agora.io/en/Interactive%20Broadcast/cdn_streaming_apple?platform=iOS#prerequisites). + - This method applies to the Native SDK v2.4.1 and later. + @param url URL address to be added to the ongoing interactive live streaming. Valid protocols are RTMP, HLS, and HTTP-FLV. + +- Supported audio codec type: AAC. +- Supported video codec type: H264 (AVC). + @param config AgoraLiveInjectStreamConfig object which contains the configuration information for the added voice or video stream. + +@return * 0: Success. +* < 0: Failure. + - `AgoraErrorCodeInvalidArgument`(-2): The injected URL does not exist. Call this method again to inject the stream and ensure that the URL is valid. + - `AgoraErrorCodeNotReady`(-3): The user is not in the channel. + - `AgoraErrorCodeNotSupported`(-4): The channel profile is not Live Broadcast. Call the [setChannelProfile]([AgoraRtcEngineKit setChannelProfile:]) method and set the channel profile to Live Broadcast before calling this method. + - `AgoraErrorCodeNotInitialized`(-7): The SDK is not initialized. Ensure that the RtcEngine object is initialized before using this method. + +*/ +- (int)addInjectStreamUrl:(NSString* _Nonnull)url config:(AgoraLiveInjectStreamConfig* _Nonnull)config; + +/** Removes the voice or video stream CDN streaming URL from the interactive live streaming. + + This method removes the URL address (added by the [addInjectStreamUrl](addInjectStreamUrl:config:) method) from the interactive live streaming. + + If this method call is successful, the SDK triggers the [didOfflineOfUid]([AgoraRtcEngineDelegate rtcEngine:didOfflineOfUid:reason:]) callback and returns a stream uid of 666. + + @warning Agora will soon stop the service for injecting online media streams on the client. If you have not implemented this service, Agora recommends that you do not use it. + + @param url URL address of the added stream to be removed. + @return * 0: Success. + * < 0: Failure. + */ +- (int)removeInjectStreamUrl:(NSString* _Nonnull)url; + +#pragma mark CDN Live Streaming + +/**----------------------------------------------------------------------------- + * @name CDN Live Streaming + * ----------------------------------------------------------------------------- + */ + +/** Publishes the local stream to a specified CDN streaming URL. + + After calling this method, you can push media streams in RTMP or RTMPS protocol to the CDN. The SDK triggers the [rtmpStreamingChangedToState]([AgoraRtcEngineDelegate rtcEngine:rtmpStreamingChangedToState:state:errorCode:]) callback on the local client to report the state of adding a local stream to the CDN. + + **Note:** + + - This method applies to the interactive live streaming profile only. + - Ensure that the user joins the channel before calling this method. + - Ensure that you enable the RTMP Converter service before using this function. See [Prerequisites](https://docs.agora.io/en/Interactive%20Broadcast/cdn_streaming_apple?platform=iOS#prerequisites). + - This method adds only one stream URL each time it is called. + - Agora supports pushing media streams in RTMPS protocol to the CDN only when you enable transcoding. + + @param url The CDN streaming URL in the RTMP or RTMPS format. The maximum length of this parameter is 1024 bytes. The CDN streaming URL must not contain special characters, such as Chinese language characters. + @param transcodingEnabled Sets whether transcoding is enabled/disabled: + + - YES: Enable transcoding. To [transcode](https://docs.agora.io/en/Agora%20Platform/terms?platform=All%20Platforms#transcoding) the audio or video streams when publishing them to CDN live, often used for combining the audio and video streams of multiple hosts in CDN live. If you set this parameter as `YES`, ensure that you call the [setLiveTranscoding]([AgoraRtcEngineKit setLiveTranscoding:]) method before this method. + - NO: Disable transcoding. + + @return * 0: Success. + * < 0: Failure. + + - `AgoraErrorCodeInvalidArgument`(-2): Invalid parameter. The URL is nil or the string length is 0. + - `AgoraErrorCodeNotInitialized`(-7): You have not initialized the RTC Engine when publishing the stream. + */ +- (int)addPublishStreamUrl:(NSString* _Nonnull)url transcodingEnabled:(BOOL)transcodingEnabled; + +/** Removes an RTMP or RTMPS stream from the CDN. + +This method removes the CDN streaming URL added by the [addPublishStreamUrl](addPublishStreamUrl:transcodingEnabled:) method from a CDN live stream. + +This method call triggers the [rtmpStreamingChangedToState]([AgoraRtcEngineDelegate rtcEngine:rtmpStreamingChangedToState:state:errorCode:]) callback on the local client to report the state of removing an RTMP or RTMPS stream from the CDN. + + **Note:** + + * This method applies to the interactive live streaming profile only. + * This method removes only one URL each time it is called. + * The URL must not contain special characters, such as Chinese language characters. + + @param url The CDN streaming URL to be removed. The maximum length of this parameter is 1024 bytes. + + @return * 0: Success. + * < 0: Failure. + */ +- (int)removePublishStreamUrl:(NSString* _Nonnull)url; + +/** Sets the video layout and audio settings for CDN live. (CDN live only.) + + The SDK triggers the [rtcEngineTranscodingUpdated]([AgoraRtcEngineDelegate rtcEngineTranscodingUpdated:]) callback when you call the `setLiveTranscoding` method to update the transcoding setting. + + **Note** + + - Ensure that you call this method after joining a channel. + - This method applies to the interactive live streaming profile only. + - Ensure that you enable the RTMP Converter service before using this function. See [Prerequisites](https://docs.agora.io/en/Interactive%20Broadcast/cdn_streaming_apple?platform=iOS#prerequisites). + - If you call the `setLiveTranscoding` method to update the transcoding setting for the first time, the SDK does not trigger the `rtcEngineTranscodingUpdated` callback. + - Agora supports pushing media streams in RTMPS protocol to the CDN only when you enable transcoding. + + @param transcoding Sets the CDN live audio/video transcoding settings. See AgoraLiveTranscoding. + + @return * 0: Success. + * < 0: Failure. + */ +- (int)setLiveTranscoding:(AgoraLiveTranscoding* _Nullable)transcoding; + +#pragma mark Data Stream + +/**----------------------------------------------------------------------------- + * @name Data Stream + * ----------------------------------------------------------------------------- + */ + +/** Creates a data stream. + + @since v3.3.0 + + Each user can create up to five data streams in a single channel. + + This method does not support data reliability. If the receiver receives a data + packet five seconds or more after it was sent, the SDK directly discards + the data. + + @param streamId ID of the created data stream. + @param config The configurations for the data stream: AgoraDataStreamConfig. + + @return * Returns the stream ID if you successfully create the data stream. +* < 0: Fails to create the data stream. + */ +- (int)createDataStream:(NSInteger* _Nonnull)streamId config:(AgoraDataStreamConfig* _Nonnull)config; + +/** Sends data stream messages to all users in a channel. + +The SDK has the following restrictions on this method: + +* Up to 30 packets can be sent per second in a channel with each packet having a maximum size of 1 kB. +* Each client can send up to 6 kB of data per second. +* Each user can have up to five data streams simultaneously. + +A successful sendStreamMessage method call triggers the [receiveStreamMessageFromUid]([AgoraRtcEngineDelegate rtcEngine:receiveStreamMessageFromUid:streamId:data:]) callback on the remote client, from which the remote user gets the stream message. + +A failed sendStreamMessage method call triggers the [didOccurStreamMessageErrorFromUid]([AgoraRtcEngineDelegate rtcEngine:didOccurStreamMessageErrorFromUid:streamId:error:missed:cached:]) callback on the remote client. + + **Note:** + + - This method applies only to the Communication profile or to the hosts in the interactive live streaming profile. If an audience in the interactive live streaming profile calls this method, the audience role may be changed to a host. + - Ensure that you have created the data stream using [createDataStream](createDataStream:reliable:ordered:) before calling this method. + + @param streamId ID of the sent data stream returned in the `createDataStream` method. + @param data Sent data. + + @return * 0: Success. + * < 0: Failure. +*/ +- (int)sendStreamMessage:(NSInteger)streamId data:(NSData* _Nonnull)data; + +#pragma mark Miscellaneous Video Control + +/**----------------------------------------------------------------------------- + * @name Miscellaneous Video Control + * ----------------------------------------------------------------------------- + */ + +/** Sets the camera capture preference. + +For a video call or interactive live streaming, generally the SDK controls the camera output parameters. When the default camera capture settings do not meet special requirements or cause performance problems, we recommend using this method to set the camera capture preference: + +* If the resolution or frame rate of the captured raw video data is higher than that set by [setVideoEncoderConfiguration]([AgoraRtcEngineKit setVideoEncoderConfiguration:]), processing video frames requires extra CPU and RAM usage and degrades performance. We recommend setting `configuration` as `AgoraCameraCaptureOutputPreferencePerformance(1)` to avoid such problems. +* If you do not need local video preview or are willing to sacrifice preview quality, we recommend setting `configuration` as `AgoraCameraCaptureOutputPreferencePerformance(1)` to optimize CPU and RAM usage. +* If you want better quality for the local video preview, we recommend setting `configuration` as `AgoraCameraCaptureOutputPreferencePreview(2)`. +* To customize the width and height of the video image captured by the local camera, set the camera capture configuration as `AgoraCameraCaptureOutputPreferenceManual(3)`. + +**Note:** + +Call this method before enabling the local camera. That said, you can call this method before calling `joinChannel`, `enableVideo`, or `enableLocalVideo`, depending on which method you use to turn on your local camera. + +@param configuration The camera capturer configuration, see AgoraCameraCapturerConfiguration. + +@return * 0: Success. +* < 0: Failure. + */ +- (int)setCameraCapturerConfiguration:(AgoraCameraCapturerConfiguration* _Nullable)configuration; + +#if defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE +#pragma mark Camera Control + +/**----------------------------------------------------------------------------- + * @name Camera Control + * ----------------------------------------------------------------------------- + */ + +/** Switches between front and rear cameras. (iOS only) + + @note Ensure that you call this method after the camera starts, for example, by calling [startPreview]([AgoraRtcEngineKit startPreview]) or [joinChannelByToken]([AgoraRtcEngineKit joinChannelByToken:channelId:info:uid:joinSuccess:]). + + @return * 0: Success. +* < 0: Failure. + */ +- (int)switchCamera; + +/** Checks whether the camera zoom function is supported. (iOS only.) + + @note Ensure that you call this method after the camera starts, for example, by calling [startPreview]([AgoraRtcEngineKit startPreview]) or [joinChannelByToken]([AgoraRtcEngineKit joinChannelByToken:channelId:info:uid:joinSuccess:]). + + @return * YES: The device supports the camera zoom function. + * NO: The device does not support the camera zoom function. + */ +- (BOOL)isCameraZoomSupported; + +/** Checks whether the device supports enabling the flash. (iOS only.) + + The SDK uses the front camera by default, so if you call + `isCameraTorchSupported` directly, you can find out from the return value + whether the device supports enabling the flash when using the front camera. + If you want to check whether the device supports enabling the flash when + using the rear camera, call [switchCamera]([AgoraRtcEngineKit switchCamera]) + to switch the camera used by the SDK to the rear camera, and then call + `isCameraTorchSupported`. + + **Note** + + - Call this method after the camera is started. + - On iPads with system version 15, even if `isCameraTorchSupported` + returns `YES`, you might fail to successfully enable the flash by calling + [setCameraTorchOn]([AgoraRtcEngineKit setCameraTorchOn:]) due to system issues. + + + @return * YES: The device supports enabling the flash. + * NO: The device does not support enabling the flash. + */ +- (BOOL)isCameraTorchSupported; + +/** Checks whether the camera manual focus function is supported. (iOS only) + + @note Ensure that you call this method after the camera starts, for example, by calling [startPreview]([AgoraRtcEngineKit startPreview]) or [joinChannelByToken]([AgoraRtcEngineKit joinChannelByToken:channelId:info:uid:joinSuccess:]). + + @return * YES: The device supports the camera manual focus function. + * NO: The device does not support the camera manual focus function. + */ +- (BOOL)isCameraFocusPositionInPreviewSupported; + +/** Checks whether the camera manual exposure function is supported. (iOS only) + + @note Ensure that you call this method after the camera starts, for example, by calling [startPreview]([AgoraRtcEngineKit startPreview]) or [joinChannelByToken]([AgoraRtcEngineKit joinChannelByToken:channelId:info:uid:joinSuccess:]). + + @return * YES: The device supports the manual exposure function. + * NO: The device does not support the manual exposure function. + */ +- (BOOL)isCameraExposurePositionSupported; + +/** Checks whether the camera auto-face focus function is supported. (iOS only) + + @note Ensure that you call this method after the camera starts, for example, by calling [startPreview]([AgoraRtcEngineKit startPreview]) or [joinChannelByToken]([AgoraRtcEngineKit joinChannelByToken:channelId:info:uid:joinSuccess:]). + + @return * YES: The device supports the camera auto-face focus function. + * NO: The device does not support the camera auto-face focus function. + */ +- (BOOL)isCameraAutoFocusFaceModeSupported; + +/** Sets the camera zoom ratio. (iOS only) + + @note Ensure that you call this method after the camera starts, for example, by calling [startPreview]([AgoraRtcEngineKit startPreview]) or [joinChannelByToken]([AgoraRtcEngineKit joinChannelByToken:channelId:info:uid:joinSuccess:]). + + @param zoomFactor Sets the camera zoom factor. The value ranges between 1.0 and the maximum zoom supported by the device. + + @return * The set camera zoom factor, if this method call is successful. + * < 0: Failure. + */ +- (CGFloat)setCameraZoomFactor:(CGFloat)zoomFactor; + +/** Sets the manual focus position. (iOS only) + + A successful setCameraFocusPositionInPreview method call triggers the o[cameraFocusDidChangedToRect]([AgoraRtcEngineDelegate rtcEngine:cameraFocusDidChangedToRect:]) callback on the local client. + + @note Ensure that you call this method after the camera starts, for example, by calling [startPreview]([AgoraRtcEngineKit startPreview]) or [joinChannelByToken]([AgoraRtcEngineKit joinChannelByToken:channelId:info:uid:joinSuccess:]). + + @param position Coordinates of the touch point in the view. + + @return * YES: Success. +* NO: Failure. + */ +- (BOOL)setCameraFocusPositionInPreview:(CGPoint)position; + +/** Sets the camera exposure position. (iOS only) + + A successful setCameraExposurePosition method call triggers the [cameraExposureDidChangedToRect]([AgoraRtcEngineDelegate rtcEngine:cameraExposureDidChangedToRect:]) callback on the local client. + + @note Ensure that you call this method after the camera starts, for example, by calling [startPreview]([AgoraRtcEngineKit startPreview]) or [joinChannelByToken]([AgoraRtcEngineKit joinChannelByToken:channelId:info:uid:joinSuccess:]). + + @param positionInView Coordinates of the touch point in the view. + + @return * YES: Success. + * NO: Failure. + */ +- (BOOL)setCameraExposurePosition:(CGPoint)positionInView; + +/** Sets whether to enable the flash. (iOS only.) + + **Note** + + - Call this method after the camera is started. + - On iPads with system version 15, even if [isCameraTorchSupported]([AgoraRtcEngineKit isCameraTorchSupported]) + returns `YES`, you might fail to successfully enable the flash by calling `setCameraTorchOn` due to system issues. + + @param isOn Determines whether to enable the flash: + + * YES: Enable the flash. + * NO: Do not enable the flash. + + @return * YES: Success. +* NO: Failure. + */ +- (BOOL)setCameraTorchOn:(BOOL)isOn; + +/** Sets whether to enable face autofocus. (iOS only.) + + The SDK earlier than v3.5.0 disables face autofocus by default. The SDK v3.5.0 + and later enables face autofocus by default. To set face autofocus, call this method. + + @note Call this method after the camera is started. + + @param enable Determines whether to enable face autofocus: + + * YES: Enable face autofocus. + * NO: Disable face autofocus. + + @return * YES: Success. +* NO: Failure. + */ +- (BOOL)setCameraAutoFocusFaceModeEnabled:(BOOL)enable; + +#endif + +#if (!(TARGET_OS_IPHONE) && (TARGET_OS_MAC)) +#pragma mark Screen Sharing + +/**----------------------------------------------------------------------------- + * @name Screen Sharing (macOS) + * ----------------------------------------------------------------------------- + */ + +/** Shares the whole or part of a screen by specifying the display ID. (macOS only.) + +@note Ensure that you call this method after joining a channel. + +@param displayId The display ID of the screen to be shared. Use this parameter to specify which screen you want to share. +For more information on how to get the display ID, see the advanced feature guide *Share the Screen* or get the display ID +from `sourceId` returned by [getScreenCaptureSourcesWithThumbSize]([AgoraRtcEngineKit getScreenCaptureSourcesWithThumbSize:iconSize:includeScreen:]). +@param rectangle (Optional) The relative location of the region to the screen. nil means sharing the whole screen. This parameter contains the following properties: + +- x: the horizontal offset from the top-left corner. +- y: the vertical offset from the top-left corner. +- width: the width of the region. +- height: the height of the region. + +If the specified region overruns the screen, the SDK shares only the region within it; if you set width or height as 0, the SDK shares the whole screen. +@param captureParams The screen sharing encoding parameters. The default video dimension is 1920 x 1080, that is, 2,073,600 +pixels. Agora uses the value of `dimensions` to calculate the charges. For details, see descriptions in [AgoraScreenCaptureParameters](AgoraScreenCaptureParameters). + +@return * 0: Success. +* < 0: Failure. + + - -2(AgoraErrorCodeInvalidArgument): the argument is invalid. + */ +- (int)startScreenCaptureByDisplayId:(NSUInteger)displayId rectangle:(CGRect)rectangle parameters:(AgoraScreenCaptureParameters* _Nonnull)captureParams; + +/** Shares the whole or part of a window by specifying the window ID. (macOS only.) + +@note Ensure that you call this method after joining a channel. + +@param windowId The ID of the window to be shared. This parameter specifies which window you want to share. For information on how to get the windowId, see *Share the Screen*. +@param rectangle (Optional) The relative location of the region to the window. nil means sharing the whole window. This parameter contains the following properties: + +- x: the horizontal offset from the top-left corner. +- y: the vertical offset from the top-left corner. +- width: the width of the region. +- height: the height of the region. + +If the specified region overruns the window, the SDK shares only the region within it; if you set width or height as 0, the SDK shares the whole window. +@param captureParams The screen sharing encoding parameters. The default video dimension is 1920 x 1080, that is, 2,073,600 +pixels. Agora uses the value of `dimensions` to calculate the charges. For details, see descriptions in [AgoraScreenCaptureParameters](AgoraScreenCaptureParameters). + +@return * 0: Success. +* < 0: Failure. + + - -2(AgoraErrorCodeInvalidArgument): the argument is invalid. + */ +- (int)startScreenCaptureByWindowId:(NSUInteger)windowId rectangle:(CGRect)rectangle parameters:(AgoraScreenCaptureParameters* _Nonnull)captureParams; + +/** Sets the content hint for screen sharing. + +A content hint suggests the type of the content being shared, so that the SDK applies different optimization algorithm to different types of content. + +You can call this method either before or after you start screen sharing. + +@param contentHint The content hint for screen sharing, see [AgoraVideoContentHint](AgoraVideoContentHint). + +@return * 0: Success. +* < 0: Failure. +*/ +- (int)setScreenCaptureContentHint:(AgoraVideoContentHint)contentHint; + +/** Updates the screen sharing parameters. (macOS only.) + +@param captureParams The screen sharing encoding parameters. The default video dimension is 1920 x 1080, that is, 2,073,600 +pixels. Agora uses the value of `dimensions` to calculate the charges. For details, see descriptions in [AgoraScreenCaptureParameters](AgoraScreenCaptureParameters). + +@return * 0: Success. +* < 0: Failure. + + - -3(AgoraErrorCodeNotReady): no screen or windows is being shared. + */ +- (int)updateScreenCaptureParameters:(AgoraScreenCaptureParameters* _Nonnull)captureParams; + +/** Updates the screen-sharing region. (macOS only.) + + @param rect The relative location of the region to the screen or window. nil means sharing the whole screen or window. This parameter contains the following properties: + +- x: the horizontal offset from the top-left corner. +- y: the vertical offset from the top-left corner. +- width: the width of the region. +- height: the height of the region. + +If the specified region overruns the screen or window, the SDK shares only the region within it; if you set width or height as 0, the SDK shares the whole screen or window. + +@return * 0: Success. +* < 0: Failure. + + - -3(AgoraErrorCodeNotReady): no screen or windows is being shared. +*/ +- (int)updateScreenCaptureRegion:(CGRect)rect; + +/** Stops screen sharing. (macOS only.) + + @return * 0: Success. +* < 0: Failure. + */ +- (int)stopScreenCapture; + +/** + Gets a list of shareable screens and windows. + + @since v3.5.2 + + You can call this method before sharing a screen or window to get a list of + shareable screens and windows, which enables a user to use thumbnails in the + list to easily choose a particular screen or window to share. This list also + contains important information such as window ID and screen ID, with which you + can call [startScreenCaptureByWindowId]([AgoraRtcEngineKit startScreenCaptureByWindowId:rectangle:parameters:]) + or [startScreenCaptureByDisplayId]([AgoraRtcEngineKit startScreenCaptureByDisplayId:rectangle:parameters:]) + to start the sharing. + + @note This method applies to macOS only. + + @param thumbSize The target size of the screen or window thumbnail. The width and height are in pixels. The SDK scales + the original image to make the length of the longest side of the image the same as that of the target size without + distorting the original image. For example, if the original image is 400 × 300 and `thumbSize` is 100 × 100, the + actual size of the thumbnail is 100 × 75. If the target size is larger than the original size, the thumbnail is the + original image and the SDK does not scale it. + @param iconSize The target size of the icon corresponding to the application program. The width and height are in pixels. + The SDK scales the original image to make the length of the longest side of the image the same as that of the target + size without distorting the original image. For example, if the original image is 400 × 300 and `iconSize` is 100 × 100, + the actual size of the icon is 100 × 75. If the target size is larger than the original size, the icon is the original + image and the SDK does not scale it. + @param includeScreen Whether the SDK returns screen information in addition to window information: + + - YES: The SDK returns screen and window information. + - NO: The SDK returns window information only. + + @return AgoraScreenCaptureSourceInfo + */ +- (NSArray* _Nullable)getScreenCaptureSourcesWithThumbSize:(NSSize)thumbSize iconSize:(NSSize)iconSize includeScreen:(BOOL)includeScreen; + +#endif + +#if (!(TARGET_OS_IPHONE) && (TARGET_OS_MAC)) +#pragma mark Device Manager (macOS) +/**----------------------------------------------------------------------------- + * @name Device Manager (macOS only) + * ----------------------------------------------------------------------------- + */ + +/** Monitors the change of a device state. (macOS only.) + + Use this method to monitor the plugging and swapping of external audio/video devices. For example, an external camera. + + @param enabled - YES: Enable the monitoring of a device state change. + - NO: Disable the monitoring of a device state change. + */ +- (void)monitorDeviceChange:(BOOL)enabled; + +/** Gets all devices in the system. (macOS only.) + + **Note:** + + Do not call this method in the main thread. + + This method returns an NSArray object, including all audio/video devices in the system. + Your app can use the AgoraRtcDeviceInfo array object to enumerate the devices. + + @param type Device type: AgoraMediaDeviceType. + @return An AgoraRtcDeviceInfo NSArray object including all devices, if this method call is successful. + */ +- (NSArray* _Nullable)enumerateDevices:(AgoraMediaDeviceType)type; + +/** Gets the information of devices, such as audio sampling and playback device. (macOS only.) + + @param type Device type: AgoraMediaDeviceType. + @return * The device information (AgoraRtcDeviceInfo), if this method call is successful. + * nil: Failure. + */ +- (AgoraRtcDeviceInfo* _Nullable)getDeviceInfo:(AgoraMediaDeviceType)type; + +/** Sets the devices, such as audio sampling and playback device. (macOS only.) + + @param type Device type: AgoraMediaDeviceType. + @param deviceId Device ID of the device, which can be retrieved by calling the [enumerateDevices](enumerateDevices:)method. `deviceId` does not change when the device is plugged or unplugged. + @return * 0: Success. +* < 0: Failure. + */ + +- (int)setDevice:(AgoraMediaDeviceType)type deviceId:(NSString* _Nonnull)deviceId; + +/** Gets the specified device's volume. (macOS only.) + + @param type Device type: AgoraMediaDeviceType. + @return * Returns the volume, if this method call is successful. + +* < 0: Failure. + */ +- (int)getDeviceVolume:(AgoraMediaDeviceType)type; + +/** Sets the specified device's volume. (macOS only.) + + @note Call this method after joining a channel. + + @param type Device type: AgoraMediaDeviceType + @param volume Sets the specified device's volume. The value ranges between 0 and 100. + @return * 0: Success. +* < 0: Failure. + */ +- (int)setDeviceVolume:(AgoraMediaDeviceType)type volume:(int)volume; + +/** Starts the audio sampling device test. (macOS only) + + This method tests whether the audio sampling device works properly. + + After calling this method, the SDK triggers the + [reportAudioVolumeIndicationOfSpeakers]([AgoraRtcEngineDelegate rtcEngine:reportAudioVolumeIndicationOfSpeakers:totalVolume:]) + callback at the time interval set in this method, which reports `uid` = 0 and the volume of the sampling device. + + @note Call this method before joining a channel. + + @param indicationInterval The time interval (ms) at which the `reportAudioVolumeIndicationOfSpeakers` callback returns. + We recommend a setting greater than 200 ms. This value must not be less than 10 ms; otherwise, you can not receive the + `reportAudioVolumeIndicationOfSpeakers` callback. + + @return * 0: Success. +* < 0: Failure. + */ +- (int)startRecordingDeviceTest:(int)indicationInterval; + +/** Stops the microphone test. (macOS only.) + + This method stops testing the microphone. You must call this method to stop the test after calling the [startRecordingDeviceTest](startRecordingDeviceTest:) method. + + @return * 0: Success. +* < 0: Failure. + */ +- (int)stopRecordingDeviceTest; + +/** Starts the audio playback device test. (macOS only) + +This method tests if the audio playback device works properly. Once a user starts the test, the SDK plays an audio file +specified by the user. If the user can hear the audio, the playback device works properly. + +After calling this method, the SDK triggers the +[reportAudioVolumeIndicationOfSpeakers]([AgoraRtcEngineDelegate rtcEngine:reportAudioVolumeIndicationOfSpeakers:totalVolume:]) +callback every 100 ms, which reports `uid` = 1 and the volume of the playback device. + +@note Call this method before joining a channel. + +@param audioFileName Absolute path of the audio file for the test in UTF-8: + +- Supported file formats: wav, mp3, m4a, and aac. +- Supported file sample rates: 8000, 16000, 32000, 44100, and 48000 Hz. + +@return * 0: Success. +* < 0: Failure. +*/ +- (int)startPlaybackDeviceTest:(NSString* _Nonnull)audioFileName; + +/** Stops the audio playback device test. (macOS only.) + + This method stops testing the audio playback device. You must call this method to stop the test after calling the [startPlaybackDeviceTest](startPlaybackDeviceTest:) method. + + @note Call this method before joining a channel. + + @return * 0: Success. +* < 0: Failure. + */ +- (int)stopPlaybackDeviceTest; + +/** Starts a video-capture device test. (macOS only.) + + This method tests whether the video-capture device works properly. Ensure that you call the [enableVideo]([AgoraRtcEngineKit enableVideo]) method before calling this method and that the parameter view window is valid. + + @param view Input parameter for displaying the video window. + + @note Call this method before joining a channel. + + @return * 0: Success. +* < 0: Failure. + + */ +- (int)startCaptureDeviceTest:(NSView* _Nonnull)view; + +/** Stops the video-capture device test. (macOS only.) + + This method stops testing the video-capture device. You must call this method to stop the test after calling the [startCaptureDeviceTest](startCaptureDeviceTest:) method. + + @note Call this method before joining a channel. + + @return * 0: Success. +* < 0: Failure. + + */ +- (int)stopCaptureDeviceTest; + +/** Starts the audio device loopback test. (macOS only) + +This method tests whether the local audio sampling device and playback device are working properly. After calling this method, +the audio sampling device samples the local audio, and the audio playback device plays the sampled audio. The SDK triggers +two independent +[reportAudioVolumeIndicationOfSpeakers]([AgoraRtcEngineDelegate rtcEngine:reportAudioVolumeIndicationOfSpeakers:totalVolume:]) +callbacks at the time interval set in this method, which reports the following information: + +- `uid` = 0 and the volume information of the sampling device. +- `uid` = 1 and the volume information of the playback device. + +**Note:** + +- This method tests the local audio devices and does not report the network conditions. +- Call this method before joining a channel. + +@param indicationInterval The time interval (ms) at which the `reportAudioVolumeIndicationOfSpeakers` callback returns. +We recommend a setting greater than 200 ms. This value must not be less than 10 ms; otherwise, you can not receive the +`reportAudioVolumeIndicationOfSpeakers` callback. + +@return * 0: Success. +* < 0: Failure. +*/ +- (int)startAudioDeviceLoopbackTest:(int)indicationInterval; + +/** Stops the audio device loopback test. (macOS only.) + + Ensure that you call this method to stop the loopback test after calling the [startAudioDeviceLoopbackTest]([AgoraRtcEngineKit startAudioDeviceLoopbackTest:]) method. + + @note Call this method before joining a channel. + + @return * 0: Success. +* < 0: Failure. +*/ +- (int)stopAudioDeviceLoopbackTest; +#endif + +#pragma mark Custom Media Metadata + +/**----------------------------------------------------------------------------- + * @name Media Metadata + * ----------------------------------------------------------------------------- + */ + +/** Sets the data source of the metadata. + + You need to implement the [AgoraMediaMetadataDataSource](AgoraMediaMetadataDataSource) protocol and specify the type of metadata in this method. + + Use this method with the [setMediaMetadataDelegate]([AgoraRtcEngineKit setMediaMetadataDelegate:withType:]) method to add synchronized metadata in the video stream. You can create more diversified interactive live streaming interactions, such as sending shopping links, digital coupons, and online quizzes. + + **Note** + + - Call this method before the [joinChannelByToken]([AgoraRtcEngineKit joinChannelByToken:channelId:info:uid:joinSuccess:]) method. + - This method applies to the interactive live streaming channel profile only. + + @param metadataDataSource The AgoraMediaMetadataDataSource protocol. + @param type The metadata type. See [AgoraMetadataType](AgoraMetadataType). Currently, the SDK supports video metadata only. + @return * YES: Success. + * NO: Failure. + */ +- (BOOL)setMediaMetadataDataSource:(id _Nullable)metadataDataSource withType:(AgoraMetadataType)type; + +/** Sets the delegate of the metadata. + + You need to implement the AgoraMediaMetadataDelegate protocol and specify the type of metadata in this method. + + **Note** + + - Call this method before the [joinChannelByToken]([AgoraRtcEngineKit joinChannelByToken:channelId:info:uid:joinSuccess:]) method. + - This method applies to the interactive live streaming channel profile only. + + @param metadataDelegate The AgoraMediaMetadataDelegate protocol. + @param type The metadata type. See [AgoraMetadataType](AgoraMetadataType). Currently, the SDK supports video metadata only. + @return * YES: Success. + * NO: Failure. + */ +- (BOOL)setMediaMetadataDelegate:(id _Nullable)metadataDelegate withType:(AgoraMetadataType)type; + +#pragma mark Miscellaneous Methods + +/**----------------------------------------------------------------------------- + * @name Miscellaneous Methods + * ----------------------------------------------------------------------------- + */ + +/** Gets the information of a specified audio file. + + @since v3.5.1 + + After calling this method successfully, the SDK triggers the + [didRequestAudioFileInfo]([AgoraRtcEngineDelegate rtcEngine:didRequestAudioFileInfo:error:]) + callback to report the information of an audio file, such as audio duration. + You can call this method multiple times to get the information of multiple + audio files. + + **Note** + + - Call this method after joining a channel. + - For the audio file formats supported by this method, see + [What formats of audio files does the Agora RTC SDK support](https://docs.agora.io/en/faq/audio_format). + + @param filePath The absolute path or URL address (including the filename extensions) + of the audio file. For example: `/var/mobile/Containers/Data/audio.mp4`. + + @return * 0: Success. + * < 0: Failure. + */ +- (int)getAudioFileInfo:(NSString* _Nullable)filePath; + +/** Gets the current call ID. + + When a user joins a channel on a client, a `callId` is generated to identify the call from the client. Feedback methods, such as the [rate](rate:rating:description:) and [complain](complain:description:) methods, must be called after the call ends to submit feedback to the SDK. + + The [rate](rate:rating:description:) and [complain](complain:description:) methods require the `callId` parameter retrieved from the `getCallId` method during a call. *callId* is passed as an argument into the [rate](rate:rating:description:) and [complain](complain:description:) methods after the call ends. + + @note Ensure that you call this method after joining a channel. + + @return callId The current call ID. + */ +- (NSString* _Nullable)getCallId; + +/** Allows a user to rate a call after the call ends. + + @note Ensure that you call this method after leaving a channel. + + @param callId Call ID retrieved from the [getCallId]([AgoraRtcEngineKit getCallId]) method. + @param rating Rating of the call. The value is between 1 (lowest score) and 5 (highest score). If you set a value out of this range, the AgoraErrorCodeInvalidArgument(-2) error occurs. + @param description (Optional) Description of the rating. The string length must be less than 800 bytes. + + @return * 0: Success. + * < 0: Failure. + + * Return AgoraErrorCodeInvalidArgument(-2):The passed argument is invalid. For example, `callId` is invalid. + * Return AgoraErrorCodeNotReady(-3):The SDK status is incorrect. For example, initialization fails. + */ +- (int)rate:(NSString* _Nonnull)callId rating:(NSInteger)rating description:(NSString* _Nullable)description; + +/** Allows a user to complain about the call quality after a call ends. + + @note Ensure that you call this method after leaving a channel. + + @param callId Call ID retrieved from the getCallId method. + @param description (Optional) Description of the complaint. The string length must be less than 800 bytes. + + @return * 0: Success. + * < 0: Failure. + + * -2(AgoraErrorCodeInvalidArgument): The parameter is invalid. + * -3(AgoraErrorCodeNotReady): The SDK fails to be initialized. You can try re-initializing the SDK. + */ +- (int)complain:(NSString* _Nonnull)callId description:(NSString* _Nullable)description; + +/** Enables/Disables dispatching delegate methods to the main queue. + + If disabled, the app should dispatch UI operations to the main queue. + + @param enabled Sets whether to dispatch delegate methods to the main queue: + + * YES: Dispatch delegate methods to the main queue. + * NO: Do not dispatch delegate methods to the main queue + + @return * 0: Success. +* < 0: Failure. + */ +- (int)enableMainQueueDispatch:(BOOL)enabled; + +/** Gets the SDK version. + + This method returns the string of the version number. + + @note You can call this method either before or after joining a channel. + + @return The version of the current SDK in the string format. For example, 2.3.0 + */ ++ (NSString* _Nonnull)getSdkVersion; + +/** Gets the description of a warning or error code. + + @param code The warning or error code that the [didOccurWarning]([AgoraRtcEngineDelegate rtcEngine:didOccurWarning:]) or [didOccurError]([AgoraRtcEngineDelegate rtcEngine:didOccurError:]) callback returns. + + @return AgoraWarningCode or AgoraErrorCode. + */ ++ (NSString* _Nullable)getErrorDescription:(NSInteger)code; + +- (NSString* _Nullable)uploadLogFile; + +/** Agora supports reporting and analyzing customized messages. + + @since 3.1.0 + + This function is in the beta stage with a free trial. + The ability provided in its beta test version is reporting a maximum of 10 message pieces within 6 seconds, + with each message piece not exceeding 256 bytes and each string not exceeding 100 bytes. + To try out this function, contact [support@agora.io](mailto:support@agora.io) and discuss the format of customized messages with us. + */ +- (int)sendCustomReportMessage:(NSString* _Nonnull)id category:(NSString* _Nonnull)category event:(NSString* _Nonnull)event label:(NSString* _Nonnull)label value:(NSInteger)value; + +/** Returns the native handler of the SDK engine. + + This interface is used to get the native C++ handler of the SDK engine used in special scenarios, such as registering the audio and video frame observer. + */ +- (void* _Nullable)getNativeHandle; + +/** Sets and gets the SDK delegate. + + The SDK uses the delegate to inform the app on engine runtime events. All methods defined in the delegate are optional implementation methods. + + */ +@property(nonatomic, weak) id _Nullable delegate; + +#pragma mark Customized Methods (Technical Preview) + +- (int)setParameters:(NSString* _Nonnull)options; + +- (NSString* _Nullable)getParameter:(NSString* _Nonnull)parameter args:(NSString* _Nullable)args; + +/** + Takes a snapshot of a video stream. + + @since v3.5.2 + + This method takes a snapshot of a video stream from the specified user, generates a JPG image, and saves it to the specified path. + + The method is asynchronous, and the SDK has not taken the snapshot when the method call returns. + After a successful method call, the SDK triggers the [snapshotTaken]([AgoraRtcEngineDelegate rtcEngine:snapshotTaken:uid:filePath:width:height:errCode:]) callback to report whether the snapshot is successfully + taken as well as the details of the snapshot taken. + + **Notes:** + + - Call this method after joining a channel. + - If the video of the specified user is pre-processed, for example, added with watermarks or image enhancement effects, the generated snapshot also includes the pre-processing effects. + + @param channel The channel name. + @param uid The user ID of the user. Set uid as 0 if you want to take a snapshot of the local user's video. + @param filePath The local path (including the filename extensions) of the snapshot. + For example, `/App Sandbox/Library/Caches/example.jpg` on iOS and `~/Library/Logs/example.jpg` on macOS. + Ensure that the path you specify exists and is writable. + + @return - 0: Success. + - < 0: Failure. + */ +- (NSInteger)takeSnapshot:(NSString* _Nonnull)channel uid:(NSInteger)uid filePath:(NSString* _Nonnull)filePath; + +- (int)enableContentInspect:(BOOL)enabled config:(AgoraContentInspectConfig* _Nonnull)config; + +#pragma mark Deprecated Methods + +/**----------------------------------------------------------------------------- + * @name Deprecated Methods + * ----------------------------------------------------------------------------- + */ + +/** Pushes the external raw audio frame data to the SDK for encoding. + + **Deprecated**This method is deprecated as of v3.5.1. + Use [pushExternalAudioFrameRawData]([AgoraRtcEngineKit pushExternalAudioFrameRawData:frame:]) 2 instead. + + @param data External audio data to be pushed. + @param samples Number of samples for the push. + @param timestamp The timestamp (ms) of the external audio frame. It is mandatory. You can use this parameter for the following purposes: + + - Restore the order of the captured audio frame. + - Synchronize audio and video frames in video-related scenarios, including scenarios where external video sources are used. + @return * YES: Success. +* NO: Failure. + */ +- (BOOL)pushExternalAudioFrameRawData:(void* _Nonnull)data samples:(NSUInteger)samples timestamp:(NSTimeInterval)timestamp __deprecated_msg("use pushExternalAudioFrameRawData:sourcePos:frame instead."); + +/** Pushes the external CMSampleBuffer audio frame to the SDK for encoding. + + **Deprecated**This method is deprecated as of v3.5.1. + Use [pushExternalAudioFrameSampleBuffer]([AgoraRtcEngineKit pushExternalAudioFrameSampleBuffer:sampleBuffer:]) 2 instead. + + @param sampleBuffer Sample buffer for the push. + @return * YES: Success. +* NO: Failure. + */ +- (BOOL)pushExternalAudioFrameSampleBuffer:(CMSampleBufferRef _Nonnull)sampleBuffer __deprecated_msg("use pushExternalAudioFrameSampleBuffer:sourcePos:sampleBuffer instead."); + +/** Gets the total duration of the current music file. + + **Deprecated** This method is deprecated as of v3.5.1. Use + [getAudioFileInfo]([AgoraRtcEngineKit getAudioFileInfo:]) instead. + + @since v3.4.0 + @note Call this method after [startAudioMixing]([AgoraRtcEngineKit startAudioMixing:loopback:replace:cycle:startPos:]). + @return * ≥ 0: A successful method call. Returns the total duration (ms) of the current music file. +* < 0: Failure. + */ +- (int)getAudioMixingDuration __deprecated_msg("use getAudioFileInfo:filePath instead."); + +/** Plays a specified audio effect. + +**Deprecated** from v3.4.0. Use [playEffect]([AgoraRtcEngineKit playEffect:filePath:loopCount:pitch:pan:gain:publish:startPos:])3 instead. + +You can use this method to add specific audio effects for specific scenarios, for example, gaming. + +With this method, you can set the loop count, pitch, pan, and gain of the audio effect file and whether the remote user can hear the audio effect. + +To play multiple audio effect files simultaneously, call this method multiple times with different soundIds and filePaths. We recommend playing no more than three audio effect files at the same time. + +When the audio effect file playback is finished, the SDK triggers the [rtcEngineDidAudioEffectFinish]([AgoraRtcEngineDelegate rtcEngineDidAudioEffectFinish:soundId:]) callback. + + **Note** + + - Call this method after joining a channel. + - For the audio file formats supported by this method, see + [What formats of audio files does the Agora RTC SDK support](https://docs.agora.io/en/faq/audio_format). + + @param soundId ID of the specified audio effect. Each audio effect has a unique ID. + If the audio effect is preloaded into the memory through the [preloadEffect](preloadEffect:filePath:) method, ensure that the `soundId` value is set to the same value as in [preloadEffect](preloadEffect:filePath:). + @param filePath The absolute path or URL address (including the filename extensions) + of the audio file. For example: `/var/mobile/Containers/Data/audio.mp4`. + @param loopCount Sets the number of times the audio effect loops: + + * 0: Plays the audio effect once. + * 1: Plays the audio effect twice. + * -1: Plays the audio effect in an indefinite loop until you call the [stopEffect](stopEffect:) or [stopAllEffects](stopAllEffects) method. + + @param pitch Sets the pitch of the audio effect. The value ranges between 0.5 and 2. The default value is 1 (no change to the pitch). The lower the value, the lower the pitch. + @param pan Sets the spatial position of the audio effect. The value ranges between -1.0 and 1.0. + + * 0.0: The audio effect displays ahead. + * 1.0: The audio effect displays to the right. + * -1.0: The audio effect displays to the left. + + @param gain Sets the volume of the audio effect. The value ranges between 0.0 and 100.0 (default). The lower the value, the lower the volume of the audio effect. + @param publish Sets whether to publish the specified audio effect to the remote stream: + + * YES: The played audio effect is published to the Agora Cloud and the remote users can hear it. + * NO: The played audio effect is not published to the Agora Cloud and the remote users cannot hear it. + @return * 0: Success. +* < 0: Failure. + */ +- (int)playEffect:(int)soundId filePath:(NSString* _Nullable)filePath loopCount:(int)loopCount pitch:(double)pitch pan:(double)pan gain:(double)gain publish:(BOOL)publish __deprecated_msg("use playEffect:filePath:loopCount:pitch:pan:gain:publish:startPos instead."); + +/** Starts an audio recording on the client. + + **Deprecated** from v3.4.0. Use [startAudioRecordingWithConfig]([AgoraRtcEngineKit startAudioRecordingWithConfig:]) instead. + + The SDK allows recording during a call. After successfully calling this method, you can record the audio of all the users in the channel and get an audio recording file. Supported formats of the recording file are as follows: + + - .wav: Large file size with high fidelity. + - .aac: Small file size with low fidelity. + + **Note** + + - Ensure that the directory you use to save the recording file exists and is writable. + - This method is usually called after the [joinChannelByToken]([AgoraRtcEngineKit joinChannelByToken:channelId:info:uid:joinSuccess:]) method. The recording automatically stops when you call the [leaveChannel]([AgoraRtcEngineKit leaveChannel:]) method. + - For better recording effects, set `quality` as AgoraAudioRecordingQualityMedium or AgoraAudioRecordingQualityHigh when `sampleRate` is 44100 Hz or 48000 Hz. + + @param filePath Absolute file path of the recording file, for example, /var/mobile/Containers/Data/audio.aac. The string of the filename is in UTF-8. + @param sampleRate Sample rate (Hz) of the recording file. Supported values are as follows: + + - 16000 + - (Default) 32000 + - 44100 + - 48000 + + @param quality Audio recording quality. See AgoraAudioRecordingQuality. + + @return - 0: Success. +- < 0: Failure. + */ +- (int)startAudioRecording:(NSString* _Nonnull)filePath sampleRate:(NSInteger)sampleRate quality:(AgoraAudioRecordingQuality)quality __deprecated_msg("use startAudioRecordingWithConfig:config instead."); + +/** Starts audio mixing. + + **Deprecated** from v3.4.0. Use [startAudioMixing]([AgoraRtcEngineKit startAudioMixing:loopback:replace:cycle:startPos:])2 instead. + + This method mixes the specified local audio file with the audio stream from the microphone, or replaces the microphone's audio stream with the specified local audio file. You can choose whether the other user can hear the local audio playback and specify the number of playback loops. This method also supports online music playback. + + A successful startAudioMixing method call triggers the [localAudioMixingStateDidChanged]([AgoraRtcEngineDelegate rtcEngine:localAudioMixingStateDidChanged:reason:])(AgoraAudioMixingStatePlaying) callback on the local client. + + When the audio mixing file playback finishes, the SDK triggers the [localAudioMixingStateDidChanged]([AgoraRtcEngineDelegate rtcEngine:localAudioMixingStateDidChanged:reason:])(AgoraAudioMixingStateStopped) callback on the local client. + + **Note:** + + - To avoid blocking, as of v3.4.5, this method changes from a synchronous call + to an asynchronous call. + - If you want to play an online music file, ensure that the time interval between playing the online music file and calling this method is greater than 100 ms, or the AudioFileOpenTooFrequent(702) warning occurs. + - If the local audio mixing file does not exist, or if the SDK does not support the file format or cannot access the music file URL, the SDK returns AgoraWarningCodeAudioMixingOpenError(701). + - For the audio file formats supported by this method, see + [What formats of audio files does the Agora RTC SDK support](https://docs.agora.io/en/faq/audio_format). + + @param filePath The absolute path or URL address (including the filename extensions) + of the audio file. For example: `/var/mobile/Containers/Data/audio.mp4`. + @param loopback Sets which user can hear the audio mixing: + + * YES: Only the local user can hear the audio mixing. + * NO: Both users can hear the audio mixing. + + @param replace Sets the audio mixing content: + + * YES: Only the specified audio file is published; the audio stream received by the microphone is not published. + * NO: The local audio file mixed with the audio stream from the microphone. + + @param cycle Sets the number of playback loops: + + * Positive integer: Number of playback loops. + * -1:Infinite playback loops. + + @return * 0: Success. +* < 0: Failure. + */ +- (int)startAudioMixing:(NSString* _Nonnull)filePath loopback:(BOOL)loopback replace:(BOOL)replace cycle:(NSInteger)cycle __deprecated_msg("use startAudioMixing(.., startPos) instead"); + +/** Stops or resumes subscribing to the video streams of all remote users by default. + + **Deprecated** This method is deprecated from v3.3.0. + + Call this method after joining a channel. After successfully calling this + method, the local user stops or resumes subscribing to the video streams of + all subsequent users. + + **Note** + + If you need to resume subscribing to the video streams of remote users + in the channel after calling `setDefaultMuteAllRemoteVideoStreams(YES)`, do + the following: + + - If you need to resume subscribing to the video stream of a specified user, + call [muteRemoteVideoStream(NO)]([AgoraRtcEngineKit muteRemoteVideoStream:mute:]), and specify the user ID. + - If you need to resume subscribing to the video streams of multiple remote + users, call `muteRemoteVideoStream(NO)` multiple times. + + @param mute Sets whether to stop subscribing to the video streams of all + remote users by default. + + * YES: Stop subscribing to the video streams of all + remote users by default. + * NO: (Default) Resume subscribing to the video streams of all remote users + by default. + + @return * 0: Success. +* < 0: Failure. + */ +- (int)setDefaultMuteAllRemoteVideoStreams:(BOOL)mute; + +/** Stops or resumes subscribing to the audio streams of all remote users by default. + + **Deprecated** This method is deprecated from v3.3.0. + + Call this method after joining a channel. After successfully calling this + method, the local user stops or resumes subscribing to the audio streams of + all subsequent users. + + **Note** + + If you need to resume subscribing to the audio streams of remote users + in the channel after calling `setDefaultMuteAllRemoteAudioStreams(YES)`, do + the following: + + - If you need to resume subscribing to the audio stream of a specified user, + call [muteRemoteAudioStream(NO)]([AgoraRtcEngineKit muteRemoteAudioStream:mute:]), and specify the user ID. + - If you need to resume subscribing to the audio streams of multiple remote + users, call `muteRemoteAudioStream(NO)` multiple times. + + @param mute Sets whether to stop subscribing to the audio streams of all + remote users by default. + + * YES: Stop subscribing to the audio streams of all + remote users by default. + * NO: (Default) Resume subscribing to the audio streams of all remote users + by default. + + @return * 0: Success. +* < 0: Failure. + */ +- (int)setDefaultMuteAllRemoteAudioStreams:(BOOL)mute; + +/** Sets the log files that the SDK outputs. + + **Deprecated** This method is deprecated from v3.3.0. Use the `logConfig` + parameter in [sharedEngineWithConfig]([AgoraRtcEngineKit sharedEngineWithConfig:delegate:]) + to set the log file path instead. + + By default, the SDK outputs five log files, `agorasdk.log`, `agorasdk_1.log`, `agorasdk_2.log`, `agorasdk_3.log`, `agorasdk_4.log`, each + with a default size of 1024 KB. These log files are encoded in UTF-8. The SDK writes the latest logs in `agorasdk.log`. When `agorasdk.log` + is full, the SDK deletes the log file with the earliest modification time among the other four, renames `agorasdk.log` to the name of the + deleted log file, and creates a new `agorasdk.log` to record latest logs. + + **Note:** + + - The default log file path is as follows: + - iOS: `App Sandbox/Library/caches/agorasdk.log` + - macOS + - Sandbox enabled: `App Sandbox/Library/Logs/agorasdk.log`, for example `/Users//Library/Containers//Data/Library/Logs/agorasdk.log`. + - Sandbox disabled: `~/Library/Logs/agorasdk.log`. + - Ensure that you call this method immediately after calling the [sharedEngineWithAppId]([AgoraRtcEngineKit sharedEngineWithAppId:delegate:]) method, otherwise the output logs may not be complete. + + @param filePath The absolute path of log files. Ensure that the directory for the log files exists and is writable. You can use this parameter to rename the log files. + + @return * 0: Success. + * < 0: Failure. + */ +- (int)setLogFile:(NSString* _Nonnull)filePath; + +/** Sets the output log level of the SDK. + + **Deprecated** This method is deprecated from v3.3.0. Use the `logConfig` + parameter in [sharedEngineWithConfig]([AgoraRtcEngineKit sharedEngineWithConfig:delegate:]) + to set the log filter instead. + + You can use one or a combination of the filters. The log level follows the sequence of `Off`, `Critical`, `Error`, `Warning`, `Info` and `Debug`. Choose a level to see the logs preceding that level. + + For example, if you set the log level to `Warning`, you see the logs within levels `Critical`, `Error`, and `Warning`. + + @param filter Log filter level: AgoraLogFilter. + + @return * 0: Success. + * < 0: Failure. + */ +- (int)setLogFilter:(NSUInteger)filter; + +/** Sets the size of a log file that the SDK outputs. + + **Deprecated** This method is deprecated from v3.3.0. Use the `logConfig` + parameter in [sharedEngineWithConfig]([AgoraRtcEngineKit sharedEngineWithConfig:delegate:]) + to set the log file size instead. + + By default, the SDK outputs five log files, `agorasdk.log`, `agorasdk_1.log`, `agorasdk_2.log`, + `agorasdk_3.log`, `agorasdk_4.log`, each with a default size of 1024 KB. These log files are + encoded in UTF-8. The SDK writes the latest logs in `agorasdk.log`. When `agorasdk.log` is full, + the SDK deletes the log file with the earliest modification time among the other four, renames + `agorasdk.log` to the name of the deleted log file, and create a new `agorasdk.log` to record latest logs. + + @note If you want to set the log file size, ensure that you call `setLogFileSize` before [setLogFile]([AgoraRtcEngineKit setLogFile:]), or the logs are cleared. + + @param fileSizeInKBytes The size (KB) of a log file. The default value is 1024 KB. If you set + `fileSizeInKByte` to 1024 KB, the SDK outputs at most 5 MB log files; if you set it to less + than 1024 KB, the maximum size of a log file is still 1024 KB. + + @return - 0: Success. + - < 0: Failure. + */ +- (int)setLogFileSize:(NSUInteger)fileSizeInKBytes; + +#pragma mark ExternalLogWriter + +@property(nonatomic, weak) id _Nullable logWriterDelegate; + +#pragma mark Deprecated Methods +/** Creates a data stream. + + **Deprecated** This method is deprecated from v3.3.0. Use the + [createDataStream]([AgoraRtcEngineKit createDataStream:config:])2 method + instead. + + Each user can create up to five data streams during the lifecycle of the [AgoraRtcEngineKit](AgoraRtcEngineKit). + + **Note:** + + - Ensure that you call this method after joining a channel. + - Set both the `reliable` and `ordered` parameters to `YES` or `NO`. Do not set one as `YES` and the other as `NO`. + + @param streamId (Output parameter) The ID of the created data stream. + @param reliable Sets whether or not the recipients are guaranteed to receive the data stream from the sender within five seconds: + + * YES: The recipients receive the data stream from the sender within five seconds. If the recipient does not receive the data stream within five seconds, an error is reported to the app. + * NO: There is no guarantee that the recipients receive the data stream within five seconds and no error message is reported for any delay or missing data stream. + + @param ordered Sets whether or not the recipients receive the data stream in the sent order: + + * YES: The recipients receive the data stream in the sent order. + * NO: The recipients do not receive the data stream in the sent order. + + @return * 0: Success. +* < 0: Failure. +*/ +- (int)createDataStream:(NSInteger* _Nonnull)streamId reliable:(BOOL)reliable ordered:(BOOL)ordered; + +/** Sets the local voice changer option. + +**Deprecated** from v3.2.0. Use the following methods instead: + +- [setAudioEffectPreset]([AgoraRtcEngineKit setAudioEffectPreset:]): Audio effects. +- [setVoiceBeautifierPreset]([AgoraRtcEngineKit setVoiceBeautifierPreset:]): Voice beautifier effects. +- [setVoiceConversionPreset]([AgoraRtcEngineKit setVoiceConversionPreset:]): Voice conversion effects. + +This method can be used to set the local voice effect for users in a Communication channel or hosts in the interactive live streaming channel. Voice changer options include the following voice effects: + +| Voice effect | Description | Scenario | +| :----------------------- | :----------------------------------------------------------- | :---------------- | +| AgoraAudioVoiceChanger* | Changes the local voice to an old man, a little boy, or the Hulk. | Voice talk | +| AgoraAudioVoiceBeauty* | Beautifies the local voice by making it sound more vigorous, resounding, or adding spacial resonance. | Voice talkSinging | +| AgoraAudioGeneralBeautyVoice* | Adds gender-based beautification effect to the local voice:
      97. For a male voice: Adds magnetism to the voice.
      98. For a female voice: Adds freshness or vitality to the voice.
      99. | Voice talk | + +**Note:** + +- You can call this method either before or after joining a channel. +- To achieve better voice effect quality, Agora recommends setting the `profile` parameter in [setAudioProfile]([AgoraRtcEngineKit setAudioProfile:scenario:]) as `AgoraAudioProfileMusicHighQuality(4)` or `AgoraAudioProfileMusicHighQualityStereo(5)`. +- This method works best with the human voice, and Agora does not recommend using it for audio containing music and a human voice. +- Do not use this method with [setLocalVoiceReverbPreset]([AgoraRtcEngineKit setLocalVoiceReverbPreset:]), because the method called later overrides the one called earlier. For detailed considerations, see the advanced guide *Set the Voice Effect*. + +@param voiceChanger

        The local voice changer option. The default value is `AgoraAudioVoiceChangerOff`, which means the original voice. See details in AgoraAudioVoiceChanger.

        +Gender-based beatification effect works best only when assigned a proper gender: +
      100. For male: AgoraAudioGeneralBeautyVoiceMaleMagnetic.
      101. For female: AgoraAudioGeneralBeautyVoiceFemaleFresh or AgoraAudioGeneralBeautyVoiceFemaleVitality.
      102. +

        Failure to do so can lead to voice distortion.

        + +@return * 0: Success. +* < 0: Failure. Check if the enumeration is properly set. +*/ +- (int)setLocalVoiceChanger:(AgoraAudioVoiceChanger)voiceChanger __deprecated_msg("use setAudioEffectPreset or setVoiceBeautifierPreset instead."); + +/** Sets the local voice reverberation option, including the virtual stereo. + +**Deprecated** from v3.2.0. Use [setAudioEffectPreset]([AgoraRtcEngineKit setAudioEffectPreset:]) or +[setVoiceBeautifierPreset]([AgoraRtcEngineKit setVoiceBeautifierPreset:]) instead. + +This method sets the local voice reverberation for users in a Communication channel or hosts in the interactive live streaming channel. After successfully calling this method, all users in the channel can hear the voice with reverberation. + +**Note:** + +- You can call this method either before or after joining a channel. +- When calling this method with enumerations that begin with `AgoraAudioReverbPresetFx`, ensure that you set `profile` in [setAudioProfile]([AgoraRtcEngineKit setAudioProfile:scenario:]) as `AgoraAudioProfileMusicHighQuality(4)` or `AgoraAudioProfileMusicHighQualityStereo(5)`. Otherwise, this method call does not take effect. +- When calling this method with `AgoraAudioReverbPresetVirtualStereo`, Agora recommends setting the `profile` parameter in `setAudioProfile` as `AgoraAudioProfileMusicHighQualityStereo(5)`. +- This method works best with the human voice, and Agora does not recommend using it for audio containing music and a human voice. +- Do not use this method with [setLocalVoiceChanger]([AgoraRtcEngineKit setLocalVoiceChanger:]), because the method called later overrides the one called earlier. For detailed considerations, see the advanced guide *Set the Voice Effect*. + + @param reverbPreset The local voice reverberation option. The default value is `AgoraAudioReverbPresetOff`, which means the original voice. See details in AgoraAudioReverbPreset.

        **Note**

        To achieve better voice effects, Agora recommends the enumeration whose name begins with `AgoraAudioReverbPresetFx`.

        + + @return * 0: Success. +* < 0: Failure. Check if the enumeration is properly set. + */ +- (int)setLocalVoiceReverbPreset:(AgoraAudioReverbPreset)reverbPreset __deprecated_msg("use setAudioEffectPreset or setVoiceBeautifierPreset instead."); + +/** Enables built-in encryption with an encryption password before joining a channel. + + **Deprecated** from v3.1.0. Use [enableEncryption]([AgoraRtcEngineKit enableEncryption:encryptionConfig:]) instead. + +All users in a channel must set the same encryption password. The encryption password is automatically cleared once a user leaves the channel. + + If the encryption password is not specified or set to empty, the encryption functionality is disabled. + + **Note:** + + - Do not use this method for CDN live streaming. + - For optimal transmission, ensure that the encrypted data size does not exceed the original data size + 16 bytes. 16 bytes is the maximum padding size for AES encryption. + + @param secret Encryption password. + @return * 0: Success. +* < 0: Failure. + */ +- (int)setEncryptionSecret:(NSString* _Nullable)secret; + +/** Sets the built-in encryption mode. + + **Deprecated** from v3.1.0. Use [enableEncryption]([AgoraRtcEngineKit enableEncryption:encryptionConfig:]) instead. + + The SDK supports built-in encryption, which is set to the `"aes-128-xts" +` mode by default. Call this method to use other encryption modes. + + All users in the same channel must use the same encryption mode and password. + + Refer to the information related to the AES encryption algorithm on the differences between the encryption modes. + + **Note:** + + - Call the [setEncryptionSecret](setEncryptionSecret:) method to enable the built-in encryption function before calling this method. + - Do not use this method for CDN live streaming. + + @param encryptionMode Sets the encryption mode. + + - "aes-128-xts": (default) 128-bit AES encryption, XTS mode. + - "aes-256-xts": 256-bit AES encryption, XTS mode. + - "aes-128-ecb": 128-bit AES encryption, ECB mode. + +When `encryptionMode` is set as NULL, the encryption mode is set as "aes-128-xts" by default. + + @return * 0: Success. + * < 0: Failure. + */ +- (int)setEncryptionMode:(NSString* _Nullable)encryptionMode; + +/** Sets the local video display mode. + + **Deprecated** from v3.0.0, use the new [setLocalRenderMode]([AgoraRtcEngineKit setLocalRenderMode:mirrorMode:]) method instead. + + This method can be invoked multiple times during a call to change the display mode. + + @param mode Sets the local video display mode. See AgoraVideoRenderMode. + + @return * 0: Success. +* < 0: Failure. + */ +- (int)setLocalRenderMode:(AgoraVideoRenderMode)mode; + +/** Sets the remote video display mode. + + **Deprecated** from v3.0.0, use the new [setRemoteRenderMode]([AgoraRtcEngineKit setRemoteRenderMode:renderMode:mirrorMode:]) method instead. + + This method can be invoked multiple times during a call to change the display mode. + + @param uid User ID of the remote user sending the video streams. + @param mode Sets the remote video display mode. See AgoraVideoRenderMode. + + @return * 0: Success. +* < 0: Failure. + */ +- (int)setRemoteRenderMode:(NSUInteger)uid mode:(AgoraVideoRenderMode)mode; + +/** Sets the local video mirror mode. + + **Deprecated** from v3.0.0, use the [setupLocalVideo]([AgoraRtcEngineKit setupLocalVideo:]) or [setLocalRenderMode]([AgoraRtcEngineKit setLocalRenderMode:mirrorMode:]) method instead. + + @warning Call this method after calling the initializing the local video view by calling `setupLocalVideo`. + @param mode Sets the local video mirror mode. See AgoraVideoMirrorMode. + + @return * 0: Success. +* < 0: Failure. + */ +- (int)setLocalVideoMirrorMode:(AgoraVideoMirrorMode)mode; + +/** Enables interoperability with the Agora Web SDK. + + **Deprecated** from v3.0.0. As of v3.0.0, the Native SDK automatically enables interoperability with the Web SDK, so you no longer need to call this method. + + - This method is applicable to the interactive live streaming profile only. In the Communication profile, the SDK is interoperable with the Web SDK by default. + - If the channel has Web SDK users, ensure that you call this method, or the video of the Native user will be a black screen for the Web user. + + @param enabled Sets whether to enable/disable interoperability with the Agora Web SDK: + + * YES: Enable. + * NO: (Default) Disable. + + @return * 0: Success. +* < 0: Failure. + */ +- (int)enableWebSdkInteroperability:(BOOL)enabled; + +/** Adds a watermark image to the local video or CDN live stream. + + **Deprecated** from v2.9.1. Use the new [addVideoWatermark]([AgoraRtcEngineKit addVideoWatermark:options:]) method. + + This method adds a PNG watermark to the local video stream for the capturing device, channel audience, or CDN live audience to see and capture. + + To add the PNG file onto a CDN live publishing stream only, see the [setLiveTranscoding]([AgoraRtcEngineKit setLiveTranscoding:]) method. + +**Note:** + +* The URL descriptions are different for the local video and CDN live streams: + * In a local video stream, `url` in AgoraImage refers to the local file path of the added watermark image file in the local video stream. + * In a CDN live stream, `url` in AgoraImage refers to the URL address of the added watermark image in the CDN live streaming. +* The source file of the watermark image must be in the PNG file format. If the width and height of the PNG file differ from your settings in this method, the PNG file is cropped to conform to your settings. +* The SDK supports adding only one watermark image onto a local video or CDN live stream. The newly added watermark image replaces the previous one. +* If you set `orientationMode` as `Adaptive` in the [setVideoEncoderConfiguration]([AgoraRtcEngineKit setVideoEncoderConfiguration:]) method, the watermark image rotates with the video frame and rotates around the upper left corner of the watermark image. + +@param watermark Watermark image to be added to the local video stream. See AgoraImage. + +@return * 0: Success. +* < 0: Failure. + */ +- (int)addVideoWatermark:(AgoraImage* _Nonnull)watermark NS_SWIFT_NAME(addVideoWatermark(_:))__deprecated_msg("use addVideoWatermark:url options instead."); + +/** Starts an audio recording. + + **Deprecated** from v2.9.1. Use [startAudioRecordingWithConfig]([AgoraRtcEngineKit startAudioRecordingWithConfig:]) instead. + + This method has a fixed sample rate of 32 kHz. + + The SDK allows recording during a call. Supported formats: + + * .wav: Large file size with high fidelity. + * .aac: Small file size with low fidelity. + + Ensure that the directory to save the recording file exists and is writable. You can call this method after calling the [joinChannelByToken]([AgoraRtcEngineKit joinChannelByToken:channelId:info:uid:joinSuccess:]) method. The recording automatically stops when you call the [leaveChannel]([AgoraRtcEngineKit leaveChannel:]) method. + + @param filePath Absolute file path of the recording file. The string of the file name is in UTF-8. + @param quality Sets the audio recording quality. See AgoraAudioRecordingQuality. + + @return * 0: Success. +* < 0: Failure. + */ +- (int)startAudioRecording:(NSString* _Nonnull)filePath quality:(AgoraAudioRecordingQuality)quality __deprecated_msg("use startAudioRecordingWithConfig:config instead."); + +/** Starts an audio call test. + +**Deprecated** from v2.4. + +This method launches an audio call test to determine whether the audio devices (for example, headset and speaker) and the network connection are working properly. + +To conduct the test: + +- The user speaks and the sampled audio data is played back within 10 seconds. +- If the user can hear the sampled audio data within 10 seconds, the audio devices and network connection are working properly. + + **Note:** + + * After calling this method, always call the stopEchoTest method to end the test. Otherwise, the app cannot run the next echo test, nor can it call the [joinChannelByToken]([AgoraRtcEngineKit joinChannelByToken:channelId:info:uid:joinSuccess:]) method to start a new call. + * In the interactive live streaming profile, only the hosts can call this method. If the user switches from the Communication to interactive live streaming profile, the user must call the [setClientRole](setClientRole:) method to change the user role from an audience (default) to a host before calling this method. + @see [startEchoTestWithInterval]([AgoraRtcEngineKit startEchoTestWithInterval:successBlock:]) + @param successBlock The SDK triggers the `successBlock` callback if this method call is successful. + + @return * 0: Success. +* < 0: Failure. + */ +- (int)startEchoTest:(void (^_Nullable)(NSString* _Nonnull channel, NSUInteger uid, NSInteger elapsed))successBlock __deprecated_msg("use startEchoTestWithInterval instead."); + +/** Sets the preferences for the video quality. (interactive live streaming only). + +**Deprecated** from v2.4. + +Under unreliable network connections or the device's CPU is overloaded, the video quality may be affected. You can use this method to choose the video smoothness (frame rate) over the image quality or vice versa. + + @param preferFrameRateOverImageQuality Sets the video quality preference: + + * YES: Frame rate over image quality. + * NO: (Default) Image quality over frame rate. + + @return * 0: Success. +* < 0: Failure. + */ +- (int)setVideoQualityParameters:(BOOL)preferFrameRateOverImageQuality __deprecated_msg("use AgoraDegradationPreference instead."); + +/** Initializes the AgoraRtcEngineKit object. + + **Deprecated** from v2.3. + + @see [sharedEngineWithappId]([AgoraRtcEngineKit sharedEngineWithAppId:delegate:]) + @param AppId App ID issued to you by Agora. Apply for a new App ID from Agora if it is missing from your kit. Each project is assigned a unique App ID. The App ID identifies your project and organization in the [joinChannelByToken]([AgoraRtcEngineKit joinChannelByToken:channelId:info:uid:joinSuccess:]) method to access the Agora Global Network, and enable one-to-one or one-to-more communication or the interactive live streaming sessions using a unique channel name for your App ID. + @param errorBlock Error code: AgoraErrorCode. + */ ++ (instancetype _Nonnull)sharedEngineWithAppId:(NSString* _Nonnull)AppId error:(void (^_Nullable)(AgoraErrorCode errorCode))errorBlock __deprecated_msg("use sharedEngineWithAppId:delegate: instead."); + +/** Disables the audio function in a channel. + +**Deprecated** from v2.3 + + @see disableAudio + @return * 0: Success. +* < 0: Failure. + */ +- (int)pauseAudio __deprecated_msg("use disableAudio instead."); + +/** Resumes the audio in a channel. + + **Deprecated** from v2.3 + + @see enableAudio + @return * 0: Success. +* < 0: Failure. + */ +- (int)resumeAudio __deprecated_msg("use enableAudio instead."); + +/** Sets the high-quality audio parameters. + + Replaced with [setAudioProfile](setAudioProfile:scenario:). + +**Deprecated** from v2.3. + + @param fullband Sets whether to enable/disable full-band codec (48 kHz sample rate). Not compatible with versions earlier than v1.7.4. + + * YES: Enable full-band codec. + * NO: Disable full-band codec. + @param stereo Sets whether to enable/disable stereo codec. Not compatible with versions earlier than v1.7.4. + + * YES: Enable stereo codec. + * NO: Disable stereo codec. + @param fullBitrate Sets whether to enable/disable high-bitrate mode. Recommended in voice-only mode. + + * YES: Enable high-bitrate mode. + * NO: Disable high-bitrate mode. + @return * 0: Success. + * < 0: Failure. + */ +- (int)setHighQualityAudioParametersWithFullband:(BOOL)fullband stereo:(BOOL)stereo fullBitrate:(BOOL)fullBitrate __deprecated_msg("use setAudioProfile:scenario: instead."); + +#if (!(TARGET_OS_IPHONE) && (TARGET_OS_MAC)) +/** Sets the speakerphone volume. (macOS only.) + + **Deprecated** from v2.3. + + @see [setDeviceVolume](setDeviceVolume:volume:). + @param volume Sets the speakerphone volume. The value ranges between 0 (lowest volume) and 255 (highest volume). + + @return * 0: Success. +* < 0: Failure. + */ +- (int)setSpeakerphoneVolume:(NSUInteger)volume __deprecated_msg("use setDeviceVolume:volume: instead."); + +/** Starts screen sharing. (macOS only.) + +**Deprecated** from v2.4. + + @see [startScreenCaptureByDisplayId]([AgoraRtcEngineKit startScreenCaptureByDisplayId:rectangle:parameters:]) + @see [startScreenCaptureByWindowId]([AgoraRtcEngineKit startScreenCaptureByWindowId:rectangle:parameters:]) + @param windowId Sets to share the whole screen, a specified window, or a specified region: + * Share the whole screen: Set `windowId` as 0 and set `rect` as nil. + * Share the specified window: Set `windowId` not as 0. Each window has a `windowId` that is not 0. + * Share the specified region: Set `windowId` as 0 and set `rect` not as nil. You can share the specified region, for example by dragging the mouse (the logic is implemented by yourself). The specified region is a region on the whole screen. Currently, sharing a specified region in a specific window is not supported. + @param captureFreq (Mandatory) The captured frame rate. The value ranges between 1 fps and 15 fps. + @param bitRate The captured bitrate. + @param rect Specifies the screen-sharing region. `rect` is valid when `windowsId` is set as 0. When you set `rect` as nil, the whole screen is shared. + @return * 0: Success. +* < 0: Failure. + */ +- (int)startScreenCapture:(NSUInteger)windowId withCaptureFreq:(NSInteger)captureFreq bitRate:(NSInteger)bitRate andRect:(CGRect)rect __deprecated_msg("use startScreenCaptureByDisplayId or startScreenCaptureByWindowId: instead."); + +#endif + +/** Sets the video profile. + + **Deprecated** from v2.3. + + Each video profile includes a set of parameters, such as the resolution, frame rate, and bitrate. If the camera device does not support the specified resolution, the SDK automatically chooses a suitable camera resolution, keeping the encoder resolution specified by setVideoProfile. + + You can call this method either before or after joining a channel. + + **Note:** + + * Always set the video profile after calling the [enableVideo](enableVideo) method. + * Always set the video profile before calling the [joinChannelByToken]([AgoraRtcEngineKit joinChannelByToken:channelId:info:uid:joinSuccess:]) or [startPreview]([AgoraRtcEngineKit startPreview]) method. + * If you do not need to set the video profile after joining the channel, call this method before calling the enableVideo method to reduce the render time of the first video frame. + + @see [setVideoEncoderConfiguration]([AgoraRtcEngineKit setVideoEncoderConfiguration:]) + @param profile Sets the video profile. See AgoraVideoProfile. + @param swapWidthAndHeight Sets whether to swap the width and height of the video: + + * YES: Swap the width and height. The video is in portrait mode. + * NO: (Default) Do not swap the width and height. The video remains in landscape mode. + + The width and height of the output video are consistent with the set video profile. + + @return * 0: Success. + * < 0: Failure. + */ +- (int)setVideoProfile:(AgoraVideoProfile)profile swapWidthAndHeight:(BOOL)swapWidthAndHeight __deprecated_msg("use setVideoEncoderConfiguration: instead."); + +/** Sets the video encoding profile manually. + + **Deprecated** from v2.3. + + If you do not need to change the video profile after joining the channel, Agora recommends calling this method before calling the enableVideo method to reduce the render time of the first video frame. + + @see [setVideoEncoderConfiguration]([AgoraRtcEngineKit setVideoEncoderConfiguration:]) + @param size Sets the size of the video. The highest value is 1280 * 720. + @param frameRate Sets the frame rate of the video. The highest value is 30. You can set it to 5, 10, 15, 24, 30, and so on. + @param bitrate Sets the bitrate of the video. You need to manually work out the bitrate according to the width, height, and frame rate. See the bitrate table in AgoraVideoEncoderConfiguration. With the same width and height, the bitrate varies with the change of the frame rate: + + * If the frame rate is 5 fps, divide the recommended bitrate by 2. + * If the frame rate is 15 fps, use the recommended bitrate. + * If the frame rate is 30 fps, multiply the recommended bitrate by 1.5. + * Calculate your bitrate with the ratio if you choose other frame rates. + + For example, the resolution is 320 * 240 and the frame rate is 15 fps, hence, the bitrate is 200: + + * If the frame rate is 5 fps, the bitrate is 100. + * If the frame rate is 30 fps, the bitrate is 300. + * If you set a bitrate beyond the proper range, the SDK automatically adjusts the bitrate to a value within the proper range. + */ +- (int)setVideoResolution:(CGSize)size andFrameRate:(NSInteger)frameRate bitrate:(NSInteger)bitrate __deprecated_msg("use setVideoEncoderConfiguration: instead."); + +#if (!(TARGET_OS_IPHONE) && (TARGET_OS_MAC)) +/** Gets the type of devices, such as audio sampling and playback device. (macOS only.) + + **Deprecated** from v2.3. + + @see [getDeviceInfo](getDeviceInfo:). + @param type Device type: AgoraMediaDeviceType. + @return * Returns the device ID of the device, if this method call is successful. + * nil: Failure. + */ +- (NSString* _Nullable)getDeviceId:(AgoraMediaDeviceType)type __deprecated_msg("use getDeviceInfo: instead."); +#endif + +/** Plays a specified audio effect. + + **Deprecated** from v2.3. + + @see [playEffect]([AgoraRtcEngineKit playEffect:filePath:loopCount:pitch:pan:gain:publish:startPos:])3 + @param soundId ID of the audio effect. Each audio effect has a unique ID. + + **Note:** + + - If you preloaded the audio effect into the memory through the [preloadEffect]([AgoraRtcEngineKit preloadEffect:filePath:]) method, ensure that the `soundID` value is set to the same value as in `preloadEffect`. + - For the audio file formats supported by this method, see + [What formats of audio files does the Agora RTC SDK support](https://docs.agora.io/en/faq/audio_format). + + @param filePath Absolute path of the audio effect file. + @param loopCount Sets the number of times looping the audio effect: + + * 0: Plays the audio effect once. + * 1: Plays the audio effect twice. + * -1: Plays the audio effect in an indefinite loop until you call the [stopEffect]([AgoraRtcEngineKit stopEffect:]) or [stopAllEffects]([AgoraRtcEngineKit stopAllEffects]) method + + @param pitch Sets whether to change the pitch of the audio effect. The value ranges between 0.5 and 2. + The default value is 1 (no change to the pitch). The lower the value, the lower the pitch. + @param pan Sets the spatial position of the audio effect. The value ranges between -1.0 and 1.0. + + * 0.0: The audio effect displays ahead. + * 1.0: The audio effect displays to the right. + * -1.0: The audio effect displays to the left. + + @param gain Sets the volume of the sound effect. The value ranges between 0.0 and 100.0 (default). The lower the value, the lower the volume of the sound effect. + @return * 0: Success. +* < 0: Failure. + */ +- (int)playEffect:(int)soundId filePath:(NSString* _Nullable)filePath loopCount:(int)loopCount pitch:(double)pitch pan:(double)pan gain:(double)gain __deprecated_msg("use playEffect:filePath:loopCount:pitch:pan:gain:publish:startPos instead."); + +/** Returns the media engine version. + + **Deprecated** from v2.3. + + @see getSdkVersion + + @return The media engine version in the string format. + */ ++ (NSString* _Nonnull)getMediaEngineVersion __deprecated; + +#pragma mark Deprecated Blocks + +/**----------------------------------------------------------------------------- + * @name Deprecated Blocks + * ----------------------------------------------------------------------------- + */ + +/** Reports which users are speaking and the speakers' volume. + + **Deprecated** from v1.1. + + This callback is disabled by default and can be enabled by the `enableAudioVolumeIndication` method. + + In the returned speakers' array: + + * If `uid` is 0 (the local user is the speaker), the returned volume is `totalVolume`. + * If `uid` is not 0 and `volume` is 0, the specified user did not speak. + * If a `uid` is found in the previous speakers' array but not in the current speakers' array, the specified user did not speak. + +@see [reportAudioVolumeIndicationOfSpeakers]([AgoraRtcEngineDelegate rtcEngine:reportAudioVolumeIndicationOfSpeakers:totalVolume:]) + +@param audioVolumeIndicationBlock This block includes: + +- speakers: An array containing the user ID and volume information for each speaker. + + - uid: User ID of the speaker. + - volume:Volume of the speaker. The value ranges between 0 (lowest volume) to 255 (highest volume). +- totalVolume: Total volume after audio mixing between 0 (lowest volume) to 255 (highest volume). + */ +- (void)audioVolumeIndicationBlock:(void (^_Nullable)(NSArray* _Nonnull speakers, NSInteger totalVolume))audioVolumeIndicationBlock __deprecated_msg("use delegate instead."); + +/** Occurs when the first local video frame is displayed/rendered on the local video view. + + **Deprecated** from v1.1. + + @see [firstLocalVideoFrameWithSize]([AgoraRtcEngineDelegate rtcEngine:firstLocalVideoFrameWithSize:elapsed:]) + + @param firstLocalVideoFrameBlock This block includes the: + + - width: Width (pixels) of the video stream. + - height: Height (pixels) of the video stream. + - elapsed: Time elapsed (ms) from the local user calling [joinChannelByToken]([AgoraRtcEngineKit joinChannelByToken:channelId:info:uid:joinSuccess:]) until the SDK triggers this callback. + */ +- (void)firstLocalVideoFrameBlock:(void (^_Nullable)(NSInteger width, NSInteger height, NSInteger elapsed))firstLocalVideoFrameBlock __deprecated_msg("use delegate instead."); + +/** Occurs when the engine decodes the first video frame from a specific remote user. + + **Deprecated** from v1.1. + + @see [firstRemoteVideoFrameOfUid]([AgoraRtcEngineDelegate rtcEngine:firstRemoteVideoFrameOfUid:size:elapsed:]) + + @param firstRemoteVideoDecodedBlock This block includes the: + + - uid: User ID of the user sending the video streams. + - width: Width (pixels) of the video stream. + - height: Height (pixels) of the video stream. + - elapsed: Time elapsed (ms) from the remote user calling [joinChannelByToken]([AgoraRtcEngineKit joinChannelByToken:channelId:info:uid:joinSuccess:]) until the SDK triggers this callback. + */ +- (void)firstRemoteVideoDecodedBlock:(void (^_Nullable)(NSUInteger uid, NSInteger width, NSInteger height, NSInteger elapsed))firstRemoteVideoDecodedBlock __deprecated_msg("use delegate instead."); + +/** Occurs when the first remote video frame is rendered. + + **Deprecated** from v1.1. + + @see [firstRemoteVideoDecodedOfUid]([AgoraRtcEngineDelegate rtcEngine:firstRemoteVideoDecodedOfUid:size:elapsed:]) + + @param firstRemoteVideoFrameBlock This block includes the: + + - uid: User ID of the remote user sending the video streams. + - width: Width (pixels) of the video stream. + - height: Height (pixels) of the video stream. + - elapsed: Time elapsed (ms) from the local user calling [joinChannelByToken]([AgoraRtcEngineKit joinChannelByToken:channelId:info:uid:joinSuccess:]) until the SDK triggers this callback. + */ +- (void)firstRemoteVideoFrameBlock:(void (^_Nullable)(NSUInteger uid, NSInteger width, NSInteger height, NSInteger elapsed))firstRemoteVideoFrameBlock __deprecated_msg("use delegate instead."); + +/** Occurs when a user joins a channel. + + **Deprecated** from v1.1. + + If there are other users in the channel when this user joins, the SDK also reports to the app on the existing users who are already in the channel. + + @see [didJoinedOfUid]([AgoraRtcEngineDelegate rtcEngine:didJoinedOfUid:elapsed:]) + + @param userJoinedBlock This block includes the: + + - uid: User ID. If the `uid` is specified in the [joinChannelByToken]([AgoraRtcEngineKit joinChannelByToken:channelId:info:uid:joinSuccess:]) method, the specified user ID is returned. If the user ID is not specified in the joinChannel method, the server automatically assigns a `uid`. + - elapsed: Time elapsed (ms) from the user calling [joinChannelByToken]([AgoraRtcEngineKit joinChannelByToken:channelId:info:uid:joinSuccess:]) until the SDK triggers this callback. + */ +- (void)userJoinedBlock:(void (^_Nullable)(NSUInteger uid, NSInteger elapsed))userJoinedBlock __deprecated_msg("use delegate instead."); + +/** Occurs when a user leaves a call or goes offline. + + **Deprecated** from v1.1. + + The SDK reads the timeout data to determine if a user leaves a channel (or goes offline). If no data packet is received from the user within 15 seconds, the SDK assumes the user is offline. Sometimes a weak network connection may lead to NO detections; therefore, Agora recommends using the [Agora RTM SDK](https://docs.agora.io/en/Real-time-Messaging/product_rtm?platform=All%20Platforms) for reliable offline detection. + + @see [didOfflineOfUid]([AgoraRtcEngineDelegate rtcEngine:didOfflineOfUid:reason:]) + @param userOfflineBlock This block includes the user ID, `uid`. + */ +- (void)userOfflineBlock:(void (^_Nullable)(NSUInteger uid))userOfflineBlock __deprecated_msg("use delegate instead."); + +/** Occurs when a remote user's audio stream is muted/unmuted. + + **Deprecated** from v1.1. + + @see [didAudioMuted]([AgoraRtcEngineDelegate rtcEngine:didAudioMuted:byUid:]) + + @param userMuteAudioBlock This block includes the: + + - uid: ID of the remote user whose audio stream is muted/unmuted. + - muted: Whether the remote user's audio stream is muted/unmuted: + + - YES: Muted. + - NO: Unmuted. + */ +- (void)userMuteAudioBlock:(void (^_Nullable)(NSUInteger uid, BOOL muted))userMuteAudioBlock __deprecated_msg("use delegate instead."); + +/** Occurs when a remote user's video stream playback pauses/resumes. + + **Deprecated** from v1.1. + + @see [didVideoMuted]([AgoraRtcEngineDelegate rtcEngine:didVideoMuted:byUid:]) + @param userMuteVideoBlock This block includes the: + + - uid: ID of the remote user whose video stream playback pauses/resumes. + - muted: Whether the remote user's video playback pauses/resumes: + + - YES: Pauses. + - NO: Resumes. + */ +- (void)userMuteVideoBlock:(void (^_Nullable)(NSUInteger uid, BOOL muted))userMuteVideoBlock __deprecated_msg("use delegate instead."); + +/** Reports the statistics of the uploading local video streams once every two seconds. + + **Deprecated** from v1.1. + + @see [localVideoStats]([AgoraRtcEngineDelegate rtcEngine:localVideoStats:]) + @param localVideoStatBlock This block includes the: + + - sentBitrate: Bitrate sent since last count. + - sentFrameRate: Frame rate sent since last count. + */ +- (void)localVideoStatBlock:(void (^_Nullable)(NSInteger sentBitrate, NSInteger sentFrameRate))localVideoStatBlock __deprecated_msg("use delegate instead."); + +/** Reports the statistics of the receiving remote video streams once every two seconds. + + **Deprecated** from v1.1. + + @see [remoteVideoStats]([AgoraRtcEngineDelegate rtcEngine:remoteVideoStats:]) + + @param remoteVideoStatBlock This block includes the: + + - uid: User ID of the remote user sending the video streams. + - delay: Time delay (ms). + - receivedBitrate: Bitrate received since last count. + - decoderOutputFrameRate: Frame rate encoder output since last count. + - renderererOutputFrameRate Frame rate render output since last count. + */ +- (void)remoteVideoStatBlock:(void (^_Nullable)(NSUInteger uid, NSInteger delay, NSInteger receivedBitrate, NSInteger decoderOutputFrameRate, NSInteger rendererOutputFrameRate))remoteVideoStatBlock __deprecated_msg("use delegate instead."); + +/** Reports the statistics of the receiving remote audio streams once every two seconds. + + **Deprecated** from v1.1. + + @see [remoteAudioStats]([AgoraRtcEngineDelegate rtcEngine:remoteAudioStats:]) + + @param remoteAudioStatBlock This block includes the: + + - uid: User ID of the user sending the audio streams. + - quality: Audio receiving quality of the user + - networkTransportDelay: Network delay from the sender to the receiver. + - jitterBufferDelay: Jitter buffer delay at the receiver. + - audioLossRate: Audio frame loss rate in the reported interval. + */ +- (void)remoteAudioStatBlock:(void (^_Nullable)(NSUInteger uid, NSInteger quality, NSInteger networkTransportDelay, NSInteger jitterBufferDelay, NSInteger audioLossRate, NSInteger numChannels, NSInteger receivedSampleRate, NSInteger receivedBitrate, NSInteger totalFrozenTime, NSInteger frozenRate, NSInteger totalActiveTime, NSInteger publishDuration, NSInteger qoeQuality, NSInteger qualityChangedReason, NSInteger mosValue))remoteAudioStatBlock __deprecated_msg("use delegate instead."); + +/** Occurs when the camera turns on and is ready to capture the video. + + **Deprecated** from v1.1. + + @see [rtcEngineCameraDidReady]([AgoraRtcEngineDelegate rtcEngineCameraDidReady:]) + */ +- (void)cameraReadyBlock:(void (^_Nullable)(void))cameraReadyBlock __deprecated_msg("use delegate instead."); + +/** Occurs when the connection between the SDK and the server is lost. + + **Deprecated** from v1.1. + + @see [rtcEngineConnectionDidInterrupted]([AgoraRtcEngineDelegate rtcEngineConnectionDidInterrupted:]) + @see [rtcEngineConnectionDidLost]([AgoraRtcEngineDelegate rtcEngineConnectionDidLost:]) + */ +- (void)connectionLostBlock:(void (^_Nullable)(void))connectionLostBlock __deprecated_msg("use delegate instead."); + +/** Occurs when a user rejoins the channel after disconnection due to network problems. + +When the client loses connection with the server because of network problems, the SDK automatically attempts to reconnect and triggers this callback upon reconnection. + + **Deprecated** from v1.1. + + @see [didRejoinChannel]([AgoraRtcEngineDelegate rtcEngine:didRejoinChannel:withUid:elapsed:]) + @param rejoinChannelSuccessBlock This block includes the: + + - channel: Channel name. + - uid: User ID. + - elapsed: Time elapsed (ms) from starting to reconnect until this callback occurs. + */ +- (void)rejoinChannelSuccessBlock:(void (^_Nullable)(NSString* _Nonnull channel, NSUInteger uid, NSInteger elapsed))rejoinChannelSuccessBlock __deprecated_msg("use delegate instead."); + +/** Reports the RtcEngine runtime statistics once every two seconds. + + **Deprecated** from v1.1. + + @see [reportRtcStats]([AgoraRtcEngineDelegate rtcEngine:reportRtcStats:]) + @param rtcStatsBlock RtcEngine runtime statistics. See [AgoraChannelStats](AgoraChannelStats). + */ +- (void)rtcStatsBlock:(void (^_Nullable)(AgoraChannelStats* _Nonnull stat))rtcStatsBlock __deprecated_msg("use delegate instead."); + +/** Occurs when a user leaves a channel. + + **Deprecated** from v1.1. + + When the app calls the [leaveChannel]([AgoraRtcEngineKit leaveChannel:]) method, the SDK uses this callback to notify the app that a user leaves a channel. + + With this callback, the app gets information, such as the call duration and statistics of the received/transmitted data in the [audioQualityOfUid]([AgoraRtcEngineDelegate rtcEngine:audioQualityOfUid:quality:delay:lost:]) callback. + + @see [didLeaveChannelWithStats]([AgoraRtcEngineDelegate rtcEngine:didLeaveChannelWithStats:]) + @param leaveChannelBlock Statistics of the call. See [AgoraChannelStats](AgoraChannelStats). + */ +- (void)leaveChannelBlock:(void (^_Nullable)(AgoraChannelStats* _Nonnull stat))leaveChannelBlock __deprecated_msg("use delegate instead."); + +/** Reports the audio quality of the current call once every two seconds. + + **Deprecated** from v1.1. + + @see [audioQualityOfUid]([AgoraRtcEngineDelegate rtcEngine:audioQualityOfUid:quality:delay:lost:]) + @param audioQualityBlock This block includes the: + + - uid: User ID of the speaker. + - quality: Audio quality of the user: AgoraNetworkQuality. + - delay: Time delay (ms). + - lost: Audio packet loss rate (%). + */ +- (void)audioQualityBlock:(void (^_Nullable)(NSUInteger uid, AgoraNetworkQuality quality, NSUInteger delay, NSUInteger lost))audioQualityBlock __deprecated_msg("use delegate instead."); + +/** Reports the network quality of a specified user in the Communication or Live Broadcast profile once every two seconds. + + **Deprecated** from v1.1. + + @see [networkQuality]([AgoraRtcEngineDelegate rtcEngine:networkQuality:txQuality:rxQuality:]) + @param networkQualityBlock This block includes the: + + - uid: User ID. The network quality of the user with this `uid` is reported. If `uid` is 0, the local network quality is reported. + - txQuality: The transmission quality of the user: AgoraNetworkQuality. + - rxQuality: The receiving quality of the user: AgoraNetworkQuality. + */ +- (void)networkQualityBlock:(void (^_Nullable)(NSUInteger uid, AgoraNetworkQuality txQuality, AgoraNetworkQuality rxQuality))networkQualityBlock __deprecated_msg("use delegate instead."); + +/** Reports the last mile network quality of the local user once every two seconds before the user joins a channel. + + **Deprecated** from v1.1. + +Last mile refers to the connection between the local device and Agora's edge server. After the app calls the [enableLastmileTest]([AgoraRtcEngineKit enableLastmileTest]) method, this callback reports once every two seconds the uplink and downlink last mile network conditions of the local user before the user joins a channel. + + @param lastmileQualityBlock Network quality. See [AgoraNetworkQuality](AgoraNetworkQuality). + */ +- (void)lastmileQualityBlock:(void (^_Nullable)(AgoraNetworkQuality quality))lastmileQualityBlock __deprecated_msg("use delegate instead."); + +/** Reports a media engine event. + + **Deprecated** from v1.1. + */ +- (void)mediaEngineEventBlock:(void (^_Nullable)(NSInteger code))mediaEngineEventBlock __deprecated_msg("use delegate instead."); + +@end +/** + The AgoraMediaRecorder class. + + @since v3.5.2 + */ +@class AgoraMediaRecorder; +/** The AgoraMediaRecorderDelegate protocol. + + @since v3.5.2 + */ +@protocol AgoraMediaRecorderDelegate +#pragma mark Media Recorder Delegate Methods +/**----------------------------------------------------------------------------- + * @name Media Recorder Delegate Methods + * ----------------------------------------------------------------------------- + */ + +/** + Occurs when the recording state changes. + + @since v3.5.2 + + When the local audio and video recording state changes, the SDK triggers this callback to report the current recording state and the reason for the change. + + @param recorder AgoraMediaRecorder + @param state The current recording state. See AgoraMediaRecorderState. + @param error The reason for the state change. See AgoraMediaRecorderErrorCode. + */ +- (void)mediaRecorder:(AgoraMediaRecorder* _Nonnull)recorder stateDidChanged:(AgoraMediaRecorderState)state error:(AgoraMediaRecorderErrorCode)error; + +/** + Occurs when the recording information is updated. + + @since v3.5.2 + + After you successfully enable the local audio and video recording, the SDK periodically triggers this callback based on the + set value of `recorderInfoUpdateInterval`. This callback reports the filename, duration, and size of the current recording file. + + @param recorder AgoraMediaRecorder + @param info Information for the recording file. See AgoraMediaRecorderInfo. + */ +- (void)mediaRecorder:(AgoraMediaRecorder* _Nonnull)recorder informationDidUpdated:(AgoraMediaRecorderInfo* _Nonnull)info; + +@end +/** + The AgoraMediaRecorder interface, for recording the audio and video on the client. AgoraMediaRecorder can record + the following content: + + - The audio captured by the local microphone and encoded in AAC format. + - The video captured by the local camera and encoded by the SDK. + + @since v3.5.2 + + @note In the `Communication` channel profile, this function is unavailable when there are users using versions of the SDK earlier than v3.0.0 in the channel. + */ +__attribute__((visibility("default"))) @interface AgoraMediaRecorder : NSObject + +/** + Creates an AgoraMediaRecorder instance. + + @since v3.5.2 + + @note Call this method after creating AgoraRtcEngineKit. + + @param engine AgoraRtcEngineKit + @param delegate AgoraMediaRecorderDelegate + + @return AgoraMediaRecorder + */ ++ (instancetype _Nonnull)sharedMediaRecorderWithRtcEngine:(AgoraRtcEngineKit* _Nonnull)engine delegate:(id _Nullable)delegate; + +/** + Destroys the AgoraMediaRecorder instance. + + @since v3.5.2 + + This method releases AgoraRtcEngineKit and all other resources used by AgoraMediaRecorder. After calling this method, + if you want to enable the recording again, you must call [sharedMediaRecorderWithRtcEngine]([AgoraMediaRecorder sharedMediaRecorderWithRtcEngine:delegate:]) to get AgoraMediaRecorder. + */ ++ (void)destroy; + +/** Enables/Disables dispatching delegate methods to the main queue. + + @since v3.5.2 + + If disabled, the app should dispatch UI operations to the main queue. + + @param enabled Sets whether or not to dispatch delegate methods to the main queue: + + * YES: Dispatch delegate methods to the main queue. + * NO: Do not dispatch delegate methods to the main queue + + @return * 0: Success. + * < 0: Failure. + */ +- (int)enableMainQueueDispatch:(BOOL)enabled; + +/** + Starts recording the local audio and video. + + @since v3.5.2 + + After successfully getting the object, you can call this method to enable the recording of the local audio and video. + + This method can record the following content: + + - The audio captured by the local microphone and encoded in AAC format. + - The video captured by the local camera and encoded by the SDK. + + The SDK can generate a recording file only when it detects the recordable audio and video streams; when there are no + audio and video streams to be recorded or the audio and video streams are interrupted for more than five seconds, the + SDK stops recording and triggers the [stateDidChanged(AgoraMediaRecorderStateError, AgoraMediaRecorderErrorCodeNoStream)]([AgoraMediaRecorderDelegate mediaRecorder:stateDidChanged:error:])callback. + + @note Call this method after joining the channel. + + @param config The recording configurations. See AgoraMediaRecorderConfiguration. + + @return - 0: Success. + - < 0: Failure. + + - `-2(AgoraErrorCodeInvalidArgument)`: The parameter is invalid. Ensure the following: + + - The specified path of the recording file exists and is writable. + - The specified format of the recording file is supported. + - The maximum recording duration is correctly set. + + - `-4(AgoraErrorCodeNotSupported)`: AgoraRtcEngineKit does not support the request due to one of the following reasons: + + - The recording is ongoing. + - The recording stops because an error occurs. + + - `-7(AgoraErrorCodeNotInitialized)`: This method is called before you create AgoraRtcEngineKit. + Ensure that you have called [sharedMediaRecorderWithRtcEngine]([AgoraMediaRecorder sharedMediaRecorderWithRtcEngine:delegate:]) before calling `startRecording`. + */ +- (int)startRecording:(AgoraMediaRecorderConfiguration* _Nonnull)config; + +/** + Stops recording the local audio and video. + + @since v3.5.2 + + @note Call this method after calling [startRecording]([AgoraMediaRecorder startRecording:]). + + @return - 0: Success. + - < 0: Failure. + + - `-7(AgoraErrorCodeNotInitialized)`: This method is called before you create AgoraRtcEngineKit. + Ensure that you have called [sharedMediaRecorderWithRtcEngine]([AgoraMediaRecorder sharedMediaRecorderWithRtcEngine:delegate:]) before calling `stopRecording`. + */ +- (int)stopRecording; + +@end diff --git a/integration_test_app/iris_integration_test/third_party/agora/rtc/include/AgoraVideoFrame.h b/integration_test_app/iris_integration_test/third_party/agora/rtc/include/AgoraVideoFrame.h new file mode 100644 index 000000000..e52025c32 --- /dev/null +++ b/integration_test_app/iris_integration_test/third_party/agora/rtc/include/AgoraVideoFrame.h @@ -0,0 +1,280 @@ +// +// AgoraVideoFrame.h +// AgoraRtcEngineKit +// +// Copyright (c) 2020 Agora. All rights reserved. +// + +#import +#import "AgoraEnumerates.h" +#import "AgoraObjects.h" + +/** The protocol of the raw video data. + + @note This protocol applies to iOS only. + */ +@protocol AgoraVideoDataFrameProtocol +@required + +/** Gets the video data captured by the local camera. + + @since v3.4.5 + + After you successfully register the raw video frame protocol, the SDK triggers + this callback each time a video frame is received. You can get the video data + captured by the local camera in `videoFrame` and then process the video data + according to your scenario. After processing, you can use `videoFrame` to pass + the processed video data back to the SDK. + + **Note**: + + - This callback applies to iOS only. + - If you get the video data in RGBA color encoding format, Agora does not + support using this callback to send the processed data in RGBA color encoding + format back to the SDK. + - The video data obtained through this callback has not undergone + preprocessing, such as watermarking, cropping content, rotating, or + image enhancement. + + @param videoFrame The video frame. See AgoraVideoDataFrame. + + @return - YES: Sets the SDK to receive the video frame. + - NO: Sets the SDK to discard the video frame. + */ +- (BOOL)onCaptureVideoFrame:(AgoraVideoDataFrame*)videoFrame; +/** Gets the local pre-encoded video data. + + @since v3.4.5 + + After you successfully register the raw video frame protocol and use + [getObservedFramePosition]([AgoraVideoDataFrameProtocol getObservedFramePosition]) + to set the observation `AgoraVideoFramePositionPreEncoder (1 << 2)`, the SDK + triggers this callback each time a video frame is received. You can get the + local pre-encoded video data in `videoFrame` and then process the video data + according to your scenario. After processing, you can use videoFrame to pass + the processed video data back to the SDK. + + **Note**: + + - This callback applies to iOS only. + - If you get the video data in RGBA color encoding format, Agora does not + support using this callback to send the processed data in RGBA color encoding + format back to the SDK. + - The video data obtained through this callback has not undergone + preprocessing, such as watermarking, cropping content, rotating, or + image enhancement. + + @param videoFrame The video frame. See AgoraVideoDataFrame. + + @return - YES: Sets the SDK to receive the video frame. + - NO: Sets the SDK to discard the video frame. + */ +- (BOOL)onPreEncodeVideoFrame:(AgoraVideoDataFrame*)videoFrame; +/** Gets the incoming remote video data. + + @since v3.4.5 + + After you successfully register the raw video frame and set the return value + of [isMultipleChannelFrameWanted]([AgoraVideoDataFrameProtocol isMultipleChannelFrameWanted]) + as `NO`, the SDK triggers this callback each time a video frame is received. + You can get the incoming remote video data in `videoFrame` and then process + the video data according to your scenario. After processing, you can use + `videoFrame` to pass the processed video data back to the SDK. + + **Note**: + + - This callback applies to iOS only. + - If you get the video data in RGBA color encoding format, Agora does not + support using this callback to send the processed data in RGBA color + encoding format back to the SDK. + + @param videoFrame The video frame. See AgoraVideoDataFrame. + @param uid The user ID of the remote user. + + @return - YES: Sets the SDK to receive the video frame. + - NO: Sets the SDK to discard the video frame. + */ +- (BOOL)onRenderVideoFrame:(AgoraVideoDataFrame*)videoFrame forUid:(unsigned int)uid; +/** Sets the format of the raw video data output by the SDK. + + @since v3.4.5 + + If you want to get raw video data in a color encoding format other than YUV + 420, you need to implement the `getVideoFormatPreference` callback in + AgoraVideoDataFrameProtocol. After you successfully register the raw video + frame protocol, the SDK triggers this callback each time a video frame is + received. You need to set the desired color encoding format of the video + data in the return value of this callback. + + @note This method applies to iOS only. + + @return The color encoding format of the raw video data output by the SDK. + See AgoraVideoFrameType. + */ +- (AgoraVideoFrameType)getVideoFormatPreference; +/** Sets whether to rotate the raw video data output by the SDK. + + @since v3.4.5 + + If you want to get raw video data that has been rotated according to the + value of `rotation` in AgoraVideoDataFrame, you need to implement the + `getRotationApplied` callback in AgoraVideoDataFrameProtocol. After you + successfully register the raw video frame protocol, the SDK triggers this + callback each time a video frame is received. You need to set whether to + rotate the observed raw video data in the return value of this callback. + + **Note**: + + - This method applies to iOS only. + - This function supports video data in RGBA and YUV 420 color encoding + formats only. + + @return Whether to rotate the raw video data output by the SDK: + + - YES: Rotate the raw video data. + - NO: (Default) Do not rotate the raw video data. + */ +- (BOOL)getRotationApplied; +/** Sets whether to mirror the raw video data output by the SDK. + + @since v3.4.5 + + If you want to get the mirrored raw video data, you need to implement the + `getMirrorApplied` callback in AgoraVideoDataFrameProtocol. After you + successfully register the raw video frame observer, the SDK triggers this + callback each time a video frame is received. You need to set whether to + mirror the observed raw video data in the return value of this callback. + + **Note**: + + - This method applies to iOS only. + - This function supports video data in RGBA and YUV 420 color encoding + formats only. + + @return Whether to mirror the raw video data output by the SDK: + + - YES: Mirror the raw video data. + - NO: (Default) Do not mirror the raw video data. + */ +- (BOOL)getMirrorApplied; +/** Sets the video observation positions. + + @since v3.4.5 + + After you successfully register the raw video frame observer, the SDK uses + the `getObservedFramePosition` callback to determine at each specific + video-frame processing node whether to trigger the following callbacks: + + - [onCaptureVideoFrame]([AgoraVideoDataFrameProtocol onCaptureVideoFrame:]) + - [onPreEncodeVideoFrame]([AgoraVideoDataFrameProtocol onPreEncodeVideoFrame:]) + - [onRenderVideoFrame]([AgoraVideoDataFrameProtocol onRenderVideoFrame:forUid:]) or + [onRenderVideoFrameEx]([AgoraVideoDataFrameProtocol onRenderVideoFrameEx:forUid:inChannel:]) + + You can set the position or positions that you want to observe by modifying + the return value of `getObservedFramePosition` according to your scenario. + + **Note**: + + - This method applies to iOS only. + - To observe multiple positions, use `|` (the OR operator). + - The default return value of this callback is + `AgoraVideoFramePositionPostCapture (1 << 0)` and + `AgoraVideoFramePositionPreRenderer (1 << 1)`. + - To conserve system resources of the device, you can reduce the number of + observation positions appropriately according to your scenario. + + @return The bit mask of the observation positions. See AgoraVideoFramePosition. + */ +- (AgoraVideoFramePosition)getObservedFramePosition; + +/** Sets whether the SDK outputs remote video data received in multiple channels. + + @since v3.4.5 + + In a multi-channel (AgoraRtcChannel) scenario, if you want to get the remote + video data received in multiple channels, you need to implement the + `isMultipleChannelFrameWanted` callback in AgoraVideoDataFrameProtocol and + set the return value of this callback to `YES`. The SDK triggers the + [onRenderVideoFrameEx]([AgoraVideoDataFrameProtocol onRenderVideoFrameEx:forUid:inChannel:]) + callback each time a video frame is received, from which you can get the + expected multi-channel video data. + + **Note**: + + - This method applies to iOS only. + - The SDK chooses to trigger either the + [onRenderVideoFrame]([AgoraVideoDataFrameProtocol onRenderVideoFrame:forUid:]) or + [onRenderVideoFrameEx]([AgoraVideoDataFrameProtocol onRenderVideoFrameEx:forUid:inChannel:]) + callback depending on the return value that you set in the + `isMultipleChannelFrameWanted` callback. Agora recommends that you set the + return value as `YES` in a multi-channel scenario. + + @return Whether the SDK outputs remote video data received in multiple channels: + + - YES: The SDK uses `onRenderVideoFrameEx` to output remote video data + received in multiple channels. + - NO: (Default) The SDK uses `onRenderVideoFrame` to output remote video data + received in a single channel. + */ +- (BOOL)isMultipleChannelFrameWanted; + +/** Gets the remote video data received in multiple channels. + + @since v3.4.5 + + After you successfully register the raw video frame protocol and set the + return value of + [isMultipleChannelFrameWanted]([AgoraVideoDataFrameProtocol isMultipleChannelFrameWanted]) + as `YES`, the SDK triggers this callback each time a video frame is received. + You get the remote video data received in multiple channels in `videoFrame` + and then process the video data according to your scenario. After processing, + you can pass the processed video data back to the SDK. + + **Note**: + + - This callback applies to iOS only. + - If you get the video data in RGBA color encoding format, Agora does not + support using this callback to send the processed data in RGBA color encoding + format back to the SDK. + + @param videoFrame The video frame. See AgoraVideoDataFrame. + @param uid The user ID of the remote user. + @param channelId The channel name. + + @return - YES: Sets the SDK to receive the video frame. + - NO: Sets the SDK to discard the video frame. + */ +- (BOOL)onRenderVideoFrameEx:(AgoraVideoDataFrame*)videoFrame forUid:(unsigned int)uid inChannel:(NSString*)channelId; + +@end + +/** The protocol of local encoded video frame. + + @since v3.4.5 + + @note This protocol applies to iOS only. + */ +@protocol AgoraVideoEncodedFrameProtocol + +@required +/** Gets the local encoded video frame. + + @since v3.4.5 + + After you successfully register the local encoded video frame protocol, the + SDK triggers this callback each time a video frame is received. You can get + the local encoded video frame in `VideoEncodedFrame` and then process the + video data according to your scenario. After processing, you can use + `VideoEncodedFrame` to pass the processed video data back to the SDK. + + @note This callback applies to iOS only. + + @param VideoEncodedFrame The local encoded video frame. + See AgoraVideoEncodedFrame. + + @return - YES: Sets the SDK to receive the video frame. + - NO: Sets the SDK to discard the video frame. + */ +- (BOOL)onVideoEncodedFrame:(AgoraVideoEncodedFrame*)VideoEncodedFrame; + +@end diff --git a/integration_test_app/iris_integration_test/third_party/agora/rtc/include/IAgoraLog.h b/integration_test_app/iris_integration_test/third_party/agora/rtc/include/IAgoraLog.h new file mode 100644 index 000000000..f648c46c1 --- /dev/null +++ b/integration_test_app/iris_integration_test/third_party/agora/rtc/include/IAgoraLog.h @@ -0,0 +1,34 @@ +// +// Agora Media SDK +// +// Copyright (c) 2015 Agora IO. All rights reserved. +// + +#pragma once + +#include + +namespace agora { +namespace commons { +/* +The SDK uses ILogWriter class Write interface to write logs as application +The application inherits the methods Write() to implentation their own log writ + +Write has default implementation, it writes logs to files. +Application can use setLogFile() to change file location, see description of set +*/ +class ILogWriter { + public: + /** user defined log Write function + @param message message content + @param length message length + @return + - 0: success + - <0: failure + */ + virtual int32_t writeLog(const char* message, uint16_t length) = 0; + virtual ~ILogWriter() {} +}; + +} // namespace commons +} // namespace agora diff --git a/integration_test_app/iris_integration_test/third_party/agora/rtc/include/IAgoraMediaEngine.h b/integration_test_app/iris_integration_test/third_party/agora/rtc/include/IAgoraMediaEngine.h new file mode 100644 index 000000000..00de6bbbb --- /dev/null +++ b/integration_test_app/iris_integration_test/third_party/agora/rtc/include/IAgoraMediaEngine.h @@ -0,0 +1,1042 @@ +#ifndef AGORA_MEDIA_ENGINE_H +#define AGORA_MEDIA_ENGINE_H +#include +#include "AgoraBase.h" + +namespace agora { +namespace media { +/** **DEPRECATED** Type of audio device. + */ +enum MEDIA_SOURCE_TYPE { + /** Audio playback device. + */ + AUDIO_PLAYOUT_SOURCE = 0, + /** Microphone. + */ + AUDIO_RECORDING_SOURCE = 1, +}; + +/** + * The channel mode. Set in \ref agora::rtc::IRtcEngine::setAudioMixingDualMonoMode "setAudioMixingDualMonoMode". + * + * @since v3.5.1 + */ +enum AUDIO_MIXING_DUAL_MONO_MODE { + /** + * 0: Original mode. + */ + AUDIO_MIXING_DUAL_MONO_AUTO = 0, + /** + * 1: Left channel mode. This mode replaces the audio of the right channel + * with the audio of the left channel, which means the user can only hear + * the audio of the left channel. + */ + AUDIO_MIXING_DUAL_MONO_L = 1, + /** + * 2: Right channel mode. This mode replaces the audio of the left channel with + * the audio of the right channel, which means the user can only hear the audio + * of the right channel. + */ + AUDIO_MIXING_DUAL_MONO_R = 2, + /** + * 3: Mixed channel mode. This mode mixes the audio of the left channel and + * the right channel, which means the user can hear the audio of the left + * channel and the right channel at the same time. + */ + AUDIO_MIXING_DUAL_MONO_MIX = 3 +}; +/** + * The push position of the external audio frame. + * Set in \ref IMediaEngine::pushAudioFrame(int32_t, IAudioFrameObserver::AudioFrame*) "pushAudioFrame" + * or \ref IMediaEngine::setExternalAudioSourceVolume "setExternalAudioSourceVolume". + * + * @since v3.5.1 + */ +enum AUDIO_EXTERNAL_SOURCE_POSITION { + /** 0: The position before local playback. If you need to play the external audio frame on the local client, + * set this position. + */ + AUDIO_EXTERNAL_PLAYOUT_SOURCE = 0, + /** 1: The position after audio capture and before audio pre-processing. If you need the audio module of the SDK + * to process the external audio frame, set this position. + */ + AUDIO_EXTERNAL_RECORD_SOURCE_PRE_PROCESS = 1, + /** 2: The position after audio pre-processing and before audio encoding. If you do not need the audio module of + * the SDK to process the external audio frame, set this position. + */ + AUDIO_EXTERNAL_RECORD_SOURCE_POST_PROCESS = 2, +}; + +/** + * The IAudioFrameObserver class. + */ +class IAudioFrameObserver { + public: + /** The frame type. */ + enum AUDIO_FRAME_TYPE { + /** 0: PCM16. */ + FRAME_TYPE_PCM16 = 0, // PCM 16bit little endian + }; + /** Definition of AudioFrame */ + struct AudioFrame { + /** The type of the audio frame. See #AUDIO_FRAME_TYPE + */ + AUDIO_FRAME_TYPE type; + /** The number of samples per channel in the audio frame. + */ + int samples; // number of samples for each channel in this frame + /**The number of bytes per audio sample, which is usually 16-bit (2-byte). + */ + int bytesPerSample; // number of bytes per sample: 2 for PCM16 + /** The number of audio channels. + - 1: Mono + - 2: Stereo (the data is interleaved) + */ + int channels; // number of channels (data are interleaved if stereo) + /** The sample rate. + */ + int samplesPerSec; // sampling rate + /** The data buffer of the audio frame. When the audio frame uses a stereo channel, the data buffer is interleaved. + The size of the data buffer is as follows: `buffer` = `samples` × `channels` × `bytesPerSample`. + */ + void* buffer; // data buffer + /** The timestamp (ms) of the external audio frame. You can use this parameter for the following purposes: + - Restore the order of the captured audio frame. + - Synchronize audio and video frames in video-related scenarios, including where external video sources are used. + */ + int64_t renderTimeMs; + /** Reserved parameter. + */ + int avsync_type; + }; + + public: + /** Gets the captured audio frame. + * + * @note To ensure that the captured audio frame has the expected format, + * Agora recommends that you + * call \ref agora::rtc::IRtcEngine::setRecordingAudioFrameParameters "setRecordingAudioFrameParameters" + * after calling \ref IMediaEngine::registerAudioFrameObserver "registerAudioFrameObserver" to + * set the audio capturing format. + * + * @param audioFrame Pointer to AudioFrame. + * @return + * - true: Valid buffer in AudioFrame, and the captured audio frame is sent out. + * - false: Invalid buffer in AudioFrame, and the captured audio frame is discarded. + */ + virtual bool onRecordAudioFrame(AudioFrame& audioFrame) = 0; + /** Gets the audio playback frame for getting the audio. + * + * @note To ensure that the audio playback frame has the expected format, Agora + * recommends that you call \ref agora::rtc::IRtcEngine::setPlaybackAudioFrameParameters "setPlaybackAudioFrameParameters" + * after calling \ref IMediaEngine::registerAudioFrameObserver "registerAudioFrameObserver" to + * set the audio playback format. + * + * @param audioFrame Pointer to AudioFrame. + * @return + * - true: Valid buffer in AudioFrame, and the audio playback frame is sent out. + * - false: Invalid buffer in AudioFrame, and the audio playback frame is discarded. + */ + virtual bool onPlaybackAudioFrame(AudioFrame& audioFrame) = 0; + /** Gets the mixed captured and playback audio frame. + * + * @note + * - This callback only returns the single-channel data. + * - To ensure that the mixed captured and playback audio frame has the + * expected format, Agora recommends that you call + * \ref agora::rtc::IRtcEngine::setMixedAudioFrameParameters "setMixedAudioFrameParameters" + * after calling \ref IMediaEngine::registerAudioFrameObserver "registerAudioFrameObserver" to + * set the mixed audio format. + * + * @param audioFrame Pointer to AudioFrame. + * @return + * - true: Valid buffer in AudioFrame and the mixed captured and playback audio frame is sent out. + * - false: Invalid buffer in AudioFrame and the mixed captured and playback audio frame is discarded. + */ + virtual bool onMixedAudioFrame(AudioFrame& audioFrame) = 0; + /** Gets the audio frame of a specified user before mixing. + * + * The SDK triggers this callback if \ref IAudioFrameObserver::isMultipleChannelFrameWanted "isMultipleChannelFrameWanted" returns false. + * + * @note To ensure that the audio playback frame has the expected format, Agora + * recommends that you call \ref agora::rtc::IRtcEngine::setPlaybackAudioFrameParameters "setPlaybackAudioFrameParameters" + * after calling \ref IMediaEngine::registerAudioFrameObserver "registerAudioFrameObserver" to + * set the audio playback format. + * + * @param uid The user ID + * @param audioFrame Pointer to AudioFrame. + * @return + * - true: Valid buffer in AudioFrame, and the mixed captured and playback audio frame is sent out. + * - false: Invalid buffer in AudioFrame, and the mixed captured and playback audio frame is discarded. + */ + virtual bool onPlaybackAudioFrameBeforeMixing(unsigned int uid, AudioFrame& audioFrame) = 0; + /** Determines whether to receive audio data from multiple channels. + + @since v3.0.1 + + After you register the audio frame observer, the SDK triggers this callback every time it captures an audio frame. + + In the multi-channel scenario, if you want to get audio data from multiple channels, + set the return value of this callback as true. After that, the SDK triggers the + \ref IAudioFrameObserver::onPlaybackAudioFrameBeforeMixingEx "onPlaybackAudioFrameBeforeMixingEx" callback to send you the before-mixing + audio data from various channels. You can also get the channel ID of each audio frame. + + @note + - Once you set the return value of this callback as true, the SDK triggers + only the \ref IAudioFrameObserver::onPlaybackAudioFrameBeforeMixingEx "onPlaybackAudioFrameBeforeMixingEx" callback + to send the before-mixing audio frame. \ref IAudioFrameObserver::onPlaybackAudioFrameBeforeMixing "onPlaybackAudioFrameBeforeMixing" is not triggered. + In the multi-channel scenario, Agora recommends setting the return value as true. + - If you set the return value of this callback as false, the SDK triggers only the `onPlaybackAudioFrameBeforeMixing` callback to send the audio data. + @return + - `true`: Receive audio data from multiple channels. + - `false`: Do not receive audio data from multiple channels. + */ + virtual bool isMultipleChannelFrameWanted() { return false; } + + /** Gets the before-mixing playback audio frame from multiple channels. + * + * After you successfully register the audio frame observer, if you set the return + * value of \ref IAudioFrameObserver::isMultipleChannelFrameWanted "isMultipleChannelFrameWanted" as true, the SDK triggers this callback each + * time it receives a before-mixing audio frame from any of the channel. + * + * @note To ensure that the audio playback frame has the expected format, Agora + * recommends that you call \ref agora::rtc::IRtcEngine::setPlaybackAudioFrameParameters "setPlaybackAudioFrameParameters" + * after calling \ref IMediaEngine::registerAudioFrameObserver "registerAudioFrameObserver" to + * set the audio playback format. + * + * @param channelId The channel ID of this audio frame. + * @param uid The ID of the user sending this audio frame. + * @param audioFrame The pointer to AudioFrame. + * @return + * - `true`: The data in AudioFrame is valid, and send this audio frame. + * - `false`: The data in AudioFrame in invalid, and do not send this audio frame. + */ + virtual bool onPlaybackAudioFrameBeforeMixingEx(const char* channelId, unsigned int uid, AudioFrame& audioFrame) { return true; } +}; + +/** + * The IVideoFrameObserver class. + */ +class IVideoFrameObserver { + public: + /** The video frame type. */ + enum VIDEO_FRAME_TYPE { + /** + * 0: (Default) YUV 420 + */ + FRAME_TYPE_YUV420 = 0, // YUV 420 format + /** + * 1: YUV 422 + */ + FRAME_TYPE_YUV422 = 1, // YUV 422 format + /** + * 2: RGBA + */ + FRAME_TYPE_RGBA = 2, // RGBA format + }; + /** + * The frame position of the video observer. + */ + enum VIDEO_OBSERVER_POSITION { + /** + * 1: The post-capturer position, which corresponds to the video data in the onCaptureVideoFrame callback. + */ + POSITION_POST_CAPTURER = 1 << 0, + /** + * 2: The pre-renderer position, which corresponds to the video data in the onRenderVideoFrame callback. + */ + POSITION_PRE_RENDERER = 1 << 1, + /** + * 4: The pre-encoder position, which corresponds to the video data in the onPreEncodeVideoFrame callback. + */ + POSITION_PRE_ENCODER = 1 << 2, + }; + /** Video frame information. The video data format is YUV 420. The buffer provides a pointer to a pointer. The interface cannot modify the pointer of the buffer, but can modify the content of the buffer only. + */ + struct VideoFrame { + VIDEO_FRAME_TYPE type; + /** Video pixel width. + */ + int width; // width of video frame + /** Video pixel height. + */ + int height; // height of video frame + /** + * For YUV data, the line span of the Y buffer; for RGBA data, the total data length. + */ + int yStride; // stride of Y data buffer + /** + * For YUV data, the line span of the U buffer; for RGBA data, the value is 0. + */ + int uStride; // stride of U data buffer + /** + * For YUV data, the line span of the V buffer; for RGBA data, the value is 0. + */ + int vStride; // stride of V data buffer + /** + * For YUV data, the pointer to the Y buffer; for RGBA data, the data buffer. + */ + void* yBuffer; // Y data buffer + /** + * For YUV data, the pointer to the U buffer; for RGBA data, the value is 0. + */ + void* uBuffer; // U data buffer + /** + * For YUV data, the pointer to the V buffer; for RGBA data, the value is 0. + */ + void* vBuffer; // V data buffer + /** The clockwise rotation angle of the video frame. The supported values are 0, 90, 180, or 270 degrees. + */ + int rotation; // rotation of this frame (0, 90, 180, 270) + /** + * The Unix timestamp (ms) when the video frame is rendered. This timestamp can be used to guide the rendering of + * the video frame. This parameter is required. + */ + int64_t renderTimeMs; + int avsync_type; + }; + + public: + /** Occurs each time the SDK receives a video frame captured by the local camera. + * + * After you successfully register the video frame observer, the SDK triggers this callback each time a video frame is received. In this callback, + * you can get the video data captured by the local camera. You can then pre-process the data according to your scenarios. + * + * After pre-processing, you can send the processed video data back to the SDK by setting the `videoFrame` parameter in this callback. + * + * @note + * - This callback does not support sending processed RGBA video data back to the SDK. + * - The video data that this callback gets has not been pre-processed, without the watermark, the cropped content, the rotation, and the image enhancement. + * + * @param videoFrame Pointer to VideoFrame. + * @return + * - true: Sets the SDK to receive the video frame. + * - false: Sets the SDK to discard the video frame. + */ + virtual bool onCaptureVideoFrame(VideoFrame& videoFrame) = 0; + /** @since v3.0.0 + * + * Occurs each time the SDK receives a video frame before encoding. + * + * After you successfully register the video frame observer, the SDK triggers this callback each time when it receives a video frame. In this callback, you can get the video data before encoding. You can then process the data according to your particular scenarios. + * + * After processing, you can send the processed video data back to the SDK by setting the `VideoFrame` parameter in this callback. + * + * @note + * - As of v3.0.1, if you want to receive this callback, you also need to set `POSITION_PRE_ENCODE(1 << 2)` as a frame position in the \ref getObservedFramePosition "getObservedFramePosition" callback. + * - The video data that this callback gets has been pre-processed, with its content cropped, rotated, and the image enhanced. + * - This callback does not support sending processed RGBA video data back to the SDK. + * + * @param videoFrame A pointer to VideoFrame + * @return + * - true: Sets the SDK to receive the video frame. + * - false: Sets the SDK to discard the video frame. + */ + virtual bool onPreEncodeVideoFrame(VideoFrame& videoFrame) { return true; } + /** Occurs each time the SDK receives a video frame sent by the remote user. + * + * After you successfully register the video frame observer and + * \ref IVideoFrameObserver::isMultipleChannelFrameWanted "isMultipleChannelFrameWanted" + * return false, the SDK triggers this callback each time a video frame is received. + * In this callback, you can get the video data sent by the remote user. You can then + * post-process the data according to your scenarios. + * + * After post-processing, you can send the processed data back to the SDK by setting the `videoFrame` parameter in this callback. + * + * @note + * This callback does not support sending processed RGBA video data back to the SDK. + * + * @param uid ID of the remote user who sends the current video frame. + * @param videoFrame Pointer to VideoFrame. + * @return + * - true: Sets the SDK to receive the video frame. + * - false: Sets the SDK to discard the video frame. + */ + virtual bool onRenderVideoFrame(unsigned int uid, VideoFrame& videoFrame) = 0; + /** Occurs each time the SDK receives a video frame and prompts you to set the video format. + * + * YUV 420 is the default video format. If you want to receive other video formats, register this callback in the IVideoFrameObserver class. + * + * After you successfully register the video frame observer, the SDK triggers this callback each time it receives a video frame. + * You need to set your preferred video data in the return value of this callback. + * + * @return Sets the video format: #VIDEO_FRAME_TYPE + */ + virtual VIDEO_FRAME_TYPE getVideoFormatPreference() { return FRAME_TYPE_YUV420; } + /** Occurs each time the SDK receives a video frame and prompts you whether to + * rotate the raw video frame according to the rotation member in the VideoFrame class. + * + * The SDK does not rotate the raw video frame by default. If you want to receive + * the raw video frame rotated according to the rotation member in the VideoFrame + * class, register this callback in the IVideoFrameObserver class. + * + * After you successfully register the video frame observer, the SDK triggers this + * callback each time it receives a video frame. You need to set whether to rotate + * the raw video frame in the return value of this callback. + * + * @note This callback applies to the video frame in the YUV 420 and RGBA formats only. + * + * @return Sets whether to rotate the raw video frame: + * - true: Rotate. + * - false: (Default) Do not rotate. + */ + virtual bool getRotationApplied() { return false; } + /** Occurs each time the SDK receives a video frame and prompts you whether to mirror the raw video frame. + * + * The SDK does not mirror the raw video frame by default. If you want to receive the raw video frame mirrored, register this callback in the IVideoFrameObserver class. + * + * After you successfully register the video frame observer, the SDK triggers this callback each time a video frame is received. + * You need to set whether to mirror the raw video frame in the return value of this callback. + * + * @note This callback applies to the video frame in the YUV 420 and RGBA formats only. + * + * @return Sets whether to mirror the raw video frame: + * - true: Mirror. + * - false: (Default) Do not mirror. + */ + virtual bool getMirrorApplied() { return false; } + /** + * Sets whether to output the acquired video frame smoothly. + * + * @since v3.0.0 + * + * @deprecated As of v3.2.0, this callback function is deprecated, and the SDK + * smooths the video frames output by `onRenderVideoFrame` and `onRenderVideoFrameEx` by default. + * + * If you want the video frames acquired from `onRenderVideoFrame` + * or `onRenderVideoFrameEx` to be more evenly spaced, you can register the `getSmoothRenderingEnabled` callback in the `IVideoFrameObserver` class and set its return value as `true`. + * + * @note + * - Register this callback before joining a channel. + * - This callback applies to scenarios where the acquired video frame is self-rendered after being processed, not to scenarios where the video frame is sent back to the SDK after being processed. + * + * @return Set whether to smooth the video frames: + * - true: Smooth the video frame. + * - false: (Default) Do not smooth. + */ + virtual bool getSmoothRenderingEnabled() AGORA_DEPRECATED_ATTRIBUTE { return false; } + /** + * Sets the frame position for the video observer. + * @since v3.0.1 + * + * After you successfully register the video observer, the SDK triggers this callback each time it receives a video frame. You can determine which position to observe by setting the return value. + * The SDK provides 3 positions for observer. Each position corresponds to a callback function: + * - `POSITION_POST_CAPTURER(1 << 0)`: The position after capturing the video data, which corresponds to the \ref onCaptureVideoFrame "onCaptureVideoFrame" callback. + * - `POSITION_PRE_RENDERER(1 << 1)`: The position before receiving the remote video data, which corresponds to the \ref onRenderVideoFrame "onRenderVideoFrame" callback. + * - `POSITION_PRE_ENCODER(1 << 2)`: The position before encoding the video data, which corresponds to the \ref onPreEncodeVideoFrame "onPreEncodeVideoFrame" callback. + * + * @note + * - To observe multiple frame positions, use '|' (the OR operator). + * - This callback observes `POSITION_POST_CAPTURER(1 << 0)` and `POSITION_PRE_RENDERER(1 << 1)` by default. + * - To conserve the system consumption, you can reduce the number of frame positions that you want to observe. + * + * @return A bit mask that controls the frame position of the video observer: #VIDEO_OBSERVER_POSITION. + * + */ + virtual uint32_t getObservedFramePosition() { return static_cast(POSITION_POST_CAPTURER | POSITION_PRE_RENDERER); } + + /** Determines whether to receive video data from multiple channels. + + @since v3.0.1 + + After you register the video frame observer, the SDK triggers this callback + every time it captures a video frame. + + In the multi-channel scenario, if you want to get video data from multiple channels, + set the return value of this callback as true. After that, the SDK triggers the + \ref IVideoFrameObserver::onRenderVideoFrameEx "onRenderVideoFrameEx" callback to send you + the video data from various channels. You can also get the channel ID of each video frame. + + @note + - Once you set the return value of this callback as true, the SDK triggers only the `onRenderVideoFrameEx` callback to + send the video frame. \ref IVideoFrameObserver::onRenderVideoFrame "onRenderVideoFrame" will not be triggered. In the multi-channel scenario, Agora recommends setting the return value as true. + - If you set the return value of this callback as false, the SDK triggers only the `onRenderVideoFrame` callback to send the video data. + @return + - `true`: Receive video data from multiple channels. + - `false`: Do not receive video data from multiple channels. + */ + virtual bool isMultipleChannelFrameWanted() { return false; } + + /** Gets the video frame from multiple channels. + * + * After you successfully register the video frame observer, if you set the return value of + * \ref IVideoFrameObserver::isMultipleChannelFrameWanted "isMultipleChannelFrameWanted" as true, the SDK triggers this callback each time it receives a video frame + * from any of the channel. + * + * You can process the video data retrieved from this callback according to your scenario, and send the + * processed data back to the SDK using the `videoFrame` parameter in this callback. + * + * @note This callback does not support sending RGBA video data back to the SDK. + * + * @param channelId The channel ID of this video frame. + * @param uid The ID of the user sending this video frame. + * @param videoFrame The pointer to VideoFrame. + * @return + * - true: Sets the SDK to receive the video frame. + * - false: Sets the SDK to discard the video frame. + */ + virtual bool onRenderVideoFrameEx(const char* channelId, unsigned int uid, VideoFrame& videoFrame) { return true; } +}; + +class IVideoFrame { + public: + enum PLANE_TYPE { Y_PLANE = 0, U_PLANE = 1, V_PLANE = 2, NUM_OF_PLANES = 3 }; + enum VIDEO_TYPE { + VIDEO_TYPE_UNKNOWN = 0, + VIDEO_TYPE_I420 = 1, + VIDEO_TYPE_IYUV = 2, + VIDEO_TYPE_RGB24 = 3, + VIDEO_TYPE_ABGR = 4, + VIDEO_TYPE_ARGB = 5, + VIDEO_TYPE_ARGB4444 = 6, + VIDEO_TYPE_RGB565 = 7, + VIDEO_TYPE_ARGB1555 = 8, + VIDEO_TYPE_YUY2 = 9, + VIDEO_TYPE_YV12 = 10, + VIDEO_TYPE_UYVY = 11, + VIDEO_TYPE_MJPG = 12, + VIDEO_TYPE_NV21 = 13, + VIDEO_TYPE_NV12 = 14, + VIDEO_TYPE_BGRA = 15, + VIDEO_TYPE_RGBA = 16, + VIDEO_TYPE_I422 = 17, + }; + virtual void release() = 0; + virtual const unsigned char* buffer(PLANE_TYPE type) const = 0; + + /** Copies the frame. + + If the required size is larger than the allocated size, new buffers of the adequate size will be allocated. + + @param dest_frame Address of the returned destination frame. See IVideoFrame. + @return + - 0: Success. + - -1: Failure. + */ + virtual int copyFrame(IVideoFrame** dest_frame) const = 0; + /** Converts the frame. + + @note The source and destination frames have equal heights. + + @param dst_video_type Type of the output video. + @param dst_sample_size Required only for the parsing of M-JPEG. + @param dst_frame Pointer to a destination frame. See IVideoFrame. + @return + - 0: Success. + - < 0: Failure. + */ + virtual int convertFrame(VIDEO_TYPE dst_video_type, int dst_sample_size, unsigned char* dst_frame) const = 0; + /** Gets the specified component in the YUV space. + + @param type Component type: #PLANE_TYPE + */ + virtual int allocated_size(PLANE_TYPE type) const = 0; + /** Gets the stride of the specified component in the YUV space. + + @param type Component type: #PLANE_TYPE + */ + virtual int stride(PLANE_TYPE type) const = 0; + /** Gets the width of the frame. + */ + virtual int width() const = 0; + /** Gets the height of the frame. + */ + virtual int height() const = 0; + /** Gets the timestamp (ms) of the frame. + */ + virtual unsigned int timestamp() const = 0; + /** Gets the render time (ms). + */ + virtual int64_t render_time_ms() const = 0; + /** Checks if a plane is of zero size. + + @return + - true: The plane is of zero size. + - false: The plane is not of zero size. + */ + virtual bool IsZeroSize() const = 0; + + virtual VIDEO_TYPE GetVideoType() const = 0; +}; +/** **DEPRECATED** */ +class IExternalVideoRenderCallback { + public: + /** Occurs when the video view size has changed. + */ + virtual void onViewSizeChanged(int width, int height) = 0; + /** Occurs when the video view is destroyed. + */ + virtual void onViewDestroyed() = 0; +}; +/** **DEPRECATED** */ +struct ExternalVideoRenerContext { + IExternalVideoRenderCallback* renderCallback; + /** Video display window. + */ + void* view; + /** Video display mode: \ref agora::rtc::RENDER_MODE_TYPE "RENDER_MODE_TYPE" */ + int renderMode; + /** The image layer location. + + - 0: (Default) The image is at the bottom of the stack + - 100: The image is at the top of the stack. + + @note If the value is set to below 0 or above 100, the #ERR_INVALID_ARGUMENT error occurs. + */ + int zOrder; + /** Video layout distance from the left. + */ + float left; + /** Video layout distance from the top. + */ + float top; + /** Video layout distance from the right. + */ + float right; + /** Video layout distance from the bottom. + */ + float bottom; +}; + +class IExternalVideoRender { + public: + virtual void release() = 0; + virtual int initialize() = 0; + virtual int deliverFrame(const IVideoFrame& videoFrame, int rotation, bool mirrored) = 0; +}; + +class IExternalVideoRenderFactory { + public: + virtual IExternalVideoRender* createRenderInstance(const ExternalVideoRenerContext& context) = 0; +}; + +/** The external video frame. + */ +struct ExternalVideoFrame { + /** + * The data type of the video frame. + * + * @since v3.5.0 + */ + enum VIDEO_BUFFER_TYPE { + /** 1: The data type is raw data. + */ + VIDEO_BUFFER_RAW_DATA = 1, + /** + * 2: The data type is the pixel. + */ + VIDEO_BUFFER_PIXEL_BUFFER = 2 + }; + + /** The video pixel format. + * + * @note The SDK does not support the alpha channel, and discards any alpha value passed to the SDK. + */ + enum VIDEO_PIXEL_FORMAT { + /** 0: The video pixel format is unknown. + */ + VIDEO_PIXEL_UNKNOWN = 0, + /** 1: The video pixel format is I420. + */ + VIDEO_PIXEL_I420 = 1, + /** 2: The video pixel format is BGRA. + */ + VIDEO_PIXEL_BGRA = 2, + /** 3: The video pixel format is NV21. + */ + VIDEO_PIXEL_NV21 = 3, + /** 4: The video pixel format is RGBA. + */ + VIDEO_PIXEL_RGBA = 4, + /** 5: The video pixel format is IMC2. + */ + VIDEO_PIXEL_IMC2 = 5, + /** 7: The video pixel format is ARGB. + */ + VIDEO_PIXEL_ARGB = 7, + /** 8: The video pixel format is NV12. + */ + VIDEO_PIXEL_NV12 = 8, + /** 16: The video pixel format is I422. + */ + VIDEO_PIXEL_I422 = 16, + }; + + /** The buffer type. See #VIDEO_BUFFER_TYPE + */ + VIDEO_BUFFER_TYPE type; + /** The pixel format. See #VIDEO_PIXEL_FORMAT + */ + VIDEO_PIXEL_FORMAT format; + /** The video buffer. + */ + void* buffer; + /** Line spacing of the incoming video frame, which must be in pixels instead of bytes. For textures, it is the width of the texture. + */ + int stride; + /** Height of the incoming video frame. + */ + int height; + /** [Raw data related parameter] The number of pixels trimmed from the left. The default value is 0. + */ + int cropLeft; + /** [Raw data related parameter] The number of pixels trimmed from the top. The default value is 0. + */ + int cropTop; + /** [Raw data related parameter] The number of pixels trimmed from the right. The default value is 0. + */ + int cropRight; + /** [Raw data related parameter] The number of pixels trimmed from the bottom. The default value is 0. + */ + int cropBottom; + /** [Raw data related parameter] The clockwise rotation of the video frame. You can set the rotation angle as 0, 90, 180, or 270. The default value is 0. + */ + int rotation; + /** Timestamp (ms) of the incoming video frame. An incorrect timestamp results in frame loss or unsynchronized audio and video. + */ + long long timestamp; + + ExternalVideoFrame() : cropLeft(0), cropTop(0), cropRight(0), cropBottom(0), rotation(0) {} +}; +/** + * The video frame type. + * + * @since v3.4.5 + */ +enum CODEC_VIDEO_FRAME_TYPE { + /** + * 0: (Default) A black frame + */ + CODEC_VIDEO_FRAME_TYPE_BLANK_FRAME = 0, + /** + * 3: The keyframe + */ + CODEC_VIDEO_FRAME_TYPE_KEY_FRAME = 3, + /** + * 4: The delta frame + */ + CODEC_VIDEO_FRAME_TYPE_DELTA_FRAME = 4, + /** + * 5: The B-frame + */ + CODEC_VIDEO_FRAME_TYPE_B_FRAME = 5, + /** + * Unknown frame + */ + CODEC_VIDEO_FRAME_TYPE_UNKNOW +}; + +/** + * The clockwise rotation angle of the video frame. + * + * @since v3.4.5 + */ +enum VIDEO_ROTATION { + /** + * 0: 0 degree + */ + VIDEO_ROTATION_0 = 0, + /** + * 90: 90 degrees + */ + VIDEO_ROTATION_90 = 90, + /** + * 180: 180 degrees + */ + VIDEO_ROTATION_180 = 180, + /** + * 270: 270 degrees + */ + VIDEO_ROTATION_270 = 270 +}; + +/** + * The video codec type. + * + * @since v3.4.5 + */ +enum VIDEO_CODEC_TYPE { + /** 1: VP8 */ + VIDEO_CODEC_VP8 = 1, + /** 2: (Default) H.264 */ + VIDEO_CODEC_H264 = 2, + /** 3: Enhanced VP8 */ + VIDEO_CODEC_EVP = 3, + /** 4: Enhanced H.264 */ + VIDEO_CODEC_E264 = 4, +}; + +/** + * The VideoEncodedFrame struct. + * + * @since v3.4.5 + */ +struct VideoEncodedFrame { + VideoEncodedFrame() : codecType(VIDEO_CODEC_H264), width(0), height(0), buffer(nullptr), length(0), frameType(CODEC_VIDEO_FRAME_TYPE_BLANK_FRAME), rotation(VIDEO_ROTATION_0), renderTimeMs(0) {} + /** + * The video codec type. See #VIDEO_CODEC_TYPE. + */ + VIDEO_CODEC_TYPE codecType; + /** + * The width (px) of the video. + */ + int width; + /** + * The height (px) of the video. + */ + int height; + /** + * The video buffer, which is in the `DirectByteBuffer` data type. + */ + const uint8_t* buffer; + /** + * The length (in bytes) of the video buffer. + */ + unsigned int length; + /** + * The video frame type. See #CODEC_VIDEO_FRAME_TYPE. + */ + CODEC_VIDEO_FRAME_TYPE frameType; + /** + * The clockwise rotation angle of the video frame. See #VIDEO_ROTATION. + */ + VIDEO_ROTATION rotation; + /** + * The Unix timestamp (ms) when the video frame is rendered. This timestamp + * can be used to guide the rendering of the video frame. This parameter is required. + */ + int64_t renderTimeMs; +}; +/** + * The IVideoEncodedFrameObserver class. + * + * @since v3.4.5 + */ +class IVideoEncodedFrameObserver { + public: + /** + * Gets the local encoded video frame. + * + * @since v3.4.5 + * + * After you successfully register the local encoded video frame observer, + * the SDK triggers this callback each time a video frame is received. You + * can get the local encoded video frame in `videoEncodedFrame` and then + * process the video data according to your scenario. After processing, + * you can use `videoEncodedFrame` to pass the processed video data back to + * the SDK. + * + * @param videoEncodedFrame The local encoded video frame. See VideoEncodedFrame. + * + * @return + * - true: Sets the SDK to receive the video frame. + * - false: Sets the SDK to discard the video frame. + */ + virtual bool onVideoEncodedFrame(const VideoEncodedFrame& videoEncodedFrame) = 0; + + virtual ~IVideoEncodedFrameObserver() {} +}; + +class IMediaEngine { + public: + virtual ~IMediaEngine(){}; + virtual void release() = 0; + /** Registers an audio frame observer object. + + This method is used to register an audio frame observer object (register a callback). This method is required to register callbacks when the engine is required to provide an \ref IAudioFrameObserver::onRecordAudioFrame "onRecordAudioFrame" or \ref IAudioFrameObserver::onPlaybackAudioFrame "onPlaybackAudioFrame" callback. + + @note Ensure that you call this method before joining a channel. + + @param observer Audio frame observer object instance. See IAudioFrameObserver. Set the value as NULL to release the + audio observer object. Agora recommends calling `registerAudioFrameObserver(NULL)` after receiving the \ref agora::rtc::IRtcEngineEventHandler::onLeaveChannel "onLeaveChannel" callback. + + @return + - 0: Success. + - < 0: Failure. + */ + virtual int registerAudioFrameObserver(IAudioFrameObserver* observer) = 0; + /** Registers a video frame observer object. + * + * You need to implement the IVideoFrameObserver class in this method, and register callbacks according to your scenarios. + * + * After you successfully register the video frame observer, the SDK triggers the registered callbacks each time a video frame is received. + * + * @note + * - When handling the video data returned in the callbacks, pay attention to the changes in the `width` and `height` parameters, + * which may be adapted under the following circumstances: + * - When the network condition deteriorates, the video resolution decreases incrementally. + * - If the user adjusts the video profile, the resolution of the video returned in the callbacks also changes. + * - Ensure that you call this method before joining a channel. + * @param observer Video frame observer object instance. If NULL is passed in, the registration is canceled. + * @return + * - 0: Success. + * - < 0: Failure. + */ + virtual int registerVideoFrameObserver(IVideoFrameObserver* observer) = 0; + /** **DEPRECATED** */ + virtual int registerVideoRenderFactory(IExternalVideoRenderFactory* factory) = 0; + /** + * Pushes the external audio frame. + * + * @deprecated This method is deprecated. Use \ref IMediaEngine::pushAudioFrame(int32_t,IAudioFrameObserver::AudioFrame*) "pushAudioFrame" [3/3] instead. + * + * @param type Type of audio capture device: #MEDIA_SOURCE_TYPE. + * @param frame Audio frame pointer: \ref IAudioFrameObserver::AudioFrame "AudioFrame". + * @param wrap Whether to use the placeholder. We recommend setting the default value. + * - true: Use. + * - false: (Default) Not use. + * + * @return + * - 0: Success. + * - < 0: Failure. + */ + virtual int pushAudioFrame(MEDIA_SOURCE_TYPE type, IAudioFrameObserver::AudioFrame* frame, bool wrap) AGORA_DEPRECATED_ATTRIBUTE = 0; + /** Pushes the external audio frame. + * + * @deprecated This method is deprecated. Use \ref IMediaEngine::pushAudioFrame(int32_t,IAudioFrameObserver::AudioFrame*) "pushAudioFrame" [3/3] instead. + * + * @param frame Pointer to the audio frame: \ref IAudioFrameObserver::AudioFrame "AudioFrame". + * + * @return + * - 0: Success. + * - < 0: Failure. + */ + virtual int pushAudioFrame(IAudioFrameObserver::AudioFrame* frame) AGORA_DEPRECATED_ATTRIBUTE = 0; + + /** + * Pushes the external audio frame to a specified position. + * + * @since v3.5.1 + * + * According to your needs, you can push the external audio frame to one of three positions: after audio capture, + * before audio encoding, or before local playback. You can call this method multiple times to push one audio frame + * to multiple positions or multiple audio frames to different positions. For example, in the KTV scenario, you can + * push the singing voice to after audio capture, so that the singing voice can be processed by the SDK audio module + * and you can obtain a high-quality audio experience; you can also push the accompaniment to before audio encoding, + * so that the accompaniment is not affected by the audio module of the SDK. + * + * @note Call this method after joining a channel. + * + * @param sourcePos The push position of the external audio frame. See #AUDIO_EXTERNAL_SOURCE_POSITION. + * @param frame The external audio frame. See AudioFrame. The value range of the audio frame length (ms) is [10,60]. + * + * @return + * - 0: Success. + * - < 0: Failure. + * - `-2 (ERR_INVALID_ARGUMENT)`: The parameter is invalid. + * - `-12 (ERR_TOO_OFTEN)`: The call frequency is too high, causing the internal buffer to overflow. Call this method again after 30-50 ms. + */ + virtual int pushAudioFrame(int32_t sourcePos, IAudioFrameObserver::AudioFrame* frame) = 0; + /** + * Sets the volume of the external audio frame in the specified position. + * + * @since v3.5.1 + * + * You can call this method multiple times to set the volume of external audio frames in different positions. + * The volume setting takes effect for all external audio frames that are pushed to the specified position. + * + * @note Call this method after joining a channel. + * + * @param sourcePos The push position of the external audio frame. See #AUDIO_EXTERNAL_SOURCE_POSITION. + * @param volume The volume of the external audio frame. The value range is [0,100]. The default value is 100, which + * represents the original value. + * + * @return + * - 0: Success. + * - < 0: Failure. + * - `-2 (ERR_INVALID_ARGUMENT)`: The parameter is invalid. + */ + virtual int setExternalAudioSourceVolume(int32_t sourcePos, int32_t volume) = 0; + /** Pulls the remote audio data. + * + * Before calling this method, call the + * \ref agora::rtc::IRtcEngine::setExternalAudioSink + * "setExternalAudioSink(enabled: true)" method to enable and set the + * external audio sink. + * + * After a successful method call, the app pulls the decoded and mixed + * audio data for playback. + * + * @note + * - Ensure that you call this method after joining a channel. + * - Once you call the \ref agora::media::IMediaEngine::pullAudioFrame + * "pullAudioFrame" method successfully, the app will not get any audio + * data from the + * \ref agora::media::IAudioFrameObserver::onPlaybackAudioFrame + * "onPlaybackAudioFrame" callback. + * - The difference between the + * \ref agora::media::IAudioFrameObserver::onPlaybackAudioFrame + * "onPlaybackAudioFrame" callback and the + * \ref agora::media::IMediaEngine::pullAudioFrame "pullAudioFrame" method is as + * follows: + * - `onPlaybackAudioFrame`: The SDK sends the audio data to the app through this callback. + * Any delay in processing the audio frames may result in audio jitter. + * - `pullAudioFrame`: The app pulls the remote audio data. After setting the + * audio data parameters, the SDK adjusts the frame buffer and avoids + * problems caused by jitter in the external audio playback. + * + * @param frame Pointers to the audio frame. + * See: \ref IAudioFrameObserver::AudioFrame "AudioFrame". + * + * @return + * - 0: Success. + * - < 0: Failure. + */ + virtual int pullAudioFrame(IAudioFrameObserver::AudioFrame* frame) = 0; + /** Configures the external video source. + + @note Ensure that you call this method before joining a channel. + + @param enable Sets whether to use the external video source: + - true: Use the external video source. + - false: (Default) Do not use the external video source. + + @param useTexture Sets whether to use texture as an input: + - true: Use texture as an input. + - false: (Default) Do not use texture as an input. + + @return + - 0: Success. + - < 0: Failure. + */ + virtual int setExternalVideoSource(bool enable, bool useTexture) = 0; + /** Pushes the video frame using the \ref ExternalVideoFrame "ExternalVideoFrame" and passes the video frame to the Agora SDK. + + @param frame Video frame to be pushed. See \ref ExternalVideoFrame "ExternalVideoFrame". + + @note In the `COMMUNICATION` profile, this method does not support video frames in the Texture format. + + @return + - 0: Success. + - < 0: Failure. + */ + virtual int pushVideoFrame(ExternalVideoFrame* frame) = 0; + /** + * Registers a local encoded video frame observer. + * + * @since v3.4.5 + * + * After you successfully register the local encoded video frame observer, + * the SDK triggers the callbacks that you have implemented in the + * IVideoEncodedFrameObserver class each time a video frame is received. + * + * @note + * - Ensure that you call this method before joining a channel. + * - The width and height of the video obtained through the observer may + * change due to poor network conditions and user-adjusted resolution. + * + * @param observer The local encoded video frame observer. See IVideoEncodedFrameObserver. + * If null is passed, the observer registration is canceled. + * + * @return + * - 0: Success. + * - < 0: Failure. + */ + virtual int registerVideoEncodedFrameObserver(IVideoEncodedFrameObserver* observer) = 0; +}; + +} // namespace media + +} // namespace agora + +#endif // AGORA_MEDIA_ENGINE_H diff --git a/integration_test_app/iris_integration_test/third_party/agora/rtc/include/IAgoraRtcChannel.h b/integration_test_app/iris_integration_test/third_party/agora/rtc/include/IAgoraRtcChannel.h new file mode 100644 index 000000000..9fc9194da --- /dev/null +++ b/integration_test_app/iris_integration_test/third_party/agora/rtc/include/IAgoraRtcChannel.h @@ -0,0 +1,1686 @@ +// +// AgoraRtcEngine SDK +// +// Copyright (c) 2019 Agora.io. All rights reserved. +// + +#ifndef IAgoraRtcChannel_h +#define IAgoraRtcChannel_h +#include "IAgoraRtcEngine.h" + +namespace agora { +namespace rtc { +/** The IChannel class. */ +class IChannel; +/** The IChannelEventHandler class. */ +class IChannelEventHandler { + public: + virtual ~IChannelEventHandler() {} + /** Reports the warning code of `IChannel`. + + @param rtcChannel IChannel + @param warn The warning code: #WARN_CODE_TYPE + @param msg The warning message. + + */ + virtual void onChannelWarning(IChannel* rtcChannel, int warn, const char* msg) { + (void)rtcChannel; + (void)warn; + (void)msg; + } + /** Reports the error code of `IChannel`. + + @param rtcChannel IChannel + @param err The error code: #ERROR_CODE_TYPE + @param msg The error message. + */ + virtual void onChannelError(IChannel* rtcChannel, int err, const char* msg) { + (void)rtcChannel; + (void)err; + (void)msg; + } + /** Occurs when a user joins a channel. + + This callback notifies the application that a user joins a specified channel. + + @param rtcChannel IChannel + @param uid The user ID. If the `uid` is not specified in the \ref IChannel::joinChannel "joinChannel" method, the server automatically assigns a `uid`. + + @param elapsed Time elapsed (ms) from the local user calling \ref IChannel::joinChannel "joinChannel" until this callback is triggered. + */ + virtual void onJoinChannelSuccess(IChannel* rtcChannel, uid_t uid, int elapsed) { + (void)rtcChannel; + (void)uid; + (void)elapsed; + } + /** Occurs when a user rejoins the channel after being disconnected due to network problems. + + @param rtcChannel IChannel + @param uid The user ID. + @param elapsed Time elapsed (ms) from the local user starting to reconnect until this callback is triggered. + + */ + virtual void onRejoinChannelSuccess(IChannel* rtcChannel, uid_t uid, int elapsed) { + (void)rtcChannel; + (void)uid; + (void)elapsed; + } + /** Occurs when a user leaves the channel. + + This callback notifies the application that a user leaves the channel when the application calls the \ref agora::rtc::IChannel::leaveChannel "leaveChannel" method. + + The application gets information, such as the call duration and statistics. + + @param rtcChannel IChannel + @param stats The call statistics: RtcStats. + */ + virtual void onLeaveChannel(IChannel* rtcChannel, const RtcStats& stats) { + (void)rtcChannel; + (void)stats; + } + /** Occurs when the user role switches in the interactive live streaming. For example, from a host to an audience or vice versa. + + This callback notifies the application of a user role switch when the application calls the \ref IChannel::setClientRole "setClientRole" method. + + The SDK triggers this callback when the local user switches the user role by calling the \ref IChannel::setClientRole "setClientRole" method after joining the channel. + + @param rtcChannel IChannel + @param oldRole Role that the user switches from: #CLIENT_ROLE_TYPE. + @param newRole Role that the user switches to: #CLIENT_ROLE_TYPE. + */ + virtual void onClientRoleChanged(IChannel* rtcChannel, CLIENT_ROLE_TYPE oldRole, CLIENT_ROLE_TYPE newRole) { + (void)rtcChannel; + (void)oldRole; + (void)newRole; + } + /** Occurs when a remote user (`COMMUNICATION`)/ host (`LIVE_BROADCASTING`) joins the channel. + + - `COMMUNICATION` profile: This callback notifies the application that another user joins the channel. If other users are already in the channel, the SDK also reports to the application on the existing users. + - `LIVE_BROADCASTING` profile: This callback notifies the application that the host joins the channel. If other hosts are already in the channel, the SDK also reports to the application on the existing hosts. We recommend limiting the number of hosts to 17. + + The SDK triggers this callback under one of the following circumstances: + - A remote user/host joins the channel by calling the \ref agora::rtc::IChannel::joinChannel "joinChannel" method. + - A remote user switches the user role to the host by calling the \ref agora::rtc::IChannel::setClientRole "setClientRole" method after joining the channel. + - A remote user/host rejoins the channel after a network interruption. + - The host injects an online media stream into the channel by calling the \ref agora::rtc::IChannel::addInjectStreamUrl "addInjectStreamUrl" method. + + @note In the `LIVE_BROADCASTING` profile: + - The host receives this callback when another host joins the channel. + - The audience in the channel receives this callback when a new host joins the channel. + - When a web application joins the channel, the SDK triggers this callback as long as the web application publishes streams. + + @param rtcChannel IChannel + @param uid User ID of the user or host joining the channel. + @param elapsed Time delay (ms) from the local user calling the \ref IChannel::joinChannel "joinChannel" method until the SDK triggers this callback. + */ + virtual void onUserJoined(IChannel* rtcChannel, uid_t uid, int elapsed) { + (void)rtcChannel; + (void)uid; + (void)elapsed; + } + /** Occurs when a remote user ( `COMMUNICATION`)/host (`LIVE_BROADCASTING`) leaves the channel. + + Reasons why the user is offline: + + - Leave the channel: When the user/host leaves the channel, the user/host sends a goodbye message. When the message is received, the SDK assumes that the user/host leaves the channel. + - Drop offline: When no data packet of the user or host is received for a certain period of time, the SDK assumes that the user/host drops offline. Unreliable network connections may lead to false detections, so we recommend using the Agora RTM SDK for more reliable offline detection. + + @param rtcChannel IChannel + @param uid User ID of the user leaving the channel or going offline. + @param reason Reason why the user is offline: #USER_OFFLINE_REASON_TYPE. + */ + virtual void onUserOffline(IChannel* rtcChannel, uid_t uid, USER_OFFLINE_REASON_TYPE reason) { + (void)rtcChannel; + (void)uid; + (void)reason; + } + /** Occurs when the SDK cannot reconnect to Agora's edge server 10 seconds after its connection to the server is interrupted. + + The SDK triggers this callback when it cannot connect to the server 10 seconds after calling the \ref IChannel::joinChannel "joinChannel" method, whether or not it is in the channel. + + This callback is different from \ref agora::rtc::IRtcEngineEventHandler::onConnectionInterrupted "onConnectionInterrupted": + + - The SDK triggers the `onConnectionInterrupted` callback when it loses connection with the server for more than four seconds after it successfully joins the channel. + - The SDK triggers the `onConnectionLost` callback when it loses connection with the server for more than 10 seconds, whether or not it joins the channel. + + If the SDK fails to rejoin the channel 20 minutes after being disconnected from Agora's edge server, the SDK stops rejoining the channel. + + @param rtcChannel IChannel + */ + virtual void onConnectionLost(IChannel* rtcChannel) { (void)rtcChannel; } + /** Occurs when the token expires. + + After a token is specified by calling the \ref IChannel::joinChannel "joinChannel" method, if the SDK losses connection with the Agora server due to network issues, the token may expire after a certain period of time and a new token may be required to reconnect to the server. + + Once you receive this callback, generate a new token on your app server, and call + \ref agora::rtc::IChannel::renewToken "renewToken" to pass the new token to the SDK. + + @param rtcChannel IChannel + */ + virtual void onRequestToken(IChannel* rtcChannel) { (void)rtcChannel; } + /** Occurs when the token expires in 30 seconds. + + The user becomes offline if the token used in the \ref IChannel::joinChannel "joinChannel" method expires. The SDK triggers this callback 30 seconds before the token expires to remind the application to get a new token. Upon receiving this callback, generate a new token on the server and call the \ref IChannel::renewToken "renewToken" method to pass the new token to the SDK. + + @param rtcChannel IChannel + @param token Token that expires in 30 seconds. + */ + virtual void onTokenPrivilegeWillExpire(IChannel* rtcChannel, const char* token) { + (void)rtcChannel; + (void)token; + } + /** Reports the statistics of the current call. + + The SDK triggers this callback once every two seconds after the user joins the channel. + + @param rtcChannel IChannel + @param stats Statistics of the RtcEngine: RtcStats. + */ + virtual void onRtcStats(IChannel* rtcChannel, const RtcStats& stats) { + (void)rtcChannel; + (void)stats; + } + /** Reports the last mile network quality of each user in the channel once every two seconds. + * + * Last mile refers to the connection between the local device and Agora's edge server. This callback reports once every + * two seconds the last mile network conditions of each user in the channel. If a channel includes multiple users, the + * SDK triggers this callback as many times. + * + * @note `txQuality` is `UNKNOWN` when the user is not sending a stream; `rxQuality` is `UNKNOWN` when the user is not receiving a stream. + * + * @param rtcChannel IChannel + * @param uid User ID. The network quality of the user with this @p uid is reported. If @p uid is 0, the local network quality is reported. + * @param txQuality Uplink transmission quality rating of the user in terms of the transmission bitrate, packet loss rate, average RTT (Round-Trip Time), and jitter of the uplink network. @p txQuality is a quality rating helping you understand how well the current uplink network conditions can support the selected VideoEncoderConfiguration. For example, a 1000 Kbps uplink network may be adequate for video frames with a resolution of 640 * 480 and a frame rate of 15 fps in the `LIVE_BROADCASTING` profile, but may be inadequate for resolutions higher than 1280 * 720. See #QUALITY_TYPE. + * @param rxQuality Downlink network quality rating of the user in terms of the packet loss rate, average RTT, and jitter of the downlink network. See #QUALITY_TYPE. + */ + virtual void onNetworkQuality(IChannel* rtcChannel, uid_t uid, int txQuality, int rxQuality) { + (void)rtcChannel; + (void)uid; + (void)txQuality; + (void)rxQuality; + } + /** Reports the statistics of the video stream from each remote user/host. + * + * The SDK triggers this callback once every two seconds for each remote + * user/host. If a channel includes multiple remote users, the SDK + * triggers this callback as many times. + * + * @param rtcChannel IChannel + * @param stats Statistics of the remote video stream. See + * RemoteVideoStats. + */ + virtual void onRemoteVideoStats(IChannel* rtcChannel, const RemoteVideoStats& stats) { + (void)rtcChannel; + (void)stats; + } + /** Reports the statistics of the audio stream from each remote user/host. + + This callback replaces the \ref agora::rtc::IRtcEngineEventHandler::onAudioQuality "onAudioQuality" callback. + + The SDK triggers this callback once every two seconds for each remote user/host. If a channel includes multiple remote users, the SDK triggers this callback as many times. + + @param rtcChannel IChannel + @param stats The statistics of the received remote audio streams. See RemoteAudioStats. + */ + virtual void onRemoteAudioStats(IChannel* rtcChannel, const RemoteAudioStats& stats) { + (void)rtcChannel; + (void)stats; + } + /** Occurs when the remote audio state changes. + * + * This callback indicates the state change of the remote audio stream. + * + * @note This callback can be inaccurate when the number of users (in the `COMMUNICATION` profile) + * or hosts (in the `LIVE_BROADCASTING` profile) in a channel exceeds 17. + * + * @param rtcChannel IChannel + * @param uid ID of the remote user whose audio state changes. + * @param state State of the remote audio. See #REMOTE_AUDIO_STATE. + * @param reason The reason of the remote audio state change. See #REMOTE_AUDIO_STATE_REASON. + * @param elapsed Time elapsed (ms) from the local user calling the + * \ref IChannel::joinChannel "joinChannel" method until the SDK + * triggers this callback. + */ + virtual void onRemoteAudioStateChanged(IChannel* rtcChannel, uid_t uid, REMOTE_AUDIO_STATE state, REMOTE_AUDIO_STATE_REASON reason, int elapsed) { + (void)rtcChannel; + (void)uid; + (void)state; + (void)reason; + (void)elapsed; + } + + /** Occurs when the audio publishing state changes. + * + * @since v3.1.0 + * + * This callback indicates the publishing state change of the local audio stream. + * + * @param rtcChannel IChannel + * @param oldState The previous publishing state. For details, see #STREAM_PUBLISH_STATE. + * @param newState The current publishing state. For details, see #STREAM_PUBLISH_STATE. + * @param elapseSinceLastState The time elapsed (ms) from the previous state to the current state. + */ + virtual void onAudioPublishStateChanged(IChannel* rtcChannel, STREAM_PUBLISH_STATE oldState, STREAM_PUBLISH_STATE newState, int elapseSinceLastState) { + (void)rtcChannel; + (void)oldState; + (void)newState; + (void)elapseSinceLastState; + } + + /** Occurs when the video publishing state changes. + * + * @since v3.1.0 + * + * This callback indicates the publishing state change of the local video stream. + * + * @param rtcChannel IChannel + * @param oldState The previous publishing state. For details, see #STREAM_PUBLISH_STATE. + * @param newState The current publishing state. For details, see #STREAM_PUBLISH_STATE. + * @param elapseSinceLastState The time elapsed (ms) from the previous state to the current state. + */ + virtual void onVideoPublishStateChanged(IChannel* rtcChannel, STREAM_PUBLISH_STATE oldState, STREAM_PUBLISH_STATE newState, int elapseSinceLastState) { + (void)rtcChannel; + (void)oldState; + (void)newState; + (void)elapseSinceLastState; + } + + /** Occurs when the audio subscribing state changes. + * + * @since v3.1.0 + * + * This callback indicates the subscribing state change of a remote audio stream. + * + * @param rtcChannel IChannel + * @param uid The ID of the remote user. + * @param oldState The previous subscribing state. For details, see #STREAM_SUBSCRIBE_STATE. + * @param newState The current subscribing state. For details, see #STREAM_SUBSCRIBE_STATE. + * @param elapseSinceLastState The time elapsed (ms) from the previous state to the current state. + */ + virtual void onAudioSubscribeStateChanged(IChannel* rtcChannel, uid_t uid, STREAM_SUBSCRIBE_STATE oldState, STREAM_SUBSCRIBE_STATE newState, int elapseSinceLastState) { + (void)rtcChannel; + (void)uid; + (void)oldState; + (void)newState; + (void)elapseSinceLastState; + } + + /** Occurs when the audio subscribing state changes. + * + * @since v3.1.0 + * + * This callback indicates the subscribing state change of a remote video stream. + * + * @param rtcChannel IChannel + * @param uid The ID of the remote user. + * @param oldState The previous subscribing state. For details, see #STREAM_SUBSCRIBE_STATE. + * @param newState The current subscribing state. For details, see #STREAM_SUBSCRIBE_STATE. + * @param elapseSinceLastState The time elapsed (ms) from the previous state to the current state. + */ + virtual void onVideoSubscribeStateChanged(IChannel* rtcChannel, uid_t uid, STREAM_SUBSCRIBE_STATE oldState, STREAM_SUBSCRIBE_STATE newState, int elapseSinceLastState) { + (void)rtcChannel; + (void)uid; + (void)oldState; + (void)newState; + (void)elapseSinceLastState; + } + + /** Reports whether the super resolution feature is successfully enabled. (beta feature) + * + * @since v3.5.1 + * + * After calling \ref IChannel::enableRemoteSuperResolution "enableRemoteSuperResolution", the SDK triggers this + * callback to report whether super resolution is successfully enabled. If it is not successfully enabled, + * use `reason` for troubleshooting. + * + * @param rtcChannel IChannel + * @param uid The user ID of the remote user. + * @param enabled Whether super resolution is successfully enabled: + * - true: Super resolution is successfully enabled. + * - false: Super resolution is not successfully enabled. + * @param reason The reason why super resolution is not successfully enabled or the message + * that confirms success. See #SUPER_RESOLUTION_STATE_REASON. + * + */ + virtual void onUserSuperResolutionEnabled(IChannel* rtcChannel, uid_t uid, bool enabled, SUPER_RESOLUTION_STATE_REASON reason) { + (void)rtcChannel; + (void)uid; + (void)enabled; + (void)reason; + } + + /** Occurs when the most active remote speaker is detected. + + After a successful call of \ref IRtcEngine::enableAudioVolumeIndication(int, int, bool) "enableAudioVolumeIndication", + the SDK continuously detects which remote user has the loudest volume. During the current period, the remote user, + who is detected as the loudest for the most times, is the most active user. + + When the number of user is no less than two and an active speaker exists, the SDK triggers this callback and reports the `uid` of the most active speaker. + - If the most active speaker is always the same user, the SDK triggers this callback only once. + - If the most active speaker changes to another user, the SDK triggers this callback again and reports the `uid` of the new active speaker. + + @param rtcChannel IChannel + @param uid The user ID of the most active remote speaker. + */ + virtual void onActiveSpeaker(IChannel* rtcChannel, uid_t uid) { + (void)rtcChannel; + (void)uid; + } + /** Occurs when the video size or rotation of a specified user changes. + + @param rtcChannel IChannel + @param uid User ID of the remote user or local user (0) whose video size or rotation changes. + @param width New width (pixels) of the video. + @param height New height (pixels) of the video. + @param rotation New rotation of the video [0 to 360). + */ + virtual void onVideoSizeChanged(IChannel* rtcChannel, uid_t uid, int width, int height, int rotation) { + (void)rtcChannel; + (void)uid; + (void)width; + (void)height; + (void)rotation; + } + /** Occurs when the remote video state changes. + * + * @note This callback can be inaccurate when the number of users (in the `COMMUNICATION` profile) or + * hosts (in the `LIVE_BROADCASTING` profile) in a channel exceeds 17. + * + * @param rtcChannel IChannel + * @param uid ID of the remote user whose video state changes. + * @param state State of the remote video. See #REMOTE_VIDEO_STATE. + * @param reason The reason of the remote video state change. See #REMOTE_VIDEO_STATE_REASON. + * @param elapsed Time elapsed (ms) from the local user calling the + * \ref agora::rtc::IChannel::joinChannel "joinChannel" method until the + * SDK triggers this callback. + */ + virtual void onRemoteVideoStateChanged(IChannel* rtcChannel, uid_t uid, REMOTE_VIDEO_STATE state, REMOTE_VIDEO_STATE_REASON reason, int elapsed) { + (void)rtcChannel; + (void)uid; + (void)state; + (void)reason; + (void)elapsed; + } + /** Occurs when the local user receives the data stream from the remote user within five seconds. + + The SDK triggers this callback when the local user receives the stream message that the remote user sends by calling the \ref agora::rtc::IChannel::sendStreamMessage "sendStreamMessage" method. + + @param rtcChannel IChannel + @param uid User ID of the remote user sending the message. + @param streamId Stream ID. + @param data The data received by the local user. + @param length Length of the data in bytes. + */ + virtual void onStreamMessage(IChannel* rtcChannel, uid_t uid, int streamId, const char* data, size_t length) { + (void)rtcChannel; + (void)uid; + (void)streamId; + (void)data; + (void)length; + } + /** Occurs when the local user does not receive the data stream from the remote user within five seconds. + + The SDK triggers this callback when the local user fails to receive the stream message that the remote user sends by calling the \ref agora::rtc::IChannel::sendStreamMessage "sendStreamMessage" method. + + @param rtcChannel IChannel + @param uid User ID of the remote user sending the message. + @param streamId Stream ID. + @param code Error code: #ERROR_CODE_TYPE. + @param missed Number of lost messages. + @param cached Number of incoming cached messages when the data stream is interrupted. + */ + virtual void onStreamMessageError(IChannel* rtcChannel, uid_t uid, int streamId, int code, int missed, int cached) { + (void)rtcChannel; + (void)uid; + (void)streamId; + (void)code; + (void)missed; + (void)cached; + } + /** Occurs when the state of the media stream relay changes. + * + * The SDK returns the state of the current media relay with any error + * message. + * @param rtcChannel IChannel + * @param state The state code in #CHANNEL_MEDIA_RELAY_STATE. + * @param code The error code in #CHANNEL_MEDIA_RELAY_ERROR. + */ + virtual void onChannelMediaRelayStateChanged(IChannel* rtcChannel, CHANNEL_MEDIA_RELAY_STATE state, CHANNEL_MEDIA_RELAY_ERROR code) { + (void)rtcChannel; + (void)state; + (void)code; + } + /** Reports events during the media stream relay. + * @param rtcChannel IChannel + * @param code The event code in #CHANNEL_MEDIA_RELAY_EVENT. + */ + virtual void onChannelMediaRelayEvent(IChannel* rtcChannel, CHANNEL_MEDIA_RELAY_EVENT code) { + (void)rtcChannel; + (void)code; + } + /** + Occurs when the state of the RTMP or RTMPS streaming changes. + + The SDK triggers this callback to report the result of the local user calling the \ref agora::rtc::IChannel::addPublishStreamUrl "addPublishStreamUrl" or \ref agora::rtc::IChannel::removePublishStreamUrl "removePublishStreamUrl" method. + + This callback indicates the state of the RTMP or RTMPS streaming. When exceptions occur, you can troubleshoot issues by referring to the detailed error descriptions in the *errCode* parameter. + + @param rtcChannel IChannel + @param url The CDN streaming URL. + @param state The RTMP or RTMPS streaming state. See: #RTMP_STREAM_PUBLISH_STATE. + @param errCode The detailed error information for streaming. See: #RTMP_STREAM_PUBLISH_ERROR. + */ + virtual void onRtmpStreamingStateChanged(IChannel* rtcChannel, const char* url, RTMP_STREAM_PUBLISH_STATE state, RTMP_STREAM_PUBLISH_ERROR errCode) { + (void)rtcChannel; + (void)url; + (RTMP_STREAM_PUBLISH_STATE) state; + (RTMP_STREAM_PUBLISH_ERROR) errCode; + } + + /** Reports events during the RTMP or RTMPS streaming. + * + * @since v3.1.0 + * + * @param rtcChannel IChannel + * @param url The RTMP or RTMPS streaming URL. + * @param eventCode The event code. See #RTMP_STREAMING_EVENT + */ + virtual void onRtmpStreamingEvent(IChannel* rtcChannel, const char* url, RTMP_STREAMING_EVENT eventCode) { + (void)rtcChannel; + (void)url; + (RTMP_STREAMING_EVENT) eventCode; + } + + /** Occurs when the publisher's transcoding is updated. + + When the `LiveTranscoding` class in the \ref agora::rtc::IChannel::setLiveTranscoding "setLiveTranscoding" method updates, the SDK triggers the `onTranscodingUpdated` callback to report the update information to the local host. + + @note If you call the `setLiveTranscoding` method to set the LiveTranscoding class for the first time, the SDK does not trigger the `onTranscodingUpdated` callback. + + @param rtcChannel IChannel + */ + virtual void onTranscodingUpdated(IChannel* rtcChannel) { (void)rtcChannel; } + /** Occurs when a voice or video stream URL address is added to the interactive live streaming. + + @warning Agora will soon stop the service for injecting online media streams on the client. If you have not implemented this service, Agora recommends that you do not use it. + + @param rtcChannel IChannel + @param url The URL address of the externally injected stream. + @param uid User ID. + @param status State of the externally injected stream: #INJECT_STREAM_STATUS. + */ + virtual void onStreamInjectedStatus(IChannel* rtcChannel, const char* url, uid_t uid, int status) { + (void)rtcChannel; + (void)url; + (void)uid; + (void)status; + } + /** Occurs when the published media stream falls back to an audio-only stream due to poor network conditions or switches back to the video after the network conditions improve. + + If you call \ref IRtcEngine::setLocalPublishFallbackOption "setLocalPublishFallbackOption" and set *option* as #STREAM_FALLBACK_OPTION_AUDIO_ONLY, the SDK triggers this callback when the published stream falls back to audio-only mode due to poor uplink conditions, or when the audio stream switches back to the video after the uplink network condition improves. + + @param rtcChannel IChannel + @param isFallbackOrRecover Whether the published stream falls back to audio-only or switches back to the video: + - true: The published stream falls back to audio-only due to poor network conditions. + - false: The published stream switches back to the video after the network conditions improve. + */ + virtual void onLocalPublishFallbackToAudioOnly(IChannel* rtcChannel, bool isFallbackOrRecover) { + (void)rtcChannel; + (void)isFallbackOrRecover; + } + /** Occurs when the remote media stream falls back to audio-only stream + * due to poor network conditions or switches back to the video stream + * after the network conditions improve. + * + * If you call + * \ref IRtcEngine::setRemoteSubscribeFallbackOption + * "setRemoteSubscribeFallbackOption" and set + * @p option as #STREAM_FALLBACK_OPTION_AUDIO_ONLY, the SDK triggers this + * callback when the remote media stream falls back to audio-only mode due + * to poor downlink conditions, or when the remote media stream switches + * back to the video after the downlink network condition improves. + * + * @note Once the remote media stream switches to the low stream due to + * poor network conditions, you can monitor the stream switch between a + * high and low stream in the RemoteVideoStats callback. + * @param rtcChannel IChannel + * @param uid ID of the remote user sending the stream. + * @param isFallbackOrRecover Whether the remotely subscribed media stream + * falls back to audio-only or switches back to the video: + * - true: The remotely subscribed media stream falls back to audio-only + * due to poor network conditions. + * - false: The remotely subscribed media stream switches back to the + * video stream after the network conditions improved. + */ + virtual void onRemoteSubscribeFallbackToAudioOnly(IChannel* rtcChannel, uid_t uid, bool isFallbackOrRecover) { + (void)rtcChannel; + (void)uid; + (void)isFallbackOrRecover; + } + /** Occurs when the connection state between the SDK and the server changes. + + @param rtcChannel IChannel + @param state See #CONNECTION_STATE_TYPE. + @param reason See #CONNECTION_CHANGED_REASON_TYPE. + */ + virtual void onConnectionStateChanged(IChannel* rtcChannel, CONNECTION_STATE_TYPE state, CONNECTION_CHANGED_REASON_TYPE reason) { + (void)rtcChannel; + (void)state; + (void)reason; + } +}; + +/** The IChannel class. */ +class IChannel { + public: + virtual ~IChannel() {} + /** Releases all IChannel resources. + + @return + - 0: Success. + - < 0: Failure. + - `ERR_NOT_INITIALIZED (7)`: The SDK is not initialized before calling this method. + */ + virtual int release() = 0; + /** Sets the channel event handler. + + After setting the channel event handler, you can listen for channel events and receive the statistics of the corresponding `IChannel` object. + + @param channelEh The event handler of the `IChannel` object. For details, see IChannelEventHandler. + + @return + - 0: Success. + - < 0: Failure. + */ + virtual int setChannelEventHandler(IChannelEventHandler* channelEh) = 0; + /** Joins the channel with a user ID. + * + * Compared with the `joinChannel` method in the IRtcEngine class, this method supports joining multiple channels at + * a time by creating multiple IChannel objects and then calling `joinChannel` in each IChannel object. + * + * Once the user joins the channel, the user publishes the local audio and video streams and automatically + * subscribes to the audio and video streams of all the other users in the channel by default. Subscribing + * incurs all associated usage costs. To unsubscribe, set the `options` parameter or call the `mute` methods accordingly. + * + * @note + * - If you are already in a channel, you cannot rejoin it with the same `uid`. + * - We recommend using different UIDs for different channels. + * - If you want to join the same channel from different devices, ensure that the UIDs in all devices are different. + * - Ensure that the app ID you use to generate the token is the same with the app ID used when creating the `IRtcEngine` object. + * + * @param token The token generated at your server. See [Authenticate Your Users with Tokens](https://docs.agora.io/en/Interactive%20Broadcast/token_server?platform=All%20Platforms). + * @param info (Optional) Additional information about the channel. This parameter can be set as null. Other users in the channel do not receive this information. + * @param uid The user ID. A 32-bit unsigned integer with a value ranging from 1 to (232-1). This parameter must be unique. If `uid` is not assigned (or set as `0`), the SDK assigns a `uid` and reports it in the \ref agora::rtc::IChannelEventHandler::onJoinChannelSuccess "onJoinChannelSuccess" callback. The app must maintain this user ID. + * @param options The channel media options: \ref agora::rtc::ChannelMediaOptions::ChannelMediaOptions "ChannelMediaOptions" + * + * @return + * - 0(ERR_OK): Success. + * - < 0: Failure. + * - -2(ERR_INVALID_ARGUMENT): The parameter is invalid. + * - -3(ERR_NOT_READY): The SDK fails to be initialized. You can try re-initializing the SDK. + * - -5(ERR_REFUSED): The request is rejected. This may be caused by the following: + * - You have created an IChannel object with the same channel name. + * - You have joined and published a stream in a channel created by the IChannel object. When you join a channel created by the IRtcEngine object, the SDK publishes the local audio and video streams to that channel by default. Because the SDK does not support publishing a local stream to more than one channel simultaneously, an error occurs in this occasion. + * - -7(ERR_NOT_INITIALIZED): The SDK is not initialized before calling this method. + * - `ERR_JOIN_CHANNEL_REJECTED(-17)`: The request to join the channel is rejected. The SDK does not support + * joining the same IChannel channel repeatedly. Therefore, the SDK returns this error code when a user who has + * already joined an IChannel channel calls the joining channel method of this IChannel object. + */ + virtual int joinChannel(const char* token, const char* info, uid_t uid, const ChannelMediaOptions& options) = 0; + /** Joins the channel with a user account. + * + * Compared with the `joinChannelWithUserAccount` method in the IRtcEngine class, this method supports joining multiple channels at + * a time by creating multiple IChannel objects and then calling `joinChannelWithUserAccount` in each IChannel object. + * + * After the user successfully joins the channel, the SDK triggers the following callbacks: + * + * - The local client: \ref agora::rtc::IRtcEngineEventHandler::onLocalUserRegistered "onLocalUserRegistered" and \ref agora::rtc::IChannelEventHandler::onJoinChannelSuccess "onJoinChannelSuccess" . + * - The remote client: \ref agora::rtc::IChannelEventHandler::onUserJoined "onUserJoined" and \ref agora::rtc::IRtcEngineEventHandler::onUserInfoUpdated "onUserInfoUpdated" , if the user joining the channel is in the `COMMUNICATION` profile, or is a host in the `LIVE_BROADCASTING` profile. + * + * Once the user joins the channel, the user publishes the local audio and video streams and + * automatically subscribes to the audio and video streams of all the other users in the channel by default. + * Subscribing incurs all associated usage costs. To unsubscribe, set the `options` parameters or call the `mute` methods accordingly. + * + * @note + * - To ensure smooth communication, use the same parameter type to identify the user. For example, if a user joins the channel with a user ID, then ensure all the other users use the user ID too. The same applies to the user account. + * If a user joins the channel with the Agora Web SDK, ensure that the uid of the user is set to the same parameter type. + * - Before using a String user name, ensure that you read [How can I use string user names](https://docs.agora.io/en/faq/string) for getting details about the limitations and implementation steps. + * + * @param token The token generated at your server. See [Authenticate Your Users with Tokens](https://docs.agora.io/en/Interactive%20Broadcast/token_server?platform=All%20Platforms). + * @param userAccount The user account. The maximum length of this parameter is 255 bytes. Ensure that the user account is unique and do not set it as null. Supported character scopes are: + * - All lowercase English letters: a to z. + * - All uppercase English letters: A to Z. + * - All numeric characters: 0 to 9. + * - The space character. + * - Punctuation characters and other symbols, including: "!", "#", "$", "%", "&", "(", ")", "+", "-", ":", ";", "<", "=", ".", ">", "?", "@", "[", "]", "^", "_", " {", "}", "|", "~", ",". + * @param options The channel media options: \ref agora::rtc::ChannelMediaOptions::ChannelMediaOptions “ChannelMediaOptions”. + * + * @return + * - 0: Success. + * - < 0: Failure. + * - #ERR_INVALID_ARGUMENT (-2) + * - #ERR_NOT_READY (-3) + * - #ERR_REFUSED (-5) + * - #ERR_NOT_INITIALIZED (-7) + * - `ERR_JOIN_CHANNEL_REJECTED(-17)`: The request to join the channel is rejected. The SDK does not support + * joining the same IChannel channel repeatedly. Therefore, the SDK returns this error code when a user who has + * already joined an IChannel channel calls the joining channel method of this IChannel object. + */ + virtual int joinChannelWithUserAccount(const char* token, const char* userAccount, const ChannelMediaOptions& options) = 0; + /** Allows a user to leave a channel, such as hanging up or exiting a call. + + After joining a channel, the user must call the *leaveChannel* method to end the call before joining another channel. + + This method returns 0 if the user leaves the channel and releases all resources related to the call. + + This method call is asynchronous, and the user has not left the channel when the method call returns. Once the user leaves the channel, the SDK triggers the \ref IChannelEventHandler::onLeaveChannel "onLeaveChannel" callback. + + A successful \ref agora::rtc::IChannel::leaveChannel "leaveChannel" method call triggers the following callbacks: + - The local client: \ref agora::rtc::IChannelEventHandler::onLeaveChannel "onLeaveChannel" + - The remote client: \ref agora::rtc::IChannelEventHandler::onUserOffline "onUserOffline" , if the user leaving the channel is in the Communication channel, or is a host in the `LIVE_BROADCASTING` profile. + + @note + - If you call the \ref IChannel::release "release" method immediately after the *leaveChannel* method, the *leaveChannel* process interrupts, and the \ref IChannelEventHandler::onLeaveChannel "onLeaveChannel" callback is not triggered. + - If you call the *leaveChannel* method during a CDN live streaming, the SDK triggers the \ref IChannel::removePublishStreamUrl "removePublishStreamUrl" method. + + @return + - 0(ERR_OK): Success. + - < 0: Failure. + - -1(ERR_FAILED): A general error occurs (no specified reason). + - -2(ERR_INVALID_ARGUMENT): The parameter is invalid. + - -7(ERR_NOT_INITIALIZED): The SDK is not initialized. + */ + virtual int leaveChannel() = 0; + + /** Publishes the local stream to the channel. + + @deprecated This method is deprecated as of v3.4.5. Use \ref IChannel::muteLocalAudioStream "muteLocalAudioStream" (false) + or \ref IChannel::muteLocalVideoStream "muteLocalVideoStream" (false) instead. + + You must keep the following restrictions in mind when calling this method. Otherwise, the SDK returns the #ERR_REFUSED (5): + - This method publishes one stream only to the channel corresponding to the current IChannel object. + - In the interactive live streaming channel, only a host can call this method. + To switch the client role, call \ref IChannel::setClientRole "setClientRole" of the current IChannel object. + - You can publish a stream to only one channel at a time. For details on joining multiple channels, see the advanced guide *Join Multiple Channels*. + + @return + - 0: Success. + - < 0: Failure. + - #ERR_REFUSED (5): The method call is refused. + */ + virtual int publish() = 0; + + /** Stops publishing a stream to the channel. + + @deprecated This method is deprecated as of v3.4.5. Use \ref IChannel::muteLocalAudioStream "muteLocalAudioStream" (true) + or \ref IChannel::muteLocalVideoStream "muteLocalVideoStream" (true) instead. + + If you call this method in a channel where you are not publishing streams, the SDK returns #ERR_REFUSED (5). + + @return + - 0: Success. + - < 0: Failure. + - #ERR_REFUSED (5): The method call is refused. + */ + virtual int unpublish() = 0; + + /** Gets the channel ID of the current `IChannel` object. + + @return + - The channel ID of the current `IChannel` object, if the method call succeeds. + - The empty string "", if the method call fails. + */ + virtual const char* channelId() = 0; + /** Gets the current call ID. + + When a user joins a channel on a client, a `callId` is generated to identify the call from the client. + Feedback methods, such as \ref IRtcEngine::rate "rate" and \ref IRtcEngine::complain "complain", must be called after the call ends to submit feedback to the SDK. + + The `rate` and `complain` methods require the `callId` parameter retrieved from the `getCallId` method during a call. `callId` is passed as an argument into the `rate` and `complain` methods after the call ends. + + @note Ensure that you call this method after joining a channel. + + @param callId The current call ID. + + @return + - 0: Success. + - < 0: Failure. + */ + virtual int getCallId(agora::util::AString& callId) = 0; + /** Gets a new token when the current token expires after a period of time. + + The `token` expires after a period of time once the token schema is enabled when: + + - The SDK triggers the \ref IChannelEventHandler::onTokenPrivilegeWillExpire "onTokenPrivilegeWillExpire" callback, or + - The \ref IChannelEventHandler::onConnectionStateChanged "onConnectionStateChanged" reports CONNECTION_CHANGED_TOKEN_EXPIRED(9). + + The application should call this method to get the new `token`. Failure to do so will result in the SDK disconnecting from the server. + + @param token The new token. + + @return + - 0(ERR_OK): Success. + - < 0: Failure. + - -1(ERR_FAILED): A general error occurs (no specified reason). + - -2(ERR_INVALID_ARGUMENT): The parameter is invalid. + - -7(ERR_NOT_INITIALIZED): The SDK is not initialized. + */ + virtual int renewToken(const char* token) = 0; + /** Enables built-in encryption with an encryption password before users join a channel. + + @deprecated Deprecated as of v3.1.0. Use the \ref agora::rtc::IChannel::enableEncryption "enableEncryption" instead. + + All users in a channel must use the same encryption password. The encryption password is automatically cleared once a user leaves the channel. + + If an encryption password is not specified, the encryption functionality will be disabled. + + @note + - Do not use this method for CDN live streaming. + - For optimal transmission, ensure that the encrypted data size does not exceed the original data size + 16 bytes. 16 bytes is the maximum padding size for AES encryption. + + @param secret Pointer to the encryption password. + + @return + - 0: Success. + - < 0: Failure. + */ + virtual int setEncryptionSecret(const char* secret) = 0; + /** Sets the built-in encryption mode. + + @deprecated Deprecated as of v3.1.0. Use the \ref agora::rtc::IChannel::enableEncryption "enableEncryption" instead. + + The Agora SDK supports built-in encryption, which is set to the `aes-128-xts` mode by default. Call this method to use other encryption modes. + + All users in the same channel must use the same encryption mode and password. + + Refer to the information related to the AES encryption algorithm on the differences between the encryption modes. + + @note Call the \ref IChannel::setEncryptionSecret "setEncryptionSecret" method to enable the built-in encryption function before calling this method. + + @param encryptionMode The set encryption mode: + - "aes-128-xts": (Default) 128-bit AES encryption, XTS mode. + - "aes-128-ecb": 128-bit AES encryption, ECB mode. + - "aes-256-xts": 256-bit AES encryption, XTS mode. + - "": When encryptionMode is set as NULL, the encryption mode is set as "aes-128-xts" by default. + + @return + - 0: Success. + - < 0: Failure. + */ + virtual int setEncryptionMode(const char* encryptionMode) = 0; + /** Enables/Disables the built-in encryption. + * + * @since v3.1.0 + * + * In scenarios requiring high security, Agora recommends calling this method to enable the built-in encryption before joining a channel. + * + * After a user leaves the channel, the SDK automatically disables the built-in encryption. + * To re-enable the built-in encryption, call this method before the user joins the channel again. + * + * As of v3.4.5, Agora recommends using either the `AES_128_GCM2` or `AES_256_GCM2` encryption mode, + * both of which support adding a salt and are more secure. For details, see *Media Stream Encryption*. + * + * @warning All users in the same channel must use the same encryption mode, encryption key, and salt; otherwise, + * users cannot communicate with each other. + * + * @note + * - If you enable the built-in encryption, you cannot use the RTMP or RTMPS streaming function. + * - To enhance security, Agora recommends using a new key and salt every time you enable the media stream encryption. + * + * @param enabled Whether to enable the built-in encryption: + * - true: Enable the built-in encryption. + * - false: Disable the built-in encryption. + * @param config Configurations of built-in encryption schemas. See EncryptionConfig. + * + * @return + * - 0: Success. + * - < 0: Failure. + * - -2(ERR_INVALID_ARGUMENT): An invalid parameter is used. Set the parameter with a valid value. + * - -4(ERR_NOT_SUPPORTED): The encryption mode is incorrect or the SDK fails to load the external encryption library. Check the enumeration or reload the external encryption library. + * - -7(ERR_NOT_INITIALIZED): The SDK is not initialized. Initialize the `IRtcEngine` instance before calling this method. + */ + virtual int enableEncryption(bool enabled, const EncryptionConfig& config) = 0; + /** Registers a packet observer. + + The Agora SDK allows your application to register a packet observer to receive callbacks for voice or video packet transmission. + + @note + - The size of the packet sent to the network after processing should not exceed 1200 bytes, otherwise, the packet may fail to be sent. + - Ensure that both receivers and senders call this method, otherwise, you may meet undefined behaviors such as no voice and black screen. + - When you use CDN live streaming and recording functions, Agora doesn't recommend calling this method. + - Call this method before joining a channel. + @param observer The registered packet observer. See IPacketObserver. + + @return + - 0: Success. + - < 0: Failure. + */ + virtual int registerPacketObserver(IPacketObserver* observer) = 0; + /** Registers the metadata observer. + + Registers the metadata observer. You need to implement the IMetadataObserver class and specify the metadata type in this method. A successful call of this method triggers the \ref agora::rtc::IMetadataObserver::getMaxMetadataSize "getMaxMetadataSize" callback. + This method enables you to add synchronized metadata in the video stream for more diversified interactive live streaming, such as sending shopping links, digital coupons, and online quizzes. + + @note + - Call this method before the joinChannel method. + - This method applies to the `LIVE_BROADCASTING` channel profile. + + @param observer The IMetadataObserver class. See the definition of IMetadataObserver for details. + @param type See \ref IMetadataObserver::METADATA_TYPE "METADATA_TYPE". The SDK supports VIDEO_METADATA (0) only for now. + + @return + - 0: Success. + - < 0: Failure. + */ + virtual int registerMediaMetadataObserver(IMetadataObserver* observer, IMetadataObserver::METADATA_TYPE type) = 0; + /** Sets the role of the user in interactive live streaming. + * + * In the `LIVE_BROADCASTING` channel profile, the + * SDK sets the user role as audience by default. You can call `setClientRole` to set the user role as host. + * + * You can call this method either before or after joining a channel. If you + * call this method to switch the user role after joining a channel, the SDK automatically does the following: + * - Calls \ref IChannel::muteLocalAudioStream "muteLocalAudioStream" and \ref IChannel::muteLocalVideoStream "muteLocalVideoStream" to + * change the publishing state. + * - Triggers \ref IChannelEventHandler::onClientRoleChanged "onClientRoleChanged" on the local client. + * - Triggers \ref IChannelEventHandler::onUserJoined "onUserJoined" or \ref IChannelEventHandler::onUserOffline "onUserOffline" (BECOME_AUDIENCE) + * on the remote client. + * + * @note This method applies to the `LIVE_BROADCASTING` profile only. + * + * @param role The role of a user in interactive live streaming. See #CLIENT_ROLE_TYPE. + * + * @return + * - 0(ERR_OK): Success. + * - < 0: Failure. + * - -1(ERR_FAILED): A general error occurs (no specified reason). + * - -2(ERR_INVALID_ARGUMENT): The parameter is invalid. + * - -5 (ERR_REFUSED): The request is rejected. In multichannel scenarios, if you have set any of the following in + * one channel, the SDK returns this error code when the user switches the user role to host in another channel: + * - Call `joinChannel` with the `options` parameter and use the default settings `publishLocalAudio = true` or `publishLocalVideo = true`. + * - Call `setClientRole` to set the user role as host. + * - Call `muteLocalAudioStream(false)` or `muteLocalVideoStream(false)`. + * - -7(ERR_NOT_INITIALIZED): The SDK is not initialized. + */ + virtual int setClientRole(CLIENT_ROLE_TYPE role) = 0; + + /** Sets the role of the user in interactive live streaming. + * + * @since v3.2.0 + * + * In the `LIVE_BROADCASTING` channel profile, the + * SDK sets the user role as audience by default. You can call `setClientRole` to set the user role as host. + * + * You can call this method either before or after joining a channel. If you + * call this method to switch the user role after joining a channel, the SDK automatically does the following: + * - Calls \ref IChannel::muteLocalAudioStream "muteLocalAudioStream" and \ref IChannel::muteLocalVideoStream "muteLocalVideoStream" to + * change the publishing state. + * - Triggers \ref IChannelEventHandler::onClientRoleChanged "onClientRoleChanged" on the local client. + * - Triggers \ref IChannelEventHandler::onUserJoined "onUserJoined" or \ref IChannelEventHandler::onUserOffline "onUserOffline" (BECOME_AUDIENCE) + * on the remote client. + * + * @note + * - This method applies to the `LIVE_BROADCASTING` profile only. + * - The difference between this method and \ref IChannel::setClientRole(CLIENT_ROLE_TYPE) "setClientRole" [1/2] is that + * this method can set the user level in addition to the user role. + * - The user role determines the permissions that the SDK grants to a user, such as permission to send local streams, + * receive remote streams, and push streams to a CDN address. + * - The user level determines the level of services that a user can enjoy within the permissions of the user's role. + * For example, an audience member can choose to receive remote streams with low latency or ultra low latency. + * **User level affects the pricing of services.** + * + * @param role The role of a user in interactive live streaming. See #CLIENT_ROLE_TYPE. + * @param options The detailed options of a user, including user level. See ClientRoleOptions. + * + * @return + * - 0(ERR_OK): Success. + * - < 0: Failure. + * - -1(ERR_FAILED): A general error occurs (no specified reason). + * - -2(ERR_INVALID_ARGUMENT): The parameter is invalid. + * - -5 (ERR_REFUSED): The request is rejected. In multichannel scenarios, if you have set any of the following in + * one channel, the SDK returns this error code when the user switches the user role to host in another channel: + * - Call `joinChannel` with the `options` parameter and use the default settings `publishLocalAudio = true` or `publishLocalVideo = true`. + * - Call `setClientRole` to set the user role as host. + * - Call `muteLocalAudioStream(false)` or `muteLocalVideoStream(false)`. + * - -7(ERR_NOT_INITIALIZED): The SDK is not initialized. + */ + virtual int setClientRole(CLIENT_ROLE_TYPE role, const ClientRoleOptions& options) = 0; + + /** Prioritizes a remote user's stream. + * + * The SDK ensures the high-priority user gets the best possible stream quality. + * + * @note + * - The Agora SDK supports setting `serPriority` as high for one user only. + * - Ensure that you call this method before joining a channel. + * + * @param uid The ID of the remote user. + * @param userPriority Sets the priority of the remote user. See #PRIORITY_TYPE. + * + * @return + * - 0: Success. + * - < 0: Failure. + */ + virtual int setRemoteUserPriority(uid_t uid, PRIORITY_TYPE userPriority) = 0; + /** Sets the sound position and gain of a remote user. + + When the local user calls this method to set the sound position of a remote user, the sound difference between the left and right channels allows the + local user to track the real-time position of the remote user, creating a real sense of space. This method applies to massively multiplayer online games, + such as Battle Royale games. + + @note + - For this method to work, enable stereo panning for remote users by calling the \ref agora::rtc::IRtcEngine::enableSoundPositionIndication "enableSoundPositionIndication" method before joining a channel. + - This method requires hardware support. For the best sound positioning, we recommend using a wired headset. + - Ensure that you call this method after joining a channel. + + @param uid The ID of the remote user. + @param pan The sound position of the remote user. The value ranges from -1.0 to 1.0: + - 0.0: the remote sound comes from the front. + - -1.0: the remote sound comes from the left. + - 1.0: the remote sound comes from the right. + @param gain Gain of the remote user. The value ranges from 0.0 to 100.0. The default value is 100.0 (the original gain of the remote user). + The smaller the value, the less the gain. + + @return + - 0: Success. + - < 0: Failure. + */ + virtual int setRemoteVoicePosition(uid_t uid, double pan, double gain) = 0; + /** Updates the display mode of the video view of a remote user. + + After initializing the video view of a remote user, you can call this method to update its rendering and mirror modes. + This method affects only the video view that the local user sees. + + @note + - Call this method after calling the \ref agora::rtc::IRtcEngine::setupRemoteVideo "setupRemoteVideo" method to initialize the remote video view. + - During a call, you can call this method as many times as necessary to update the display mode of the video view of a remote user. + + @param userId The ID of the remote user. + @param renderMode The rendering mode of the remote video view. See #RENDER_MODE_TYPE. + @param mirrorMode + - The mirror mode of the remote video view. See #VIDEO_MIRROR_MODE_TYPE. + - **Note**: The SDK disables the mirror mode by default. + + @return + - 0: Success. + - < 0: Failure. + */ + virtual int setRemoteRenderMode(uid_t userId, RENDER_MODE_TYPE renderMode, VIDEO_MIRROR_MODE_TYPE mirrorMode) = 0; + /** Stops or resumes subscribing to the audio streams of all remote users by default. + * + * @deprecated This method is deprecated from v3.3.0. + * + * + * Call this method after joining a channel. After successfully calling this method, the + * local user stops or resumes subscribing to the audio streams of all subsequent users. + * + * @note If you need to resume subscribing to the audio streams of remote users in the + * channel after calling \ref IRtcEngine::setDefaultMuteAllRemoteAudioStreams "setDefaultMuteAllRemoteAudioStreams" (true), do the following: + * - If you need to resume subscribing to the audio stream of a specified user, call \ref IRtcEngine::muteRemoteAudioStream "muteRemoteAudioStream" (false), and specify the user ID. + * - If you need to resume subscribing to the audio streams of multiple remote users, call \ref IRtcEngine::muteRemoteAudioStream "muteRemoteAudioStream" (false) multiple times. + * + * @param mute Sets whether to stop subscribing to the audio streams of all remote users by default. + * - true: Stop subscribing to the audio streams of all remote users by default. + * - false: (Default) Resume subscribing to the audio streams of all remote users by default. + * + * @return + * - 0: Success. + * - < 0: Failure. + */ + virtual int setDefaultMuteAllRemoteAudioStreams(bool mute) = 0; + /** Stops or resumes subscribing to the video streams of all remote users by default. + * + * @deprecated This method is deprecated from v3.3.0. + * + * Call this method after joining a channel. After successfully calling this method, the + * local user stops or resumes subscribing to the video streams of all subsequent users. + * + * @note If you need to resume subscribing to the video streams of remote users in the + * channel after calling \ref IChannel::setDefaultMuteAllRemoteVideoStreams "setDefaultMuteAllRemoteVideoStreams" (true), do the following: + * - If you need to resume subscribing to the video stream of a specified user, call \ref IChannel::muteRemoteVideoStream "muteRemoteVideoStream" (false), and specify the user ID. + * - If you need to resume subscribing to the video streams of multiple remote users, call \ref IChannel::muteRemoteVideoStream "muteRemoteVideoStream" (false) multiple times. + * + * @param mute Sets whether to stop subscribing to the video streams of all remote users by default. + * - true: Stop subscribing to the video streams of all remote users by default. + * - false: (Default) Resume subscribing to the video streams of all remote users by default. + * + * @return + * - 0: Success. + * - < 0: Failure. + */ + virtual int setDefaultMuteAllRemoteVideoStreams(bool mute) = 0; + /** + * Stops or resumes publishing the local audio stream. + * + * @since v3.4.5 + * + * This method only sets the publishing state of the audio stream in the channel of IChannel. + * + * A successful method call triggers the + * \ref IChannelEventHandler::onRemoteAudioStateChanged "onRemoteAudioStateChanged" + * callback on the remote client. + * + * You can only publish the local stream in one channel at a time. If you create multiple channels, ensure that + * you only call \ref IChannel::muteLocalAudioStream "muteLocalAudioStream" (false) in one channel; + * otherwise, the method call fails, and the SDK returns `-5 (ERR_REFUSED)`. + * + * @note + * - This method does not change the usage state of the audio-capturing device. + * - Whether this method call takes effect is affected by the \ref IChannel::joinChannel "joinChannel" + * and \ref IChannel::setClientRole "setClientRole" methods. For details, see *Set the Publishing State*. + * + * @param mute Sets whether to stop publishing the local audio stream. + * - true: Stop publishing the local audio stream. + * - false: Resume publishing the local audio stream. + * + * @return + * - 0: Success. + * - < 0: Failure. + * - `-5 (ERR_REFUSED)`: The request is rejected. + */ + virtual int muteLocalAudioStream(bool mute) = 0; + /** Stops or resumes publishing the local video stream. + * + * @since v3.4.5 + * + * This method only sets the publishing state of the video stream in the channel of IChannel. + * + * A successful method call triggers the \ref IChannelEventHandler::onRemoteVideoStateChanged "onRemoteVideoStateChanged" + * callback on the remote client. + * + * You can only publish the local stream in one channel at a time. If you create multiple channels, + * ensure that you only call \ref IChannel::muteLocalVideoStream "muteLocalVideoStream" (false) in one channel; + * otherwise, the method call fails, and the SDK returns `-5 (ERR_REFUSED)`. + * + * @note + * - This method does not change the usage state of the video-capturing device. + * - Whether this method call takes effect is affected by the \ref IChannel::joinChannel "joinChannel" + * and \ref IChannel::setClientRole "setClientRole" methods. For details, see *Set the Publishing State*. + * + * @param mute Sets whether to stop publishing the local video stream. + * - true: Stop publishing the local video stream. + * - false: Resume publishing the local video stream. + * + * @return + * - 0: Success. + * - < 0: Failure. + * - `-5 (ERR_REFUSED)`: The request is rejected. + */ + virtual int muteLocalVideoStream(bool mute) = 0; + /** + * Stops or resumes subscribing to the audio streams of all remote users. + * + * After successfully calling this method, the local user stops or resumes + * subscribing to the audio streams of all remote users, including all subsequent users. + * + * @note + * - Call this method after joining a channel. + * - As of v3.3.0, this method contains the function of \ref IChannel::setDefaultMuteAllRemoteAudioStreams "setDefaultMuteAllRemoteAudioStreams". + * Agora recommends not calling `muteAllRemoteAudioStreams` and `setDefaultMuteAllRemoteAudioStreams` + * together; otherwise, the settings may not take effect. See *Set the Subscribing State*. + * + * @param mute Sets whether to stop subscribing to the audio streams of all remote users. + * - true: Stop subscribing to the audio streams of all remote users. + * - false: (Default) Resume subscribing to the audio streams of all remote users. + * + * @return + * - 0: Success. + * - < 0: Failure. + */ + virtual int muteAllRemoteAudioStreams(bool mute) = 0; + /** Adjust the playback signal volume of the specified remote user. + * + * After joining a channel, call \ref agora::rtc::IRtcEngine::adjustPlaybackSignalVolume "adjustPlaybackSignalVolume" to adjust the playback volume of different remote users, + * or adjust multiple times for one remote user. + * + * @note + * - Call this method after joining a channel. + * - This method adjusts the playback volume, which is the mixed volume for the specified remote user. + * - This method can only adjust the playback volume of one specified remote user at a time. If you want to adjust the playback volume of several remote users, + * call the method multiple times, once for each remote user. + * + * @param userId The user ID, which should be the same as the `uid` of \ref agora::rtc::IChannel::joinChannel "joinChannel" + * @param volume The playback volume of the voice. The value + * ranges between 0 and 400, including the following: + * - 0: Mute. + * - 100: (Default) Original volume. + * - 400: Four times the original volume with signal-clipping protection. + * + * @return + * - 0: Success. + * - < 0: Failure. + */ + virtual int adjustUserPlaybackSignalVolume(uid_t userId, int volume) = 0; + /** + * Stops or resumes subscribing to the audio stream of a specified user. + * + * @note + * - Call this method after joining a channel. + * - See recommended settings in *Set the Subscribing State*. + * + * @param userId The user ID of the specified remote user. + * @param mute Sets whether to stop subscribing to the audio stream of a specified user. + * - true: Stop subscribing to the audio stream of a specified user. + * - false: (Default) Resume subscribing to the audio stream of a specified user. + * + * @return + * - 0: Success. + * - < 0: Failure. + */ + virtual int muteRemoteAudioStream(uid_t userId, bool mute) = 0; + /** + * Stops or resumes subscribing to the video streams of all remote users. + * + * After successfully calling this method, the local user stops or resumes + * subscribing to the video streams of all remote users, including all subsequent users. + * + * @note + * - Call this method after joining a channel. + * - See recommended settings in *Set the Subscribing State*. + * + * @param mute Sets whether to stop subscribing to the video streams of all remote users. + * - true: Stop subscribing to the video streams of all remote users. + * - false: (Default) Resume subscribing to the video streams of all remote users. + * + * @return + * - 0: Success. + * - < 0: Failure. + */ + virtual int muteAllRemoteVideoStreams(bool mute) = 0; + /** + * Stops or resumes subscribing to the video stream of a specified user. + * + * @note + * - Call this method after joining a channel. + * - See recommended settings in *Set the Subscribing State*. + * + * @param userId The user ID of the specified remote user. + * @param mute Sets whether to stop subscribing to the video stream of a specified user. + * - true: Stop subscribing to the video stream of a specified user. + * - false: (Default) Resume subscribing to the video stream of a specified user. + * + * @return + * - 0: Success. + * - < 0: Failure. + */ + virtual int muteRemoteVideoStream(uid_t userId, bool mute) = 0; + /** Sets the stream type of the remote video. + + Under limited network conditions, if the publisher has not disabled the dual-stream mode using + \ref agora::rtc::IRtcEngine::enableDualStreamMode "enableDualStreamMode" (false), + the receiver can choose to receive either the high-quality video stream (the high resolution, and high bitrate video stream) or + the low-video stream (the low resolution, and low bitrate video stream). + + By default, users receive the high-quality video stream. Call this method if you want to switch to the low-video stream. + This method allows the app to adjust the corresponding video stream type based on the size of the video window to + reduce the bandwidth and resources. + + The aspect ratio of the low-video stream is the same as the high-quality video stream. Once the resolution of the high-quality video + stream is set, the system automatically sets the resolution, frame rate, and bitrate of the low-video stream. + + The method result returns in the \ref agora::rtc::IRtcEngineEventHandler::onApiCallExecuted "onApiCallExecuted" callback. + + @note You can call this method either before or after joining a channel. If you call both + \ref IChannel::setRemoteVideoStreamType "setRemoteVideoStreamType" and + \ref IChannel::setRemoteDefaultVideoStreamType "setRemoteDefaultVideoStreamType", the SDK applies the settings in + the \ref IChannel::setRemoteVideoStreamType "setRemoteVideoStreamType" method. + + @param userId The ID of the remote user sending the video stream. + @param streamType Sets the video-stream type. See #REMOTE_VIDEO_STREAM_TYPE. + @return + - 0: Success. + - < 0: Failure. + */ + virtual int setRemoteVideoStreamType(uid_t userId, REMOTE_VIDEO_STREAM_TYPE streamType) = 0; + /** Sets the default stream type of remote videos. + + Under limited network conditions, if the publisher has not disabled the dual-stream mode using + \ref agora::rtc::IRtcEngine::enableDualStreamMode "enableDualStreamMode" (false), + the receiver can choose to receive either the high-quality video stream (the high resolution, and high bitrate video stream) or + the low-video stream (the low resolution, and low bitrate video stream). + + By default, users receive the high-quality video stream. Call this method if you want to switch to the low-video stream. + This method allows the app to adjust the corresponding video stream type based on the size of the video window to + reduce the bandwidth and resources. The aspect ratio of the low-video stream is the same as the high-quality video stream. + Once the resolution of the high-quality video + stream is set, the system automatically sets the resolution, frame rate, and bitrate of the low-video stream. + + The method result returns in the \ref agora::rtc::IRtcEngineEventHandler::onApiCallExecuted "onApiCallExecuted" callback. + + @note You can call this method either before or after joining a channel. If you call both + \ref IChannel::setRemoteVideoStreamType "setRemoteVideoStreamType" and + \ref IChannel::setRemoteDefaultVideoStreamType "setRemoteDefaultVideoStreamType", the SDK applies the settings in + the \ref IChannel::setRemoteVideoStreamType "setRemoteVideoStreamType" method. + + @param streamType Sets the default video-stream type. See #REMOTE_VIDEO_STREAM_TYPE. + + @return + - 0: Success. + - < 0: Failure. + */ + virtual int setRemoteDefaultVideoStreamType(REMOTE_VIDEO_STREAM_TYPE streamType) = 0; + /** Creates a data stream. + + @deprecated This method is deprecated from v3.3.0. Use the \ref IChannel::createDataStream(int* streamId, DataStreamConfig& config) "createDataStream" [2/2] method instead. + + Each user can create up to five data streams during the lifecycle of the IChannel. + + @note + - Do not set `reliable` as `true` while setting `ordered` as `false`. + - Ensure that you call this method after joining a channel. + + @param[out] streamId The ID of the created data stream. + @param reliable Sets whether or not the recipients are guaranteed to receive the data stream from the sender within five seconds: + - true: The recipients receive the data stream from the sender within five seconds. If the recipient does not receive the data stream within five seconds, + an error is reported to the application. + - false: There is no guarantee that the recipients receive the data stream within five seconds and no error message is reported for + any delay or missing data stream. + @param ordered Sets whether or not the recipients receive the data stream in the sent order: + - true: The recipients receive the data stream in the sent order. + - false: The recipients do not receive the data stream in the sent order. + + @return + - Returns 0: Success. + - < 0: Failure. + */ + virtual int createDataStream(int* streamId, bool reliable, bool ordered) = 0; + /** Creates a data stream. + * + * @since v3.3.0 + * + * Each user can create up to five data streams in a single channel. + * + * This method does not support data reliability. If the receiver receives a data packet five + * seconds or more after it was sent, the SDK directly discards the data. + * + * @param[out] streamId The ID of the created data stream. + * @param config The configurations for the data stream: DataStreamConfig. + * + * @return + * - 0: Creates the data stream successfully. + * - < 0: Fails to create the data stream. + */ + virtual int createDataStream(int* streamId, DataStreamConfig& config) = 0; + /** Sends data stream messages to all users in a channel. + + The SDK has the following restrictions on this method: + - Up to 30 packets can be sent per second in a channel with each packet having a maximum size of 1 kB. + - Each client can send up to 6 kB of data per second. + - Each user can have up to five data streams simultaneously. + + A successful \ref agora::rtc::IChannel::sendStreamMessage "sendStreamMessage" method call triggers + the \ref agora::rtc::IChannelEventHandler::onStreamMessage "onStreamMessage" callback on the remote client, from which the remote user gets the stream message. + + A failed \ref agora::rtc::IChannel::sendStreamMessage "sendStreamMessage" method call triggers + the \ref agora::rtc::IChannelEventHandler::onStreamMessageError "onStreamMessage" callback on the remote client. + + @note + - This method applies only to the `COMMUNICATION` profile or to the hosts in the `LIVE_BROADCASTING` profile. If an audience in the `LIVE_BROADCASTING` profile calls this method, the audience may be switched to a host. + - Ensure that you have created the data stream using \ref agora::rtc::IChannel::createDataStream "createDataStream" before calling this method. + + @param streamId The ID of the sent data stream, returned in the \ref IChannel::createDataStream "createDataStream" method. + @param data The sent data. + @param length The length of the sent data. + + @return + - 0: Success. + - < 0: Failure. + */ + virtual int sendStreamMessage(int streamId, const char* data, size_t length) = 0; + /** Publishes the local stream to a specified CDN streaming URL. (CDN live only.) + + The SDK returns the result of this method call in the \ref IRtcEngineEventHandler::onStreamPublished "onStreamPublished" callback. + + After calling this method, you can push media streams in RTMP or RTMPS protocol to the CDN. The SDK triggers + the \ref agora::rtc::IChannelEventHandler::onRtmpStreamingStateChanged "onRtmpStreamingStateChanged" callback on the local client + to report the state of adding a local stream to the CDN. + + @note + - Ensure that the user joins the channel before calling this method. + - Ensure that you enable the RTMP Converter service before using this function. See Prerequisites in the advanced guide *Push Streams to CDN*. + - This method adds only one stream CDN streaming URL each time it is called. + - Agora supports pushing media streams in RTMPS protocol to the CDN only when you enable transcoding. + + @param url The CDN streaming URL in the RTMP or RTMPS format. The maximum length of this parameter is 1024 bytes. The CDN streaming URL must not contain special characters, such as Chinese language characters. + @param transcodingEnabled Sets whether transcoding is enabled/disabled: + - true: Enable transcoding. To [transcode](https://docs.agora.io/en/Agora%20Platform/terms?platform=All%20Platforms#transcoding) the audio or video streams when publishing them to CDN live, often used for combining the audio and video streams of multiple hosts in CDN live. If you set this parameter as `true`, ensure that you call the \ref IChannel::setLiveTranscoding "setLiveTranscoding" method before this method. + - false: Disable transcoding. + + @return + - 0: Success. + - < 0: Failure. + - #ERR_INVALID_ARGUMENT (-2): The CDN streaming URL is NULL or has a string length of 0. + - #ERR_NOT_INITIALIZED (-7): You have not initialized `IChannel` when publishing the stream. + */ + virtual int addPublishStreamUrl(const char* url, bool transcodingEnabled) = 0; + /** Removes an RTMP or RTMPS stream from the CDN. + + This method removes the CDN streaming URL (added by the \ref IChannel::addPublishStreamUrl "addPublishStreamUrl" method) from a CDN live stream. + The SDK returns the result of this method call in the \ref IRtcEngineEventHandler::onStreamUnpublished "onStreamUnpublished" callback. + + The \ref agora::rtc::IChannel::removePublishStreamUrl "removePublishStreamUrl" method call triggers + the \ref agora::rtc::IChannelEventHandler::onRtmpStreamingStateChanged "onRtmpStreamingStateChanged" callback on the local client to report the state of removing an RTMP or RTMPS stream from the CDN. + + @note + - This method removes only one CDN streaming URL each time it is called. + - The CDN streaming URL must not contain special characters, such as Chinese language characters. + + @param url The CDN streaming URL to be removed. The maximum length of this parameter is 1024 bytes. + + @return + - 0: Success. + - < 0: Failure. + */ + virtual int removePublishStreamUrl(const char* url) = 0; + /** Sets the video layout and audio settings for CDN live. (CDN live only.) + + The SDK triggers the \ref agora::rtc::IChannelEventHandler::onTranscodingUpdated "onTranscodingUpdated" callback when you + call the `setLiveTranscoding` method to update the transcoding setting. + + @note + - Ensure that you enable the RTMP Converter service before using this function. See Prerequisites in the advanced guide *Push Streams to CDN*.. + - If you call the `setLiveTranscoding` method to set the transcoding setting for the first time, the SDK does not trigger the `onTranscodingUpdated` callback. + - Ensure that you call this method after joining a channel. + - Agora supports pushing media streams in RTMPS protocol to the CDN only when you enable transcoding. + + @param transcoding Sets the CDN live audio/video transcoding settings. See LiveTranscoding. + + @return + - 0: Success. + - < 0: Failure. + */ + virtual int setLiveTranscoding(const LiveTranscoding& transcoding) = 0; + /** Adds a voice or video stream URL address to the interactive live streaming. + + The \ref IRtcEngineEventHandler::onStreamPublished "onStreamPublished" callback returns the inject status. + If this method call is successful, the server pulls the voice or video stream and injects it into a live channel. + This is applicable to scenarios where all audience members in the channel can watch a live show and interact with each other. + + The \ref agora::rtc::IChannel::addInjectStreamUrl "addInjectStreamUrl" method call triggers the following callbacks: + - The local client: + - \ref agora::rtc::IChannelEventHandler::onStreamInjectedStatus "onStreamInjectedStatus" , with the state of the injecting the online stream. + - \ref agora::rtc::IChannelEventHandler::onUserJoined "onUserJoined" (uid: 666), if the method call is successful and the online media stream is injected into the channel. + - The remote client: + - \ref agora::rtc::IChannelEventHandler::onUserJoined "onUserJoined" (uid: 666), if the method call is successful and the online media stream is injected into the channel. + + @warning Agora will soon stop the service for injecting online media streams on the client. If you have not implemented this service, Agora recommends that you do not use it. + + @note + - Ensure that you enable the RTMP Converter service before using this function. See Prerequisites in the advanced guide *Push Streams to CDN*. + - This method applies to the Native SDK v2.4.1 and later. + - This method applies to the `LIVE_BROADCASTING` profile only. + - You can inject only one media stream into the channel at the same time. + - Ensure that you call this method after joining a channel. + + @param url The URL address to be added to the ongoing live streaming. Valid protocols are RTMP, HLS, and HTTP-FLV. + - Supported audio codec type: AAC. + - Supported video codec type: H264 (AVC). + @param config The InjectStreamConfig object that contains the configuration of the added voice or video stream. + + @return + - 0: Success. + - < 0: Failure. + - #ERR_INVALID_ARGUMENT (-2): The injected URL does not exist. Call this method again to inject the stream and ensure that the URL is valid. + - #ERR_NOT_READY (-3): The user is not in the channel. + - #ERR_NOT_SUPPORTED (-4): The channel profile is not `LIVE_BROADCASTING`. Call the \ref IRtcEngine::setChannelProfile "setChannelProfile" method and set the channel profile to `LIVE_BROADCASTING` before calling this method. + - #ERR_NOT_INITIALIZED (-7): The SDK is not initialized. Ensure that the IChannel object is initialized before calling this method. + */ + virtual int addInjectStreamUrl(const char* url, const InjectStreamConfig& config) = 0; + /** Removes the voice or video stream URL address from a live streaming. + + This method removes the URL address (added by the \ref IChannel::addInjectStreamUrl "addInjectStreamUrl" method) from the live streaming. + + @warning Agora will soon stop the service for injecting online media streams on the client. If you have not implemented this service, Agora recommends that you do not use it. + + @note If this method is called successfully, the SDK triggers the \ref IChannelEventHandler::onUserOffline "onUserOffline" callback and returns a stream uid of 666. + + @param url Pointer to the URL address of the added stream to be removed. + + @return + - 0: Success. + - < 0: Failure. + */ + virtual int removeInjectStreamUrl(const char* url) = 0; + /** Starts to relay media streams across channels. + * + * After a successful method call, the SDK triggers the + * \ref agora::rtc::IChannelEventHandler::onChannelMediaRelayStateChanged + * "onChannelMediaRelayStateChanged" and + * \ref agora::rtc::IChannelEventHandler::onChannelMediaRelayEvent + * "onChannelMediaRelayEvent" callbacks, and these callbacks return the + * state and events of the media stream relay. + * - If the + * \ref agora::rtc::IChannelEventHandler::onChannelMediaRelayStateChanged + * "onChannelMediaRelayStateChanged" callback returns + * #RELAY_STATE_RUNNING (2) and #RELAY_OK (0), and the + * \ref agora::rtc::IChannelEventHandler::onChannelMediaRelayEvent + * "onChannelMediaRelayEvent" callback returns + * #RELAY_EVENT_PACKET_SENT_TO_DEST_CHANNEL (4), the host starts + * sending data to the destination channel. + * - If the + * \ref agora::rtc::IChannelEventHandler::onChannelMediaRelayStateChanged + * "onChannelMediaRelayStateChanged" callback returns + * #RELAY_STATE_FAILURE (3), an exception occurs during the media stream + * relay. + * + * @note + * - Call this method after the \ref joinChannel() "joinChannel" method. + * - This method takes effect only when you are a host in a + * `LIVE_BROADCASTING` channel. + * - After a successful method call, if you want to call this method + * again, ensure that you call the + * \ref stopChannelMediaRelay() "stopChannelMediaRelay" method to quit the + * current relay. + * - Contact sales-us@agora.io before implementing this function. + * - We do not support string user accounts in this API. + * + * @param configuration The configuration of the media stream relay: + * ChannelMediaRelayConfiguration. + * + * @return + * - 0: Success. + * - < 0: Failure. + */ + virtual int startChannelMediaRelay(const ChannelMediaRelayConfiguration& configuration) = 0; + /** Updates the channels for media stream relay. + * + * After a successful + * \ref startChannelMediaRelay() "startChannelMediaRelay" method call, if + * you want to relay the media stream to more channels, or leave the + * current relay channel, you can call the + * \ref updateChannelMediaRelay() "updateChannelMediaRelay" method. + * + * After a successful method call, the SDK triggers the + * \ref agora::rtc::IChannelEventHandler::onChannelMediaRelayEvent + * "onChannelMediaRelayEvent" callback with the + * #RELAY_EVENT_PACKET_UPDATE_DEST_CHANNEL (7) state code. + * + * @note Call this method after successfully calling the \ref startChannelMediaRelay() "startChannelMediaRelay" method + * and receiving the \ref IChannelEventHandler::onChannelMediaRelayStateChanged "onChannelMediaRelayStateChanged" (RELAY_STATE_RUNNING, RELAY_OK) callback; + * otherwise, this method call fails. + * + * @param configuration The media stream relay configuration: + * ChannelMediaRelayConfiguration. + * + * @return + * - 0: Success. + * - < 0: Failure. + */ + virtual int updateChannelMediaRelay(const ChannelMediaRelayConfiguration& configuration) = 0; + + /** + * Pauses the media stream relay to all destination channels. + * + * @since v3.5.1 + * + * After the cross-channel media stream relay starts, you can call this method + * to pause relaying media streams to all destination channels; after the pause, + * if you want to resume the relay, call \ref IChannel::resumeAllChannelMediaRelay "resumeAllChannelMediaRelay". + * + * After a successful method call, the SDK triggers the + * \ref IChannelEventHandler::onChannelMediaRelayEvent "onChannelMediaRelayEvent" + * callback to report whether the media stream relay is successfully paused. + * + * @note Call this method after the \ref IChannel::startChannelMediaRelay "startChannelMediaRelay" method. + * + * @return + * - 0: Success. + * - < 0: Failure. + */ + virtual int pauseAllChannelMediaRelay() = 0; + + /** Resumes the media stream relay to all destination channels. + * + * @since v3.5.1 + * + * After calling the \ref IChannel::pauseAllChannelMediaRelay "pauseAllChannelMediaRelay" method, + * you can call this method to resume relaying media streams to all destination channels. + * + * After a successful method call, the SDK triggers the + * \ref IChannelEventHandler::onChannelMediaRelayEvent "onChannelMediaRelayEvent" + * callback to report whether the media stream relay is successfully resumed. + * + * @note Call this method after the \ref IChannel::pauseAllChannelMediaRelay "pauseAllChannelMediaRelay" method. + * + * @return + * - 0: Success. + * - < 0: Failure. + */ + virtual int resumeAllChannelMediaRelay() = 0; + + /** Stops the media stream relay. + * + * Once the relay stops, the host quits all the destination + * channels. + * + * After a successful method call, the SDK triggers the + * \ref agora::rtc::IChannelEventHandler::onChannelMediaRelayStateChanged + * "onChannelMediaRelayStateChanged" callback. If the callback returns + * #RELAY_STATE_IDLE (0) and #RELAY_OK (0), the host successfully + * stops the relay. + * + * @note + * If the method call fails, the SDK triggers the + * \ref agora::rtc::IChannelEventHandler::onChannelMediaRelayStateChanged + * "onChannelMediaRelayStateChanged" callback with the + * #RELAY_ERROR_SERVER_NO_RESPONSE (2) or + * #RELAY_ERROR_SERVER_CONNECTION_LOST (8) error code. You can leave the + * channel by calling the \ref leaveChannel() "leaveChannel" method, and + * the media stream relay automatically stops. + * + * @return + * - 0: Success. + * - < 0: Failure. + */ + virtual int stopChannelMediaRelay() = 0; + /** Gets the current connection state of the SDK. + + @note You can call this method either before or after joining a channel. + + @return #CONNECTION_STATE_TYPE. + */ + virtual CONNECTION_STATE_TYPE getConnectionState() = 0; + + /** Enables/Disables the super resolution feature for a remote user's video. (beta feature) + * + * @since v3.5.1 + * + * This feature effectively boosts the resolution of a remote user's video seen by the local + * user. If the original resolution of a remote user's video is a × b, the local user's device + * can render the remote video at a resolution of 2a × 2b after you enable this feature. + * + * After calling this method, the SDK triggers the + * \ref IChannelEventHandler::onUserSuperResolutionEnabled "onUserSuperResolutionEnabled" + * callback to report whether you have successfully enabled super resolution. + * + * @warning The super resolution feature requires extra system resources. To balance the visual experience and system consumption, the SDK poses the following restrictions: + * - This feature can only be enabled for a single remote user. + * - The original resolution of the remote user's video cannot exceed a certain range. If the local user use super resolution on Android, + * the original resolution of the remote user's video cannot exceed 640 × 360 pixels; if the local user use super resolution on iOS, + * the original resolution of the remote user's video cannot exceed 640 × 480 pixels. + * + * @warning If you exceed these limitations, the SDK triggers the + * \ref IRtcEngineEventHandler::onWarning "onWarning" callback and returns the corresponding warning codes: + * - #WARN_SUPER_RESOLUTION_STREAM_OVER_LIMITATION (1610): The original resolution of the remote user's video is beyond + * the range where super resolution can be applied. + * - #WARN_SUPER_RESOLUTION_USER_COUNT_OVER_LIMITATION (1611): Super resolution is already being used to boost another + * remote user's video. + * - #WARN_SUPER_RESOLUTION_DEVICE_NOT_SUPPORTED (1612): The device does not support using super resolution. + * + * @note + * - This method is for Android and iOS only. + * - Before calling this method, ensure that you have integrated the following dynamic library into your project: + * - Android: `libagora_super_resolution_extension.so` + * - iOS: `AgoraSuperResolutionExtension.xcframework` + * - Because this method has certain system performance requirements, Agora recommends that you use the following devices or better: + * - Android: + * - VIVO: V1821A, NEX S, 1914A, 1916A, 1962A, 1824BA, X60, X60 Pro + * - OPPO: PCCM00, Find X3 + * - OnePlus: A6000 + * - Xiaomi: Mi 8, Mi 9, Mi 10, Mi 11, MIX3, Redmi K20 Pro + * - SAMSUNG: SM-G9600, SM-G9650, SM-N9600, SM-G9708, SM-G960U, SM-G9750, S20, S21 + * - HUAWEI: SEA-AL00, ELE-AL00, VOG-AL00, YAL-AL10, HMA-AL00, EVR-AN00, nova 4, nova 5 Pro, + * nova 6 5G, nova 7 5G, Mate 30, Mate 30 Pro, Mate 40, Mate 40 Pro, P40 P40 Pro, HUAWEI MediaPad M6, MatePad 10.8 + * - iOS (iOS 12.0 or later): + * - iPhone XR + * - iPhone XS + * - iPhone XS Max + * - iPhone 11 + * - iPhone 11 Pro + * - iPhone 11 Pro Max + * - iPhone 12 + * - iPhone 12 mini + * - iPhone 12 Pro + * - iPhone 12 Pro Max + * - iPhone 12 SE (2nd generation) + * - iPad Pro 11-inch (3rd generation) + * - iPad Pro 12.9-inch (3rd generation) + * - iPad Air (3rd generation) + * - iPad Air (4th generation) + * + * @param userId The user ID of the remote user. + * @param enable Determines whether to enable super resolution for the remote user's video: + * - true: Enable super resolution. + * - false: Disable super resolution. + * + * @return + * - 0: Success. + * - < 0: Failure. + * - `-157 (ERR_MODULE_NOT_FOUND)`: The dynamic library for super resolution is not integrated. + */ + virtual int enableRemoteSuperResolution(uid_t userId, bool enable) = 0; +}; +/** @since v3.0.0 + + The IRtcEngine2 class. */ +class IRtcEngine2 : public IRtcEngine { + public: + /** Creates and gets an `IChannel` object. + + To join more than one channel, call this method multiple times to create as many `IChannel` objects as needed, and + call the \ref agora::rtc::IChannel::joinChannel "joinChannel" method of each created `IChannel` object. + + After joining multiple channels, you can simultaneously subscribe to streams of all the channels, but publish a stream in only one channel at one time. + @param channelId The unique channel name for an Agora RTC session. It must be in the string format and not exceed 64 bytes in length. Supported character scopes are: + - All lowercase English letters: a to z. + - All uppercase English letters: A to Z. + - All numeric characters: 0 to 9. + - The space character. + - Punctuation characters and other symbols, including: "!", "#", "$", "%", "&", "(", ")", "+", "-", ":", ";", "<", "=", ".", ">", "?", "@", "[", "]", "^", "_", " {", "}", "|", "~", ",". + + @note + - This parameter does not have a default value. You must set it. + - Do not set it as the empty string "". Otherwise, the SDK returns #ERR_REFUSED (5). + + @return + - The `IChannel` object, if the method call succeeds. + - An empty pointer NULL, if the method call fails. + - `ERR_REFUSED(5)`, if you set channelId as the empty string "". + */ + virtual IChannel* createChannel(const char* channelId) = 0; +}; + +} // namespace rtc +} // namespace agora + +#endif diff --git a/integration_test_app/iris_integration_test/third_party/agora/rtc/include/IAgoraRtcEngine.h b/integration_test_app/iris_integration_test/third_party/agora/rtc/include/IAgoraRtcEngine.h new file mode 100644 index 000000000..907337e73 --- /dev/null +++ b/integration_test_app/iris_integration_test/third_party/agora/rtc/include/IAgoraRtcEngine.h @@ -0,0 +1,11354 @@ +// +// AgoraRtcEngine SDK +// +// Copyright (c) 2019 Agora.io. All rights reserved. +// + +/** + @defgroup createAgoraRtcEngine Create an AgoraRtcEngine + */ + +#ifndef AGORA_RTC_ENGINE_H +#define AGORA_RTC_ENGINE_H +#include "AgoraBase.h" +#include "IAgoraService.h" +#include "IAgoraLog.h" + +#include "IAgoraMediaEngine.h" +#if defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE /* Warning fixing. Lionfore Oct 12th, 2019 */ +#include +#endif + +namespace agora { +namespace rtc { +/** The IMediaRecorderObserver class. + * + * @since v3.5.2 + */ +class IMediaRecorderObserver; +/** + * The MediaRecorderConfiguration struct. + * + * @since v3.5.2 + */ +struct MediaRecorderConfiguration; +typedef unsigned int uid_t; +typedef void* view_t; +/** Maximum length of the device ID. + */ +enum MAX_DEVICE_ID_LENGTH_TYPE { + /** The maximum length of the device ID is 512 bytes. + */ + MAX_DEVICE_ID_LENGTH = 512 +}; +/** Maximum length of user account. + */ +enum MAX_USER_ACCOUNT_LENGTH_TYPE { + /** The maximum length of user account is 255 bytes. + */ + MAX_USER_ACCOUNT_LENGTH = 256 +}; +/** Maximum length of channel ID. + */ +enum MAX_CHANNEL_ID_LENGTH_TYPE { + /** The maximum length of channel id is 64 bytes. + */ + MAX_CHANNEL_ID_LENGTH = 65 +}; +/** Formats of the quality report. + */ +enum QUALITY_REPORT_FORMAT_TYPE { + /** 0: The quality report in JSON format, + */ + QUALITY_REPORT_JSON = 0, + /** 1: The quality report in HTML format. + */ + QUALITY_REPORT_HTML = 1, +}; +/// @cond +enum MEDIA_ENGINE_EVENT_CODE_TYPE { + /** 0: For internal use only. + */ + MEDIA_ENGINE_RECORDING_ERROR = 0, + /** 1: For internal use only. + */ + MEDIA_ENGINE_PLAYOUT_ERROR = 1, + /** 2: For internal use only. + */ + MEDIA_ENGINE_RECORDING_WARNING = 2, + /** 3: For internal use only. + */ + MEDIA_ENGINE_PLAYOUT_WARNING = 3, + /** 10: For internal use only. + */ + MEDIA_ENGINE_AUDIO_FILE_MIX_FINISH = 10, + /** 12: For internal use only. + */ + MEDIA_ENGINE_AUDIO_FAREND_MUSIC_BEGINS = 12, + /** 13: For internal use only. + */ + MEDIA_ENGINE_AUDIO_FAREND_MUSIC_ENDS = 13, + /** 14: For internal use only. + */ + MEDIA_ENGINE_LOCAL_AUDIO_RECORD_ENABLED = 14, + /** 15: For internal use only. + */ + MEDIA_ENGINE_LOCAL_AUDIO_RECORD_DISABLED = 15, + // media engine role changed + /** 20: For internal use only. + */ + MEDIA_ENGINE_ROLE_BROADCASTER_SOLO = 20, + /** 21: For internal use only. + */ + MEDIA_ENGINE_ROLE_BROADCASTER_INTERACTIVE = 21, + /** 22: For internal use only. + */ + MEDIA_ENGINE_ROLE_AUDIENCE = 22, + /** 23: For internal use only. + */ + MEDIA_ENGINE_ROLE_COMM_PEER = 23, + /** 24: For internal use only. + */ + MEDIA_ENGINE_ROLE_GAME_PEER = 24, + /** 30: For internal use only. + */ + MEDIA_ENGINE_AUDIO_AIRPLAY_CONNECTED = 30, + + // iOS adm sample rate changed + /** 110: For internal use only. + */ + MEDIA_ENGINE_AUDIO_ADM_REQUIRE_RESTART = 110, + /** 111: For internal use only. + */ + MEDIA_ENGINE_AUDIO_ADM_SPECIAL_RESTART = 111, + /** 112: For internal use only. + */ + MEDIA_ENGINE_AUDIO_ADM_USING_COMM_PARAMS = 112, + /** 113: For internal use only. + */ + MEDIA_ENGINE_AUDIO_ADM_USING_NORM_PARAMS = 113, + /** 114: For internal use only. + */ + MEDIA_ENGINE_AUDIO_ADM_ROUTING_UPDATE = 114, + // audio mix event + /** 720: For internal use only. + */ + MEDIA_ENGINE_AUDIO_EVENT_MIXING_STARTED_BY_USER = 720, + /** 721: For internal use only. + */ + MEDIA_ENGINE_AUDIO_EVENT_MIXING_ONE_LOOP_COMPLETED = 721, + /** 722: For internal use only. + */ + MEDIA_ENGINE_AUDIO_EVENT_MIXING_START_NEW_LOOP = 722, + /** 723: For internal use only. + */ + MEDIA_ENGINE_AUDIO_EVENT_MIXING_ALL_LOOPS_COMPLETED = 723, + /** 724: For internal use only. + */ + MEDIA_ENGINE_AUDIO_EVENT_MIXING_STOPPED_BY_USER = 724, + /** 725: For internal use only. + */ + MEDIA_ENGINE_AUDIO_EVENT_MIXING_PAUSED_BY_USER = 725, + /** 726: For internal use only. + */ + MEDIA_ENGINE_AUDIO_EVENT_MIXING_RESUMED_BY_USER = 726, + // Mixing error codes + /** 701: For internal use only. + */ + MEDIA_ENGINE_AUDIO_ERROR_MIXING_OPEN = 701, + /** 702: For internal use only. + */ + MEDIA_ENGINE_AUDIO_ERROR_MIXING_TOO_FREQUENT = 702, + /** 703: The audio mixing file playback is interrupted. For internal use only. + */ + MEDIA_ENGINE_AUDIO_ERROR_MIXING_INTERRUPTED_EOF = 703, + /** 0: For internal use only. + */ + MEDIA_ENGINE_AUDIO_ERROR_MIXING_NO_ERROR = 0, +}; +/// @endcond + +/** The current music file playback state. + * + * Reports in the \ref IRtcEngineEventHandler::onAudioMixingStateChanged "onAudioMixingStateChanged" callback. + */ +enum AUDIO_MIXING_STATE_TYPE { + /** 710: The music file is playing. + * + * This state comes with one of the following associated reasons: + * - #AUDIO_MIXING_REASON_STARTED_BY_USER (720) + * - #AUDIO_MIXING_REASON_ONE_LOOP_COMPLETED (721) + * - #AUDIO_MIXING_REASON_START_NEW_LOOP (722) + * - #AUDIO_MIXING_REASON_RESUMED_BY_USER (726) + */ + AUDIO_MIXING_STATE_PLAYING = 710, + /** 711: The music file pauses playing. + * + * This state comes with #AUDIO_MIXING_REASON_PAUSED_BY_USER (725). + */ + AUDIO_MIXING_STATE_PAUSED = 711, + /** 713: The music file stops playing. + * + * This state comes with one of the following associated reasons: + * - #AUDIO_MIXING_REASON_ALL_LOOPS_COMPLETED (723) + * - #AUDIO_MIXING_REASON_STOPPED_BY_USER (724) + */ + AUDIO_MIXING_STATE_STOPPED = 713, + /** 714: An exception occurs during the playback of the music file. + * + * This state comes with one of the following associated reasons: + * - #AUDIO_MIXING_REASON_CAN_NOT_OPEN (701) + * - #AUDIO_MIXING_REASON_TOO_FREQUENT_CALL (702) + * - #AUDIO_MIXING_REASON_INTERRUPTED_EOF (703) + */ + AUDIO_MIXING_STATE_FAILED = 714, +}; + +/** + * @deprecated Deprecated from v3.4.0. Use #AUDIO_MIXING_REASON_TYPE instead. + * + * The error codes of the local user's audio mixing file. + */ +enum AGORA_DEPRECATED_ATTRIBUTE AUDIO_MIXING_ERROR_TYPE { + /** 701: The SDK cannot open the audio mixing file. + */ + AUDIO_MIXING_ERROR_CAN_NOT_OPEN = 701, + /** 702: The SDK opens the audio mixing file too frequently. + */ + AUDIO_MIXING_ERROR_TOO_FREQUENT_CALL = 702, + /** 703: The audio mixing file playback is interrupted. + */ + AUDIO_MIXING_ERROR_INTERRUPTED_EOF = 703, + /** 0: The SDK can open the audio mixing file. + */ + AUDIO_MIXING_ERROR_OK = 0, +}; + +/** The reason for the change of the music file playback state. + * + * @since v3.4.0 + * + * Reports in the \ref IRtcEngineEventHandler::onAudioMixingStateChanged "onAudioMixingStateChanged" callback. + */ +enum AUDIO_MIXING_REASON_TYPE { + /** 701: The SDK cannot open the music file. Possible causes include the local + * music file does not exist, the SDK does not support the file format, or the + * SDK cannot access the music file URL. + */ + AUDIO_MIXING_REASON_CAN_NOT_OPEN = 701, + /** 702: The SDK opens the music file too frequently. If you need to call + * \ref IRtcEngine::startAudioMixing(const char*,bool,bool,int,int) "startAudioMixing" multiple times, ensure + * that the call interval is longer than 500 ms. + */ + AUDIO_MIXING_REASON_TOO_FREQUENT_CALL = 702, + /** 703: The music file playback is interrupted. + */ + AUDIO_MIXING_REASON_INTERRUPTED_EOF = 703, + /** 720: Successfully calls \ref IRtcEngine::startAudioMixing(const char*,bool,bool,int,int) "startAudioMixing" + * to play a music file. + */ + AUDIO_MIXING_REASON_STARTED_BY_USER = 720, + /** 721: The music file completes a loop playback. + */ + AUDIO_MIXING_REASON_ONE_LOOP_COMPLETED = 721, + /** 722: The music file starts a new loop playback. + */ + AUDIO_MIXING_REASON_START_NEW_LOOP = 722, + /** 723: The music file completes all loop playback. + */ + AUDIO_MIXING_REASON_ALL_LOOPS_COMPLETED = 723, + /** 724: Successfully calls \ref IRtcEngine::stopAudioMixing "stopAudioMixing" + * to stop playing the music file. + */ + AUDIO_MIXING_REASON_STOPPED_BY_USER = 724, + /** 725: Successfully calls \ref IRtcEngine::pauseAudioMixing "pauseAudioMixing" + * to pause playing the music file. + */ + AUDIO_MIXING_REASON_PAUSED_BY_USER = 725, + /** 726: Successfully calls \ref IRtcEngine::resumeAudioMixing "resumeAudioMixing" + * to resume playing the music file. + */ + AUDIO_MIXING_REASON_RESUMED_BY_USER = 726, +}; + +/** Media device states. + */ +enum MEDIA_DEVICE_STATE_TYPE { + /** 0: The device is ready for use. + * + * @since v3.4.5 + */ + MEDIA_DEVICE_STATE_IDLE = 0, + /** 1: The device is in use. + * + * @since v3.4.5 + */ + MEDIA_DEVICE_STATE_ACTIVE = 1, + /** 2: The device is disabled. + */ + MEDIA_DEVICE_STATE_DISABLED = 2, + /** 4: The device is not present. + */ + MEDIA_DEVICE_STATE_NOT_PRESENT = 4, + /** 8: The device is unplugged. + */ + MEDIA_DEVICE_STATE_UNPLUGGED = 8, + /** 16: The device is not recommended. + */ + MEDIA_DEVICE_STATE_UNRECOMMENDED = 16, +}; + +/** Media device types. + */ +enum MEDIA_DEVICE_TYPE { + /** -1: Unknown device type. + */ + UNKNOWN_AUDIO_DEVICE = -1, + /** 0: Audio playback device. + */ + AUDIO_PLAYOUT_DEVICE = 0, + /** 1: Audio capturing device. + */ + AUDIO_RECORDING_DEVICE = 1, + /** 2: Video renderer. + */ + VIDEO_RENDER_DEVICE = 2, + /** 3: Video capturer. + */ + VIDEO_CAPTURE_DEVICE = 3, + /** 4: Application audio playback device. + */ + AUDIO_APPLICATION_PLAYOUT_DEVICE = 4, +}; + +/** Local video state types. + */ +enum LOCAL_VIDEO_STREAM_STATE { + /** 0: Initial state. */ + LOCAL_VIDEO_STREAM_STATE_STOPPED = 0, + /** 1: The local video capturing device starts successfully. + * + * The SDK also reports this state when you share a maximized window by calling \ref IRtcEngine::startScreenCaptureByWindowId "startScreenCaptureByWindowId". + */ + LOCAL_VIDEO_STREAM_STATE_CAPTURING = 1, + /** 2: The first video frame is successfully encoded. */ + LOCAL_VIDEO_STREAM_STATE_ENCODING = 2, + /** 3: The local video fails to start. */ + LOCAL_VIDEO_STREAM_STATE_FAILED = 3 +}; + +/** Local video state error codes. + */ +enum LOCAL_VIDEO_STREAM_ERROR { + /** 0: The local video is normal. */ + LOCAL_VIDEO_STREAM_ERROR_OK = 0, + /** 1: No specified reason for the local video failure. */ + LOCAL_VIDEO_STREAM_ERROR_FAILURE = 1, + /** 2: No permission to use the local video capturing device. */ + LOCAL_VIDEO_STREAM_ERROR_DEVICE_NO_PERMISSION = 2, + /** 3: The local video capturing device is in use. */ + LOCAL_VIDEO_STREAM_ERROR_DEVICE_BUSY = 3, + /** 4: The local video capture fails. Check whether the capturing device is working properly. */ + LOCAL_VIDEO_STREAM_ERROR_CAPTURE_FAILURE = 4, + /** 5: The local video encoding fails. */ + LOCAL_VIDEO_STREAM_ERROR_ENCODE_FAILURE = 5, + /** 6: (iOS only) The application is in the background. + * + * @since v3.3.0 + */ + LOCAL_VIDEO_STREAM_ERROR_CAPTURE_INBACKGROUND = 6, + /** 7: (iOS only) The application is running in Slide Over, Split View, or Picture in Picture mode. + * + * @since v3.3.0 + */ + LOCAL_VIDEO_STREAM_ERROR_CAPTURE_MULTIPLE_FOREGROUND_APPS = 7, + /** + * 8: The SDK cannot find the local video capture device. + * + * @since v3.4.0 + */ + LOCAL_VIDEO_STREAM_ERROR_DEVICE_NOT_FOUND = 8, + /** + * 10: (macOS and Windows only) The SDK cannot find the video device in the video device list. Check whether the ID + * of the video device is valid. + * + * @since v3.5.2 + */ + LOCAL_VIDEO_STREAM_ERROR_DEVICE_INVALID_ID = 10, + /** + * 11: The shared window is minimized when you call + * \ref IRtcEngine::startScreenCaptureByWindowId "startScreenCaptureByWindowId" + * to share a window. + */ + LOCAL_VIDEO_STREAM_ERROR_SCREEN_CAPTURE_WINDOW_MINIMIZED = 11, + /** 12: The error code indicates that a window shared by the window ID has been closed, or a full-screen window + * shared by the window ID has exited full-screen mode. + * After exiting full-screen mode, remote users cannot see the shared window. To prevent remote users from seeing a + * black screen, Agora recommends that you immediately stop screen sharing. + * + * Common scenarios for reporting this error code: + * - When the local user closes the shared window, the SDK reports this error code. + * - The local user shows some slides in full-screen mode first, and then shares the windows of the slides. After + * the user exits full-screen mode, the SDK reports this error code. + * - The local user watches web video or reads web document in full-screen mode first, and then shares the window of + * the web video or document. After the user exits full-screen mode, the SDK reports this error code. + */ + LOCAL_VIDEO_STREAM_ERROR_SCREEN_CAPTURE_WINDOW_CLOSED = 12, + /** + * 13: (Windows only) The window being shared is overlapped by another window, so the overlapped area is blacked out by + * the SDK during window sharing. + * + * @since v3.5.2 + */ + LOCAL_VIDEO_STREAM_ERROR_SCREEN_CAPTURE_WINDOW_OCCLUDED = 13, + /** + * 20: (Windows only) The SDK does not support sharing this type of window. + * + * @since v3.5.2 + */ + LOCAL_VIDEO_STREAM_ERROR_SCREEN_CAPTURE_WINDOW_NOT_SUPPORTED = 20, + +}; + +/** Local audio state types. + */ +enum LOCAL_AUDIO_STREAM_STATE { + /** 0: The local audio is in the initial state. + */ + LOCAL_AUDIO_STREAM_STATE_STOPPED = 0, + /** 1: The capturing device starts successfully. + */ + LOCAL_AUDIO_STREAM_STATE_RECORDING = 1, + /** 2: The first audio frame encodes successfully. + */ + LOCAL_AUDIO_STREAM_STATE_ENCODING = 2, + /** 3: The local audio fails to start. + */ + LOCAL_AUDIO_STREAM_STATE_FAILED = 3 +}; + +/** Local audio state error codes. + */ +enum LOCAL_AUDIO_STREAM_ERROR { + /** 0: The local audio is normal. + */ + LOCAL_AUDIO_STREAM_ERROR_OK = 0, + /** 1: No specified reason for the local audio failure. + */ + LOCAL_AUDIO_STREAM_ERROR_FAILURE = 1, + /** 2: No permission to use the local audio device. + */ + LOCAL_AUDIO_STREAM_ERROR_DEVICE_NO_PERMISSION = 2, + /** 3: The microphone is in use. + */ + LOCAL_AUDIO_STREAM_ERROR_DEVICE_BUSY = 3, + /** 4: The local audio capturing fails. Check whether the capturing device + * is working properly. + */ + LOCAL_AUDIO_STREAM_ERROR_RECORD_FAILURE = 4, + /** 5: The local audio encoding fails. + */ + LOCAL_AUDIO_STREAM_ERROR_ENCODE_FAILURE = 5, + /** 6: The SDK cannot find the local audio recording device. + * + * @since v3.4.0 + */ + LOCAL_AUDIO_STREAM_ERROR_NO_RECORDING_DEVICE = 6, + /** 7: The SDK cannot find the local audio playback device. + * + * @since v3.4.0 + */ + LOCAL_AUDIO_STREAM_ERROR_NO_PLAYOUT_DEVICE = 7, + /** + * 8: The local audio capturing is interrupted by the system call. + */ + LOCAL_AUDIO_STREAM_ERROR_INTERRUPTED = 8, + /** 9: An invalid audio capture device ID. + * + * @since v3.5.1 + */ + LOCAL_AUDIO_STREAM_ERROR_RECORD_INVALID_ID = 9, + /** 10: An invalid audio playback device ID. + * + * @since v3.5.1 + */ + LOCAL_AUDIO_STREAM_ERROR_PLAYOUT_INVALID_ID = 10, +}; + +/** Audio recording quality, which is set in + * \ref IRtcEngine::startAudioRecording(const AudioRecordingConfiguration&) "startAudioRecording". + */ +enum AUDIO_RECORDING_QUALITY_TYPE { + /** 0: Low quality. For example, the size of an AAC file with a sample rate + * of 32,000 Hz and a 10-minute recording is approximately 1.2 MB. + */ + AUDIO_RECORDING_QUALITY_LOW = 0, + /** 1: (Default) Medium quality. For example, the size of an AAC file with + * a sample rate of 32,000 Hz and a 10-minute recording is approximately + * 2 MB. + */ + AUDIO_RECORDING_QUALITY_MEDIUM = 1, + /** 2: High quality. For example, the size of an AAC file with a sample rate + * of 32,000 Hz and a 10-minute recording is approximately 3.75 MB. + */ + AUDIO_RECORDING_QUALITY_HIGH = 2, +}; + +/** Network quality types. */ +enum QUALITY_TYPE { + /** 0: The network quality is unknown. */ + QUALITY_UNKNOWN = 0, + /** 1: The network quality is excellent. */ + QUALITY_EXCELLENT = 1, + /** 2: The network quality is quite good, but the bitrate may be slightly lower than excellent. */ + QUALITY_GOOD = 2, + /** 3: Users can feel the communication slightly impaired. */ + QUALITY_POOR = 3, + /** 4: Users cannot communicate smoothly. */ + QUALITY_BAD = 4, + /** 5: The network is so bad that users can barely communicate. */ + QUALITY_VBAD = 5, + /** 6: The network is down and users cannot communicate at all. */ + QUALITY_DOWN = 6, + /** 7: Users cannot detect the network quality. (Not in use.) */ + QUALITY_UNSUPPORTED = 7, + /** 8: Detecting the network quality. */ + QUALITY_DETECTING = 8, +}; + +/** Video display modes. */ +enum RENDER_MODE_TYPE { + /** +1: Uniformly scale the video until it fills the visible boundaries (cropped). One dimension of the video may have clipped contents. + */ + RENDER_MODE_HIDDEN = 1, + /** +2: Uniformly scale the video until one of its dimension fits the boundary (zoomed to fit). Areas that are not filled due to disparity in the aspect ratio are filled with black. +*/ + RENDER_MODE_FIT = 2, + /** **DEPRECATED** 3: This mode is deprecated. + */ + RENDER_MODE_ADAPTIVE = 3, + /** + 4: The fill mode. In this mode, the SDK stretches or zooms the video to fill the display window. + */ + RENDER_MODE_FILL = 4, +}; + +/** Video mirror modes. */ +enum VIDEO_MIRROR_MODE_TYPE { + /** 0: (Default) The SDK enables the mirror mode. + */ + VIDEO_MIRROR_MODE_AUTO = 0, // determined by SDK + /** 1: Enable mirror mode. */ + VIDEO_MIRROR_MODE_ENABLED = 1, // enabled mirror + /** 2: Disable mirror mode. */ + VIDEO_MIRROR_MODE_DISABLED = 2, // disable mirror +}; + +/** @deprecated Video profiles. */ +enum AGORA_DEPRECATED_ATTRIBUTE VIDEO_PROFILE_TYPE { + /** 0: 160 * 120, frame rate 15 fps, bitrate 65 Kbps. */ + VIDEO_PROFILE_LANDSCAPE_120P = 0, + /** 2: 120 * 120, frame rate 15 fps, bitrate 50 Kbps. */ + VIDEO_PROFILE_LANDSCAPE_120P_3 = 2, + /** 10: 320*180, frame rate 15 fps, bitrate 140 Kbps. */ + VIDEO_PROFILE_LANDSCAPE_180P = 10, + /** 12: 180 * 180, frame rate 15 fps, bitrate 100 Kbps. */ + VIDEO_PROFILE_LANDSCAPE_180P_3 = 12, + /** 13: 240 * 180, frame rate 15 fps, bitrate 120 Kbps. */ + VIDEO_PROFILE_LANDSCAPE_180P_4 = 13, + /** 20: 320 * 240, frame rate 15 fps, bitrate 200 Kbps. */ + VIDEO_PROFILE_LANDSCAPE_240P = 20, + /** 22: 240 * 240, frame rate 15 fps, bitrate 140 Kbps. */ + VIDEO_PROFILE_LANDSCAPE_240P_3 = 22, + /** 23: 424 * 240, frame rate 15 fps, bitrate 220 Kbps. */ + VIDEO_PROFILE_LANDSCAPE_240P_4 = 23, + /** 30: 640 * 360, frame rate 15 fps, bitrate 400 Kbps. */ + VIDEO_PROFILE_LANDSCAPE_360P = 30, + /** 32: 360 * 360, frame rate 15 fps, bitrate 260 Kbps. */ + VIDEO_PROFILE_LANDSCAPE_360P_3 = 32, + /** 33: 640 * 360, frame rate 30 fps, bitrate 600 Kbps. */ + VIDEO_PROFILE_LANDSCAPE_360P_4 = 33, + /** 35: 360 * 360, frame rate 30 fps, bitrate 400 Kbps. */ + VIDEO_PROFILE_LANDSCAPE_360P_6 = 35, + /** 36: 480 * 360, frame rate 15 fps, bitrate 320 Kbps. */ + VIDEO_PROFILE_LANDSCAPE_360P_7 = 36, + /** 37: 480 * 360, frame rate 30 fps, bitrate 490 Kbps. */ + VIDEO_PROFILE_LANDSCAPE_360P_8 = 37, + /** 38: 640 * 360, frame rate 15 fps, bitrate 800 Kbps. + @note `LIVE_BROADCASTING` profile only. + */ + VIDEO_PROFILE_LANDSCAPE_360P_9 = 38, + /** 39: 640 * 360, frame rate 24 fps, bitrate 800 Kbps. + @note `LIVE_BROADCASTING` profile only. + */ + VIDEO_PROFILE_LANDSCAPE_360P_10 = 39, + /** 100: 640 * 360, frame rate 24 fps, bitrate 1000 Kbps. + @note `LIVE_BROADCASTING` profile only. + */ + VIDEO_PROFILE_LANDSCAPE_360P_11 = 100, + /** 40: 640 * 480, frame rate 15 fps, bitrate 500 Kbps. */ + VIDEO_PROFILE_LANDSCAPE_480P = 40, + /** 42: 480 * 480, frame rate 15 fps, bitrate 400 Kbps. */ + VIDEO_PROFILE_LANDSCAPE_480P_3 = 42, + /** 43: 640 * 480, frame rate 30 fps, bitrate 750 Kbps. */ + VIDEO_PROFILE_LANDSCAPE_480P_4 = 43, + /** 45: 480 * 480, frame rate 30 fps, bitrate 600 Kbps. */ + VIDEO_PROFILE_LANDSCAPE_480P_6 = 45, + /** 47: 848 * 480, frame rate 15 fps, bitrate 610 Kbps. */ + VIDEO_PROFILE_LANDSCAPE_480P_8 = 47, + /** 48: 848 * 480, frame rate 30 fps, bitrate 930 Kbps. */ + VIDEO_PROFILE_LANDSCAPE_480P_9 = 48, + /** 49: 640 * 480, frame rate 10 fps, bitrate 400 Kbps. */ + VIDEO_PROFILE_LANDSCAPE_480P_10 = 49, + /** 50: 1280 * 720, frame rate 15 fps, bitrate 1130 Kbps. */ + VIDEO_PROFILE_LANDSCAPE_720P = 50, + /** 52: 1280 * 720, frame rate 30 fps, bitrate 1710 Kbps. */ + VIDEO_PROFILE_LANDSCAPE_720P_3 = 52, + /** 54: 960 * 720, frame rate 15 fps, bitrate 910 Kbps. */ + VIDEO_PROFILE_LANDSCAPE_720P_5 = 54, + /** 55: 960 * 720, frame rate 30 fps, bitrate 1380 Kbps. */ + VIDEO_PROFILE_LANDSCAPE_720P_6 = 55, + /** 60: 1920 * 1080, frame rate 15 fps, bitrate 2080 Kbps. */ + VIDEO_PROFILE_LANDSCAPE_1080P = 60, + /** 62: 1920 * 1080, frame rate 30 fps, bitrate 3150 Kbps. */ + VIDEO_PROFILE_LANDSCAPE_1080P_3 = 62, + /** 64: 1920 * 1080, frame rate 60 fps, bitrate 4780 Kbps. */ + VIDEO_PROFILE_LANDSCAPE_1080P_5 = 64, + /** 66: 2560 * 1440, frame rate 30 fps, bitrate 4850 Kbps. */ + VIDEO_PROFILE_LANDSCAPE_1440P = 66, + /** 67: 2560 * 1440, frame rate 60 fps, bitrate 6500 Kbps. */ + VIDEO_PROFILE_LANDSCAPE_1440P_2 = 67, + /** 70: 3840 * 2160, frame rate 30 fps, bitrate 6500 Kbps. */ + VIDEO_PROFILE_LANDSCAPE_4K = 70, + /** 72: 3840 * 2160, frame rate 60 fps, bitrate 6500 Kbps. */ + VIDEO_PROFILE_LANDSCAPE_4K_3 = 72, + /** 1000: 120 * 160, frame rate 15 fps, bitrate 65 Kbps. */ + VIDEO_PROFILE_PORTRAIT_120P = 1000, + /** 1002: 120 * 120, frame rate 15 fps, bitrate 50 Kbps. */ + VIDEO_PROFILE_PORTRAIT_120P_3 = 1002, + /** 1010: 180 * 320, frame rate 15 fps, bitrate 140 Kbps. */ + VIDEO_PROFILE_PORTRAIT_180P = 1010, + /** 1012: 180 * 180, frame rate 15 fps, bitrate 100 Kbps. */ + VIDEO_PROFILE_PORTRAIT_180P_3 = 1012, + /** 1013: 180 * 240, frame rate 15 fps, bitrate 120 Kbps. */ + VIDEO_PROFILE_PORTRAIT_180P_4 = 1013, + /** 1020: 240 * 320, frame rate 15 fps, bitrate 200 Kbps. */ + VIDEO_PROFILE_PORTRAIT_240P = 1020, + /** 1022: 240 * 240, frame rate 15 fps, bitrate 140 Kbps. */ + VIDEO_PROFILE_PORTRAIT_240P_3 = 1022, + /** 1023: 240 * 424, frame rate 15 fps, bitrate 220 Kbps. */ + VIDEO_PROFILE_PORTRAIT_240P_4 = 1023, + /** 1030: 360 * 640, frame rate 15 fps, bitrate 400 Kbps. */ + VIDEO_PROFILE_PORTRAIT_360P = 1030, + /** 1032: 360 * 360, frame rate 15 fps, bitrate 260 Kbps. */ + VIDEO_PROFILE_PORTRAIT_360P_3 = 1032, + /** 1033: 360 * 640, frame rate 30 fps, bitrate 600 Kbps. */ + VIDEO_PROFILE_PORTRAIT_360P_4 = 1033, + /** 1035: 360 * 360, frame rate 30 fps, bitrate 400 Kbps. */ + VIDEO_PROFILE_PORTRAIT_360P_6 = 1035, + /** 1036: 360 * 480, frame rate 15 fps, bitrate 320 Kbps. */ + VIDEO_PROFILE_PORTRAIT_360P_7 = 1036, + /** 1037: 360 * 480, frame rate 30 fps, bitrate 490 Kbps. */ + VIDEO_PROFILE_PORTRAIT_360P_8 = 1037, + /** 1038: 360 * 640, frame rate 15 fps, bitrate 800 Kbps. + @note `LIVE_BROADCASTING` profile only. + */ + VIDEO_PROFILE_PORTRAIT_360P_9 = 1038, + /** 1039: 360 * 640, frame rate 24 fps, bitrate 800 Kbps. + @note `LIVE_BROADCASTING` profile only. + */ + VIDEO_PROFILE_PORTRAIT_360P_10 = 1039, + /** 1100: 360 * 640, frame rate 24 fps, bitrate 1000 Kbps. + @note `LIVE_BROADCASTING` profile only. + */ + VIDEO_PROFILE_PORTRAIT_360P_11 = 1100, + /** 1040: 480 * 640, frame rate 15 fps, bitrate 500 Kbps. */ + VIDEO_PROFILE_PORTRAIT_480P = 1040, + /** 1042: 480 * 480, frame rate 15 fps, bitrate 400 Kbps. */ + VIDEO_PROFILE_PORTRAIT_480P_3 = 1042, + /** 1043: 480 * 640, frame rate 30 fps, bitrate 750 Kbps. */ + VIDEO_PROFILE_PORTRAIT_480P_4 = 1043, + /** 1045: 480 * 480, frame rate 30 fps, bitrate 600 Kbps. */ + VIDEO_PROFILE_PORTRAIT_480P_6 = 1045, + /** 1047: 480 * 848, frame rate 15 fps, bitrate 610 Kbps. */ + VIDEO_PROFILE_PORTRAIT_480P_8 = 1047, + /** 1048: 480 * 848, frame rate 30 fps, bitrate 930 Kbps. */ + VIDEO_PROFILE_PORTRAIT_480P_9 = 1048, + /** 1049: 480 * 640, frame rate 10 fps, bitrate 400 Kbps. */ + VIDEO_PROFILE_PORTRAIT_480P_10 = 1049, + /** 1050: 720 * 1280, frame rate 15 fps, bitrate 1130 Kbps. */ + VIDEO_PROFILE_PORTRAIT_720P = 1050, + /** 1052: 720 * 1280, frame rate 30 fps, bitrate 1710 Kbps. */ + VIDEO_PROFILE_PORTRAIT_720P_3 = 1052, + /** 1054: 720 * 960, frame rate 15 fps, bitrate 910 Kbps. */ + VIDEO_PROFILE_PORTRAIT_720P_5 = 1054, + /** 1055: 720 * 960, frame rate 30 fps, bitrate 1380 Kbps. */ + VIDEO_PROFILE_PORTRAIT_720P_6 = 1055, + /** 1060: 1080 * 1920, frame rate 15 fps, bitrate 2080 Kbps. */ + VIDEO_PROFILE_PORTRAIT_1080P = 1060, + /** 1062: 1080 * 1920, frame rate 30 fps, bitrate 3150 Kbps. */ + VIDEO_PROFILE_PORTRAIT_1080P_3 = 1062, + /** 1064: 1080 * 1920, frame rate 60 fps, bitrate 4780 Kbps. */ + VIDEO_PROFILE_PORTRAIT_1080P_5 = 1064, + /** 1066: 1440 * 2560, frame rate 30 fps, bitrate 4850 Kbps. */ + VIDEO_PROFILE_PORTRAIT_1440P = 1066, + /** 1067: 1440 * 2560, frame rate 60 fps, bitrate 6500 Kbps. */ + VIDEO_PROFILE_PORTRAIT_1440P_2 = 1067, + /** 1070: 2160 * 3840, frame rate 30 fps, bitrate 6500 Kbps. */ + VIDEO_PROFILE_PORTRAIT_4K = 1070, + /** 1072: 2160 * 3840, frame rate 60 fps, bitrate 6500 Kbps. */ + VIDEO_PROFILE_PORTRAIT_4K_3 = 1072, + /** Default 640 * 360, frame rate 15 fps, bitrate 400 Kbps. */ + VIDEO_PROFILE_DEFAULT = VIDEO_PROFILE_LANDSCAPE_360P, +}; + +/** Audio profiles. + +Sets the sample rate, bitrate, encoding mode, and the number of channels:*/ +enum AUDIO_PROFILE_TYPE // sample rate, bit rate, mono/stereo, speech/music codec +{ + /** + * 0: Default audio profile: + * - For the `LIVE_BROADCASTING` profile: A sample rate of 48 KHz, music encoding, mono, and a bitrate of up to 64 Kbps. + * - For the `COMMUNICATION` profile: + * - Windows: A sample rate of 16 KHz, audio encoding, mono, and a bitrate of up to 16 Kbps. + * - Android/macOS/iOS: A sample rate of 32 KHz, audio encoding, mono, and a bitrate of up to 18 Kbps. + */ + AUDIO_PROFILE_DEFAULT = 0, // use default settings + /** + 1: A sample rate of 32 KHz, audio encoding, mono, and a bitrate of up to 18 Kbps. + */ + AUDIO_PROFILE_SPEECH_STANDARD = 1, // 32Khz, 18Kbps, mono, speech + /** + 2: A sample rate of 48 KHz, music encoding, mono, and a bitrate of up to 64 Kbps. + */ + AUDIO_PROFILE_MUSIC_STANDARD = 2, // 48Khz, 48Kbps, mono, music + /** + 3: A sample rate of 48 KHz, music encoding, stereo, and a bitrate of up to 80 Kbps. + */ + AUDIO_PROFILE_MUSIC_STANDARD_STEREO = 3, // 48Khz, 56Kbps, stereo, music + /** + 4: A sample rate of 48 KHz, music encoding, mono, and a bitrate of up to 96 Kbps. + */ + AUDIO_PROFILE_MUSIC_HIGH_QUALITY = 4, // 48Khz, 128Kbps, mono, music + /** + 5: A sample rate of 48 KHz, music encoding, stereo, and a bitrate of up to 128 Kbps. + */ + AUDIO_PROFILE_MUSIC_HIGH_QUALITY_STEREO = 5, // 48Khz, 192Kbps, stereo, music + /** + 6: A sample rate of 16 KHz, audio encoding, mono, and Acoustic Echo Cancellation (AES) enabled. + */ + AUDIO_PROFILE_IOT = 6, + /// @cond + AUDIO_PROFILE_NUM = 7, + /// @endcond +}; + +/** Audio application scenarios. + */ +enum AUDIO_SCENARIO_TYPE // set a suitable scenario for your app type +{ + /** 0: Default audio scenario. + * + * @note If you run the iOS app on an M1 Mac, due to the hardware differences + * between M1 Macs, iPhones, and iPads, the default audio scenario of the Agora + * iOS SDK is the same as that of the Agora macOS SDK. + */ + AUDIO_SCENARIO_DEFAULT = 0, + /** 1: Entertainment scenario where users need to frequently switch the user role. */ + AUDIO_SCENARIO_CHATROOM_ENTERTAINMENT = 1, + /** 2: Education scenario where users want smoothness and stability. */ + AUDIO_SCENARIO_EDUCATION = 2, + /** 3: High-quality audio chatroom scenario where hosts mainly play music. */ + AUDIO_SCENARIO_GAME_STREAMING = 3, + /** 4: Showroom scenario where a single host wants high-quality audio. */ + AUDIO_SCENARIO_SHOWROOM = 4, + /** 5: Gaming scenario for group chat that only contains the human voice. */ + AUDIO_SCENARIO_CHATROOM_GAMING = 5, + /** 6: IoT (Internet of Things) scenario where users use IoT devices with low power consumption. */ + AUDIO_SCENARIO_IOT = 6, + /** 8: Meeting scenario that mainly contains the human voice. + * + * @since v3.2.0 + */ + AUDIO_SCENARIO_MEETING = 8, + /** The number of elements in the enumeration. + */ + AUDIO_SCENARIO_NUM = 9, +}; + +/** The channel profile. + */ +enum CHANNEL_PROFILE_TYPE { + /** Communication. This profile applies to scenarios such as an audio call or video call, + * where all users can publish and subscribe to streams. + */ + CHANNEL_PROFILE_COMMUNICATION = 0, + /** Live streaming. In this profile, uses have roles, namely, host and audience (default). + * A host both publishes and subscribes to streams, while an audience subscribes to streams only. + * This profile applies to scenarios such as a chat room or interactive video streaming. + */ + CHANNEL_PROFILE_LIVE_BROADCASTING = 1, + /** 2: Gaming. This profile uses a codec with a lower bitrate and consumes less power. Applies to the gaming scenario, where all game players can talk freely. + * + * @note Agora does not recommend using this setting. + */ + CHANNEL_PROFILE_GAME = 2, +}; + +/** The role of a user in interactive live streaming. */ +enum CLIENT_ROLE_TYPE { + /** 1: Host. A host can both send and receive streams. */ + CLIENT_ROLE_BROADCASTER = 1, + /** 2: (Default) Audience. An `audience` member can only receive streams. */ + CLIENT_ROLE_AUDIENCE = 2, +}; + +/** The latency level of an audience member in interactive live streaming. + * + * @note Takes effect only when the user role is `CLIENT_ROLE_AUDIENCE`. + */ +enum AUDIENCE_LATENCY_LEVEL_TYPE { + /** 1: Low latency. */ + AUDIENCE_LATENCY_LEVEL_LOW_LATENCY = 1, + /** 2: (Default) Ultra low latency. */ + AUDIENCE_LATENCY_LEVEL_ULTRA_LOW_LATENCY = 2, +}; + +/** + * The reason why super resolution is not successfully enabled or the message + * that confirms success. + * + * @since v3.5.1 + */ +enum SUPER_RESOLUTION_STATE_REASON { + /** 0: Super resolution is successfully enabled. + */ + SR_STATE_REASON_SUCCESS = 0, + /** 1: The original resolution of the remote video is beyond the range where + * super resolution can be applied. + */ + SR_STATE_REASON_STREAM_OVER_LIMITATION = 1, + /** 2: Super resolution is already being used to boost another remote user's video. + */ + SR_STATE_REASON_USER_COUNT_OVER_LIMITATION = 2, + /** 3: The device does not support using super resolution. + */ + SR_STATE_REASON_DEVICE_NOT_SUPPORTED = 3, +}; + +/** + * The reason why the virtual background is not successfully enabled or the message that confirms success. + * + * @since v3.4.5 + */ +enum VIRTUAL_BACKGROUND_SOURCE_STATE_REASON { + /** + * 0: The virtual background is successfully enabled. + */ + VIRTUAL_BACKGROUND_SOURCE_STATE_REASON_SUCCESS = 0, + /** + * 1: The custom background image does not exist. Please check the value of `source` in VirtualBackgroundSource. + */ + VIRTUAL_BACKGROUND_SOURCE_STATE_REASON_IMAGE_NOT_EXIST = 1, + /** + * 2: The color format of the custom background image is invalid. Please check the value of `color` in VirtualBackgroundSource. + */ + VIRTUAL_BACKGROUND_SOURCE_STATE_REASON_COLOR_FORMAT_NOT_SUPPORTED = 2, + /** + * 3: The device does not support using the virtual background. + */ + VIRTUAL_BACKGROUND_SOURCE_STATE_REASON_DEVICE_NOT_SUPPORTED = 3, +}; +/// @cond +enum CONTENT_INSPECT_RESULT { + CONTENT_INSPECT_NEUTRAL = 1, + CONTENT_INSPECT_SEXY = 2, + CONTENT_INSPECT_PORN = 3, +}; +/// @endcond + +/** Reasons for a user being offline. */ +enum USER_OFFLINE_REASON_TYPE { + /** 0: The user quits the call. */ + USER_OFFLINE_QUIT = 0, + /** 1: The SDK times out and the user drops offline because no data packet is received within a certain period of time. If the user quits the call and the message is not passed to the SDK (due to an unreliable channel), the SDK assumes the user dropped offline. */ + USER_OFFLINE_DROPPED = 1, + /** 2: (`LIVE_BROADCASTING` only.) The client role switched from the host to the audience. */ + USER_OFFLINE_BECOME_AUDIENCE = 2, +}; +/** + States of the RTMP or RTMPS streaming. + */ +enum RTMP_STREAM_PUBLISH_STATE { + /** The RTMP or RTMPS streaming has not started or has ended. This state is also triggered after you remove an RTMP or RTMPS stream from the CDN by calling `removePublishStreamUrl`. + */ + RTMP_STREAM_PUBLISH_STATE_IDLE = 0, + /** The SDK is connecting to Agora's streaming server and the CDN server. This state is triggered after you call the \ref IRtcEngine::addPublishStreamUrl "addPublishStreamUrl" method. + */ + RTMP_STREAM_PUBLISH_STATE_CONNECTING = 1, + /** The RTMP or RTMPS streaming publishes. The SDK successfully publishes the RTMP or RTMPS streaming and returns this state. + */ + RTMP_STREAM_PUBLISH_STATE_RUNNING = 2, + /** The RTMP or RTMPS streaming is recovering. When exceptions occur to the CDN, or the streaming is interrupted, the SDK tries to resume RTMP or RTMPS streaming and returns this state. + + - If the SDK successfully resumes the streaming, #RTMP_STREAM_PUBLISH_STATE_RUNNING (2) returns. + - If the streaming does not resume within 60 seconds or server errors occur, #RTMP_STREAM_PUBLISH_STATE_FAILURE (4) returns. You can also reconnect to the server by calling the \ref IRtcEngine::removePublishStreamUrl "removePublishStreamUrl" and \ref IRtcEngine::addPublishStreamUrl "addPublishStreamUrl" methods. + */ + RTMP_STREAM_PUBLISH_STATE_RECOVERING = 3, + /** The RTMP or RTMPS streaming fails. See the errCode parameter for the detailed error information. You can also call the \ref IRtcEngine::addPublishStreamUrl "addPublishStreamUrl" method to publish the RTMP or RTMPS streaming again. + */ + RTMP_STREAM_PUBLISH_STATE_FAILURE = 4, +}; + +/** + Error codes of the RTMP or RTMPS streaming. + */ +enum RTMP_STREAM_PUBLISH_ERROR { + /** The RTMP or RTMPS streaming publishes successfully. */ + RTMP_STREAM_PUBLISH_ERROR_OK = 0, + /** Invalid argument used. If, for example, you do not call the \ref IRtcEngine::setLiveTranscoding "setLiveTranscoding" method to configure the LiveTranscoding parameters before calling the addPublishStreamUrl method, the SDK returns this error. Check whether you set the parameters in the *setLiveTranscoding* method properly. */ + RTMP_STREAM_PUBLISH_ERROR_INVALID_ARGUMENT = 1, + /** The RTMP or RTMPS streaming is encrypted and cannot be published. */ + RTMP_STREAM_PUBLISH_ERROR_ENCRYPTED_STREAM_NOT_ALLOWED = 2, + /** Timeout for the RTMP or RTMPS streaming. Call the \ref IRtcEngine::addPublishStreamUrl "addPublishStreamUrl" method to publish the streaming again. */ + RTMP_STREAM_PUBLISH_ERROR_CONNECTION_TIMEOUT = 3, + /** An error occurs in Agora's streaming server. Call the `addPublishStreamUrl` method to publish the streaming again. */ + RTMP_STREAM_PUBLISH_ERROR_INTERNAL_SERVER_ERROR = 4, + /** An error occurs in the CDN server. */ + RTMP_STREAM_PUBLISH_ERROR_RTMP_SERVER_ERROR = 5, + /** The RTMP or RTMPS streaming publishes too frequently. */ + RTMP_STREAM_PUBLISH_ERROR_TOO_OFTEN = 6, + /** The host publishes more than 10 URLs. Delete the unnecessary URLs before adding new ones. */ + RTMP_STREAM_PUBLISH_ERROR_REACH_LIMIT = 7, + /** The host manipulates other hosts' URLs. Check your app logic. */ + RTMP_STREAM_PUBLISH_ERROR_NOT_AUTHORIZED = 8, + /** Agora's server fails to find the RTMP or RTMPS streaming. */ + RTMP_STREAM_PUBLISH_ERROR_STREAM_NOT_FOUND = 9, + /** The format of the RTMP or RTMPS streaming URL is not supported. Check whether the URL format is correct. */ + RTMP_STREAM_PUBLISH_ERROR_FORMAT_NOT_SUPPORTED = 10, + /** + * 100: The streaming has been stopped normally. After you call + * \ref IRtcEngine::removePublishStreamUrl "removePublishStreamUrl" + * to stop streaming, the SDK returns this value. + * + * @since v3.4.5 + */ + RTMP_STREAM_UNPUBLISH_ERROR_OK = 100, +}; + +/** Events during the RTMP or RTMPS streaming. */ +enum RTMP_STREAMING_EVENT { + /** An error occurs when you add a background image or a watermark image to the RTMP or RTMPS stream. + */ + RTMP_STREAMING_EVENT_FAILED_LOAD_IMAGE = 1, + /** 2: The streaming URL is already being used for CDN live streaming. If you want to start new streaming, use a new streaming URL. + * + * @since v3.4.5 + */ + RTMP_STREAMING_EVENT_URL_ALREADY_IN_USE = 2, +}; + +/** States of importing an external video stream in the interactive live streaming. */ +enum INJECT_STREAM_STATUS { + /** 0: The external video stream imported successfully. */ + INJECT_STREAM_STATUS_START_SUCCESS = 0, + /** 1: The external video stream already exists. */ + INJECT_STREAM_STATUS_START_ALREADY_EXISTS = 1, + /** 2: The external video stream to be imported is unauthorized. */ + INJECT_STREAM_STATUS_START_UNAUTHORIZED = 2, + /** 3: Import external video stream timeout. */ + INJECT_STREAM_STATUS_START_TIMEDOUT = 3, + /** 4: Import external video stream failed. */ + INJECT_STREAM_STATUS_START_FAILED = 4, + /** 5: The external video stream stopped importing successfully. */ + INJECT_STREAM_STATUS_STOP_SUCCESS = 5, + /** 6: No external video stream is found. */ + INJECT_STREAM_STATUS_STOP_NOT_FOUND = 6, + /** 7: The external video stream to be stopped importing is unauthorized. */ + INJECT_STREAM_STATUS_STOP_UNAUTHORIZED = 7, + /** 8: Stop importing external video stream timeout. */ + INJECT_STREAM_STATUS_STOP_TIMEDOUT = 8, + /** 9: Stop importing external video stream failed. */ + INJECT_STREAM_STATUS_STOP_FAILED = 9, + /** 10: The external video stream is corrupted. */ + INJECT_STREAM_STATUS_BROKEN = 10, +}; +/** Remote video stream types. */ +enum REMOTE_VIDEO_STREAM_TYPE { + /** 0: High-stream video. */ + REMOTE_VIDEO_STREAM_HIGH = 0, + /** 1: Low-stream video. */ + REMOTE_VIDEO_STREAM_LOW = 1, +}; +/** The brightness level of the video image captured by the local camera. + * + * @since v3.3.0 + */ +enum CAPTURE_BRIGHTNESS_LEVEL_TYPE { + /** -1: The SDK does not detect the brightness level of the video image. + * Wait a few seconds to get the brightness level from `CAPTURE_BRIGHTNESS_LEVEL_TYPE` in the next callback. + */ + CAPTURE_BRIGHTNESS_LEVEL_INVALID = -1, + /** 0: The brightness level of the video image is normal. + */ + CAPTURE_BRIGHTNESS_LEVEL_NORMAL = 0, + /** 1: The brightness level of the video image is too bright. + */ + CAPTURE_BRIGHTNESS_LEVEL_BRIGHT = 1, + /** 2: The brightness level of the video image is too dark. + */ + CAPTURE_BRIGHTNESS_LEVEL_DARK = 2, +}; + +/** The use mode of the audio data in the \ref media::IAudioFrameObserver::onRecordAudioFrame "onRecordAudioFrame" or \ref media::IAudioFrameObserver::onPlaybackAudioFrame "onPlaybackAudioFrame" callback. + */ +enum RAW_AUDIO_FRAME_OP_MODE_TYPE { + /** 0: Read-only mode: Users only read the \ref agora::media::IAudioFrameObserver::AudioFrame "AudioFrame" data without modifying anything. For example, when users acquire the data with the Agora SDK, then push the RTMP or RTMPS streams. */ + RAW_AUDIO_FRAME_OP_MODE_READ_ONLY = 0, + /** 1: Write-only mode: Users replace the \ref agora::media::IAudioFrameObserver::AudioFrame "AudioFrame" data with their own data and pass the data to the SDK for encoding. For example, when users acquire the data. */ + RAW_AUDIO_FRAME_OP_MODE_WRITE_ONLY = 1, + /** 2: Read and write mode: Users read the data from \ref agora::media::IAudioFrameObserver::AudioFrame "AudioFrame", modify it, and then play it. For example, when users have their own sound-effect processing module and perform some voice pre-processing, such as a voice change. */ + RAW_AUDIO_FRAME_OP_MODE_READ_WRITE = 2, +}; + +/** Audio-sample rates. */ +enum AUDIO_SAMPLE_RATE_TYPE { + /** 32000: 32 kHz */ + AUDIO_SAMPLE_RATE_32000 = 32000, + /** 44100: 44.1 kHz */ + AUDIO_SAMPLE_RATE_44100 = 44100, + /** 48000: 48 kHz */ + AUDIO_SAMPLE_RATE_48000 = 48000, +}; + +/** Video codec profile types. */ +enum VIDEO_CODEC_PROFILE_TYPE { /** 66: Baseline video codec profile. Generally used in video calls on mobile phones. */ + VIDEO_CODEC_PROFILE_BASELINE = 66, + /** 77: Main video codec profile. Generally used in mainstream electronics such as MP4 players, portable video players, PSP, and iPads. */ + VIDEO_CODEC_PROFILE_MAIN = 77, + /** 100: (Default) High video codec profile. Generally used in high-resolution live streaming or television. */ + VIDEO_CODEC_PROFILE_HIGH = 100, +}; + +/** Video codec types */ +enum VIDEO_CODEC_TYPE { + /** 1: Standard VP8 */ + VIDEO_CODEC_VP8 = 1, + /** 2: Standard H.264 */ + VIDEO_CODEC_H264 = 2, + /** 3: Enhanced VP8 */ + VIDEO_CODEC_EVP = 3, + /** 4: Enhanced H.264 */ + VIDEO_CODEC_E264 = 4, +}; + +/** + * The video codec type of the output video stream. + * + * @since v3.2.0 + */ +enum VIDEO_CODEC_TYPE_FOR_STREAM { + /** + * 1: (Default) H.264 + */ + VIDEO_CODEC_H264_FOR_STREAM = 1, + /** + * 2: H.265 + */ + VIDEO_CODEC_H265_FOR_STREAM = 2, +}; + +/** Audio equalization band frequencies. */ +enum AUDIO_EQUALIZATION_BAND_FREQUENCY { + /** 0: 31 Hz */ + AUDIO_EQUALIZATION_BAND_31 = 0, + /** 1: 62 Hz */ + AUDIO_EQUALIZATION_BAND_62 = 1, + /** 2: 125 Hz */ + AUDIO_EQUALIZATION_BAND_125 = 2, + /** 3: 250 Hz */ + AUDIO_EQUALIZATION_BAND_250 = 3, + /** 4: 500 Hz */ + AUDIO_EQUALIZATION_BAND_500 = 4, + /** 5: 1 kHz */ + AUDIO_EQUALIZATION_BAND_1K = 5, + /** 6: 2 kHz */ + AUDIO_EQUALIZATION_BAND_2K = 6, + /** 7: 4 kHz */ + AUDIO_EQUALIZATION_BAND_4K = 7, + /** 8: 8 kHz */ + AUDIO_EQUALIZATION_BAND_8K = 8, + /** 9: 16 kHz */ + AUDIO_EQUALIZATION_BAND_16K = 9, +}; + +/** Audio reverberation types. */ +enum AUDIO_REVERB_TYPE { + /** 0: The level of the dry signal (db). The value is between -20 and 10. */ + AUDIO_REVERB_DRY_LEVEL = 0, // (dB, [-20,10]), the level of the dry signal + /** 1: The level of the early reflection signal (wet signal) (dB). The value is between -20 and 10. */ + AUDIO_REVERB_WET_LEVEL = 1, // (dB, [-20,10]), the level of the early reflection signal (wet signal) + /** 2: The room size of the reflection. The value is between 0 and 100. */ + AUDIO_REVERB_ROOM_SIZE = 2, // ([0,100]), the room size of the reflection + /** 3: The length of the initial delay of the wet signal (ms). The value is between 0 and 200. */ + AUDIO_REVERB_WET_DELAY = 3, // (ms, [0,200]), the length of the initial delay of the wet signal in ms + /** 4: The reverberation strength. The value is between 0 and 100. */ + AUDIO_REVERB_STRENGTH = 4, // ([0,100]), the strength of the reverberation +}; + +/** + * @deprecated Deprecated from v3.2.0. + * + * Local voice changer options. + * + * Gender-based beatification effect works best only when assigned a proper gender: + * + * - For male: #GENERAL_BEAUTY_VOICE_MALE_MAGNETIC + * - For female: #GENERAL_BEAUTY_VOICE_FEMALE_FRESH or #GENERAL_BEAUTY_VOICE_FEMALE_VITALITY + * + * Failure to do so can lead to voice distortion. + */ +enum AGORA_DEPRECATED_ATTRIBUTE VOICE_CHANGER_PRESET { + /** + * The original voice (no local voice change). + */ + VOICE_CHANGER_OFF = 0x00000000, // Turn off the voice changer + /** + * The voice of an old man. + */ + VOICE_CHANGER_OLDMAN = 0x00000001, + /** + * The voice of a little boy. + */ + VOICE_CHANGER_BABYBOY = 0x00000002, + /** + * The voice of a little girl. + */ + VOICE_CHANGER_BABYGIRL = 0x00000003, + /** + * The voice of Zhu Bajie, a character in Journey to the West who has a voice like that of a growling bear. + */ + VOICE_CHANGER_ZHUBAJIE = 0x00000004, + /** + * The ethereal voice. + */ + VOICE_CHANGER_ETHEREAL = 0x00000005, + /** + * The voice of Hulk. + */ + VOICE_CHANGER_HULK = 0x00000006, + /** + * A more vigorous voice. + */ + VOICE_BEAUTY_VIGOROUS = 0x00100001, // 7, + /** + * A deeper voice. + */ + VOICE_BEAUTY_DEEP = 0x00100002, + /** + * A mellower voice. + */ + VOICE_BEAUTY_MELLOW = 0x00100003, + /** + * Falsetto. + */ + VOICE_BEAUTY_FALSETTO = 0x00100004, + /** + * A fuller voice. + */ + VOICE_BEAUTY_FULL = 0x00100005, + /** + * A clearer voice. + */ + VOICE_BEAUTY_CLEAR = 0x00100006, + /** + * A more resounding voice. + */ + VOICE_BEAUTY_RESOUNDING = 0x00100007, + /** + * A more ringing voice. + */ + VOICE_BEAUTY_RINGING = 0x00100008, + /** + * A more spatially resonant voice. + */ + VOICE_BEAUTY_SPACIAL = 0x00100009, + /** + * (For male only) A more magnetic voice. Do not use it when the speaker is a female; otherwise, voice distortion occurs. + */ + GENERAL_BEAUTY_VOICE_MALE_MAGNETIC = 0x00200001, + /** + * (For female only) A fresher voice. Do not use it when the speaker is a male; otherwise, voice distortion occurs. + */ + GENERAL_BEAUTY_VOICE_FEMALE_FRESH = 0x00200002, + /** + * (For female only) A more vital voice. Do not use it when the speaker is a male; otherwise, voice distortion occurs. + */ + GENERAL_BEAUTY_VOICE_FEMALE_VITALITY = 0x00200003 + +}; + +/** @deprecated Deprecated from v3.2.0. + * + * Local voice reverberation presets. + */ +enum AGORA_DEPRECATED_ATTRIBUTE AUDIO_REVERB_PRESET { + /** + * Turn off local voice reverberation, that is, to use the original voice. + */ + AUDIO_REVERB_OFF = 0x00000000, // Turn off audio reverb + /** + * + * The reverberation style typical of a KTV venue (enhanced). + */ + AUDIO_REVERB_FX_KTV = 0x00100001, + /** + * + * The reverberation style typical of a concert hall (enhanced). + */ + AUDIO_REVERB_FX_VOCAL_CONCERT = 0x00100002, + /** + * + * The reverberation style typical of an uncle's voice. + */ + AUDIO_REVERB_FX_UNCLE = 0x00100003, + /** + * + * The reverberation style typical of a little sister's voice. + */ + AUDIO_REVERB_FX_SISTER = 0x00100004, + /** + * + * The reverberation style typical of a recording studio (enhanced). + */ + AUDIO_REVERB_FX_STUDIO = 0x00100005, + /** + * + * The reverberation style typical of popular music (enhanced). + */ + AUDIO_REVERB_FX_POPULAR = 0x00100006, + /** + * + * The reverberation style typical of R&B music (enhanced). + */ + AUDIO_REVERB_FX_RNB = 0x00100007, + /** + * + * The reverberation style typical of the vintage phonograph. + */ + AUDIO_REVERB_FX_PHONOGRAPH = 0x00100008, + /** + * + * The reverberation style typical of popular music. + */ + AUDIO_REVERB_POPULAR = 0x00000001, + /** + * + * The reverberation style typical of R&B music. + */ + AUDIO_REVERB_RNB = 0x00000002, + /** + * + * The reverberation style typical of rock music. + */ + AUDIO_REVERB_ROCK = 0x00000003, + /** + * + * The reverberation style typical of hip-hop music. + */ + AUDIO_REVERB_HIPHOP = 0x00000004, + /** + * + * The reverberation style typical of a concert hall. + */ + AUDIO_REVERB_VOCAL_CONCERT = 0x00000005, + /** + * + * The reverberation style typical of a KTV venue. + */ + AUDIO_REVERB_KTV = 0x00000006, + /** + * + * The reverberation style typical of a recording studio. + */ + AUDIO_REVERB_STUDIO = 0x00000007, + /** + * + * The reverberation of the virtual stereo. The virtual stereo is an effect that renders the monophonic + * audio as the stereo audio, so that all users in the channel can hear the stereo voice effect. + * To achieve better virtual stereo reverberation, Agora recommends setting `profile` in `setAudioProfile` + * as `AUDIO_PROFILE_MUSIC_HIGH_QUALITY_STEREO(5)`. + */ + AUDIO_VIRTUAL_STEREO = 0x00200001, + /** + * + * A pitch correction effect that corrects the user's pitch based on the pitch of the natural C major scale. + */ + AUDIO_ELECTRONIC_VOICE = 0x00300001, + /** + * + * A 3D voice effect that makes the voice appear to be moving around the user. + */ + AUDIO_THREEDIM_VOICE = 0x00400001 +}; +/** The options for SDK preset voice beautifier effects. + */ +enum VOICE_BEAUTIFIER_PRESET { + /** Turn off voice beautifier effects and use the original voice. + */ + VOICE_BEAUTIFIER_OFF = 0x00000000, + /** A more magnetic voice. + * + * @note Agora recommends using this enumerator to process a male-sounding voice; otherwise, you may experience vocal distortion. + */ + CHAT_BEAUTIFIER_MAGNETIC = 0x01010100, + /** A fresher voice. + * + * @note Agora recommends using this enumerator to process a female-sounding voice; otherwise, you may experience vocal distortion. + */ + CHAT_BEAUTIFIER_FRESH = 0x01010200, + /** A more vital voice. + * + * @note Agora recommends using this enumerator to process a female-sounding voice; otherwise, you may experience vocal distortion. + */ + CHAT_BEAUTIFIER_VITALITY = 0x01010300, + /** + * @since v3.3.0 + * + * Singing beautifier effect. + * - If you call \ref IRtcEngine::setVoiceBeautifierPreset "setVoiceBeautifierPreset" (SINGING_BEAUTIFIER), you can beautify a male-sounding voice and add a reverberation + * effect that sounds like singing in a small room. Agora recommends not using \ref IRtcEngine::setVoiceBeautifierPreset "setVoiceBeautifierPreset" (SINGING_BEAUTIFIER) + * to process a female-sounding voice; otherwise, you may experience vocal distortion. + * - If you call \ref IRtcEngine::setVoiceBeautifierParameters "setVoiceBeautifierParameters"(SINGING_BEAUTIFIER, param1, param2), you can beautify a male- or + * female-sounding voice and add a reverberation effect. + */ + SINGING_BEAUTIFIER = 0x01020100, + /** A more vigorous voice. + */ + TIMBRE_TRANSFORMATION_VIGOROUS = 0x01030100, + /** A deeper voice. + */ + TIMBRE_TRANSFORMATION_DEEP = 0x01030200, + /** A mellower voice. + */ + TIMBRE_TRANSFORMATION_MELLOW = 0x01030300, + /** A falsetto voice. + */ + TIMBRE_TRANSFORMATION_FALSETTO = 0x01030400, + /** A fuller voice. + */ + TIMBRE_TRANSFORMATION_FULL = 0x01030500, + /** A clearer voice. + */ + TIMBRE_TRANSFORMATION_CLEAR = 0x01030600, + /** A more resounding voice. + */ + TIMBRE_TRANSFORMATION_RESOUNDING = 0x01030700, + /** A more ringing voice. + */ + TIMBRE_TRANSFORMATION_RINGING = 0x01030800 +}; +/** The options for SDK preset audio effects. + */ +enum AUDIO_EFFECT_PRESET { + /** Turn off audio effects and use the original voice. + */ + AUDIO_EFFECT_OFF = 0x00000000, + /** An audio effect typical of a KTV venue. + * + * @note To achieve better audio effect quality, Agora recommends calling \ref IRtcEngine::setAudioProfile "setAudioProfile" + * and setting the `profile` parameter to `AUDIO_PROFILE_MUSIC_HIGH_QUALITY(4)` or `AUDIO_PROFILE_MUSIC_HIGH_QUALITY_STEREO(5)` + * before setting this enumerator. + */ + ROOM_ACOUSTICS_KTV = 0x02010100, + /** An audio effect typical of a concert hall. + * + * @note To achieve better audio effect quality, Agora recommends calling \ref IRtcEngine::setAudioProfile "setAudioProfile" + * and setting the `profile` parameter to `AUDIO_PROFILE_MUSIC_HIGH_QUALITY(4)` or `AUDIO_PROFILE_MUSIC_HIGH_QUALITY_STEREO(5)` + * before setting this enumerator. + */ + ROOM_ACOUSTICS_VOCAL_CONCERT = 0x02010200, + /** An audio effect typical of a recording studio. + * + * @note To achieve better audio effect quality, Agora recommends calling \ref IRtcEngine::setAudioProfile "setAudioProfile" + * and setting the `profile` parameter to `AUDIO_PROFILE_MUSIC_HIGH_QUALITY(4)` or `AUDIO_PROFILE_MUSIC_HIGH_QUALITY_STEREO(5)` + * before setting this enumerator. + */ + ROOM_ACOUSTICS_STUDIO = 0x02010300, + /** An audio effect typical of a vintage phonograph. + * + * @note To achieve better audio effect quality, Agora recommends calling \ref IRtcEngine::setAudioProfile "setAudioProfile" + * and setting the `profile` parameter to `AUDIO_PROFILE_MUSIC_HIGH_QUALITY(4)` or `AUDIO_PROFILE_MUSIC_HIGH_QUALITY_STEREO(5)` + * before setting this enumerator. + */ + ROOM_ACOUSTICS_PHONOGRAPH = 0x02010400, + /** A virtual stereo effect that renders monophonic audio as stereo audio. + * + * @note Call \ref IRtcEngine::setAudioProfile "setAudioProfile" and set the `profile` parameter to + * `AUDIO_PROFILE_MUSIC_STANDARD_STEREO(3)` or `AUDIO_PROFILE_MUSIC_HIGH_QUALITY_STEREO(5)` before setting this + * enumerator; otherwise, the enumerator setting does not take effect. + */ + ROOM_ACOUSTICS_VIRTUAL_STEREO = 0x02010500, + /** A more spatial audio effect. + * + * @note To achieve better audio effect quality, Agora recommends calling \ref IRtcEngine::setAudioProfile "setAudioProfile" + * and setting the `profile` parameter to `AUDIO_PROFILE_MUSIC_HIGH_QUALITY(4)` or `AUDIO_PROFILE_MUSIC_HIGH_QUALITY_STEREO(5)` + * before setting this enumerator. + */ + ROOM_ACOUSTICS_SPACIAL = 0x02010600, + /** A more ethereal audio effect. + * + * @note To achieve better audio effect quality, Agora recommends calling \ref IRtcEngine::setAudioProfile "setAudioProfile" + * and setting the `profile` parameter to `AUDIO_PROFILE_MUSIC_HIGH_QUALITY(4)` or `AUDIO_PROFILE_MUSIC_HIGH_QUALITY_STEREO(5)` + * before setting this enumerator. + */ + ROOM_ACOUSTICS_ETHEREAL = 0x02010700, + /** A 3D voice effect that makes the voice appear to be moving around the user. The default cycle period of the 3D + * voice effect is 10 seconds. To change the cycle period, call \ref IRtcEngine::setAudioEffectParameters "setAudioEffectParameters" + * after this method. + * + * @note + * - Call \ref IRtcEngine::setAudioProfile "setAudioProfile" and set the `profile` parameter to `AUDIO_PROFILE_MUSIC_STANDARD_STEREO(3)` + * or `AUDIO_PROFILE_MUSIC_HIGH_QUALITY_STEREO(5)` before setting this enumerator; otherwise, the enumerator setting does not take effect. + * - If the 3D voice effect is enabled, users need to use stereo audio playback devices to hear the anticipated voice effect. + */ + ROOM_ACOUSTICS_3D_VOICE = 0x02010800, + /** The voice of a middle-aged man. + * + * @note + * - Agora recommends using this enumerator to process a male-sounding voice; otherwise, you may not hear the anticipated voice effect. + * - To achieve better audio effect quality, Agora recommends calling \ref IRtcEngine::setAudioProfile "setAudioProfile" and + * setting the `profile` parameter to `AUDIO_PROFILE_MUSIC_HIGH_QUALITY(4)` or `AUDIO_PROFILE_MUSIC_HIGH_QUALITY_STEREO(5)` before + * setting this enumerator. + */ + VOICE_CHANGER_EFFECT_UNCLE = 0x02020100, + /** The voice of an old man. + * + * @note + * - Agora recommends using this enumerator to process a male-sounding voice; otherwise, you may not hear the anticipated voice effect. + * - To achieve better audio effect quality, Agora recommends calling \ref IRtcEngine::setAudioProfile "setAudioProfile" and setting + * the `profile` parameter to `AUDIO_PROFILE_MUSIC_HIGH_QUALITY(4)` or `AUDIO_PROFILE_MUSIC_HIGH_QUALITY_STEREO(5)` before setting + * this enumerator. + */ + VOICE_CHANGER_EFFECT_OLDMAN = 0x02020200, + /** The voice of a boy. + * + * @note + * - Agora recommends using this enumerator to process a male-sounding voice; otherwise, you may not hear the anticipated voice effect. + * - To achieve better audio effect quality, Agora recommends calling \ref IRtcEngine::setAudioProfile "setAudioProfile" and setting + * the `profile` parameter to `AUDIO_PROFILE_MUSIC_HIGH_QUALITY(4)` or `AUDIO_PROFILE_MUSIC_HIGH_QUALITY_STEREO(5)` before + * setting this enumerator. + */ + VOICE_CHANGER_EFFECT_BOY = 0x02020300, + /** The voice of a young woman. + * + * @note + * - Agora recommends using this enumerator to process a female-sounding voice; otherwise, you may not hear the anticipated voice effect. + * - To achieve better audio effect quality, Agora recommends calling \ref IRtcEngine::setAudioProfile "setAudioProfile" and setting + * the `profile` parameter to `AUDIO_PROFILE_MUSIC_HIGH_QUALITY(4)` or `AUDIO_PROFILE_MUSIC_HIGH_QUALITY_STEREO(5)` before + * setting this enumerator. + */ + VOICE_CHANGER_EFFECT_SISTER = 0x02020400, + /** The voice of a girl. + * + * @note + * - Agora recommends using this enumerator to process a female-sounding voice; otherwise, you may not hear the anticipated voice effect. + * - To achieve better audio effect quality, Agora recommends calling \ref IRtcEngine::setAudioProfile "setAudioProfile" and setting + * the `profile` parameter to `AUDIO_PROFILE_MUSIC_HIGH_QUALITY(4)` or `AUDIO_PROFILE_MUSIC_HIGH_QUALITY_STEREO(5)` before + * setting this enumerator. + */ + VOICE_CHANGER_EFFECT_GIRL = 0x02020500, + /** The voice of Pig King, a character in Journey to the West who has a voice like a growling bear. + * + * @note To achieve better audio effect quality, Agora recommends calling \ref IRtcEngine::setAudioProfile "setAudioProfile" and + * setting the `profile` parameter to `AUDIO_PROFILE_MUSIC_HIGH_QUALITY(4)` or `AUDIO_PROFILE_MUSIC_HIGH_QUALITY_STEREO(5)` before + * setting this enumerator. + */ + VOICE_CHANGER_EFFECT_PIGKING = 0x02020600, + /** The voice of Hulk. + * + * @note To achieve better audio effect quality, Agora recommends calling \ref IRtcEngine::setAudioProfile "setAudioProfile" and + * setting the `profile` parameter to `AUDIO_PROFILE_MUSIC_HIGH_QUALITY(4)` or `AUDIO_PROFILE_MUSIC_HIGH_QUALITY_STEREO(5)` before + * setting this enumerator. + */ + VOICE_CHANGER_EFFECT_HULK = 0x02020700, + /** An audio effect typical of R&B music. + * + * @note To achieve better audio effect quality, Agora recommends calling \ref IRtcEngine::setAudioProfile "setAudioProfile" and + * setting the `profile` parameter to `AUDIO_PROFILE_MUSIC_HIGH_QUALITY(4)` or `AUDIO_PROFILE_MUSIC_HIGH_QUALITY_STEREO(5)` before + * setting this enumerator. + */ + STYLE_TRANSFORMATION_RNB = 0x02030100, + /** An audio effect typical of popular music. + * + * @note To achieve better audio effect quality, Agora recommends calling \ref IRtcEngine::setAudioProfile "setAudioProfile" and + * setting the `profile` parameter to `AUDIO_PROFILE_MUSIC_HIGH_QUALITY(4)` or `AUDIO_PROFILE_MUSIC_HIGH_QUALITY_STEREO(5)` before + * setting this enumerator. + */ + STYLE_TRANSFORMATION_POPULAR = 0x02030200, + /** A pitch correction effect that corrects the user's pitch based on the pitch of the natural C major scale. + * To change the basic mode and tonic pitch, call \ref IRtcEngine::setAudioEffectParameters "setAudioEffectParameters" after this method. + * + * @note To achieve better audio effect quality, Agora recommends calling \ref IRtcEngine::setAudioProfile "setAudioProfile" and + * setting the `profile` parameter to `AUDIO_PROFILE_MUSIC_HIGH_QUALITY(4)` or `AUDIO_PROFILE_MUSIC_HIGH_QUALITY_STEREO(5)` before + * setting this enumerator. + */ + PITCH_CORRECTION = 0x02040100 +}; +/** The options for SDK preset voice conversion effects. + * + * @since v3.3.1 + */ +enum VOICE_CONVERSION_PRESET { + /** Turn off voice conversion effects and use the original voice. + */ + VOICE_CONVERSION_OFF = 0x00000000, + /** A gender-neutral voice. To avoid audio distortion, ensure that you use + * this enumerator to process a female-sounding voice. + */ + VOICE_CHANGER_NEUTRAL = 0x03010100, + /** A sweet voice. To avoid audio distortion, ensure that you use this + * enumerator to process a female-sounding voice. + */ + VOICE_CHANGER_SWEET = 0x03010200, + /** A steady voice. To avoid audio distortion, ensure that you use this + * enumerator to process a male-sounding voice. + */ + VOICE_CHANGER_SOLID = 0x03010300, + /** A deep voice. To avoid audio distortion, ensure that you use this + * enumerator to process a male-sounding voice. + */ + VOICE_CHANGER_BASS = 0x03010400 +}; +/** Audio codec profile types. The default value is LC_ACC. */ +enum AUDIO_CODEC_PROFILE_TYPE { + /** 0: LC-AAC, which is the low-complexity audio codec type. */ + AUDIO_CODEC_PROFILE_LC_AAC = 0, + /** 1: HE-AAC, which is the high-efficiency audio codec type. */ + AUDIO_CODEC_PROFILE_HE_AAC = 1, +}; + +/** Remote audio states. + */ +enum REMOTE_AUDIO_STATE { + /** 0: The remote audio is in the default state, probably due to + * #REMOTE_AUDIO_REASON_LOCAL_MUTED (3), + * #REMOTE_AUDIO_REASON_REMOTE_MUTED (5), or + * #REMOTE_AUDIO_REASON_REMOTE_OFFLINE (7). + */ + REMOTE_AUDIO_STATE_STOPPED = 0, // Default state, audio is started or remote user disabled/muted audio stream + /** 1: The first remote audio packet is received. + */ + REMOTE_AUDIO_STATE_STARTING = 1, // The first audio frame packet has been received + /** 2: The remote audio stream is decoded and plays normally, probably + * due to #REMOTE_AUDIO_REASON_NETWORK_RECOVERY (2), + * #REMOTE_AUDIO_REASON_LOCAL_UNMUTED (4), or + * #REMOTE_AUDIO_REASON_REMOTE_UNMUTED (6). + */ + REMOTE_AUDIO_STATE_DECODING = 2, // The first remote audio frame has been decoded or fronzen state ends + /** 3: The remote audio is frozen, probably due to + * #REMOTE_AUDIO_REASON_NETWORK_CONGESTION (1). + */ + REMOTE_AUDIO_STATE_FROZEN = 3, // Remote audio is frozen, probably due to network issue + /** 4: The remote audio fails to start, probably due to + * #REMOTE_AUDIO_REASON_INTERNAL (0). + */ + REMOTE_AUDIO_STATE_FAILED = 4, // Remote audio play failed +}; + +/** Remote audio state reasons. + */ +enum REMOTE_AUDIO_STATE_REASON { + /** 0: The SDK reports this reason when the audio state changes. + */ + REMOTE_AUDIO_REASON_INTERNAL = 0, + /** 1: Network congestion. + */ + REMOTE_AUDIO_REASON_NETWORK_CONGESTION = 1, + /** 2: Network recovery. + */ + REMOTE_AUDIO_REASON_NETWORK_RECOVERY = 2, + /** 3: The local user stops receiving the remote audio stream or + * disables the audio module. + */ + REMOTE_AUDIO_REASON_LOCAL_MUTED = 3, + /** 4: The local user resumes receiving the remote audio stream or + * enables the audio module. + */ + REMOTE_AUDIO_REASON_LOCAL_UNMUTED = 4, + /** 5: The remote user stops sending the audio stream or disables the + * audio module. + */ + REMOTE_AUDIO_REASON_REMOTE_MUTED = 5, + /** 6: The remote user resumes sending the audio stream or enables the + * audio module. + */ + REMOTE_AUDIO_REASON_REMOTE_UNMUTED = 6, + /** 7: The remote user leaves the channel. + */ + REMOTE_AUDIO_REASON_REMOTE_OFFLINE = 7, +}; + +/** Remote video states. */ +// enum REMOTE_VIDEO_STATE +// { +// // REMOTE_VIDEO_STATE_STOPPED is not used at this version. Ignore this value. +// // REMOTE_VIDEO_STATE_STOPPED = 0, // Default state, video is started or remote user disabled/muted video stream +// /** 1: The remote video is playing. */ +// REMOTE_VIDEO_STATE_RUNNING = 1, // Running state, remote video can be displayed normally +// /** 2: The remote video is frozen. */ +// REMOTE_VIDEO_STATE_FROZEN = 2, // Remote video is frozen, probably due to network issue. +// }; + +/** The state of the remote video. */ +enum REMOTE_VIDEO_STATE { + /** 0: The remote video is in the default state, probably due to #REMOTE_VIDEO_STATE_REASON_LOCAL_MUTED (3), #REMOTE_VIDEO_STATE_REASON_REMOTE_MUTED (5), or #REMOTE_VIDEO_STATE_REASON_REMOTE_OFFLINE (7). + */ + REMOTE_VIDEO_STATE_STOPPED = 0, + + /** 1: The first remote video packet is received. + */ + REMOTE_VIDEO_STATE_STARTING = 1, + + /** 2: The remote video stream is decoded and plays normally, probably due to #REMOTE_VIDEO_STATE_REASON_NETWORK_RECOVERY (2), #REMOTE_VIDEO_STATE_REASON_LOCAL_UNMUTED (4), #REMOTE_VIDEO_STATE_REASON_REMOTE_UNMUTED (6), or #REMOTE_VIDEO_STATE_REASON_AUDIO_FALLBACK_RECOVERY (9). + */ + REMOTE_VIDEO_STATE_DECODING = 2, + + /** 3: The remote video is frozen, probably due to #REMOTE_VIDEO_STATE_REASON_NETWORK_CONGESTION (1) or #REMOTE_VIDEO_STATE_REASON_AUDIO_FALLBACK (8). + */ + REMOTE_VIDEO_STATE_FROZEN = 3, + + /** 4: The remote video fails to start, probably due to #REMOTE_VIDEO_STATE_REASON_INTERNAL (0). + */ + REMOTE_VIDEO_STATE_FAILED = 4 +}; +/** The publishing state. + */ +enum STREAM_PUBLISH_STATE { + /** 0: The initial publishing state after joining the channel. + */ + PUB_STATE_IDLE = 0, + /** 1: Fails to publish the local stream. Possible reasons: + * - The local user calls \ref IRtcEngine::muteLocalAudioStream "muteLocalAudioStream(true)" or \ref IRtcEngine::muteLocalVideoStream "muteLocalVideoStream(true)" to stop sending local streams. + * - The local user calls \ref IRtcEngine::disableAudio "disableAudio" or \ref IRtcEngine::disableVideo "disableVideo" to disable the entire audio or video module. + * - The local user calls \ref IRtcEngine::enableLocalAudio "enableLocalAudio(false)" or \ref IRtcEngine::enableLocalVideo "enableLocalVideo(false)" to disable the local audio sampling or video capturing. + * - The role of the local user is `AUDIENCE`. + */ + PUB_STATE_NO_PUBLISHED = 1, + /** 2: Publishing. + */ + PUB_STATE_PUBLISHING = 2, + /** 3: Publishes successfully. + */ + PUB_STATE_PUBLISHED = 3 +}; +/** The subscribing state. + */ +enum STREAM_SUBSCRIBE_STATE { + /** 0: The initial subscribing state after joining the channel. + */ + SUB_STATE_IDLE = 0, + /** 1: Fails to subscribe to the remote stream. Possible reasons: + * - The remote user: + * - Calls \ref IRtcEngine::muteLocalAudioStream "muteLocalAudioStream(true)" or \ref IRtcEngine::muteLocalVideoStream "muteLocalVideoStream(true)" to stop sending local streams. + * - Calls \ref IRtcEngine::disableAudio "disableAudio" or \ref IRtcEngine::disableVideo "disableVideo" to disable the entire audio or video modules. + * - Calls \ref IRtcEngine::enableLocalAudio "enableLocalAudio(false)" or \ref IRtcEngine::enableLocalVideo "enableLocalVideo(false)" to disable the local audio sampling or video capturing. + * - The role of the remote user is `AUDIENCE`. + * - The local user calls the following methods to stop receiving remote streams: + * - Calls \ref IRtcEngine::muteRemoteAudioStream "muteRemoteAudioStream(true)", \ref IRtcEngine::muteAllRemoteAudioStreams "muteAllRemoteAudioStreams(true)", or \ref IRtcEngine::setDefaultMuteAllRemoteAudioStreams "setDefaultMuteAllRemoteAudioStreams(true)" to stop receiving remote audio streams. + * - Calls \ref IRtcEngine::muteRemoteVideoStream "muteRemoteVideoStream(true)", \ref IRtcEngine::muteAllRemoteVideoStreams "muteAllRemoteVideoStreams(true)", or \ref IRtcEngine::setDefaultMuteAllRemoteVideoStreams "setDefaultMuteAllRemoteVideoStreams(true)" to stop receiving remote video streams. + */ + SUB_STATE_NO_SUBSCRIBED = 1, + /** 2: Subscribing. + */ + SUB_STATE_SUBSCRIBING = 2, + /** 3: Subscribes to and receives the remote stream successfully. + */ + SUB_STATE_SUBSCRIBED = 3 +}; + +/** The remote video frozen type. */ +enum XLA_REMOTE_VIDEO_FROZEN_TYPE { + /** 0: 500ms video frozen type. + */ + XLA_REMOTE_VIDEO_FROZEN_500MS = 0, + /** 1: 200ms video frozen type. + */ + XLA_REMOTE_VIDEO_FROZEN_200MS = 1, + /** 2: 600ms video frozen type. + */ + XLA_REMOTE_VIDEO_FROZEN_600MS = 2, + /** 3: max video frozen type. + */ + XLA_REMOTE_VIDEO_FROZEN_TYPE_MAX = 3, +}; + +/** The remote audio frozen type. */ +enum XLA_REMOTE_AUDIO_FROZEN_TYPE { + /** 0: 80ms audio frozen. + */ + XLA_REMOTE_AUDIO_FROZEN_80MS = 0, + /** 1: 200ms audio frozen. + */ + XLA_REMOTE_AUDIO_FROZEN_200MS = 1, + /** 2: max audio frozen type. + */ + XLA_REMOTE_AUDIO_FROZEN_TYPE_MAX = 2, +}; + +/** The reason for the remote video state change. */ +enum REMOTE_VIDEO_STATE_REASON { + /** 0: The SDK reports this reason when the video state changes. + */ + REMOTE_VIDEO_STATE_REASON_INTERNAL = 0, + + /** 1: Network congestion. + */ + REMOTE_VIDEO_STATE_REASON_NETWORK_CONGESTION = 1, + + /** 2: Network recovery. + */ + REMOTE_VIDEO_STATE_REASON_NETWORK_RECOVERY = 2, + + /** 3: The local user stops receiving the remote video stream or disables the video module. + */ + REMOTE_VIDEO_STATE_REASON_LOCAL_MUTED = 3, + + /** 4: The local user resumes receiving the remote video stream or enables the video module. + */ + REMOTE_VIDEO_STATE_REASON_LOCAL_UNMUTED = 4, + + /** 5: The remote user stops sending the video stream or disables the video module. + */ + REMOTE_VIDEO_STATE_REASON_REMOTE_MUTED = 5, + + /** 6: The remote user resumes sending the video stream or enables the video module. + */ + REMOTE_VIDEO_STATE_REASON_REMOTE_UNMUTED = 6, + + /** 7: The remote user leaves the channel. + */ + REMOTE_VIDEO_STATE_REASON_REMOTE_OFFLINE = 7, + + /** 8: The remote audio-and-video stream falls back to the audio-only stream due to poor network conditions. + */ + REMOTE_VIDEO_STATE_REASON_AUDIO_FALLBACK = 8, + + /** 9: The remote audio-only stream switches back to the audio-and-video stream after the network conditions improve. + */ + REMOTE_VIDEO_STATE_REASON_AUDIO_FALLBACK_RECOVERY = 9 + +}; + +/** Video frame rates. */ +enum FRAME_RATE { + /** 1: 1 fps */ + FRAME_RATE_FPS_1 = 1, + /** 7: 7 fps */ + FRAME_RATE_FPS_7 = 7, + /** 10: 10 fps */ + FRAME_RATE_FPS_10 = 10, + /** 15: 15 fps */ + FRAME_RATE_FPS_15 = 15, + /** 24: 24 fps */ + FRAME_RATE_FPS_24 = 24, + /** 30: 30 fps */ + FRAME_RATE_FPS_30 = 30, + /** 60: 60 fps (Windows and macOS only) */ + FRAME_RATE_FPS_60 = 60, +}; + +/** Video output orientation modes. + */ +enum ORIENTATION_MODE { + /** 0: (Default) Adaptive mode. + + The video encoder adapts to the orientation mode of the video input device. + + - If the width of the captured video from the SDK is greater than the height, the encoder sends the video in landscape mode. The encoder also sends the rotational information of the video, and the receiver uses the rotational information to rotate the received video. + - When you use a custom video source, the output video from the encoder inherits the orientation of the original video. If the original video is in portrait mode, the output video from the encoder is also in portrait mode. The encoder also sends the rotational information of the video to the receiver. + */ + ORIENTATION_MODE_ADAPTIVE = 0, + /** 1: Landscape mode. + + The video encoder always sends the video in landscape mode. The video encoder rotates the original video before sending it and the rotational infomation is 0. This mode applies to scenarios involving CDN live streaming. + */ + ORIENTATION_MODE_FIXED_LANDSCAPE = 1, + /** 2: Portrait mode. + + The video encoder always sends the video in portrait mode. The video encoder rotates the original video before sending it and the rotational infomation is 0. This mode applies to scenarios involving CDN live streaming. + */ + ORIENTATION_MODE_FIXED_PORTRAIT = 2, +}; + +/** Video degradation preferences under limited bandwidth. */ +enum DEGRADATION_PREFERENCE { + /** 0: (Default) Prefers to reduce the video frame rate while maintaining + * video quality during video encoding under limited bandwidth. This + * degradation preference is suitable for scenarios where video quality is + * prioritized. + * + * @note In the `COMMUNICATION` channel profile, the resolution of the video + * sent may change, so remote users need to handle this issue. + * See \ref IRtcEngineEventHandler::onVideoSizeChanged "onVideoSizeChanged". + */ + MAINTAIN_QUALITY = 0, + /** 1: Prefers to reduce the video quality while maintaining the video frame + * rate during video encoding under limited bandwidth. This degradation + * preference is suitable for scenarios where smoothness is prioritized and + * video quality is allowed to be reduced. + */ + MAINTAIN_FRAMERATE = 1, + /** 2: Reduces the video frame rate and video quality simultaneously during + * video encoding under limited bandwidth. `MAINTAIN_BALANCED` has a lower + * reduction than `MAINTAIN_QUALITY` and `MAINTAIN_FRAMERATE`, and this + * preference is suitable for scenarios where both smoothness and video + * quality are a priority. + * + * @note The resolution of the video sent may change, so remote users need + * to handle this issue. + * See \ref IRtcEngineEventHandler::onVideoSizeChanged "onVideoSizeChanged". + */ + MAINTAIN_BALANCED = 2, +}; + +/** Stream fallback options. */ +enum STREAM_FALLBACK_OPTIONS { + /** 0: No fallback behavior for the local/remote video stream when the uplink/downlink network conditions are poor. The quality of the stream is not guaranteed. */ + STREAM_FALLBACK_OPTION_DISABLED = 0, + /** 1: Under poor downlink network conditions, the remote video stream, to which you subscribe, falls back to the low-stream (low resolution and low bitrate) video. You can set this option only in the \ref IRtcEngine::setRemoteSubscribeFallbackOption "setRemoteSubscribeFallbackOption" method. Nothing happens when you set this in the \ref IRtcEngine::setLocalPublishFallbackOption "setLocalPublishFallbackOption" method. */ + STREAM_FALLBACK_OPTION_VIDEO_STREAM_LOW = 1, + /** 2: Under poor uplink network conditions, the published video stream falls back to audio only. + + Under poor downlink network conditions, the remote video stream, to which you subscribe, first falls back to the low-stream (low resolution and low bitrate) video; and then to an audio-only stream if the network conditions worsen.*/ + STREAM_FALLBACK_OPTION_AUDIO_ONLY = 2, +}; + +/** Camera capture preference. + */ +enum CAPTURER_OUTPUT_PREFERENCE { + /** 0: (Default) self-adapts the camera output parameters to the system performance and network conditions to balance CPU consumption and video preview quality. + */ + CAPTURER_OUTPUT_PREFERENCE_AUTO = 0, + /** 1: Prioritizes the system performance. The SDK chooses the dimension and frame rate of the local camera capture closest to those set by \ref IRtcEngine::setVideoEncoderConfiguration "setVideoEncoderConfiguration". + */ + CAPTURER_OUTPUT_PREFERENCE_PERFORMANCE = 1, + /** 2: Prioritizes the local preview quality. The SDK chooses higher camera output parameters to improve the local video preview quality. This option requires extra CPU and RAM usage for video pre-processing. + */ + CAPTURER_OUTPUT_PREFERENCE_PREVIEW = 2, + /** 3: Allows you to customize the width and height of the video image captured by the local camera. + * + * @since v3.3.0 + */ + CAPTURER_OUTPUT_PREFERENCE_MANUAL = 3, +}; + +/** The priority of the remote user. + */ +enum PRIORITY_TYPE { + /** 50: The user's priority is high. + */ + PRIORITY_HIGH = 50, + /** 100: (Default) The user's priority is normal. + */ + PRIORITY_NORMAL = 100, +}; + +/** Connection states. */ +enum CONNECTION_STATE_TYPE { + /** 1: The SDK is disconnected from Agora's edge server. + + - This is the initial state before calling the \ref agora::rtc::IRtcEngine::joinChannel "joinChannel" method. + - The SDK also enters this state when the application calls the \ref agora::rtc::IRtcEngine::leaveChannel "leaveChannel" method. + */ + CONNECTION_STATE_DISCONNECTED = 1, + /** 2: The SDK is connecting to Agora's edge server. + + - When the application calls the \ref agora::rtc::IRtcEngine::joinChannel "joinChannel" method, the SDK starts to establish a connection to the specified channel, triggers the \ref agora::rtc::IRtcEngineEventHandler::onConnectionStateChanged "onConnectionStateChanged" callback, and switches to the #CONNECTION_STATE_CONNECTING state. + - When the SDK successfully joins the channel, it triggers the \ref agora::rtc::IRtcEngineEventHandler::onConnectionStateChanged "onConnectionStateChanged" callback and switches to the #CONNECTION_STATE_CONNECTED state. + - After the SDK joins the channel and when it finishes initializing the media engine, the SDK triggers the \ref agora::rtc::IRtcEngineEventHandler::onJoinChannelSuccess "onJoinChannelSuccess" callback. + */ + CONNECTION_STATE_CONNECTING = 2, + /** 3: The SDK is connected to Agora's edge server and has joined a channel. You can now publish or subscribe to a media stream in the channel. + + If the connection to the channel is lost because, for example, if the network is down or switched, the SDK automatically tries to reconnect and triggers: + - The \ref agora::rtc::IRtcEngineEventHandler::onConnectionInterrupted "onConnectionInterrupted" callback (deprecated). + - The \ref agora::rtc::IRtcEngineEventHandler::onConnectionStateChanged "onConnectionStateChanged" callback and switches to the #CONNECTION_STATE_RECONNECTING state. + */ + CONNECTION_STATE_CONNECTED = 3, + /** 4: The SDK keeps rejoining the channel after being disconnected from a joined channel because of network issues. + + - If the SDK cannot rejoin the channel within 10 seconds after being disconnected from Agora's edge server, the SDK triggers the \ref agora::rtc::IRtcEngineEventHandler::onConnectionLost "onConnectionLost" callback, stays in the #CONNECTION_STATE_RECONNECTING state, and keeps rejoining the channel. + - If the SDK fails to rejoin the channel 20 minutes after being disconnected from Agora's edge server, the SDK triggers the \ref agora::rtc::IRtcEngineEventHandler::onConnectionStateChanged "onConnectionStateChanged" callback, switches to the #CONNECTION_STATE_FAILED state, and stops rejoining the channel. + */ + CONNECTION_STATE_RECONNECTING = 4, + /** 5: The SDK fails to connect to Agora's edge server or join the channel. + + You must call the \ref agora::rtc::IRtcEngine::leaveChannel "leaveChannel" method to leave this state, and call the \ref agora::rtc::IRtcEngine::joinChannel "joinChannel" method again to rejoin the channel. + + If the SDK is banned from joining the channel by Agora's edge server (through the RESTful API), the SDK triggers the \ref agora::rtc::IRtcEngineEventHandler::onConnectionBanned "onConnectionBanned" (deprecated) and \ref agora::rtc::IRtcEngineEventHandler::onConnectionStateChanged "onConnectionStateChanged" callbacks. + */ + CONNECTION_STATE_FAILED = 5, +}; + +/** Reasons for a connection state change. */ +enum CONNECTION_CHANGED_REASON_TYPE { + /** 0: The SDK is connecting to Agora's edge server. */ + CONNECTION_CHANGED_CONNECTING = 0, + /** 1: The SDK has joined the channel successfully. */ + CONNECTION_CHANGED_JOIN_SUCCESS = 1, + /** 2: The connection between the SDK and Agora's edge server is interrupted. */ + CONNECTION_CHANGED_INTERRUPTED = 2, + /** 3: The user is banned by the server. This error occurs when the user is kicked out the channel from the server. */ + CONNECTION_CHANGED_BANNED_BY_SERVER = 3, + /** 4: The SDK fails to join the channel for more than 20 minutes and stops reconnecting to the channel. */ + CONNECTION_CHANGED_JOIN_FAILED = 4, + /** 5: The SDK has left the channel. */ + CONNECTION_CHANGED_LEAVE_CHANNEL = 5, + /** + * 6: The specified App ID is invalid. Try to rejoin the channel with a valid App ID. + */ + CONNECTION_CHANGED_INVALID_APP_ID = 6, + /** 7: The connection failed since channel name is not valid. */ + CONNECTION_CHANGED_INVALID_CHANNEL_NAME = 7, + /** 8: The connection failed since token is not valid, possibly because: + + - The App Certificate for the project is enabled in Console, but you do not use Token when joining the channel. If you enable the App Certificate, you must use a token to join the channel. + - The uid that you specify in the \ref agora::rtc::IRtcEngine::joinChannel "joinChannel" method is different from the uid that you pass for generating the token. + */ + CONNECTION_CHANGED_INVALID_TOKEN = 8, + /** 9: The connection failed since token is expired. */ + CONNECTION_CHANGED_TOKEN_EXPIRED = 9, + /** 10: The connection is rejected by server. This error usually occurs in the following situations: + * - When the user is already in the channel, and still calls the method to join the channel, for example, + * \ref IRtcEngine::joinChannel "joinChannel". + * - When the user tries to join a channel during \ref IRtcEngine::startEchoTest "startEchoTest". Once you + * call \ref IRtcEngine::startEchoTest "startEchoTest", you need to call \ref IRtcEngine::stopEchoTest "stopEchoTest" before joining a channel. + * + */ + CONNECTION_CHANGED_REJECTED_BY_SERVER = 10, + /** 11: The connection changed to reconnecting since SDK has set a proxy server. */ + CONNECTION_CHANGED_SETTING_PROXY_SERVER = 11, + /** 12: When SDK is in connection failed, the renew token operation will make it connecting. */ + CONNECTION_CHANGED_RENEW_TOKEN = 12, + /** 13: The IP Address of SDK client has changed. i.e., Network type or IP/Port changed by network operator might change client IP address. */ + CONNECTION_CHANGED_CLIENT_IP_ADDRESS_CHANGED = 13, + /** 14: Timeout for the keep-alive of the connection between the SDK and Agora's edge server. The connection state changes to CONNECTION_STATE_RECONNECTING(4). */ + CONNECTION_CHANGED_KEEP_ALIVE_TIMEOUT = 14, + /** 15: In cloud proxy mode, the proxy server connection interrupted. */ + CONNECTION_CHANGED_PROXY_SERVER_INTERRUPTED = 15, +}; + +/** Network type. */ +enum NETWORK_TYPE { + /** -1: The network type is unknown. */ + NETWORK_TYPE_UNKNOWN = -1, + /** 0: The SDK disconnects from the network. */ + NETWORK_TYPE_DISCONNECTED = 0, + /** 1: The network type is LAN. */ + NETWORK_TYPE_LAN = 1, + /** 2: The network type is Wi-Fi (including hotspots). */ + NETWORK_TYPE_WIFI = 2, + /** 3: The network type is mobile 2G. */ + NETWORK_TYPE_MOBILE_2G = 3, + /** 4: The network type is mobile 3G. */ + NETWORK_TYPE_MOBILE_3G = 4, + /** 5: The network type is mobile 4G. */ + NETWORK_TYPE_MOBILE_4G = 5, + /** 6: The network type is mobile 5G. + * + * @since v3.5.1 + */ + NETWORK_TYPE_MOBILE_5G = 6, +}; +/// @cond +/** + * The reason for the upload failure. + * + * @since v3.3.0 + */ +enum UPLOAD_ERROR_REASON { + /** 0: The log file is successfully uploaded. + */ + UPLOAD_SUCCESS = 0, + /** + * 1: Network error. Check the network connection and call \ref IRtcEngine::uploadLogFile "uploadLogFile" again to upload the log file. + */ + UPLOAD_NET_ERROR = 1, + /** + * 2: An error occurs in the Agora server. Try uploading the log files later. + */ + UPLOAD_SERVER_ERROR = 2, +}; +/// @endcond + +/** States of the last-mile network probe test. */ +enum LASTMILE_PROBE_RESULT_STATE { + /** 1: The last-mile network probe test is complete. */ + LASTMILE_PROBE_RESULT_COMPLETE = 1, + /** 2: The last-mile network probe test is incomplete and the bandwidth estimation is not available, probably due to limited test resources. */ + LASTMILE_PROBE_RESULT_INCOMPLETE_NO_BWE = 2, + /** 3: The last-mile network probe test is not carried out, probably due to poor network conditions. */ + LASTMILE_PROBE_RESULT_UNAVAILABLE = 3 +}; +/** The current audio route. + * + * Reports in the \ref IRtcEngineEventHandler::onAudioRouteChanged "onAudioRouteChanged" callback. + */ +enum AUDIO_ROUTE_TYPE { + /** -1: Default audio route. + */ + AUDIO_ROUTE_DEFAULT = -1, + /** 0: The audio route is a headset with a microphone. + */ + AUDIO_ROUTE_HEADSET = 0, + /** 1: The audio route is an earpiece. + */ + AUDIO_ROUTE_EARPIECE = 1, + /** 2: The audio route is a headset without a microphone. + */ + AUDIO_ROUTE_HEADSET_NO_MIC = 2, + /** 3: The audio route is the speaker that comes with the device. + */ + AUDIO_ROUTE_SPEAKERPHONE = 3, + /** 4: (iOS and macOS only) The audio route is an external speaker. + */ + AUDIO_ROUTE_LOUDSPEAKER = 4, + /** 5: The audio route is a Bluetooth headset. + */ + AUDIO_ROUTE_BLUETOOTH = 5, + /** 6: (macOS only) The audio route is a USB peripheral device. + */ + AUDIO_ROUTE_USB = 6, + /** 7: (macOS only) The audio route is an HDMI peripheral device. + */ + AUDIO_ROUTE_HDMI = 7, + /** 8: (macOS only) The audio route is a DisplayPort peripheral device. + */ + AUDIO_ROUTE_DISPLAYPORT = 8, + /** 9: (iOS and macOS only) The audio route is Apple AirPlay. + */ + AUDIO_ROUTE_AIRPLAY = 9, +}; + +/** The cloud proxy type. + * + * @since v3.3.0 + */ +enum CLOUD_PROXY_TYPE { + /** 0: Do not use the cloud proxy. + */ + NONE_PROXY = 0, + /** 1: The cloud proxy for the UDP protocol. + */ + UDP_PROXY = 1, + /// @cond + /** 2: The cloud proxy for the TCP (encrypted) protocol. + */ + TCP_PROXY = 2, + /// @endcond +}; + +#if (defined(__APPLE__) && TARGET_OS_IOS) +/** + * The operational permission of the SDK on the audio session. + */ +enum AUDIO_SESSION_OPERATION_RESTRICTION { + /** + * 0: No restriction; the SDK can change the audio session. + */ + AUDIO_SESSION_OPERATION_RESTRICTION_NONE = 0, + /** + * 1: The SDK cannot change the audio session category. + */ + AUDIO_SESSION_OPERATION_RESTRICTION_SET_CATEGORY = 1, + /** + * 2: The SDK cannot change the audio session category, mode, or categoryOptions. + */ + AUDIO_SESSION_OPERATION_RESTRICTION_CONFIGURE_SESSION = 1 << 1, + /** + * 4: The SDK keeps the audio session active when the user leaves the + * channel, for example, to play an audio file in the background. + */ + AUDIO_SESSION_OPERATION_RESTRICTION_DEACTIVATE_SESSION = 1 << 2, + /** + * 128: Completely restricts the operational permission of the SDK on the + * audio session; the SDK cannot change the audio session. + */ + AUDIO_SESSION_OPERATION_RESTRICTION_ALL = 1 << 7, +}; +#endif + +#if defined(__ANDROID__) || (defined(__APPLE__) && TARGET_OS_IOS) +enum CAMERA_DIRECTION { + /** The rear camera. */ + CAMERA_REAR = 0, + /** The front camera. */ + CAMERA_FRONT = 1, +}; +#endif + +/** + * Recording content, which is set + * in \ref IRtcEngine::startAudioRecording(const AudioRecordingConfiguration&) "startAudioRecording". + */ +enum AUDIO_RECORDING_POSITION { + /** 0: (Default) Records the mixed audio of the local user and all remote + * users. + */ + AUDIO_RECORDING_POSITION_MIXED_RECORDING_AND_PLAYBACK = 0, + /** 1: Records the audio of the local user only. + */ + AUDIO_RECORDING_POSITION_RECORDING = 1, + /** 2: Records the audio of all remote users only. + */ + AUDIO_RECORDING_POSITION_MIXED_PLAYBACK = 2, +}; + +/** The uplink or downlink last-mile network probe test result. */ +struct LastmileProbeOneWayResult { + /** The packet loss rate (%). */ + unsigned int packetLossRate; + /** The network jitter (ms). */ + unsigned int jitter; + /* The estimated available bandwidth (bps). */ + unsigned int availableBandwidth; +}; + +/** The uplink and downlink last-mile network probe test result. */ +struct LastmileProbeResult { + /** The state of the probe test. */ + LASTMILE_PROBE_RESULT_STATE state; + /** The uplink last-mile network probe test result. */ + LastmileProbeOneWayResult uplinkReport; + /** The downlink last-mile network probe test result. */ + LastmileProbeOneWayResult downlinkReport; + /** The round-trip delay time (ms). */ + unsigned int rtt; +}; + +/** Configurations of the last-mile network probe test. */ +struct LastmileProbeConfig { + /** Sets whether to test the uplink network. Some users, for example, the audience in a `LIVE_BROADCASTING` channel, do not need such a test: + - true: test. + - false: do not test. */ + bool probeUplink; + /** Sets whether to test the downlink network: + - true: test. + - false: do not test. */ + bool probeDownlink; + /** The expected maximum sending bitrate (bps) of the local user. The value ranges between 100000 and 5000000. We recommend setting this parameter according to the bitrate value set by \ref IRtcEngine::setVideoEncoderConfiguration "setVideoEncoderConfiguration". */ + unsigned int expectedUplinkBitrate; + /** The expected maximum receiving bitrate (bps) of the local user. The value ranges between 100000 and 5000000. */ + unsigned int expectedDownlinkBitrate; +}; + +/** The volume information of users. + */ +struct AudioVolumeInfo { + /** + * The user ID. + * - In the local user's callback, `uid = 0`. + * - In the remote users' callback, `uid` is the ID of a remote user whose instantaneous volume is one of the three highest. + */ + uid_t uid; + /** The volume of each user after audio mixing. The value ranges between 0 (lowest volume) and 255 (highest volume). + * In the local user's callback, `volume = totalVolume`. + */ + unsigned int volume; + /** Voice activity status of the local user. + * - `0`: The local user is not speaking. + * - `1`: The local user is speaking. + * + * @note + * - The `vad` parameter cannot report the voice activity status of remote users. + * In the remote users' callback, `vad` is always `1`. + * - To use this parameter, you must set the `report_vad` parameter to `true` + * when calling \ref agora::rtc::IRtcEngine::enableAudioVolumeIndication(int, int, bool) "enableAudioVolumeIndication". + */ + unsigned int vad; + /** The name of the channel where the user is in. + */ + const char* channelId; +}; + +/** + * The information of an audio file. This struct is reported + * in \ref IRtcEngineEventHandler::onRequestAudioFileInfo "onRequestAudioFileInfo". + * + * @since v3.5.1 + */ +struct AudioFileInfo { + /** The file path. + */ + const char* filePath; + /** The file duration (ms). + */ + int durationMs; +}; + +/** The information acquisition state. This enum is reported + * in \ref IRtcEngineEventHandler::onRequestAudioFileInfo "onRequestAudioFileInfo". + * + * @since v3.5.1 + */ +enum AUDIO_FILE_INFO_ERROR { + /** 0: Successfully get the information of an audio file. + */ + AUDIO_FILE_INFO_ERROR_OK = 0, + + /** 1: Fail to get the information of an audio file. + */ + AUDIO_FILE_INFO_ERROR_FAILURE = 1 +}; + +/** The detailed options of a user. + */ +struct ClientRoleOptions { + /** The latency level of an audience member in interactive live streaming. See #AUDIENCE_LATENCY_LEVEL_TYPE. + */ + AUDIENCE_LATENCY_LEVEL_TYPE audienceLatencyLevel; + ClientRoleOptions() : audienceLatencyLevel(AUDIENCE_LATENCY_LEVEL_ULTRA_LOW_LATENCY) {} +}; +/** Statistics of the channel. + */ +struct RtcStats { + /** + * Call duration of the local user in seconds, represented by an aggregate value. + */ + unsigned int duration; + /** + * Total number of bytes transmitted, represented by an aggregate value. + */ + unsigned int txBytes; + /** + * Total number of bytes received, represented by an aggregate value. + */ + unsigned int rxBytes; + /** Total number of audio bytes sent (bytes), represented + * by an aggregate value. + */ + unsigned int txAudioBytes; + /** Total number of video bytes sent (bytes), represented + * by an aggregate value. + */ + unsigned int txVideoBytes; + /** Total number of audio bytes received (bytes) before + * network countermeasures, represented by an aggregate value. + */ + unsigned int rxAudioBytes; + /** Total number of video bytes received (bytes), + * represented by an aggregate value. + */ + unsigned int rxVideoBytes; + + /** + * Transmission bitrate (Kbps), represented by an instantaneous value. + */ + unsigned short txKBitRate; + /** + * Receive bitrate (Kbps), represented by an instantaneous value. + */ + unsigned short rxKBitRate; + /** + * Audio receive bitrate (Kbps), represented by an instantaneous value. + */ + unsigned short rxAudioKBitRate; + /** + * Audio transmission bitrate (Kbps), represented by an instantaneous value. + */ + unsigned short txAudioKBitRate; + /** + * Video receive bitrate (Kbps), represented by an instantaneous value. + */ + unsigned short rxVideoKBitRate; + /** + * Video transmission bitrate (Kbps), represented by an instantaneous value. + */ + unsigned short txVideoKBitRate; + /** Client-server latency (ms) + */ + unsigned short lastmileDelay; + /** The packet loss rate (%) from the local client to Agora's edge server, + * before using the anti-packet-loss method. + */ + unsigned short txPacketLossRate; + /** The packet loss rate (%) from Agora's edge server to the local client, + * before using the anti-packet-loss method. + */ + unsigned short rxPacketLossRate; + /** Number of users in the channel. + * + * - `COMMUNICATION` profile: The number of users in the channel. + * - `LIVE_BROADCASTING` profile: + * - If the local user is an audience: The number of users in the channel = The number of hosts in the channel + 1. + * - If the user is a host: The number of users in the channel = The number of hosts in the channel. + */ + unsigned int userCount; + /** + * Application CPU usage (%). + * + * @note + * - The `cpuAppUsage` reported in the \ref IRtcEngineEventHandler::onLeaveChannel "onLeaveChannel" callback is always 0. + * - As of Android 8.1, you cannot get the CPU usage from this attribute due to system limitations. + */ + double cpuAppUsage; + /** + * System CPU usage (%). + * + * In the multi-kernel environment, this member represents the average CPU usage. + * The value **=** 100 **-** System Idle Progress in Task Manager (%). + * + * @note + * - The `cpuTotalUsage` reported in the \ref IRtcEngineEventHandler::onLeaveChannel "onLeaveChannel" callback is always 0. + * - As of Android 8.1, you cannot get the CPU usage from this attribute due to system limitations. + */ + double cpuTotalUsage; + /** The round-trip time delay from the client to the local router. + * + * @note + * - On iOS, As of v3.3.0, this attribute is disabled on devices running iOS 14 or later, and enabled on devices + * running versions earlier than iOS 14 by default. To enable this property on devices running iOS 14 or later, + * contact support@agora.io. See [FAQ](https://docs.agora.io/en/Interactive%20Broadcast/faq/local_network_privacy) for details. + * - On Android, to get this attribute, ensure that the `android.permission.ACCESS_WIFI_STATE` permission has been added after `` in + * the `AndroidManifest.xml` file in your project. + */ + int gatewayRtt; + /** + * The memory usage ratio of the app (%). + * + * @note This value is for reference only. Due to system limitations, you may not get the value of this member. + */ + double memoryAppUsageRatio; + /** + * The memory usage ratio of the system (%). + * + * @note This value is for reference only. Due to system limitations, you may not get the value of this member. + */ + double memoryTotalUsageRatio; + /** + * The memory usage of the app (KB). + * + * @note This value is for reference only. Due to system limitations, you may not get the value of this member. + */ + int memoryAppUsageInKbytes; + RtcStats() : duration(0), txBytes(0), rxBytes(0), txAudioBytes(0), txVideoBytes(0), rxAudioBytes(0), rxVideoBytes(0), txKBitRate(0), rxKBitRate(0), rxAudioKBitRate(0), txAudioKBitRate(0), rxVideoKBitRate(0), txVideoKBitRate(0), lastmileDelay(0), txPacketLossRate(0), rxPacketLossRate(0), userCount(0), cpuAppUsage(0), cpuTotalUsage(0), gatewayRtt(0), memoryAppUsageRatio(0), memoryTotalUsageRatio(0), memoryAppUsageInKbytes(0) {} +}; + +/** Quality change of the local video in terms of target frame rate and target bit rate since last count. + */ +enum QUALITY_ADAPT_INDICATION { + /** The quality of the local video stays the same. */ + ADAPT_NONE = 0, + /** The quality improves because the network bandwidth increases. */ + ADAPT_UP_BANDWIDTH = 1, + /** The quality worsens because the network bandwidth decreases. */ + ADAPT_DOWN_BANDWIDTH = 2, +}; +/** Quality of experience (QoE) of the local user when receiving a remote audio stream. + * + * @since v3.3.0 + */ +enum EXPERIENCE_QUALITY_TYPE { + /** 0: QoE of the local user is good. */ + EXPERIENCE_QUALITY_GOOD = 0, + /** 1: QoE of the local user is poor. */ + EXPERIENCE_QUALITY_BAD = 1, +}; + +/** + * The reason for poor QoE of the local user when receiving a remote audio stream. + * + * @since v3.3.0 + */ +enum EXPERIENCE_POOR_REASON { + /** 0: No reason, indicating good QoE of the local user. + */ + EXPERIENCE_REASON_NONE = 0, + /** 1: The remote user's network quality is poor. + */ + REMOTE_NETWORK_QUALITY_POOR = 1, + /** 2: The local user's network quality is poor. + */ + LOCAL_NETWORK_QUALITY_POOR = 2, + /** 4: The local user's Wi-Fi or mobile network signal is weak. + */ + WIRELESS_SIGNAL_POOR = 4, + /** 8: The local user enables both Wi-Fi and bluetooth, and their signals interfere with each other. + * As a result, audio transmission quality is undermined. + */ + WIFI_BLUETOOTH_COEXIST = 8, +}; + +/** The error code in CHANNEL_MEDIA_RELAY_ERROR. */ +enum CHANNEL_MEDIA_RELAY_ERROR { + /** 0: The state is normal. + */ + RELAY_OK = 0, + /** 1: An error occurs in the server response. + */ + RELAY_ERROR_SERVER_ERROR_RESPONSE = 1, + /** 2: No server response. + * + * You can call the + * \ref agora::rtc::IRtcEngine::leaveChannel "leaveChannel" method to + * leave the channel. + * + * This error can also occur if your project has not enabled co-host token + * authentication. Contact support@agora.io to enable the co-host token + * authentication service before starting a channel media relay. + */ + RELAY_ERROR_SERVER_NO_RESPONSE = 2, + /** 3: The SDK fails to access the service, probably due to limited + * resources of the server. + */ + RELAY_ERROR_NO_RESOURCE_AVAILABLE = 3, + /** 4: Fails to send the relay request. + */ + RELAY_ERROR_FAILED_JOIN_SRC = 4, + /** 5: Fails to accept the relay request. + */ + RELAY_ERROR_FAILED_JOIN_DEST = 5, + /** 6: The server fails to receive the media stream. + */ + RELAY_ERROR_FAILED_PACKET_RECEIVED_FROM_SRC = 6, + /** 7: The server fails to send the media stream. + */ + RELAY_ERROR_FAILED_PACKET_SENT_TO_DEST = 7, + /** 8: The SDK disconnects from the server due to poor network + * connections. You can call the \ref agora::rtc::IRtcEngine::leaveChannel + * "leaveChannel" method to leave the channel. + */ + RELAY_ERROR_SERVER_CONNECTION_LOST = 8, + /** 9: An internal error occurs in the server. + */ + RELAY_ERROR_INTERNAL_ERROR = 9, + /** 10: The token of the source channel has expired. + */ + RELAY_ERROR_SRC_TOKEN_EXPIRED = 10, + /** 11: The token of the destination channel has expired. + */ + RELAY_ERROR_DEST_TOKEN_EXPIRED = 11, +}; + +/** The event code in CHANNEL_MEDIA_RELAY_EVENT. */ +enum CHANNEL_MEDIA_RELAY_EVENT { + /** 0: The user disconnects from the server due to poor network + * connections. + */ + RELAY_EVENT_NETWORK_DISCONNECTED = 0, + /** 1: The network reconnects. + */ + RELAY_EVENT_NETWORK_CONNECTED = 1, + /** 2: The user joins the source channel. + */ + RELAY_EVENT_PACKET_JOINED_SRC_CHANNEL = 2, + /** 3: The user joins the destination channel. + */ + RELAY_EVENT_PACKET_JOINED_DEST_CHANNEL = 3, + /** 4: The SDK starts relaying the media stream to the destination channel. + */ + RELAY_EVENT_PACKET_SENT_TO_DEST_CHANNEL = 4, + /** 5: The server receives the video stream from the source channel. + */ + RELAY_EVENT_PACKET_RECEIVED_VIDEO_FROM_SRC = 5, + /** 6: The server receives the audio stream from the source channel. + */ + RELAY_EVENT_PACKET_RECEIVED_AUDIO_FROM_SRC = 6, + /** 7: The destination channel is updated. + */ + RELAY_EVENT_PACKET_UPDATE_DEST_CHANNEL = 7, + /** 8: The destination channel update fails due to internal reasons. + */ + RELAY_EVENT_PACKET_UPDATE_DEST_CHANNEL_REFUSED = 8, + /** 9: The destination channel does not change, which means that the + * destination channel fails to be updated. + */ + RELAY_EVENT_PACKET_UPDATE_DEST_CHANNEL_NOT_CHANGE = 9, + /** 10: The destination channel name is NULL. + */ + RELAY_EVENT_PACKET_UPDATE_DEST_CHANNEL_IS_NULL = 10, + /** 11: The video profile is sent to the server. + */ + RELAY_EVENT_VIDEO_PROFILE_UPDATE = 11, + /** 12: The SDK successfully pauses relaying the media stream to destination channels. + * + * @since v3.5.1 + */ + RELAY_EVENT_PAUSE_SEND_PACKET_TO_DEST_CHANNEL_SUCCESS = 12, + /** 13: The SDK fails to pause relaying the media stream to destination channels. + * + * @since v3.5.1 + */ + RELAY_EVENT_PAUSE_SEND_PACKET_TO_DEST_CHANNEL_FAILED = 13, + /** 14: The SDK successfully resumes relaying the media stream to destination channels. + * + * @since v3.5.1 + */ + RELAY_EVENT_RESUME_SEND_PACKET_TO_DEST_CHANNEL_SUCCESS = 14, + /** 15: The SDK fails to resume relaying the media stream to destination channels. + * + * @since v3.5.1 + */ + RELAY_EVENT_RESUME_SEND_PACKET_TO_DEST_CHANNEL_FAILED = 15, +}; + +/** The state code in CHANNEL_MEDIA_RELAY_STATE. */ +enum CHANNEL_MEDIA_RELAY_STATE { + /** 0: The initial state. After you successfully stop the channel media + * relay by calling \ref IRtcEngine::stopChannelMediaRelay "stopChannelMediaRelay", + * the \ref IRtcEngineEventHandler::onChannelMediaRelayStateChanged "onChannelMediaRelayStateChanged" callback returns this state. + */ + RELAY_STATE_IDLE = 0, + /** 1: The SDK tries to relay the media stream to the destination channel. + */ + RELAY_STATE_CONNECTING = 1, + /** 2: The SDK successfully relays the media stream to the destination + * channel. + */ + RELAY_STATE_RUNNING = 2, + /** 3: A failure occurs. See the details in code. + */ + RELAY_STATE_FAILURE = 3, +}; + +/** Statistics of the local video stream. + */ +struct LocalVideoStats { + /** Bitrate (Kbps) sent in the reported interval, which does not include + * the bitrate of the retransmission video after packet loss. + */ + int sentBitrate; + /** Frame rate (fps) sent in the reported interval, which does not include + * the frame rate of the retransmission video after packet loss. + */ + int sentFrameRate; + /** The encoder output frame rate (fps) of the local video. + */ + int encoderOutputFrameRate; + /** The render output frame rate (fps) of the local video. + */ + int rendererOutputFrameRate; + /** The target bitrate (Kbps) of the current encoder. This value is estimated by the SDK based on the current network conditions. + */ + int targetBitrate; + /** The target frame rate (fps) of the current encoder. + */ + int targetFrameRate; + /** Quality change of the local video in terms of target frame rate and + * target bit rate in this reported interval. See #QUALITY_ADAPT_INDICATION. + */ + QUALITY_ADAPT_INDICATION qualityAdaptIndication; + /** The encoding bitrate (Kbps), which does not include the bitrate of the + * re-transmission video after packet loss. + */ + int encodedBitrate; + /** The width of the encoding frame (px). + */ + int encodedFrameWidth; + /** The height of the encoding frame (px). + */ + int encodedFrameHeight; + /** The value of the sent frames, represented by an aggregate value. + */ + int encodedFrameCount; + /** The codec type of the local video: + * - VIDEO_CODEC_VP8 = 1: VP8. + * - VIDEO_CODEC_H264 = 2: (Default) H.264. + */ + VIDEO_CODEC_TYPE codecType; + /** The video packet loss rate (%) from the local client to the Agora edge server before applying the anti-packet loss strategies. + */ + unsigned short txPacketLossRate; + /** The capture frame rate (fps) of the local video. + */ + int captureFrameRate; + /** The brightness level of the video image captured by the local camera. See #CAPTURE_BRIGHTNESS_LEVEL_TYPE. + * + * @since v3.3.0 + */ + CAPTURE_BRIGHTNESS_LEVEL_TYPE captureBrightnessLevel; +}; + +/** Statistics of the remote video stream. + */ +struct RemoteVideoStats { + /** + User ID of the remote user sending the video streams. + */ + uid_t uid; + /** **DEPRECATED** Time delay (ms). + * + * In scenarios where audio and video is synchronized, you can use the value of + * `networkTransportDelay` and `jitterBufferDelay` in `RemoteAudioStats` to know the delay statistics of the remote video. + */ + int delay; + /** Width (pixels) of the video stream. + */ + int width; + /** + Height (pixels) of the video stream. + */ + int height; + /** + Bitrate (Kbps) received since the last count. + */ + int receivedBitrate; + /** The decoder output frame rate (fps) of the remote video. + */ + int decoderOutputFrameRate; + /** The render output frame rate (fps) of the remote video. + */ + int rendererOutputFrameRate; + /** Packet loss rate (%) of the remote video stream after using the anti-packet-loss method. + */ + int packetLossRate; + /** The type of the remote video stream: #REMOTE_VIDEO_STREAM_TYPE + */ + REMOTE_VIDEO_STREAM_TYPE rxStreamType; + /** + The total freeze time (ms) of the remote video stream after the remote user joins the channel. + In a video session where the frame rate is set to no less than 5 fps, video freeze occurs when + the time interval between two adjacent renderable video frames is more than 500 ms. + */ + int totalFrozenTime; + /** + The total video freeze time as a percentage (%) of the total time when the video is available. + */ + int frozenRate; + /** + The total time (ms) when the remote user in the Communication profile or the remote + broadcaster in the Live-broadcast profile neither stops sending the video stream nor + disables the video module after joining the channel. + + @since v3.0.1 + */ + int totalActiveTime; + /** + * The total publish duration (ms) of the remote video stream. + */ + int publishDuration; +}; + +/** Audio statistics of the local user */ +struct LocalAudioStats { + /** The number of channels. + */ + int numChannels; + /** The sample rate (Hz). + */ + int sentSampleRate; + /** The average sending bitrate (Kbps). + */ + int sentBitrate; + /** The audio packet loss rate (%) from the local client to the Agora edge server before applying the anti-packet loss strategies. + */ + unsigned short txPacketLossRate; +}; + +/** Audio statistics of a remote user */ +struct RemoteAudioStats { + /** User ID of the remote user sending the audio streams. + * + */ + uid_t uid; + /** Audio quality received by the user: #QUALITY_TYPE. + */ + int quality; + /** Network delay (ms) from the sender to the receiver. + */ + int networkTransportDelay; + /** Network delay (ms) from the receiver to the jitter buffer. + */ + int jitterBufferDelay; + /** The audio frame loss rate in the reported interval. + */ + int audioLossRate; + /** The number of channels. + */ + int numChannels; + /** The sample rate (Hz) of the received audio stream in the reported + * interval. + */ + int receivedSampleRate; + /** The average bitrate (Kbps) of the received audio stream in the + * reported interval. */ + int receivedBitrate; + /** The total freeze time (ms) of the remote audio stream after the remote user joins the channel. In a session, audio freeze occurs when the audio frame loss rate reaches 4%. + */ + int totalFrozenTime; + /** The total audio freeze time as a percentage (%) of the total time when the audio is available. */ + int frozenRate; + /** The total time (ms) when the remote user in the `COMMUNICATION` profile or the remote host in + the `LIVE_BROADCASTING` profile neither stops sending the audio stream nor disables the audio module after joining the channel. + */ + int totalActiveTime; + /** + * The total publish duration (ms) of the remote audio stream. + */ + int publishDuration; + /** + * Quality of experience (QoE) of the local user when receiving a remote audio stream. See #EXPERIENCE_QUALITY_TYPE. + * + * @since v3.3.0 + */ + int qoeQuality; + /** + * The reason for poor QoE of the local user when receiving a remote audio stream. See #EXPERIENCE_POOR_REASON. + * + * @since v3.3.0 + */ + int qualityChangedReason; + /** + * The quality of the remote audio stream as determined by the Agora + * real-time audio MOS (Mean Opinion Score) measurement method in the + * reported interval. The return value ranges from 0 to 500. Dividing the + * return value by 100 gets the MOS score, which ranges from 0 to 5. The + * higher the score, the better the audio quality. + * + * @since v3.3.1 + * + * The subjective perception of audio quality corresponding to the Agora + * real-time audio MOS scores is as follows: + * + * | MOS score | Perception of audio quality | + * |-----------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------| + * | Greater than 4 | Excellent. The audio sounds clear and smooth. | + * | From 3.5 to 4 | Good. The audio has some perceptible impairment, but still sounds clear. | + * | From 3 to 3.5 | Fair. The audio freezes occasionally and requires attentive listening. | + * | From 2.5 to 3 | Poor. The audio sounds choppy and requires considerable effort to understand. | + * | From 2 to 2.5 | Bad. The audio has occasional noise. Consecutive audio dropouts occur, resulting in some information loss. The users can communicate only with difficulty. | + * | Less than 2 | Very bad. The audio has persistent noise. Consecutive audio dropouts are frequent, resulting in severe information loss. Communication is nearly impossible. | + */ + int mosValue; +}; + +/** + * Video dimensions. + */ +struct VideoDimensions { + /** Width (pixels) of the video. */ + int width; + /** Height (pixels) of the video. */ + int height; + VideoDimensions() : width(640), height(480) {} + VideoDimensions(int w, int h) : width(w), height(h) {} +}; + +/** (Recommended) The standard bitrate set in the \ref IRtcEngine::setVideoEncoderConfiguration "setVideoEncoderConfiguration" method. + + In this mode, the bitrates differ between the interactive live streaming and communication profiles: + + - `COMMUNICATION` profile: The video bitrate is the same as the base bitrate. + - `LIVE_BROADCASTING` profile: The video bitrate is twice the base bitrate. + + */ +const int STANDARD_BITRATE = 0; + +/** The compatible bitrate set in the \ref IRtcEngine::setVideoEncoderConfiguration "setVideoEncoderConfiguration" method. + + The bitrate remains the same regardless of the channel profile. If you choose this mode in the `LIVE_BROADCASTING` profile, the video frame rate may be lower than the set value. + */ +const int COMPATIBLE_BITRATE = -1; + +/** Use the default minimum bitrate. + */ +const int DEFAULT_MIN_BITRATE = -1; + +/** Video encoder configurations. + */ +struct VideoEncoderConfiguration { + /** The video frame dimensions (px) used to specify the video quality and measured by the total number of pixels along a frame's width and height: VideoDimensions. The default value is 640 x 360. + */ + VideoDimensions dimensions; + /** The frame rate of the video: #FRAME_RATE. The default value is 15. + + Note that we do not recommend setting this to a value greater than 30. + */ + FRAME_RATE frameRate; + /** The minimum frame rate of the video. The default value is -1. + */ + int minFrameRate; + /** The video encoding bitrate (Kbps). + + Choose one of the following options: + + - #STANDARD_BITRATE: (Recommended) The standard bitrate. + - the `COMMUNICATION` profile: the encoding bitrate equals the base bitrate. + - the `LIVE_BROADCASTING` profile: the encoding bitrate is twice the base bitrate. + - #COMPATIBLE_BITRATE: The compatible bitrate: the bitrate stays the same regardless of the profile. + + the `COMMUNICATION` profile prioritizes smoothness, while the `LIVE_BROADCASTING` profile prioritizes video quality (requiring a higher bitrate). We recommend setting the bitrate mode as #STANDARD_BITRATE to address this difference. + + The following table lists the recommended video encoder configurations, where the base bitrate applies to the `COMMUNICATION` profile. Set your bitrate based on this table. If you set a bitrate beyond the proper range, the SDK automatically sets it to within the range. + + @note + In the following table, **Base Bitrate** applies to the `COMMUNICATION` profile, and **Live Bitrate** applies to the `LIVE_BROADCASTING` profile. + + | Resolution | Frame Rate (fps) | Base Bitrate (Kbps) | Live Bitrate (Kbps) | + |------------------------|------------------|----------------------------------------|----------------------------------------| + | 160 * 120 | 15 | 65 | 130 | + | 120 * 120 | 15 | 50 | 100 | + | 320 * 180 | 15 | 140 | 280 | + | 180 * 180 | 15 | 100 | 200 | + | 240 * 180 | 15 | 120 | 240 | + | 320 * 240 | 15 | 200 | 400 | + | 240 * 240 | 15 | 140 | 280 | + | 424 * 240 | 15 | 220 | 440 | + | 640 * 360 | 15 | 400 | 800 | + | 360 * 360 | 15 | 260 | 520 | + | 640 * 360 | 30 | 600 | 1200 | + | 360 * 360 | 30 | 400 | 800 | + | 480 * 360 | 15 | 320 | 640 | + | 480 * 360 | 30 | 490 | 980 | + | 640 * 480 | 15 | 500 | 1000 | + | 480 * 480 | 15 | 400 | 800 | + | 640 * 480 | 30 | 750 | 1500 | + | 480 * 480 | 30 | 600 | 1200 | + | 848 * 480 | 15 | 610 | 1220 | + | 848 * 480 | 30 | 930 | 1860 | + | 640 * 480 | 10 | 400 | 800 | + | 1280 * 720 | 15 | 1130 | 2260 | + | 1280 * 720 | 30 | 1710 | 3420 | + | 960 * 720 | 15 | 910 | 1820 | + | 960 * 720 | 30 | 1380 | 2760 | + | 1920 * 1080 | 15 | 2080 | 4160 | + | 1920 * 1080 | 30 | 3150 | 6300 | + | 1920 * 1080 | 60 | 4780 | 6500 | + + */ + int bitrate; + /** The minimum encoding bitrate (Kbps). + + The SDK automatically adjusts the encoding bitrate to adapt to the network conditions. Using a value greater than the default value forces the video encoder to output high-quality images but may cause more packet loss and hence sacrifice the smoothness of the video transmission. That said, unless you have special requirements for image quality, Agora does not recommend changing this value. + + @note This parameter applies only to the `LIVE_BROADCASTING` profile. + */ + int minBitrate; + /** The video orientation mode of the video: #ORIENTATION_MODE. + */ + ORIENTATION_MODE orientationMode; + /** The video encoding degradation preference under limited bandwidth: #DEGRADATION_PREFERENCE. + */ + DEGRADATION_PREFERENCE degradationPreference; + /** Sets the mirror mode of the published local video stream. It only affects the video that the remote user sees. See #VIDEO_MIRROR_MODE_TYPE + + @note The SDK disables the mirror mode by default. + */ + VIDEO_MIRROR_MODE_TYPE mirrorMode; + + VideoEncoderConfiguration(const VideoDimensions& d, FRAME_RATE f, int b, ORIENTATION_MODE m, VIDEO_MIRROR_MODE_TYPE mr = VIDEO_MIRROR_MODE_AUTO) : dimensions(d), frameRate(f), minFrameRate(-1), bitrate(b), minBitrate(DEFAULT_MIN_BITRATE), orientationMode(m), degradationPreference(MAINTAIN_QUALITY), mirrorMode(mr) {} + VideoEncoderConfiguration(int width, int height, FRAME_RATE f, int b, ORIENTATION_MODE m, VIDEO_MIRROR_MODE_TYPE mr = VIDEO_MIRROR_MODE_AUTO) : dimensions(width, height), frameRate(f), minFrameRate(-1), bitrate(b), minBitrate(DEFAULT_MIN_BITRATE), orientationMode(m), degradationPreference(MAINTAIN_QUALITY), mirrorMode(mr) {} + VideoEncoderConfiguration() : dimensions(640, 480), frameRate(FRAME_RATE_FPS_15), minFrameRate(-1), bitrate(STANDARD_BITRATE), minBitrate(DEFAULT_MIN_BITRATE), orientationMode(ORIENTATION_MODE_ADAPTIVE), degradationPreference(MAINTAIN_QUALITY), mirrorMode(VIDEO_MIRROR_MODE_AUTO) {} +}; + +/** Recording configuration, which is set in + * \ref IRtcEngine::startAudioRecording(const AudioRecordingConfiguration&) "startAudioRecording". + * + * @since v3.4.0 + */ +struct AudioRecordingConfiguration { + /** The absolute path (including the filename extensions) of the recording + * file. For example: `C:\music\audio.aac`. + * + * @note Ensure that the path you specify exists and is writable. + */ + const char* filePath; + /** Audio recording quality. See #AUDIO_RECORDING_QUALITY_TYPE. + * + * @note This parameter applies to AAC files only. + */ + AUDIO_RECORDING_QUALITY_TYPE recordingQuality; + /** Recording content. See #AUDIO_RECORDING_POSITION. + */ + AUDIO_RECORDING_POSITION recordingPosition; + /** Recording sample rate (Hz). The following values are supported: + * + * - `16000` + * - (Default) `32000` + * - `44100` + * - `48000` + * + * @note If this parameter is set to `44100` or `48000`, for better + * recording effects, Agora recommends recording WAV files or AAC files + * whose `recordingQuality` is + * #AUDIO_RECORDING_QUALITY_MEDIUM or #AUDIO_RECORDING_QUALITY_HIGH. + */ + int recordingSampleRate; + AudioRecordingConfiguration() : filePath(nullptr), recordingQuality(AUDIO_RECORDING_QUALITY_MEDIUM), recordingPosition(AUDIO_RECORDING_POSITION_MIXED_RECORDING_AND_PLAYBACK), recordingSampleRate(32000) {} + AudioRecordingConfiguration(const char* path, AUDIO_RECORDING_QUALITY_TYPE quality, AUDIO_RECORDING_POSITION position, int sampleRate) : filePath(path), recordingQuality(quality), recordingPosition(position), recordingSampleRate(sampleRate) {} +}; + +/** The video and audio properties of the user displaying the video in the CDN live. Agora supports a maximum of 17 transcoding users in a CDN streaming channel. + */ +typedef struct TranscodingUser { + /** User ID of the user displaying the video in the CDN live. + */ + uid_t uid; + + /** Horizontal position (pixel) of the video frame relative to the top left corner. + */ + int x; + /** Vertical position (pixel) of the video frame relative to the top left corner. + */ + int y; + /** Width (pixel) of the video frame. The default value is 360. + */ + int width; + /** Height (pixel) of the video frame. The default value is 640. + */ + int height; + + /** The layer index of the video frame. An integer. The value range is [0, 100]. + + - 0: (Default) Bottom layer. + - 100: Top layer. + + @note + - If zOrder is beyond this range, the SDK reports #ERR_INVALID_ARGUMENT. + - As of v2.3, the SDK supports zOrder = 0. + */ + int zOrder; + /** The transparency level of the user's video. The value ranges between 0 and 1.0: + + - 0: Completely transparent + - 1.0: (Default) Opaque + */ + double alpha; + /** The audio channel of the sound. The default value is 0: + + - 0: (Default) Supports dual channels at most, depending on the upstream of the host. + - 1: The audio stream of the host uses the FL audio channel. If the upstream of the host uses multiple audio channels, these channels are mixed into mono first. + - 2: The audio stream of the host uses the FC audio channel. If the upstream of the host uses multiple audio channels, these channels are mixed into mono first. + - 3: The audio stream of the host uses the FR audio channel. If the upstream of the host uses multiple audio channels, these channels are mixed into mono first. + - 4: The audio stream of the host uses the BL audio channel. If the upstream of the host uses multiple audio channels, these channels are mixed into mono first. + - 5: The audio stream of the host uses the BR audio channel. If the upstream of the host uses multiple audio channels, these channels are mixed into mono first. + + @note If your setting is not 0, you may need a specialized player. + */ + int audioChannel; + TranscodingUser() : uid(0), x(0), y(0), width(0), height(0), zOrder(0), alpha(1.0), audioChannel(0) {} + +} TranscodingUser; + +/** Image properties. + + The properties of the watermark and background images. + */ +typedef struct RtcImage { + RtcImage() : url(NULL), x(0), y(0), width(0), height(0) {} + /** HTTP/HTTPS URL address of the image on the live video. The maximum length of this parameter is 1024 bytes. */ + const char* url; + /** Horizontal position of the image from the upper left of the live video. */ + int x; + /** Vertical position of the image from the upper left of the live video. */ + int y; + /** Width of the image on the live video. */ + int width; + /** Height of the image on the live video. */ + int height; +} RtcImage; +/// @cond +/** The configuration for advanced features of the RTMP or RTMPS streaming with transcoding. + */ +typedef struct LiveStreamAdvancedFeature { + LiveStreamAdvancedFeature() : featureName(NULL), opened(false) {} + + /** The advanced feature for high-quality video with a lower bitrate. */ + const char* LBHQ = "lbhq"; + /** The advanced feature for the optimized video encoder. */ + const char* VEO = "veo"; + + /** The name of the advanced feature. It contains LBHQ and VEO. + */ + const char* featureName; + + /** Whether to enable the advanced feature: + * - true: Enable the advanced feature. + * - false: (Default) Disable the advanced feature. + */ + bool opened; +} LiveStreamAdvancedFeature; +/// @endcond +/** A struct for managing CDN live audio/video transcoding settings. + */ +typedef struct LiveTranscoding { + /** The width of the video in pixels. The default value is 360. + * - When pushing video streams to the CDN, the value range of `width` is [64,1920]. + * If the value is less than 64, Agora server automatically adjusts it to 64; if the + * value is greater than 1920, Agora server automatically adjusts it to 1920. + * - When pushing audio streams to the CDN, set `width` and `height` as 0. + */ + int width; + /** The height of the video in pixels. The default value is 640. + * - When pushing video streams to the CDN, the value range of `height` is [64,1080]. + * If the value is less than 64, Agora server automatically adjusts it to 64; if the + * value is greater than 1080, Agora server automatically adjusts it to 1080. + * - When pushing audio streams to the CDN, set `width` and `height` as 0. + */ + int height; + /** Bitrate of the CDN live output video stream. The default value is 400 Kbps. + + Set this parameter according to the Video Bitrate Table. If you set a bitrate beyond the proper range, the SDK automatically adapts it to a value within the range. + */ + int videoBitrate; + /** Frame rate of the output video stream set for the CDN live streaming. The default value is 15 fps, and the value range is (0,30]. + + @note The Agora server adjusts any value over 30 to 30. + */ + int videoFramerate; + + /** **DEPRECATED** Latency mode: + + - true: Low latency with unassured quality. + - false: (Default) High latency with assured quality. + */ + bool lowLatency; + + /** Video GOP in frames. The default value is 30 fps. + */ + int videoGop; + /** Self-defined video codec profile: #VIDEO_CODEC_PROFILE_TYPE. + + @note If you set this parameter to other values, Agora adjusts it to the default value of 100. + */ + VIDEO_CODEC_PROFILE_TYPE videoCodecProfile; + /** The background color in RGB hex value. Value only. Do not include a preceeding #. For example, 0xFFB6C1 (light pink). The default value is 0x000000 (black). + */ + unsigned int backgroundColor; + + /** + * The video codec type of the output video stream. See #VIDEO_CODEC_TYPE_FOR_STREAM. + * + * @since v3.2.0 + */ + VIDEO_CODEC_TYPE_FOR_STREAM videoCodecType; + + /** The number of users in the interactive live streaming. + */ + unsigned int userCount; + /** TranscodingUser + */ + TranscodingUser* transcodingUsers; + /** Reserved property. Extra user-defined information to send SEI for the H.264/H.265 video stream to the CDN live client. Maximum length: 4096 Bytes. + + For more information on SEI frame, see [SEI-related questions](https://docs.agora.io/en/faq/sei). + */ + const char* transcodingExtraInfo; + + /** **DEPRECATED** The metadata sent to the CDN live client defined by the RTMP or HTTP-FLV metadata. + */ + const char* metadata; + /** The watermark image added to the CDN live publishing stream. + + Ensure that the format of the image is PNG. Once a watermark image is added, the audience of the CDN live publishing stream can see the watermark image. See RtcImage. + */ + RtcImage* watermark; + /** The background image added to the CDN live publishing stream. + + Once a background image is added, the audience of the CDN live publishing stream can see the background image. See RtcImage. + */ + RtcImage* backgroundImage; + /** Self-defined audio-sample rate: #AUDIO_SAMPLE_RATE_TYPE. + */ + AUDIO_SAMPLE_RATE_TYPE audioSampleRate; + /** Bitrate of the CDN live audio output stream. The default value is 48 Kbps, and the highest value is 128. + */ + int audioBitrate; + /** The numbder of audio channels for the CDN live stream. Agora recommends choosing 1 (mono), or 2 (stereo) audio channels. Special players are required if you choose option 3, 4, or 5: + + - 1: (Default) Mono. + - 2: Stereo. + - 3: Three audio channels. + - 4: Four audio channels. + - 5: Five audio channels. + */ + int audioChannels; + /** Self-defined audio codec profile: #AUDIO_CODEC_PROFILE_TYPE. + */ + + AUDIO_CODEC_PROFILE_TYPE audioCodecProfile; + /// @cond + /** Advanced features of the RTMP or RTMPS streaming with transcoding. See LiveStreamAdvancedFeature. + * + * @since v3.1.0 + */ + LiveStreamAdvancedFeature* advancedFeatures; + + /** The number of enabled advanced features. The default value is 0. */ + unsigned int advancedFeatureCount; + /// @endcond + LiveTranscoding() : width(360), height(640), videoBitrate(400), videoFramerate(15), lowLatency(false), videoGop(30), videoCodecProfile(VIDEO_CODEC_PROFILE_HIGH), backgroundColor(0x000000), videoCodecType(VIDEO_CODEC_H264_FOR_STREAM), userCount(0), transcodingUsers(NULL), transcodingExtraInfo(NULL), metadata(NULL), watermark(NULL), backgroundImage(NULL), audioSampleRate(AUDIO_SAMPLE_RATE_48000), audioBitrate(48), audioChannels(1), audioCodecProfile(AUDIO_CODEC_PROFILE_LC_AAC), advancedFeatures(NULL), advancedFeatureCount(0) {} +} LiveTranscoding; + +/** Camera capturer configuration. + */ +struct CameraCapturerConfiguration { + /** Camera capturer preference settings. See: #CAPTURER_OUTPUT_PREFERENCE. */ + CAPTURER_OUTPUT_PREFERENCE preference; + /** The width (px) of the video image captured by the local camera. + * To customize the width of the video image, set `preference` as #CAPTURER_OUTPUT_PREFERENCE_MANUAL (3) first, + * and then use `captureWidth`. + * + * @since v3.3.0 + */ + int captureWidth; + /** The height (px) of the video image captured by the local camera. + * To customize the height of the video image, set `preference` as #CAPTURER_OUTPUT_PREFERENCE_MANUAL (3) first, + * and then use `captureHeight`. + * + * @since v3.3.0 + */ + int captureHeight; +#if defined(__ANDROID__) || (defined(__APPLE__) && TARGET_OS_IOS) + /** Camera direction settings (for Android/iOS only). See: #CAMERA_DIRECTION. */ + CAMERA_DIRECTION cameraDirection; +#endif + + CameraCapturerConfiguration() : preference(CAPTURER_OUTPUT_PREFERENCE_AUTO), captureWidth(640), captureHeight(480) {} + + CameraCapturerConfiguration(int width, int height) : preference(CAPTURER_OUTPUT_PREFERENCE_MANUAL), captureWidth(width), captureHeight(height) {} +}; +/** The configurations for the data stream. + * + * @since v3.3.0 + * + * |`syncWithAudio` |`ordered`| SDK behaviors| + * |--------------|--------|-------------| + * | false | false |The SDK triggers the `onStreamMessage` callback immediately after the receiver receives a data packet | + * | true | false |

        If the data packet delay is within the audio delay, the SDK triggers the `onStreamMessage` callback when the synchronized audio packet is played out.

        If the data packet delay exceeds the audio delay, the SDK triggers the `onStreamMessage` callback as soon as the data packet is received. In this case, the data packet is not synchronized with the audio packet.

        | + * | false | true |

        If the delay of a data packet is within five seconds, the SDK corrects the order of the data packet.

        If the delay of a data packet exceeds five seconds, the SDK discards the data packet.

        | + * | true | true |

        If the delay of a data packet is within the audio delay, the SDK corrects the order of the data packet.

        If the delay of a data packet exceeds the audio delay, the SDK discards this data packet.

        | + */ +struct DataStreamConfig { + /** Whether to synchronize the data packet with the published audio packet. + * + * - true: Synchronize the data packet with the audio packet. + * - false: Do not synchronize the data packet with the audio packet. + * + * When you set the data packet to synchronize with the audio, then if the data + * packet delay is within the audio delay, the SDK triggers the `onStreamMessage` callback when + * the synchronized audio packet is played out. Do not set this parameter as `true` if you + * need the receiver to receive the data packet immediately. Agora recommends that you set + * this parameter to `true` only when you need to implement specific functions, for example + * lyric synchronization. + */ + bool syncWithAudio; + /** Whether the SDK guarantees that the receiver receives the data in the sent order. + * + * - true: Guarantee that the receiver receives the data in the sent order. + * - false: Do not guarantee that the receiver receives the data in the sent order. + * + * Do not set this parameter to `true` if you need the receiver to receive the data immediately. + */ + bool ordered; +}; +/** Configuration of the injected media stream. + */ +struct InjectStreamConfig { + /** Width of the injected stream in the interactive live streaming. The default value is 0 (same width as the original stream). + */ + int width; + /** Height of the injected stream in the interactive live streaming. The default value is 0 (same height as the original stream). + */ + int height; + /** Video GOP (in frames) of the injected stream in the interactive live streaming. The default value is 30 fps. + */ + int videoGop; + /** Video frame rate of the injected stream in the interactive live streaming. The default value is 15 fps. + */ + int videoFramerate; + /** Video bitrate of the injected stream in the interactive live streaming. The default value is 400 Kbps. + + @note The setting of the video bitrate is closely linked to the resolution. If the video bitrate you set is beyond a reasonable range, the SDK sets it within a reasonable range. + */ + int videoBitrate; + /** Audio-sample rate of the injected stream in the interactive live streaming: #AUDIO_SAMPLE_RATE_TYPE. The default value is 48000 Hz. + + @note We recommend setting the default value. + */ + AUDIO_SAMPLE_RATE_TYPE audioSampleRate; + /** Audio bitrate of the injected stream in the interactive live streaming. The default value is 48. + + @note We recommend setting the default value. + */ + int audioBitrate; + /** Audio channels in the interactive live streaming. + + + - 1: (Default) Mono + - 2: Two-channel stereo + + @note We recommend setting the default value. + */ + int audioChannels; + + // width / height default set to 0 means pull the stream with its original resolution + InjectStreamConfig() : width(0), height(0), videoGop(30), videoFramerate(15), videoBitrate(400), audioSampleRate(AUDIO_SAMPLE_RATE_48000), audioBitrate(48), audioChannels(1) {} +}; +/** The definition of ChannelMediaInfo. + */ +struct ChannelMediaInfo { + /** The channel name. + */ + const char* channelName; + /** The token that enables the user to join the channel. + */ + const char* token; + /** The user ID. + */ + uid_t uid; +}; + +/** The definition of ChannelMediaRelayConfiguration. + */ +struct ChannelMediaRelayConfiguration { + /** Pointer to the information of the source channel: ChannelMediaInfo. It contains the following members: + * - `channelName`: The name of the source channel. The default value is `NULL`, which means the SDK applies the name of the current channel. + * - `uid`: The unique ID to identify the relay stream in the source channel. The default value is 0, which means the SDK generates a random UID. You must set it as 0. + * - `token`: The token for joining the source channel. It is generated with the `channelName` and `uid` you set in `srcInfo`. + * - If you have not enabled the App Certificate, set this parameter as the default value `NULL`, which means the SDK applies the App ID. + * - If you have enabled the App Certificate, you must use the `token` generated with the `channelName` and `uid`, and the `uid` must be set as 0. + */ + ChannelMediaInfo* srcInfo; + /** Pointer to the information of the destination channel: ChannelMediaInfo. It contains the following members: + * - `channelName`: The name of the destination channel. + * - `uid`: The unique ID to identify the relay stream in the destination channel. The value ranges from 0 to (232-1). + * To avoid UID conflicts, this `uid` must be different from any other UIDs in the destination channel. The default + * value is 0, which means the SDK generates a random UID. Do not set this parameter as the `uid` of the host in + * the destination channel, and ensure that this `uid` is different from any other `uid` in the channel. + * - `token`: The token for joining the destination channel. It is generated with the `channelName` and `uid` you set in `destInfos`. + * - If you have not enabled the App Certificate, set this parameter as the default value `NULL`, which means the SDK applies the App ID. + * - If you have enabled the App Certificate, you must use the `token` generated with the `channelName` and `uid`. + */ + ChannelMediaInfo* destInfos; + /** The number of destination channels. The default value is 0, and the + * value range is [0,4]. Ensure that the value of this parameter + * corresponds to the number of ChannelMediaInfo structs you define in + * `destInfos`. + */ + int destCount; + + ChannelMediaRelayConfiguration() : srcInfo(nullptr), destInfos(nullptr), destCount(0) {} +}; + +/** **DEPRECATED** Lifecycle of the CDN live video stream. + */ +enum RTMP_STREAM_LIFE_CYCLE_TYPE { + /** Bind to the channel lifecycle. If all hosts leave the channel, the CDN live streaming stops after 30 seconds. + */ + RTMP_STREAM_LIFE_CYCLE_BIND2CHANNEL = 1, + /** Bind to the owner of the RTMP stream. If the owner leaves the channel, the CDN live streaming stops immediately. + */ + RTMP_STREAM_LIFE_CYCLE_BIND2OWNER = 2, +}; + +/** Content hints for screen sharing. + */ +enum VideoContentHint { + /** (Default) No content hint. + */ + CONTENT_HINT_NONE, + /** Motion-intensive content. Choose this option if you prefer smoothness or when you are sharing a video clip, movie, or video game. + */ + CONTENT_HINT_MOTION, + /** Motionless content. Choose this option if you prefer sharpness or when you are sharing a picture, PowerPoint slide, or text. + */ + CONTENT_HINT_DETAILS +}; + +/** The relative location of the region to the screen or window. + */ +struct Rectangle { + /** The horizontal offset from the top-left corner. + */ + int x; + /** The vertical offset from the top-left corner. + */ + int y; + /** The width of the region. + */ + int width; + /** The height of the region. + */ + int height; + + Rectangle() : x(0), y(0), width(0), height(0) {} + Rectangle(int xx, int yy, int ww, int hh) : x(xx), y(yy), width(ww), height(hh) {} +}; + +/** **DEPRECATED** Definition of the rectangular region. */ +typedef struct Rect { + /** Y-axis of the top line. + */ + int top; + /** X-axis of the left line. + */ + int left; + /** Y-axis of the bottom line. + */ + int bottom; + /** X-axis of the right line. + */ + int right; + + Rect() : top(0), left(0), bottom(0), right(0) {} + Rect(int t, int l, int b, int r) : top(t), left(l), bottom(b), right(r) {} +} Rect; + +/** The options of the watermark image to be added. */ +typedef struct WatermarkOptions { + /** Sets whether or not the watermark image is visible in the local video preview: + * - true: (Default) The watermark image is visible in preview. + * - false: The watermark image is not visible in preview. + */ + bool visibleInPreview; + /** + * The watermark position in the landscape mode. See Rectangle. + * For detailed information on the landscape mode, see the advanced guide *Video Rotation*. + */ + Rectangle positionInLandscapeMode; + /** + * The watermark position in the portrait mode. See Rectangle. + * For detailed information on the portrait mode, see the advanced guide *Video Rotation*. + */ + Rectangle positionInPortraitMode; + + WatermarkOptions() : visibleInPreview(true), positionInLandscapeMode(0, 0, 0, 0), positionInPortraitMode(0, 0, 0, 0) {} +} WatermarkOptions; + +/** Screen sharing encoding parameters. + */ +struct ScreenCaptureParameters { + /** The maximum encoding dimensions of the shared region in terms of width * height. + + The default value is 1920 * 1080 pixels, that is, 2073600 pixels. Agora uses the value of this parameter to calculate the charges. + + If the aspect ratio is different between the encoding dimensions and screen dimensions, Agora applies the following algorithms for encoding. Suppose the encoding dimensions are 1920 x 1080: + + - If the value of the screen dimensions is lower than that of the encoding dimensions, for example, 1000 * 1000, the SDK uses 1000 * 1000 for encoding. + - If the value of the screen dimensions is higher than that of the encoding dimensions, for example, 2000 * 1500, the SDK uses the maximum value under 1920 * 1080 with the aspect ratio of the screen dimension (4:3) for encoding, that is, 1440 * 1080. + */ + VideoDimensions dimensions; + /** The frame rate (fps) of the shared region. + + The default value is 5. We do not recommend setting this to a value greater than 15. + */ + int frameRate; + /** The bitrate (Kbps) of the shared region. + + The default value is 0 (the SDK works out a bitrate according to the dimensions of the current screen). + */ + int bitrate; + /** Sets whether to capture the mouse for screen sharing: + + - true: (Default) Capture the mouse. + - false: Do not capture the mouse. + */ + bool captureMouseCursor; + /** Whether to bring the window to the front when calling \ref IRtcEngine::startScreenCaptureByWindowId "startScreenCaptureByWindowId" to share the window: + * - true: Bring the window to the front. + * - false: (Default) Do not bring the window to the front. + */ + bool windowFocus; + /** A list of IDs of windows to be blocked. + * + * When calling \ref IRtcEngine::startScreenCaptureByScreenRect "startScreenCaptureByScreenRect" to start screen sharing, you can use this parameter to block the specified windows. + * When calling \ref IRtcEngine::updateScreenCaptureParameters "updateScreenCaptureParameters" to update the configuration for screen sharing, you can use this parameter to dynamically block the specified windows during screen sharing. + */ + view_t* excludeWindowList; + /** The number of windows to be blocked. + */ + int excludeWindowCount; + + ScreenCaptureParameters() : dimensions(1920, 1080), frameRate(5), bitrate(STANDARD_BITRATE), captureMouseCursor(true), windowFocus(false), excludeWindowList(NULL), excludeWindowCount(0) {} + ScreenCaptureParameters(const VideoDimensions& d, int f, int b, bool c, bool focus, view_t* ex = NULL, int cnt = 0) : dimensions(d), frameRate(f), bitrate(b), captureMouseCursor(c), windowFocus(focus), excludeWindowList(ex), excludeWindowCount(cnt) {} + ScreenCaptureParameters(int width, int height, int f, int b, bool c, bool focus, view_t* ex = NULL, int cnt = 0) : dimensions(width, height), frameRate(f), bitrate(b), captureMouseCursor(c), windowFocus(focus), excludeWindowList(ex), excludeWindowCount(cnt) {} +}; + +/** Video display settings of the VideoCanvas class. + */ +struct VideoCanvas { + /** Video display window (view). + */ + view_t view; + /** The rendering mode of the video view. See #RENDER_MODE_TYPE + */ + int renderMode; + /** The unique channel name for the AgoraRTC session in the string format. The string length must be less than 64 bytes. Supported character scopes are: + - All lowercase English letters: a to z. + - All uppercase English letters: A to Z. + - All numeric characters: 0 to 9. + - The space character. + - Punctuation characters and other symbols, including: "!", "#", "$", "%", "&", "(", ")", "+", "-", ":", ";", "<", "=", ".", ">", "?", "@", "[", "]", "^", "_", " {", "}", "|", "~", ",". + + @note + - The default value is the empty string "". Use the default value if the user joins the channel using the \ref IRtcEngine::joinChannel "joinChannel" method in the IRtcEngine class. The `VideoCanvas` struct defines the video canvas of the user in the channel. + - If the user joins the channel using the \ref IRtcEngine::joinChannel "joinChannel" method in the IChannel class, set this parameter as the `channelId` of the `IChannel` object. The `VideoCanvas` struct defines the video canvas of the user in the channel with the specified channel ID. + */ + char channelId[MAX_CHANNEL_ID_LENGTH]; + /** The user ID. */ + uid_t uid; + void* priv; // private data (underlying video engine denotes it) + /** The mirror mode of the video view. See VIDEO_MIRROR_MODE_TYPE + @note + - For the mirror mode of the local video view: If you use a front camera, the SDK enables the mirror mode by default; if you use a rear camera, the SDK disables the mirror mode by default. + - For the mirror mode of the remote video view: The SDK disables the mirror mode by default. + */ + VIDEO_MIRROR_MODE_TYPE mirrorMode; + + VideoCanvas() : view(NULL), renderMode(RENDER_MODE_HIDDEN), uid(0), priv(NULL), mirrorMode(VIDEO_MIRROR_MODE_AUTO) { channelId[0] = '\0'; } + VideoCanvas(view_t v, int m, uid_t u) : view(v), renderMode(m), uid(u), priv(NULL), mirrorMode(VIDEO_MIRROR_MODE_AUTO) { channelId[0] = '\0'; } + VideoCanvas(view_t v, int m, const char* ch, uid_t u) : view(v), renderMode(m), uid(u), priv(NULL), mirrorMode(VIDEO_MIRROR_MODE_AUTO) { + strncpy(channelId, ch, MAX_CHANNEL_ID_LENGTH); + channelId[MAX_CHANNEL_ID_LENGTH - 1] = '\0'; + } + VideoCanvas(view_t v, int rm, uid_t u, VIDEO_MIRROR_MODE_TYPE mm) : view(v), renderMode(rm), uid(u), priv(NULL), mirrorMode(mm) { channelId[0] = '\0'; } + VideoCanvas(view_t v, int rm, const char* ch, uid_t u, VIDEO_MIRROR_MODE_TYPE mm) : view(v), renderMode(rm), uid(u), priv(NULL), mirrorMode(mm) { + strncpy(channelId, ch, MAX_CHANNEL_ID_LENGTH); + channelId[MAX_CHANNEL_ID_LENGTH - 1] = '\0'; + } +}; + +/** Image enhancement options. + */ +struct BeautyOptions { + /** The contrast level, used with the @p lightening parameter. + */ + enum LIGHTENING_CONTRAST_LEVEL { + /** Low contrast level. */ + LIGHTENING_CONTRAST_LOW = 0, + /** (Default) Normal contrast level. */ + LIGHTENING_CONTRAST_NORMAL, + /** High contrast level. */ + LIGHTENING_CONTRAST_HIGH + }; + + /** The contrast level, used with the @p lightening parameter. + */ + LIGHTENING_CONTRAST_LEVEL lighteningContrastLevel; + + /** The brightness level. The value ranges from 0.0 (original) to 1.0. */ + float lighteningLevel; + + /** The sharpness level. The value ranges between 0 (original) and 1. This parameter is usually used to remove blemishes. + */ + float smoothnessLevel; + + /** The redness level. The value ranges between 0 (original) and 1. This parameter adjusts the red saturation level. + */ + float rednessLevel; + + BeautyOptions(LIGHTENING_CONTRAST_LEVEL contrastLevel, float lightening, float smoothness, float redness) : lighteningLevel(lightening), smoothnessLevel(smoothness), rednessLevel(redness), lighteningContrastLevel(contrastLevel) {} + + BeautyOptions() : lighteningLevel(0), smoothnessLevel(0), rednessLevel(0), lighteningContrastLevel(LIGHTENING_CONTRAST_NORMAL) {} +}; + +/** The custom background image. + * + * @since v3.4.5 + */ +struct VirtualBackgroundSource { + /** The type of the custom background image. + * + * @since v3.4.5 + */ + enum BACKGROUND_SOURCE_TYPE { + /** + * 1: (Default) The background image is a solid color. + */ + BACKGROUND_COLOR = 1, + /** + * The background image is a file in PNG or JPG format. + */ + BACKGROUND_IMG, + /** + * The background image is blurred. + * + * @since v3.5.1 + */ + BACKGROUND_BLUR, + }; + + /** + * The degree of blurring applied to the custom background image. + * + * @since v3.5.1 + */ + enum BACKGROUND_BLUR_DEGREE { + /** + * 1: The degree of blurring applied to the custom background image is low. + * The user can almost see the background clearly. + */ + BLUR_DEGREE_LOW = 1, + /** + * The degree of blurring applied to the custom background image is medium. + * It is difficult for the user to recognize details in the background. + */ + BLUR_DEGREE_MEDIUM, + /** + * (Default) The degree of blurring applied to the custom background image is high. + * The user can barely see any distinguishing features in the background. + */ + BLUR_DEGREE_HIGH, + }; + + /** The type of the custom background image. See #BACKGROUND_SOURCE_TYPE. + */ + BACKGROUND_SOURCE_TYPE background_source_type; + + /** + * The color of the custom background image. The format is a hexadecimal integer defined by RGB, without the # sign, + * such as 0xFFB6C1 for light pink. The default value is 0xFFFFFF, which signifies white. The value range + * is [0x000000,0xFFFFFF]. If the value is invalid, the SDK replaces the original background image with a white + * background image. + * + * @note This parameter takes effect only when the type of the custom background image is `BACKGROUND_COLOR`. + */ + unsigned int color; + + /** + * The local absolute path of the custom background image. PNG and JPG formats are supported. If the path is invalid, + * the SDK replaces the original background image with a white background image. + * + * @note This parameter takes effect only when the type of the custom background image is `BACKGROUND_IMG`. + */ + const char* source; + + /** + * The degree of blurring applied to the custom background image. See #BACKGROUND_BLUR_DEGREE. + * + * @note This parameter takes effect only when the type of the custom background image is `BACKGROUND_BLUR`. + * + * @since v3.5.1 + */ + BACKGROUND_BLUR_DEGREE blur_degree; + + VirtualBackgroundSource() : color(0xffffff), source(NULL), background_source_type(BACKGROUND_COLOR), blur_degree(BLUR_DEGREE_HIGH) {} +}; + +/** + * The UserInfo struct. + */ +struct UserInfo { + /** + * The user ID. + */ + uid_t uid; + /** + * The user account. + */ + char userAccount[MAX_USER_ACCOUNT_LENGTH]; + UserInfo() : uid(0) { userAccount[0] = '\0'; } +}; +/** + * The configuration of the audio and video call loop test. + * + * @since v3.5.2 + */ +struct EchoTestConfiguration { + /** + * The view used to render the local user's video. This parameter is only applicable to scenarios testing video + * devices, that is, when `enableVideo` is `true`. + */ + view_t view; + /** + * Whether to enable the audio device for the call loop test: + * - true: (Default) Enables the audio device. To test the audio device, set this parameter as `true`. + * - false: Disables the audio device. + */ + bool enableAudio; + /** + * Whether to enable the video device for the call loop test: + * - true: (Default) Enables the video device. To test the video device, set this parameter as `true`. + * - false: Disables the video device. + */ + bool enableVideo; + /** + * The token used to secure the audio and video call loop test. If you do not enable App Certificate in Agora + * Console, you do not need to pass a value in this parameter; if you have enabled App Certificate in Agora Console, + * you must pass a token in this parameter, the `uid` used when you generate the token must be 0xFFFFFFFF, and the + * channel name used must be the channel name that identifies each audio and video call loop tested. For server-side + * token generation, see [Authenticate Your Users with Tokens](https://docs.agora.io/en/Interactive%20Broadcast/token_server?platform=All%20Platforms). + */ + const char* token; + /** + * The channel name that identifies each audio and video call loop. To ensure proper loop test functionality, the + * channel name passed in to identify each loop test cannot be the same when users of the same project (App ID) + * perform audio and video call loop tests on different devices. + */ + const char* channelId; + EchoTestConfiguration() : view(NULL), enableAudio(true), enableVideo(true), token(NULL), channelId(NULL) {} + EchoTestConfiguration(view_t v, bool ea, bool ev, const char* t, const char* c) : view(v), enableAudio(ea), enableVideo(ev), token(t), channelId(c) {} +}; + +/** + * Regions for connetion. + */ +enum AREA_CODE { + /** + * Mainland China. + */ + AREA_CODE_CN = 0x00000001, + /** + * North America. + */ + AREA_CODE_NA = 0x00000002, + /** + * Europe. + */ + AREA_CODE_EU = 0x00000004, + /** + * Asia, excluding Mainland China. + */ + AREA_CODE_AS = 0x00000008, + /** + * Japan. + */ + AREA_CODE_JP = 0x00000010, + /** + * India. + */ + AREA_CODE_IN = 0x00000020, + /** + * (Default) Global. + */ + AREA_CODE_GLOB = 0xFFFFFFFF +}; + +enum ENCRYPTION_CONFIG { + /** + * - 1: Force set master key and mode; + * - 0: Not force set, checking whether encryption plugin exists + */ + ENCRYPTION_FORCE_SETTING = (1 << 0), + /** + * - 1: Force not encrypting packet; + * - 0: Not force encrypting; + */ + ENCRYPTION_FORCE_DISABLE_PACKET = (1 << 1) +}; +/// @cond +typedef int ContentInspectType; +/** + * (Default) content inspect type invalid + */ +const ContentInspectType kContentInspectInvalid = 0; +/** + * Content inspect type moderation + */ +const ContentInspectType kContentInspectModeration = 1; +/** + * Content inspect type supervise + */ +const ContentInspectType kContentInspectSupervise = 2; + +enum MAX_CONTENT_INSPECT_MODULE_TYPE { + /** The maximum count of content inspect feature type is 32. + */ + MAX_CONTENT_INSPECT_MODULE_COUNT = 32 +}; +/// @endcond +/// @cond +/** Definition of ContentInspectModule. + */ +struct ContentInspectModule { + /** + * The content inspect module type. + * the module type can be 0 to 31. + * kContentInspectInvalid(0) + * kContentInspectModeration(1) + * kContentInspectSupervise(2) + */ + ContentInspectType type; + /**The content inspect frequency, default is 0 second. + * the frequency <= 0 is invalid. + */ + int interval; + /**The content inspect default value. + */ + ContentInspectModule() { + type = kContentInspectInvalid; + interval = 0; + } +}; +/// @endcond +/// @cond +/** Definition of ContentInspectConfig. + */ +struct ContentInspectConfig { + /** The extra information, max lenght of extraInfo is 1024. + * The extra information will send to server with content(image). + */ + const char* extraInfo; + /**The content inspect modules, max length of modules is 32. + * the content(snapshot of send video stream, image) can be used to max of 32 types functions. + */ + ContentInspectModule modules[MAX_CONTENT_INSPECT_MODULE_COUNT]; + /**The content inspect module count. + */ + int moduleCount; + + ContentInspectConfig() : extraInfo(NULL), moduleCount(0) {} +}; +/// @endcond + +/** Definition of IPacketObserver. + */ +class IPacketObserver { + public: + /** Definition of Packet. + */ + struct Packet { + /** Buffer address of the sent or received data. + * + * @note Agora recommends that the value of buffer is more than 2048 bytes, + * otherwise, you may meet undefined behaviors such as a crash. + */ + const unsigned char* buffer; + /** Buffer size of the sent or received data. + */ + unsigned int size; + }; + /** Occurs when the local user sends an audio packet. + + @param packet The sent audio packet. See Packet. + @return + - true: The audio packet is sent successfully. + - false: The audio packet is discarded. + */ + virtual bool onSendAudioPacket(Packet& packet) = 0; + /** Occurs when the local user sends a video packet. + + @param packet The sent video packet. See Packet. + @return + - true: The video packet is sent successfully. + - false: The video packet is discarded. + */ + virtual bool onSendVideoPacket(Packet& packet) = 0; + /** Occurs when the local user receives an audio packet. + + @param packet The received audio packet. See Packet. + @return + - true: The audio packet is received successfully. + - false: The audio packet is discarded. + */ + virtual bool onReceiveAudioPacket(Packet& packet) = 0; + /** Occurs when the local user receives a video packet. + + @param packet The received video packet. See Packet. + @return + - true: The video packet is received successfully. + - false: The video packet is discarded. + */ + virtual bool onReceiveVideoPacket(Packet& packet) = 0; +}; + +#if defined(_WIN32) +/** The capture type of the custom video source. + */ +enum VIDEO_CAPTURE_TYPE { + /** Unknown type. + */ + VIDEO_CAPTURE_UNKNOWN, + /** (Default) Video captured by the camera. + */ + VIDEO_CAPTURE_CAMERA, + /** Video for screen sharing. + */ + VIDEO_CAPTURE_SCREEN, +}; + +/** The IVideoFrameConsumer class. The SDK uses it to receive the video frame that you capture. + */ +class IVideoFrameConsumer { + public: + /** Receives the raw video frame. + * + * @note Ensure that the video frame type that you specify in this method is the same as that in the \ref agora::rtc::IVideoSource::getBufferType "getBufferType" callback. + * + * @param buffer The video buffer. + * @param frameType The video frame type. See \ref agora::media::ExternalVideoFrame::VIDEO_PIXEL_FORMAT "VIDEO_PIXEL_FORMAT". + * @param width The width (px) of the video frame. + * @param height The height (px) of the video frame. + * @param rotation The angle (degree) at which the video frame rotates clockwise. If you set the rotation angle, the + * SDK rotates the video frame after receiving it. You can set the rotation angle as `0`, `90`, `180`, and `270`. + * @param timestamp The Unix timestamp (ms) of the video frame. You must set a timestamp for each video frame. + */ + virtual void consumeRawVideoFrame(const unsigned char* buffer, agora::media::ExternalVideoFrame::VIDEO_PIXEL_FORMAT frameType, int width, int height, int rotation, long timestamp) = 0; +}; + +/** The IVideoSource class. You can use it to customize the video source. + */ +class IVideoSource { + public: + /** Notification for initializing the custom video source. + * + * The SDK triggers this callback to remind you to initialize the custom video source. After receiving this callback, + * you can do some preparation, such as enabling the camera, and then use the return value to tell the SDK whether the + * custom video source is prepared. + * + * @param consumer An IVideoFrameConsumer object that the SDK passes to you. You need to reserve this object and use it + * to send the video frame to the SDK once the custom video source is started. See IVideoFrameConsumer. + * + * @return + * - true: The custom video source is initialized. + * - false: The custom video source is not ready or fails to initialize. The SDK stops and reports the error. + */ + virtual bool onInitialize(IVideoFrameConsumer* consumer) = 0; + + /** Notification for disabling the custom video source. + * + * The SDK triggers this callback to remind you to disable the custom video source device. This callback tells you + * that the SDK is about to release the IVideoFrameConsumer object. Ensure that you no longer use IVideoFrameConsumer + * after receiving this callback. + */ + virtual void onDispose() = 0; + + /** Notification for starting the custom video source. + * + * The SDK triggers this callback to remind you to start the custom video source for capturing video. The SDK uses + * IVideoFrameConsumer to receive the video frame that you capture after the video source is started. You must use + * the return value to tell the SDK whether the custom video source is started. + * + * @return + * - true: The custom video source is started. + * - false: The custom video source fails to start. The SDK stops and reports the error. + */ + virtual bool onStart() = 0; + + /** Notification for stopping capturing video. + * + * The SDK triggers this callback to remind you to stop capturing video. This callback tells you that the SDK is about + * to stop using IVideoFrameConsumer to receive the video frame that you capture. + */ + virtual void onStop() = 0; + + /** Gets the video frame type. + * + * Before you initialize the custom video source, the SDK triggers this callback to query the video frame type. You + * must specify the video frame type in the return value and then pass it to the SDK. + * + * @note Ensure that the video frame type that you specify in this callback is the same as that in the \ref agora::rtc::IVideoFrameConsumer::consumeRawVideoFrame "consumeRawVideoFrame" method. + * + * @return \ref agora::media::ExternalVideoFrame::VIDEO_PIXEL_FORMAT "VIDEO_PIXEL_FORMAT" + */ + virtual agora::media::ExternalVideoFrame::VIDEO_PIXEL_FORMAT getBufferType() = 0; + /** Gets the capture type of the custom video source. + * + * Before you initialize the custom video source, the SDK triggers this callback to query the capture type of the video source. + * You must specify the capture type in the return value and then pass it to the SDK. The SDK enables the corresponding video + * processing algorithm according to the capture type after receiving the video frame. + * + * @return #VIDEO_CAPTURE_TYPE + */ + virtual VIDEO_CAPTURE_TYPE getVideoCaptureType() = 0; + /** Gets the content hint of the custom video source. + * + * If you specify the custom video source as a screen-sharing video, the SDK triggers this callback to query the + * content hint of the video source before you initialize the video source. You must specify the content hint in the + * return value and then pass it to the SDK. The SDK enables the corresponding video processing algorithm according + * to the content hint after receiving the video frame. + * + * @return \ref agora::rtc::VideoContentHint "VideoContentHint" + */ + virtual VideoContentHint getVideoContentHint() = 0; +}; +#endif + +#if (defined(__APPLE__) && TARGET_OS_MAC && !TARGET_OS_IPHONE) +/** + * The target size of the thumbnail or icon. (macOS only) + * + * @since v3.5.2 + */ +struct SIZE { + /** The target width (px) of the thumbnail or icon. The default value is 0. + */ + int width; + /** The target height (px) of the thumbnail or icon. The default value is 0. + */ + int height; + + SIZE() : width(0), height(0) {} + SIZE(int w, int h) : width(w), height(h) {} +}; +#endif +/** + * The image content of the thumbnail or icon. + * + * @since v3.5.2 + * + * @note The default image is in the RGBA format. If you need to use another format, you need to convert the image on + * your own. + */ +struct ThumbImageBuffer { + /** + * The buffer of the thumbnail or icon. + */ + const char* buffer; + /** + * The buffer length (bytes) of the thumbnail or icon. + */ + unsigned int length; + /** + * The actual width (px) of the thumbnail or icon. + */ + unsigned int width; + /** + * The actual height (px) of the thumbnail or icon. + */ + unsigned int height; + ThumbImageBuffer() : buffer(nullptr), length(0), width(0), height(0) {} +}; +/** + * The type of the shared target. + * + * @since v3.5.2 + */ +enum ScreenCaptureSourceType { + /** + * -1: Unknown type. + */ + ScreenCaptureSourceType_Unknown = -1, + /** + * 0: The shared target is a window. + */ + ScreenCaptureSourceType_Window = 0, + /** + * 1: The shared target is a screen of a particular monitor. + */ + ScreenCaptureSourceType_Screen = 1, + /** + * 2: Reserved parameter. + */ + ScreenCaptureSourceType_Custom = 2, +}; +/** + * The information about the specified shareable window or screen. + * + * @since v3.5.2 + */ +struct ScreenCaptureSourceInfo { + /** + * The type of the shared target. See \ref agora::rtc::ScreenCaptureSourceType "ScreenCaptureSourceType". + */ + ScreenCaptureSourceType type; + /** + * The window ID for a window or the display ID for a screen. + */ + view_t sourceId; + /** + * The name of the window or screen. UTF-8 encoding. + */ + const char* sourceName; + /** + * The image content of the thumbnail. See ThumbImageBuffer. + */ + ThumbImageBuffer thumbImage; + /** + * The image content of the icon. See ThumbImageBuffer. + */ + ThumbImageBuffer iconImage; + /** + * The process to which the window belongs. UTF-8 encoding. + */ + const char* processPath; + /** + * The title of the window. UTF-8 encoding. + */ + const char* sourceTitle; + /** + * Determines whether the screen is the primary display: + * - true: The screen is the primary display. + * - false: The screen is not the primary display. + */ + bool primaryMonitor; + ScreenCaptureSourceInfo() : type(ScreenCaptureSourceType_Unknown), sourceId(nullptr), sourceName(nullptr), processPath(nullptr), sourceTitle(nullptr), primaryMonitor(false) {} +}; +/** + * The IScreenCaptureSourceList class. + * + * @since v3.5.2 + */ +class IScreenCaptureSourceList { + protected: + virtual ~IScreenCaptureSourceList(){}; + + public: + /** + * Gets the number of shareable windows and screens. + * + * @since v3.5.2 + * + * @return The number of shareable windows and screens. + */ + virtual unsigned int getCount() = 0; + /** + * Gets information about the specified shareable window or screen. + * + * @since v3.5.2 + * + * After you get IScreenCaptureSourceList, you can pass in the index value of the specified shareable window or + * screen to get information about that window or screen from ScreenCaptureSourceInfo. + * + * @param index The index of the specified shareable window or screen. The value range is [0,`getCount()`). + * + * @return ScreenCaptureSourceInfo + */ + virtual ScreenCaptureSourceInfo getSourceInfo(unsigned int index) = 0; + /** + * Releases IScreenCaptureSourceList. + * + * @since v3.5.2 + * + * After you get the list of shareable windows and screens, to avoid memory leaks, call `release` to release + * `IScreenCaptureSourceList` instead of deleting `IScreenCaptureSourceList` directly. + */ + virtual void release() = 0; +}; + +/** The SDK uses the IRtcEngineEventHandler interface class to send callbacks to the application. The application inherits the methods of this interface class to retrieve these callbacks. + + All methods in this interface class have default (empty) implementations. Therefore, the application can only inherit some required events. In the callbacks, avoid time-consuming tasks or calling blocking APIs, such as the SendMessage method. Otherwise, the SDK may not work properly. + */ +class IRtcEngineEventHandler { + public: + virtual ~IRtcEngineEventHandler() {} + + /** Reports a warning during SDK runtime. + + In most cases, the application can ignore the warning reported by the SDK because the SDK can usually fix the issue and resume running. For example, when losing connection with the server, the SDK may report #WARN_LOOKUP_CHANNEL_TIMEOUT and automatically try to reconnect. + + @param warn Warning code: #WARN_CODE_TYPE. + @param msg Pointer to the warning message. + */ + virtual void onWarning(int warn, const char* msg) { + (void)warn; + (void)msg; + } + + /** Reports an error during SDK runtime. + + In most cases, the SDK cannot fix the issue and resume running. The SDK requires the application to take action or informs the user about the issue. + + For example, the SDK reports an #ERR_START_CALL error when failing to initialize a call. The application informs the user that the call initialization failed and invokes the \ref IRtcEngine::leaveChannel "leaveChannel" method to leave the channel. + + @param err Error code: #ERROR_CODE_TYPE. + @param msg Pointer to the error message. + */ + virtual void onError(int err, const char* msg) { + (void)err; + (void)msg; + } + + /** Occurs when a user joins a channel. + + This callback notifies the application that a user joins a specified channel when the application calls the \ref IRtcEngine::joinChannel "joinChannel" method. + + The channel name assignment is based on @p channelName specified in the \ref IRtcEngine::joinChannel "joinChannel" method. + + If the @p uid is not specified in the *joinChannel* method, the server automatically assigns a @p uid. + + @param channel Pointer to the channel name. + @param uid User ID of the user joining the channel. + @param elapsed Time elapsed (ms) from the user calling the \ref IRtcEngine::joinChannel "joinChannel" method until the SDK triggers this callback. + */ + virtual void onJoinChannelSuccess(const char* channel, uid_t uid, int elapsed) { + (void)channel; + (void)uid; + (void)elapsed; + } + + /** Occurs when a user rejoins the channel after disconnection due to network problems. + + When a user loses connection with the server because of network problems, the SDK automatically tries to reconnect and triggers this callback upon reconnection. + + @param channel Pointer to the channel name. + @param uid User ID of the user rejoining the channel. + @param elapsed Time elapsed (ms) from starting to reconnect until the SDK triggers this callback. + */ + virtual void onRejoinChannelSuccess(const char* channel, uid_t uid, int elapsed) { + (void)channel; + (void)uid; + (void)elapsed; + } + + /** Occurs when a user leaves the channel. + + This callback notifies the application that a user leaves the channel when the application calls the \ref IRtcEngine::leaveChannel "leaveChannel" method. + + The application gets information, such as the call duration and statistics. + + @param stats Pointer to the statistics of the call: RtcStats. + */ + virtual void onLeaveChannel(const RtcStats& stats) { (void)stats; } + + /** Occurs when the user role switches in the interactive live streaming. For example, from a host to an audience or vice versa. + + This callback notifies the application of a user role switch when the application calls the \ref IRtcEngine::setClientRole "setClientRole" method. + + The SDK triggers this callback when the local user switches the user role by calling the \ref agora::rtc::IRtcEngine::setClientRole "setClientRole" method after joining the channel. + @param oldRole Role that the user switches from: #CLIENT_ROLE_TYPE. + @param newRole Role that the user switches to: #CLIENT_ROLE_TYPE. + */ + virtual void onClientRoleChanged(CLIENT_ROLE_TYPE oldRole, CLIENT_ROLE_TYPE newRole) {} + + /** Occurs when a remote user (`COMMUNICATION`)/ host (`LIVE_BROADCASTING`) joins the channel. + + - `COMMUNICATION` profile: This callback notifies the application that another user joins the channel. If other users are already in the channel, the SDK also reports to the application on the existing users. + - `LIVE_BROADCASTING` profile: This callback notifies the application that the host joins the channel. If other hosts are already in the channel, the SDK also reports to the application on the existing hosts. We recommend limiting the number of hosts to 17. + + The SDK triggers this callback under one of the following circumstances: + - A remote user/host joins the channel by calling the \ref agora::rtc::IRtcEngine::joinChannel "joinChannel" method. + - A remote user switches the user role to the host by calling the \ref agora::rtc::IRtcEngine::setClientRole "setClientRole" method after joining the channel. + - A remote user/host rejoins the channel after a network interruption. + - The host injects an online media stream into the channel by calling the \ref agora::rtc::IRtcEngine::addInjectStreamUrl "addInjectStreamUrl" method. + + @note In the `LIVE_BROADCASTING` profile: + - The host receives this callback when another host joins the channel. + - The audience in the channel receives this callback when a new host joins the channel. + - When a web application joins the channel, the SDK triggers this callback as long as the web application publishes streams. + + @param uid User ID of the user or host joining the channel. + @param elapsed Time delay (ms) from the local user calling the \ref IRtcEngine::joinChannel "joinChannel" method until the SDK triggers this callback. + */ + virtual void onUserJoined(uid_t uid, int elapsed) { + (void)uid; + (void)elapsed; + } + + /** Occurs when a remote user (`COMMUNICATION`)/ host (`LIVE_BROADCASTING`) leaves the channel. + + Reasons why the user is offline: + + - Leave the channel: When the user/host leaves the channel, the user/host sends a goodbye message. When the message is received, the SDK assumes that the user/host leaves the channel. + - Drop offline: When no data packet of the user or host is received for a certain period of time, the SDK assumes that the user/host drops offline. Unreliable network connections may lead to false detections, so we recommend using the Agora RTM SDK for more reliable offline detection. + + @param uid User ID of the user leaving the channel or going offline. + @param reason Reason why the user is offline: #USER_OFFLINE_REASON_TYPE. + */ + virtual void onUserOffline(uid_t uid, USER_OFFLINE_REASON_TYPE reason) { + (void)uid; + (void)reason; + } + + /** Reports the last mile network quality of the local user once every two seconds before the user joins the channel. + + Last mile refers to the connection between the local device and Agora's edge server. After the application calls the \ref IRtcEngine::enableLastmileTest "enableLastmileTest" method, this callback reports once every two seconds the uplink and downlink last mile network conditions of the local user before the user joins the channel. + + @param quality The last mile network quality: #QUALITY_TYPE. + */ + virtual void onLastmileQuality(int quality) { (void)quality; } + + /** Reports the last-mile network probe result. + + The SDK triggers this callback within 30 seconds after the app calls the \ref agora::rtc::IRtcEngine::startLastmileProbeTest "startLastmileProbeTest" method. + + @param result The uplink and downlink last-mile network probe test result. See LastmileProbeResult. + */ + virtual void onLastmileProbeResult(const LastmileProbeResult& result) { (void)result; } + + /** **DEPRECATED** Occurs when the connection between the SDK and the server is interrupted. + + Deprecated as of v2.3.2. Replaced by the \ref agora::rtc::IRtcEngineEventHandler::onConnectionStateChanged "onConnectionStateChanged(CONNECTION_STATE_RECONNECTING, CONNECTION_CHANGED_INTERRUPTED)" callback. + + The SDK triggers this callback when it loses connection with the server for more than four seconds after the connection is established. + + After triggering this callback, the SDK tries reconnecting to the server. You can use this callback to implement pop-up reminders. + + This callback is different from \ref agora::rtc::IRtcEngineEventHandler::onConnectionLost "onConnectionLost": + - The SDK triggers the \ref agora::rtc::IRtcEngineEventHandler::onConnectionInterrupted "onConnectionInterrupted" callback when it loses connection with the server for more than four seconds after it successfully joins the channel. + - The SDK triggers the \ref agora::rtc::IRtcEngineEventHandler::onConnectionLost "onConnectionLost" callback when it loses connection with the server for more than 10 seconds, whether or not it joins the channel. + + If the SDK fails to rejoin the channel 20 minutes after being disconnected from Agora's edge server, the SDK stops rejoining the channel. + + */ + virtual void onConnectionInterrupted() {} + + /** Occurs when the SDK cannot reconnect to Agora's edge server 10 seconds after its connection to the server is interrupted. + + The SDK triggers this callback when it cannot connect to the server 10 seconds after calling the \ref IRtcEngine::joinChannel "joinChannel" method, whether or not it is in the channel. + + This callback is different from \ref agora::rtc::IRtcEngineEventHandler::onConnectionInterrupted "onConnectionInterrupted": + + - The SDK triggers the \ref agora::rtc::IRtcEngineEventHandler::onConnectionInterrupted "onConnectionInterrupted" callback when it loses connection with the server for more than four seconds after it successfully joins the channel. + - The SDK triggers the \ref agora::rtc::IRtcEngineEventHandler::onConnectionLost "onConnectionLost" callback when it loses connection with the server for more than 10 seconds, whether or not it joins the channel. + + If the SDK fails to rejoin the channel 20 minutes after being disconnected from Agora's edge server, the SDK stops rejoining the channel. + + */ + virtual void onConnectionLost() {} + + /** **DEPRECATED** Deprecated as of v2.3.2. Replaced by the \ref agora::rtc::IRtcEngineEventHandler::onConnectionStateChanged "onConnectionStateChanged(CONNECTION_STATE_FAILED, CONNECTION_CHANGED_BANNED_BY_SERVER)" callback. + + Occurs when your connection is banned by the Agora Server. + */ + virtual void onConnectionBanned() {} + + /** Occurs when a method is executed by the SDK. + + @param err The error code (#ERROR_CODE_TYPE) returned by the SDK when a method call fails. If the SDK returns 0, then the method call is successful. + @param api Pointer to the method executed by the SDK. + @param result Pointer to the result of the method call. + */ + virtual void onApiCallExecuted(int err, const char* api, const char* result) { + (void)err; + (void)api; + (void)result; + } + + /** Occurs when the token expires. + + After a token is specified by calling the \ref IRtcEngine::joinChannel "joinChannel" method, if the SDK losses + connection with the Agora server due to network issues, the token may expire after a certain period of time and a + new token may be required to reconnect to the server. + + Once you receive this callback, generate a new token on your app server, and call + \ref agora::rtc::IRtcEngine::renewToken "renewToken" to pass the new token to the SDK. + */ + virtual void onRequestToken() {} + + /** Occurs when the token expires in 30 seconds. + + The user becomes offline if the token used in the \ref IRtcEngine::joinChannel "joinChannel" method expires. The SDK triggers this callback 30 seconds before the token expires to remind the application to get a new token. Upon receiving this callback, generate a new token on the server and call the \ref IRtcEngine::renewToken "renewToken" method to pass the new token to the SDK. + + @param token The token that expires in 30 seconds. + */ + virtual void onTokenPrivilegeWillExpire(const char* token) { (void)token; } + + /** **DEPRECATED** Reports the statistics of the audio stream from each remote user/host. + + Deprecated as of v2.3.2. Use the \ref agora::rtc::IRtcEngineEventHandler::onRemoteAudioStats "onRemoteAudioStats" callback instead. + + The SDK triggers this callback once every two seconds to report the audio quality of each remote user/host sending an audio stream. If a channel has multiple users/hosts sending audio streams, the SDK triggers this callback as many times. + + @param uid User ID of the speaker. + @param quality Audio quality of the user: #QUALITY_TYPE. + @param delay Time delay (ms) of sending the audio packet from the sender to the receiver, including the time delay of audio sampling pre-processing, transmission, and the jitter buffer. + @param lost Packet loss rate (%) of the audio packet sent from the sender to the receiver. + */ + virtual void onAudioQuality(uid_t uid, int quality, unsigned short delay, unsigned short lost) { + (void)uid; + (void)quality; + (void)delay; + (void)lost; + } + + /** Reports the statistics of the current call. + + The SDK triggers this callback once every two seconds after the user joins the channel. + + @param stats Statistics of the IRtcEngine: RtcStats. + */ + virtual void onRtcStats(const RtcStats& stats) { (void)stats; } + + /** Reports the last mile network quality of each user in the channel once every two seconds. + * + * Last mile refers to the connection between the local device and Agora's edge server. This callback + * reports once every two seconds the last mile network conditions of each user in the channel. If a channel includes + * multiple users, the SDK triggers this callback as many times. + * + * @note `txQuality` is `UNKNOWN` when the user is not sending a stream; `rxQuality` is `UNKNOWN` when the user is not receiving a stream. + * + * @param uid User ID. The network quality of the user with this @p uid is reported. If @p uid is 0, the local network quality is reported. + * @param txQuality Uplink transmission quality rating of the user in terms of the transmission bitrate, packet loss rate, average RTT (Round-Trip Time), and jitter of the uplink network. @p txQuality is a quality rating helping you understand how well the current uplink network conditions can support the selected VideoEncoderConfiguration. For example, a 1000 Kbps uplink network may be adequate for video frames with a resolution of 640 * 480 and a frame rate of 15 fps in the `LIVE_BROADCASTING` profile, but may be inadequate for resolutions higher than 1280 * 720. See #QUALITY_TYPE. + * @param rxQuality Downlink network quality rating of the user in terms of the packet loss rate, average RTT, and jitter of the downlink network. See #QUALITY_TYPE. + */ + virtual void onNetworkQuality(uid_t uid, int txQuality, int rxQuality) { + (void)uid; + (void)txQuality; + (void)rxQuality; + } + + /** Reports the statistics of the local video stream. + * + * The SDK triggers this callback once every two seconds for each + * user/host. If there are multiple users/hosts in the channel, the SDK + * triggers this callback as many times. + * + * @note + * If you have called the + * \ref agora::rtc::IRtcEngine::enableDualStreamMode "enableDualStreamMode" + * method, the \ref onLocalVideoStats() "onLocalVideoStats" callback + * reports the statistics of the high-video + * stream (high bitrate, and high-resolution video stream). + * + * @param stats Statistics of the local video stream. See LocalVideoStats. + */ + virtual void onLocalVideoStats(const LocalVideoStats& stats) { (void)stats; } + + /** Reports the statistics of the video stream from each remote user/host. + * + * The SDK triggers this callback once every two seconds for each remote + * user/host. If a channel includes multiple remote users, the SDK + * triggers this callback as many times. + * + * @param stats Statistics of the remote video stream. See + * RemoteVideoStats. + */ + virtual void onRemoteVideoStats(const RemoteVideoStats& stats) { (void)stats; } + + /** Reports the statistics of the local audio stream. + * + * The SDK triggers this callback once every two seconds. + * + * @param stats The statistics of the local audio stream. + * See LocalAudioStats. + */ + virtual void onLocalAudioStats(const LocalAudioStats& stats) { (void)stats; } + + /** Reports the statistics of the audio stream from each remote user/host. + + This callback replaces the \ref agora::rtc::IRtcEngineEventHandler::onAudioQuality "onAudioQuality" callback. + + The SDK triggers this callback once every two seconds for each remote user/host. If a channel includes multiple remote users, the SDK triggers this callback as many times. + + @param stats Pointer to the statistics of the received remote audio streams. See RemoteAudioStats. + */ + virtual void onRemoteAudioStats(const RemoteAudioStats& stats) { (void)stats; } + + /** Occurs when the local audio state changes. + * This callback indicates the state change of the local audio stream, + * including the state of the audio capturing and encoding, and allows + * you to troubleshoot issues when exceptions occur. + * + * @note + * When the state is #LOCAL_AUDIO_STREAM_STATE_FAILED (3), see the `error` + * parameter for details. + * + * @param state State of the local audio. See #LOCAL_AUDIO_STREAM_STATE. + * @param error The error information of the local audio. + * See #LOCAL_AUDIO_STREAM_ERROR. + */ + virtual void onLocalAudioStateChanged(LOCAL_AUDIO_STREAM_STATE state, LOCAL_AUDIO_STREAM_ERROR error) { + (void)state; + (void)error; + } + + /** Occurs when the remote audio state changes. + * + * This callback indicates the state change of the remote audio stream. + * + * @note This callback can be inaccurate when the number of users (in the `COMMUNICATION` profile) + * or hosts (in the `LIVE_BROADCASTING` profile) in a channel exceeds 17. + * + * @param uid ID of the remote user whose audio state changes. + * @param state State of the remote audio. See #REMOTE_AUDIO_STATE. + * @param reason The reason of the remote audio state change. See #REMOTE_AUDIO_STATE_REASON. + * @param elapsed Time elapsed (ms) from the local user calling the + * \ref IRtcEngine::joinChannel "joinChannel" method until the SDK + * triggers this callback. + */ + virtual void onRemoteAudioStateChanged(uid_t uid, REMOTE_AUDIO_STATE state, REMOTE_AUDIO_STATE_REASON reason, int elapsed) { + (void)uid; + (void)state; + (void)reason; + (void)elapsed; + } + + /** Occurs when the audio publishing state changes. + * + * @since v3.1.0 + * + * This callback indicates the publishing state change of the local audio stream. + * + * @param channel The channel name. + * @param oldState The previous publishing state. For details, see #STREAM_PUBLISH_STATE. + * @param newState The current publishing state. For details, see #STREAM_PUBLISH_STATE. + * @param elapseSinceLastState The time elapsed (ms) from the previous state to the current state. + */ + virtual void onAudioPublishStateChanged(const char* channel, STREAM_PUBLISH_STATE oldState, STREAM_PUBLISH_STATE newState, int elapseSinceLastState) { + (void)channel; + (void)oldState; + (void)newState; + (void)elapseSinceLastState; + } + + /** Occurs when the video publishing state changes. + * + * @since v3.1.0 + * + * This callback indicates the publishing state change of the local video stream. + * + * @param channel The channel name. + * @param oldState The previous publishing state. For details, see #STREAM_PUBLISH_STATE. + * @param newState The current publishing state. For details, see #STREAM_PUBLISH_STATE. + * @param elapseSinceLastState The time elapsed (ms) from the previous state to the current state. + */ + virtual void onVideoPublishStateChanged(const char* channel, STREAM_PUBLISH_STATE oldState, STREAM_PUBLISH_STATE newState, int elapseSinceLastState) { + (void)channel; + (void)oldState; + (void)newState; + (void)elapseSinceLastState; + } + + /** Occurs when the audio subscribing state changes. + * + * @since v3.1.0 + * + * This callback indicates the subscribing state change of a remote audio stream. + * + * @param channel The channel name. + * @param uid The ID of the remote user. + * @param oldState The previous subscribing state. For details, see #STREAM_SUBSCRIBE_STATE. + * @param newState The current subscribing state. For details, see #STREAM_SUBSCRIBE_STATE. + * @param elapseSinceLastState The time elapsed (ms) from the previous state to the current state. + */ + virtual void onAudioSubscribeStateChanged(const char* channel, uid_t uid, STREAM_SUBSCRIBE_STATE oldState, STREAM_SUBSCRIBE_STATE newState, int elapseSinceLastState) { + (void)channel; + (void)uid; + (void)oldState; + (void)newState; + (void)elapseSinceLastState; + } + + /** Occurs when the audio subscribing state changes. + * + * @since v3.1.0 + * + * This callback indicates the subscribing state change of a remote video stream. + * + * @param channel The channel name. + * @param uid The ID of the remote user. + * @param oldState The previous subscribing state. For details, see #STREAM_SUBSCRIBE_STATE. + * @param newState The current subscribing state. For details, see #STREAM_SUBSCRIBE_STATE. + * @param elapseSinceLastState The time elapsed (ms) from the previous state to the current state. + */ + virtual void onVideoSubscribeStateChanged(const char* channel, uid_t uid, STREAM_SUBSCRIBE_STATE oldState, STREAM_SUBSCRIBE_STATE newState, int elapseSinceLastState) { + (void)channel; + (void)uid; + (void)oldState; + (void)newState; + (void)elapseSinceLastState; + } + + /** Reports the volume information of users. + * + * By default, this callback is disabled. You can enable it by calling \ref IRtcEngine::enableAudioVolumeIndication(int, int, bool) "enableAudioVolumeIndication". + * Once this callback is enabled and users send streams in the channel, the SDK triggers the `onAudioVolumeIndication` callback + * at the time interval set in `enableAudioVolumeIndication`. + * + * The SDK triggers two independent `onAudioVolumeIndication` callbacks simultaneously, which separately report the + * volume information of the local user who sends a stream and the remote users (up to three) whose instantaneous + * volumes are the highest. + * + * @note After you enable this callback, calling \ref agora::rtc::IRtcEngine::muteLocalAudioStream "muteLocalAudioStream" + * affects the SDK's behavior as follows: + * - If the local user calls `muteLocalAudioStream`, the SDK stops triggering the local user's callback. + * - 20 seconds after a remote user whose volume is one of the three highest calls `muteLocalAudioStream`, the + * remote users' callback excludes this remote user's information; 20 seconds after all remote users call + * `muteLocalAudioStream`, the SDK stops triggering the remote users' callback. + * + * @param speakers The volume information of users. See AudioVolumeInfo. + * + * An empty speakers array in the callback indicates that no remote user is in the channel or sending a stream at the moment. + * @param speakerNumber Total number of users. + * - In the local user's callback, when the local user sends a stream, `speakerNumber = 1`. + * - In the remote users' callback, the value ranges between 0 and 3. If the number of remote users who send + * streams is greater than or equal to three, `speakerNumber = 3`. + * @param totalVolume Total volume after audio mixing. The value ranges between 0 (lowest volume) and 255 (highest volume). + * - In the local user's callback, totalVolume is the volume of the local user who sends a stream. + * - In the remote users' callback, totalVolume is the sum of the volume of all remote users (up to three) whose + * instantaneous volumes are the highest. + * + * If the user calls \ref IRtcEngine::startAudioMixing(const char*,bool,bool,int,int) "startAudioMixing", `totalVolume` is the sum of + * the voice volume and audio-mixing volume. + */ + virtual void onAudioVolumeIndication(const AudioVolumeInfo* speakers, unsigned int speakerNumber, int totalVolume) { + (void)speakers; + (void)speakerNumber; + (void)totalVolume; + } + + /** Occurs when the most active remote speaker is detected. + + After a successful call of \ref IRtcEngine::enableAudioVolumeIndication(int, int, bool) "enableAudioVolumeIndication", + the SDK continuously detects which remote user has the loudest volume. During the current period, the remote user, + who is detected as the loudest for the most times, is the most active user. + + When the number of user is no less than two and an active speaker exists, the SDK triggers this callback and reports the `uid` of the most active speaker. + - If the most active speaker is always the same user, the SDK triggers this callback only once. + - If the most active speaker changes to another user, the SDK triggers this callback again and reports the `uid` of the new active speaker. + + @param uid The user ID of the most active remote speaker. + */ + virtual void onActiveSpeaker(uid_t uid) { (void)uid; } + + /** **DEPRECATED** Occurs when the video stops playing. + + The application can use this callback to change the configuration of the view (for example, displaying other pictures in the view) after the video stops playing. + + Deprecated as of v2.4.1. Use LOCAL_VIDEO_STREAM_STATE_STOPPED(0) in the \ref agora::rtc::IRtcEngineEventHandler::onLocalVideoStateChanged "onLocalVideoStateChanged" callback instead. + */ + virtual void onVideoStopped() {} + + /** Occurs when the first local video frame is displayed/rendered on the local video view. + + @param width Width (px) of the first local video frame. + @param height Height (px) of the first local video frame. + @param elapsed Time elapsed (ms) from the local user calling the \ref IRtcEngine::joinChannel "joinChannel" method until the SDK triggers this callback. + If you call the \ref IRtcEngine::startPreview "startPreview" method before calling the *joinChannel* method, then @p elapsed is the time elapsed from calling the *startPreview* method until the SDK triggers this callback. + */ + virtual void onFirstLocalVideoFrame(int width, int height, int elapsed) { + (void)width; + (void)height; + (void)elapsed; + } + + /** Occurs when the first video frame is published. + * + * @since v3.1.0 + * + * The SDK triggers this callback under one of the following circumstances: + * - The local client enables the video module and calls \ref IRtcEngine::joinChannel "joinChannel" successfully. + * - The local client calls \ref IRtcEngine::muteLocalVideoStream "muteLocalVideoStream(true)" and \ref IRtcEngine::muteLocalVideoStream "muteLocalVideoStream(false)" in sequence. + * - The local client calls \ref IRtcEngine::disableVideo "disableVideo" and \ref IRtcEngine::enableVideo "enableVideo" in sequence. + * - The local client calls \ref agora::media::IMediaEngine::pushVideoFrame "pushVideoFrame" to successfully push the video frame to the SDK. + * + * @param elapsed The time elapsed (ms) from the local client calling \ref IRtcEngine::joinChannel "joinChannel" until the SDK triggers this callback. + */ + virtual void onFirstLocalVideoFramePublished(int elapsed) { (void)elapsed; } + + /** Occurs when the first remote video frame is received and decoded. + * + * This callback is triggered in either of the following scenarios: + * + * - The remote user joins the channel and sends the video stream. + * - The remote user stops sending the video stream and re-sends it after + * 15 seconds. Reasons for such an interruption include: + * - The remote user leaves the channel. + * - The remote user drops offline. + * - The remote user calls the + * \ref agora::rtc::IRtcEngine::muteLocalVideoStream "muteLocalVideoStream" + * method to stop sending the video stream. + * - The remote user calls the + * \ref agora::rtc::IRtcEngine::disableVideo "disableVideo" method to + * disable video. + * + * The application can configure the user view settings in this callback. + * + * @param uid User ID of the remote user sending the video stream. + * @param width Width (px) of the video stream. + * @param height Height (px) of the video stream. + * @param elapsed Time elapsed (ms) from the local user calling the + * \ref IRtcEngine::joinChannel "joinChannel" method until the SDK + * triggers this callback. + */ + virtual void onFirstRemoteVideoDecoded(uid_t uid, int width, int height, int elapsed) { + (void)uid; + (void)width; + (void)height; + (void)elapsed; + } + + /** Occurs when the first remote video frame is rendered. + The SDK triggers this callback when the first frame of the remote video is displayed in the user's video window. The application can get the time elapsed from a user joining the channel until the first video frame is displayed. + + @param uid User ID of the remote user sending the video stream. + @param width Width (px) of the video frame. + @param height Height (px) of the video stream. + @param elapsed Time elapsed (ms) from the local user calling the \ref IRtcEngine::joinChannel "joinChannel" method until the SDK triggers this callback. + */ + virtual void onFirstRemoteVideoFrame(uid_t uid, int width, int height, int elapsed) { + (void)uid; + (void)width; + (void)height; + (void)elapsed; + } + + /** Occurs when a remote user's audio stream playback pauses/resumes. + * + * The SDK triggers this callback when the remote user stops or resumes sending the audio stream by calling the \ref agora::rtc::IRtcEngine::muteLocalAudioStream "muteLocalAudioStream" method. + * + * @note This callback can be inaccurate when the number of users (in the `COMMUNICATION` profile) + * or hosts (in the `LIVE_BROADCASTING` profile) in a channel exceeds 17. + * + * @param uid User ID of the remote user. + * @param muted Whether the remote user's audio stream is muted/unmuted: + * - true: Muted. + * - false: Unmuted. + */ + virtual void onUserMuteAudio(uid_t uid, bool muted) { + (void)uid; + (void)muted; + } + + /** + * Occurs when a remote user stops or resumes publishing the video stream. + * + * When a remote user calls \ref IRtcEngine::muteLocalVideoStream "muteLocalVideoStream" to + * stop or resume publishing the video stream, the SDK triggers this callback to report the + * state of the remote user's publishing stream to the local user. + * + * @note This callback can be inaccurate when the number of users + * (in the `COMMUNICATION` profile) or hosts (in the `LIVE_BROADCASTING` profile) in a + * channel exceeds 17. + * + * @param uid The user ID of the remote user. + * @param muted Whether the remote user stops publishing the video stream: + * - true: Stop publishing the video stream. + * - false: Publish the video stream. + */ + virtual void onUserMuteVideo(uid_t uid, bool muted) { + (void)uid; + (void)muted; + } + + /** Occurs when a specific remote user enables/disables the video + * module. + * + * Once the video module is disabled, the remote user can only use a + * voice call. The remote user cannot send or receive any video from + * other users. + * + * The SDK triggers this callback when the remote user enables or disables + * the video module by calling the + * \ref agora::rtc::IRtcEngine::enableVideo "enableVideo" or + * \ref agora::rtc::IRtcEngine::disableVideo "disableVideo" method. + * + * @note This callback returns invalid when the number of users in a + * channel exceeds 20. + * + * @param uid User ID of the remote user. + * @param enabled Whether the remote user enables/disables the video + * module: + * - true: Enable. The remote user can enter a video session. + * - false: Disable. The remote user can only enter a voice session, and + * cannot send or receive any video stream. + */ + virtual void onUserEnableVideo(uid_t uid, bool enabled) { + (void)uid; + (void)enabled; + } + + /** Occurs when the audio device state changes. + * + * This callback notifies the application that the system's audio device state is changed. For example, a headset is unplugged from the device. + * + * @param deviceId Pointer to the device ID. + * @param deviceType Device type: #MEDIA_DEVICE_TYPE. + * @param deviceState The state of the device: + * - On macOS: + * - 0: The device is ready for use. + * - 8: The device is not connected. + * - On Windows: #MEDIA_DEVICE_STATE_TYPE. + */ + virtual void onAudioDeviceStateChanged(const char* deviceId, int deviceType, int deviceState) { + (void)deviceId; + (void)deviceType; + (void)deviceState; + } + + /** Occurs when the volume of the playback device, microphone, or application changes. + + @param deviceType Device type: #MEDIA_DEVICE_TYPE. + @param volume Volume of the device. The value ranges between 0 and 255. + @param muted + - true: The audio device is muted. + - false: The audio device is not muted. + */ + virtual void onAudioDeviceVolumeChanged(MEDIA_DEVICE_TYPE deviceType, int volume, bool muted) { + (void)deviceType; + (void)volume; + (void)muted; + } + + /** **DEPRECATED** Occurs when the camera turns on and is ready to capture the video. + + If the camera fails to turn on, fix the error reported in the \ref IRtcEngineEventHandler::onError "onError" callback. + + Deprecated as of v2.4.1. Use #LOCAL_VIDEO_STREAM_STATE_CAPTURING (1) in the \ref agora::rtc::IRtcEngineEventHandler::onLocalVideoStateChanged "onLocalVideoStateChanged" callback instead. + */ + virtual void onCameraReady() {} + + /** Occurs when the camera focus area changes. + + The SDK triggers this callback when the local user changes the camera focus position by calling the setCameraFocusPositionInPreview method. + + @note This callback is for Android and iOS only. + + @param x x coordinate of the changed camera focus area. + @param y y coordinate of the changed camera focus area. + @param width Width of the changed camera focus area. + @param height Height of the changed camera focus area. + */ + virtual void onCameraFocusAreaChanged(int x, int y, int width, int height) { + (void)x; + (void)y; + (void)width; + (void)height; + } +#if defined(__ANDROID__) || (defined(__APPLE__) && TARGET_OS_IOS) + /** + * Reports the face detection result of the local user. Applies to Android and iOS only. + * @since v3.0.1 + * + * Once you enable face detection by calling \ref IRtcEngine::enableFaceDetection "enableFaceDetection"(true), you can get the following information on the local user in real-time: + * - The width and height of the local video. + * - The position of the human face in the local video. + * - The distance between the human face and the device screen. This value is based on the fitting calculation of the local video size and the position of the human face. + * + * @note + * - If the SDK does not detect a face, it reduces the frequency of this callback to reduce power consumption on the local device. + * - The SDK stops triggering this callback when a human face is in close proximity to the screen. + * - On Android, the `distance` value reported in this callback may be slightly different from the actual distance. Therefore, Agora does not recommend using it for + * accurate calculation. + * @param imageWidth The width (px) of the local video. + * @param imageHeight The height (px) of the local video. + * @param vecRectangle The position and size of the human face on the local video: + * - `x`: The x coordinate (px) of the human face in the local video. Taking the top left corner of the captured video as the origin, + * the x coordinate represents the relative lateral displacement of the top left corner of the human face to the origin. + * - `y`: The y coordinate (px) of the human face in the local video. Taking the top left corner of the captured video as the origin, + * the y coordinate represents the relative longitudinal displacement of the top left corner of the human face to the origin. + * - `width`: The width (px) of the human face in the captured video. + * - `height`: The height (px) of the human face in the captured video. + * @param vecDistance The distance (cm) between the human face and the screen. + * @param numFaces The number of faces detected. If the value is 0, it means that no human face is detected. + */ + virtual void onFacePositionChanged(int imageWidth, int imageHeight, Rectangle* vecRectangle, int* vecDistance, int numFaces) { + (void)imageWidth; + (void)imageHeight; + (void)vecRectangle; + (void)vecDistance; + (void)numFaces; + } +#endif + /** Occurs when the camera exposure area changes. + + The SDK triggers this callback when the local user changes the camera exposure position by calling the setCameraExposurePosition method. + + @note This callback is for Android and iOS only. + + @param x x coordinate of the changed camera exposure area. + @param y y coordinate of the changed camera exposure area. + @param width Width of the changed camera exposure area. + @param height Height of the changed camera exposure area. + */ + virtual void onCameraExposureAreaChanged(int x, int y, int width, int height) { + (void)x; + (void)y; + (void)width; + (void)height; + } + + /** Occurs when the audio mixing file playback finishes. + + **DEPRECATED** use onAudioMixingStateChanged instead. + + You can start an audio mixing file playback by calling the \ref IRtcEngine::startAudioMixing(const char*,bool,bool,int,int) "startAudioMixing" method. The SDK triggers this callback when the audio mixing file playback finishes. + + If the *startAudioMixing* method call fails, an error code returns in the \ref IRtcEngineEventHandler::onError "onError" callback. + + */ + virtual void onAudioMixingFinished() {} + + /** Occurs when the state of the local user's music file changes. + * + * @since v3.4.0 + * + * When the playback state of the local user's music file changes, the SDK triggers this callback and + * reports the current playback state and the reason for the change. + * + * @param state The current music file playback state. See #AUDIO_MIXING_STATE_TYPE. + * @param reason The reason for the change of the music file playback state. See #AUDIO_MIXING_REASON_TYPE. + */ + virtual void onAudioMixingStateChanged(AUDIO_MIXING_STATE_TYPE state, AUDIO_MIXING_REASON_TYPE reason) {} + /** Occurs when a remote user starts audio mixing. + + When a remote user calls \ref IRtcEngine::startAudioMixing(const char*,bool,bool,int,int) "startAudioMixing" to play the background music, the SDK reports this callback. + */ + virtual void onRemoteAudioMixingBegin() {} + /** Occurs when a remote user finishes audio mixing. + */ + virtual void onRemoteAudioMixingEnd() {} + + /** + * Reports the information of an audio file. + * + * @since v3.5.1 + * + * After successfully calling \ref IRtcEngine::getAudioFileInfo "getAudioFileInfo", the SDK triggers this + * callback to report the information of the audio file, such as the file path and duration. + * + * @param info The information of an audio file. See AudioFileInfo. + * @param error The information acquisition state. See #AUDIO_FILE_INFO_ERROR. + */ + virtual void onRequestAudioFileInfo(const AudioFileInfo& info, AUDIO_FILE_INFO_ERROR error) {} + + /** Occurs when the local audio effect playback finishes. + + The SDK triggers this callback when the local audio effect file playback finishes. + + @param soundId ID of the local audio effect. Each local audio effect has a unique ID. + */ + virtual void onAudioEffectFinished(int soundId) {} + /// @cond + /** Occurs when AirPlay is connected. + */ + virtual void onAirPlayConnected() {} + /// @endcond + + /** + Occurs when the SDK decodes the first remote audio frame for playback. + + @deprecated v3.0.0 + + This callback is deprecated. Use `onRemoteAudioStateChanged` instead. + + This callback is triggered in either of the following scenarios: + + - The remote user joins the channel and sends the audio stream. + - The remote user stops sending the audio stream and re-sends it after 15 seconds. Reasons for such an interruption include: + - The remote user leaves channel. + - The remote user drops offline. + - The remote user calls the \ref agora::rtc::IRtcEngine::muteLocalAudioStream "muteLocalAudioStream" method to stop sending the local audio stream. + - The remote user calls the \ref agora::rtc::IRtcEngine::disableAudio "disableAudio" method to disable audio. + + @param uid User ID of the remote user sending the audio stream. + @param elapsed Time elapsed (ms) from the local user calling the \ref IRtcEngine::joinChannel "joinChannel" method until the SDK triggers this callback. + */ + virtual void onFirstRemoteAudioDecoded(uid_t uid, int elapsed) AGORA_DEPRECATED_ATTRIBUTE { + (void)uid; + (void)elapsed; + } + + /** Occurs when the video device state changes. + * + * @note On a Windows device with an external camera for video capturing, the video disables once the external camera is unplugged. + * + * @param deviceId Pointer to the device ID of the video device that changes state. + * @param deviceType Device type: #MEDIA_DEVICE_TYPE. + * @param deviceState The state of the device: + * - On macOS: + * - 0: The device is ready for use. + * - 8: The device is not connected. + * - On Windows: #MEDIA_DEVICE_STATE_TYPE. + */ + virtual void onVideoDeviceStateChanged(const char* deviceId, int deviceType, int deviceState) { + (void)deviceId; + (void)deviceType; + (void)deviceState; + } + + /** Occurs when the local video stream state changes. + * + * This callback indicates the state of the local video stream, including camera capturing and video encoding, and allows you to troubleshoot issues when exceptions occur. + * + * The SDK triggers the `onLocalVideoStateChanged(LOCAL_VIDEO_STREAM_STATE_FAILED, LOCAL_VIDEO_STREAM_ERROR_CAPTURE_FAILURE)` callback in the following situations: + * - The application exits to the background, and the system recycles the camera. + * - The camera starts normally, but the captured video is not output for four seconds. + * + * When the camera outputs the captured video frames, if all the video frames are the same for 15 consecutive frames, the SDK triggers the + * `onLocalVideoStateChanged(LOCAL_VIDEO_STREAM_STATE_CAPTURING, LOCAL_VIDEO_STREAM_ERROR_CAPTURE_FAILURE)` callback. Note that the + * video frame duplication detection is only available for video frames with a resolution greater than 200 × 200, a frame rate greater than or equal to 10 fps, + * and a bitrate less than 20 Kbps. + * + * @note For some device models, the SDK will not trigger this callback when the state of the local video changes while the local video capturing device is in use, so you have to make your own timeout judgment. + * + * @param localVideoState State type #LOCAL_VIDEO_STREAM_STATE. + * @param error The detailed error information: #LOCAL_VIDEO_STREAM_ERROR. + */ + virtual void onLocalVideoStateChanged(LOCAL_VIDEO_STREAM_STATE localVideoState, LOCAL_VIDEO_STREAM_ERROR error) { + (void)localVideoState; + (void)error; + } + + /** Occurs when the video size or rotation of a specified user changes. + + @param uid User ID of the remote user or local user (0) whose video size or rotation changes. + @param width New width (pixels) of the video. + @param height New height (pixels) of the video. + @param rotation New rotation of the video [0 to 360). + */ + virtual void onVideoSizeChanged(uid_t uid, int width, int height, int rotation) { + (void)uid; + (void)width; + (void)height; + (void)rotation; + } + /** Occurs when the remote video state changes. + * + * @note This callback can be inaccurate when the number of users (in the `COMMUNICATION` profile) + * or hosts (in the `LIVE_BROADCASTING` profile) in a channel exceeds 17. + * + * @param uid ID of the remote user whose video state changes. + * @param state State of the remote video. See #REMOTE_VIDEO_STATE. + * @param reason The reason of the remote video state change. See #REMOTE_VIDEO_STATE_REASON. + * @param elapsed Time elapsed (ms) from the local user calling the + * \ref agora::rtc::IRtcEngine::joinChannel "joinChannel" method until the + * SDK triggers this callback. + */ + virtual void onRemoteVideoStateChanged(uid_t uid, REMOTE_VIDEO_STATE state, REMOTE_VIDEO_STATE_REASON reason, int elapsed) { + (void)uid; + (void)state; + (void)reason; + (void)elapsed; + } + + /** Occurs when a specified remote user enables/disables the local video + * capturing function. + * + * This callback is only applicable to the scenario when the user only + * wants to watch the remote video without sending any video stream to the + * other user. + * + * The SDK triggers this callback when the remote user resumes or stops + * capturing the video stream by calling the + * \ref agora::rtc::IRtcEngine::enableLocalVideo "enableLocalVideo" method. + * + * @param uid User ID of the remote user. + * @param enabled Whether the specified remote user enables/disables the + * local video capturing function: + * - true: Enable. Other users in the channel can see the video of this + * remote user. + * - false: Disable. Other users in the channel can no longer receive the + * video stream from this remote user, while this remote user can still + * receive the video streams from other users. + */ + virtual void onUserEnableLocalVideo(uid_t uid, bool enabled) { + (void)uid; + (void)enabled; + } + + // virtual void onStreamError(int streamId, int code, int parameter, const char* message, size_t length) {} + /** Occurs when the local user receives the data stream from the remote user within five seconds. + + The SDK triggers this callback when the local user receives the stream message that the remote user sends by calling the \ref agora::rtc::IRtcEngine::sendStreamMessage "sendStreamMessage" method. + @param uid User ID of the remote user sending the message. + @param streamId Stream ID. + @param data Pointer to the data received by the local user. + @param length Length of the data in bytes. + */ + virtual void onStreamMessage(uid_t uid, int streamId, const char* data, size_t length) { + (void)uid; + (void)streamId; + (void)data; + (void)length; + } + + /** Occurs when the local user does not receive the data stream from the remote user within five seconds. + +The SDK triggers this callback when the local user fails to receive the stream message that the remote user sends by calling the \ref agora::rtc::IRtcEngine::sendStreamMessage "sendStreamMessage" method. +@param uid User ID of the remote user sending the message. +@param streamId Stream ID. +@param code Error code: #ERROR_CODE_TYPE. +@param missed Number of lost messages. +@param cached Number of incoming cached messages when the data stream is interrupted. +*/ + virtual void onStreamMessageError(uid_t uid, int streamId, int code, int missed, int cached) { + (void)uid; + (void)streamId; + (void)code; + (void)missed; + (void)cached; + } + + /** Occurs when the media engine loads.*/ + virtual void onMediaEngineLoadSuccess() {} + /** Occurs when the media engine call starts.*/ + virtual void onMediaEngineStartCallSuccess() {} + + /** Reports whether the super resolution feature is successfully enabled. (beta feature) + * + * @since v3.5.1 + * + * After calling \ref IRtcEngine::enableRemoteSuperResolution "enableRemoteSuperResolution", the SDK triggers this + * callback to report whether super resolution is successfully enabled. If it is not successfully enabled, + * use `reason` for troubleshooting. + * + * @param uid The user ID of the remote user. + * @param enabled Whether super resolution is successfully enabled: + * - true: Super resolution is successfully enabled. + * - false: Super resolution is not successfully enabled. + * @param reason The reason why super resolution is not successfully enabled or the message + * that confirms success. See #SUPER_RESOLUTION_STATE_REASON. + * + */ + virtual void onUserSuperResolutionEnabled(uid_t uid, bool enabled, SUPER_RESOLUTION_STATE_REASON reason) { + (void)uid; + (void)enabled; + (void)reason; + } + + /** + * Reports whether the virtual background is successfully enabled. (beta feature) + * + * @since v3.4.5 + * + * After you call \ref IRtcEngine::enableVirtualBackground "enableVirtualBackground", the SDK triggers this callback + * to report whether the virtual background is successfully enabled. + * + * @note If the background image customized in the virtual background is in PNG or JPG format, the triggering of this + * callback is delayed until the image is read. + * + * @param enabled Whether the virtual background is successfully enabled: + * - true: The virtual background is successfully enabled. + * - false: The virtual background is not successfully enabled. + * @param reason The reason why the virtual background is not successfully enabled or the message that confirms + * success. See #VIRTUAL_BACKGROUND_SOURCE_STATE_REASON. + */ + virtual void onVirtualBackgroundSourceEnabled(bool enabled, VIRTUAL_BACKGROUND_SOURCE_STATE_REASON reason) { + (void)enabled; + (void)reason; + } + /// @cond + /** Reports result of Content Inspect*/ + virtual void onContentInspectResult(CONTENT_INSPECT_RESULT result) { (void)result; } + /// @endcond + /** + * Reports the result of taking a video snapshot. + * + * @since v3.5.2 + * + * After a successful \ref IRtcEngine::takeSnapshot "takeSnapshot" method call, the SDK triggers this callback to + * report whether the snapshot is successfully taken as well as the details for the snapshot taken. + * + * @param channel The channel name. + * @param uid The user ID of the user. A `uid` of 0 indicates the local user. + * @param filePath The local path of the snapshot. + * @param width The width (px) of the snapshot. + * @param height The height (px) of the snapshot. + * @param errCode The message that confirms success or the reason why the snapshot is not successfully taken: + * - `0`: Success. + * - < 0: Failure: + * - `-1`: The SDK fails to write data to a file or encode a JPEG image. + * - `-2`: The SDK does not find the video stream of the specified user within one second after + * the \ref IRtcEngine::takeSnapshot "takeSnapshot" method call succeeds. + */ + virtual void onSnapshotTaken(const char* channel, uid_t uid, const char* filePath, int width, int height, int errCode) { + (void)channel; + (void)uid; + (void)filePath; + (void)width; + (void)height; + (void)errCode; + } + + /** Occurs when the state of the media stream relay changes. + * + * The SDK returns the state of the current media relay with any error + * message. + * + * @param state The state code in #CHANNEL_MEDIA_RELAY_STATE. + * @param code The error code in #CHANNEL_MEDIA_RELAY_ERROR. + */ + virtual void onChannelMediaRelayStateChanged(CHANNEL_MEDIA_RELAY_STATE state, CHANNEL_MEDIA_RELAY_ERROR code) {} + + /** Reports events during the media stream relay. + * + * @param code The event code in #CHANNEL_MEDIA_RELAY_EVENT. + */ + virtual void onChannelMediaRelayEvent(CHANNEL_MEDIA_RELAY_EVENT code) {} + + /** Occurs when the engine sends the first local audio frame. + + @deprecated Deprecated as of v3.1.0. Use the \ref IRtcEngineEventHandler::onFirstLocalAudioFramePublished "onFirstLocalAudioFramePublished" callback instead. + + @param elapsed Time elapsed (ms) from the local user calling \ref IRtcEngine::joinChannel "joinChannel" until the SDK triggers this callback. + */ + virtual void onFirstLocalAudioFrame(int elapsed) AGORA_DEPRECATED_ATTRIBUTE { (void)elapsed; } + + /** Occurs when the first audio frame is published. + * + * @since v3.1.0 + * + * The SDK triggers this callback under one of the following circumstances: + * - The local client enables the audio module and calls \ref IRtcEngine::joinChannel "joinChannel" successfully. + * - The local client calls \ref IRtcEngine::muteLocalAudioStream "muteLocalAudioStream(true)" and \ref IRtcEngine::muteLocalAudioStream "muteLocalAudioStream(false)" in sequence. + * - The local client calls \ref IRtcEngine::disableAudio "disableAudio" and \ref IRtcEngine::enableAudio "enableAudio" in sequence. + * - The local client calls \ref agora::media::IMediaEngine::pushAudioFrame "pushAudioFrame" to successfully push the video frame to the SDK. + * + * @param elapsed The time elapsed (ms) from the local client calling \ref IRtcEngine::joinChannel "joinChannel" until the SDK triggers this callback. + */ + virtual void onFirstLocalAudioFramePublished(int elapsed) { (void)elapsed; } + + /** Occurs when the engine receives the first audio frame from a specific remote user. + + @deprecated v3.0.0 + + This callback is deprecated. Use `onRemoteAudioStateChanged` instead. + + @param uid User ID of the remote user. + @param elapsed Time elapsed (ms) from the remote user calling \ref IRtcEngine::joinChannel "joinChannel" until the SDK triggers this callback. + */ + virtual void onFirstRemoteAudioFrame(uid_t uid, int elapsed) AGORA_DEPRECATED_ATTRIBUTE { + (void)uid; + (void)elapsed; + } + + /** + Occurs when the state of the RTMP or RTMPS streaming changes. + + The SDK triggers this callback to report the result of the local user calling the \ref agora::rtc::IRtcEngine::addPublishStreamUrl "addPublishStreamUrl" or \ref agora::rtc::IRtcEngine::removePublishStreamUrl "removePublishStreamUrl" method. + + This callback indicates the state of the RTMP or RTMPS streaming. When exceptions occur, you can troubleshoot issues by referring to the detailed error descriptions in the *errCode* parameter. + + @param url The CDN streaming URL. + @param state The RTMP or RTMPS streaming state. See: #RTMP_STREAM_PUBLISH_STATE. + @param errCode The detailed error information for streaming. See: #RTMP_STREAM_PUBLISH_ERROR. + */ + virtual void onRtmpStreamingStateChanged(const char* url, RTMP_STREAM_PUBLISH_STATE state, RTMP_STREAM_PUBLISH_ERROR errCode) { + (void)url; + (void)state; + (void)errCode; + } + + /** Reports events during the RTMP or RTMPS streaming. + * + * @since v3.1.0 + * + * @param url The RTMP or RTMPS streaming URL. + * @param eventCode The event code. See #RTMP_STREAMING_EVENT + */ + virtual void onRtmpStreamingEvent(const char* url, RTMP_STREAMING_EVENT eventCode) { + (void)url; + (void)eventCode; + } + + /** @deprecated This method is deprecated, use the \ref agora::rtc::IRtcEngineEventHandler::onRtmpStreamingStateChanged "onRtmpStreamingStateChanged" callback instead. + + Reports the result of calling the \ref IRtcEngine::addPublishStreamUrl "addPublishStreamUrl" method. (CDN live only.) + + @param url The CDN streaming URL. + @param error Error code: #ERROR_CODE_TYPE. Main errors include: + - #ERR_OK (0): The publishing succeeds. + - #ERR_FAILED (1): The publishing fails. + - #ERR_INVALID_ARGUMENT (-2): Invalid argument used. If, for example, you did not call \ref agora::rtc::IRtcEngine::setLiveTranscoding "setLiveTranscoding" to configure LiveTranscoding before calling \ref agora::rtc::IRtcEngine::addPublishStreamUrl "addPublishStreamUrl", the SDK reports #ERR_INVALID_ARGUMENT. + - #ERR_TIMEDOUT (-10): The publishing timed out. + - #ERR_ALREADY_IN_USE (-19): The chosen URL address is already in use for CDN live streaming. + - #ERR_ENCRYPTED_STREAM_NOT_ALLOWED_PUBLISH (130): You cannot publish an encrypted stream. + - #ERR_PUBLISH_STREAM_CDN_ERROR (151) + - #ERR_PUBLISH_STREAM_NUM_REACH_LIMIT (152) + - #ERR_PUBLISH_STREAM_NOT_AUTHORIZED (153) + - #ERR_PUBLISH_STREAM_INTERNAL_SERVER_ERROR (154) + - #ERR_PUBLISH_STREAM_FORMAT_NOT_SUPPORTED (156) + */ + virtual void onStreamPublished(const char* url, int error) AGORA_DEPRECATED_ATTRIBUTE { + (void)url; + (void)error; + } + /** @deprecated This method is deprecated, use the \ref agora::rtc::IRtcEngineEventHandler::onRtmpStreamingStateChanged "onRtmpStreamingStateChanged" callback instead. + + Reports the result of calling the \ref agora::rtc::IRtcEngine::removePublishStreamUrl "removePublishStreamUrl" method. (CDN live only.) + + This callback indicates whether you have successfully removed an RTMP or RTMPS stream from the CDN. + + @param url The CDN streaming URL. + */ + virtual void onStreamUnpublished(const char* url) AGORA_DEPRECATED_ATTRIBUTE { (void)url; } + /** Occurs when the publisher's transcoding is updated. + * + * When the `LiveTranscoding` class in the \ref agora::rtc::IRtcEngine::setLiveTranscoding "setLiveTranscoding" method updates, the SDK triggers the `onTranscodingUpdated` callback to report the update information to the local host. + * + * @note If you call the `setLiveTranscoding` method to set the LiveTranscoding class for the first time, the SDK does not trigger the `onTranscodingUpdated` callback. + * + */ + virtual void onTranscodingUpdated() {} + /** Occurs when a voice or video stream URL address is added to the interactive live streaming. + + @warning Agora will soon stop the service for injecting online media streams on the client. If you have not implemented this service, Agora recommends that you do not use it. + + @param url Pointer to the URL address of the externally injected stream. + @param uid User ID. + @param status State of the externally injected stream: #INJECT_STREAM_STATUS. + */ + virtual void onStreamInjectedStatus(const char* url, uid_t uid, int status) { + (void)url; + (void)uid; + (void)status; + } + + /** Occurs when the local audio route changes. + * + * @note This callback applies to Android, iOS and macOS only. + * + * @param routing The current audio routing. See: #AUDIO_ROUTE_TYPE. + */ + virtual void onAudioRouteChanged(AUDIO_ROUTE_TYPE routing) { (void)routing; } + + /** Occurs when the published media stream falls back to an audio-only stream due to poor network conditions or switches back to the video after the network conditions improve. + + If you call \ref IRtcEngine::setLocalPublishFallbackOption "setLocalPublishFallbackOption" and set *option* as #STREAM_FALLBACK_OPTION_AUDIO_ONLY, the SDK triggers this callback when the + published stream falls back to audio-only mode due to poor uplink conditions, or when the audio stream switches back to the video after the uplink network condition improves. + @note If the local stream fallbacks to the audio-only stream, the remote user receives the \ref IRtcEngineEventHandler::onUserMuteVideo "onUserMuteVideo" callback. + + @param isFallbackOrRecover Whether the published stream falls back to audio-only or switches back to the video: + - true: The published stream falls back to audio-only due to poor network conditions. + - false: The published stream switches back to the video after the network conditions improve. + */ + virtual void onLocalPublishFallbackToAudioOnly(bool isFallbackOrRecover) { (void)isFallbackOrRecover; } + + /** Occurs when the remote media stream falls back to audio-only stream + * due to poor network conditions or switches back to the video stream + * after the network conditions improve. + * + * If you call + * \ref IRtcEngine::setRemoteSubscribeFallbackOption + * "setRemoteSubscribeFallbackOption" and set + * @p option as #STREAM_FALLBACK_OPTION_AUDIO_ONLY, the SDK triggers this + * callback when the remote media stream falls back to audio-only mode due + * to poor downlink conditions, or when the remote media stream switches + * back to the video after the downlink network condition improves. + * + * @note Once the remote media stream switches to the low stream due to + * poor network conditions, you can monitor the stream switch between a + * high and low stream in the RemoteVideoStats callback. + * + * @param uid ID of the remote user sending the stream. + * @param isFallbackOrRecover Whether the remotely subscribed media stream + * falls back to audio-only or switches back to the video: + * - true: The remotely subscribed media stream falls back to audio-only + * due to poor network conditions. + * - false: The remotely subscribed media stream switches back to the + * video stream after the network conditions improved. + */ + virtual void onRemoteSubscribeFallbackToAudioOnly(uid_t uid, bool isFallbackOrRecover) { + (void)uid; + (void)isFallbackOrRecover; + } + + /** Reports the transport-layer statistics of each remote audio stream. + * + * @deprecated + * This callback is deprecated and replaced by the + * \ref onRemoteAudioStats() "onRemoteAudioStats" callback. + * + * This callback reports the transport-layer statistics, such as the + * packet loss rate and network time delay, once every two seconds after + * the local user receives an audio packet from a remote user. + * + * @param uid User ID of the remote user sending the audio packet. + * @param delay Network time delay (ms) from the remote user sending the + * audio packet to the local user. + * @param lost Packet loss rate (%) of the audio packet sent from the + * remote user. + * @param rxKBitRate Received bitrate (Kbps) of the audio packet sent + * from the remote user. + */ + virtual void onRemoteAudioTransportStats(uid_t uid, unsigned short delay, unsigned short lost, unsigned short rxKBitRate) AGORA_DEPRECATED_ATTRIBUTE { + (void)uid; + (void)delay; + (void)lost; + (void)rxKBitRate; + } + + /** Reports the transport-layer statistics of each remote video stream. + * + * @deprecated + * This callback is deprecated and replaced by the + * \ref onRemoteVideoStats() "onRemoteVideoStats" callback. + * + * This callback reports the transport-layer statistics, such as the + * packet loss rate and network time delay, once every two seconds after + * the local user receives a video packet from a remote user. + * + * @param uid User ID of the remote user sending the video packet. + * @param delay Network time delay (ms) from the remote user sending the + * video packet to the local user. + * @param lost Packet loss rate (%) of the video packet sent from the + * remote user. + * @param rxKBitRate Received bitrate (Kbps) of the video packet sent + * from the remote user. + */ + virtual void onRemoteVideoTransportStats(uid_t uid, unsigned short delay, unsigned short lost, unsigned short rxKBitRate) AGORA_DEPRECATED_ATTRIBUTE { + (void)uid; + (void)delay; + (void)lost; + (void)rxKBitRate; + } + + /** Occurs when the microphone is enabled/disabled. + * + * @deprecated v2.9.0 + * + * The \ref onMicrophoneEnabled() "onMicrophoneEnabled" callback is + * deprecated. Use #LOCAL_AUDIO_STREAM_STATE_STOPPED (0) or + * #LOCAL_AUDIO_STREAM_STATE_RECORDING (1) in the + * \ref onLocalAudioStateChanged() "onLocalAudioStateChanged" callback + * instead. + * + * The SDK triggers this callback when the local user resumes or stops + * capturing the local audio stream by calling the + * \ref agora::rtc::IRtcEngine::enableLocalAudio "enableLocalAudio" method. + * + * @param enabled Whether the microphone is enabled/disabled: + * - true: Enabled. + * - false: Disabled. + */ + virtual void onMicrophoneEnabled(bool enabled) AGORA_DEPRECATED_ATTRIBUTE { (void)enabled; } + /** Occurs when the connection state between the SDK and the server changes. + + @param state See #CONNECTION_STATE_TYPE. + @param reason See #CONNECTION_CHANGED_REASON_TYPE. + */ + virtual void onConnectionStateChanged(CONNECTION_STATE_TYPE state, CONNECTION_CHANGED_REASON_TYPE reason) { + (void)state; + (void)reason; + } + + /** Occurs when the local network type changes. + + When the network connection is interrupted, this callback indicates whether the interruption is caused by a network type change or poor network conditions. + + @param type See #NETWORK_TYPE. + */ + virtual void onNetworkTypeChanged(NETWORK_TYPE type) { (void)type; } + /** Occurs when the local user successfully registers a user account by calling the \ref agora::rtc::IRtcEngine::registerLocalUserAccount "registerLocalUserAccount" method or joins a channel by calling the \ref agora::rtc::IRtcEngine::joinChannelWithUserAccount "joinChannelWithUserAccount" method.This callback reports the user ID and user account of the local user. + + @param uid The ID of the local user. + @param userAccount The user account of the local user. + */ + virtual void onLocalUserRegistered(uid_t uid, const char* userAccount) { + (void)uid; + (void)userAccount; + } + /** Occurs when the SDK gets the user ID and user account of the remote user. + + After a remote user joins the channel, the SDK gets the UID and user account of the remote user, + caches them in a mapping table object (`userInfo`), and triggers this callback on the local client. + + @param uid The ID of the remote user. + @param info The `UserInfo` object that contains the user ID and user account of the remote user. + */ + virtual void onUserInfoUpdated(uid_t uid, const UserInfo& info) { + (void)uid; + (void)info; + } + /// @cond + /** Reports the result of uploading the SDK log files. + * + * @since v3.3.0 + * + * After the method call of \ref IRtcEngine::uploadLogFile "uploadLogFile", the SDK triggers this callback to report the + * result of uploading the log files. If the upload fails, refer to the `reason` parameter to troubleshoot. + * + * @param requestId The request ID. This request ID is the same as `requestId` returned by \ref IRtcEngine::uploadLogFile "uploadLogFile", + * and you can use `requestId` to match a specific upload with a callback. + * @param success Whether the log files are successfully uploaded. + * - true: Successfully uploads the log files. + * - false: Fails to upload the log files. For details, see the `reason` parameter. + * @param reason The reason for the upload failure. See #UPLOAD_ERROR_REASON. + */ + virtual void onUploadLogResult(const char* requestId, bool success, UPLOAD_ERROR_REASON reason) { + (void)requestId; + (void)success; + (void)reason; + } + /// @endcond +}; + +/** +* Video device collection methods. + + The IVideoDeviceCollection interface class gets the video device information. +*/ +class IVideoDeviceCollection { + protected: + virtual ~IVideoDeviceCollection() {} + + public: + /** Gets the total number of the indexed video devices in the system. + + @return Total number of the indexed video devices: + */ + virtual int getCount() = 0; + + /** Gets a specified piece of information about an indexed video device. + + @param index The specified index of the video device that must be less than the return value of \ref IVideoDeviceCollection::getCount "getCount". + @param deviceName Pointer to the video device name. + @param deviceId Pointer to the video device ID. + @return + - 0: Success. + - < 0: Failure. + */ + virtual int getDevice(int index, char deviceName[MAX_DEVICE_ID_LENGTH], char deviceId[MAX_DEVICE_ID_LENGTH]) = 0; + + /** Sets the device with the device ID. + + @param deviceId Device ID of the device. + @return + - 0: Success. + - < 0: Failure. + */ + virtual int setDevice(const char deviceId[MAX_DEVICE_ID_LENGTH]) = 0; + + /** Releases all IVideoDeviceCollection resources. + */ + virtual void release() = 0; +}; + +/** Video device management methods. + + The IVideoDeviceManager interface class tests the video device interfaces. Instantiate an AVideoDeviceManager class to get an IVideoDeviceManager interface. +*/ +class IVideoDeviceManager { + protected: + virtual ~IVideoDeviceManager() {} + + public: + /** Enumerates the video devices. + + This method returns an IVideoDeviceCollection object including all video devices + in the system. With the IVideoDeviceCollection object, the application can enumerate + the video devices. The application must call the \ref IVideoDeviceCollection::release "release" method to release the returned object after using it. + + @return + - An IVideoDeviceCollection object including all video devices in the system: Success. + - NULL: Failure. + */ + virtual IVideoDeviceCollection* enumerateVideoDevices() = 0; + + /** Starts the video-capture device test. + + This method tests whether the video-capture device works properly. Before calling this method, ensure that you have already called the \ref IRtcEngine::enableVideo "enableVideo" method, and the window handle (*hwnd*) parameter is valid. + + @param hwnd The window handle used to display the screen. + + @return + - 0: Success. + - < 0: Failure. + */ + virtual int startDeviceTest(view_t hwnd) = 0; + + /** Stops the video-capture device test. + + @return + - 0: Success. + - < 0: Failure. + */ + virtual int stopDeviceTest() = 0; + + /** Sets a device with the device ID. + + @param deviceId Pointer to the video-capture device ID. Call the \ref IVideoDeviceManager::enumerateVideoDevices "enumerateVideoDevices" method to get it. + + @note Plugging or unplugging the device does not change the device ID. + + @return + - 0: Success. + - < 0: Failure. + */ + virtual int setDevice(const char deviceId[MAX_DEVICE_ID_LENGTH]) = 0; + + /** Gets the video-capture device that is in use. + + @param deviceId Pointer to the video-capture device ID. + @return + - 0: Success. + - < 0: Failure. + */ + virtual int getDevice(char deviceId[MAX_DEVICE_ID_LENGTH]) = 0; + + /** Releases all IVideoDeviceManager resources. + */ + virtual void release() = 0; +}; + +/** Audio device collection methods. + +The IAudioDeviceCollection interface class gets device-related information. +*/ +class IAudioDeviceCollection { + protected: + virtual ~IAudioDeviceCollection() {} + + public: + /** Gets the total number of audio playback or audio capturing devices. + + @note You must first call the \ref IAudioDeviceManager::enumeratePlaybackDevices "enumeratePlaybackDevices" or \ref IAudioDeviceManager::enumerateRecordingDevices "enumerateRecordingDevices" method before calling this method to return the number of audio playback or audio capturing devices. + + @return Number of audio playback or audio capturing devices. + */ + virtual int getCount() = 0; + + /** Gets a specified piece of information about an indexed audio device. + + @param index The specified index that must be less than the return value of \ref IAudioDeviceCollection::getCount "getCount". + @param deviceName Pointer to the audio device name. + @param deviceId Pointer to the audio device ID. + @return + - 0: Success. + - < 0: Failure. + */ + virtual int getDevice(int index, char deviceName[MAX_DEVICE_ID_LENGTH], char deviceId[MAX_DEVICE_ID_LENGTH]) = 0; + + /** Specifies a device with the device ID. + + @param deviceId Pointer to the device ID of the device. + @return + - 0: Success. + - < 0: Failure. + */ + virtual int setDevice(const char deviceId[MAX_DEVICE_ID_LENGTH]) = 0; + + /** Sets the volume of the application. + + @param volume Application volume. The value ranges between 0 (lowest volume) and 255 (highest volume). + @return + - 0: Success. + - < 0: Failure. + */ + virtual int setApplicationVolume(int volume) = 0; + + /** Gets the volume of the application. + + @param volume Pointer to the application volume. The volume value ranges between 0 (lowest volume) and 255 (highest volume). + + @return + - 0: Success. + - < 0: Failure. + */ + virtual int getApplicationVolume(int& volume) = 0; + + /** Mutes the application. + + @param mute Sets whether to mute/unmute the application: + - true: Mute the application. + - false: Unmute the application. + + @return + - 0: Success. + - < 0: Failure. + */ + virtual int setApplicationMute(bool mute) = 0; + /** Gets the mute state of the application. + + @param mute Pointer to whether the application is muted/unmuted. + - true: The application is muted. + - false: The application is not muted. + + @return + - 0: Success. + - < 0: Failure. + */ + virtual int isApplicationMute(bool& mute) = 0; + + /** Releases all IAudioDeviceCollection resources. + */ + virtual void release() = 0; +}; +/** Audio device management methods. + + The IAudioDeviceManager interface class allows for audio device interface testing. Instantiate an AAudioDeviceManager class to get the IAudioDeviceManager interface. +*/ +class IAudioDeviceManager { + protected: + virtual ~IAudioDeviceManager() {} + + public: + /** Enumerates the audio playback devices. + + This method returns an IAudioDeviceCollection object that includes all audio playback devices in the system. With the IAudioDeviceCollection object, the application can enumerate the audio playback devices. + + @note The application must call the \ref IAudioDeviceCollection::release "release" method to release the returned object after using it. + + @return + - Success: Returns an IAudioDeviceCollection object that includes all audio playback devices in the system. For wireless Bluetooth headset devices with master and slave headsets, the master headset is the playback device. + - Returns NULL: Failure. + */ + virtual IAudioDeviceCollection* enumeratePlaybackDevices() = 0; + + /** Enumerates the audio capturing devices. + + This method returns an IAudioDeviceCollection object that includes all audio capturing devices in the system. With the IAudioDeviceCollection object, the application can enumerate the audio capturing devices. + + @note The application needs to call the \ref IAudioDeviceCollection::release "release" method to release the returned object after using it. + + @return + - Returns an IAudioDeviceCollection object that includes all audio capturing devices in the system: Success. + - Returns NULL: Failure. + */ + virtual IAudioDeviceCollection* enumerateRecordingDevices() = 0; + + /** Sets the audio playback device using the device ID. + + @note Plugging or unplugging the audio device does not change the device ID. + + @param deviceId Device ID of the audio playback device, retrieved by calling the \ref IAudioDeviceManager::enumeratePlaybackDevices "enumeratePlaybackDevices" method. + + @return + - 0: Success. + - < 0: Failure. + */ + virtual int setPlaybackDevice(const char deviceId[MAX_DEVICE_ID_LENGTH]) = 0; + + /** Sets the audio capturing device using the device ID. + + @param deviceId Device ID of the audio capturing device, retrieved by calling the \ref IAudioDeviceManager::enumerateRecordingDevices "enumerateRecordingDevices" method. + + @note Plugging or unplugging the audio device does not change the device ID. + + @return + - 0: Success. + - < 0: Failure. + */ + virtual int setRecordingDevice(const char deviceId[MAX_DEVICE_ID_LENGTH]) = 0; + + /** Starts the audio playback device test. + * + * This method tests if the audio playback device works properly. Once a user starts the test, the SDK plays an + * audio file specified by the user. If the user can hear the audio, the playback device works properly. + * + * After calling this method, the SDK triggers the + * \ref IRtcEngineEventHandler::onAudioVolumeIndication "onAudioVolumeIndication" callback every 100 ms, which + * reports `uid = 1` and the volume of the playback device. + * + * @note + * - Call this method before joining a channel. + * - This method is for Windows and macOS only. + * + * @param testAudioFilePath Pointer to the path of the audio file for the audio playback device test in UTF-8: + * - Supported file formats: wav, mp3, m4a, and aac. + * - Supported file sample rates: 8000, 16000, 32000, 44100, and 48000 Hz. + * + * @return + * - 0: Success, and you can hear the sound of the specified audio file. + * - < 0: Failure. + */ + virtual int startPlaybackDeviceTest(const char* testAudioFilePath) = 0; + + /** Stops the audio playback device test. + + This method stops testing the audio playback device. You must call this method to stop the test after calling the \ref IAudioDeviceManager::startPlaybackDeviceTest "startPlaybackDeviceTest" method. + + @return + - 0: Success. + - < 0: Failure. + */ + virtual int stopPlaybackDeviceTest() = 0; + + /** Sets the volume of the audio playback device. + + @param volume Sets the volume of the audio playback device. The value ranges between 0 (lowest volume) and 255 (highest volume). + @return + - 0: Success. + - < 0: Failure. + */ + virtual int setPlaybackDeviceVolume(int volume) = 0; + + /** Gets the volume of the audio playback device. + + @param volume Pointer to the audio playback device volume. The volume value ranges between 0 (lowest volume) and 255 (highest volume). + @return + - 0: Success. + - < 0: Failure. + */ + virtual int getPlaybackDeviceVolume(int* volume) = 0; + + /** Sets the volume of the microphone. + + @note Ensure that you call this method after joining a channel. + + @param volume Sets the volume of the microphone. The value ranges between 0 (lowest volume) and 255 (highest volume). + @return + - 0: Success. + - < 0: Failure. + */ + virtual int setRecordingDeviceVolume(int volume) = 0; + + /** Gets the volume of the microphone. + + @param volume Pointer to the microphone volume. The volume value ranges between 0 (lowest volume) and 255 (highest volume). + @return + - 0: Success. + - < 0: Failure. + */ + virtual int getRecordingDeviceVolume(int* volume) = 0; + + /** Mutes the audio playback device. + + @param mute Sets whether to mute/unmute the audio playback device: + - true: Mutes. + - false: Unmutes. + + @return + - 0: Success. + - < 0: Failure. + */ + virtual int setPlaybackDeviceMute(bool mute) = 0; + /** Gets the mute status of the audio playback device. + + @param mute Pointer to whether the audio playback device is muted/unmuted. + - true: Muted. + - false: Unmuted. + + @return + - 0: Success. + - < 0: Failure. + */ + virtual int getPlaybackDeviceMute(bool* mute) = 0; + /** Mutes/Unmutes the microphone. + + @param mute Sets whether to mute/unmute the microphone: + - true: Mutes. + - false: Unmutes. + + @return + - 0: Success. + - < 0: Failure. + */ + virtual int setRecordingDeviceMute(bool mute) = 0; + + /** Gets the microphone's mute status. + + @param mute Pointer to whether the microphone is muted/unmuted. + - true: Muted. + - false: Unmuted. + + @return + - 0: Success. + - < 0: Failure. + */ + virtual int getRecordingDeviceMute(bool* mute) = 0; + + /** Starts the audio capturing device test. + + This method tests whether the audio capturing device works properly. + + After calling this method, the SDK triggers the + \ref IRtcEngineEventHandler::onAudioVolumeIndication "onAudioVolumeIndication" callback at the time interval set + in this method, which reports `uid = 0` and the volume of the capturing device. + + @note + - Call this method before joining a channel. + - This method is for Windows and macOS only. + + @param indicationInterval The time interval (ms) at which the `onAudioVolumeIndication` callback returns. We + recommend a setting greater than 200 ms. This value must not be less than 10 ms; otherwise, you can not receive + the `onAudioVolumeIndication` callback. + + @return + - 0: Success. + - < 0: Failure. + */ + virtual int startRecordingDeviceTest(int indicationInterval) = 0; + + /** Stops the audio capturing device test. + + This method stops the audio capturing device test. You must call this method to stop the test after calling the \ref IAudioDeviceManager::startRecordingDeviceTest "startRecordingDeviceTest" method. + + @return + - 0: Success. + - < 0: Failure. + */ + virtual int stopRecordingDeviceTest() = 0; + + /** Gets the audio playback device associated with the device ID. + + @param deviceId Pointer to the ID of the audio playback device. + @return + - 0: Success. + - < 0: Failure. + */ + virtual int getPlaybackDevice(char deviceId[MAX_DEVICE_ID_LENGTH]) = 0; + + /** Gets the audio playback device information associated with the device ID and device name. + + @param deviceId Pointer to the device ID of the audio playback device. + @param deviceName Pointer to the device name of the audio playback device. + @return + - 0: Success. + - < 0: Failure. + */ + virtual int getPlaybackDeviceInfo(char deviceId[MAX_DEVICE_ID_LENGTH], char deviceName[MAX_DEVICE_ID_LENGTH]) = 0; + + /** Gets the audio capturing device associated with the device ID. + + @param deviceId Pointer to the device ID of the audio capturing device. + @return + - 0: Success. + - < 0: Failure. + */ + virtual int getRecordingDevice(char deviceId[MAX_DEVICE_ID_LENGTH]) = 0; + + /** Gets the audio capturing device information associated with the device ID and device name. + + @param deviceId Pointer to the device ID of the audio capturing device. + @param deviceName Pointer to the device name of the audio capturing device. + @return + - 0: Success. + - < 0: Failure. + */ + virtual int getRecordingDeviceInfo(char deviceId[MAX_DEVICE_ID_LENGTH], char deviceName[MAX_DEVICE_ID_LENGTH]) = 0; + + /** Starts the audio device loopback test. + * + * This method tests whether the local audio sampling device and playback device are working properly. After calling + * this method, the audio sampling device samples the local audio, and the audio playback device plays the sampled + * audio. The SDK triggers two independent + * \ref IRtcEngineEventHandler::onAudioVolumeIndication "onAudioVolumeIndication" callbacks at the time interval set + * in this method, which reports the following information: + * - `uid = 0` and the volume information of the sampling device. + * - `uid = 1` and the volume information of the playback device. + * + * @note + * - Call this method before joining a channel. + * - This method tests local audio devices and does not report the network conditions. + * - This method is for Windows and macOS only. + * + * @param indicationInterval The time interval (ms) at which the `onAudioVolumeIndication` callback returns. We + * recommend a setting greater than 200 ms. This value must not be less than 10 ms; otherwise, you can not receive + * the `onAudioVolumeIndication` callback. + * + * @return + * - 0: Success. + * - < 0: Failure. + */ + virtual int startAudioDeviceLoopbackTest(int indicationInterval) = 0; + + /** Stops the audio device loopback test. + + @note Ensure that you call this method to stop the loopback test after calling the \ref IAudioDeviceManager::startAudioDeviceLoopbackTest "startAudioDeviceLoopbackTest" method. + + @return + - 0: Success. + - < 0: Failure. + */ + virtual int stopAudioDeviceLoopbackTest() = 0; + + /** Releases all IAudioDeviceManager resources. + */ + virtual void release() = 0; +}; + +/** The configuration of the log files. + * + * @since v3.3.0 + */ +struct LogConfig { + /** The absolute path of log files. + * + * The default file path is: + * - Android: `/storage/emulated/0/Android/data//files/agorasdk.log` + * - iOS: `App Sandbox/Library/caches/agorasdk.log` + * - macOS: + * - Sandbox enabled: `App Sandbox/Library/Logs/agorasdk.log`, such as `/Users//Library/Containers//Data/Library/Logs/agorasdk.log`. + * - Sandbox disabled: `~/Library/Logs/agorasdk.log`. + * - Windows: `C:\Users\\AppData\Local\Agora\\agorasdk.log` + * + * Ensure that the directory for the log files exists and is writable. You can use this parameter to rename the log files. + */ + const char* filePath; + /** The size (KB) of a log file. The default value is 1024 KB. If you set `fileSize` to 1024 KB, the SDK outputs at most 5 MB log files; + * if you set it to less than 1024 KB, the setting is invalid, and the maximum size of a log file is still 1024 KB. + */ + int fileSize; + /** The output log level of the SDK. See #LOG_LEVEL. + * + * For example, if you set the log level to WARN, the SDK outputs the logs within levels FATAL, ERROR, and WARN. + */ + LOG_LEVEL level; + LogConfig() : filePath(NULL), fileSize(-1), level(LOG_LEVEL::LOG_LEVEL_INFO) {} +}; + +/** Definition of RtcEngineContext. + */ +struct RtcEngineContext { + /** The IRtcEngineEventHandler object. + */ + IRtcEngineEventHandler* eventHandler; + /** + * The App ID issued to you by Agora. See [How to get the App ID](https://docs.agora.io/en/Agora%20Platform/token#get-an-app-id). + * Only users in apps with the same App ID can join the same channel and communicate with each other. Use an App ID to create only + * one `IRtcEngine` instance. To change your App ID, call `release` to destroy the current `IRtcEngine` instance and then call `createAgoraRtcEngine` + * and `initialize` to create an `IRtcEngine` instance with the new App ID. + */ + const char* appId; + // For android, it the context(Activity or Application + // for windows,Video hot plug device + /** The video window handle. Once set, this parameter enables you to plug + * or unplug the video devices while they are powered. + */ + void* context; + /** + * The region for connection. This advanced feature applies to scenarios that have regional restrictions. + * + * For the regions that Agora supports, see #AREA_CODE. The area codes support bitwise operation. + * + * After specifying the region, the SDK connects to the Agora servers within that region. + */ + unsigned int areaCode; + /** The configuration of the log files that the SDK outputs. See LogConfig. + * + * @since v3.3.0 + * + * By default, the SDK outputs five log files, `agorasdk.log`, `agorasdk_1.log`, `agorasdk_2.log`, `agorasdk_3.log`, `agorasdk_4.log`, each with + * a default size of 1024 KB. These log files are encoded in UTF-8. The SDK writes the latest logs in `agorasdk.log`. When `agorasdk.log` is + * full, the SDK deletes the log file with the earliest modification time among the other four, renames `agorasdk.log` to the name of the + * deleted log file, and creates a new `agorasdk.log` to record latest logs. + * + */ + LogConfig logConfig; + RtcEngineContext() : eventHandler(NULL), appId(NULL), context(NULL), areaCode(rtc::AREA_CODE_GLOB) {} +}; + +/** Definition of IMetadataObserver + */ +class IMetadataObserver { + public: + /** Metadata type of the observer. + @note We only support video metadata for now. + */ + enum METADATA_TYPE { + /** -1: the metadata type is unknown. + */ + UNKNOWN_METADATA = -1, + /** 0: the metadata type is video. + */ + VIDEO_METADATA = 0, + }; + + struct Metadata { + /** The User ID. + + - For the receiver: the ID of the user who sent the metadata. + - For the sender: ignore it. + */ + unsigned int uid; + /** Buffer size of the sent or received Metadata. + */ + unsigned int size; + /** Buffer address of the sent or received Metadata. + */ + unsigned char* buffer; + /** Timestamp (ms) of the frame following the metadata. + */ + long long timeStampMs; + }; + + virtual ~IMetadataObserver(){}; + + /** Occurs when the SDK requests the maximum size of the Metadata. + + The metadata includes the following parameters: + - `uid`: ID of the user who sends the metadata. + - `size`: The size of the sent or received metadata. + - `buffer`: The sent or received metadata. + - `timeStampMs`: The timestamp (ms) of the metadata. + + The SDK triggers this callback after you successfully call the \ref agora::rtc::IRtcEngine::registerMediaMetadataObserver "registerMediaMetadataObserver" method. You need to specify the maximum size of the metadata in the return value of this callback. + + @return The maximum size of the buffer of the metadata that you want to use. The highest value is 1024 bytes. Ensure that you set the return value. + */ + virtual int getMaxMetadataSize() = 0; + + /** Occurs when the SDK is ready to receive and send metadata. + + @note Ensure that the size of the metadata does not exceed the value set in the \ref agora::rtc::IMetadataObserver::getMaxMetadataSize "getMaxMetadataSize" callback. + + @param metadata The Metadata to be sent. + @return + - true: Send. + - false: Do not send. + */ + virtual bool onReadyToSendMetadata(Metadata& metadata) = 0; + + /** Occurs when the local user receives the metadata. + + @param metadata The received Metadata. + */ + virtual void onMetadataReceived(const Metadata& metadata) = 0; +}; + +/** Encryption mode. Agora recommends using either the `AES_128_GCM2` or `AES_256_GCM2` + * encryption mode, both of which support adding a salt and are more secure. + */ +enum ENCRYPTION_MODE { + /** 1: 128-bit AES encryption, XTS mode. + */ + AES_128_XTS = 1, + /** 2: 128-bit AES encryption, ECB mode. + */ + AES_128_ECB = 2, + /** 3: 256-bit AES encryption, XTS mode. + */ + AES_256_XTS = 3, + /// @cond + /** 4: 128-bit SM4 encryption, ECB mode. + */ + SM4_128_ECB = 4, + /// @endcond + /** 5: 128-bit AES encryption, GCM mode. + * + * @since v3.3.1 + */ + AES_128_GCM = 5, + /** 6: 256-bit AES encryption, GCM mode. + * + * @since v3.3.1 + */ + AES_256_GCM = 6, + /** 7: (Default) 128-bit AES encryption, GCM mode. Compared to `AES_128_GCM` encryption mode, + * `AES_128_GCM2` encryption mode is more secure and requires you to set the salt (`encryptionKdfSalt`). + * + * @since v3.4.5 + */ + AES_128_GCM2 = 7, + /** 8: 256-bit AES encryption, GCM mode. Compared to `AES_256_GCM` encryption mode, + * `AES_256_GCM2` encryption mode is more secure and requires you to set the salt (`encryptionKdfSalt`). + * + * @since v3.4.5 + */ + AES_256_GCM2 = 8, + /** Enumerator boundary. + */ + MODE_END, +}; + +/** Configurations of built-in encryption schemas. */ +struct EncryptionConfig { + /** + * Encryption mode. The default encryption mode is `AES_128_GCM2`. See #ENCRYPTION_MODE. + */ + ENCRYPTION_MODE encryptionMode; + /** + * Encryption key in string type with unlimited length. Agora recommends using a 32-byte key. + * + * @note If you do not set an encryption key or set it as NULL, you cannot use the built-in encryption, and the SDK returns #ERR_INVALID_ARGUMENT (-2). + */ + const char* encryptionKey; + /** + * The salt with the length of 32 bytes. Agora recommends using OpenSSL to generate the salt on your server. + * For details, see *Media Stream Encryption*. + * + * @note This parameter is only valid when you set the encryption mode as `AES_128_GCM2` or `AES_256_GCM2`. + * In this case, ensure that this parameter is not `0`. + * + * @since v3.4.5 + */ + uint8_t encryptionKdfSalt[32]; + + EncryptionConfig() { + encryptionMode = AES_128_GCM2; + encryptionKey = nullptr; + memset(encryptionKdfSalt, 0, sizeof(encryptionKdfSalt)); + } + + /// @cond + const char* getEncryptionString() const { + switch (encryptionMode) { + case AES_128_XTS: + return "aes-128-xts"; + case AES_128_ECB: + return "aes-128-ecb"; + case AES_256_XTS: + return "aes-256-xts"; + case SM4_128_ECB: + return "sm4-128-ecb"; + case AES_128_GCM: + return "aes-128-gcm"; + case AES_256_GCM: + return "aes-256-gcm"; + case AES_128_GCM2: + return "aes-128-gcm-2"; + case AES_256_GCM2: + return "aes-256-gcm-2"; + default: + return "aes-128-gcm-2"; + } + return "aes-128-gcm-2"; + } + /// @endcond +}; + +/** The channel media options. + */ +struct ChannelMediaOptions { + /** Determines whether to automatically subscribe to all remote audio streams when the user joins a channel: + - true: (Default) Subscribe. + - false: Do not subscribe. + + This member serves a similar function to the `muteAllRemoteAudioStreams` method. After joining the channel, + you can call the `muteAllRemoteAudioStreams` method to set whether to subscribe to audio streams in the channel. + */ + bool autoSubscribeAudio; + /** Determines whether to subscribe to video streams when the user joins the channel: + - true: (Default) Subscribe. + - false: Do not subscribe. + + This member serves a similar function to the `muteAllRemoteVideoStreams` method. After joining the channel, + you can call the `muteAllRemoteVideoStreams` method to set whether to subscribe to video streams in the channel. + */ + bool autoSubscribeVideo; + /** Determines whether to publish the local audio stream when the user joins a channel: + * - true: (Default) Publish. + * - false: Do not publish. + * + * This member serves a similar function to the `muteLocalAudioStream` method. After the user joins + * the channel, you can call the `muteLocalAudioStream` method to set whether to publish the + * local audio stream in the channel. + * + * @since v3.4.5 + */ + bool publishLocalAudio; + /** Determines whether to publish the local video stream when the user joins a channel: + * - true: (Default) Publish. + * - false: Do not publish. + * + * This member serves a similar function to the `muteLocalVideoStream` method. After the user joins + * the channel, you can call the `muteLocalVideoStream` method to set whether to publish the + * local video stream in the channel. + */ + bool publishLocalVideo; + ChannelMediaOptions() : autoSubscribeAudio(true), autoSubscribeVideo(true), publishLocalAudio(true), publishLocalVideo(true) {} +}; +/** + * @since v3.5.0 + * + * The IVideoSink class, which can set up a custom video renderer. + * + * During a real-time audio and video interaction, the Agora SDK enables the default renderer to render local and + * remote video. The IVideoSink class can customize the video renderer. You can implement this interface first, and + * then customize the video renderer that you want by calling + * \ref IRtcEngine::setLocalVideoRenderer "setLocalVideoRenderer" or + * \ref IRtcEngine::setRemoteVideoRenderer "setRemoteVideoRenderer". + */ +class IVideoSink { + public: + /** + * Notification for initializing the custom video renderer. + * + * @since v3.5.0 + * + * The SDK triggers this callback to remind you to initialize the custom video renderer. + * After receiving this callback, you can do some preparation, and then use the return value to tell the SDK + * whether the custom video renderer is prepared. The SDK takes the corresponding behavior based on the return value. + * + * @return + * - true: The custom video renderer is initialized. The SDK is ready to send the video data to be rendered. + * - false: The custom video renderer is not ready or fails to initialize. The SDK reports the error. + */ + virtual bool onInitialize() = 0; + /** + * Notification for starting the custom video source. + * + * @since v3.5.0 + * + * The SDK triggers this callback to remind you to start the custom video source for capturing video. After receiving + * this callback, you can do some preparation, and then use the return value to tell the SDK whether the custom video + * renderer is started. The SDK takes the corresponding behavior based on the return value. + * + * @return + * - true: The custom video renderer is started. The SDK is ready to send the video data to be rendered to the custom video renderer for rendering. + * - false: The custom video renderer is not ready or fails to initialize. The SDK stops and reports the error. + */ + virtual bool onStart() = 0; + /** + * Notification for stopping rendering the video. + * + * @since v3.5.0 + * + * The SDK triggers this callback to remind you to stop rendering the video. This callback informs you that the SDK + * is about to stop sending video data to the custom video renderer. + */ + virtual void onStop() = 0; + /** + * Notification for disabling the custom video renderer. + * + * @since v3.5.0 + * + * The SDK triggers this callback to remind you to disable the custom video renderer. + */ + virtual void onDispose() = 0; + /** + * Gets the video frame type. + * + * @since v3.5.0 + * + * Before you initialize the custom video renderer, the SDK triggers this callback to query the data type of the + * video frame that you want to process. You must specify the data type of the video frame in the return value of + * this callback and then pass it to the SDK. + * + * @return \ref agora::media::ExternalVideoFrame::VIDEO_BUFFER_TYPE "VIDEO_BUFFER_TYPE" + */ + virtual agora::media::ExternalVideoFrame::VIDEO_BUFFER_TYPE getBufferType() = 0; + /** + * Gets the video frame pixel format. + * + * @since v3.5.0 + * + * Before you initialize the custom video renderer, the SDK triggers this callback to query the pixel format of the + * video frame that you want to process. You must specify a pixel format for the video frame in the return value of + * this callback and then pass it to the SDK. + * + * @return \ref agora::media::ExternalVideoFrame::VIDEO_PIXEL_FORMAT "VIDEO_PIXEL_FORMAT" + */ + virtual agora::media::ExternalVideoFrame::VIDEO_PIXEL_FORMAT getPixelFormat() = 0; +#if (defined(__APPLE__) && TARGET_OS_IOS) + /** + * Notification for rendering the video in the pixel data type. + * + * @since v3.5.0 + * + * The SDK triggers this callback after capturing video in the pixel data type to alter the custom video renderer + * to process the video data. + * + * @note This method applies to iOS only. + * + * @param pixelBuffer The video data in the pixel data type. + * @param rotation The clockwise rotation angle of the video. + */ + virtual void onRenderPixelBuffer(CVPixelBufferRef pixelBuffer, int rotation) = 0; +#endif + /** + * Notification for rendering the video in the raw data type. + * + * @since v3.5.0 + * + * The SDK triggers this callback after capturing video in the raw data type to alter the custom video renderer to + * process the video data. + * + * @param rawData The video data in the raw data type. + * @param width The width (px) of the video. + * @param height The height (px) of the video. + * @param rotation The clockwise rotation angle of the video. + */ + virtual void onRenderRawData(uint8_t* rawData, int width, int height, int rotation) = 0; +}; +/** IRtcEngine is the base interface class of the Agora SDK that provides the main Agora SDK methods +invoked by your application. +Enable the Agora SDK's communication functionality through the creation of an IRtcEngine object, then call the methods of this object. + */ +class IRtcEngine { + protected: + virtual ~IRtcEngine() {} + + public: + /** Initializes the Agora service. + * + * Unless otherwise specified, all the methods provided by the IRtcEngine class are executed asynchronously. Agora recommends calling these methods in the same thread. + * + * @note Ensure that you call the + * \ref agora::rtc::IRtcEngine::createAgoraRtcEngine + * "createAgoraRtcEngine" and \ref agora::rtc::IRtcEngine::initialize + * "initialize" methods before calling any other APIs. + * + * @param context Pointer to the RTC engine context. See RtcEngineContext. + * + * @return + * - 0(ERR_OK): Success. + * - < 0: Failure. + * - -1(ERR_FAILED): A general error occurs (no specified reason). + * - -2(ERR_INVALID_ARGUMENT): No `IRtcEngineEventHandler` object is specified. + * - -7(ERR_NOT_INITIALIZED): The SDK is not initialized. Check whether `context` is properly set. + * - -22(ERR_RESOURCE_LIMITED): The resource is limited. The app uses too much of the system resource and fails to allocate any resources. + * - -101(ERR_INVALID_APP_ID): The App ID is invalid. + */ + virtual int initialize(const RtcEngineContext& context) = 0; + + /** Releases all IRtcEngine resources. + * + * Use this method for apps in which users occasionally make voice or video calls. When users do not make calls, you + * can free up resources for other operations. Once you call `release` to destroy the created `IRtcEngine` instance, + * you cannot use any method or callback in the SDK any more. If you want to use the real-time communication functions + * again, you must call \ref createAgoraRtcEngine "createAgoraRtcEngine" and \ref agora::rtc::IRtcEngine::initialize "initialize" + * to create a new `IRtcEngine` instance. + * + * @note If you want to create a new `IRtcEngine` instance after destroying the current one, ensure that you wait + * till the `release` method completes executing. + * + * @param sync + * - true: Synchronous call. Agora suggests calling this method in a sub-thread to avoid congestion in the main thread + * because the synchronous call and the app cannot move on to another task until the execution completes. + * Besides, you **cannot** call this method in any method or callback of the SDK. Otherwise, the SDK cannot release the + * resources occupied by the `IRtcEngine` instance until the callbacks return results, which may result in a deadlock. + * The SDK automatically detects the deadlock and converts this method into an asynchronous call, causing the test to + * take additional time. + * - false: Asynchronous call. Do not immediately uninstall the SDK's dynamic library after the call, or it may cause + * a crash due to the SDK clean-up thread not quitting. + */ + AGORA_CPP_API static void release(bool sync = false); + + /** Sets the channel profile of the Agora IRtcEngine. + * + * After initialization, the SDK uses the `CHANNEL_PROFILE_COMMUNICATION` channel profile by default. + * You can call this method to set the channel profile. The Agora IRtcEngine differentiates channel profiles and + * applies optimization algorithms accordingly. + * For example, it prioritizes smoothness and low latency for a video call, and prioritizes video quality for the interactive live video streaming. + * + * @warning + * - To ensure the quality of real-time communication, we recommend that all users in a channel use the same channel profile. + * - Call this method before calling \ref IRtcEngine::joinChannel "joinChannel" . You cannot set the channel profile once you have joined the channel. + * - The default audio route and video encoding bitrate are different in different channel profiles. For details, see + * \ref IRtcEngine::setDefaultAudioRouteToSpeakerphone "setDefaultAudioRouteToSpeakerphone" and \ref IRtcEngine::setVideoEncoderConfiguration "setVideoEncoderConfiguration". + * + * @param profile The channel profile of the Agora IRtcEngine. See #CHANNEL_PROFILE_TYPE + * @return + * - 0(ERR_OK): Success. + * - < 0: Failure. + * - -2 (ERR_INVALID_ARGUMENT): The parameter is invalid. + * - -7(ERR_NOT_INITIALIZED): The SDK is not initialized. + */ + virtual int setChannelProfile(CHANNEL_PROFILE_TYPE profile) = 0; + + /** Sets the role of the user in interactive live streaming. + * + * After calling \ref IRtcEngine::setChannelProfile "setChannelProfile" (CHANNEL_PROFILE_LIVE_BROADCASTING), the + * SDK sets the user role as audience by default. You can call `setClientRole` to set the user role as host. + * + * You can call this method either before or after joining a channel. If you + * call this method to switch the user role after joining a channel, the SDK automatically does the following: + * - Calls \ref IRtcEngine::muteLocalAudioStream "muteLocalAudioStream" and \ref IRtcEngine::muteLocalVideoStream "muteLocalVideoStream" to + * change the publishing state. + * - Triggers \ref IRtcEngineEventHandler::onClientRoleChanged "onClientRoleChanged" on the local client. + * - Triggers \ref IRtcEngineEventHandler::onUserJoined "onUserJoined" or \ref IRtcEngineEventHandler::onUserOffline "onUserOffline" (BECOME_AUDIENCE) + * on the remote client. + * + * @note This method applies to the `LIVE_BROADCASTING` profile only. + * + * @param role The role of a user in interactive live streaming. See #CLIENT_ROLE_TYPE. + * + * @return + * - 0(ERR_OK): Success. + * - < 0: Failure. + * - -1(ERR_FAILED): A general error occurs (no specified reason). + * - -2(ERR_INVALID_ARGUMENT): The parameter is invalid. + * - -5 (ERR_REFUSED): The request is rejected. In multichannel scenarios, if you have set any of the following in + * one channel, the SDK returns this error code when the user switches the user role to host in another channel: + * - Call `joinChannel` with the `options` parameter and use the default settings `publishLocalAudio = true` or `publishLocalVideo = true`. + * - Call `setClientRole` to set the user role as host. + * - Call `muteLocalAudioStream(false)` or `muteLocalVideoStream(false)`. + * - -7(ERR_NOT_INITIALIZED): The SDK is not initialized. + */ + virtual int setClientRole(CLIENT_ROLE_TYPE role) = 0; + + /** Sets the role of the user in interactive live streaming. + * + * @since v3.2.0 + * + * In the `LIVE_BROADCASTING` channel profile, the + * SDK sets the user role as audience by default. You can call `setClientRole` to set the user role as host. + * + * You can call this method either before or after joining a channel. If you + * call this method to switch the user role after joining a channel, the SDK automatically does the following: + * - Calls \ref IRtcEngine::muteLocalAudioStream "muteLocalAudioStream" and \ref IRtcEngine::muteLocalVideoStream "muteLocalVideoStream" to + * change the publishing state. + * - Triggers \ref IRtcEngineEventHandler::onClientRoleChanged "onClientRoleChanged" on the local client. + * - Triggers \ref IRtcEngineEventHandler::onUserJoined "onUserJoined" or \ref IRtcEngineEventHandler::onUserOffline "onUserOffline" (BECOME_AUDIENCE) + * on the remote client. + * + * @note + * - This method applies to the `LIVE_BROADCASTING` profile only. + * - The difference between this method and \ref IRtcEngine::setClientRole(CLIENT_ROLE_TYPE) "setClientRole" [1/2] is that + * this method can set the user level in addition to the user role. + * - The user role determines the permissions that the SDK grants to a user, such as permission to send local streams, + * receive remote streams, and push streams to a CDN address. + * - The user level determines the level of services that a user can enjoy within the permissions of the user's role. + * For example, an audience member can choose to receive remote streams with low latency or ultra low latency. + * **User level affects the pricing of services.** + * + * @param role The role of a user in interactive live streaming. See #CLIENT_ROLE_TYPE. + * @param options The detailed options of a user, including user level. See ClientRoleOptions. + * + * @return + * - 0(ERR_OK): Success. + * - < 0: Failure. + * - -1(ERR_FAILED): A general error occurs (no specified reason). + * - -2(ERR_INVALID_ARGUMENT): The parameter is invalid. + * - -5 (ERR_REFUSED): The request is rejected. In multichannel scenarios, if you have set any of the following in + * one channel, the SDK returns this error code when the user switches the user role to host in another channel: + * - Call `joinChannel` with the `options` parameter and use the default settings `publishLocalAudio = true` or `publishLocalVideo = true`. + * - Call `setClientRole` to set the user role as host. + * - Call `muteLocalAudioStream(false)` or `muteLocalVideoStream(false)`. + * - -7(ERR_NOT_INITIALIZED): The SDK is not initialized. + */ + virtual int setClientRole(CLIENT_ROLE_TYPE role, const ClientRoleOptions& options) = 0; + + /** Joins a channel with the user ID. + + Users in the same channel can talk to each other, and multiple users in the same channel can start a group chat. Users with different App IDs cannot call each other. + + + You must call the \ref IRtcEngine::leaveChannel "leaveChannel" method to exit the current call before entering another channel. + + A successful \ref agora::rtc::IRtcEngine::joinChannel "joinChannel" method call triggers the following callbacks: + - The local client: \ref agora::rtc::IRtcEngineEventHandler::onJoinChannelSuccess "onJoinChannelSuccess". + - The remote client: \ref agora::rtc::IRtcEngineEventHandler::onUserJoined "onUserJoined" , if the user joining the channel is in the `COMMUNICATION` profile, or is a host in the `LIVE_BROADCASTING` profile. + + When the connection between the client and Agora's server is interrupted due to poor network conditions, the SDK tries reconnecting to the server. When the local client successfully rejoins the channel, the SDK triggers the \ref agora::rtc::IRtcEngineEventHandler::onRejoinChannelSuccess "onRejoinChannelSuccess" callback on the local client. + + Once the user joins the channel (switches to another channel), the user subscribes to the audio and video streams of all the other users in the channel by default, giving rise to usage and billing calculation. If you do not want to subscribe to a specified stream or all remote streams, call the `mute` methods accordingly. + + @note A channel does not accept duplicate uids, such as two users with the same @p uid. If you set @p uid as 0, the system automatically assigns a @p uid. If you want to join a channel from different devices, ensure that each device has a different uid. + @warning Ensure that the App ID used for creating the token is the same App ID used by the \ref IRtcEngine::initialize "initialize" method for initializing the RTC engine. Otherwise, the CDN live streaming may fail. + + @param token The token generated at your server. See [Authenticate Your Users with Tokens](https://docs.agora.io/en/Interactive%20Broadcast/token_server?platform=All%20Platforms). + @param channelId Pointer to the unique channel name for the Agora RTC session in the string format smaller than 64 bytes. Supported characters: + - All lowercase English letters: a to z. + - All uppercase English letters: A to Z. + - All numeric characters: 0 to 9. + - The space character. + - Punctuation characters and other symbols, including: "!", "#", "$", "%", "&", "(", ")", "+", "-", ":", ";", "<", "=", ".", ">", "?", "@", "[", "]", "^", "_", " {", "}", "|", "~", ",". + @param info (Optional) Pointer to additional information about the channel. This parameter can be set to NULL or contain channel related information. Other users in the channel will not receive this message. + @param uid (Optional) User ID. A 32-bit unsigned integer with a value ranging from 1 to 232-1. The @p uid must be unique. If a @p uid is not assigned (or set to 0), the SDK assigns and returns a @p uid in the \ref IRtcEngineEventHandler::onJoinChannelSuccess "onJoinChannelSuccess" callback. Your application must record and maintain the returned `uid`, because the SDK does not do so. + + @return + - 0(ERR_OK): Success. + - < 0: Failure. + - -2(ERR_INVALID_ARGUMENT): The parameter is invalid. + - -3(ERR_NOT_READY): The SDK fails to be initialized. You can try re-initializing the SDK. + - -5(ERR_REFUSED): The request is rejected. This may be caused by the following: + - You have created an IChannel object with the same channel name. + - You have joined and published a stream in a channel created by the IChannel object. When you join a channel created by the IRtcEngine object, the SDK publishes the local audio and video streams to that channel by default. Because the SDK does not support publishing a local stream to more than one channel simultaneously, an error occurs in this occasion. + - -7(ERR_NOT_INITIALIZED): The SDK is not initialized before calling this method. + - -17(ERR_JOIN_CHANNEL_REJECTED): The request to join the channel is rejected. The SDK supports joining only one + IRtcEngine channel at a time. Therefore, the SDK returns this error code when a user who has already joined an + IRtcEngine channel calls the joining channel method of the IRtcEngine class with a valid channel name. + */ + virtual int joinChannel(const char* token, const char* channelId, const char* info, uid_t uid) = 0; + /** Joins a channel with the user ID, and configures whether to publish or automatically subscribe to the audio or video streams. + * + * @since v3.3.0 + * + * Users in the same channel can talk to each other, and multiple users in the same channel can start a group chat. Users with different App IDs cannot call each other. + * + * You must call the \ref IRtcEngine::leaveChannel "leaveChannel" method to exit the current call before entering another channel. + * + * A successful \ref IRtcEngine::joinChannel "joinChannel" method call triggers the following callbacks: + * - The local client: \ref IRtcEngineEventHandler::onJoinChannelSuccess "onJoinChannelSuccess". + * - The remote client: \ref IRtcEngineEventHandler::onUserJoined "onUserJoined", if the user joining the channel is in the `COMMUNICATION` profile, or is a host in the `LIVE_BROADCASTING` profile. + * + * When the connection between the client and the Agora server is interrupted due to poor network conditions, the SDK tries reconnecting to the server. + * When the local client successfully rejoins the channel, the SDK triggers the \ref IRtcEngineEventHandler::onRejoinChannelSuccess "onRejoinChannelSuccess" callback on the local client. + * + * @note + * - Compared with \ref IRtcEngine::joinChannel(const char* token, const char* channelId, const char* info, uid_t uid) "joinChannel" [1/2], this method + * has the `options` parameter, which configures whether the user publishes or automatically subscribes to the audio and video streams in the channel when + * joining the channel. By default, the user publishes the local audio and video streams and automatically subscribes to the audio and video streams + * of all the other users in the channel. Subscribing incurs all + * associated usage costs. To unsubscribe, set the `options` parameter or call the `mute` methods accordingly. + * - Ensure that the App ID used for generating the token is the same App ID used in the \ref IRtcEngine::initialize "initialize" method for + * creating an `IRtcEngine` object. + * + * @param token The token generated at your server. See [Authenticate Your Users with Tokens](https://docs.agora.io/en/Interactive%20Broadcast/token_server?platform=All%20Platforms). + * @param channelId Pointer to the unique channel name for the Agora RTC session in the string format smaller than 64 bytes. Supported characters: + * - All lowercase English letters: a to z. + * - All uppercase English letters: A to Z. + * - All numeric characters: 0 to 9. + * - The space character. + * - Punctuation characters and other symbols, including: "!", "#", "$", "%", "&", "(", ")", "+", "-", ":", ";", "<", "=", ".", ">", "?", "@", "[", "]", "^", "_", " {", "}", "|", "~", ",". + * @param info (Optional) Reserved for future use. + * @param uid (Optional) User ID. A 32-bit unsigned integer with a value ranging from 1 to 232-1. The @p uid must be unique. If a @p uid is + * not assigned (or set to 0), the SDK assigns and returns a `uid` in the \ref IRtcEngineEventHandler::onJoinChannelSuccess "onJoinChannelSuccess" callback. + * Your application must record and maintain the returned `uid`, because the SDK does not do so. **Note**: The ID of each user in the channel should be unique. + * If you want to join the same channel from different devices, ensure that the user IDs in all devices are different. + * @param options The channel media options: ChannelMediaOptions. + @return + * - 0(ERR_OK): Success. + * - < 0: Failure. + * - -2(ERR_INVALID_ARGUMENT): The parameter is invalid. + * - -3(ERR_NOT_READY): The SDK fails to be initialized. You can try re-initializing the SDK. + * - -5(ERR_REFUSED): The request is rejected. This may be caused by the following: + * - You have created an IChannel object with the same channel name. + * - You have joined and published a stream in a channel created by the IChannel object. When you join a channel created by the IRtcEngine object, the SDK publishes the local audio and video streams to that channel by default. Because the SDK does not support publishing a local stream to more than one channel simultaneously, an error occurs in this occasion. + * - -7(ERR_NOT_INITIALIZED): The SDK is not initialized before calling this method. + * - -17(ERR_JOIN_CHANNEL_REJECTED): The request to join the channel is rejected. The SDK supports joining only one + * IRtcEngine channel at a time. Therefore, the SDK returns this error code when a user who has already joined an + * IRtcEngine channel calls the joining channel method of the IRtcEngine class with a valid channel name. + */ + virtual int joinChannel(const char* token, const char* channelId, const char* info, uid_t uid, const ChannelMediaOptions& options) = 0; + /** Switches to a different channel. + * + * This method allows the audience of a `LIVE_BROADCASTING` channel to switch + * to a different channel. + * + * After the user successfully switches to another channel, the + * \ref agora::rtc::IRtcEngineEventHandler::onLeaveChannel "onLeaveChannel" + * and \ref agora::rtc::IRtcEngineEventHandler::onJoinChannelSuccess + * "onJoinChannelSuccess" callbacks are triggered to indicate that the + * user has left the original channel and joined a new one. + * + * Once the user switches to another channel, the user subscribes to the + * audio and video streams of all the other users in the channel by + * default, giving rise to usage and billing calculation. If you do not + * want to subscribe to a specified stream or all remote streams, call + * the `mute` methods accordingly. + * + * @note + * This method applies to the audience role in a `LIVE_BROADCASTING` channel + * only. + * + * @param token The token generated at your server. See [Authenticate Your Users with Tokens](https://docs.agora.io/en/Interactive%20Broadcast/token_server?platform=All%20Platforms). + * @param channelId Unique channel name for the AgoraRTC session in the + * string format. The string length must be less than 64 bytes. Supported + * character scopes are: + * - All lowercase English letters: a to z. + * - All uppercase English letters: A to Z. + * - All numeric characters: 0 to 9. + * - The space character. + * - Punctuation characters and other symbols, including: "!", "#", "$", "%", "&", "(", ")", "+", "-", ":", ";", "<", "=", ".", ">", "?", "@", "[", "]", "^", "_", " {", "}", "|", "~", ",". + * + * @return + * - 0(ERR_OK): Success. + * - < 0: Failure. + * - -1(ERR_FAILED): A general error occurs (no specified reason). + * - -2(ERR_INVALID_ARGUMENT): The parameter is invalid. + * - -5(ERR_REFUSED): The request is rejected, probably because the user is not an audience. + * - -7(ERR_NOT_INITIALIZED): The SDK is not initialized. + * - -102(ERR_INVALID_CHANNEL_NAME): The channel name is invalid. + * - -113(ERR_NOT_IN_CHANNEL): The user is not in the channel. + */ + virtual int switchChannel(const char* token, const char* channelId) = 0; + /** Switches to a different channel, and configures whether to automatically subscribe to audio or video streams in the target channel. + * + * @since v3.3.0 + * + * This method allows the audience of a `LIVE_BROADCASTING` channel to switch to a different channel. + * + * After the user successfully switches to another channel, the \ref IRtcEngineEventHandler::onLeaveChannel "onLeaveChannel" + * and \ref IRtcEngineEventHandler::onJoinChannelSuccess "onJoinChannelSuccess" callbacks are triggered to indicate that + * the user has left the original channel and joined a new one. + * + * @note + * - This method applies to the audience role in a `LIVE_BROADCASTING` channel only. + * - The difference between this method and \ref IRtcEngine::switchChannel(const char* token, const char* channelId) "switchChannel[1/2]" + * is that the former adds the options parameter to configure whether the user automatically subscribes to all remote audio and video streams in the target channel. + * By default, the user subscribes to the audio and video streams of all the other users in the target channel, thus incurring all associated usage costs. + * To unsubscribe, set the `options` parameter or call the `mute` methods accordingly. + * + * @param token The token generated at your server. See [Authenticate Your Users with Tokens](https://docs.agora.io/en/Interactive%20Broadcast/token_server?platform=All%20Platforms). + * @param channelId Unique channel name for the AgoraRTC session in the + * string format. The string length must be less than 64 bytes. Supported + * character scopes are: + * - All lowercase English letters: a to z. + * - All uppercase English letters: A to Z. + * - All numeric characters: 0 to 9. + * - The space character. + * - Punctuation characters and other symbols, including: "!", "#", "$", "%", "&", "(", ")", "+", "-", ":", ";", "<", "=", ".", ">", "?", "@", "[", "]", "^", "_", " {", "}", "|", "~", ",". + * @param options The channel media options: ChannelMediaOptions. + * + * @return + * - 0(ERR_OK): Success. + * - < 0: Failure. + * - -1(ERR_FAILED): A general error occurs (no specified reason). + * - -2(ERR_INVALID_ARGUMENT): The parameter is invalid. + * - -5(ERR_REFUSED): The request is rejected, probably because the user is not an audience. + * - -7(ERR_NOT_INITIALIZED): The SDK is not initialized. + * - -102(ERR_INVALID_CHANNEL_NAME): The channel name is invalid. + * - -113(ERR_NOT_IN_CHANNEL): The user is not in the channel. + */ + virtual int switchChannel(const char* token, const char* channelId, const ChannelMediaOptions& options) = 0; + + /** Allows a user to leave a channel, such as hanging up or exiting a call. + + After joining a channel, the user must call the *leaveChannel* method to end the call before joining another channel. + + This method returns 0 if the user leaves the channel and releases all resources related to the call. + + This method call is asynchronous, and the user has not left the channel when the method call returns. Once the user leaves the channel, the SDK triggers the \ref IRtcEngineEventHandler::onLeaveChannel "onLeaveChannel" callback. + + A successful \ref agora::rtc::IRtcEngine::leaveChannel "leaveChannel" method call triggers the following callbacks: + - The local client: \ref agora::rtc::IRtcEngineEventHandler::onLeaveChannel "onLeaveChannel" + - The remote client: \ref agora::rtc::IRtcEngineEventHandler::onUserOffline "onUserOffline" , if the user leaving the channel is in the `COMMUNICATION` channel, or is a host in the `LIVE_BROADCASTING` profile. + + @note + - If you call the \ref IRtcEngine::release "release" method immediately after the *leaveChannel* method, the *leaveChannel* process interrupts, and the \ref IRtcEngineEventHandler::onLeaveChannel "onLeaveChannel" callback is not triggered. + - If you call the *leaveChannel* method during a CDN live streaming, the SDK triggers the \ref IRtcEngine::removePublishStreamUrl "removePublishStreamUrl" method. + + @return + - 0(ERR_OK): Success. + - < 0: Failure. + - -1(ERR_FAILED): A general error occurs (no specified reason). + - -2(ERR_INVALID_ARGUMENT): The parameter is invalid. + - -7(ERR_NOT_INITIALIZED): The SDK is not initialized. + */ + virtual int leaveChannel() = 0; + + /** Gets a new token when the current token expires after a period of time. + + The `token` expires after a period of time once the token schema is enabled when: + + - The SDK triggers the \ref IRtcEngineEventHandler::onTokenPrivilegeWillExpire "onTokenPrivilegeWillExpire" callback, or + - The \ref IRtcEngineEventHandler::onConnectionStateChanged "onConnectionStateChanged" reports CONNECTION_CHANGED_TOKEN_EXPIRED(9). + + The application should call this method to get the new `token`. Failure to do so will result in the SDK disconnecting from the server. + + @param token The new token. + + @return + - 0(ERR_OK): Success. + - < 0: Failure. + - -1(ERR_FAILED): A general error occurs (no specified reason). + - -2(ERR_INVALID_ARGUMENT): The parameter is invalid. + - -7(ERR_NOT_INITIALIZED): The SDK is not initialized. + */ + virtual int renewToken(const char* token) = 0; + + /** Gets the pointer to the device manager object. + + @param iid ID of the interface. + @param inter Pointer to the *DeviceManager* object. + @return + - 0: Success. + - < 0: Failure. + */ + virtual int queryInterface(INTERFACE_ID_TYPE iid, void** inter) = 0; + + /** Registers a user account. + + Once registered, the user account can be used to identify the local user when the user joins the channel. + After the user successfully registers a user account, the SDK triggers the \ref agora::rtc::IRtcEngineEventHandler::onLocalUserRegistered "onLocalUserRegistered" callback on the local client, + reporting the user ID and user account of the local user. + + To join a channel with a user account, you can choose either of the following: + + - Call the \ref agora::rtc::IRtcEngine::registerLocalUserAccount "registerLocalUserAccount" method to create a user account, and then the \ref agora::rtc::IRtcEngine::joinChannelWithUserAccount "joinChannelWithUserAccount" method to join the channel. + - Call the \ref agora::rtc::IRtcEngine::joinChannelWithUserAccount "joinChannelWithUserAccount" method to join the channel. + + The difference between the two is that for the former, the time elapsed between calling the \ref agora::rtc::IRtcEngine::joinChannelWithUserAccount "joinChannelWithUserAccount" method + and joining the channel is shorter than the latter. + + @note + - Ensure that you set the `userAccount` parameter. Otherwise, this method does not take effect. + - Ensure that the value of the `userAccount` parameter is unique in the channel. + - To ensure smooth communication, use the same parameter type to identify the user. For example, if a user joins the channel with a user ID, then ensure all the other users use the user ID too. The same applies to the user account. If a user joins the channel with the Agora Web SDK, ensure that the uid of the user is set to the same parameter type. + + @param appId The App ID of your project. + @param userAccount The user account. The maximum length of this parameter is 255 bytes. Ensure that the user account is unique and do not set it as null. Supported character scopes are: + - All lowercase English letters: a to z. + - All uppercase English letters: A to Z. + - All numeric characters: 0 to 9. + - The space character. + - Punctuation characters and other symbols, including: "!", "#", "$", "%", "&", "(", ")", "+", "-", ":", ";", "<", "=", ".", ">", "?", "@", "[", "]", "^", "_", " {", "}", "|", "~", ",". + + @return + - 0: Success. + - < 0: Failure. + */ + virtual int registerLocalUserAccount(const char* appId, const char* userAccount) = 0; + /** Joins the channel with a user account. + + After the user successfully joins the channel, the SDK triggers the following callbacks: + + - The local client: \ref agora::rtc::IRtcEngineEventHandler::onLocalUserRegistered "onLocalUserRegistered" and \ref agora::rtc::IRtcEngineEventHandler::onJoinChannelSuccess "onJoinChannelSuccess" . + - The remote client: \ref agora::rtc::IRtcEngineEventHandler::onUserJoined "onUserJoined" and \ref agora::rtc::IRtcEngineEventHandler::onUserInfoUpdated "onUserInfoUpdated" , if the user joining the channel is in the `COMMUNICATION` profile, or is a host in the `LIVE_BROADCASTING` profile. + + Once the user joins the channel (switches to another channel), the user subscribes to the audio and video streams of all the other users in the channel by default, giving rise to usage and billing calculation. If you do not want to subscribe to a specified stream or all remote streams, call the `mute` methods accordingly. + + @note + - To ensure smooth communication, use the same parameter type to identify the user. For example, if a user joins the channel with a user ID, then ensure all the other users use the user ID too. The same applies to the user account. + If a user joins the channel with the Agora Web SDK, ensure that the uid of the user is set to the same parameter type. + - Before using a String user name, ensure that you read [How can I use string user names](https://docs.agora.io/en/faq/string) for getting details about the limitations and implementation steps. + + @param token The token generated at your server. See [Authenticate Your Users with Tokens](https://docs.agora.io/en/Interactive%20Broadcast/token_server?platform=All%20Platforms). + @param channelId The channel name. The maximum length of this parameter is 64 bytes. Supported character scopes are: + - All lowercase English letters: a to z. + - All uppercase English letters: A to Z. + - All numeric characters: 0 to 9. + - The space character. + - Punctuation characters and other symbols, including: "!", "#", "$", "%", "&", "(", ")", "+", "-", ":", ";", "<", "=", ".", ">", "?", "@", "[", "]", "^", "_", " {", "}", "|", "~", ",". + @param userAccount The user account. The maximum length of this parameter is 255 bytes. Ensure that the user account is unique and do not set it as null. Supported character scopes are: + - All lowercase English letters: a to z. + - All uppercase English letters: A to Z. + - All numeric characters: 0 to 9. + - The space character. + - Punctuation characters and other symbols, including: "!", "#", "$", "%", "&", "(", ")", "+", "-", ":", ";", "<", "=", ".", ">", "?", "@", "[", "]", "^", "_", " {", "}", "|", "~", ",". + + @return + - 0: Success. + - < 0: Failure. + - #ERR_INVALID_ARGUMENT (-2) + - #ERR_NOT_READY (-3) + - #ERR_REFUSED (-5) + - #ERR_NOT_INITIALIZED (-7) + - -17(ERR_JOIN_CHANNEL_REJECTED): The request to join the channel is rejected. The SDK supports joining only one + IRtcEngine channel at a time. Therefore, the SDK returns this error code when a user who has already joined an + IRtcEngine channel calls the joining channel method of the IRtcEngine class with a valid channel name. + */ + virtual int joinChannelWithUserAccount(const char* token, const char* channelId, const char* userAccount) = 0; + /** Joins the channel with a user account, and configures + * whether to publish or automatically subscribe to the audio or video streams. + * + * @since v3.3.0 + * + * After the user successfully joins the channel, the SDK triggers the following callbacks: + * - The local client: \ref agora::rtc::IRtcEngineEventHandler::onLocalUserRegistered "onLocalUserRegistered" and \ref agora::rtc::IRtcEngineEventHandler::onJoinChannelSuccess "onJoinChannelSuccess" . + * - The remote client: \ref agora::rtc::IRtcEngineEventHandler::onUserJoined "onUserJoined" and \ref agora::rtc::IRtcEngineEventHandler::onUserInfoUpdated "onUserInfoUpdated" , if the user joining the channel is in the `COMMUNICATION` profile, or is a host in the `LIVE_BROADCASTING` profile. + * + * @note + * - Compared with \ref IRtcEngine::joinChannelWithUserAccount(const char* token, const char* channelId, const char* userAccount) "joinChannelWithUserAccount" [1/2], + * this method has the options parameter, which configures whether the user publishes or automatically subscribes to the audio and video streams in the channel when + * joining the channel. By default, the user publishes the local audio and video streams and automatically subscribes to the audio and video streams of all the other + * users in the channel. Subscribing incurs all associated usage costs. To unsubscribe, set the `options` parameter or call the `mute` methods accordingly. + * - To ensure smooth communication, use the same parameter type to identify the user. For example, if a user joins the channel with a user ID, then ensure all + * the other users use the user ID too. The same applies to the user account. If a user joins the channel with the Agora Web SDK, ensure that the + * uid of the user is set to the same parameter type. + * - Before using a String user name, ensure that you read [How can I use string user names](https://docs.agora.io/en/faq/string) for getting details about the limitations and implementation steps. + * + * @param token The token generated at your server. See [Authenticate Your Users with Tokens](https://docs.agora.io/en/Interactive%20Broadcast/token_server?platform=All%20Platforms). + * @param channelId The channel name. The maximum length of this parameter is 64 bytes. Supported character scopes are: + * - All lowercase English letters: a to z. + * - All uppercase English letters: A to Z. + * - All numeric characters: 0 to 9. + * - The space character. + * - Punctuation characters and other symbols, including: "!", "#", "$", "%", "&", "(", ")", "+", "-", ":", ";", "<", "=", ".", ">", "?", "@", "[", "]", "^", "_", " {", "}", "|", "~", ",". + * @param userAccount The user account. The maximum length of this parameter is 255 bytes. Ensure that the user account is unique and do not set it as null. Supported character scopes are: + * - All lowercase English letters: a to z. + * - All uppercase English letters: A to Z. + * - All numeric characters: 0 to 9. + * - The space character. + * - Punctuation characters and other symbols, including: "!", "#", "$", "%", "&", "(", ")", "+", "-", ":", ";", "<", "=", ".", ">", "?", "@", "[", "]", "^", "_", " {", "}", "|", "~", ",". + * @param options The channel media options: ChannelMediaOptions. + * @return + * - 0: Success. + * - < 0: Failure. + * - #ERR_INVALID_ARGUMENT (-2) + * - #ERR_NOT_READY (-3) + * - #ERR_REFUSED (-5) + * - -17(ERR_JOIN_CHANNEL_REJECTED): The request to join the channel is rejected. The SDK supports joining only one + * IRtcEngine channel at a time. Therefore, the SDK returns this error code when a user who has already joined an + * IRtcEngine channel calls the joining channel method of the IRtcEngine class with a valid channel name. + */ + virtual int joinChannelWithUserAccount(const char* token, const char* channelId, const char* userAccount, const ChannelMediaOptions& options) = 0; + + /** Gets the user information by passing in the user account. + + After a remote user joins the channel, the SDK gets the user ID and user account of the remote user, caches them + in a mapping table object (`userInfo`), and triggers the \ref agora::rtc::IRtcEngineEventHandler::onUserInfoUpdated "onUserInfoUpdated" callback on the local client. + + After receiving the o\ref agora::rtc::IRtcEngineEventHandler::onUserInfoUpdated "onUserInfoUpdated" callback, you can call this method to get the user ID of the + remote user from the `userInfo` object by passing in the user account. + + @param userAccount The user account of the user. Ensure that you set this parameter. + @param [in,out] userInfo A userInfo object that identifies the user: + - Input: A userInfo object. + - Output: A userInfo object that contains the user account and user ID of the user. + + @return + - 0: Success. + - < 0: Failure. + */ + virtual int getUserInfoByUserAccount(const char* userAccount, UserInfo* userInfo) = 0; + /** Gets the user information by passing in the user ID. + + After a remote user joins the channel, the SDK gets the user ID and user account of the remote user, + caches them in a mapping table object (`userInfo`), and triggers the \ref agora::rtc::IRtcEngineEventHandler::onUserInfoUpdated "onUserInfoUpdated" callback on the local client. + + After receiving the \ref agora::rtc::IRtcEngineEventHandler::onUserInfoUpdated "onUserInfoUpdated" callback, you can call this method to get the user account of the remote user + from the `userInfo` object by passing in the user ID. + + @param uid The user ID of the remote user. Ensure that you set this parameter. + @param[in,out] userInfo A userInfo object that identifies the user: + - Input: A userInfo object. + - Output: A userInfo object that contains the user account and user ID of the user. + + @return + - 0: Success. + - < 0: Failure. + */ + virtual int getUserInfoByUid(uid_t uid, UserInfo* userInfo) = 0; + + /** **DEPRECATED** Starts an audio call test. + + This method is deprecated as of v2.4.0. + + This method starts an audio call test to check whether the audio devices (for example, headset and speaker) and the network connection are working properly. + + To conduct the test: + + - The user speaks and the recording is played back within 10 seconds. + - If the user can hear the recording within 10 seconds, the audio devices and network connection are working properly. + + @note + - After calling this method, always call the \ref IRtcEngine::stopEchoTest "stopEchoTest" method to end the test. Otherwise, the application cannot run the next echo test. + - In the `LIVE_BROADCASTING` profile, only the hosts can call this method. If the user switches from the `COMMUNICATION` to`LIVE_BROADCASTING` profile, the user must call the \ref IRtcEngine::setClientRole "setClientRole" method to change the user role from the audience (default) to the host before calling this method. + + @return + - 0: Success. + - < 0: Failure. + */ + virtual int startEchoTest() = 0; + + /** Starts an audio call test. + + This method starts an audio call test to determine whether the audio devices (for example, headset and speaker) and the network connection are working properly. + + In the audio call test, you record your voice. If the recording plays back within the set time interval, the audio devices and the network connection are working properly. + + @note + - Call this method before joining a channel. + - After calling this method, call the \ref IRtcEngine::stopEchoTest "stopEchoTest" method to end the test. Otherwise, the app cannot run the next echo test, or call the \ref IRtcEngine::joinChannel "joinChannel" method. + - In the `LIVE_BROADCASTING` profile, only a host can call this method. + @param intervalInSeconds The time interval (s) between when you speak and when the recording plays back. + + @return + - 0: Success. + - < 0: Failure. + */ + virtual int startEchoTest(int intervalInSeconds) = 0; + + /** Starts an audio and video call loop test. + * + * @since v3.5.2 + * + * Before joining a channel, to test whether the user's local sending and receiving streams are normal, you can call + * this method to perform an audio and video call loop test, which tests whether the audio and video devices and the + * user's upstream and downstream networks are working properly. + * + * After starting the test, the user needs to make a sound or face the camera. The audio or video is output after + * about two seconds. If the audio playback is normal, the audio device and the user's upstream and downstream + * networks are working properly; if the video playback is normal, the video device and the user's upstream and + * downstream networks are working properly. + * + * @note + * - Call this method before joining a channel. + * - After calling this method, call \ref IRtcEngine::stopEchoTest "stopEchoTest" to end the test; otherwise, the + * user cannot perform the next audio and video call loop test and cannot join the channel. + * - In the `LIVE_BROADCASTING` profile, only a host can call this method. + * + * @param config The configuration of the audio and video call loop test. See EchoTestConfiguration. + * + * @return + * - 0: Success. + * - < 0: Failure. + */ + virtual int startEchoTest(const EchoTestConfiguration& config) = 0; + + /** Stops call loop test. + * + * After calling `startEchoTest [2/3]` or `startEchoTest [3/3]`, call this method if you want to stop the call loop test. + * + * @return + * - 0: Success. + * - < 0: Failure. + */ + virtual int stopEchoTest() = 0; + + /** Sets the Agora cloud proxy service. + * + * @since v3.3.0 + * + * When the user's firewall restricts the IP address and port, refer to *Use Cloud Proxy* to add the specific + * IP addresses and ports to the firewall whitelist; then, call this method to enable the cloud proxy and set + * the `proxyType` parameter as `UDP_PROXY(1)`, which is the cloud proxy for the UDP protocol. + * + * After a successfully cloud proxy connection, the SDK triggers + * the \ref IRtcEngineEventHandler::onConnectionStateChanged "onConnectionStateChanged" (CONNECTION_STATE_CONNECTING, CONNECTION_CHANGED_SETTING_PROXY_SERVER) callback. + * + * To disable the cloud proxy that has been set, call `setCloudProxy(NONE_PROXY)`. To change the cloud proxy type that has been set, + * call `setCloudProxy(NONE_PROXY)` first, and then call `setCloudProxy`, and pass the value that you expect in `proxyType`. + * + * @note + * - Agora recommends that you call this method before joining the channel or after leaving the channel. + * - For the SDK v3.3.x, the services for pushing streams to CDN and co-hosting across channels are not available + * when you use the cloud proxy for the UDP protocol. For the SDK v3.4.0 and later, the services for pushing streams + * to CDN and co-hosting across channels are not available when the user is in a network environment with a firewall + * and uses the cloud proxy for the UDP protocol. + * + * @param proxyType The cloud proxy type, see #CLOUD_PROXY_TYPE. This parameter is required, and the SDK reports an error if you do not pass in a value. + * + * @return + * - 0: Success. + * - < 0: Failure. + * - `-2(ERR_INVALID_ARGUMENT)`: The parameter is invalid. + * - `-7(ERR_NOT_INITIALIZED)`: The SDK is not initialized. + */ + virtual int setCloudProxy(CLOUD_PROXY_TYPE proxyType) = 0; + /** Enables the video module. + * + * Call this method either before joining a channel or during a call. If this method is called before joining a channel, the call starts in the video mode. If this method is called during an audio call, the audio mode switches to the video mode. To disable the video module, call the \ref IRtcEngine::disableVideo "disableVideo" method. + * + * A successful \ref agora::rtc::IRtcEngine::enableVideo "enableVideo" method call triggers the \ref agora::rtc::IRtcEngineEventHandler::onUserEnableVideo "onUserEnableVideo" (true) callback on the remote client. + * @note + * - This method affects the internal engine and can be called after the \ref agora::rtc::IRtcEngine::leaveChannel "leaveChannel" method. + * - This method resets the internal engine and takes some time to take effect. We recommend using the following API methods to control the video engine modules separately: + * - \ref IRtcEngine::enableLocalVideo "enableLocalVideo": Whether to enable the camera to create the local video stream. + * - \ref IRtcEngine::muteLocalVideoStream "muteLocalVideoStream": Whether to publish the local video stream. + * - \ref IRtcEngine::muteRemoteVideoStream "muteRemoteVideoStream": Whether to subscribe to and play the remote video stream. + * - \ref IRtcEngine::muteAllRemoteVideoStreams "muteAllRemoteVideoStreams": Whether to subscribe to and play all remote video streams. + * + * @return + * - 0: Success. + * - < 0: Failure. + */ + virtual int enableVideo() = 0; + + /** Disables the video module. + * + * This method can be called before joining a channel or during a call. If this method is called before joining a + * channel, the call starts in audio mode. If this method is called during a video call, the video mode switches to + * the audio mode. To enable the video module, call the \ref IRtcEngine::enableVideo "enableVideo" method. + * + * A successful \ref agora::rtc::IRtcEngine::disableVideo "disableVideo" method call triggers + * the \ref agora::rtc::IRtcEngineEventHandler::onUserEnableVideo "onUserEnableVideo" (false) callback on the remote + * client. + * + * @note + * - This method affects the internal engine and can be called after + * the \ref agora::rtc::IRtcEngine::leaveChannel "leaveChannel" method. + * - This method resets the internal engine and takes some time to take effect. We recommend using the following + * APIs to control the video engine modules separately: + * - \ref IRtcEngine::enableLocalVideo "enableLocalVideo": Whether to enable the camera to create the local video stream. + * - \ref IRtcEngine::muteLocalVideoStream "muteLocalVideoStream": Whether to publish the local video stream. + * - \ref IRtcEngine::muteRemoteVideoStream "muteRemoteVideoStream": Whether to subscribe to and play the remote video stream. + * - \ref IRtcEngine::muteAllRemoteVideoStreams "muteAllRemoteVideoStreams": Whether to subscribe to and play all remote video streams. + * + * @return + * - 0: Success. + * - < 0: Failure. + */ + virtual int disableVideo() = 0; + + /** Sets the video profile. + + @deprecated This method is deprecated as of v2.3. Use the \ref IRtcEngine::setVideoEncoderConfiguration "setVideoEncoderConfiguration" method instead. + + Each video profile includes a set of parameters, such as the resolution, frame rate, and bitrate. If the camera device does not support the specified resolution, the SDK automatically chooses a suitable camera resolution, keeping the encoder resolution specified by the *setVideoProfile* method. + + @note + - You can call this method either before or after joining a channel. + - If you do not need to set the video profile after joining the channel, call this method before the \ref IRtcEngine::enableVideo "enableVideo" method to reduce the render time of the first video frame. + - Always set the video profile before calling the \ref IRtcEngine::joinChannel "joinChannel" or \ref IRtcEngine::startPreview "startPreview" method. + + @param profile Sets the video profile. See #VIDEO_PROFILE_TYPE. + @param swapWidthAndHeight Sets whether to swap the width and height of the video stream: + - true: Swap the width and height. + - false: (Default) Do not swap the width and height. + The width and height of the output video are consistent with the set video profile. + @note Since the landscape or portrait mode of the output video can be decided directly by the video profile, We recommend setting *swapWidthAndHeight* to *false* (default). + + @return + - 0: Success. + - < 0: Failure. + */ + virtual int setVideoProfile(VIDEO_PROFILE_TYPE profile, bool swapWidthAndHeight) AGORA_DEPRECATED_ATTRIBUTE = 0; + + /** Sets the video encoder configuration. + + Each video encoder configuration corresponds to a set of video parameters, including the resolution, frame rate, bitrate, and video orientation. + + The parameters specified in this method are the maximum values under ideal network conditions. If the video engine cannot render the video using the specified parameters due to poor network conditions, the parameters further down the list are considered until a successful configuration is found. + + @note + - You can call this method either before or after joining a channel. + - If you do not need to set the video encoder configuration after joining the channel, you can call this method before the \ref IRtcEngine::enableVideo "enableVideo" method to reduce the render time of the first video frame. + + @param config Sets the local video encoder configuration. See VideoEncoderConfiguration. + @return + - 0: Success. + - < 0: Failure. + */ + virtual int setVideoEncoderConfiguration(const VideoEncoderConfiguration& config) = 0; + /** Sets the camera capture configuration. + + For a video call or the interactive live video streaming, generally the SDK controls the camera output parameters. When the default camera capturer settings do not meet special requirements or cause performance problems, we recommend using this method to set the camera capturer configuration: + + - If the resolution or frame rate of the captured raw video data are higher than those set by \ref IRtcEngine::setVideoEncoderConfiguration "setVideoEncoderConfiguration", processing video frames requires extra CPU and RAM usage and degrades performance. We recommend setting config as #CAPTURER_OUTPUT_PREFERENCE_PERFORMANCE (1) to avoid such problems. + - If you do not need local video preview or are willing to sacrifice preview quality, we recommend setting config as #CAPTURER_OUTPUT_PREFERENCE_PERFORMANCE (1) to optimize CPU and RAM usage. + - If you want better quality for the local video preview, we recommend setting config as #CAPTURER_OUTPUT_PREFERENCE_PREVIEW (2). + - To customize the width and height of the video image captured by the local camera, set the camera capture configuration as #CAPTURER_OUTPUT_PREFERENCE_MANUAL (3). + + @note Call this method before enabling the local camera. That said, you can call this method before calling \ref agora::rtc::IRtcEngine::joinChannel "joinChannel", \ref agora::rtc::IRtcEngine::enableVideo "enableVideo", or \ref IRtcEngine::enableLocalVideo "enableLocalVideo", depending on which method you use to turn on your local camera. + + @param config Sets the camera capturer configuration. See CameraCapturerConfiguration. + + @return + - 0: Success. + - < 0: Failure. + */ + virtual int setCameraCapturerConfiguration(const CameraCapturerConfiguration& config) = 0; + + /** Initializes the local video view. + + This method initializes the video view of a local stream on the local device. It affects only the video view that the local user sees, not the published local video stream. + + Call this method to bind the local video stream to a video view and to set the rendering and mirror modes of the video view. + The binding is still valid after the user leaves the channel, which means that the window still displays. To unbind the view, set the *view* in VideoCanvas to NULL. + + @note + - You can call this method either before or after joining a channel. + - During a call, you can call this method as many times as necessary to update the display mode of the local video view. + + @param canvas Pointer to the local video view and settings. See VideoCanvas. + @return + - 0: Success. + - < 0: Failure. + */ + virtual int setupLocalVideo(const VideoCanvas& canvas) = 0; + + /** Initializes the video view of a remote user. + + This method initializes the video view of a remote stream on the local device. It affects only the video view that the local user sees. + + Call this method to bind the remote video stream to a video view and to set the rendering and mirror modes of the video view. + + The application specifies the uid of the remote video in this method before the remote user joins the channel. If the remote uid is unknown to the application, set it after the application receives the \ref IRtcEngineEventHandler::onUserJoined "onUserJoined" callback. + If the Video Recording function is enabled, the Video Recording Service joins the channel as a dummy client, causing other clients to also receive the \ref IRtcEngineEventHandler::onUserJoined "onUserJoined" callback. Do not bind the dummy client to the application view because the dummy client does not send any video streams. If your application does not recognize the dummy client, bind the remote user to the view when the SDK triggers the \ref IRtcEngineEventHandler::onFirstRemoteVideoDecoded "onFirstRemoteVideoDecoded" callback. + To unbind the remote user from the view, set the view in VideoCanvas to NULL. Once the remote user leaves the channel, the SDK unbinds the remote user. + + @note To update the rendering or mirror mode of the remote video view during a call, use the \ref IRtcEngine::setRemoteRenderMode "setRemoteRenderMode" method. + + @param canvas Pointer to the remote video view and settings. See VideoCanvas. + @return + - 0: Success. + - < 0: Failure. + */ + virtual int setupRemoteVideo(const VideoCanvas& canvas) = 0; + + /** Starts the local video preview before joining the channel. + + Before calling this method, you must: + + - Call the \ref IRtcEngine::setupLocalVideo "setupLocalVideo" method to set up the local preview window and configure the attributes. + - Call the \ref IRtcEngine::enableVideo "enableVideo" method to enable video. + + @note Once the startPreview method is called to start the local video preview, if you leave the channel by calling the \ref IRtcEngine::leaveChannel "leaveChannel" method, the local video preview remains until you call the \ref IRtcEngine::stopPreview "stopPreview" method to disable it. + + @return + - 0: Success. + - < 0: Failure. + */ + virtual int startPreview() = 0; + + /** Prioritizes a remote user's stream. + * + * The SDK ensures the high-priority user gets the best possible stream quality. + * + * @note + * - The Agora SDK supports setting @p userPriority as high for one user only. + * - Ensure that you call this method before joining a channel. + * + * @param uid The ID of the remote user. + * @param userPriority Sets the priority of the remote user. See #PRIORITY_TYPE. + * + * @return + * - 0: Success. + * - < 0: Failure. + */ + virtual int setRemoteUserPriority(uid_t uid, PRIORITY_TYPE userPriority) = 0; + + /** Stops the local video preview. + * + * After calling \ref IRtcEngine::startPreview "startPreview", if you want to stop + * the local video preview, call `stopPreview`. + * + * @note Call this method before you join the channel or after you leave the channel. + * + * @return + * - 0: Success. + * - < 0: Failure. + */ + virtual int stopPreview() = 0; + + /** Enables the audio module. + + The audio mode is enabled by default. + + @note + - This method affects the audio module and can be called after the \ref agora::rtc::IRtcEngine::leaveChannel "leaveChannel" method. You can call this method either before or after joining a channel. + - This method enables the audio module and takes some time to take effect. Agora recommends using the following API methods to control the audio module separately: + - \ref IRtcEngine::enableLocalAudio "enableLocalAudio": Whether to enable the microphone to create the local audio stream. + - \ref IRtcEngine::muteLocalAudioStream "muteLocalAudioStream": Whether to publish the local audio stream. + - \ref IRtcEngine::muteRemoteAudioStream "muteRemoteAudioStream": Whether to subscribe to and play the remote audio stream. + - \ref IRtcEngine::muteAllRemoteAudioStreams "muteAllRemoteAudioStreams": Whether to subscribe to and play all remote audio streams. + + @return + - 0: Success. + - < 0: Failure. + */ + virtual int enableAudio() = 0; + + /** Disables/Re-enables the local audio function. + * + * The audio function is enabled by default. This method disables or re-enables the local audio function, that is, to stop or restart local audio capturing. + * + * This method does not affect receiving the remote audio streams,and enableLocalAudio(false) is applicable to scenarios where the user wants to + * receive remote audio streams without sending any audio stream to other users in the channel. + * + * Once the local audio function is disabled or re-enabled, the SDK triggers the \ref agora::rtc::IRtcEngineEventHandler::onLocalAudioStateChanged "onLocalAudioStateChanged" callback, + * which reports `LOCAL_AUDIO_STREAM_STATE_STOPPED(0)` or `LOCAL_AUDIO_STREAM_STATE_RECORDING(1)`. + * + * @note + * - This method is different from the \ref agora::rtc::IRtcEngine::muteLocalAudioStream "muteLocalAudioStream" method: + * - \ref agora::rtc::IRtcEngine::enableLocalAudio "enableLocalAudio": Disables/Re-enables the local audio capturing and processing. + * If you disable or re-enable local audio capturing using the `enableLocalAudio` method, the local user may hear a pause in the remote audio playback. + * - \ref agora::rtc::IRtcEngine::muteLocalAudioStream "muteLocalAudioStream": Sends/Stops sending the local audio streams. + * - This method can be called either before or after you join a channel. Calling it before you + * join a channel can set the device state only, and it takes effect immediately after you join the + * channel. + * + * @param enabled Sets whether to disable/re-enable the local audio function: + * - true: (Default) Re-enable the local audio function, that is, to start the local audio capturing device (for example, the microphone). + * - false: Disable the local audio function, that is, to stop local audio capturing. + * + * @return + * - 0: Success. + * - < 0: Failure. + */ + virtual int enableLocalAudio(bool enabled) = 0; + + /** Disables the audio module. + + @note + - This method affects the internal engine and can be called after the \ref agora::rtc::IRtcEngine::leaveChannel "leaveChannel" method. You can call this method either before or after joining a channel. + - This method resets the internal engine and takes some time to take effect. We recommend using the \ref agora::rtc::IRtcEngine::enableLocalAudio "enableLocalAudio" and \ref agora::rtc::IRtcEngine::muteLocalAudioStream "muteLocalAudioStream" methods to capture, process, and send the local audio streams. + + @return + - 0: Success. + - < 0: Failure. + */ + virtual int disableAudio() = 0; + + /** Sets the audio parameters and application scenarios. + + @note + - The `setAudioProfile` method must be called before the \ref IRtcEngine::joinChannel "joinChannel" method. + - In the `COMMUNICATION` and `LIVE_BROADCASTING` profiles, the bitrate may be different from your settings due to network self-adaptation. + - In scenarios requiring high-quality audio, for example, a music teaching scenario, we recommend setting profile as AUDIO_PROFILE_MUSIC_HIGH_QUALITY (4) and scenario as AUDIO_SCENARIO_GAME_STREAMING (3). + + @param profile Sets the sample rate, bitrate, encoding mode, and the number of channels. See #AUDIO_PROFILE_TYPE. + @param scenario Sets the audio application scenario. See #AUDIO_SCENARIO_TYPE. + Under different audio scenarios, the device uses different volume types. For details, see + [What is the difference between the in-call volume and the media volume?](https://docs.agora.io/en/faq/system_volume). + + @return + - 0: Success. + - < 0: Failure. + */ + virtual int setAudioProfile(AUDIO_PROFILE_TYPE profile, AUDIO_SCENARIO_TYPE scenario) = 0; + /** + * Stops or resumes publishing the local audio stream. + * + * As of v3.4.5, this method only sets the publishing state of the audio stream in the channel of IRtcEngine. + * + * A successful method call triggers the \ref IRtcEngineEventHandler::onUserMuteAudio "onUserMuteAudio" callback + * on the remote client. + * + * You can only publish the local stream in one channel at a time. If you create multiple channels, ensure that + * you only call \ref IRtcEngine::muteLocalAudioStream "muteLocalAudioStream" (false) in one channel; + * otherwise, the method call fails, and the SDK returns `-5 (ERR_REFUSED)`. + * + * @note + * - This method does not change the usage state of the audio-capturing device. + * - Whether this method call takes effect is affected by the + * \ref IRtcEngine::joinChannel(const char* token, const char* channelId, const char* info, uid_t uid, const ChannelMediaOptions& options) "joinChannel" [2/2] + * and \ref IRtcEngine::setClientRole "setClientRole" methods. For details, see *Set the Publishing State*. + * + * @param mute Sets whether to stop publishing the local audio stream. + * - true: Stop publishing the local audio stream. + * - false: Resume publishing the local audio stream. + * + * @return + * - 0: Success. + * - < 0: Failure. + * - `-5 (ERR_REFUSED)`: The request is rejected. + */ + virtual int muteLocalAudioStream(bool mute) = 0; + /** + * Stops or resumes subscribing to the audio streams of all remote users. + * + * After successfully calling this method, the local user stops or resumes + * subscribing to the audio streams of all remote users, including all subsequent users. + * + * @note + * - Call this method after joining a channel. + * - As of v3.3.0, this method contains the function of \ref IRtcEngine::setDefaultMuteAllRemoteAudioStreams "setDefaultMuteAllRemoteAudioStreams". + * Agora recommends not calling `muteAllRemoteAudioStreams` and `setDefaultMuteAllRemoteAudioStreams` + * together; otherwise, the settings may not take effect. See *Set the Subscribing State*. + * + * @param mute Sets whether to stop subscribing to the audio streams of all remote users. + * - true: Stop subscribing to the audio streams of all remote users. + * - false: (Default) Resume subscribing to the audio streams of all remote users. + * + * @return + * - 0: Success. + * - < 0: Failure. + */ + virtual int muteAllRemoteAudioStreams(bool mute) = 0; + /** Stops or resumes subscribing to the audio streams of all remote users by default. + * + * @deprecated This method is deprecated from v3.3.0. + * + * + * Call this method after joining a channel. After successfully calling this method, the + * local user stops or resumes subscribing to the audio streams of all subsequent users. + * + * @note If you need to resume subscribing to the audio streams of remote users in the + * channel after calling \ref IRtcEngine::setDefaultMuteAllRemoteAudioStreams "setDefaultMuteAllRemoteAudioStreams" (true), do the following: + * - If you need to resume subscribing to the audio stream of a specified user, call \ref IRtcEngine::muteRemoteAudioStream "muteRemoteAudioStream" (false), and specify the user ID. + * - If you need to resume subscribing to the audio streams of multiple remote users, call \ref IRtcEngine::muteRemoteAudioStream "muteRemoteAudioStream" (false) multiple times. + * + * @param mute Sets whether to stop subscribing to the audio streams of all remote users by default. + * - true: Stop subscribing to the audio streams of all remote users by default. + * - false: (Default) Resume subscribing to the audio streams of all remote users by default. + * + * @return + * - 0: Success. + * - < 0: Failure. + */ + virtual int setDefaultMuteAllRemoteAudioStreams(bool mute) AGORA_DEPRECATED_ATTRIBUTE = 0; + + /** Adjusts the playback signal volume of a specified remote user. + * + * You can call this method as many times as necessary to adjust the playback volume of different remote users, or to repeatedly adjust the playback volume of the same remote user. + * + * @note + * - Call this method after joining a channel. + * - The playback volume here refers to the mixed volume of a specified remote user. + * - This method can only adjust the playback volume of one specified remote user at a time. To adjust the playback volume of different remote users, call the method as many times, once for each remote user. + * + * @param uid The ID of the remote user. + * @param volume The playback volume of the specified remote user. The value + * ranges between 0 and 400, including the following: + * - 0: Mute. + * - 100: (Default) Original volume. + * - 400: Four times the original volume with signal-clipping protection. + * + * @return + * - 0: Success. + * - < 0: Failure. + */ + virtual int adjustUserPlaybackSignalVolume(unsigned int uid, int volume) = 0; + /** + * Stops or resumes subscribing to the audio stream of a specified user. + * + * @note + * - Call this method after joining a channel. + * - See recommended settings in *Set the Subscribing State*. + * + * @param userId The user ID of the specified remote user. + * @param mute Sets whether to stop subscribing to the audio stream of a specified user. + * - true: Stop subscribing to the audio stream of a specified user. + * - false: (Default) Resume subscribing to the audio stream of a specified user. + * + * @return + * - 0: Success. + * - < 0: Failure. + */ + virtual int muteRemoteAudioStream(uid_t userId, bool mute) = 0; + /** Stops or resumes publishing the local video stream. + * + * As of v3.4.5, this method only sets the publishing state of the video stream in the channel of IRtcEngine. + * + * A successful method call triggers the \ref IRtcEngineEventHandler::onUserMuteVideo "onUserMuteVideo" + * callback on the remote client. + * + * You can only publish the local stream in one channel at a time. If you create multiple channels, + * ensure that you only call \ref IRtcEngine::muteLocalVideoStream "muteLocalVideoStream" (false) in one channel; + * otherwise, the method call fails, and the SDK returns `-5 (ERR_REFUSED)`. + * + * @note + * - This method does not change the usage state of the video-capturing device. + * - Whether this method call takes effect is affected by the + * \ref IRtcEngine::joinChannel(const char* token, const char* channelId, const char* info, uid_t uid, const ChannelMediaOptions& options) "joinChannel" [2/2] + * and \ref IRtcEngine::setClientRole "setClientRole" methods. For details, see *Set the Publishing State*. + * + * @param mute Sets whether to stop publishing the local video stream. + * - true: Stop publishing the local video stream. + * - false: Resume publishing the local video stream. + * + * @return + * - 0: Success. + * - < 0: Failure. + * - `-5 (ERR_REFUSED)`: The request is rejected. + */ + virtual int muteLocalVideoStream(bool mute) = 0; + /** Enables/Disables the local video capture. + + This method disables or re-enables the local video capturer, and does not affect receiving the remote video stream. + + After you call the \ref agora::rtc::IRtcEngine::enableVideo "enableVideo" method, the local video capturer is enabled by default. You can call \ref agora::rtc::IRtcEngine::enableLocalVideo "enableLocalVideo(false)" to disable the local video capturer. If you want to re-enable it, call \ref agora::rtc::IRtcEngine::enableLocalVideo "enableLocalVideo(true)". + + After the local video capturer is successfully disabled or re-enabled, the SDK triggers the \ref agora::rtc::IRtcEngineEventHandler::onUserEnableLocalVideo "onUserEnableLocalVideo" callback on the remote client. + + @note + - You can call this method either before or after joining a channel. + - This method affects the internal engine and can be called after the \ref agora::rtc::IRtcEngine::leaveChannel "leaveChannel" method. + + @param enabled Sets whether to disable/re-enable the local video, including the capturer, renderer, and sender: + - true: (Default) Re-enable the local video. + - false: Disable the local video. Once the local video is disabled, the remote users can no longer receive the video stream of this user, while this user can still receive the video streams of the other remote users. + + @return + - 0: Success. + - < 0: Failure. + */ + virtual int enableLocalVideo(bool enabled) = 0; + /** + * Stops or resumes subscribing to the video streams of all remote users. + * + * After successfully calling this method, the local user stops or resumes + * subscribing to the video streams of all remote users, including all subsequent users. + * + * @note + * - Call this method after joining a channel. + * - See recommended settings in *Set the Subscribing State*. + * + * @param mute Sets whether to stop subscribing to the video streams of all remote users. + * - true: Stop subscribing to the video streams of all remote users. + * - false: (Default) Resume subscribing to the video streams of all remote users. + * + * @return + * - 0: Success. + * - < 0: Failure. + */ + virtual int muteAllRemoteVideoStreams(bool mute) = 0; + /** Stops or resumes subscribing to the video streams of all remote users by default. + * + * @deprecated This method is deprecated from v3.3.0. + * + * Call this method after joining a channel. After successfully calling this method, the + * local user stops or resumes subscribing to the video streams of all subsequent users. + * + * @note If you need to resume subscribing to the video streams of remote users in the + * channel after calling \ref IRtcEngine::setDefaultMuteAllRemoteVideoStreams "setDefaultMuteAllRemoteVideoStreams" (true), do the following: + * - If you need to resume subscribing to the video stream of a specified user, call \ref IRtcEngine::muteRemoteVideoStream "muteRemoteVideoStream" (false), and specify the user ID. + * - If you need to resume subscribing to the video streams of multiple remote users, call \ref IRtcEngine::muteRemoteVideoStream "muteRemoteVideoStream" (false) multiple times. + * + * @param mute Sets whether to stop subscribing to the video streams of all remote users by default. + * - true: Stop subscribing to the video streams of all remote users by default. + * - false: (Default) Resume subscribing to the video streams of all remote users by default. + * + * @return + * - 0: Success. + * - < 0: Failure. + */ + virtual int setDefaultMuteAllRemoteVideoStreams(bool mute) AGORA_DEPRECATED_ATTRIBUTE = 0; + /** + * Stops or resumes subscribing to the video stream of a specified user. + * + * @note + * - Call this method after joining a channel. + * - See recommended settings in *Set the Subscribing State*. + * + * @param userId The user ID of the specified remote user. + * @param mute Sets whether to stop subscribing to the video stream of a specified user. + * - true: Stop subscribing to the video stream of a specified user. + * - false: (Default) Resume subscribing to the video stream of a specified user. + * + * @return + * - 0: Success. + * - < 0: Failure. + */ + virtual int muteRemoteVideoStream(uid_t userId, bool mute) = 0; + /** Sets the stream type of the remote video. + + Under limited network conditions, if the publisher has not disabled the dual-stream mode using `enableDualStreamMode(false)`, + the receiver can choose to receive either the high-quality video stream (the high resolution, and high bitrate video stream) or + the low-video stream (the low resolution, and low bitrate video stream). + + By default, users receive the high-quality video stream. Call this method if you want to switch to the low-video stream. + This method allows the app to adjust the corresponding video stream type based on the size of the video window to + reduce the bandwidth and resources. + + The aspect ratio of the low-video stream is the same as the high-quality video stream. Once the resolution of the high-quality video + stream is set, the system automatically sets the resolution, frame rate, and bitrate of the low-video stream. + + The method result returns in the \ref agora::rtc::IRtcEngineEventHandler::onApiCallExecuted "onApiCallExecuted" callback. + + @note You can call this method either before or after joining a channel. If you call both + \ref IRtcEngine::setRemoteVideoStreamType "setRemoteVideoStreamType" and + \ref IRtcEngine::setRemoteDefaultVideoStreamType "setRemoteDefaultVideoStreamType", the SDK applies the settings in + the \ref IRtcEngine::setRemoteVideoStreamType "setRemoteVideoStreamType" method. + + @param userId ID of the remote user sending the video stream. + @param streamType Sets the video-stream type. See #REMOTE_VIDEO_STREAM_TYPE. + @return + - 0: Success. + - < 0: Failure. + */ + virtual int setRemoteVideoStreamType(uid_t userId, REMOTE_VIDEO_STREAM_TYPE streamType) = 0; + /** Sets the default stream type of remote videos. + + Under limited network conditions, if the publisher has not disabled the dual-stream mode using `enableDualStreamMode(false)`, + the receiver can choose to receive either the high-quality video stream (the high resolution, and high bitrate video stream) or + the low-video stream (the low resolution, and low bitrate video stream). + + By default, users receive the high-quality video stream. Call this method if you want to switch to the low-video stream. + This method allows the app to adjust the corresponding video stream type based on the size of the video window to + reduce the bandwidth and resources. The aspect ratio of the low-video stream is the same as the high-quality video stream. + Once the resolution of the high-quality video + stream is set, the system automatically sets the resolution, frame rate, and bitrate of the low-video stream. + + The method result returns in the \ref agora::rtc::IRtcEngineEventHandler::onApiCallExecuted "onApiCallExecuted" callback. + + @note You can call this method either before or after joining a channel. If you call both + \ref IRtcEngine::setRemoteVideoStreamType "setRemoteVideoStreamType" and + \ref IRtcEngine::setRemoteDefaultVideoStreamType "setRemoteDefaultVideoStreamType", the SDK applies the settings in + the \ref IRtcEngine::setRemoteVideoStreamType "setRemoteVideoStreamType" method. + + @param streamType Sets the default video-stream type. See #REMOTE_VIDEO_STREAM_TYPE. + + @return + - 0: Success. + - < 0: Failure. + */ + virtual int setRemoteDefaultVideoStreamType(REMOTE_VIDEO_STREAM_TYPE streamType) = 0; + + /** Enables the reporting of users' volume indication. + + This method enables the SDK to regularly report the volume information of the local user who sends a stream and + remote users (up to three) whose instantaneous volumes are the highest to the app. Once you call this method and + users send streams in the channel, the SDK triggers the + \ref IRtcEngineEventHandler::onAudioVolumeIndication "onAudioVolumeIndication" callback at the time interval set + in this method. + + @note You can call this method either before or after joining a channel. + + @param interval Sets the time interval between two consecutive volume indications: + - ≤ 0: Disables the volume indication. + - > 0: Time interval (ms) between two consecutive volume indications. We recommend setting @p interval > 200 ms. Do not set @p interval < 10 ms, or the *onAudioVolumeIndication* callback will not be triggered. + @param smooth Smoothing factor sets the sensitivity of the audio volume indicator. The value ranges between 0 and 10. The greater the value, the more sensitive the indicator. The recommended value is 3. + @param report_vad + - true: Enable the voice activity detection of the local user. Once it is enabled, the `vad` parameter of the `onAudioVolumeIndication` callback reports the voice activity status of the local user. + - false: (Default) Disable the voice activity detection of the local user. Once it is disabled, the `vad` parameter of the `onAudioVolumeIndication` callback does not report the voice activity status of the local user, except for the scenario where the engine automatically detects the voice activity of the local user. + @return + - 0: Success. + - < 0: Failure. + */ + virtual int enableAudioVolumeIndication(int interval, int smooth, bool report_vad) = 0; + /** Starts an audio recording. + + @deprecated Deprecated from v2.9.1. + Use \ref IRtcEngine::startAudioRecording(const AudioRecordingConfiguration&) "startAudioRecording" [3/3] instead. + + The SDK allows recording during a call. Supported formats: + + - .wav: Large file size with high fidelity. + - .aac: Small file size with low fidelity. + + This method has a fixed sample rate of 32 kHz. + + Ensure that the directory to save the recording file exists and is writable. + This method is usually called after the \ref agora::rtc::IRtcEngine::joinChannel "joinChannel" method. + The recording automatically stops when the \ref agora::rtc::IRtcEngine::leaveChannel "leaveChannel" method is called. + + @param filePath Pointer to the absolute file path of the recording file. The string of the file name is in UTF-8. + @param quality Sets the audio recording quality. See #AUDIO_RECORDING_QUALITY_TYPE. + + @return + - 0: Success. + - < 0: Failure. + */ + virtual int startAudioRecording(const char* filePath, AUDIO_RECORDING_QUALITY_TYPE quality) AGORA_DEPRECATED_ATTRIBUTE = 0; + + /** Starts an audio recording on the client. + * + * @deprecated Deprecated from v3.4.0. Use + * \ref IRtcEngine::startAudioRecording(const AudioRecordingConfiguration&) "startAudioRecording" [3/3] instead. + * + * The SDK allows recording during a call. After successfully calling this method, you can record the audio of all the users in the channel and get an audio recording file. + * Supported formats of the recording file are as follows: + * - .wav: Large file size with high fidelity. + * - .aac: Small file size with low fidelity. + * + * @note + * - Ensure that the directory you use to save the recording file exists and is writable. + * - This method is usually called after the `joinChannel` method. The recording automatically stops when you call the `leaveChannel` method. + * - For better recording effects, set quality as #AUDIO_RECORDING_QUALITY_MEDIUM or #AUDIO_RECORDING_QUALITY_HIGH when `sampleRate` is 44.1 kHz or 48 kHz. + * + * @param filePath Pointer to the absolute file path of the recording file. The string of the file name is in UTF-8, such as c:/music/audio.aac. + * @param sampleRate Sample rate (Hz) of the recording file. Supported values are as follows: + * - 16000 + * - (Default) 32000 + * - 44100 + * - 48000 + * @param quality Sets the audio recording quality. See #AUDIO_RECORDING_QUALITY_TYPE. + * + * @return + * - 0: Success. + * - < 0: Failure. + */ + virtual int startAudioRecording(const char* filePath, int sampleRate, AUDIO_RECORDING_QUALITY_TYPE quality) AGORA_DEPRECATED_ATTRIBUTE = 0; + /** + * Starts an audio recording on the client. + * + * @since v3.4.0 + * + * The SDK allows recording audio during a call. After successfully calling + * this method, you can record the audio of users in the channel and get + * an audio recording file. Supported file formats are as follows: + * - WAV: High-fidelity files with typically larger file sizes. For example, + * if the sample rate is 32,000 Hz, the file size for a 10-minute recording + * is approximately 73 MB. + * - AAC: Low-fidelity files with typically smaller file sizes. For example, + * if the sample rate is 32,000 Hz and the recording quality is + * #AUDIO_RECORDING_QUALITY_MEDIUM, the file size for a 10-minute recording + * is approximately 2 MB. + * + * Once the user leaves the channel, the recording automatically stops. + * + * @note Call this method after joining a channel. + * + * @param config Recording configuration. See AudioRecordingConfiguration. + * + * @return + * - 0: Success. + * - < 0: Failure. + * - `-160(ERR_ALREADY_IN_RECORDING)`: The client is already recording + * audio. To start a new recording, + * call \ref IRtcEngine::stopAudioRecording "stopAudioRecording" to stop the + * current recording first, and then + * call \ref IRtcEngine::startAudioRecording(const AudioRecordingConfiguration&) "startAudioRecording". + */ + virtual int startAudioRecording(const AudioRecordingConfiguration& config) = 0; + /** Stops an audio recording on the client. + + @return + - 0: Success + - < 0: Failure. + */ + virtual int stopAudioRecording() = 0; + + /** Starts playing and mixing the music file. + * + * @deprecated Deprecated from v3.4.0. Use + * \ref IRtcEngine::startAudioMixing(const char*,bool,bool,int,int) "startAudioMixing" [2/2] instead. + * + * This method mixes the specified local audio file with the audio stream from the microphone, or replaces the microphone's audio stream with the specified local audio file. You can choose whether the other user can hear the local audio playback and specify the number of playback loops. This method also supports online music playback. + * + * When the audio mixing file playback finishes after calling this method, the SDK triggers the \ref agora::rtc::IRtcEngineEventHandler::onAudioMixingFinished "onAudioMixingFinished" callback. + * + * A successful \ref IRtcEngine::startAudioMixing(const char*,bool,bool,int,int) "startAudioMixing" method call triggers the \ref agora::rtc::IRtcEngineEventHandler::onAudioMixingStateChanged "onAudioMixingStateChanged" (PLAY) callback on the local client. + * + * When the audio mixing file playback finishes, the SDK triggers the \ref agora::rtc::IRtcEngineEventHandler::onAudioMixingStateChanged "onAudioMixingStateChanged" (STOPPED) callback on the local client. + * + * @note + * - If the local audio mixing file does not exist, or if the SDK does not support the file format or cannot access the music file URL, the SDK returns #WARN_AUDIO_MIXING_OPEN_ERROR (701). + * - If you want to play an online music file, ensure that the time interval between calling this method is more than 100 ms, or the `AUDIO_MIXING_ERROR_TOO_FREQUENT_CALL(702)` error code occurs. + * - To avoid blocking, as of v3.4.5, this method changes from a synchronous call to an asynchronous call. + * - For the audio file formats supported by this method, see [What formats of audio files does the Agora RTC SDK support](https://docs.agora.io/en/faq/audio_format). + * + * @param filePath The absolute path or URL address (including the filename extensions) + * of the music file. For example: `C:\music\audio.mp4`. + * When you access a local file on Android, Agora recommends passing a URI address or the path starts + * with `/assets/` in this parameter. + * @param loopback Sets which user can hear the audio mixing: + * - true: Only the local user can hear the audio mixing. + * - false: Both users can hear the audio mixing. + * @param replace Sets the audio mixing content: + * - true: Only publish the specified audio file. The audio stream from the microphone is not published. + * - false: The local audio file is mixed with the audio stream from the microphone. + * @param cycle Sets the number of playback loops: + * - Positive integer: Number of playback loops. + * - `-1`: Infinite playback loops. + * + * @return + * - 0: Success. + * - < 0: Failure. + */ + virtual int startAudioMixing(const char* filePath, bool loopback, bool replace, int cycle) AGORA_DEPRECATED_ATTRIBUTE = 0; + /** + * Starts playing and mixing the music file. + * + * @since v3.4.0 + * + * This method supports mixing or replacing local or online music file and + * audio collected by a microphone. After successfully playing the music + * file, the SDK triggers + * \ref IRtcEngineEventHandler::onAudioMixingStateChanged "onAudioMixingStateChanged" (AUDIO_MIXING_STATE_PLAYING,AUDIO_MIXING_REASON_STARTED_BY_USER). + * After completing playing the music file, the SDK triggers + * `onAudioMixingStateChanged(AUDIO_MIXING_STATE_STOPPED,AUDIO_MIXING_REASON_ALL_LOOPS_COMPLETED)`. + * + * @note + * - If you need to call + * \ref IRtcEngine::startAudioMixing(const char*,bool,bool,int,int) "startAudioMixing" multiple times, + * ensure that the call interval is longer than 500 ms. + * - If the local music file does not exist, or if the SDK does not support + * the file format or cannot access the music file URL, the SDK returns + * #WARN_AUDIO_MIXING_OPEN_ERROR (701). + * - On Android: + * - To use this method, ensure that the Android device is v4.2 or later + * and the API version is v16 or later. + * - If you need to play an online music file, Agora does not recommend + * using the redirected URL address. Some Android devices may fail to open a redirected URL address. + * - If you call this method on an emulator, ensure that the music file is + * in the `/sdcard/` directory and the format is MP3. + * - To avoid blocking, as of v3.4.5, this method changes from a synchronous call to an asynchronous call. + * - For the audio file formats supported by this method, see [What formats of audio files does the Agora RTC SDK support](https://docs.agora.io/en/faq/audio_format). + * + * @param filePath The absolute path or URL address (including the filename extensions) + * of the music file. For example: `C:\music\audio.mp4`. + * When you access a local file on Android, Agora recommends passing a URI address or the path starts + * with `/assets/` in this parameter. + * @param loopback Whether to only play the music file on the local client: + * - true: Only play the music file on the local client so that only the local + * user can hear the music. + * - false: Publish the music file to remote clients so that both the local + * user and remote users can hear the music. + * @param replace Whether to replace the audio collected by the microphone + * with a music file: + * - true: Replace. Users can only hear music. + * - false: Do not replace. Users can hear both music and audio collected by + * the microphone. + * @param cycle The number of times the music file plays. + * - ≥ 0: The number of playback times. For example, `0` means that the + * SDK does not play the music file, while `1` means that the SDK plays the + * music file once. + * - `-1`: Play the music in an indefinite loop. + * @param startPos The playback position (ms) of the music file. + * + * @return + * - 0: Success. + * - < 0: Failure. + */ + virtual int startAudioMixing(const char* filePath, bool loopback, bool replace, int cycle, int startPos) = 0; + /** + * Sets the playback speed of the current music file. + * + * @since v3.5.1 + * + * @note Call this method after calling \ref IRtcEngine::startAudioMixing(const char*,bool,bool,int,int) "startAudioMixing" [2/2] + * and receiving the \ref IRtcEngineEventHandler::onAudioMixingStateChanged "onAudioMixingStateChanged" (AUDIO_MIXING_STATE_PLAYING) callback. + * + * @param speed The playback speed. Agora recommends that you limit this value to between 50 and 400, defined as follows: + * - 50: Half the original speed. + * - 100: The original speed. + * - 400: 4 times the original speed. + * + * @return + * - 0: Success. + * - < 0: Failure. + */ + virtual int setAudioMixingPlaybackSpeed(int speed) = 0; + /** Stops playing and mixing the music file. + + Call this method when you are in a channel. + + @return + - 0: Success. + - < 0: Failure. + */ + virtual int stopAudioMixing() = 0; + /** Pauses playing and mixing the music file. + + Call this method when you are in a channel. + + @return + - 0: Success. + - < 0: Failure. + */ + virtual int pauseAudioMixing() = 0; + /** + * Specifies the playback track of the current music file. + * + * @since v3.5.1 + * + * After getting the audio track index of the current music file, call this + * method to specify any audio track to play. For example, if different tracks + * of a multitrack file store songs in different languages, you can call this + * method to set the language of the music file to play. + * + * @note + * - This method is for Android, iOS, and Windows only. + * - Call this method after calling \ref IRtcEngine::startAudioMixing(const char*,bool,bool,int,int) "startAudioMixing" [2/2] + * and receiving the \ref IRtcEngineEventHandler::onAudioMixingStateChanged "onAudioMixingStateChanged" (AUDIO_MIXING_STATE_PLAYING) callback. + * - For the audio file formats supported by this method, see [What formats of audio files does the Agora RTC SDK support](https://docs.agora.io/en/faq/audio_format). + * + * @param index The specified playback track. This parameter must be less than or equal to the return value + * of \ref IRtcEngine::getAudioTrackCount "getAudioTrackCount". + * + * @return + * - 0: Success. + * - < 0: Failure. + */ + virtual int selectAudioTrack(int index) = 0; + /** + * Gets the audio track index of the current music file. + * + * @since v3.5.1 + * + * @note + * - This method is for Android, iOS, and Windows only. + * - Call this method after calling \ref IRtcEngine::startAudioMixing(const char*,bool,bool,int,int) "startAudioMixing" [2/2] + * and receiving the \ref IRtcEngineEventHandler::onAudioMixingStateChanged "onAudioMixingStateChanged" (AUDIO_MIXING_STATE_PLAYING) callback. + * - For the audio file formats supported by this method, see [What formats of audio files does the Agora RTC SDK support](https://docs.agora.io/en/faq/audio_format). + * + * @return + * - ≥ 0: The audio track index of the current music file, if this method call succeeds. + * - < 0: Failure. + */ + virtual int getAudioTrackCount() = 0; + /** + * Sets the channel mode of the current music file. + * + * @since v3.5.1 + * + * In a stereo music file, the left and right channels can store different audio data. + * According to your needs, you can set the channel mode to original mode, left channel mode, + * right channel mode, or mixed channel mode. For example, in the KTV scenario, the left + * channel of the music file stores the musical accompaniment, and the right channel + * stores the singing voice. If you only need to listen to the accompaniment, call this + * method to set the channel mode of the music file to left channel mode; if you need to + * listen to the accompaniment and the singing voice at the same time, call this method + * to set the channel mode to mixed channel mode. + * + * @note + * - Call this method after calling \ref IRtcEngine::startAudioMixing(const char*,bool,bool,int,int) "startAudioMixing" [2/2] + * and receiving the \ref IRtcEngineEventHandler::onAudioMixingStateChanged "onAudioMixingStateChanged" (AUDIO_MIXING_STATE_PLAYING) callback. + * - This method only applies to stereo audio files. + * + * @param mode The channel mode. See \ref agora::media::AUDIO_MIXING_DUAL_MONO_MODE "AUDIO_MIXING_DUAL_MONO_MODE". + * + * @return + * - 0: Success. + * - < 0: Failure. + */ + virtual int setAudioMixingDualMonoMode(agora::media::AUDIO_MIXING_DUAL_MONO_MODE mode) = 0; + /** Resumes playing and mixing the music file. + + Call this method when you are in a channel. + + @return + - 0: Success. + - < 0: Failure. + */ + virtual int resumeAudioMixing() = 0; + /** **DEPRECATED** Agora does not recommend using this method. + + Sets the high-quality audio preferences. Call this method and set all parameters before joining a channel. + + Do not call this method again after joining a channel. + + @param fullband Sets whether to enable/disable full-band codec (48-kHz sample rate). Not compatible with SDK versions before v1.7.4: + - true: Enable full-band codec. + - false: Disable full-band codec. + @param stereo Sets whether to enable/disable stereo codec. Not compatible with SDK versions before v1.7.4: + - true: Enable stereo codec. + - false: Disable stereo codec. + @param fullBitrate Sets whether to enable/disable high-bitrate mode. Recommended in voice-only mode: + - true: Enable high-bitrate mode. + - false: Disable high-bitrate mode. + + @return + - 0: Success. + - < 0: Failure. + */ + virtual int setHighQualityAudioParameters(bool fullband, bool stereo, bool fullBitrate) = 0; + /** Adjusts the volume during audio mixing. + + @note + - Calling this method does not affect the volume of audio effect file playback invoked by the \ref IRtcEngine::playEffect(int,const char*,int,double,double,int,bool,int) "playEffect" method. + - Call this method after calling \ref IRtcEngine::startAudioMixing(const char*,bool,bool,int,int) "startAudioMixing" and receiving the \ref IRtcEngineEventHandler::onAudioMixingStateChanged "onAudioMixingStateChanged" (AUDIO_MIXING_STATE_PLAYING) callback. + + @param volume Audio mixing volume. The value ranges between 0 and 100 (default). + + @return + - 0: Success. + - < 0: Failure. + */ + virtual int adjustAudioMixingVolume(int volume) = 0; + /** Adjusts the audio mixing volume for local playback. + + @note Call this method after calling \ref IRtcEngine::startAudioMixing(const char*,bool,bool,int,int) "startAudioMixing" and receiving the \ref IRtcEngineEventHandler::onAudioMixingStateChanged "onAudioMixingStateChanged" (AUDIO_MIXING_STATE_PLAYING) callback. + + @param volume Audio mixing volume for local playback. The value ranges between 0 and 100 (default). + + @return + - 0: Success. + - < 0: Failure. + */ + virtual int adjustAudioMixingPlayoutVolume(int volume) = 0; + /** Gets the audio mixing volume for local playback. + + This method helps troubleshoot audio volume related issues. + + @note + - Call this method when you are in a channel. + - Call this method after calling \ref IRtcEngine::startAudioMixing(const char*,bool,bool,int,int) "startAudioMixing" and receiving the \ref IRtcEngineEventHandler::onAudioMixingStateChanged "onAudioMixingStateChanged" (AUDIO_MIXING_STATE_PLAYING) callback. + + @return + - ≥ 0: The audio mixing volume, if this method call succeeds. The value range is [0,100]. + - < 0: Failure. + */ + virtual int getAudioMixingPlayoutVolume() = 0; + /** Adjusts the audio mixing volume for publishing (for remote users). + + @note Call this method after calling \ref IRtcEngine::startAudioMixing(const char*,bool,bool,int,int) "startAudioMixing" and receiving the \ref IRtcEngineEventHandler::onAudioMixingStateChanged "onAudioMixingStateChanged" (AUDIO_MIXING_STATE_PLAYING) callback. + + @param volume Audio mixing volume for publishing. The value ranges between 0 and 100 (default). + + @return + - 0: Success. + - < 0: Failure. + */ + virtual int adjustAudioMixingPublishVolume(int volume) = 0; + /** Gets the audio mixing volume for publishing. + + This method helps troubleshoot audio volume related issues. + + @note + - Call this method when you are in a channel. + - Call this method after calling \ref IRtcEngine::startAudioMixing(const char*,bool,bool,int,int) "startAudioMixing" and receiving the \ref IRtcEngineEventHandler::onAudioMixingStateChanged "onAudioMixingStateChanged" (AUDIO_MIXING_STATE_PLAYING) callback. + + @return + - ≥ 0: The audio mixing volume for publishing, if this method call succeeds. The value range is [0,100]. + - < 0: Failure. + */ + virtual int getAudioMixingPublishVolume() = 0; + + /** Gets the duration (ms) of the music file. + * + * @deprecated This method is deprecated as of v3.5.1. Use \ref IRtcEngine::getAudioFileInfo "getAudioFileInfo" instead. + * + * @note + * - Call this method when you are in a channel. + * - Call this method after calling \ref IRtcEngine::startAudioMixing(const char*,bool,bool,int,int) "startAudioMixing" + * and receiving the \ref IRtcEngineEventHandler::onAudioMixingStateChanged "onAudioMixingStateChanged" (AUDIO_MIXING_STATE_PLAYING) callback. + * + * @return + * - ≥ 0: The audio mixing duration, if this method call succeeds. + * - < 0: Failure. + */ + virtual int getAudioMixingDuration() AGORA_DEPRECATED_ATTRIBUTE = 0; + /** Gets the playback position (ms) of the music file. + * + * @note + * - Call this method after calling \ref IRtcEngine::startAudioMixing(const char*,bool,bool,int,int) "startAudioMixing" and receiving the \ref IRtcEngineEventHandler::onAudioMixingStateChanged "onAudioMixingStateChanged" (AUDIO_MIXING_STATE_PLAYING) callback. + * - If you need to call `getAudioMixingCurrentPosition` multiple times, ensure that the call interval is longer than 500 ms. + * + * @return + * - ≥ 0: The current playback position (ms) of the music file, if this method call succeeds. 0 represents that the current music file does not start playing. + * - < 0: Failure. + */ + virtual int getAudioMixingCurrentPosition() = 0; + /** Sets the playback position of the music file to a different starting position (the default plays from the beginning). + + @note Call this method after calling \ref IRtcEngine::startAudioMixing(const char*,bool,bool,int,int) "startAudioMixing" and receiving the \ref IRtcEngineEventHandler::onAudioMixingStateChanged "onAudioMixingStateChanged" (AUDIO_MIXING_STATE_PLAYING) callback. + + @param pos The playback starting position (ms) of the music file. + + @return + - 0: Success. + - < 0: Failure. + */ + virtual int setAudioMixingPosition(int pos /*in ms*/) = 0; + /** Sets the pitch of the local music file. + * @since v3.0.1 + * + * When a local music file is mixed with a local human voice, call this method to set the pitch of the local music file only. + * + * @note Call this method after calling \ref IRtcEngine::startAudioMixing(const char*,bool,bool,int,int) "startAudioMixing" and receiving the \ref IRtcEngineEventHandler::onAudioMixingStateChanged "onAudioMixingStateChanged" (AUDIO_MIXING_STATE_PLAYING) callback. + * + * @param pitch Sets the pitch of the local music file by chromatic scale. The default value is 0, + * which means keeping the original pitch. The value ranges from -12 to 12, and the pitch value between + * consecutive values is a chromatic value. The greater the absolute value of this parameter, the + * higher or lower the pitch of the local music file. + * + * @return + * - 0: Success. + * - < 0: Failure. + */ + virtual int setAudioMixingPitch(int pitch) = 0; + /** Gets the volume of the audio effects. + + The value ranges between 0.0 and 100.0. + + @note Ensure that this method is called after \ref IRtcEngine::playEffect(int,const char*,int,double,double,int,bool,int) "playEffect" . + + @return + - ≥ 0: Volume of the audio effects, if this method call succeeds. + + - < 0: Failure. + */ + virtual int getEffectsVolume() = 0; + /** Sets the volume of the audio effects. + + @note Ensure that this method is called after \ref IRtcEngine::playEffect(int,const char*,int,double,double,int,bool,int) "playEffect" . + + @param volume Sets the volume of the audio effects. The value ranges between 0 and 100 (default). + + @return + - 0: Success. + - < 0: Failure. + */ + virtual int setEffectsVolume(int volume) = 0; + /** Sets the volume of a specified audio effect. + + @note Ensure that this method is called after \ref IRtcEngine::playEffect(int,const char*,int,double,double,int,bool,int) "playEffect" . + + @param soundId ID of the audio effect. Each audio effect has a unique ID. + @param volume Sets the volume of the specified audio effect. The value ranges between 0 and 100 (default). + + @return + - 0: Success. + - < 0: Failure. + */ + virtual int setVolumeOfEffect(int soundId, int volume) = 0; + +#if defined(__ANDROID__) || (defined(__APPLE__) && TARGET_OS_IOS) + /** + * Enables/Disables face detection for the local user. + * + * @since v3.0.1 + * + * @note + * - Applies to Android and iOS only. + * - You can call this method either before or after joining a channel. + * + * Once face detection is enabled, the SDK triggers the \ref IRtcEngineEventHandler::onFacePositionChanged "onFacePositionChanged" callback + * to report the face information of the local user, which includes the following aspects: + * - The width and height of the local video. + * - The position of the human face in the local video. + * - The distance between the human face and the device screen. + * + * @param enable Determines whether to enable the face detection function for the local user: + * - true: Enable face detection. + * - false: (Default) Disable face detection. + * @return + * - 0: Success. + * - < 0: Failure. + */ + virtual int enableFaceDetection(bool enable) = 0; +#endif + /** Plays a specified local or online audio effect file. + * + * @deprecated Deprecated from v3.4.0. Use + * \ref IRtcEngine::playEffect(int,const char*,int,double,double,int,bool,int) "playEffect" [2/2] instead. + * + * This method allows you to set the loop count, pitch, pan, and gain of the audio effect file, as well as whether the remote user can hear the audio effect. + * + * To play multiple audio effect files simultaneously, call this method multiple times with different soundIds and filePaths. We recommend playing no more than three audio effect files at the same time. + * + * @note + * - If the audio effect is preloaded into the memory through the \ref IRtcEngine::preloadEffect "preloadEffect" method, the value of @p soundID must be the same as that in the *preloadEffect* method. + * - Playing multiple online audio effect files simultaneously is not supported on macOS and Windows. + * - Ensure that you call this method after joining a channel. + * - For the audio file formats supported by this method, see [What formats of audio files does the Agora RTC SDK support](https://docs.agora.io/en/faq/audio_format). + * + * @param soundId ID of the specified audio effect. Each audio effect has a unique ID. + * @param filePath The absolute path or URL address (including the filename extensions) + * of the music file. For example: `C:\music\audio.mp4`. + * When you access a local file on Android, Agora recommends passing a URI address or the path starts + * with `/assets/` in this parameter. + * @param loopCount Sets the number of times the audio effect loops: + * - 0: Play the audio effect once. + * - 1: Play the audio effect twice. + * - -1: Play the audio effect in an indefinite loop until the \ref IRtcEngine::stopEffect "stopEffect" or \ref IRtcEngine::stopAllEffects "stopAllEffects" method is called. + * @param pitch Sets the pitch of the audio effect. The value ranges between 0.5 and 2. The default value is 1 (no change to the pitch). The lower the value, the lower the pitch. + * @param pan Sets the spatial position of the audio effect. The value ranges between -1.0 and 1.0: + * - 0.0: The audio effect displays ahead. + * - 1.0: The audio effect displays to the right. + * - -1.0: The audio effect displays to the left. + * @param gain Sets the volume of the audio effect. The value ranges between 0 and 100 (default). The lower the value, the lower the volume of the audio effect. + * @param publish Sets whether to publish the specified audio effect to the remote stream: + * - true: The locally played audio effect is published to the Agora Cloud and the remote users can hear it. + * - false: The locally played audio effect is not published to the Agora Cloud and the remote users cannot hear it. + * @return + * - 0: Success. + * - < 0: Failure. + */ + virtual int playEffect(int soundId, const char* filePath, int loopCount, double pitch, double pan, int gain, bool publish = false) AGORA_DEPRECATED_ATTRIBUTE = 0; + /** + * Plays a specified local or online audio effect file. + * + * @since v3.4.0 + * + * To play multiple audio effect files at the same time, call this method + * multiple times with different `soundId` and `filePath` values. For the + * best user experience, Agora recommends playing no more than three audio + * effect files at the same time. + * + * After completing playing an audio effect file, the SDK triggers the + * \ref IRtcEngineEventHandler::onAudioEffectFinished "onAudioEffectFinished" + * callback. + * + * @note + * - Call this method after joining a channel. + * - For the audio file formats supported by this method, see [What formats of audio files does the Agora RTC SDK support](https://docs.agora.io/en/faq/audio_format). + * + * @param soundId Audio effect ID. The ID of each audio effect file is + * unique. If you preloaded an audio effect into memory by calling + * \ref IRtcEngine::preloadEffect "preloadEffect", ensure that this + * parameter is set to the same value as in `preloadEffect`. + * @param filePath The absolute path or URL address (including the filename extensions) + * of the music file. For example: `C:\music\audio.mp4`. + * If you preloaded an audio effect into memory by calling + * \ref IRtcEngine::preloadEffect "preloadEffect", ensure that this + * parameter is set to the same value as in `preloadEffect`. + * When you access a local file on Android, Agora recommends passing a URI address or the path starts + * with `/assets/` in this parameter. + * + * @param loopCount The number of times the audio effect loops: + * - ≥ 0: The number of loops. For example, `1` means loop one time, + * which means play the audio effect two times in total. + * - `-1`: Play the audio effect in an indefinite loop. + * @param pitch The pitch of the audio effect. The range is 0.5 to 2.0. + * The default value is 1.0, which means the original pitch. The lower the + * value, the lower the pitch. + * @param pan The spatial position of the audio effect. The range is `-1.0` + * to `1.0`. For example: + * - `-1.0`: The audio effect occurs on the left. + * - `0.0`: The audio effect occurs in the front. + * - `1.0`: The audio effect occurs on the right. + * @param gain The volume of the audio effect. The range is 0.0 to 100.0. + * The default value is 100.0, which means the original volume. The smaller + * the value, the less the gain. + * @param publish Whether to publish the audio effect to the remote users: + * - true: Publish. Both the local user and remote users can hear the audio + * effect. + * - false: Do not publish. Only the local user can hear the audio effect. + * @param startPos The playback position (ms) of the audio effect file. + * + * @return + * - 0: Success. + * - < 0: Failure. + */ + virtual int playEffect(int soundId, const char* filePath, int loopCount, double pitch, double pan, int gain, bool publish, int startPos) = 0; + /** Stops playing a specified audio effect. + + @param soundId ID of the audio effect to stop playing. Each audio effect has a unique ID. + + @return + - 0: Success. + - < 0: Failure. + */ + virtual int stopEffect(int soundId) = 0; + /** Stops playing all audio effects. + + @return + - 0: Success. + - < 0: Failure. + */ + virtual int stopAllEffects() = 0; + + /** Preloads a specified audio effect file into the memory. + * + * To ensure smooth communication, limit the size of the audio effect file. We recommend using this method to preload the audio effect before calling the \ref IRtcEngine::joinChannel "joinChannel" method. + * + * @note This method does not support online audio effect files. For the audio file formats supported by this method, see [What formats of audio files does the Agora RTC SDK support](https://docs.agora.io/en/faq/audio_format). + * + * @param soundId ID of the audio effect. Each audio effect has a unique ID. + * @param filePath The absolute path or URL address (including the filename extensions) + * of the music file. For example: `C:\music\audio.mp4`. + * When you access a local file on Android, Agora recommends passing a URI address or the path starts + * with `/assets/` in this parameter. + * + * @return + * - 0: Success. + * - < 0: Failure. + */ + virtual int preloadEffect(int soundId, const char* filePath) = 0; + /** Releases a specified preloaded audio effect from the memory. + + @param soundId ID of the audio effect. Each audio effect has a unique ID. + @return + - 0: Success. + - < 0: Failure. + */ + virtual int unloadEffect(int soundId) = 0; + /** Pauses a specified audio effect. + + @param soundId ID of the audio effect. Each audio effect has a unique ID. + @return + - 0: Success. + - < 0: Failure. + */ + virtual int pauseEffect(int soundId) = 0; + /** Pauses all audio effects. + + @return + - 0: Success. + - < 0: Failure. + */ + virtual int pauseAllEffects() = 0; + /** Resumes playing a specified audio effect. + + @param soundId ID of the audio effect. Each audio effect has a unique ID. + @return + - 0: Success. + - < 0: Failure. + */ + virtual int resumeEffect(int soundId) = 0; + /** Resumes playing all audio effects. + + @return + - 0: Success. + - < 0: Failure. + */ + virtual int resumeAllEffects() = 0; + /** + * Gets the duration of the audio effect file. + * + * @since v3.4.0 + * + * @note + * - Call this method after joining a channel. + * - For the audio file formats supported by this method, see [What formats of audio files does the Agora RTC SDK support](https://docs.agora.io/en/faq/audio_format). + * + * @param filePath The absolute path or URL address (including the filename extensions) + * of the music file. For example: `C:\music\audio.mp4`. + * When you access a local file on Android, Agora recommends passing a URI address or the path starts + * with `/assets/` in this parameter. + * + * @return + * - ≥ 0: A successful method call. Returns the total duration (ms) of + * the specified audio effect file. + * - < 0: Failure. + * - `-22(ERR_RESOURCE_LIMITED)`: Cannot find the audio effect file. Please + * set a correct `filePath`. + */ + virtual int getEffectDuration(const char* filePath) = 0; + /** + * Sets the playback position of an audio effect file. + * + * @since v3.4.0 + * + * After a successful setting, the local audio effect file starts playing at the specified position. + * + * @note Call this method after \ref IRtcEngine::playEffect(int,const char*,int,double,double,int,bool,int) "playEffect" . + * + * @param soundId Audio effect ID. Ensure that this parameter is set to the + * same value as in \ref IRtcEngine::playEffect(int,const char*,int,double,double,int,bool,int) "playEffect" . + * @param pos The playback position (ms) of the audio effect file. + * + * @return + * - 0: Success. + * - < 0: Failure. + * - `-22(ERR_RESOURCE_LIMITED)`: Cannot find the audio effect file. Please + * set a correct `soundId`. + */ + virtual int setEffectPosition(int soundId, int pos) = 0; + /** + * Gets the playback position of the audio effect file. + * + * @since v3.4.0 + * + * @note Call this method after \ref IRtcEngine::playEffect(int,const char*,int,double,double,int,bool,int) "playEffect" . + * + * @param soundId Audio effect ID. Ensure that this parameter is set to the + * same value as in \ref IRtcEngine::playEffect(int,const char*,int,double,double,int,bool,int) "playEffect" . + * + * @return + * - ≥ 0: A successful method call. Returns the playback position (ms) of + * the specified audio effect file. + * - < 0: Failure. + * - `-22(ERR_RESOURCE_LIMITED)`: Cannot find the audio effect file. Please + * set a correct `soundId`. + */ + virtual int getEffectCurrentPosition(int soundId) = 0; + + /** Gets the information of a specified audio file. + * + * @since v3.5.1 + * + * After calling this method successfully, the SDK triggers the + * \ref IRtcEngineEventHandler::onRequestAudioFileInfo "onRequestAudioFileInfo" + * callback to report the information of an audio file, such as audio duration. + * You can call this method multiple times to get the information of multiple audio files. + * + * @note + * - Call this method after joining a channel. + * - For the audio file formats supported by this method, see [What formats of audio files does the Agora RTC SDK support](https://docs.agora.io/en/faq/audio_format). + * + * @param filePath The file path: + * - Windows: The absolute path or URL address (including the filename extensions) of + * the audio file. For example: `C:\music\audio.mp4`. + * - Android: The file path, including the filename extensions. To access an online file, + * Agora supports using a URL address; to access a local file, Agora supports using a URI + * address, an absolute path, or a path that starts with `/assets/`. You might encounter + * permission issues if you use an absolute path to access a local file, so Agora recommends + * using a URI address instead. For example: `content://com.android.providers.media.documents/document/audio%3A14441`. + * - iOS or macOS: The absolute path or URL address (including the filename extensions) of the audio file. + * For example: `/var/mobile/Containers/Data/audio.mp4`. + * + * @return + * - 0: Success. + * - < 0: Failure. + */ + virtual int getAudioFileInfo(const char* filePath) = 0; + + /** Enables or disables deep-learning noise reduction. + * + * @since v3.3.0 + * + * The SDK enables traditional noise reduction mode by default to reduce most of the stationary background noise. + * If you need to reduce most of the non-stationary background noise, Agora recommends enabling deep-learning + * noise reduction as follows: + * + * 1. Ensure that the dynamical library is integrated in your project: + * - Android: `libagora_ai_denoise_extension.so` + * - iOS: `AgoraAIDenoiseExtension.xcframework` + * - macOS: `AgoraAIDenoiseExtension.framework` + * - Windows: `libagora_ai_denoise_extension.dll` + * 2. Call `enableDeepLearningDenoise(true)`. + * + * Deep-learning noise reduction requires high-performance devices. For example, the following devices and later + * models are known to support deep-learning noise reduction: + * - iPhone 6S + * - MacBook Pro 2015 + * - iPad Pro (2nd generation) + * - iPad mini (5th generation) + * - iPad Air (3rd generation) + * + * After successfully enabling deep-learning noise reduction, if the SDK detects that the device performance + * is not sufficient, it automatically disables deep-learning noise reduction and enables traditional noise reduction. + * + * If you call `enableDeepLearningDenoise(false)` or the SDK automatically disables deep-learning noise reduction + * in the channel, when you need to re-enable deep-learning noise reduction, you need to call \ref IRtcEngine::leaveChannel "leaveChannel" + * first, and then call `enableDeepLearningDenoise(true)`. + * + * @note + * - This method dynamically loads the library, so Agora recommends calling this method before joining a channel. + * - This method works best with the human voice. Agora does not recommend using this method for audio containing music. + * + * @param enable Sets whether to enable deep-learning noise reduction. + * - true: (Default) Enables deep-learning noise reduction. + * - false: Disables deep-learning noise reduction. + * + * @return + * - 0: Success. + * - < 0: Failure. + * - -157 (ERR_MODULE_NOT_FOUND): The dynamical library for enabling deep-learning noise reduction is not integrated. + */ + virtual int enableDeepLearningDenoise(bool enable) = 0; + /** Enables/Disables stereo panning for remote users. + + Ensure that you call this method before joinChannel to enable stereo panning for remote users so that the local user can track the position of a remote user by calling \ref agora::rtc::IRtcEngine::setRemoteVoicePosition "setRemoteVoicePosition". + + @param enabled Sets whether to enable stereo panning for remote users: + - true: enables stereo panning. + - false: disables stereo panning. + + @return + - 0: Success. + - < 0: Failure. + */ + virtual int enableSoundPositionIndication(bool enabled) = 0; + /** Sets the sound position and gain of a remote user. + + When the local user calls this method to set the sound position of a remote user, the sound difference between the left and right channels allows the local user to track the real-time position of the remote user, creating a real sense of space. This method applies to massively multiplayer online games, such as Battle Royale games. + + @note + - For this method to work, enable stereo panning for remote users by calling the \ref agora::rtc::IRtcEngine::enableSoundPositionIndication "enableSoundPositionIndication" method before joining a channel. + - This method requires hardware support. For the best sound positioning, we recommend using a wired headset. + - Ensure that you call this method after joining a channel. + + @param uid The ID of the remote user. + @param pan The sound position of the remote user. The value ranges from -1.0 to 1.0: + - 0.0: the remote sound comes from the front. + - -1.0: the remote sound comes from the left. + - 1.0: the remote sound comes from the right. + @param gain Gain of the remote user. The value ranges from 0.0 to 100.0. The default value is 100.0 (the original gain of the remote user). The smaller the value, the less the gain. + + @return + - 0: Success. + - < 0: Failure. + */ + virtual int setRemoteVoicePosition(uid_t uid, double pan, double gain) = 0; + + /** Changes the voice pitch of the local speaker. + + @note You can call this method either before or after joining a channel. + + @param pitch Sets the voice pitch. The value ranges between 0.5 and 2.0. The lower the value, the lower the voice pitch. The default value is 1.0 (no change to the local voice pitch). + @return + - 0: Success. + - < 0: Failure. + */ + virtual int setLocalVoicePitch(double pitch) = 0; + /** Sets the local voice equalization effect. + @note You can call this method either before or after joining a channel. + + @param bandFrequency Sets the band frequency. The value ranges between 0 and 9, representing the respective 10-band center frequencies of the voice effects, including 31, 62, 125, 250, 500, 1k, 2k, 4k, 8k, and 16k Hz. See #AUDIO_EQUALIZATION_BAND_FREQUENCY. + + @param bandGain Sets the gain of each band in dB. The value ranges between -15 and 15. + + @return + - 0: Success. + - < 0: Failure. + */ + virtual int setLocalVoiceEqualization(AUDIO_EQUALIZATION_BAND_FREQUENCY bandFrequency, int bandGain) = 0; + /** Sets the local voice reverberation. + * + * As of v3.2.0, the SDK provides a more convenient method + * \ref IRtcEngine::setAudioEffectPreset "setAudioEffectPreset", which + * directly implements the popular music, R&B music, KTV and other preset + * reverb effects. + * + * @note You can call this method either before or after joining a channel. + * + * @param reverbKey Sets the reverberation key. See #AUDIO_REVERB_TYPE. + * @param value Sets the value of the reverberation key. See #AUDIO_REVERB_TYPE. + * + * @return + * - 0: Success. + * - < 0: Failure. + */ + virtual int setLocalVoiceReverb(AUDIO_REVERB_TYPE reverbKey, int value) = 0; + /** Sets the local voice changer option. + + @deprecated Deprecated from v3.2.0. Use the following methods instead: + - \ref IRtcEngine::setAudioEffectPreset "setAudioEffectPreset": Audio effects. + - \ref IRtcEngine::setVoiceBeautifierPreset "setVoiceBeautifierPreset": Voice beautifier effects. + - \ref IRtcEngine::setVoiceConversionPreset "setVoiceConversionPreset": Voice conversion effects. + + This method can be used to set the local voice effect for users in a `COMMUNICATION` channel or hosts in a `LIVE_BROADCASTING` channel. + Voice changer options include the following voice effects: + + - `VOICE_CHANGER_XXX`: Changes the local voice to an old man, a little boy, or the Hulk. Applies to the voice talk scenario. + - `VOICE_BEAUTY_XXX`: Beautifies the local voice by making it sound more vigorous, resounding, or adding spacial resonance. Applies to the voice talk and singing scenario. + - `GENERAL_VOICE_BEAUTY_XXX`: Adds gender-based beautification effect to the local voice. Applies to the voice talk scenario. + - For a male voice: Adds magnetism to the voice. + - For a female voice: Adds freshness or vitality to the voice. + + @note + - To achieve better voice effect quality, Agora recommends setting the profile parameter in \ref IRtcEngine::setAudioProfile "setAudioProfile" as #AUDIO_PROFILE_MUSIC_HIGH_QUALITY (4) or #AUDIO_PROFILE_MUSIC_HIGH_QUALITY_STEREO (5) + - This method works best with the human voice, and Agora does not recommend using it for audio containing music and a human voice. + - Do not use this method with \ref IRtcEngine::setLocalVoiceReverbPreset "setLocalVoiceReverbPreset" , because the method called later overrides the one called earlier. For detailed considerations, see the advanced guide *Set the Voice Effect*. + - You can call this method either before or after joining a channel. + + @param voiceChanger Sets the local voice changer option. The default value is `VOICE_CHANGER_OFF`, + which means the original voice. See details in #VOICE_CHANGER_PRESET. + + @return + - 0: Success. + - < 0: Failure. Check if the enumeration is properly set. + */ + virtual int setLocalVoiceChanger(VOICE_CHANGER_PRESET voiceChanger) AGORA_DEPRECATED_ATTRIBUTE = 0; + /** Sets the local voice reverberation option, including the virtual stereo. + * + * @deprecated Deprecated from v3.2.0. Use \ref IRtcEngine::setAudioEffectPreset "setAudioEffectPreset" or + * \ref IRtcEngine::setVoiceBeautifierPreset "setVoiceBeautifierPreset" instead. + * + * This method sets the local voice reverberation for users in a `COMMUNICATION` channel or hosts in a `LIVE_BROADCASTING` channel. + * After successfully calling this method, all users in the channel can hear the voice with reverberation. + * + * @note + * - When calling this method with enumerations that begin with `AUDIO_REVERB_FX`, ensure that you set profile in `setAudioProfile` as + * `AUDIO_PROFILE_MUSIC_HIGH_QUALITY(4)` or `AUDIO_PROFILE_MUSIC_HIGH_QUALITY_STEREO(5)`; otherwise, this methods cannot set the corresponding voice reverberation option. + * - When calling this method with `AUDIO_VIRTUAL_STEREO`, Agora recommends setting the `profile` parameter in `setAudioProfile` as `AUDIO_PROFILE_MUSIC_HIGH_QUALITY_STEREO(5)`. + * - This method works best with the human voice, and Agora does not recommend using it for audio containing music and a human voice. + * - Do not use this method with `setLocalVoiceChanger`, because the method called later overrides the one called earlier. + * For detailed considerations, see the advanced guide *Set the Voice Effect*. + * - You can call this method either before or after joining a channel. + * + * @param reverbPreset The local voice reverberation option. The default value is `AUDIO_REVERB_OFF`, + * which means the original voice. See #AUDIO_REVERB_PRESET. + * To achieve better voice effects, Agora recommends the enumeration whose name begins with `AUDIO_REVERB_FX`. + * + * @return + * - 0: Success. + * - < 0: Failure. + */ + virtual int setLocalVoiceReverbPreset(AUDIO_REVERB_PRESET reverbPreset) AGORA_DEPRECATED_ATTRIBUTE = 0; + /** Sets an SDK preset voice beautifier effect. + * + * @since v3.2.0 + * + * Call this method to set an SDK preset voice beautifier effect for the local user who sends an audio stream. After + * setting a voice beautifier effect, all users in the channel can hear the effect. + * + * You can set different voice beautifier effects for different scenarios. See *Set the Voice Effect*. + * + * To achieve better audio effect quality, Agora recommends calling \ref IRtcEngine::setAudioProfile "setAudioProfile" and + * setting the `scenario` parameter to `AUDIO_SCENARIO_GAME_STREAMING(3)` and the `profile` parameter to + * `AUDIO_PROFILE_MUSIC_HIGH_QUALITY(4)` or `AUDIO_PROFILE_MUSIC_HIGH_QUALITY_STEREO(5)` before calling this method. + * + * @note + * - You can call this method either before or after joining a channel. + * - Do not set the `profile` parameter of \ref IRtcEngine::setAudioProfile "setAudioProfile" to `AUDIO_PROFILE_SPEECH_STANDARD(1)` + * or `AUDIO_PROFILE_IOT(6)`; otherwise, this method call does not take effect. + * - This method works best with the human voice. Agora does not recommend using this method for audio containing music. + * - After calling this method, Agora recommends not calling the following methods, because they can override \ref IRtcEngine::setAudioEffectParameters "setAudioEffectParameters": + * - \ref IRtcEngine::setAudioEffectPreset "setAudioEffectPreset" + * - \ref IRtcEngine::setVoiceBeautifierPreset "setVoiceBeautifierPreset" + * - \ref IRtcEngine::setLocalVoiceReverbPreset "setLocalVoiceReverbPreset" + * - \ref IRtcEngine::setLocalVoiceChanger "setLocalVoiceChanger" + * - \ref IRtcEngine::setLocalVoicePitch "setLocalVoicePitch" + * - \ref IRtcEngine::setLocalVoiceEqualization "setLocalVoiceEqualization" + * - \ref IRtcEngine::setLocalVoiceReverb "setLocalVoiceReverb" + * - \ref IRtcEngine::setVoiceBeautifierParameters "setVoiceBeautifierParameters" + * - \ref IRtcEngine::setVoiceConversionPreset "setVoiceConversionPreset" + * + * @param preset The options for SDK preset voice beautifier effects: #VOICE_BEAUTIFIER_PRESET. + * + * @return + * - 0: Success. + * - < 0: Failure. + */ + virtual int setVoiceBeautifierPreset(VOICE_BEAUTIFIER_PRESET preset) = 0; + /** Sets an SDK preset audio effect. + * + * @since v3.2.0 + * + * Call this method to set an SDK preset audio effect for the local user who sends an audio stream. This audio effect + * does not change the gender characteristics of the original voice. After setting an audio effect, all users in the + * channel can hear the effect. + * + * You can set different audio effects for different scenarios. See *Set the Voice Effect*. + * + * To achieve better audio effect quality, Agora recommends calling \ref IRtcEngine::setAudioProfile "setAudioProfile" + * and setting the `scenario` parameter to `AUDIO_SCENARIO_GAME_STREAMING(3)` before calling this method. + * + * @note + * - You can call this method either before or after joining a channel. + * - Do not set the profile `parameter` of `setAudioProfile` to `AUDIO_PROFILE_SPEECH_STANDARD(1)` or `AUDIO_PROFILE_IOT(6)`; + * otherwise, this method call does not take effect. + * - This method works best with the human voice. Agora does not recommend using this method for audio containing music. + * - If you call this method and set the `preset` parameter to enumerators except `ROOM_ACOUSTICS_3D_VOICE` or `PITCH_CORRECTION`, + * do not call \ref IRtcEngine::setAudioEffectParameters "setAudioEffectParameters"; otherwise, `setAudioEffectParameters` + * overrides this method. + * - After calling this method, Agora recommends not calling the following methods, because they can override `setAudioEffectPreset`: + * - \ref IRtcEngine::setVoiceBeautifierPreset "setVoiceBeautifierPreset" + * - \ref IRtcEngine::setLocalVoiceReverbPreset "setLocalVoiceReverbPreset" + * - \ref IRtcEngine::setLocalVoiceChanger "setLocalVoiceChanger" + * - \ref IRtcEngine::setLocalVoicePitch "setLocalVoicePitch" + * - \ref IRtcEngine::setLocalVoiceEqualization "setLocalVoiceEqualization" + * - \ref IRtcEngine::setLocalVoiceReverb "setLocalVoiceReverb" + * - \ref IRtcEngine::setVoiceBeautifierParameters "setVoiceBeautifierParameters" + * - \ref IRtcEngine::setVoiceConversionPreset "setVoiceConversionPreset" + * + * @param preset The options for SDK preset audio effects. See #AUDIO_EFFECT_PRESET. + * + * @return + * - 0: Success. + * - < 0: Failure. + */ + virtual int setAudioEffectPreset(AUDIO_EFFECT_PRESET preset) = 0; + /** Sets an SDK preset voice conversion effect. + * + * @since v3.3.1 + * + * Call this method to set an SDK preset voice conversion effect for the + * local user who sends an audio stream. After setting a voice conversion + * effect, all users in the channel can hear the effect. + * + * You can set different voice conversion effects for different scenarios. + * See *Set the Voice Effect*. + * + * To achieve better voice effect quality, Agora recommends calling + * \ref IRtcEngine::setAudioProfile "setAudioProfile" and setting the + * `profile` parameter to #AUDIO_PROFILE_MUSIC_HIGH_QUALITY (4) or + * #AUDIO_PROFILE_MUSIC_HIGH_QUALITY_STEREO (5) and the `scenario` + * parameter to #AUDIO_SCENARIO_GAME_STREAMING (3) before calling this + * method. + * + * @note + * - You can call this method either before or after joining a channel. + * - Do not set the `profile` parameter of `setAudioProfile` to + * #AUDIO_PROFILE_SPEECH_STANDARD (1) or + * #AUDIO_PROFILE_IOT (6); otherwise, this method call does not take effect. + * - This method works best with the human voice. Agora does not recommend + * using this method for audio containing music. + * - After calling this method, Agora recommends not calling the following + * methods, because they can override `setVoiceConversionPreset`: + * - \ref IRtcEngine::setAudioEffectPreset "setAudioEffectPreset" + * - \ref IRtcEngine::setAudioEffectParameters "setAudioEffectParameters" + * - \ref IRtcEngine::setVoiceBeautifierPreset "setVoiceBeautifierPreset" + * - \ref IRtcEngine::setVoiceBeautifierParameters "setVoiceBeautifierParameters" + * - \ref IRtcEngine::setLocalVoiceReverbPreset "setLocalVoiceReverbPreset" + * - \ref IRtcEngine::setLocalVoiceChanger "setLocalVoiceChanger" + * - \ref IRtcEngine::setLocalVoicePitch "setLocalVoicePitch" + * - \ref IRtcEngine::setLocalVoiceEqualization "setLocalVoiceEqualization" + * - \ref IRtcEngine::setLocalVoiceReverb "setLocalVoiceReverb" + * + * @param preset The options for SDK preset voice conversion effects: #VOICE_CONVERSION_PRESET. + * + * @return + * - 0: Success. + * - < 0: Failure. + */ + virtual int setVoiceConversionPreset(VOICE_CONVERSION_PRESET preset) = 0; + /** Sets parameters for SDK preset audio effects. + * + * @since v3.2.0 + * + * Call this method to set the following parameters for the local user who sends an audio stream: + * - 3D voice effect: Sets the cycle period of the 3D voice effect. + * - Pitch correction effect: Sets the basic mode and tonic pitch of the pitch correction effect. Different songs + * have different modes and tonic pitches. Agora recommends bounding this method with interface elements to enable + * users to adjust the pitch correction interactively. + * + * After setting parameters, all users in the channel can hear the relevant effect. + * + * + * @note + * - You can call this method either before or after joining a channel. + * - To achieve better audio effect quality, Agora recommends calling \ref IRtcEngine::setAudioProfile "setAudioProfile" + * and setting the `scenario` parameter to `AUDIO_SCENARIO_GAME_STREAMING(3)` before calling this method. + * - Do not set the `profile` parameter of \ref IRtcEngine::setAudioProfile "setAudioProfile" to `AUDIO_PROFILE_SPEECH_STANDARD(1)` or + * `AUDIO_PROFILE_IOT(6)`; otherwise, this method call does not take effect. + * - This method works best with the human voice. Agora does not recommend using this method for audio containing music. + * - After calling this method, Agora recommends not calling the following methods, because they can override `setAudioEffectParameters`: + * - \ref IRtcEngine::setAudioEffectPreset "setAudioEffectPreset" + * - \ref IRtcEngine::setVoiceBeautifierPreset "setVoiceBeautifierPreset" + * - \ref IRtcEngine::setLocalVoiceReverbPreset "setLocalVoiceReverbPreset" + * - \ref IRtcEngine::setLocalVoiceChanger "setLocalVoiceChanger" + * - \ref IRtcEngine::setLocalVoicePitch "setLocalVoicePitch" + * - \ref IRtcEngine::setLocalVoiceEqualization "setLocalVoiceEqualization" + * - \ref IRtcEngine::setLocalVoiceReverb "setLocalVoiceReverb" + * - \ref IRtcEngine::setVoiceBeautifierParameters "setVoiceBeautifierParameters" + * - \ref IRtcEngine::setVoiceConversionPreset "setVoiceConversionPreset" + * @param preset The options for SDK preset audio effects: + * - 3D voice effect: `ROOM_ACOUSTICS_3D_VOICE`. + * - Call \ref IRtcEngine::setAudioProfile "setAudioProfile" and set the `profile` parameter to `AUDIO_PROFILE_MUSIC_STANDARD_STEREO(3)` + * or `AUDIO_PROFILE_MUSIC_HIGH_QUALITY_STEREO(5)` before setting this enumerator; otherwise, the enumerator setting does not take effect. + * - If the 3D voice effect is enabled, users need to use stereo audio playback devices to hear the anticipated voice effect. + * - Pitch correction effect: `PITCH_CORRECTION`. To achieve better audio effect quality, Agora recommends calling + * \ref IRtcEngine::setAudioProfile "setAudioProfile" and setting the `profile` parameter to `AUDIO_PROFILE_MUSIC_HIGH_QUALITY(4)` or + * `AUDIO_PROFILE_MUSIC_HIGH_QUALITY_STEREO(5)` before setting this enumerator. + * @param param1 + * - If you set `preset` to `ROOM_ACOUSTICS_3D_VOICE`, the `param1` sets the cycle period of the 3D voice effect. + * The value range is [1,60] and the unit is a second. The default value is 10 seconds, indicating that the voice moves + * around you every 10 seconds. + * - If you set `preset` to `PITCH_CORRECTION`, `param1` sets the basic mode of the pitch correction effect: + * - `1`: (Default) Natural major scale. + * - `2`: Natural minor scale. + * - `3`: Japanese pentatonic scale. + * @param param2 + * - If you set `preset` to `ROOM_ACOUSTICS_3D_VOICE`, you need to set `param2` to `0`. + * - If you set `preset` to `PITCH_CORRECTION`, `param2` sets the tonic pitch of the pitch correction effect: + * - `1`: A + * - `2`: A# + * - `3`: B + * - `4`: (Default) C + * - `5`: C# + * - `6`: D + * - `7`: D# + * - `8`: E + * - `9`: F + * - `10`: F# + * - `11`: G + * - `12`: G# + * + * @return + * - 0: Success. + * - < 0: Failure. + */ + virtual int setAudioEffectParameters(AUDIO_EFFECT_PRESET preset, int param1, int param2) = 0; + /** Sets parameters for SDK preset voice beautifier effects. + * + * @since v3.3.0 + * + * Call this method to set a gender characteristic and a reverberation effect for the singing beautifier effect. This method sets parameters for the local user who sends an audio stream. + * + * After you call this method successfully, all users in the channel can hear the relevant effect. + * + * To achieve better audio effect quality, before you call this method, Agora recommends calling \ref IRtcEngine::setAudioProfile "setAudioProfile", and setting the `scenario` parameter + * as `AUDIO_SCENARIO_GAME_STREAMING(3)` and the `profile` parameter as `AUDIO_PROFILE_MUSIC_HIGH_QUALITY(4)` or `AUDIO_PROFILE_MUSIC_HIGH_QUALITY_STEREO(5)`. + * + * @note + * - You can call this method either before or after joining a channel. + * - Do not set the `profile` parameter of \ref IRtcEngine::setAudioProfile "setAudioProfile" as `AUDIO_PROFILE_SPEECH_STANDARD(1)` or `AUDIO_PROFILE_IOT(6)`; otherwise, this method call does not take effect. + * - This method works best with the human voice. Agora does not recommend using this method for audio containing music. + * - After you call this method, Agora recommends not calling the following methods, because they can override `setVoiceBeautifierParameters`: + * - \ref IRtcEngine::setAudioEffectPreset "setAudioEffectPreset" + * - \ref IRtcEngine::setAudioEffectParameters "setAudioEffectParameters" + * - \ref IRtcEngine::setVoiceBeautifierPreset "setVoiceBeautifierPreset" + * - \ref IRtcEngine::setLocalVoiceReverbPreset "setLocalVoiceReverbPreset" + * - \ref IRtcEngine::setLocalVoiceChanger "setLocalVoiceChanger" + * - \ref IRtcEngine::setLocalVoicePitch "setLocalVoicePitch" + * - \ref IRtcEngine::setLocalVoiceEqualization "setLocalVoiceEqualization" + * - \ref IRtcEngine::setLocalVoiceReverb "setLocalVoiceReverb" + * - \ref IRtcEngine::setVoiceConversionPreset "setVoiceConversionPreset" + * + * @param preset The options for SDK preset voice beautifier effects: + * - `SINGING_BEAUTIFIER`: Singing beautifier effect. + * @param param1 The gender characteristics options for the singing voice: + * - `1`: A male-sounding voice. + * - `2`: A female-sounding voice. + * @param param2 The reverberation effects options: + * - `1`: The reverberation effect sounds like singing in a small room. + * - `2`: The reverberation effect sounds like singing in a large room. + * - `3`: The reverberation effect sounds like singing in a hall. + * + * @return + * - 0: Success. + * - < 0: Failure. + */ + virtual int setVoiceBeautifierParameters(VOICE_BEAUTIFIER_PRESET preset, int param1, int param2) = 0; + /** Sets the log files that the SDK outputs. + * + * @deprecated This method is deprecated from v3.3.0. Use `logConfig` in the \ref IRtcEngine::initialize "initialize" method instead. + * + * By default, the SDK outputs five log files, `agorasdk.log`, `agorasdk_1.log`, `agorasdk_2.log`, `agorasdk_3.log`, `agorasdk_4.log`, each with a default size of 1024 KB. + * These log files are encoded in UTF-8. The SDK writes the latest logs in `agorasdk.log`. When `agorasdk.log` is full, the SDK deletes the log file with the earliest + * modification time among the other four, renames `agorasdk.log` to the name of the deleted log file, and create a new `agorasdk.log` to record latest logs. + * + * @note Ensure that you call this method immediately after calling \ref agora::rtc::IRtcEngine::initialize "initialize" , otherwise the output logs may not be complete. + * + * @see \ref IRtcEngine::setLogFileSize "setLogFileSize" + * @see \ref IRtcEngine::setLogFilter "setLogFilter" + * + * @param filePath The absolute path of log files. The default file path is `C: \Users\\AppData\Local\Agora\\agorasdk.log`. + * Ensure that the directory for the log files exists and is writable. You can use this parameter to rename the log files. + * + * @return + * - 0: Success. + * - < 0: Failure. + */ + virtual int setLogFile(const char* filePath) AGORA_DEPRECATED_ATTRIBUTE = 0; + /// @cond + /** Specifies an SDK external log writer. + + The external log writer output all SDK operations during runtime if it exist. + + @note + - Ensure that you call this method after calling the \ref agora::rtc::IRtcEngine::initialize "initialize" method. + + @param pLogWriter . + + @return + - 0: Success. + - < 0: Failure. + */ + virtual int setLogWriter(agora::commons::ILogWriter* pLogWriter) = 0; + + /** Set the value of external log writer to null + @note + - Ensure that you call this method after calling the \ref agora::rtc::IRtcEngine::initialize "initialize" method. + + @return + - 0: Success. + - < 0: Failure. + */ + virtual int releaseLogWriter() = 0; + /// @endcond + /** Sets the output log level of the SDK. + + @deprecated This method is deprecated from v3.3.0. Use `logConfig` in the \ref IRtcEngine::initialize "initialize" method instead. + + You can use one or a combination of the log filter levels. The log level follows the sequence of OFF, CRITICAL, ERROR, WARNING, INFO, and DEBUG. Choose a level to see the logs preceding that level. + + If you set the log level to WARNING, you see the logs within levels CRITICAL, ERROR, and WARNING. + + @see \ref IRtcEngine::setLogFile "setLogFile" + @see \ref IRtcEngine::setLogFileSize "setLogFileSize" + + @param filter Sets the log filter level. See #LOG_FILTER_TYPE. + + @return + - 0: Success. + - < 0: Failure. + */ + virtual int setLogFilter(unsigned int filter) AGORA_DEPRECATED_ATTRIBUTE = 0; + /** Sets the size of a log file that the SDK outputs. + * + * @deprecated This method is deprecated from v3.3.0. Use `logConfig` in the \ref IRtcEngine::initialize "initialize" method instead. + * + * @note If you want to set the log file size, ensure that you call + * this method before \ref IRtcEngine::setLogFile "setLogFile", or the logs are cleared. + * + * By default, the SDK outputs five log files, `agorasdk.log`, `agorasdk_1.log`, `agorasdk_2.log`, `agorasdk_3.log`, `agorasdk_4.log`, each with a default size of 1024 KB. + * These log files are encoded in UTF-8. The SDK writes the latest logs in `agorasdk.log`. When `agorasdk.log` is full, the SDK deletes the log file with the earliest + * modification time among the other four, renames `agorasdk.log` to the name of the deleted log file, and create a new `agorasdk.log` to record latest logs. + * + * @see \ref IRtcEngine::setLogFile "setLogFile" + * @see \ref IRtcEngine::setLogFilter "setLogFilter" + * + * @param fileSizeInKBytes The size (KB) of a log file. The default value is 1024 KB. If you set `fileSizeInKByte` to 1024 KB, + * the SDK outputs at most 5 MB log files; if you set it to less than 1024 KB, the maximum size of a log file is still 1024 KB. + * + * @return + * - 0: Success. + * - < 0: Failure. + */ + virtual int setLogFileSize(unsigned int fileSizeInKBytes) AGORA_DEPRECATED_ATTRIBUTE = 0; + /// @cond + /** Uploads all SDK log files. + * + * @since v3.3.0 + * + * Uploads all SDK log files from the client to the Agora server. + * After a successful method call, the SDK triggers the \ref agora::rtc::IRtcEngineEventHandler::onUploadLogResult "onUploadLogResult" callback + * to report whether the log files are successfully uploaded to the Agora server. + * + * + * For easier debugging, Agora recommends that you bind this method to the UI element of your App, so as to instruct the + * user to upload a log file when a quality issue occurs. + * + * @note Do not call this method more than once per minute, otherwise the SDK reports #ERR_TOO_OFTEN (12). + * + * @param[out] requestId The request ID. This request ID is the same as requestId in the \ref IRtcEngineEventHandler::onUploadLogResult "onUploadLogResult" callback, + * and you can use the request ID to match a specific upload with a callback. + * + * @return + * - 0: Success. + * - < 0: Failure. + * - -12(ERR_TOO_OFTEN): The call frequency exceeds the limit. + */ + virtual int uploadLogFile(agora::util::AString& requestId) = 0; + /// @endcond + /** + @deprecated This method is deprecated, use the \ref IRtcEngine::setLocalRenderMode(RENDER_MODE_TYPE renderMode, VIDEO_MIRROR_MODE_TYPE mirrorMode) "setLocalRenderMode" [2/2] method instead. + Sets the local video display mode. + + This method can be called multiple times during a call to change the display mode. + + @param renderMode Sets the local video display mode. See #RENDER_MODE_TYPE. + @return + - 0: Success. + - < 0: Failure. + */ + virtual int setLocalRenderMode(RENDER_MODE_TYPE renderMode) AGORA_DEPRECATED_ATTRIBUTE = 0; + /** Updates the display mode of the local video view. + + @since v3.0.0 + + After initializing the local video view, you can call this method to update its rendering and mirror modes. It affects only the video view that the local user sees, not the published local video stream. + + @note + - Ensure that you have called the \ref IRtcEngine::setupLocalVideo "setupLocalVideo" method to initialize the local video view before calling this method. + - During a call, you can call this method as many times as necessary to update the display mode of the local video view. + @param renderMode The rendering mode of the local video view. See #RENDER_MODE_TYPE. + @param mirrorMode + - The mirror mode of the local video view. See #VIDEO_MIRROR_MODE_TYPE. + - **Note**: If you use a front camera, the SDK enables the mirror mode by default; if you use a rear camera, the SDK disables the mirror mode by default. + @return + - 0: Success. + - < 0: Failure. + */ + virtual int setLocalRenderMode(RENDER_MODE_TYPE renderMode, VIDEO_MIRROR_MODE_TYPE mirrorMode) = 0; + /** + @deprecated This method is deprecated, use the \ref IRtcEngine::setRemoteRenderMode(uid_t userId, RENDER_MODE_TYPE renderMode, VIDEO_MIRROR_MODE_TYPE mirrorMode) "setRemoteRenderMode" [2/2] method instead. + Sets the video display mode of a specified remote user. + + This method can be called multiple times during a call to change the display mode. + + @param userId ID of the remote user. + @param renderMode Sets the video display mode. See #RENDER_MODE_TYPE. + @return + - 0: Success. + - < 0: Failure. + */ + virtual int setRemoteRenderMode(uid_t userId, RENDER_MODE_TYPE renderMode) AGORA_DEPRECATED_ATTRIBUTE = 0; + /** Updates the display mode of the video view of a remote user. + + @since v3.0.0 + After initializing the video view of a remote user, you can call this method to update its rendering and mirror modes. This method affects only the video view that the local user sees. + + @note + - Ensure that you have called the \ref IRtcEngine::setupRemoteVideo "setupRemoteVideo" method to initialize the remote video view before calling this method. + - During a call, you can call this method as many times as necessary to update the display mode of the video view of a remote user. + + @param userId The ID of the remote user. + @param renderMode The rendering mode of the remote video view. See #RENDER_MODE_TYPE. + @param mirrorMode + - The mirror mode of the remote video view. See #VIDEO_MIRROR_MODE_TYPE. + - **Note**: The SDK disables the mirror mode by default. + + @return + - 0: Success. + - < 0: Failure. + */ + virtual int setRemoteRenderMode(uid_t userId, RENDER_MODE_TYPE renderMode, VIDEO_MIRROR_MODE_TYPE mirrorMode) = 0; + /** + @deprecated This method is deprecated, use the \ref IRtcEngine::setupLocalVideo "setupLocalVideo" + or \ref IRtcEngine::setLocalRenderMode(RENDER_MODE_TYPE renderMode, VIDEO_MIRROR_MODE_TYPE mirrorMode) "setLocalRenderMode" method instead. + + Sets the local video mirror mode. + + @warning Call this method after calling the \ref agora::rtc::IRtcEngine::setupLocalVideo "setupLocalVideo" method to initialize the local video view. + + @param mirrorMode Sets the local video mirror mode. See #VIDEO_MIRROR_MODE_TYPE. + @return + - 0: Success. + - < 0: Failure. + */ + virtual int setLocalVideoMirrorMode(VIDEO_MIRROR_MODE_TYPE mirrorMode) AGORA_DEPRECATED_ATTRIBUTE = 0; + /** Sets the stream mode to the single-stream (default) or dual-stream mode. + + If the dual-stream mode is enabled, the receiver can choose to receive the high stream (high-resolution and high-bitrate video stream), or the low stream (low-resolution and low-bitrate video stream). + + @note You can call this method either before or after joining a channel. + + @param enabled Sets the stream mode: + - true: Dual-stream mode. + - false: Single-stream mode. + + @return + - 0: Success. + - < 0: Failure. + */ + virtual int enableDualStreamMode(bool enabled) = 0; + /** Sets the external audio source. + + @note Please call this method before \ref agora::rtc::IRtcEngine::joinChannel "joinChannel" + and \ref IRtcEngine::startPreview "startPreview". + + @param enabled Sets whether to enable/disable the external audio source: + - true: Enables the external audio source. + - false: (Default) Disables the external audio source. + @param sampleRate Sets the sample rate (Hz) of the external audio source, which can be set as 8000, 16000, 32000, 44100, or 48000 Hz. + @param channels Sets the number of audio channels of the external audio source: + - 1: Mono. + - 2: Stereo. + + @return + - 0: Success. + - < 0: Failure. + */ + virtual int setExternalAudioSource(bool enabled, int sampleRate, int channels) = 0; + /** Sets the external audio sink. + * This method applies to scenarios where you want to use external audio + * data for playback. After enabling the external audio sink, you can call + * the \ref agora::media::IMediaEngine::pullAudioFrame "pullAudioFrame" method to pull the remote audio data, process + * it, and play it with the audio effects that you want. + * + * @note + * - Once you enable the external audio sink, the app will not get any + * audio data from the + * \ref agora::media::IAudioFrameObserver::onPlaybackAudioFrame "onPlaybackAudioFrame" callback. + * - Ensure that you call this method before joining a channel. + * + * @param enabled + * - true: Enables the external audio sink. + * - false: (Default) Disables the external audio sink. + * @param sampleRate Sets the sample rate (Hz) of the external audio sink, which can be set as 16000, 32000, 44100 or 48000. + * @param channels Sets the number of audio channels of the external + * audio sink: + * - 1: Mono. + * - 2: Stereo. + * + * @return + * - 0: Success. + * - < 0: Failure. + */ + virtual int setExternalAudioSink(bool enabled, int sampleRate, int channels) = 0; + /** Sets the audio recording format for the \ref agora::media::IAudioFrameObserver::onRecordAudioFrame "onRecordAudioFrame" callback. + + @note Ensure that you call this method before joining a channel. + + @param sampleRate Sets the sample rate (@p samplesPerSec) returned in the *onRecordAudioFrame* callback, which can be set as 8000, 16000, 32000, 44100, or 48000 Hz. + @param channel Sets the number of audio channels (@p channels) returned in the *onRecordAudioFrame* callback: + - 1: Mono + - 2: Stereo + @param mode Sets the use mode (see #RAW_AUDIO_FRAME_OP_MODE_TYPE) of the *onRecordAudioFrame* callback. + @param samplesPerCall Sets the number of samples returned in the *onRecordAudioFrame* callback. `samplesPerCall` is usually set as 1024 for RTMP or RTMPS streaming. + + + @note The SDK triggers the `onRecordAudioFrame` callback according to the sample interval. Ensure that the sample interval ≥ 0.01 (s). And, Sample interval (sec) = `samplePerCall`/(`sampleRate` × `channel`). + + @return + - 0: Success. + - < 0: Failure. + */ + virtual int setRecordingAudioFrameParameters(int sampleRate, int channel, RAW_AUDIO_FRAME_OP_MODE_TYPE mode, int samplesPerCall) = 0; + /** Sets the audio playback format for the \ref agora::media::IAudioFrameObserver::onPlaybackAudioFrame "onPlaybackAudioFrame" callback. + + @note Ensure that you call this method before joining a channel. + + @param sampleRate Sets the sample rate (@p samplesPerSec) returned in the *onPlaybackAudioFrame* callback, which can be set as 8000, 16000, 32000, 44100, or 48000 Hz. + @param channel Sets the number of channels (@p channels) returned in the *onPlaybackAudioFrame* callback: + - 1: Mono + - 2: Stereo + @param mode Sets the use mode (see #RAW_AUDIO_FRAME_OP_MODE_TYPE) of the *onPlaybackAudioFrame* callback. + @param samplesPerCall Sets the number of samples returned in the *onPlaybackAudioFrame* callback. `samplesPerCall` is usually set as 1024 for RTMP or RTMPS streaming. + + @note The SDK triggers the `onPlaybackAudioFrame` callback according to the sample interval. Ensure that the sample interval ≥ 0.01 (s). And, Sample interval (sec) = `samplePerCall`/(`sampleRate` × `channel`). + + @return + - 0: Success. + - < 0: Failure. + */ + virtual int setPlaybackAudioFrameParameters(int sampleRate, int channel, RAW_AUDIO_FRAME_OP_MODE_TYPE mode, int samplesPerCall) = 0; + /** Sets the mixed audio format for the \ref agora::media::IAudioFrameObserver::onMixedAudioFrame "onMixedAudioFrame" callback. + + @note Ensure that you call this method before joining a channel. + + @param sampleRate Sets the sample rate (@p samplesPerSec) returned in the *onMixedAudioFrame* callback, which can be set as 8000, 16000, 32000, 44100, or 48000 Hz. + @param samplesPerCall Sets the number of samples (`samples`) returned in the *onMixedAudioFrame* callback. `samplesPerCall` is usually set as 1024 for RTMP or RTMPS streaming. + + @note The SDK triggers the `onMixedAudioFrame` callback according to the sample interval. Ensure that the sample interval ≥ 0.01 (s). And, Sample interval (sec) = `samplePerCall`/(`sampleRate` × `channels`). + + @return + - 0: Success. + - < 0: Failure. + */ + virtual int setMixedAudioFrameParameters(int sampleRate, int samplesPerCall) = 0; + /** Adjusts the volume of the signal captured by the microphone. + * + * @note You can call this method either before or after joining a channel. + * + * @param volume The volume of the signal captured by the microphone. + * The value ranges between 0 and 400, including the following: + * - 0: Mute. + * - 100: (Default) Original volume. + * - 400: Four times the original volume with signal-clipping protection. + * + * @return + * - 0: Success. + * - < 0: Failure. + */ + virtual int adjustRecordingSignalVolume(int volume) = 0; + /** Adjusts the playback signal volume of all remote users. + * + * @note + * - This method adjusts the playback volume that is the mixed volume of all + * remote users. + * - You can call this method either before or after joining a channel. + * - (Since v2.3.2) To mute the local audio playback, call both the + * `adjustPlaybackSignalVolume` and + * \ref IRtcEngine::adjustAudioMixingVolume "adjustAudioMixingVolume" + * methods and set the volume as `0`. + * + * @param volume The playback volume. The value ranges between 0 and 400, + * including the following: + * - 0: Mute. + * - 100: (Default) Original volume. + * - 400: Four times the original volume with signal-clipping protection. + * + * @return + * - 0: Success. + * - < 0: Failure. + */ + virtual int adjustPlaybackSignalVolume(int volume) = 0; + /** + * Adjusts the volume of the signal captured by the sound card. + * + * @since v3.4.0 + * + * After calling enableLoopbackRecording to enable loopback audio capturing, + * you can call this method to adjust the volume of the signal captured by + * the sound card. + * + * @note This method applies to Windows and macOS only. + * + * @param volume The volume of the signal captured by the sound card. + * The value ranges between 0 and 400, including the following: + * - 0: Mute. + * - 100: (Default) Original volume. + * - 400: Four times the original volume with signal-clipping protection. + * + * @return + * - 0: Success. + * - < 0: Failure. + */ + virtual int adjustLoopbackRecordingSignalVolume(int volume) = 0; + /** + @deprecated This method is deprecated. As of v3.0.0, the Native SDK automatically enables interoperability with the Web SDK, so you no longer need to call this method. + Enables interoperability with the Agora Web SDK. + + @note + - This method applies to the `LIVE_BROADCASTING` profile. In the `COMMUNICATION` profile, interoperability with the Agora Web SDK is enabled by default. + - If the channel has Web SDK users, ensure that you call this method, or the video of the Native user will be a black screen for the Web user. + + @param enabled Sets whether to enable/disable interoperability with the Agora Web SDK: + - true: Enable. + - false: (Default) Disable. + + @return + - 0: Success. + - < 0: Failure. + */ + virtual int enableWebSdkInteroperability(bool enabled) AGORA_DEPRECATED_ATTRIBUTE = 0; + // only for live broadcast + /** **DEPRECATED** Sets the preferences for the high-quality video. (`LIVE_BROADCASTING` only). + + This method is deprecated as of v2.4.0. + + @param preferFrameRateOverImageQuality Sets the video quality preference: + - true: Frame rate over image quality. + - false: (Default) Image quality over frame rate. + + @return + - 0: Success. + - < 0: Failure. + */ + virtual int setVideoQualityParameters(bool preferFrameRateOverImageQuality) = 0; + /** Sets the fallback option for the published video stream based on the network conditions. + + If `option` is set as #STREAM_FALLBACK_OPTION_AUDIO_ONLY (2), the SDK will: + + - Disable the upstream video but enable audio only when the network conditions deteriorate and cannot support both video and audio. + - Re-enable the video when the network conditions improve. + + When the published video stream falls back to audio only or when the audio-only stream switches back to the video, the SDK triggers the \ref agora::rtc::IRtcEngineEventHandler::onLocalPublishFallbackToAudioOnly "onLocalPublishFallbackToAudioOnly" callback. + + @note + - Agora does not recommend using this method for CDN live streaming, because the remote CDN live user will have a noticeable lag when the published video stream falls back to audio only. + - Ensure that you call this method before joining a channel. + + @param option Sets the fallback option for the published video stream: + - #STREAM_FALLBACK_OPTION_DISABLED (0): (Default) No fallback behavior for the published video stream when the uplink network condition is poor. The stream quality is not guaranteed. + - #STREAM_FALLBACK_OPTION_AUDIO_ONLY (2): The published video stream falls back to audio only when the uplink network condition is poor. + + @return + - 0: Success. + - < 0: Failure. + */ + virtual int setLocalPublishFallbackOption(STREAM_FALLBACK_OPTIONS option) = 0; + /** Sets the fallback option for the remotely subscribed video stream based on the network conditions. + + The default setting for `option` is #STREAM_FALLBACK_OPTION_VIDEO_STREAM_LOW (1), where the remotely subscribed video stream falls back to the low-stream video (low resolution and low bitrate) under poor downlink network conditions. + + If `option` is set as #STREAM_FALLBACK_OPTION_AUDIO_ONLY (2), the SDK automatically switches the video from a high-stream to a low-stream, or disables the video when the downlink network conditions cannot support both audio and video to guarantee the quality of the audio. The SDK monitors the network quality and restores the video stream when the network conditions improve. + + When the remotely subscribed video stream falls back to audio only or when the audio-only stream switches back to the video stream, the SDK triggers the \ref agora::rtc::IRtcEngineEventHandler::onRemoteSubscribeFallbackToAudioOnly "onRemoteSubscribeFallbackToAudioOnly" callback. + + @note Ensure that you call this method before joining a channel. + + @param option Sets the fallback option for the remotely subscribed video stream. See #STREAM_FALLBACK_OPTIONS. + @return + - 0: Success. + - < 0: Failure. + */ + virtual int setRemoteSubscribeFallbackOption(STREAM_FALLBACK_OPTIONS option) = 0; + +#if defined(__ANDROID__) || (defined(__APPLE__) && TARGET_OS_IOS) + /** Switches between front and rear cameras. + + @note + - This method is for Android and iOS only. + - Ensure that you call this method after the camera starts, for example, by + calling \ref IRtcEngine::startPreview "startPreview" or \ref IRtcEngine::joinChannel "joinChannel". + + @return + - 0: Success. + - < 0: Failure. + */ + virtual int switchCamera() = 0; + /// @cond + /** Switches between front and rear cameras. + + @note This method is for Android and iOS only. + @note This method is private. + + @param direction Sets the camera to be used: + - CAMERA_DIRECTION.CAMERA_REAR: Use the rear camera. + - CAMERA_DIRECTION.CAMERA_FRONT: Use the front camera. + + @return + - 0: Success. + - < 0: Failure. + */ + virtual int switchCamera(CAMERA_DIRECTION direction) = 0; + /// @endcond + /** + * Sets the default audio route. + * + * If the default audio route of the SDK (see *Set the Audio Route*) cannot meet your requirements, you can + * call this method to switch the default audio route. After successfully switching the audio route, the SDK + * triggers the \ref IRtcEngineEventHandler::onAudioRouteChanged "onAudioRouteChanged" callback to indicate the changes. + * + * @note + * - This method applies to Android and iOS only. + * - Call this method before calling \ref IRtcEngine::joinChannel "joinChannel". If you need to switch the audio + * route after joining a channel, call \ref IRtcEngine::setEnableSpeakerphone "setEnableSpeakerphone". + * - If the user uses an external audio playback device such as a Bluetooth or wired headset, this method does not + * take effect, and the SDK plays audio through the external device. When the user uses multiple external devices, + * the SDK plays audio through the last connected device. + * + * @param defaultToSpeaker Sets the default audio route as follows: + * - true: Set to the speakerphone. + * - false: Set to the earpiece. + * + * @return + * - 0: Success. + * - < 0: Failure. + */ + virtual int setDefaultAudioRouteToSpeakerphone(bool defaultToSpeaker) = 0; + /** + * Enables/Disables the audio route to the speakerphone. + * + * If the default audio route of the SDK (see *Set the Audio Route*) or the + * setting in \ref IRtcEngine::setDefaultAudioRouteToSpeakerphone "setDefaultAudioRouteToSpeakerphone" + * cannot meet your requirements, you can call this method to switch the current audio route. + * After successfully switching the audio route, the SDK triggers the + * \ref IRtcEngineEventHandler::onAudioRouteChanged "onAudioRouteChanged" callback to indicate the changes. + * + * This method only sets the audio route in the current channel and does not influence the default audio route. + * If the user leaves the current channel and joins another channel, the default audio route is used. + * + * @note + * - This method applies to Android and iOS only. + * - Call this method after calling joinChannel. + * - If the user uses an external audio playback device such as a Bluetooth or wired headset, this method + * does not take effect, and the SDK plays audio through the external device. When the user uses multiple external + * devices, the SDK plays audio through the last connected device. + * + * @param speakerOn Sets whether to enable the speakerphone or earpiece: + * - true: Enable the speakerphone. The audio route is the speakerphone. + * - false: Disable the speakerphone. The audio route is the earpiece. + * + * @return + * - 0: Success. + * - < 0: Failure. + */ + virtual int setEnableSpeakerphone(bool speakerOn) = 0; + /** Enables in-ear monitoring (for Android and iOS only). + * + * @note + * - Users must use wired earphones to hear their own voices. + * - You can call this method either before or after joining a channel. + * + * @param enabled Determines whether to enable in-ear monitoring. + * - true: Enable. + * - false: (Default) Disable. + * + * @return + * - 0: Success. + * - < 0: Failure. + */ + virtual int enableInEarMonitoring(bool enabled) = 0; + /** Sets the volume of the in-ear monitor. + * + * @note + * - This method is for Android and iOS only. + * - Users must use wired earphones to hear their own voices. + * - You can call this method either before or after joining a channel. + * + * @param volume Sets the volume of the in-ear monitor. The value ranges between 0 and 100 (default). + * + * @return + * - 0: Success. + * - < 0: Failure. + */ + virtual int setInEarMonitoringVolume(int volume) = 0; + /** Checks whether the speakerphone is enabled. + + @note + - This method is for Android and iOS only. + - You can call this method either before or after joining a channel. + + @return + - true: The speakerphone is enabled, and the audio plays from the speakerphone. + - false: The speakerphone is not enabled, and the audio plays from devices other than the speakerphone. For example, the headset or earpiece. + */ + virtual bool isSpeakerphoneEnabled() = 0; +#endif + +#if (defined(__APPLE__) && TARGET_OS_IOS) + /** Sets the operational permission of the SDK on the audio session. + * + * The SDK and the app can both configure the audio session by default. If + * you need to only use the app to configure the audio session, this method + * restricts the operational permission of the SDK on the audio session. + * + * You can call this method either before or after joining a channel. Once + * you call this method to restrict the operational permission of the SDK + * on the audio session, the restriction takes effect when the SDK needs to + * change the audio session. + * + * @note + * - This method is for iOS only. + * - This method does not restrict the operational permission of the app on + * the audio session. + * + * @param restriction The operational permission of the SDK on the audio session. + * See #AUDIO_SESSION_OPERATION_RESTRICTION. This parameter is in bit mask + * format, and each bit corresponds to a permission. + * + * @return + * - 0: Success. + * - < 0: Failure. + */ + virtual int setAudioSessionOperationRestriction(AUDIO_SESSION_OPERATION_RESTRICTION restriction) = 0; +#endif + +#if (defined(__APPLE__) && TARGET_OS_MAC && !TARGET_OS_IPHONE) || defined(_WIN32) + /** Enables loopback audio capturing. + + If you enable loopback audio capturing, the output of the sound card is mixed into the audio stream sent to the other end. + + @note You can call this method either before or after joining a channel. + + @param enabled Sets whether to enable/disable loopback capturing. + - true: Enable loopback capturing. + - false: (Default) Disable loopback capturing. + @param deviceName Pointer to the device name of the sound card. The default value is NULL (the default sound card). + + @note + - This method is for macOS and Windows only. + - macOS does not support loopback capturing of the default sound card. If you need to use this method, please use a virtual sound card and pass its name to the deviceName parameter. Agora has tested and recommends using soundflower. + + */ + virtual int enableLoopbackRecording(bool enabled, const char* deviceName = NULL) = 0; + /** + * Gets a list of shareable screens and windows. + * + * @since v3.5.2 + * + * You can call this method before sharing a screen or window to get a list of shareable screens and windows, which + * enables a user to use thumbnails in the list to easily choose a particular screen or window to share. This list + * also contains important information such as window ID and screen ID, with which you can + * call \ref IRtcEngine::startScreenCaptureByWindowId "startScreenCaptureByWindowId" or + * \ref IRtcEngine::startScreenCaptureByDisplayId "startScreenCaptureByDisplayId" to start the sharing. + * + * @note This method applies to macOS and Windows only. + * + * @param thumbSize The target size of the screen or window thumbnail. The width and height are in pixels. See SIZE. + * The SDK scales the original image to make the length of the longest side of the image the same as that of the + * target size without distorting the original image. For example, if the original image is 400 × 300 and `thumbSize` + * is 100 × 100, the actual size of the thumbnail is 100 × 75. If the target size is larger than the original size, + * the thumbnail is the original image and the SDK does not scale it. + * @param iconSize The target size of the icon corresponding to the application program. The width and height are in + * pixels. See SIZE. The SDK scales the original image to make the length of the longest side of the image the same + * as that of the target size without distorting the original image. For example, if the original image is 400 × 300 + * and `iconSize` is 100 × 100, the actual size of the icon is 100 × 75. If the target size is larger than the + * original size, the icon is the original image and the SDK does not scale it. + * @param includeScreen Whether the SDK returns screen information in addition to window information: + * - true: The SDK returns screen and window information. + * - false: The SDK returns window information only. + * + * @return IScreenCaptureSourceList + */ + virtual IScreenCaptureSourceList* getScreenCaptureSources(const SIZE& thumbSize, const SIZE& iconSize, const bool includeScreen) = 0; + /** Shares the whole or part of a screen by specifying the display ID. + * + * @note + * - This method is for macOS and Windows only. + * - Ensure that you call this method after joining a channel. + * + * @warning On Windows platforms, if the user device is connected to another display, to avoid screen sharing issues, + * use `startScreenCaptureByDisplayId` to start sharing instead of + * using \ref IRtcEngine::startScreenCaptureByScreenRect "startScreenCaptureByScreenRect". + * + * @param displayId The display ID of the screen to be shared. Use this parameter to specify which screen you want to + * share. For more information on how to get the display ID, see the advanced feature guide *Share the Screen* or get + * the display ID from `sourceId` returned by \ref IRtcEngine::getScreenCaptureSources "getScreenCaptureSources". + * @param regionRect (Optional) Sets the relative location of the region to the screen. NIL means sharing the whole screen. See Rectangle. If the specified region overruns the screen, the SDK shares only the region within it; if you set width or height as 0, the SDK shares the whole screen. + * @param captureParams The screen sharing encoding parameters. The default video dimension is 1920 x 1080, that is, 2,073,600 pixels. Agora uses the value of `videoDimension` to calculate the charges. + * For details, see descriptions in ScreenCaptureParameters. + * + * + * @return + * - 0: Success. + * - < 0: Failure: + * - #ERR_INVALID_ARGUMENT: The argument is invalid. + */ + virtual int startScreenCaptureByDisplayId(unsigned int displayId, const Rectangle& regionRect, const ScreenCaptureParameters& captureParams) = 0; + +#if defined(_WIN32) + /** Shares the whole or part of a screen by specifying the screen rect. + * + * @note + * - Ensure that you call this method after joining a channel. + * - Applies to the Windows platform only. + * + * @warning On Windows platforms, if the user device is connected to another display, to avoid screen sharing issues, + * use \ref IRtcEngine::startScreenCaptureByDisplayId "startScreenCaptureByDisplayId" to start sharing instead of + * using \ref IRtcEngine::startScreenCaptureByScreenRect "startScreenCaptureByScreenRect". + * + * @param screenRect Sets the relative location of the screen to the virtual screen. For information on how to get screenRect, see the advanced guide *Share Screen*. + * @param regionRect (Optional) Sets the relative location of the region to the screen. NULL means sharing the whole screen. See Rectangle. If the specified region overruns the screen, the SDK shares only the region within it; if you set width or height as 0, the SDK shares the whole screen. + * @param captureParams The screen sharing encoding parameters. The default video dimension is 1920 x 1080, that is, 2,073,600 pixels. + * Agora uses the value of `videoDimension` to calculate the charges. For details, see descriptions in ScreenCaptureParameters. + * + * @return + * - 0: Success. + * - < 0: Failure: + * - #ERR_INVALID_ARGUMENT: The argument is invalid. + */ + virtual int startScreenCaptureByScreenRect(const Rectangle& screenRect, const Rectangle& regionRect, const ScreenCaptureParameters& captureParams) = 0; +#endif + + /** Shares the whole or part of a window by specifying the window ID. + * + * @note + * - Ensure that you call this method after joining a channel. + * - Applies to the macOS and Windows platforms only. + * + * Since v3.0.0, this method supports window sharing of UWP (Universal Windows Platform) applications. + * + * Agora tests the mainstream UWP applications by using the lastest SDK, see details as follows: + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
        OS versionSoftwareSoftware nameWhether support
        win10Chrome76.0.3809.100No
        Office Word18.1903.1152.0Yes
        Office ExcelNo
        Office PPTYes
        WPS Word11.1.0.9145Yes
        WPS Excel
        WPS PPT
        Media Player (come with the system)AllYes
        win8ChromeAllYes
        Office WordAllYes
        Office Excel
        Office PPT
        WPS Word11.1.0.9098Yes
        WPS Excel
        WPS PPT
        Media Player(come with the system)AllYes
        win7Chrome73.0.3683.103No
        Office WordAllYes
        Office Excel
        Office PPT
        WPS Word11.1.0.9098No
        WPS Excel
        WPS PPT11.1.0.9098Yes
        Media Player(come with the system)AllNo
        + * @param windowId The ID of the window to be shared. For information on how to get the windowId, see the advanced guide *Share Screen*. + * @param regionRect (Optional) The relative location of the region to the window. NULL/NIL means sharing the whole window. See Rectangle. If the specified region overruns the window, the SDK shares only the region within it; if you set width or height as 0, the SDK shares the whole window. + * @param captureParams The screen sharing encoding parameters. The default video dimension is 1920 x 1080, that is, 2,073,600 pixels. Agora uses the value of `videoDimension` to calculate the charges. For details, see descriptions in ScreenCaptureParameters. + * + * @return + * - 0: Success. + * - < 0: Failure: + * - #ERR_INVALID_ARGUMENT: The argument is invalid. + */ + virtual int startScreenCaptureByWindowId(view_t windowId, const Rectangle& regionRect, const ScreenCaptureParameters& captureParams) = 0; + + /** Sets the content hint for screen sharing. + + A content hint suggests the type of the content being shared, so that the SDK applies different optimization algorithm to different types of content. + + @note You can call this method either before or after you start screen sharing. + + @param contentHint Sets the content hint for screen sharing. See VideoContentHint. + + @return + - 0: Success. + - < 0: Failure. + */ + virtual int setScreenCaptureContentHint(VideoContentHint contentHint) = 0; + + /** Updates the screen sharing parameters. + + @param captureParams The screen sharing encoding parameters. The default video dimension is 1920 x 1080, that is, + 2,073,600 pixels. Agora uses the value of `videoDimension` to calculate the charges. For details, + see descriptions in ScreenCaptureParameters. + + @return + - 0: Success. + - < 0: Failure: + - #ERR_NOT_READY: no screen or windows is being shared. + */ + virtual int updateScreenCaptureParameters(const ScreenCaptureParameters& captureParams) = 0; + + /** Updates the screen sharing region. + + @param regionRect Sets the relative location of the region to the screen or window. NULL means sharing the whole screen or window. See Rectangle. If the specified region overruns the screen or window, the SDK shares only the region within it; if you set width or height as 0, the SDK shares the whole screen or window. + + @return + - 0: Success. + - < 0: Failure: + - #ERR_NOT_READY: no screen or window is being shared. + */ + virtual int updateScreenCaptureRegion(const Rectangle& regionRect) = 0; + + /** Stop screen sharing. + + @return + - 0: Success. + - < 0: Failure. + */ + virtual int stopScreenCapture() = 0; + +#if defined(__APPLE__) + typedef unsigned int WindowIDType; +#elif defined(_WIN32) + typedef HWND WindowIDType; +#endif + + /** **DEPRECATED** Starts screen sharing. + + This method is deprecated as of v2.4.0. See the following methods instead: + + - \ref agora::rtc::IRtcEngine::startScreenCaptureByDisplayId "startScreenCaptureByDisplayId" + - \ref agora::rtc::IRtcEngine::startScreenCaptureByScreenRect "startScreenCaptureByScreenRect" + - \ref agora::rtc::IRtcEngine::startScreenCaptureByWindowId "startScreenCaptureByWindowId" + + This method shares the whole screen, specified window, or specified region: + + - Whole screen: Set @p windowId as 0 and @p rect as NULL. + - Specified window: Set @p windowId as a value other than 0. Each window has a @p windowId that is not 0. + - Specified region: Set @p windowId as 0 and @p rect not as NULL. In this case, you can share the specified region, for example by dragging the mouse or implementing your own logic. + + @note The specified region is a region on the whole screen. Currently, sharing a specified region in a specific window is not supported. + *captureFreq* is the captured frame rate once the screen-sharing function is enabled. The mandatory value ranges between 1 fps and 15 fps. + + @param windowId Sets the screen sharing area. See WindowIDType. + @param captureFreq (Mandatory) The captured frame rate. The value ranges between 1 fps and 15 fps. + @param rect Specifies the screen-sharing region. @p rect is valid when @p windowsId is set as 0. When @p rect is set as NULL, the whole screen is shared. + @param bitrate The captured bitrate. + + @return + - 0: Success. + - < 0: Failure. + */ + virtual int startScreenCapture(WindowIDType windowId, int captureFreq, const Rect* rect, int bitrate) = 0; + + /** **DEPRECATED** Updates the screen capture region. + + @param rect Specifies the required region inside the screen or window. + @return + - 0: Success. + - < 0: Failure. + */ + virtual int updateScreenCaptureRegion(const Rect* rect) = 0; +#endif + +#if defined(_WIN32) + /** Sets a custom video source. + * + * During real-time communication, the Agora SDK enables the default video input device, that is, the built-in camera to + * capture video. If you need a custom video source, implement the IVideoSource class first, and call this method to add + * the custom video source to the SDK. + * + * @note You can call this method either before or after joining a channel. + * + * @param source The custom video source. See IVideoSource. + * + * @return + * - true: The custom video source is added to the SDK. + * - false: The custom video source is not added to the SDK. + */ + virtual bool setVideoSource(IVideoSource* source) = 0; +#endif + + /** Gets the current call ID. + + When a user joins a channel on a client, a @p callId is generated to identify the call from the client. Feedback methods, such as \ref IRtcEngine::rate "rate" and \ref IRtcEngine::complain "complain", must be called after the call ends to submit feedback to the SDK. + + The \ref IRtcEngine::rate "rate" and \ref IRtcEngine::complain "complain" methods require the @p callId parameter retrieved from the *getCallId* method during a call. @p callId is passed as an argument into the \ref IRtcEngine::rate "rate" and \ref IRtcEngine::complain "complain" methods after the call ends. + + @note Ensure that you call this method after joining a channel. + + @param callId Pointer to the current call ID. + + @return + - 0: Success. + - < 0: Failure. + */ + virtual int getCallId(agora::util::AString& callId) = 0; + + /** Allows a user to rate a call after the call ends. + + @note Ensure that you call this method after joining a channel. + + @param callId Pointer to the ID of the call, retrieved from the \ref IRtcEngine::getCallId "getCallId" method. + @param rating Rating of the call. The value is between 1 (lowest score) and 5 (highest score). If you set a value out of this range, the #ERR_INVALID_ARGUMENT (2) error returns. + @param description (Optional) Pointer to the description of the rating, with a string length of less than 800 bytes. + + @return + - 0: Success. + - < 0: Failure. + */ + virtual int rate(const char* callId, int rating, const char* description) = 0; + + /** Allows a user to complain about the call quality after a call ends. + + @note Ensure that you call this method after joining a channel. + + @param callId Pointer to the ID of the call, retrieved from the \ref IRtcEngine::getCallId "getCallId" method. + @param description (Optional) Pointer to the description of the complaint, with a string length of less than 800 bytes. + + @return + - 0: Success. + - < 0: Failure. + + */ + virtual int complain(const char* callId, const char* description) = 0; + + /** Gets the SDK version number. + + @param build Pointer to the build number. + @return The version of the current SDK in the string format. For example, 2.3.1. + */ + virtual const char* getVersion(int* build) = 0; + + /** Enables the network connection quality test. + + This method tests the quality of the users' network connections and is disabled by default. + + Before a user joins a channel or before an audience switches to a host, call this method to check the uplink network quality. + + This method consumes additional network traffic, and hence may affect communication quality. + + Call the \ref IRtcEngine::disableLastmileTest "disableLastmileTest" method to disable this test after receiving the \ref IRtcEngineEventHandler::onLastmileQuality "onLastmileQuality" callback, and before joining a channel. + + @note + - Do not call any other methods before receiving the \ref IRtcEngineEventHandler::onLastmileQuality "onLastmileQuality" callback. Otherwise, the callback may be interrupted by other methods, and hence may not be triggered. + - A host should not call this method after joining a channel (when in a call). + - If you call this method to test the last mile network quality, the SDK consumes the bandwidth of a video stream, whose bitrate corresponds to the bitrate you set in the \ref agora::rtc::IRtcEngine::setVideoEncoderConfiguration "setVideoEncoderConfiguration" method. After you join the channel, whether you have called the `disableLastmileTest` method or not, the SDK automatically stops consuming the bandwidth. + + @return + - 0: Success. + - < 0: Failure. + */ + virtual int enableLastmileTest() = 0; + + /** Disables the network connection quality test. + + @return + - 0: Success. + - < 0: Failure. + */ + virtual int disableLastmileTest() = 0; + + /** Starts the last-mile network probe test. + + This method starts the last-mile network probe test before joining a channel to get the uplink and downlink last mile network statistics, including the bandwidth, packet loss, jitter, and round-trip time (RTT). + + Call this method to check the uplink network quality before users join a channel or before an audience switches to a host. + Once this method is enabled, the SDK returns the following callbacks: + - \ref IRtcEngineEventHandler::onLastmileQuality "onLastmileQuality": the SDK triggers this callback within two seconds depending on the network conditions. This callback rates the network conditions and is more closely linked to the user experience. + - \ref IRtcEngineEventHandler::onLastmileProbeResult "onLastmileProbeResult": the SDK triggers this callback within 30 seconds depending on the network conditions. This callback returns the real-time statistics of the network conditions and is more objective. + + @note + - This method consumes extra network traffic and may affect communication quality. We do not recommend calling this method together with enableLastmileTest. + - Do not call other methods before receiving the \ref IRtcEngineEventHandler::onLastmileQuality "onLastmileQuality" and \ref IRtcEngineEventHandler::onLastmileProbeResult "onLastmileProbeResult" callbacks. Otherwise, the callbacks may be interrupted. + - In the `LIVE_BROADCASTING` profile, a host should not call this method after joining a channel. + + @param config Sets the configurations of the last-mile network probe test. See LastmileProbeConfig. + + @return + - 0: Success. + - < 0: Failure. + */ + virtual int startLastmileProbeTest(const LastmileProbeConfig& config) = 0; + + /** Stops the last-mile network probe test. */ + virtual int stopLastmileProbeTest() = 0; + + /** Gets the warning or error description. + + @param code Warning code or error code returned in the \ref agora::rtc::IRtcEngineEventHandler::onWarning "onWarning" or \ref agora::rtc::IRtcEngineEventHandler::onError "onError" callback. + + @return #WARN_CODE_TYPE or #ERROR_CODE_TYPE. + */ + virtual const char* getErrorDescription(int code) = 0; + + /** Enables built-in encryption with an encryption password before users join a channel. + + @deprecated Deprecated as of v3.1.0. Use the \ref agora::rtc::IRtcEngine::enableEncryption "enableEncryption" instead. + + All users in a channel must use the same encryption password. The encryption password is automatically cleared once a user leaves the channel. + + If an encryption password is not specified, the encryption functionality will be disabled. + + @note + - Do not use this method for CDN live streaming. + - For optimal transmission, ensure that the encrypted data size does not exceed the original data size + 16 bytes. 16 bytes is the maximum padding size for AES encryption. + + @param secret Pointer to the encryption password. + + @return + - 0: Success. + - < 0: Failure. + */ + virtual int setEncryptionSecret(const char* secret) AGORA_DEPRECATED_ATTRIBUTE = 0; + + /** Sets the built-in encryption mode. + + @deprecated Deprecated as of v3.1.0. Use the \ref agora::rtc::IRtcEngine::enableEncryption "enableEncryption" instead. + + The Agora SDK supports built-in encryption, which is set to the @p aes-128-xts mode by default. Call this method to use other encryption modes. + + All users in the same channel must use the same encryption mode and password. + + Refer to the information related to the AES encryption algorithm on the differences between the encryption modes. + + @note Call the \ref IRtcEngine::setEncryptionSecret "setEncryptionSecret" method to enable the built-in encryption function before calling this method. + + @param encryptionMode Pointer to the set encryption mode: + - "aes-128-xts": (Default) 128-bit AES encryption, XTS mode. + - "aes-128-ecb": 128-bit AES encryption, ECB mode. + - "aes-256-xts": 256-bit AES encryption, XTS mode. + - "": When encryptionMode is set as NULL, the encryption mode is set as "aes-128-xts" by default. + + @return + - 0: Success. + - < 0: Failure. + */ + virtual int setEncryptionMode(const char* encryptionMode) AGORA_DEPRECATED_ATTRIBUTE = 0; + + /** Enables/Disables the built-in encryption. + * + * @since v3.1.0 + * + * In scenarios requiring high security, Agora recommends calling this method to enable the built-in encryption before joining a channel. + * + * After a user leaves the channel, the SDK automatically disables the built-in encryption. + * To re-enable the built-in encryption, call this method before the user joins the channel again. + * + * As of v3.4.5, Agora recommends using either the `AES_128_GCM2` or `AES_256_GCM2` encryption mode, + * both of which support adding a salt and are more secure. For details, see *Media Stream Encryption*. + * + * @warning All users in the same channel must use the same encryption mode, encryption key, and salt; otherwise, + * users cannot communicate with each other. + * + * @note + * - If you enable the built-in encryption, you cannot use the RTMP or RTMPS streaming function. + * - To enhance security, Agora recommends using a new key and salt every time you enable the media stream encryption. + * + * @param enabled Whether to enable the built-in encryption: + * - true: Enable the built-in encryption. + * - false: Disable the built-in encryption. + * @param config Configurations of built-in encryption schemas. See EncryptionConfig. + * + * @return + * - 0: Success. + * - < 0: Failure. + * - -2(ERR_INVALID_ARGUMENT): An invalid parameter is used. Set the parameter with a valid value. + * - -4(ERR_NOT_SUPPORTED): The encryption mode is incorrect or the SDK fails to load the external encryption library. Check the enumeration or reload the external encryption library. + * - -7(ERR_NOT_INITIALIZED): The SDK is not initialized. Initialize the `IRtcEngine` instance before calling this method. + */ + virtual int enableEncryption(bool enabled, const EncryptionConfig& config) = 0; + + /** Registers a packet observer. + + The Agora SDK allows your application to register a packet observer to receive callbacks for voice or video packet transmission. + + @note + - The size of the packet sent to the network after processing should not exceed 1200 bytes, otherwise, the packet may fail to be sent. + - Ensure that both receivers and senders call this method, otherwise, you may meet undefined behaviors such as no voice and black screen. + - When you use CDN live streaming and recording functions, Agora doesn't recommend calling this method. + - Call this method before joining a channel. + + @param observer Pointer to the registered packet observer. See IPacketObserver. + + @return + - 0: Success. + - < 0: Failure. + */ + virtual int registerPacketObserver(IPacketObserver* observer) = 0; + + /** Creates a data stream. + + @deprecated This method is deprecated from v3.3.0. Use the \ref IRtcEngine::createDataStream(int* streamId, DataStreamConfig& config) "createDataStream" [2/2] method instead. + + Each user can create up to five data streams during the lifecycle of the IRtcEngine. + + @note + - Do not set `reliable` as `true` while setting `ordered` as `false`. + - Ensure that you call this method after joining a channel. + + @param[out] streamId Pointer to the ID of the created data stream. + @param reliable Sets whether or not the recipients are guaranteed to receive the data stream from the sender within five seconds: + - true: The recipients receive the data stream from the sender within five seconds. If the recipient does not receive the data stream within five seconds, an error is reported to the application. + - false: There is no guarantee that the recipients receive the data stream within five seconds and no error message is reported for any delay or missing data stream. + @param ordered Sets whether or not the recipients receive the data stream in the sent order: + - true: The recipients receive the data stream in the sent order. + - false: The recipients do not receive the data stream in the sent order. + + @return + - 0: Success. + - < 0: Failure. + */ + virtual int createDataStream(int* streamId, bool reliable, bool ordered) AGORA_DEPRECATED_ATTRIBUTE = 0; + /** Creates a data stream. + * + * @since v3.3.0 + * + * Each user can create up to five data streams in a single channel. + * + * This method does not support data reliability. If the receiver receives a data packet five + * seconds or more after it was sent, the SDK directly discards the data. + * + * @param[out] streamId The ID of the created data stream. + * @param config The configurations for the data stream: DataStreamConfig. + * + * @return + * - 0: Creates the data stream successfully. + * - < 0: Fails to create the data stream. + */ + virtual int createDataStream(int* streamId, DataStreamConfig& config) = 0; + + /** Sends data stream messages to all users in a channel. + + The SDK has the following restrictions on this method: + - Up to 30 packets can be sent per second in a channel with each packet having a maximum size of 1 kB. + - Each client can send up to 6 kB of data per second. + - Each user can have up to five data streams simultaneously. + + A successful \ref agora::rtc::IRtcEngine::sendStreamMessage "sendStreamMessage" method call triggers the + \ref agora::rtc::IRtcEngineEventHandler::onStreamMessage "onStreamMessage" callback on the remote client, from which the remote user gets the stream message. + + A failed \ref agora::rtc::IRtcEngine::sendStreamMessage "sendStreamMessage" method call triggers the + \ref agora::rtc::IRtcEngineEventHandler::onStreamMessage "onStreamMessage" callback on the remote client. + @note This method applies only to the `COMMUNICATION` profile or to the hosts in the `LIVE_BROADCASTING` profile. If an audience in the `LIVE_BROADCASTING` profile calls this method, the audience may be switched to a host. + @param streamId ID of the sent data stream, returned in the \ref IRtcEngine::createDataStream "createDataStream" method. + @param data Pointer to the sent data. + @param length Length of the sent data. + + @return + - 0: Success. + - < 0: Failure. + */ + virtual int sendStreamMessage(int streamId, const char* data, size_t length) = 0; + + /** Publishes the local stream to a specified CDN live address. (CDN live only.) + + The SDK returns the result of this method call in the \ref IRtcEngineEventHandler::onStreamPublished "onStreamPublished" callback. + + The \ref agora::rtc::IRtcEngine::addPublishStreamUrl "addPublishStreamUrl" method call triggers the \ref agora::rtc::IRtcEngineEventHandler::onRtmpStreamingStateChanged "onRtmpStreamingStateChanged" callback on the local client to report the state of adding a local stream to the CDN. + @note + - Ensure that the user joins the channel before calling this method. + - Ensure that you enable the RTMP Converter service before using this function. See *Prerequisites* in the advanced guide *Push Streams to CDN*. + - This method adds only one stream CDN streaming URL each time it is called. + - This method applies to `LIVE_BROADCASTING` only. + + @param url The CDN streaming URL in the RTMP or RTMPS format. The maximum length of this parameter is 1024 bytes. The CDN streaming URL must not contain special characters, such as Chinese language characters. + @param transcodingEnabled Sets whether transcoding is enabled/disabled: + - true: Enable transcoding. To [transcode](https://docs.agora.io/en/Agora%20Platform/terms?platform=All%20Platforms#transcoding) the audio or video streams when publishing them to CDN live, often used for combining the audio and video streams of multiple hosts in CDN live. If you set this parameter as `true`, ensure that you call the \ref IRtcEngine::setLiveTranscoding "setLiveTranscoding" method before this method. + - false: Disable transcoding. + + @return + - 0: Success. + - < 0: Failure. + - #ERR_INVALID_ARGUMENT (-2): The CDN streaming URL is NULL or has a string length of 0. + - #ERR_NOT_INITIALIZED (-7): You have not initialized the RTC engine when publishing the stream. + */ + virtual int addPublishStreamUrl(const char* url, bool transcodingEnabled) = 0; + + /** Removes an RTMP or RTMPS stream from the CDN. (CDN live only.) + + This method removes the CDN streaming URL (added by the \ref IRtcEngine::addPublishStreamUrl "addPublishStreamUrl" method) from a CDN live stream. The SDK returns the result of this method call in the \ref IRtcEngineEventHandler::onStreamUnpublished "onStreamUnpublished" callback. + + The \ref agora::rtc::IRtcEngine::removePublishStreamUrl "removePublishStreamUrl" method call triggers the \ref agora::rtc::IRtcEngineEventHandler::onRtmpStreamingStateChanged "onRtmpStreamingStateChanged" callback on the local client to report the state of removing an RTMP or RTMPS stream from the CDN. + + @note + - This method removes only one CDN streaming URL each time it is called. + - The CDN streaming URL must not contain special characters, such as Chinese language characters. + - This method applies to `LIVE_BROADCASTING` only. + + @param url The CDN streaming URL to be removed. The maximum length of this parameter is 1024 bytes. + + @return + - 0: Success. + - < 0: Failure. + */ + virtual int removePublishStreamUrl(const char* url) = 0; + + /** Sets the video layout and audio settings for CDN live. (CDN live only.) + + The SDK triggers the \ref agora::rtc::IRtcEngineEventHandler::onTranscodingUpdated "onTranscodingUpdated" callback when you call the `setLiveTranscoding` method to update the transcoding setting. + + @note + - This method applies to `LIVE_BROADCASTING` only. + - Ensure that you enable the RTMP Converter service before using this function. See *Prerequisites* in the advanced guide *Push Streams to CDN*. + - If you call the `setLiveTranscoding` method to update the transcoding setting for the first time, the SDK does not trigger the `onTranscodingUpdated` callback. + - Ensure that you call this method after joining a channel. + - Agora supports pushing media streams in RTMPS protocol to the CDN only when you enable transcoding. + + @param transcoding Sets the CDN live audio/video transcoding settings. See LiveTranscoding. + + @return + - 0: Success. + - < 0: Failure. + */ + virtual int setLiveTranscoding(const LiveTranscoding& transcoding) = 0; + + /** **DEPRECATED** Adds a watermark image to the local video or CDN live stream. + + This method is deprecated from v2.9.1. Use \ref agora::rtc::IRtcEngine::addVideoWatermark(const char* watermarkUrl, const WatermarkOptions& options) "addVideoWatermark" [2/2] instead. + + This method adds a PNG watermark image to the local video stream for the capturing device, channel audience, and CDN live audience to view and capture. + + To add the PNG file to the CDN live publishing stream, see the \ref IRtcEngine::setLiveTranscoding "setLiveTranscoding" method. + + @param watermark Pointer to the watermark image to be added to the local video stream. See RtcImage. + + @note + - The URL descriptions are different for the local video and CDN live streams: + - In a local video stream, `url` in RtcImage refers to the absolute path of the added watermark image file in the local video stream. + - In a CDN live stream, `url` in RtcImage refers to the URL address of the added watermark image in the CDN live streaming. + - The source file of the watermark image must be in the PNG file format. If the width and height of the PNG file differ from your settings in this method, the PNG file will be cropped to conform to your settings. + - The Agora SDK supports adding only one watermark image onto a local video or CDN live stream. The newly added watermark image replaces the previous one. + + @return + - 0: Success. + - < 0: Failure. + */ + virtual int addVideoWatermark(const RtcImage& watermark) = 0; + + /** Adds a watermark image to the local video. + * + * This method adds a PNG watermark image to the local video in the live streaming. Once the watermark image is added, all the audience in the channel (CDN audience included), + * and the capturing device can see and capture it. Agora supports adding only one watermark image onto the local video, and the newly watermark image replaces the previous one. + * + * The watermark position depends on the settings in the \ref IRtcEngine::setVideoEncoderConfiguration "setVideoEncoderConfiguration" method: + * - If the orientation mode of the encoding video is #ORIENTATION_MODE_FIXED_LANDSCAPE, or the landscape mode in #ORIENTATION_MODE_ADAPTIVE, the watermark uses the landscape orientation. + * - If the orientation mode of the encoding video is #ORIENTATION_MODE_FIXED_PORTRAIT, or the portrait mode in #ORIENTATION_MODE_ADAPTIVE, the watermark uses the portrait orientation. + * - When setting the watermark position, the region must be less than the dimensions set in the `setVideoEncoderConfiguration` method. Otherwise, the watermark image will be cropped. + * + * @note + * - Ensure that you have called the \ref agora::rtc::IRtcEngine::enableVideo "enableVideo" method to enable the video module before calling this method. + * - If you only want to add a watermark image to the local video for the audience in the CDN live streaming channel to see and capture, you can call this method or the \ref agora::rtc::IRtcEngine::setLiveTranscoding "setLiveTranscoding" method. + * - This method supports adding a watermark image in the PNG file format only. Supported pixel formats of the PNG image are RGBA, RGB, Palette, Gray, and Alpha_gray. + * - If the dimensions of the PNG image differ from your settings in this method, the image will be cropped or zoomed to conform to your settings. + * - If you have enabled the local video preview by calling the \ref agora::rtc::IRtcEngine::startPreview "startPreview" method, you can use the `visibleInPreview` member in the WatermarkOptions class to set whether or not the watermark is visible in preview. + * - If you have enabled the mirror mode for the local video, the watermark on the local video is also mirrored. To avoid mirroring the watermark, Agora recommends that you do not use the mirror and watermark functions for the local video at the same time. You can implement the watermark function in your application layer. + * + * @param watermarkUrl The local file path of the watermark image to be added. + * This method supports adding a watermark image from the local absolute or relative file path. + * On Android, Agora recommends passing a URI address or the path starts with `/assets/` in this parameter + * @param options Pointer to the watermark's options to be added. See WatermarkOptions for more infomation. + * + * @return + * - 0: Success. + * - < 0: Failure. + */ + virtual int addVideoWatermark(const char* watermarkUrl, const WatermarkOptions& options) = 0; + + /** Removes the watermark image from the video stream added by the \ref agora::rtc::IRtcEngine::addVideoWatermark(const char* watermarkUrl, const WatermarkOptions& options) "addVideoWatermark" method. + + @return + - 0: Success. + - < 0: Failure. + */ + virtual int clearVideoWatermarks() = 0; + + /** Enables/Disables image enhancement and sets the options. + * + * @note + * - Call this method after calling the \ref IRtcEngine::enableVideo "enableVideo" method. + * - On Android, this method applies to Android 5.0 or later. + * + * @param enabled Determines whether to enable image enhancement: + * - true: Enables image enhancement. + * - false: Disables image enhancement. + * @param options The image enhancement option. See BeautyOptions. + * + * @return + * - 0: Success. + * - < 0: Failure. + * - `-4(ERR_NOT_SUPPORTED)`: The system version is earlier than Android 5.0, which does not support this function. + */ + virtual int setBeautyEffectOptions(bool enabled, BeautyOptions options) = 0; + /** + * Enables/Disables the virtual background. (beta feature) + * + * Support for macOS and Windows as of v3.4.5 and Android and iOS as of v3.5.0. + * + * After enabling the virtual background feature, you can replace the original background image of the local user + * with a custom background image. After the replacement, all users in the channel can see the custom background + * image. You can find out from the + * \ref IRtcEngineEventHandler::onVirtualBackgroundSourceEnabled "onVirtualBackgroundSourceEnabled" callback + * whether the virtual background is successfully enabled or the cause of any errors. + * + * @note + * - Before calling this method, ensure that you have integrated the following dynamic library into your project: + * - Android: `libagora_segmentation_extension.so` + * - iOS: `AgoraVideoSegmentationExtension.xcframework` + * - macOS: `AgoraVideoSegmentationExtension.framework` + * - Windows: `libagora_segmentation_extension.dll` + * - Call this method after \ref IRtcEngine::enableVideo "enableVideo". + * - This functions requires a high-performance device. Agora recommends that you use this function on the + * following devices: + * - Android: Devices with the following chips: + * - Snapdragon 700 series 750G and later + * - Snapdragon 800 series 835 and later + * - Dimensity 700 series 720 and later + * - Kirin 800 series 810 and later + * - Kirin 900 series 980 and later + * - iOS: Devices with an A9 chip and better, as follows: + * - iPhone 6S and later + * - iPad Air (3rd generation) and later + * - iPad (5th generation) and later + * - iPad Pro (1st generation) and later + * - iPad mini (5th generation) and later + * - macOS and Windows: Devices with an i5 CPU and better + * - Agora recommends that you use this function in scenarios that meet the following conditions: + * - A high-definition camera device is used, and the environment is uniformly lit. + * - The captured video image is uncluttered, the user's portrait is half-length and largely unobstructed, and the + * background is a single color that differs from the color of the user's clothing. + * - The virtual background feature does not support video in the Texture format or video obtained from custom video capture by the Push method. + * + * @param enabled Sets whether to enable the virtual background: + * - true: Enable. + * - false: Disable. + * @param backgroundSource The custom background image. See VirtualBackgroundSource. + * Note: To adapt the resolution of the custom background image to the resolution of the SDK capturing video, + * the SDK scales and crops + * the custom background image while ensuring that the content of the custom background image is not distorted. + * + * @return + * - 0: Success. + * - < 0: Failure. + */ + virtual int enableVirtualBackground(bool enabled, VirtualBackgroundSource backgroundSource) = 0; + + /** Adds a voice or video stream URL address to the live streaming. + + The \ref IRtcEngineEventHandler::onStreamPublished "onStreamPublished" callback returns the inject status. If this method call is successful, the server pulls the voice or video stream and injects it into a live channel. This is applicable to scenarios where all audience members in the channel can watch a live show and interact with each other. + + The \ref agora::rtc::IRtcEngine::addInjectStreamUrl "addInjectStreamUrl" method call triggers the following callbacks: + - The local client: + - \ref agora::rtc::IRtcEngineEventHandler::onStreamInjectedStatus "onStreamInjectedStatus" , with the state of the injecting the online stream. + - \ref agora::rtc::IRtcEngineEventHandler::onUserJoined "onUserJoined" (uid: 666), if the method call is successful and the online media stream is injected into the channel. + - The remote client: + - \ref agora::rtc::IRtcEngineEventHandler::onUserJoined "onUserJoined" (uid: 666), if the method call is successful and the online media stream is injected into the channel. + + @warning Agora will soon stop the service for injecting online media streams on the client. If you have not implemented this service, Agora recommends that you do not use it. + + @note + - Ensure that you enable the RTMP Converter service before using this function. See *Prerequisites* in the advanced guide *Push Streams to CDN*. + - This method applies to the Native SDK v2.4.1 and later. + - This method applies to the `LIVE_BROADCASTING` profile only. + - You can inject only one media stream into the channel at the same time. + - Ensure that you call this method after joining a channel. + + @param url Pointer to the URL address to be added to the ongoing streaming. Valid protocols are RTMP, HLS, and HTTP-FLV. + - Supported audio codec type: AAC. + - Supported video codec type: H264 (AVC). + @param config Pointer to the InjectStreamConfig object that contains the configuration of the added voice or video stream. + + @return + - 0: Success. + - < 0: Failure. + - #ERR_INVALID_ARGUMENT (-2): The injected URL does not exist. Call this method again to inject the stream and ensure that the URL is valid. + - #ERR_NOT_READY (-3): The user is not in the channel. + - #ERR_NOT_SUPPORTED (-4): The channel profile is not `LIVE_BROADCASTING`. Call the \ref agora::rtc::IRtcEngine::setChannelProfile "setChannelProfile" method and set the channel profile to `LIVE_BROADCASTING` before calling this method. + - #ERR_NOT_INITIALIZED (-7): The SDK is not initialized. Ensure that the IRtcEngine object is initialized before calling this method. + */ + virtual int addInjectStreamUrl(const char* url, const InjectStreamConfig& config) = 0; + /** Starts to relay media streams across channels. + * + * After a successful method call, the SDK triggers the + * \ref agora::rtc::IRtcEngineEventHandler::onChannelMediaRelayStateChanged + * "onChannelMediaRelayStateChanged" and + * \ref agora::rtc::IRtcEngineEventHandler::onChannelMediaRelayEvent + * "onChannelMediaRelayEvent" callbacks, and these callbacks return the + * state and events of the media stream relay. + * - If the + * \ref agora::rtc::IRtcEngineEventHandler::onChannelMediaRelayStateChanged + * "onChannelMediaRelayStateChanged" callback returns + * #RELAY_STATE_RUNNING (2) and #RELAY_OK (0), and the + * \ref agora::rtc::IRtcEngineEventHandler::onChannelMediaRelayEvent + * "onChannelMediaRelayEvent" callback returns + * #RELAY_EVENT_PACKET_SENT_TO_DEST_CHANNEL (4), the host starts + * sending data to the destination channel. + * - If the + * \ref agora::rtc::IRtcEngineEventHandler::onChannelMediaRelayStateChanged + * "onChannelMediaRelayStateChanged" callback returns + * #RELAY_STATE_FAILURE (3), an exception occurs during the media stream + * relay. + * + * @note + * - Call this method after the \ref joinChannel() "joinChannel" method. + * - This method takes effect only when you are a host in a + * `LIVE_BROADCASTING` channel. + * - After a successful method call, if you want to call this method + * again, ensure that you call the + * \ref stopChannelMediaRelay() "stopChannelMediaRelay" method to quit the + * current relay. + * - Contact sales-us@agora.io before implementing this function. + * - We do not support string user accounts in this API. + * + * @param configuration The configuration of the media stream relay: + * ChannelMediaRelayConfiguration. + * + * @return + * - 0: Success. + * - < 0: Failure. + */ + virtual int startChannelMediaRelay(const ChannelMediaRelayConfiguration& configuration) = 0; + /** Updates the channels for media stream relay. After a successful + * \ref startChannelMediaRelay() "startChannelMediaRelay" method call, if + * you want to relay the media stream to more channels, or leave the + * current relay channel, you can call the + * \ref updateChannelMediaRelay() "updateChannelMediaRelay" method. + * + * After a successful method call, the SDK triggers the + * \ref agora::rtc::IRtcEngineEventHandler::onChannelMediaRelayEvent + * "onChannelMediaRelayEvent" callback with the + * #RELAY_EVENT_PACKET_UPDATE_DEST_CHANNEL (7) state code. + * + * @note Call this method after successfully calling the \ref startChannelMediaRelay() "startChannelMediaRelay" method + * and receiving the \ref IRtcEngineEventHandler::onChannelMediaRelayStateChanged "onChannelMediaRelayStateChanged" (RELAY_STATE_RUNNING, RELAY_OK) callback; + * otherwise, this method call fails. + * + * @param configuration The media stream relay configuration: + * ChannelMediaRelayConfiguration. + * + * @return + * - 0: Success. + * - < 0: Failure. + */ + virtual int updateChannelMediaRelay(const ChannelMediaRelayConfiguration& configuration) = 0; + + /** + * Pauses the media stream relay to all destination channels. + * + * @since v3.5.1 + * + * After the cross-channel media stream relay starts, you can call this method + * to pause relaying media streams to all destination channels; after the pause, + * if you want to resume the relay, call \ref IRtcEngine::resumeAllChannelMediaRelay "resumeAllChannelMediaRelay". + * + * After a successful method call, the SDK triggers the + * \ref IRtcEngineEventHandler::onChannelMediaRelayEvent "onChannelMediaRelayEvent" + * callback to report whether the media stream relay is successfully paused. + * + * @note Call this method after the \ref IRtcEngine::startChannelMediaRelay "startChannelMediaRelay" method. + * + * @return + * - 0: Success. + * - < 0: Failure. + */ + virtual int pauseAllChannelMediaRelay() = 0; + + /** Resumes the media stream relay to all destination channels. + * + * @since v3.5.1 + * + * After calling the \ref IRtcEngine::pauseAllChannelMediaRelay "pauseAllChannelMediaRelay" method, + * you can call this method to resume relaying media streams to all destination channels. + * + * After a successful method call, the SDK triggers the + * \ref IRtcEngineEventHandler::onChannelMediaRelayEvent "onChannelMediaRelayEvent" + * callback to report whether the media stream relay is successfully resumed. + * + * @note Call this method after the \ref IRtcEngine::pauseAllChannelMediaRelay "pauseAllChannelMediaRelay" method. + * + * @return + * - 0: Success. + * - < 0: Failure. + */ + virtual int resumeAllChannelMediaRelay() = 0; + + /** Stops the media stream relay. + * + * Once the relay stops, the host quits all the destination + * channels. + * + * After a successful method call, the SDK triggers the + * \ref agora::rtc::IRtcEngineEventHandler::onChannelMediaRelayStateChanged + * "onChannelMediaRelayStateChanged" callback. If the callback returns + * #RELAY_STATE_IDLE (0) and #RELAY_OK (0), the host successfully + * stops the relay. + * + * @note + * If the method call fails, the SDK triggers the + * \ref agora::rtc::IRtcEngineEventHandler::onChannelMediaRelayStateChanged + * "onChannelMediaRelayStateChanged" callback with the + * #RELAY_ERROR_SERVER_NO_RESPONSE (2) or + * #RELAY_ERROR_SERVER_CONNECTION_LOST (8) error code. You can leave the + * channel by calling the \ref leaveChannel() "leaveChannel" method, and + * the media stream relay automatically stops. + * + * @return + * - 0: Success. + * - < 0: Failure. + */ + virtual int stopChannelMediaRelay() = 0; + + /** Removes the voice or video stream URL address from the live streaming. + + This method removes the URL address (added by the \ref IRtcEngine::addInjectStreamUrl "addInjectStreamUrl" method) from the live streaming. + + @warning Agora will soon stop the service for injecting online media streams on the client. If you have not implemented this service, Agora recommends that you do not use it. + + @note If this method is called successfully, the SDK triggers the \ref IRtcEngineEventHandler::onUserOffline "onUserOffline" callback and returns a stream uid of 666. + + @param url Pointer to the URL address of the injected stream to be removed. + + @return + - 0: Success. + - < 0: Failure. + */ + virtual int removeInjectStreamUrl(const char* url) = 0; + virtual bool registerEventHandler(IRtcEngineEventHandler* eventHandler) = 0; + virtual bool unregisterEventHandler(IRtcEngineEventHandler* eventHandler) = 0; + /** Agora supports reporting and analyzing customized messages. + * + * @since v3.1.0 + * + * This function is in the beta stage with a free trial. The ability provided in its beta test version is reporting a maximum of 10 message pieces within 6 seconds, with each message piece not exceeding 256 bytes and each string not exceeding 100 bytes. + * To try out this function, contact [support@agora.io](mailto:support@agora.io) and discuss the format of customized messages with us. + */ + virtual int sendCustomReportMessage(const char* id, const char* category, const char* event, const char* label, int value) = 0; + /** Gets the current connection state of the SDK. + + @note You can call this method either before or after joining a channel. + + @return #CONNECTION_STATE_TYPE. + */ + virtual CONNECTION_STATE_TYPE getConnectionState() = 0; + + /** Enables/Disables the super resolution feature for a remote user's video. (beta feature) + * + * @since v3.5.1 + * + * This feature effectively boosts the resolution of a remote user's video seen by the local + * user. If the original resolution of a remote user's video is a × b, the local user's device + * can render the remote video at a resolution of 2a × 2b after you enable this feature. + * + * After calling this method, the SDK triggers the + * \ref IRtcEngineEventHandler::onUserSuperResolutionEnabled "onUserSuperResolutionEnabled" + * callback to report whether you have successfully enabled super resolution. + * + * @warning The super resolution feature requires extra system resources. To balance the visual experience and system consumption, the SDK poses the following restrictions: + * - This feature can only be enabled for a single remote user. + * - The original resolution of the remote user's video cannot exceed a certain range. If the local user use super resolution on Android, + * the original resolution of the remote user's video cannot exceed 640 × 360 pixels; if the local user use super resolution on iOS, + * the original resolution of the remote user's video cannot exceed 640 × 480 pixels. + * + * @warning If you exceed these limitations, the SDK triggers the + * \ref IRtcEngineEventHandler::onWarning "onWarning" callback and returns the corresponding warning codes: + * - #WARN_SUPER_RESOLUTION_STREAM_OVER_LIMITATION (1610): The original resolution of the remote user's video is beyond + * the range where super resolution can be applied. + * - #WARN_SUPER_RESOLUTION_USER_COUNT_OVER_LIMITATION (1611): Super resolution is already being used to boost another + * remote user's video. + * - #WARN_SUPER_RESOLUTION_DEVICE_NOT_SUPPORTED (1612): The device does not support using super resolution. + * + * @note + * - This method is for Android and iOS only. + * - Before calling this method, ensure that you have integrated the following dynamic library into your project: + * - Android: `libagora_super_resolution_extension.so` + * - iOS: `AgoraSuperResolutionExtension.xcframework` + * - Because this method has certain system performance requirements, Agora recommends that you use the following devices or better: + * - Android: + * - VIVO: V1821A, NEX S, 1914A, 1916A, 1962A, 1824BA, X60, X60 Pro + * - OPPO: PCCM00, Find X3 + * - OnePlus: A6000 + * - Xiaomi: Mi 8, Mi 9, Mi 10, Mi 11, MIX3, Redmi K20 Pro + * - SAMSUNG: SM-G9600, SM-G9650, SM-N9600, SM-G9708, SM-G960U, SM-G9750, S20, S21 + * - HUAWEI: SEA-AL00, ELE-AL00, VOG-AL00, YAL-AL10, HMA-AL00, EVR-AN00, nova 4, nova 5 Pro, + * nova 6 5G, nova 7 5G, Mate 30, Mate 30 Pro, Mate 40, Mate 40 Pro, P40 P40 Pro, HUAWEI MediaPad M6, MatePad 10.8 + * - iOS (iOS 12.0 or later): + * - iPhone XR + * - iPhone XS + * - iPhone XS Max + * - iPhone 11 + * - iPhone 11 Pro + * - iPhone 11 Pro Max + * - iPhone 12 + * - iPhone 12 mini + * - iPhone 12 Pro + * - iPhone 12 Pro Max + * - iPhone 12 SE (2nd generation) + * - iPad Pro 11-inch (3rd generation) + * - iPad Pro 12.9-inch (3rd generation) + * - iPad Air (3rd generation) + * - iPad Air (4th generation) + * + * @param userId The user ID of the remote user. + * @param enable Determines whether to enable super resolution for the remote user's video: + * - true: Enable super resolution. + * - false: Disable super resolution. + * + * @return + * - 0: Success. + * - < 0: Failure. + * - `-157 (ERR_MODULE_NOT_FOUND)`: The dynamic library for super resolution is not integrated. + */ + virtual int enableRemoteSuperResolution(uid_t userId, bool enable) = 0; + /** This method enables you to add synchronized metadata in the video stream for more diversified interactive live streaming, such as sending shopping links, digital coupons, and online quizzes. + + @note + - Call this method before the joinChannel method. + - This method applies to the `LIVE_BROADCASTING` channel profile. + + @param observer The IMetadataObserver class. See the definition of IMetadataObserver for details. + @param type See \ref IMetadataObserver::METADATA_TYPE "METADATA_TYPE". The SDK supports VIDEO_METADATA (0) only for now. + + @return + - 0: Success. + - < 0: Failure. + */ + virtual int registerMediaMetadataObserver(IMetadataObserver* observer, IMetadataObserver::METADATA_TYPE type) = 0; + /** Provides technical preview functionalities or special customizations by configuring the SDK with JSON options. + + The JSON options are not public by default. Agora is working on making commonly used JSON options public in a standard way. + + @param parameters Sets the parameter as a JSON string in the specified format. + + @return + - 0: Success. + - < 0: Failure. + */ + virtual int setParameters(const char* parameters) = 0; +#if defined(_WIN32) + /** + * Customizes the local video renderer. (for Windows only) + * + * @since v3.5.0 + * + * During a real-time audio and video interaction, the Agora SDK enables the default renderer to render local video. + * If you want to customize the local video rendering, you can first customize the video renderer via the IVideoSink + * class, and then call this method to use the custom video renderer to render the local video. + * + * @note You can call this method either before or after joining a channel. + * + * @param videoSink The custom video renderer. See IVideoSink. + * + * @return + * - 0: Success. + * - < 0: Failure. + */ + virtual int setLocalVideoRenderer(IVideoSink* videoSink) = 0; + /** + * Customizes the remote video renderer. (for Windows only) + * + * @since v3.5.0 + * + * During a real-time audio and video interaction, the Agora SDK enables the default renderer to render remote video. + * If you want to customize the remote video rendering, you can first customize the video renderer via the IVideoSink + * class, and then call this method to use the custom video renderer to render the remote video. + * + * @note You can call this method either before or after joining a channel. + * + * @param uid The user ID of the remote user. + * @param videoSink The custom video renderer. See IVideoSink. + * + * @return + * - 0: Success. + * - < 0: Failure. + */ + virtual int setRemoteVideoRenderer(uid_t uid, IVideoSink* videoSink) = 0; +#endif + /// @cond + /** set local access point addresses in local proxy mode. use this method before join + channel. + + @param ips local access point ip addresses. + @param ipSize the number of local access point. + @param domain The domain described in certificate installed on specific local access point. pass "" means using sni domain on specific local access point + + @return + - 0: Success + - < 0: Failure + */ + virtual int setLocalAccessPoint(const char** ips, int ipSize, const char* domain) = 0; + /// @endcond +#if defined(__ANDROID__) || (defined(__APPLE__) && TARGET_OS_IOS) + /** + * Sets whether to enable the flash. + * + * @since v3.5.1 + * + * @note + * - Call this method after the camera is started. + * - This method is for Android and iOS only. + * - On iPads with system version 15, even if \ref IRtcEngine::isCameraTorchSupported "isCameraTorchSupported" + * returns true, you might fail to successfully enable the flash by calling `setCameraTorchOn` due to + * system issues. + * + * @param isOn Determines whether to enable the flash: + * - true: Enable the flash. + * - false: Disable the flash. + * + * @return + * - 0: Success + * - < 0: Failure + */ + virtual int setCameraTorchOn(bool isOn) = 0; + /** + * Checks whether the device supports enabling the flash. + * + * @since v3.5.1 + * + * The SDK uses the front camera by default, so if you call `isCameraTorchSupported` directly, + * you can find out from the return value whether the device supports enabling the flash + * when using the front camera. If you want to check whether the device supports enabling the + * flash when using the rear camera, call \ref IRtcEngine::switchCamera "switchCamera" + * to switch the camera used by the SDK to the rear camera, and then call `isCameraTorchSupported`. + * + * @note + * - Call this method after the camera is started. + * - This method is for Android and iOS only. + * - On iPads with system version 15, even if `isCameraTorchSupported` returns true, you might + * fail to successfully enable the flash by calling \ref IRtcEngine::setCameraTorchOn "setCameraTorchOn" + * due to system issues. + * + * @return + * - true: The device supports enabling the flash. + * - false: The device does not support enabling the flash. + */ + virtual bool isCameraTorchSupported() = 0; +#endif + + /** + * Takes a snapshot of a video stream. + * + * @since v3.5.2 + * + * This method takes a snapshot of a video stream from the specified user, generates a JPG image, + * and saves it to the specified path. + * + * The method is asynchronous, and the SDK has not taken the snapshot when the method call returns. + * After a successful method call, the SDK triggers the \ref IRtcEngineEventHandler::onSnapshotTaken "onSnapshotTaken" + * callback to report whether the snapshot is successfully taken as well as the details of the snapshot taken. + * + * @note + * - Call this method after joining a channel. + * - If the video of the specified user is pre-processed, for example, added with watermarks or image enhancement + * effects, the generated snapshot also includes the pre-processing effects. + * + * @param channel The channel name. + * @param uid The user ID of the user. Set `uid` as 0 if you want to take a snapshot of the local user's video. + * @param filePath The local path (including the filename extensions) of the snapshot. For example, + * `C:\Users\\AppData\Local\Agora\\example.jpg` on Windows, + * `/App Sandbox/Library/Caches/example.jpg` on iOS, `~/Library/Logs/example.jpg` on macOS, and + * `/storage/emulated/0/Android/data//files/example.jpg` on Android. Ensure that the path you specify + * exists and is writable. + * + * @return + * - 0: Success. + * - < 0: Failure. + */ + virtual int takeSnapshot(const char* channel, uid_t uid, const char* filePath) = 0; + + /// @cond + virtual int enableContentInspect(bool enabled, const ContentInspectConfig& config) = 0; + /// @endcond +}; + +class IRtcEngineParameter { + public: + virtual ~IRtcEngineParameter() {} + /** + * Releases all IRtcEngineParameter resources. + */ + virtual void release() = 0; + + /** Sets the bool value of a specified key in the JSON format. + + @param key Pointer to the name of the key. + @param value Sets the value. + @return + - 0: Success. + - < 0: Failure. + */ + virtual int setBool(const char* key, bool value) = 0; + + /** Sets the int value of a specified key in the JSON format. + + @param key Pointer to the name of the key. + @param value Sets the value. + + @return + - 0: Success. + - < 0: Failure. + */ + virtual int setInt(const char* key, int value) = 0; + + /** Sets the unsigned int value of a specified key in the JSON format. + + @param key Pointer to the name of the key. + @param value Sets the value. + + @return + - 0: Success. + - < 0: Failure. + */ + virtual int setUInt(const char* key, unsigned int value) = 0; + + /** Sets the double value of a specified key in the JSON format. + + @param key Pointer to the name of the key. + @param value Sets the value. + + @return + - 0: Success. + - < 0: Failure. + */ + virtual int setNumber(const char* key, double value) = 0; + + /** Sets the string value of a specified key in the JSON format. + + @param key Pointer to the name of the key. + @param value Pointer to the set value. + + @return + - 0: Success. + - < 0: Failure. + */ + virtual int setString(const char* key, const char* value) = 0; + + /** Sets the object value of a specified key in the JSON format. + + @param key Pointer to the name of the key. + @param value Pointer to the set value. + + @return + - 0: Success. + - < 0: Failure. + */ + virtual int setObject(const char* key, const char* value) = 0; + + /** Gets the bool value of a specified key in the JSON format. + + @param key Pointer to the name of the key. + @param value Pointer to the retrieved value. + + @return + - 0: Success. + - < 0: Failure. + */ + virtual int getBool(const char* key, bool& value) = 0; + + /** Gets the int value of the JSON format. + + @param key Pointer to the name of the key. + @param value Pointer to the retrieved value. + + @return + - 0: Success. + - < 0: Failure. + */ + virtual int getInt(const char* key, int& value) = 0; + + /** Gets the unsigned int value of a specified key in the JSON format. + + @param key Pointer to the name of the key. + @param value Pointer to the retrieved value. + @return + - 0: Success. + - < 0: Failure. + */ + virtual int getUInt(const char* key, unsigned int& value) = 0; + + /** Gets the double value of a specified key in the JSON format. + + @param key Pointer to the name of the key. + @param value Pointer to the retrieved value. + + @return + - 0: Success. + - < 0: Failure. + */ + virtual int getNumber(const char* key, double& value) = 0; + + /** Gets the string value of a specified key in the JSON format. + + @param key Pointer to the name of the key. + @param value Pointer to the retrieved value. + + @return + - 0: Success. + - < 0: Failure. + */ + virtual int getString(const char* key, agora::util::AString& value) = 0; + + /** Gets a child object value of a specified key in the JSON format. + + @param key Pointer to the name of the key. + @param value Pointer to the retrieved value. + @return + - 0: Success. + - < 0: Failure. + */ + virtual int getObject(const char* key, agora::util::AString& value) = 0; + + /** Gets the array value of a specified key in the JSON format. + + @param key Pointer to the name of the key. + @param value Pointer to the retrieved value. + @return + - 0: Success. + - < 0: Failure. + */ + virtual int getArray(const char* key, agora::util::AString& value) = 0; + + /** Provides the technical preview functionalities or special customizations by configuring the SDK with JSON options. + + @param parameters Pointer to the set parameters in a JSON string. + + @return + - 0: Success. + - < 0: Failure. + */ + virtual int setParameters(const char* parameters) = 0; + + /** Sets the profile to control the RTC engine. + + @param profile Pointer to the set profile. + @param merge Sets whether to merge the profile data with the original value: + - true: Merge the profile data with the original value. + - false: Do not merge the profile data with the original value. + + @return + - 0: Success. + - < 0: Failure. + */ + virtual int setProfile(const char* profile, bool merge) = 0; + + virtual int convertPath(const char* filePath, agora::util::AString& value) = 0; +}; + +class AAudioDeviceManager : public agora::util::AutoPtr { + public: + AAudioDeviceManager(IRtcEngine* engine) { queryInterface(engine, AGORA_IID_AUDIO_DEVICE_MANAGER); } +}; + +class AVideoDeviceManager : public agora::util::AutoPtr { + public: + AVideoDeviceManager(IRtcEngine* engine) { queryInterface(engine, AGORA_IID_VIDEO_DEVICE_MANAGER); } +}; + +class AParameter : public agora::util::AutoPtr { + public: + AParameter(IRtcEngine& engine) { initialize(&engine); } + AParameter(IRtcEngine* engine) { initialize(engine); } + AParameter(IRtcEngineParameter* p) : agora::util::AutoPtr(p) {} + + private: + bool initialize(IRtcEngine* engine) { + IRtcEngineParameter* p = NULL; + if (engine && !engine->queryInterface(AGORA_IID_RTC_ENGINE_PARAMETER, (void**)&p)) reset(p); + return p != NULL; + } +}; +/** **DEPRECATED** The RtcEngineParameters class is deprecated, use the IRtcEngine class instead. + */ +class RtcEngineParameters { + public: + RtcEngineParameters(IRtcEngine& engine) : m_parameter(&engine) {} + RtcEngineParameters(IRtcEngine* engine) : m_parameter(engine) {} + + int enableLocalVideo(bool enabled) { return setParameters("{\"rtc.video.capture\":%s,\"che.video.local.capture\":%s,\"che.video.local.render\":%s,\"che.video.local.send\":%s}", enabled ? "true" : "false", enabled ? "true" : "false", enabled ? "true" : "false", enabled ? "true" : "false"); } + + int muteLocalVideoStream(bool mute) { return setParameters("{\"rtc.video.mute_me\":%s}", mute ? "true" : "false"); } + + int muteAllRemoteVideoStreams(bool mute) { return m_parameter ? m_parameter->setBool("rtc.video.mute_peers", mute) : -ERR_NOT_INITIALIZED; } + + int setDefaultMuteAllRemoteVideoStreams(bool mute) { return m_parameter ? m_parameter->setBool("rtc.video.set_default_mute_peers", mute) : -ERR_NOT_INITIALIZED; } + + int muteRemoteVideoStream(uid_t uid, bool mute) { return setObject("rtc.video.mute_peer", "{\"uid\":%u,\"mute\":%s}", uid, mute ? "true" : "false"); } + + int setPlaybackDeviceVolume(int volume) { // [0,255] + return m_parameter ? m_parameter->setInt("che.audio.output.volume", volume) : -ERR_NOT_INITIALIZED; + } + + int startAudioRecording(const char* filePath, AUDIO_RECORDING_QUALITY_TYPE quality) { return startAudioRecording(filePath, 32000, quality); } + + int startAudioRecording(const char* filePath, int sampleRate, AUDIO_RECORDING_QUALITY_TYPE quality) { + if (!m_parameter) return -ERR_NOT_INITIALIZED; +#if defined(_WIN32) + util::AString path; + if (!m_parameter->convertPath(filePath, path)) + filePath = path->c_str(); + else + return -ERR_INVALID_ARGUMENT; +#endif + return setObject("che.audio.start_recording", "{\"filePath\":\"%s\",\"sampleRate\":%d,\"quality\":%d}", filePath, sampleRate, quality); + } + + int stopAudioRecording() { return setParameters("{\"che.audio.stop_recording\":true, \"che.audio.stop_nearend_recording\":true, \"che.audio.stop_farend_recording\":true}"); } + + int startAudioMixing(const char* filePath, bool loopback, bool replace, int cycle, int startPos = 0) { + if (!m_parameter) return -ERR_NOT_INITIALIZED; +#if defined(_WIN32) + util::AString path; + if (!m_parameter->convertPath(filePath, path)) + filePath = path->c_str(); + else + return -ERR_INVALID_ARGUMENT; +#endif + return setObject("che.audio.start_file_as_playout", "{\"filePath\":\"%s\",\"loopback\":%s,\"replace\":%s,\"cycle\":%d, \"startPos\":%d}", filePath, loopback ? "true" : "false", replace ? "true" : "false", cycle, startPos); + } + + int stopAudioMixing() { return m_parameter ? m_parameter->setBool("che.audio.stop_file_as_playout", true) : -ERR_NOT_INITIALIZED; } + + int pauseAudioMixing() { return m_parameter ? m_parameter->setBool("che.audio.pause_file_as_playout", true) : -ERR_NOT_INITIALIZED; } + + int resumeAudioMixing() { return m_parameter ? m_parameter->setBool("che.audio.pause_file_as_playout", false) : -ERR_NOT_INITIALIZED; } + + int adjustAudioMixingVolume(int volume) { + int ret = adjustAudioMixingPlayoutVolume(volume); + if (ret == 0) { + adjustAudioMixingPublishVolume(volume); + } + return ret; + } + + int adjustAudioMixingPlayoutVolume(int volume) { return m_parameter ? m_parameter->setInt("che.audio.set_file_as_playout_volume", volume) : -ERR_NOT_INITIALIZED; } + + int getAudioMixingPlayoutVolume() { + int volume = 0; + int r = m_parameter ? m_parameter->getInt("che.audio.get_file_as_playout_volume", volume) : -ERR_NOT_INITIALIZED; + if (r == 0) r = volume; + return r; + } + + int adjustAudioMixingPublishVolume(int volume) { return m_parameter ? m_parameter->setInt("che.audio.set_file_as_playout_publish_volume", volume) : -ERR_NOT_INITIALIZED; } + + int getAudioMixingPublishVolume() { + int volume = 0; + int r = m_parameter ? m_parameter->getInt("che.audio.get_file_as_playout_publish_volume", volume) : -ERR_NOT_INITIALIZED; + if (r == 0) r = volume; + return r; + } + + int getAudioMixingDuration() { + int duration = 0; + int r = m_parameter ? m_parameter->getInt("che.audio.get_mixing_file_length_ms", duration) : -ERR_NOT_INITIALIZED; + if (r == 0) r = duration; + return r; + } + + int getAudioMixingCurrentPosition() { + if (!m_parameter) return -ERR_NOT_INITIALIZED; + int pos = 0; + int r = m_parameter->getInt("che.audio.get_mixing_file_played_ms", pos); + if (r == 0) r = pos; + return r; + } + + int setAudioMixingPosition(int pos /*in ms*/) { return m_parameter ? m_parameter->setInt("che.audio.mixing.file.position", pos) : -ERR_NOT_INITIALIZED; } + + int setAudioMixingPitch(int pitch) { + if (!m_parameter) { + return -ERR_NOT_INITIALIZED; + } + if (pitch > 12 || pitch < -12) { + return -ERR_INVALID_ARGUMENT; + } + return m_parameter->setInt("che.audio.set_playout_file_pitch_semitones", pitch); + } + + int getEffectsVolume() { + if (!m_parameter) return -ERR_NOT_INITIALIZED; + int volume = 0; + int r = m_parameter->getInt("che.audio.game_get_effects_volume", volume); + if (r == 0) r = volume; + return r; + } + + int setEffectsVolume(int volume) { return m_parameter ? m_parameter->setInt("che.audio.game_set_effects_volume", volume) : -ERR_NOT_INITIALIZED; } + + int setVolumeOfEffect(int soundId, int volume) { return setObject("che.audio.game_adjust_effect_volume", "{\"soundId\":%d,\"gain\":%d}", soundId, volume); } + + int playEffect(int soundId, const char* filePath, int loopCount, double pitch, double pan, int gain, bool publish = false) { +#if defined(_WIN32) + util::AString path; + if (!m_parameter->convertPath(filePath, path)) + filePath = path->c_str(); + else if (!filePath) + filePath = ""; +#endif + return setObject("che.audio.game_play_effect", "{\"soundId\":%d,\"filePath\":\"%s\",\"loopCount\":%d, \"pitch\":%lf,\"pan\":%lf,\"gain\":%d, \"send2far\":%d}", soundId, filePath, loopCount, pitch, pan, gain, publish); + } + + int stopEffect(int soundId) { return m_parameter ? m_parameter->setInt("che.audio.game_stop_effect", soundId) : -ERR_NOT_INITIALIZED; } + + int stopAllEffects() { return m_parameter ? m_parameter->setBool("che.audio.game_stop_all_effects", true) : -ERR_NOT_INITIALIZED; } + + int preloadEffect(int soundId, char* filePath) { return setObject("che.audio.game_preload_effect", "{\"soundId\":%d,\"filePath\":\"%s\"}", soundId, filePath); } + + int unloadEffect(int soundId) { return m_parameter ? m_parameter->setInt("che.audio.game_unload_effect", soundId) : -ERR_NOT_INITIALIZED; } + + int pauseEffect(int soundId) { return m_parameter ? m_parameter->setInt("che.audio.game_pause_effect", soundId) : -ERR_NOT_INITIALIZED; } + + int pauseAllEffects() { return m_parameter ? m_parameter->setBool("che.audio.game_pause_all_effects", true) : -ERR_NOT_INITIALIZED; } + + int resumeEffect(int soundId) { return m_parameter ? m_parameter->setInt("che.audio.game_resume_effect", soundId) : -ERR_NOT_INITIALIZED; } + + int resumeAllEffects() { return m_parameter ? m_parameter->setBool("che.audio.game_resume_all_effects", true) : -ERR_NOT_INITIALIZED; } + + int enableSoundPositionIndication(bool enabled) { return m_parameter ? m_parameter->setBool("che.audio.enable_sound_position", enabled) : -ERR_NOT_INITIALIZED; } + + int setRemoteVoicePosition(uid_t uid, double pan, double gain) { return setObject("che.audio.game_place_sound_position", "{\"uid\":%u,\"pan\":%lf,\"gain\":%lf}", uid, pan, gain); } + + int setLocalVoicePitch(double pitch) { return m_parameter ? m_parameter->setInt("che.audio.morph.pitch_shift", static_cast(pitch * 100)) : -ERR_NOT_INITIALIZED; } + + int setLocalVoiceEqualization(AUDIO_EQUALIZATION_BAND_FREQUENCY bandFrequency, int bandGain) { return setObject("che.audio.morph.equalization", "{\"index\":%d,\"gain\":%d}", static_cast(bandFrequency), bandGain); } + + int setLocalVoiceReverb(AUDIO_REVERB_TYPE reverbKey, int value) { return setObject("che.audio.morph.reverb", "{\"key\":%d,\"value\":%d}", static_cast(reverbKey), value); } + + int setLocalVoiceChanger(VOICE_CHANGER_PRESET voiceChanger) { + if (!m_parameter) return -ERR_NOT_INITIALIZED; + if (voiceChanger == 0x00000000) { + return m_parameter->setInt("che.audio.morph.voice_changer", static_cast(voiceChanger)); + } else if (voiceChanger > 0x00000000 && voiceChanger < 0x00100000) { + return m_parameter->setInt("che.audio.morph.voice_changer", static_cast(voiceChanger)); + } else if (voiceChanger > 0x00100000 && voiceChanger < 0x00200000) { + return m_parameter->setInt("che.audio.morph.voice_changer", static_cast(voiceChanger - 0x00100000 + 6)); + } else if (voiceChanger > 0x00200000 && voiceChanger < 0x00300000) { + return m_parameter->setInt("che.audio.morph.beauty_voice", static_cast(voiceChanger - 0x00200000)); + } else { + return -ERR_INVALID_ARGUMENT; + } + } + + int setLocalVoiceReverbPreset(AUDIO_REVERB_PRESET reverbPreset) { + if (!m_parameter) return -ERR_NOT_INITIALIZED; + if (reverbPreset == 0x00000000) { + return m_parameter->setInt("che.audio.morph.reverb_preset", static_cast(reverbPreset)); + } else if (reverbPreset > 0x00000000 && reverbPreset < 0x00100000) { + return m_parameter->setInt("che.audio.morph.reverb_preset", static_cast(reverbPreset + 8)); + } else if (reverbPreset > 0x00100000 && reverbPreset < 0x00200000) { + return m_parameter->setInt("che.audio.morph.reverb_preset", static_cast(reverbPreset - 0x00100000)); + } else if (reverbPreset > 0x00200000 && reverbPreset < 0x00200002) { + return m_parameter->setInt("che.audio.morph.virtual_stereo", static_cast(reverbPreset - 0x00200000)); + } else if (reverbPreset > (AUDIO_REVERB_PRESET)0x00300000 && reverbPreset < (AUDIO_REVERB_PRESET)0x00300002) + return setObject("che.audio.morph.electronic_voice", "{\"key\":%d,\"value\":%d}", 1, 4); + else if (reverbPreset > (AUDIO_REVERB_PRESET)0x00400000 && reverbPreset < (AUDIO_REVERB_PRESET)0x00400002) + return m_parameter->setInt("che.audio.morph.threedim_voice", 10); + else { + return -ERR_INVALID_ARGUMENT; + } + } + + int setAudioEffectPreset(AUDIO_EFFECT_PRESET preset) { + if (!m_parameter) return -ERR_NOT_INITIALIZED; + if (preset == AUDIO_EFFECT_OFF) { + return m_parameter->setInt("che.audio.morph.voice_changer", 0); + } + if (preset == ROOM_ACOUSTICS_KTV) { + return m_parameter->setInt("che.audio.morph.reverb_preset", 1); + } + if (preset == ROOM_ACOUSTICS_VOCAL_CONCERT) { + return m_parameter->setInt("che.audio.morph.reverb_preset", 2); + } + if (preset == ROOM_ACOUSTICS_STUDIO) { + return m_parameter->setInt("che.audio.morph.reverb_preset", 5); + } + if (preset == ROOM_ACOUSTICS_PHONOGRAPH) { + return m_parameter->setInt("che.audio.morph.reverb_preset", 8); + } + if (preset == ROOM_ACOUSTICS_VIRTUAL_STEREO) { + return m_parameter->setInt("che.audio.morph.virtual_stereo", 1); + } + if (preset == ROOM_ACOUSTICS_SPACIAL) { + return m_parameter->setInt("che.audio.morph.voice_changer", 15); + } + if (preset == ROOM_ACOUSTICS_ETHEREAL) { + return m_parameter->setInt("che.audio.morph.voice_changer", 5); + } + if (preset == ROOM_ACOUSTICS_3D_VOICE) { + return m_parameter->setInt("che.audio.morph.threedim_voice", 10); + } + if (preset == VOICE_CHANGER_EFFECT_UNCLE) { + return m_parameter->setInt("che.audio.morph.reverb_preset", 3); + } + if (preset == VOICE_CHANGER_EFFECT_OLDMAN) { + return m_parameter->setInt("che.audio.morph.voice_changer", 1); + } + if (preset == VOICE_CHANGER_EFFECT_BOY) { + return m_parameter->setInt("che.audio.morph.voice_changer", 2); + } + if (preset == VOICE_CHANGER_EFFECT_SISTER) { + return m_parameter->setInt("che.audio.morph.reverb_preset", 4); + } + if (preset == VOICE_CHANGER_EFFECT_GIRL) { + return m_parameter->setInt("che.audio.morph.voice_changer", 3); + } + if (preset == VOICE_CHANGER_EFFECT_PIGKING) { + return m_parameter->setInt("che.audio.morph.voice_changer", 4); + } + if (preset == VOICE_CHANGER_EFFECT_HULK) { + return m_parameter->setInt("che.audio.morph.voice_changer", 6); + } + if (preset == STYLE_TRANSFORMATION_RNB) { + return m_parameter->setInt("che.audio.morph.reverb_preset", 7); + } + if (preset == STYLE_TRANSFORMATION_POPULAR) { + return m_parameter->setInt("che.audio.morph.reverb_preset", 6); + } + if (preset == PITCH_CORRECTION) { + return setObject("che.audio.morph.electronic_voice", "{\"key\":%d,\"value\":%d}", 1, 4); + } + return -ERR_INVALID_ARGUMENT; + } + + int setVoiceBeautifierPreset(VOICE_BEAUTIFIER_PRESET preset) { + if (!m_parameter) return -ERR_NOT_INITIALIZED; + if (preset == VOICE_BEAUTIFIER_OFF) { + return m_parameter->setInt("che.audio.morph.voice_changer", 0); + } + if (preset == CHAT_BEAUTIFIER_MAGNETIC) { + return m_parameter->setInt("che.audio.morph.beauty_voice", 1); + } + if (preset == CHAT_BEAUTIFIER_FRESH) { + return m_parameter->setInt("che.audio.morph.beauty_voice", 2); + } + if (preset == CHAT_BEAUTIFIER_VITALITY) { + return m_parameter->setInt("che.audio.morph.beauty_voice", 3); + } + if (preset == SINGING_BEAUTIFIER) { + return setObject("che.audio.morph.beauty_sing", "{\"key\":%d,\"value\":%d}", 1, 1); + } + if (preset == TIMBRE_TRANSFORMATION_VIGOROUS) { + return m_parameter->setInt("che.audio.morph.voice_changer", 7); + } + if (preset == TIMBRE_TRANSFORMATION_DEEP) { + return m_parameter->setInt("che.audio.morph.voice_changer", 8); + } + if (preset == TIMBRE_TRANSFORMATION_MELLOW) { + return m_parameter->setInt("che.audio.morph.voice_changer", 9); + } + if (preset == TIMBRE_TRANSFORMATION_FALSETTO) { + return m_parameter->setInt("che.audio.morph.voice_changer", 10); + } + if (preset == TIMBRE_TRANSFORMATION_FULL) { + return m_parameter->setInt("che.audio.morph.voice_changer", 11); + } + if (preset == TIMBRE_TRANSFORMATION_CLEAR) { + return m_parameter->setInt("che.audio.morph.voice_changer", 12); + } + if (preset == TIMBRE_TRANSFORMATION_RESOUNDING) { + return m_parameter->setInt("che.audio.morph.voice_changer", 13); + } + if (preset == TIMBRE_TRANSFORMATION_RINGING) { + return m_parameter->setInt("che.audio.morph.voice_changer", 14); + } + return -ERR_INVALID_ARGUMENT; + } + + int setAudioEffectParameters(AUDIO_EFFECT_PRESET preset, int param1, int param2) { + if (!m_parameter) return -ERR_NOT_INITIALIZED; + if (preset == PITCH_CORRECTION) { + return setObject("che.audio.morph.electronic_voice", "{\"key\":%d,\"value\":%d}", param1, param2); + } + if (preset == ROOM_ACOUSTICS_3D_VOICE) { + return m_parameter->setInt("che.audio.morph.threedim_voice", param1); + } + return -ERR_INVALID_ARGUMENT; + } + + int setVoiceBeautifierParameters(VOICE_BEAUTIFIER_PRESET preset, int param1, int param2) { + if (!m_parameter) return -ERR_NOT_INITIALIZED; + if (preset == SINGING_BEAUTIFIER) { + return setObject("che.audio.morph.beauty_sing", "{\"key\":%d,\"value\":%d}", param1, param2); + } + return -ERR_INVALID_ARGUMENT; + } + + /** **DEPRECATED** Use \ref IRtcEngine::disableAudio "disableAudio" instead. Disables the audio function in the channel. + + @return + - 0: Success. + - < 0: Failure. + */ + int pauseAudio() { return m_parameter ? m_parameter->setBool("che.pause.audio", true) : -ERR_NOT_INITIALIZED; } + + int resumeAudio() { return m_parameter ? m_parameter->setBool("che.pause.audio", false) : -ERR_NOT_INITIALIZED; } + + int setHighQualityAudioParameters(bool fullband, bool stereo, bool fullBitrate) { return setObject("che.audio.codec.hq", "{\"fullband\":%s,\"stereo\":%s,\"fullBitrate\":%s}", fullband ? "true" : "false", stereo ? "true" : "false", fullBitrate ? "true" : "false"); } + + int adjustRecordingSignalVolume(int volume) { //[0, 400]: e.g. 50~0.5x 100~1x 400~4x + if (volume < 0) + volume = 0; + else if (volume > 400) + volume = 400; + return m_parameter ? m_parameter->setInt("che.audio.record.signal.volume", volume) : -ERR_NOT_INITIALIZED; + } + + int adjustPlaybackSignalVolume(int volume) { //[0, 400] + if (volume < 0) + volume = 0; + else if (volume > 400) + volume = 400; + return m_parameter ? m_parameter->setInt("che.audio.playout.signal.volume", volume) : -ERR_NOT_INITIALIZED; + } + + int enableAudioVolumeIndication(int interval, int smooth, bool report_vad) { // in ms: <= 0: disable, > 0: enable, interval in ms + if (interval < 0) interval = 0; + return setObject("che.audio.volume_indication", "{\"interval\":%d,\"smooth\":%d,\"vad\":%d}", interval, smooth, report_vad); + } + + int muteLocalAudioStream(bool mute) { return setParameters("{\"rtc.audio.mute_me\":%s}", mute ? "true" : "false"); } + // mute/unmute all peers. unmute will clear all muted peers specified mutePeer() interface + + int muteRemoteAudioStream(uid_t uid, bool mute) { return setObject("rtc.audio.mute_peer", "{\"uid\":%u,\"mute\":%s}", uid, mute ? "true" : "false"); } + + int muteAllRemoteAudioStreams(bool mute) { return m_parameter ? m_parameter->setBool("rtc.audio.mute_peers", mute) : -ERR_NOT_INITIALIZED; } + + int setVoiceConversionPreset(VOICE_CONVERSION_PRESET preset) { + if (!m_parameter) return -ERR_NOT_INITIALIZED; + if (preset == VOICE_CONVERSION_OFF) { + return m_parameter->setInt("che.audio.morph.voice_changer", 0); + } + if (preset == VOICE_CHANGER_NEUTRAL) { + return m_parameter->setInt("che.audio.morph.vocal_changer", 1); + } + if (preset == VOICE_CHANGER_SWEET) { + return m_parameter->setInt("che.audio.morph.vocal_changer", 2); + } + if (preset == VOICE_CHANGER_SOLID) { + return m_parameter->setInt("che.audio.morph.vocal_changer", 3); + } + if (preset == VOICE_CHANGER_BASS) { + return m_parameter->setInt("che.audio.morph.vocal_changer", 4); + } + return -ERR_INVALID_ARGUMENT; + } + + int setDefaultMuteAllRemoteAudioStreams(bool mute) { return m_parameter ? m_parameter->setBool("rtc.audio.set_default_mute_peers", mute) : -ERR_NOT_INITIALIZED; } + + int setExternalAudioSource(bool enabled, int sampleRate, int channels) { + if (enabled) + return setParameters("{\"che.audio.external_capture\":true,\"che.audio.set_external_source_format\":{\"sampleRate\":%d,\"channelCnt\":%d}}", sampleRate, channels); + else + return setParameters("{\"che.audio.external_capture\":false}"); + } + + int setExternalAudioSink(bool enabled, int sampleRate, int channels) { + if (enabled) + return setParameters("{\"che.audio.external_render\":true,\"che.audio.external_render.pull\":true,\"che.audio.set_render_raw_audio_format\":{\"sampleRate\":%d,\"channelCnt\":%d,\"mode\":%d}}", sampleRate, channels, RAW_AUDIO_FRAME_OP_MODE_TYPE::RAW_AUDIO_FRAME_OP_MODE_READ_ONLY); + else + return setParameters("{\"che.audio.external_render\":false,\"che.audio.external_render.pull\":false}"); + } + + int setLogFile(const char* filePath) { + if (!m_parameter) return -ERR_NOT_INITIALIZED; +#if defined(_WIN32) + util::AString path; + if (!m_parameter->convertPath(filePath, path)) + filePath = path->c_str(); + else if (!filePath) + filePath = ""; +#endif + return m_parameter->setString("rtc.log_file", filePath); + } + + int setLogFilter(unsigned int filter) { return m_parameter ? m_parameter->setUInt("rtc.log_filter", filter & LOG_FILTER_MASK) : -ERR_NOT_INITIALIZED; } + + int setLogFileSize(unsigned int fileSizeInKBytes) { return m_parameter ? m_parameter->setUInt("rtc.log_size", fileSizeInKBytes) : -ERR_NOT_INITIALIZED; } + + int setLocalRenderMode(RENDER_MODE_TYPE renderMode) { return setRemoteRenderMode(0, renderMode); } + + int setRemoteRenderMode(uid_t uid, RENDER_MODE_TYPE renderMode) { return setParameters("{\"che.video.render_mode\":[{\"uid\":%u,\"renderMode\":%d}]}", uid, renderMode); } + + int setCameraCapturerConfiguration(const CameraCapturerConfiguration& config) { + if (!m_parameter) return -ERR_NOT_INITIALIZED; + if (config.preference == CAPTURER_OUTPUT_PREFERENCE_MANUAL) { + m_parameter->setInt("che.video.capture_width", config.captureWidth); + m_parameter->setInt("che.video.capture_height", config.captureHeight); + } + return m_parameter->setInt("che.video.camera_capture_mode", (int)config.preference); + } + + int enableDualStreamMode(bool enabled) { return setParameters("{\"rtc.dual_stream_mode\":%s,\"che.video.enableLowBitRateStream\":%d}", enabled ? "true" : "false", enabled ? 1 : 0); } + + int setRemoteVideoStreamType(uid_t uid, REMOTE_VIDEO_STREAM_TYPE streamType) { + return setParameters("{\"rtc.video.set_remote_video_stream\":{\"uid\":%u,\"stream\":%d}, \"che.video.setstream\":{\"uid\":%u,\"stream\":%d}}", uid, streamType, uid, streamType); + // return setObject("rtc.video.set_remote_video_stream", "{\"uid\":%u,\"stream\":%d}", uid, streamType); + } + + int setRemoteDefaultVideoStreamType(REMOTE_VIDEO_STREAM_TYPE streamType) { return m_parameter ? m_parameter->setInt("rtc.video.set_remote_default_video_stream_type", streamType) : -ERR_NOT_INITIALIZED; } + + int setRecordingAudioFrameParameters(int sampleRate, int channel, RAW_AUDIO_FRAME_OP_MODE_TYPE mode, int samplesPerCall) { return setObject("che.audio.set_capture_raw_audio_format", "{\"sampleRate\":%d,\"channelCnt\":%d,\"mode\":%d,\"samplesPerCall\":%d}", sampleRate, channel, mode, samplesPerCall); } + + int setPlaybackAudioFrameParameters(int sampleRate, int channel, RAW_AUDIO_FRAME_OP_MODE_TYPE mode, int samplesPerCall) { return setObject("che.audio.set_render_raw_audio_format", "{\"sampleRate\":%d,\"channelCnt\":%d,\"mode\":%d,\"samplesPerCall\":%d}", sampleRate, channel, mode, samplesPerCall); } + + int setMixedAudioFrameParameters(int sampleRate, int samplesPerCall) { return setObject("che.audio.set_mixed_raw_audio_format", "{\"sampleRate\":%d,\"samplesPerCall\":%d}", sampleRate, samplesPerCall); } + + int enableWebSdkInteroperability(bool enabled) { // enable interoperability with zero-plugin web sdk + return setParameters("{\"rtc.video.web_h264_interop_enable\":%s,\"che.video.web_h264_interop_enable\":%s}", enabled ? "true" : "false", enabled ? "true" : "false"); + } + + // only for live broadcast + + int setVideoQualityParameters(bool preferFrameRateOverImageQuality) { return setParameters("{\"rtc.video.prefer_frame_rate\":%s,\"che.video.prefer_frame_rate\":%s}", preferFrameRateOverImageQuality ? "true" : "false", preferFrameRateOverImageQuality ? "true" : "false"); } + + int setLocalVideoMirrorMode(VIDEO_MIRROR_MODE_TYPE mirrorMode) { + if (!m_parameter) return -ERR_NOT_INITIALIZED; + const char* value; + switch (mirrorMode) { + case VIDEO_MIRROR_MODE_AUTO: + value = "default"; + break; + case VIDEO_MIRROR_MODE_ENABLED: + value = "forceMirror"; + break; + case VIDEO_MIRROR_MODE_DISABLED: + value = "disableMirror"; + break; + default: + return -ERR_INVALID_ARGUMENT; + } + return m_parameter->setString("che.video.localViewMirrorSetting", value); + } + + int setLocalPublishFallbackOption(STREAM_FALLBACK_OPTIONS option) { return m_parameter ? m_parameter->setInt("rtc.local_publish_fallback_option", option) : -ERR_NOT_INITIALIZED; } + + int setRemoteSubscribeFallbackOption(STREAM_FALLBACK_OPTIONS option) { return m_parameter ? m_parameter->setInt("rtc.remote_subscribe_fallback_option", option) : -ERR_NOT_INITIALIZED; } + +#if (defined(__APPLE__) && TARGET_OS_MAC && !TARGET_OS_IPHONE) || defined(_WIN32) + + int enableLoopbackRecording(bool enabled, const char* deviceName = NULL) { + if (!deviceName) { + return setParameters("{\"che.audio.loopback.recording\":%s}", enabled ? "true" : "false"); + } else { + return setParameters("{\"che.audio.loopback.deviceName\":\"%s\",\"che.audio.loopback.recording\":%s}", deviceName, enabled ? "true" : "false"); + } + } +#endif + + int setInEarMonitoringVolume(int volume) { return m_parameter ? m_parameter->setInt("che.audio.headset.monitoring.parameter", volume) : -ERR_NOT_INITIALIZED; } + + protected: + AParameter& parameter() { return m_parameter; } + int setParameters(const char* format, ...) { + char buf[512]; + va_list args; + va_start(args, format); + vsnprintf(buf, sizeof(buf) - 1, format, args); + va_end(args); + return m_parameter ? m_parameter->setParameters(buf) : -ERR_NOT_INITIALIZED; + } + int setObject(const char* key, const char* format, ...) { + char buf[512]; + va_list args; + va_start(args, format); + vsnprintf(buf, sizeof(buf) - 1, format, args); + va_end(args); + return m_parameter ? m_parameter->setObject(key, buf) : -ERR_NOT_INITIALIZED; + } + int stopAllRemoteVideo() { return m_parameter ? m_parameter->setBool("che.video.peer.stop_render", true) : -ERR_NOT_INITIALIZED; } + + private: + AParameter m_parameter; +}; +/** + * The format of the recording file. + * + * @since v3.5.2 + */ +enum MediaRecorderContainerFormat { + /** + * 1: (Default) MP4. + */ + FORMAT_MP4 = 1, + /** + * Reserved parameter. + */ + FORMAT_FLV = 2, +}; +/** + * The recording content. + * + * @since v3.5.2 + */ +enum MediaRecorderStreamType { + /** + * Only audio. + */ + STREAM_TYPE_AUDIO = 0x01, + /** + * Only video. + */ + STREAM_TYPE_VIDEO = 0x02, + /** + * (Default) Audio and video. + */ + STREAM_TYPE_BOTH = STREAM_TYPE_AUDIO | STREAM_TYPE_VIDEO, +}; +/** + * The current recording state. + * + * @since v3.5.2 + */ +enum RecorderState { + /** + * -1: An error occurs during the recording. See RecorderErrorCode for the reason. + */ + RECORDER_STATE_ERROR = -1, + /** + * 2: The audio and video recording is started. + */ + RECORDER_STATE_START = 2, + /** + * 3: The audio and video recording is stopped. + */ + RECORDER_STATE_STOP = 3, +}; +/** + * The reason for the state change + * + * @since v3.5.2 + */ +enum RecorderErrorCode { + /** + * 0: No error occurs. + */ + RECORDER_ERROR_NONE = 0, + /** + * 1: The SDK fails to write the recorded data to a file. + */ + RECORDER_ERROR_WRITE_FAILED = 1, + /** + * 2: The SDK does not detect audio and video streams to be recorded, or audio and video streams are interrupted for more than five seconds during recording. + */ + RECORDER_ERROR_NO_STREAM = 2, + /** + * 3: The recording duration exceeds the upper limit. + */ + RECORDER_ERROR_OVER_MAX_DURATION = 3, + /** + * 4: The recording configuration changes. + */ + RECORDER_ERROR_CONFIG_CHANGED = 4, + /** + * 5: The SDK detects audio and video streams from users using versions of the SDK earlier than v3.0.0 in + * the `COMMUNICATION` channel profile. + */ + RECORDER_ERROR_CUSTOM_STREAM_DETECTED = 5, +}; +/** + * Configurations for the local audio and video recording. + * + * @since v3.5.2 + */ +struct MediaRecorderConfiguration { + /** + * The absolute path (including the filename extensions) of the recording file. + * For example, `C:\Users\\AppData\Local\Agora\\example.mp4` on Windows, + * `/App Sandbox/Library/Caches/example.mp4` on iOS, `/Library/Logs/example.mp4` on macOS, and + * `/storage/emulated/0/Android/data//files/example.mp4` on Android. + * + * @note Ensure that the specified path exists and is writable. + */ + const char* storagePath; + /** + * The format of the recording file. See \ref agora::rtc::MediaRecorderContainerFormat "MediaRecorderContainerFormat". + */ + MediaRecorderContainerFormat containerFormat; + /** + * The recording content. See \ref agora::rtc::MediaRecorderStreamType "MediaRecorderStreamType". + */ + MediaRecorderStreamType streamType; + /** + * The maximum recording duration, in milliseconds. The default value is 120000. + */ + int maxDurationMs; + /** + * The interval (ms) of updating the recording information. The value range is + * [1000,10000]. Based on the set value of `recorderInfoUpdateInterval`, the + * SDK triggers the \ref IMediaRecorderObserver::onRecorderInfoUpdated "onRecorderInfoUpdated" + * callback to report the updated recording information. + */ + int recorderInfoUpdateInterval; + + MediaRecorderConfiguration() : storagePath(nullptr), containerFormat(FORMAT_MP4), streamType(STREAM_TYPE_BOTH), maxDurationMs(120000), recorderInfoUpdateInterval(0) {} + MediaRecorderConfiguration(const char* path, MediaRecorderContainerFormat format, MediaRecorderStreamType type, int duration, int interval) : storagePath(path), containerFormat(format), streamType(type), maxDurationMs(duration), recorderInfoUpdateInterval(interval) {} +}; +/** + * Information for the recording file. + * + * @since v3.5.2 + */ +struct RecorderInfo { + /** + * The absolute path of the recording file. + */ + const char* fileName; + /** + * The recording duration, in milliseconds. + */ + unsigned int durationMs; + /** + * The size in bytes of the recording file. + */ + unsigned int fileSize; + + RecorderInfo() = default; + RecorderInfo(const char* name, unsigned int dur, unsigned int size) : fileName(name), durationMs(dur), fileSize(size) {} +}; + +/** + * The IMediaRecorderObserver class. + * + * @since v3.5.2 + */ +class IMediaRecorderObserver { + public: + /** + * Occurs when the recording state changes. + * + * @since v3.5.2 + * + * When the local audio and video recording state changes, the SDK triggers this callback to report the current + * recording state and the reason for the change. + * + * @param state The current recording state. See \ref agora::rtc::RecorderState "RecorderState". + * @param error The reason for the state change. See \ref agora::rtc::RecorderErrorCode "RecorderErrorCode". + */ + virtual void onRecorderStateChanged(RecorderState state, RecorderErrorCode error) = 0; + /** + * Occurs when the recording information is updated. + * + * @since v3.5.2 + * + * After you successfully register this callback and enable the local audio and video recording, the SDK periodically triggers + * the `onRecorderInfoUpdated` callback based on the set value of `recorderInfoUpdateInterval`. This callback reports the + * filename, duration, and size of the current recording file. + * + * @param info Information for the recording file. See RecorderInfo. + * + */ + virtual void onRecorderInfoUpdated(const RecorderInfo& info){}; +}; +/** + * The IMediaRecorder class, for recording the audio and video on the client. IMediaRecorder can record the + * following content: + * - The audio captured by the local microphone and encoded in AAC format. + * - The video captured by the local camera and encoded by the SDK. + * + * @since v3.5.2 + * + * @note In the `COMMUNICATION` channel profile, this function is unavailable when there are users using versions of + * the SDK earlier than v3.0.0 in the channel. + */ +class IMediaRecorder { + public: + /** + * Gets the IMediaRecorder object. + * + * @since v3.5.2 + * + * @note Call this method after initializing the IRtcEngine object. + * + * @param engine IRtcEngine + * @param callback IMediaRecorderObserver + * + * @return IMediaRecorder + */ + AGORA_CPP_API static IMediaRecorder* getMediaRecorder(IRtcEngine* engine, IMediaRecorderObserver* callback); + /** + * Starts recording the local audio and video. + * + * @since v3.5.2 + * + * After successfully getting the object, you can call this method to enable the recording of the local audio and video. + * + * This method can record the following content: + * - The audio captured by the local microphone and encoded in AAC format. + * - The video captured by the local camera and encoded by the SDK. + * + * The SDK can generate a recording file only when it detects the recordable audio and video streams; when there are + * no audio and video streams to be recorded or the audio and video streams are interrupted for more than five + * seconds, the SDK stops recording and triggers the + * \ref IMediaRecorderObserver::onRecorderStateChanged "onRecorderStateChanged" (RECORDER_STATE_ERROR, RECORDER_ERROR_NO_STREAM) + * callback. + * + * @note Call this method after joining the channel. + * + * @param config The recording configurations. See MediaRecorderConfiguration. + * + * @return + * - 0(ERR_OK): Success. + * - < 0: Failure: + * - `-2(ERR_INVALID_ARGUMENT)`: The parameter is invalid. Ensure the following: + * - The specified path of the recording file exists and is writable. + * - The specified format of the recording file is supported. + * - The maximum recording duration is correctly set. + * - `-4(ERR_NOT_SUPPORTED)`: IRtcEngine does not support the request due to one of the following reasons: + * - The recording is ongoing. + * - The recording stops because an error occurs. + * - `-7(ERR_NOT_INITIALIZED)`: This method is called before the initialization of IRtcEngine. Ensure that you have + * called \ref IMediaRecorder::getMediaRecorder "getMediaRecorder" before calling `startRecording`. + */ + virtual int startRecording(const MediaRecorderConfiguration& config) = 0; + /** + * Stops recording the local audio and video. + * + * @since v3.5.2 + * + * @note Call this method after calling \ref IMediaRecorder::startRecording "startRecording". + * + * @return + * - 0(ERR_OK): Success. + * - < 0: Failure: + * - `-7(ERR_NOT_INITIALIZED)`: This method is called before the initialization of IRtcEngine. Ensure that you have + * called \ref IMediaRecorder::getMediaRecorder "getMediaRecorder" before calling `stopRecording`. + */ + virtual int stopRecording() = 0; + /** + * Releases the IMediaRecorder object. + * + * @since v3.5.2 + * + * This method releases the IRtcEngine object and all other resources used by the IMediaRecorder object. After calling + * this method, if you want to enable the recording again, you must call + * \ref IMediaRecorder::getMediaRecorder "getMediaRecorder" to get the IMediaRecorder object. + */ + virtual void releaseRecorder() = 0; +}; + +} // namespace rtc +} // namespace agora + +#define getAgoraRtcEngineVersion getAgoraSdkVersion + +//////////////////////////////////////////////////////// +/** \addtogroup createAgoraRtcEngine + @{ + */ +//////////////////////////////////////////////////////// + +/** Creates the IRtcEngine object and returns the pointer. + * + * @note The Agora RTC Native SDK supports creating only one `IRtcEngine` object for an app for now. + * + * @return Pointer to the IRtcEngine object. + */ +AGORA_API agora::rtc::IRtcEngine* AGORA_CALL createAgoraRtcEngine(); + +//////////////////////////////////////////////////////// +/** @} */ +//////////////////////////////////////////////////////// + +#define getAgoraRtcEngineErrorDescription getAgoraSdkErrorDescription +#define setAgoraRtcEngineExternalSymbolLoader setAgoraSdkExternalSymbolLoader + +#endif diff --git a/integration_test_app/iris_integration_test/third_party/agora/rtc/include/IAgoraRtcEngine2.h b/integration_test_app/iris_integration_test/third_party/agora/rtc/include/IAgoraRtcEngine2.h new file mode 100755 index 000000000..044417486 --- /dev/null +++ b/integration_test_app/iris_integration_test/third_party/agora/rtc/include/IAgoraRtcEngine2.h @@ -0,0 +1,52 @@ +// +// Agora Media SDK +// +// Created by Sting Feng in 2015-05. +// Copyright (c) 2015 Agora IO. All rights reserved. +// +#pragma once +#include "IAgoraRtcChannel.h" +#include "IAgoraRtcEngine.h" + +namespace agora { +namespace rtc { + +enum AppType { + APP_TYPE_NATIVE = 0, + APP_TYPE_COCOS = 1, + APP_TYPE_UNITY = 2, + APP_TYPE_ELECTRON = 3, + APP_TYPE_FLUTTER = 4, + APP_TYPE_UNREAL = 5, + APP_TYPE_XAMARIN = 6, + APP_TYPE_API_CLOUD = 7, + APP_TYPE_REACT_NATIVE = 8, + APP_TYPE_PYTHON = 9, + APP_TYPE_COCOS_CREATOR = 10, + APP_TYPE_RUST = 11, + APP_TYPE_C_SHARP = 12, + APP_TYPE_CEF = 13, + APP_TYPE_UNI_APP = 14, +}; + +class IRtcEngine3 : public IRtcEngine2 { + public: + /** + * Specify video stream parameters based on video profile + * @param [in] width + * width of video resolution in pixel + * @param [in] height + * height of video resolution in pixel + * @param [in] frameRate + * frame rate in fps + * @param [in] bitrate + * bit rate in kbps + * @return return 0 if success or an error code + */ + virtual int setVideoProfileEx(int width, int height, int frameRate, + int bitrate) = 0; + virtual int setAppType(AppType appType) = 0; +}; + +}// namespace rtc +}// namespace agora diff --git a/integration_test_app/iris_integration_test/third_party/agora/rtc/include/IAgoraService.h b/integration_test_app/iris_integration_test/third_party/agora/rtc/include/IAgoraService.h new file mode 100644 index 000000000..555ed8866 --- /dev/null +++ b/integration_test_app/iris_integration_test/third_party/agora/rtc/include/IAgoraService.h @@ -0,0 +1,73 @@ +// Agora SDK +// +// Copyright (c) 2019 Agora.io. All rights reserved. +// + +#ifndef AGORA_SERVICE_H +#define AGORA_SERVICE_H +#include "AgoraBase.h" + +namespace agora { +namespace rtc { +class IRtcEngine; +} +namespace rtm { +class IRtmService; +} +namespace base { + +struct AgoraServiceContext {}; + +class IAgoraService { + protected: + virtual ~IAgoraService() {} + + public: + AGORA_CPP_API static void release(); + + /** Initializes the engine. + +@param context RtcEngine context. +@return +- 0: Success. +- < 0: Failure. +*/ + virtual int initialize(const AgoraServiceContext& context) = 0; + + /** Gets the SDK version number. + * @param build Build number. + * @return The current SDK version in the string format. For example, 2.4.0 + */ + virtual const char* getVersion(int* build) = 0; + + virtual rtm::IRtmService* createRtmService() = 0; +}; + +} // namespace base +} // namespace agora + +/** Gets the SDK version number. + + @param build Build number of the Agora SDK. + @return + - 0: Success. + - < 0: Failure. +*/ +AGORA_API const char* AGORA_CALL getAgoraSdkVersion(int* build); + +/** + * Creates the RtcEngine object and returns the pointer. + * @param err Error code + * @return returns Description of the error code + */ +AGORA_API const char* AGORA_CALL getAgoraSdkErrorDescription(int err); + +/** + * Creates the Agora Service object and returns the pointer. + * @return returns Pointer of the Agora Service object + */ +AGORA_API agora::base::IAgoraService* AGORA_CALL createAgoraService(); + +AGORA_API int AGORA_CALL setAgoraSdkExternalSymbolLoader(void* (*func)(const char* symname)); + +#endif diff --git a/integration_test_app/iris_integration_test/third_party/googletest b/integration_test_app/iris_integration_test/third_party/googletest new file mode 160000 index 000000000..c9461a9b5 --- /dev/null +++ b/integration_test_app/iris_integration_test/third_party/googletest @@ -0,0 +1 @@ +Subproject commit c9461a9b55ba954df0489bab6420eb297bed846b diff --git a/integration_test_app/iris_integration_test/third_party/iris/iris_audio_processor.h b/integration_test_app/iris_integration_test/third_party/iris/iris_audio_processor.h new file mode 100644 index 000000000..381107a0c --- /dev/null +++ b/integration_test_app/iris_integration_test/third_party/iris/iris_audio_processor.h @@ -0,0 +1,30 @@ +// +// Created by LXH on 2021/7/20. +// + +#ifndef IRIS_AUDIO_PROCESSOR_H_ +#define IRIS_AUDIO_PROCESSOR_H_ + +#include "iris_media_base.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef void *IrisAudioFrameMixingPtr; + +IRIS_API IrisAudioFrameMixingPtr CreateIrisAudioFrameMixing(); + +IRIS_API void FreeIrisAudioFrameMixing(IrisAudioFrameMixingPtr mixing_ptr); + +IRIS_API void PushAudioFrame(IrisAudioFrameMixingPtr mixing_ptr, + IrisAudioFrame *audio_frame); + +IRIS_API void Mixing(IrisAudioFrameMixingPtr mixing_ptr, + IrisAudioFrame *audio_frame); + +#ifdef __cplusplus +} +#endif + +#endif//IRIS_AUDIO_PROCESSOR_H_ diff --git a/integration_test_app/iris_integration_test/third_party/iris/iris_base.h b/integration_test_app/iris_integration_test/third_party/iris/iris_base.h new file mode 100644 index 000000000..55cb3b06d --- /dev/null +++ b/integration_test_app/iris_integration_test/third_party/iris/iris_base.h @@ -0,0 +1,140 @@ +// +// Created by LXH on 2021/5/10. +// + +#ifndef IRIS_BASE_H_ +#define IRIS_BASE_H_ + +#include +#if defined(__APPLE__) +#include +#endif + +#if defined(_WIN32) +#define IRIS_CALL __cdecl +#if defined(IRIS_EXPORT) +#define IRIS_API extern "C" __declspec(dllexport) +#define IRIS_CPP_API __declspec(dllexport) +#else +#define IRIS_API extern "C" __declspec(dllimport) +#define IRIS_CPP_API __declspec(dllimport) +#endif +#elif defined(__APPLE__) +#define IRIS_API __attribute__((visibility("default"))) extern "C" +#define IRIS_CPP_API __attribute__((visibility("default"))) +#define IRIS_CALL +#elif defined(__ANDROID__) || defined(__linux__) +#define IRIS_API extern "C" __attribute__((visibility("default"))) +#define IRIS_CPP_API __attribute__((visibility("default"))) +#define IRIS_CALL +#else +#define IRIS_API extern "C" +#define IRIS_CPP_API +#define IRIS_CALL +#endif + +#ifdef __GNUC__ +#define AGORA_GCC_VERSION_AT_LEAST(x, y) \ + (__GNUC__ > (x) || __GNUC__ == (x) && __GNUC_MINOR__ >= (y)) +#else +#define AGORA_GCC_VERSION_AT_LEAST(x, y) 0 +#endif + +#if AGORA_GCC_VERSION_AT_LEAST(3, 1) +#define IRIS_DEPRECATED __attribute__((deprecated)) +#elif defined(_MSC_VER) +#define IRIS_DEPRECATED +#else +#define IRIS_DEPRECATED +#endif + +#if defined(IRIS_DEBUG) +#define IRIS_DEBUG_API IRIS_API +#define IRIS_DEBUG_CPP_API IRIS_CPP_API +#else +#define IRIS_DEBUG_API +#define IRIS_DEBUG_CPP_API +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +const int kBasicResultLength = 512; +const int kMaxResultLength = 2048; + +enum IrisAppType { + kAppTypeNative = 0, + kAppTypeCocos = 1, + kAppTypeUnity = 2, + kAppTypeElectron = 3, + kAppTypeFlutter = 4, + kAppTypeUnreal = 5, + kAppTypeXamarin = 6, + kAppTypeApiCloud = 7, + kAppTypeReactNative = 8, + kAppTypePython = 9, + kAppTypeCocosCreator = 10, + kAppTypeRust = 11, + kAppTypeCSharp = 12, + kAppTypeCef = 13, + kAppTypeUniApp = 14, +}; + +IRIS_API unsigned int kValueType; + +IRIS_API void InitIrisLogger(const char *tag, const char *path); + +IRIS_API void UseJsonObject(); + +IRIS_API void UseJsonArray(); + +typedef struct IrisRect { + double x; + double y; + double width; + double height; +} IrisRect; + +typedef struct IrisDisplay { + unsigned int id; + float scale; + IrisRect bounds; + IrisRect work_area; + int rotation; +} IrisDisplay; + +typedef struct IrisDisplayCollection { + IrisDisplay *displays; + unsigned int length; +} IrisDisplayCollection; + +typedef struct IrisWindow { + unsigned long id; + char name[kBasicResultLength]; + char owner_name[kBasicResultLength]; + IrisRect bounds; + IrisRect work_area; +} IrisWindow; + +typedef struct IrisWindowCollection { + IrisWindow *windows; + unsigned int length; +} IrisWindowCollection; + +#if (defined(__APPLE__) && TARGET_OS_MAC && !TARGET_OS_IPHONE) \ + || defined(_WIN32) +IRIS_API IrisDisplayCollection *EnumerateDisplays(); + +IRIS_API void FreeIrisDisplayCollection(IrisDisplayCollection *collection); + +IRIS_API IrisWindowCollection *EnumerateWindows(); + +IRIS_API void FreeIrisWindowCollection(IrisWindowCollection *collection); +#endif + +#ifdef __cplusplus +} +#endif + +#endif//IRIS_BASE_H_ diff --git a/integration_test_app/iris_integration_test/third_party/iris/iris_delegate.h b/integration_test_app/iris_integration_test/third_party/iris/iris_delegate.h new file mode 100644 index 000000000..a5dc47019 --- /dev/null +++ b/integration_test_app/iris_integration_test/third_party/iris/iris_delegate.h @@ -0,0 +1,33 @@ +// +// Created by LXH on 2021/4/29. +// + +#ifndef IRIS_DELEGATE_H_ +#define IRIS_DELEGATE_H_ + +#include "iris_event_handler.h" + +namespace agora { +namespace iris { + +template +class IrisDelegate { + public: + virtual ~IrisDelegate() = default; + + public: + virtual void SetEventHandler(IrisEventHandler *event_handler) = 0; + + virtual IrisEventHandler *GetEventHandler() = 0; + + virtual int CallApi(ApiType api_type, const char *params, + char result[kBasicResultLength]) = 0; + + virtual int CallApi(ApiType api_type, const char *params, void *buffer, + unsigned int length, char result[kBasicResultLength]) = 0; +}; + +}// namespace iris +}// namespace agora + +#endif//IRIS_DELEGATE_H_ diff --git a/integration_test_app/iris_integration_test/third_party/iris/iris_event_handler.h b/integration_test_app/iris_integration_test/third_party/iris/iris_event_handler.h new file mode 100644 index 000000000..4da047978 --- /dev/null +++ b/integration_test_app/iris_integration_test/third_party/iris/iris_event_handler.h @@ -0,0 +1,44 @@ +// +// Created by LXH on 2021/1/14. +// + +#ifndef IRIS_EVENT_HANDLER_H_ +#define IRIS_EVENT_HANDLER_H_ + +#include "iris_base.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef void(IRIS_CALL *Func_Event)(const char *event, const char *data); +typedef void(IRIS_CALL *Func_EventWithBuffer)(const char *event, + const char *data, + const void *buffer, + unsigned int length); +typedef struct IrisCEventHandler { + Func_Event OnEvent; + Func_EventWithBuffer OnEventWithBuffer; +} IrisCEventHandler; +typedef void *IrisEventHandlerHandle; + +#ifdef __cplusplus +} +#endif + +namespace agora { +namespace iris { +class IrisEventHandler { + public: + virtual ~IrisEventHandler() = default; + + public: + virtual void OnEvent(const char *event, const char *data) = 0; + + virtual void OnEvent(const char *event, const char *data, const void *buffer, + unsigned int length) = 0; +}; +}// namespace iris +}// namespace agora + +#endif//IRIS_EVENT_HANDLER_H_ diff --git a/integration_test_app/iris_integration_test/third_party/iris/iris_media_base.h b/integration_test_app/iris_integration_test/third_party/iris/iris_media_base.h new file mode 100644 index 000000000..382fe4abd --- /dev/null +++ b/integration_test_app/iris_integration_test/third_party/iris/iris_media_base.h @@ -0,0 +1,198 @@ +// +// Created by LXH on 2021/7/20. +// + +#ifndef IRIS_MEDIA_BASE_H_ +#define IRIS_MEDIA_BASE_H_ + +#include "iris_base.h" +#include + +#ifdef __cplusplus +extern "C" { +#endif + +enum AudioFrameType { + kAudioFrameTypePCM16, +}; + +typedef struct IrisAudioFrame { + AudioFrameType type; + int samples; + int bytes_per_sample; + int channels; + int samples_per_sec; + void *buffer; + unsigned int buffer_length; + int64_t render_time_ms; + int av_sync_type; +} IrisAudioFrame; + +IRIS_API const struct IrisAudioFrame IrisAudioFrame_default; + +IRIS_API void ResizeAudioFrame(IrisAudioFrame *audio_frame); + +IRIS_API void ClearAudioFrame(IrisAudioFrame *audio_frame); + +IRIS_API void CopyAudioFrame(IrisAudioFrame *dst, const IrisAudioFrame *src); + +enum IrisVideoFrameType { + kVideoFrameTypeYUV420, + kVideoFrameTypeYUV422, + kVideoFrameTypeRGBA, + kVideoFrameTypeBGRA, +}; + +enum IrisVideoSourceType { + kVideoSourceTypeCameraPrimary, + kVideoSourceTypeCameraSecondary, + kVideoSourceTypeScreenPrimary, + kVideoSourceTypeScreenSecondary, + kVideoSourceTypeCustom, + kVideoSourceTypeMediaPlayer, + kVideoSourceTypeRtcImagePng, + kVideoSourceTypeRtcImageJpeg, + kVideoSourceTypeRtcImageGif, + kVideoSourceTypeRemote, + kVideoSourceTypeTranscoded, + kVideoSourceTypeUnknown, +}; + +typedef struct IrisVideoFrame { + IrisVideoFrameType type; + int width; + int height; + int y_stride; + int u_stride; + int v_stride; + void *y_buffer; + void *u_buffer; + void *v_buffer; + unsigned int y_buffer_length; + unsigned int u_buffer_length; + unsigned int v_buffer_length; + int rotation; + int64_t render_time_ms; + int av_sync_type; +} IrisVideoFrame; + +IRIS_API const struct IrisVideoFrame IrisVideoFrame_default; + +IRIS_API void ResizeVideoFrame(IrisVideoFrame *video_frame); + +IRIS_API void ClearVideoFrame(IrisVideoFrame *video_frame); + +IRIS_API void CopyVideoFrame(IrisVideoFrame *dst, const IrisVideoFrame *src); + +IRIS_API IrisVideoFrame ConvertVideoFrame(const IrisVideoFrame *src, + IrisVideoFrameType format); + +typedef struct IrisPacket { + const unsigned char *buffer; + unsigned int size; +} IrisPacket; + +#ifdef __cplusplus +} +#endif + +namespace agora { +namespace iris { + +class IrisVideoFrameBufferManager; + +class IrisAudioFrameObserver { + public: + virtual bool OnRecordAudioFrame(IrisAudioFrame &audio_frame) = 0; +}; + +class IrisVideoFrameObserver { + public: + virtual bool OnCaptureVideoFrame(IrisVideoFrame &video_frame) = 0; +}; + +class IrisPacketObserver { + public: + virtual bool OnSendAudioPacket(IrisPacket &packet) = 0; + virtual bool OnSendVideoPacket(IrisPacket &packet) = 0; + virtual bool OnReceiveAudioPacket(IrisPacket &packet) = 0; + virtual bool OnReceiveVideoPacket(IrisPacket &packet) = 0; +}; + +class IRIS_CPP_API IrisAudioFrameObserverManager { + public: + IrisAudioFrameObserverManager(); + ~IrisAudioFrameObserverManager(); + + public: + void RegisterAudioFrameObserver(IrisAudioFrameObserver *observer, int order, + const char *identifier); + + void UnRegisterAudioFrameObserver(const char *identifier = nullptr); + + unsigned int GetAudioFrameObserverCount(); + + IrisAudioFrameObserver *GetAudioFrameObserver(unsigned int index); + + private: + class Impl; + Impl *impl_; +}; + +class IRIS_CPP_API IrisVideoFrameObserverManager { + public: + IrisVideoFrameObserverManager(); + ~IrisVideoFrameObserverManager(); + + public: + void RegisterVideoFrameObserver(IrisVideoFrameObserver *observer, int order, + const char *identifier); + + void UnRegisterVideoFrameObserver(const char *identifier = nullptr); + + unsigned int GetVideoFrameObserverCount(); + + IrisVideoFrameObserver *GetVideoFrameObserver(unsigned int index); + + void Attach(IrisVideoFrameBufferManager *manager); + + IrisVideoFrameBufferManager *buffer_manager(); + + private: + class Impl; + Impl *impl_; +}; + +class IRIS_CPP_API IrisPacketObserverManager { + public: + IrisPacketObserverManager(); + ~IrisPacketObserverManager(); + + public: + void RegisterPacketObserver(IrisPacketObserver *observer, int order, + const char *identifier); + + void UnRegisterPacketObserver(const char *identifier = nullptr); + + unsigned int GetPacketObserverCount(); + + IrisPacketObserver *GetPacketObserver(unsigned int index); + + private: + class Impl; + Impl *impl_; +}; + +class IRIS_CPP_API IrisCommonObserverManager + : public IrisAudioFrameObserverManager, + public IrisVideoFrameObserverManager, + public IrisPacketObserverManager { + public: + IrisCommonObserverManager(); + virtual ~IrisCommonObserverManager(); +}; + +}// namespace iris +}// namespace agora + +#endif//IRIS_MEDIA_BASE_H_ diff --git a/integration_test_app/iris_integration_test/third_party/iris/iris_rtc_base.h b/integration_test_app/iris_integration_test/third_party/iris/iris_rtc_base.h new file mode 100644 index 000000000..d0bb4a5cf --- /dev/null +++ b/integration_test_app/iris_integration_test/third_party/iris/iris_rtc_base.h @@ -0,0 +1,323 @@ +// +// Created by LXH on 2021/1/14. +// + +#ifndef IRIS_RTC_BASE_H_ +#define IRIS_RTC_BASE_H_ + +#include "iris_base.h" +#include "iris_media_base.h" + +#ifdef __cplusplus +extern "C" { +#endif + +enum EngineType { + kEngineTypeNormal, + kEngineTypeSubProcess, +}; + +enum ApiTypeEngine { + kEngineInitialize = 0, + kEngineRelease = 1, + kEngineSetChannelProfile = 2, + kEngineSetClientRole = 3, + kEngineJoinChannel = 4, + kEngineSwitchChannel = 5, + kEngineLeaveChannel = 6, + kEngineRenewToken = 7, + kEngineRegisterLocalUserAccount = 8, + kEngineJoinChannelWithUserAccount = 9, + kEngineGetUserInfoByUserAccount = 10, + kEngineGetUserInfoByUid = 11, + kEngineStartEchoTest = 12, + kEngineStopEchoTest = 13, + kEngineSetCloudProxy = 14, + kEngineEnableVideo = 15, + kEngineDisableVideo = 16, + kEngineSetVideoProfile = 17, + kEngineSetVideoEncoderConfiguration = 18, + kEngineSetCameraCapturerConfiguration = 19, + kEngineSetupLocalVideo = 20, + kEngineSetupRemoteVideo = 21, + kEngineStartPreview = 22, + kEngineSetRemoteUserPriority = 23, + kEngineStopPreview = 24, + kEngineEnableAudio = 25, + kEngineEnableLocalAudio = 26, + kEngineDisableAudio = 27, + kEngineSetAudioProfile = 28, + kEngineMuteLocalAudioStream = 29, + kEngineMuteAllRemoteAudioStreams = 30, + kEngineSetDefaultMuteAllRemoteAudioStreams = 31, + kEngineAdjustUserPlaybackSignalVolume = 32, + kEngineMuteRemoteAudioStream = 33, + kEngineMuteLocalVideoStream = 34, + kEngineEnableLocalVideo = 35, + kEngineMuteAllRemoteVideoStreams = 36, + kEngineSetDefaultMuteAllRemoteVideoStreams = 37, + kEngineMuteRemoteVideoStream = 38, + kEngineSetRemoteVideoStreamType = 39, + kEngineSetRemoteDefaultVideoStreamType = 40, + kEngineEnableAudioVolumeIndication = 41, + kEngineStartAudioRecording = 42, + kEngineStopAudioRecording = 43, + kEngineStartAudioMixing = 44, + kEngineStopAudioMixing = 45, + kEnginePauseAudioMixing = 46, + kEngineResumeAudioMixing = 47, + kEngineSetHighQualityAudioParameters = 48, + kEngineAdjustAudioMixingVolume = 49, + kEngineAdjustAudioMixingPlayoutVolume = 50, + kEngineGetAudioMixingPlayoutVolume = 51, + kEngineAdjustAudioMixingPublishVolume = 52, + kEngineGetAudioMixingPublishVolume = 53, + kEngineGetAudioMixingDuration = 54, + kEngineGetAudioMixingCurrentPosition = 55, + kEngineSetAudioMixingPosition = 56, + kEngineSetAudioMixingPitch = 57, + kEngineGetEffectsVolume = 58, + kEngineSetEffectsVolume = 59, + kEngineSetVolumeOfEffect = 60, + kEngineEnableFaceDetection = 61, + kEnginePlayEffect = 62, + kEngineStopEffect = 63, + kEngineStopAllEffects = 64, + kEnginePreloadEffect = 65, + kEngineUnloadEffect = 66, + kEnginePauseEffect = 67, + kEnginePauseAllEffects = 68, + kEngineResumeEffect = 69, + kEngineResumeAllEffects = 70, + kEngineGetEffectDuration = 71, + kEngineSetEffectPosition = 72, + kEngineGetEffectCurrentPosition = 73, + kEngineEnableDeepLearningDenoise = 74, + kEngineEnableSoundPositionIndication = 75, + kEngineSetRemoteVoicePosition = 76, + kEngineSetLocalVoicePitch = 77, + kEngineSetLocalVoiceEqualization = 78, + kEngineSetLocalVoiceReverb = 79, + kEngineSetLocalVoiceChanger = 80, + kEngineSetLocalVoiceReverbPreset = 81, + kEngineSetVoiceBeautifierPreset = 82, + kEngineSetAudioEffectPreset = 83, + kEngineSetVoiceConversionPreset = 84, + kEngineSetAudioEffectParameters = 85, + kEngineSetVoiceBeautifierParameters = 86, + kEngineSetLogFile = 87, + kEngineSetLogFilter = 88, + kEngineSetLogFileSize = 89, + kEngineUploadLogFile = 90, + kEngineSetLocalRenderMode = 91, + kEngineSetRemoteRenderMode = 92, + kEngineSetLocalVideoMirrorMode = 93, + kEngineEnableDualStreamMode = 94, + kEngineSetExternalAudioSource = 95, + kEngineSetExternalAudioSink = 96, + kEngineSetRecordingAudioFrameParameters = 97, + kEngineSetPlaybackAudioFrameParameters = 98, + kEngineSetMixedAudioFrameParameters = 99, + kEngineAdjustRecordingSignalVolume = 100, + kEngineAdjustPlaybackSignalVolume = 101, + kEngineAdjustLoopBackRecordingSignalVolume = 102, + kEngineEnableWebSdkInteroperability = 103, + kEngineSetVideoQualityParameters = 104, + kEngineSetLocalPublishFallbackOption = 105, + kEngineSetRemoteSubscribeFallbackOption = 106, + kEngineSwitchCamera = 107, + kEngineSetDefaultAudioRouteToSpeakerPhone = 108, + kEngineSetEnableSpeakerPhone = 109, + kEngineEnableInEarMonitoring = 110, + kEngineSetInEarMonitoringVolume = 111, + kEngineIsSpeakerPhoneEnabled = 112, + kEngineSetAudioSessionOperationRestriction = 113, + kEngineEnableLoopBackRecording = 114, + kEngineStartScreenCaptureByDisplayId = 115, + kEngineStartScreenCaptureByScreenRect = 116, + kEngineStartScreenCaptureByWindowId = 117, + kEngineSetScreenCaptureContentHint = 118, + kEngineUpdateScreenCaptureParameters = 119, + kEngineUpdateScreenCaptureRegion = 120, + kEngineStopScreenCapture = 121, + kEngineStartScreenCapture = 122, + kEngineSetVideoSource = 123, + kEngineGetCallId = 124, + kEngineRate = 125, + kEngineComplain = 126, + kEngineGetVersion = 127, + kEngineEnableLastMileTest = 128, + kEngineDisableLastMileTest = 129, + kEngineStartLastMileProbeTest = 130, + kEngineStopLastMileProbeTest = 131, + kEngineGetErrorDescription = 132, + kEngineSetEncryptionSecret = 133, + kEngineSetEncryptionMode = 134, + kEngineEnableEncryption = 135, + kEngineRegisterPacketObserver = 136, + kEngineCreateDataStream = 137, + kEngineSendStreamMessage = 138, + kEngineAddPublishStreamUrl = 139, + kEngineRemovePublishStreamUrl = 140, + kEngineSetLiveTranscoding = 141, + kEngineAddVideoWaterMark = 142, + kEngineClearVideoWaterMarks = 143, + kEngineSetBeautyEffectOptions = 144, + kEngineEnableVirtualBackground = 145, + kEngineAddInjectStreamUrl = 146, + kEngineStartChannelMediaRelay = 147, + kEngineUpdateChannelMediaRelay = 148, + kEnginePauseAllChannelMediaRelay = 149, + kEngineResumeAllChannelMediaRelay = 150, + kEngineStopChannelMediaRelay = 151, + kEngineRemoveInjectStreamUrl = 152, + kEngineSendCustomReportMessage = 153, + kEngineGetConnectionState = 154, + kEngineEnableRemoteSuperResolution = 155, + kEngineRegisterMediaMetadataObserver = 156, + kEngineSetParameters = 157, + kEngineSetLocalAccessPoint = 158, + kEngineUnRegisterMediaMetadataObserver = 159, + kEngineSetMaxMetadataSize = 160, + kEngineSendMetadata = 161, + kEngineSetAppType = 162, + kMediaPushAudioFrame = 163, + kMediaPullAudioFrame = 164, + kMediaSetExternalVideoSource = 165, + kMediaPushVideoFrame = 166, + kEngineSetAudioMixingPlaybackSpeed = 167, + kEngineSelectAudioTrack = 168, + kEngineGetAudioTrackCount = 169, + kEngineSetAudioMixingDualMonoMode = 170, + kEngineGetAudioFileInfo = 171, + kEngineSetVideoProfileEx = 172, + kMediaSetExternalAudioSourceVolume = 173, + kEngineSetLogWriter = 174, + kEngineReleaseLogWriter = 175, + kEngineSetLocalVideoRenderer = 176, + kEngineSetRemoteVideoRenderer = 177, + kEngineSetCameraTorchOn = 178, + kEngineIsCameraTorchSupported = 179, + kEngineGetCameraMaxZoomFactor = 180, + kEngineIsCameraAutoFocusFaceModeSupported = 181, + kEngineIsCameraExposurePositionSupported = 182, + kEngineIsCameraFocusSupported = 183, + kEngineIsCameraZoomSupported = 184, + kEngineSetCameraAutoFocusFaceModeEnabled = 185, + kEngineSetCameraExposurePosition = 186, + kEngineSetCameraFocusPositionInPreview = 187, + kEngineSetCameraZoomFactor = 188, + kEngineStartRhythmPlayer = 189, + kEngineStopRhythmPlayer = 190, + kEngineConfigRhythmPlayer = 191, + kEngineGetNativeHandle = 192, + kEngineGetScreenCaptureSources = 193, + kEngineTakeSnapshot = 194, + kEngineEnableContentInspect = 195, +}; + +enum ApiTypeChannel { + kChannelCreateChannel = 0, + kChannelRelease = 1, + kChannelJoinChannel = 2, + kChannelJoinChannelWithUserAccount = 3, + kChannelLeaveChannel = 4, + kChannelPublish = 5, + kChannelUnPublish = 6, + kChannelChannelId = 7, + kChannelGetCallId = 8, + kChannelRenewToken = 9, + kChannelSetEncryptionSecret = 10, + kChannelSetEncryptionMode = 11, + kChannelEnableEncryption = 12, + kChannelRegisterPacketObserver = 13, + kChannelRegisterMediaMetadataObserver = 14, + kChannelUnRegisterMediaMetadataObserver = 15, + kChannelSetMaxMetadataSize = 16, + kChannelSendMetadata = 17, + kChannelSetClientRole = 18, + kChannelSetRemoteUserPriority = 19, + kChannelSetRemoteVoicePosition = 20, + kChannelSetRemoteRenderMode = 21, + kChannelSetDefaultMuteAllRemoteAudioStreams = 22, + kChannelSetDefaultMuteAllRemoteVideoStreams = 23, + kChannelMuteLocalAudioStream = 24, + kChannelMuteLocalVideoStream = 25, + kChannelMuteAllRemoteAudioStreams = 26, + kChannelAdjustUserPlaybackSignalVolume = 27, + kChannelMuteRemoteAudioStream = 28, + kChannelMuteAllRemoteVideoStreams = 29, + kChannelMuteRemoteVideoStream = 30, + kChannelSetRemoteVideoStreamType = 31, + kChannelSetRemoteDefaultVideoStreamType = 32, + kChannelCreateDataStream = 33, + kChannelSendStreamMessage = 34, + kChannelAddPublishStreamUrl = 35, + kChannelRemovePublishStreamUrl = 36, + kChannelSetLiveTranscoding = 37, + kChannelAddInjectStreamUrl = 38, + kChannelRemoveInjectStreamUrl = 39, + kChannelStartChannelMediaRelay = 40, + kChannelUpdateChannelMediaRelay = 41, + kChannelPauseAllChannelMediaRelay = 42, + kChannelResumeAllChannelMediaRelay = 43, + kChannelStopChannelMediaRelay = 44, + kChannelGetConnectionState = 45, + kChannelEnableRemoteSuperResolution = 46, +}; + +enum ApiTypeAudioDeviceManager { + kADMEnumeratePlaybackDevices = 0, + kADMSetPlaybackDevice = 1, + kADMGetPlaybackDevice = 2, + kADMGetPlaybackDeviceInfo = 3, + kADMSetPlaybackDeviceVolume = 4, + kADMGetPlaybackDeviceVolume = 5, + kADMSetPlaybackDeviceMute = 6, + kADMGetPlaybackDeviceMute = 7, + kADMStartPlaybackDeviceTest = 8, + kADMStopPlaybackDeviceTest = 9, + kADMEnumerateRecordingDevices = 10, + kADMSetRecordingDevice = 11, + kADMGetRecordingDevice = 12, + kADMGetRecordingDeviceInfo = 13, + kADMSetRecordingDeviceVolume = 14, + kADMGetRecordingDeviceVolume = 15, + kADMSetRecordingDeviceMute = 16, + kADMGetRecordingDeviceMute = 17, + kADMStartRecordingDeviceTest = 18, + kADMStopRecordingDeviceTest = 19, + kADMStartAudioDeviceLoopbackTest = 20, + kADMStopAudioDeviceLoopbackTest = 21, +}; + +enum ApiTypeVideoDeviceManager { + kVDMEnumerateVideoDevices = 0, + kVDMSetDevice = 1, + kVDMGetDevice = 2, + kVDMStartDeviceTest = 3, + kVDMStopDeviceTest = 4, +}; + +enum ApiTypeRawDataPluginManager { + kRDPMRegisterPlugin = 0, + kRDPMUnregisterPlugin = 1, + kRDPMHasPlugin = 2, + kRDPMEnablePlugin = 3, + kRDPMGetPlugins = 4, + kRDPMSetPluginParameter = 5, + kRDPMGetPluginParameter = 6, + kRDPMRelease = 7, +}; + +enum VideoObserverPosition { + kPositionPostCapturer = 1 << 0, + kPositionPreRenderer = 1 << 1, + kPositionPreEncoder = 1 << 2, +}; + +#ifdef __cplusplus +} +#endif + +#endif//IRIS_RTC_BASE_H_ diff --git a/integration_test_app/iris_integration_test/third_party/iris/iris_rtc_c_api.h b/integration_test_app/iris_integration_test/third_party/iris/iris_rtc_c_api.h new file mode 100644 index 000000000..5eedcd773 --- /dev/null +++ b/integration_test_app/iris_integration_test/third_party/iris/iris_rtc_c_api.h @@ -0,0 +1,161 @@ +// +// Created by LXH on 2021/1/14. +// + +#ifndef IRIS_RTC_C_API_H_ +#define IRIS_RTC_C_API_H_ + +#include "iris_rtc_base.h" +#include "iris_video_processor.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef bool(IRIS_CALL *Func_Bool)(); +typedef uint32_t(IRIS_CALL *Func_Uint32_t)(); + +typedef bool(IRIS_CALL *Func_AudioFrameLocal)(IrisAudioFrame *audio_frame); +typedef bool(IRIS_CALL *Func_AudioFrameRemote)(unsigned int uid, + IrisAudioFrame *audio_frame); +typedef bool(IRIS_CALL *Func_AudioFrameEx)(const char *channel_id, + unsigned int uid, + IrisAudioFrame *audio_frame); +typedef struct IrisRtcCAudioFrameObserver { + Func_AudioFrameLocal OnRecordAudioFrame; + Func_AudioFrameLocal OnPlaybackAudioFrame; + Func_AudioFrameLocal OnMixedAudioFrame; + Func_AudioFrameRemote OnPlaybackAudioFrameBeforeMixing; + Func_Bool IsMultipleChannelFrameWanted; + Func_AudioFrameEx OnPlaybackAudioFrameBeforeMixingEx; +} IrisRtcCAudioFrameObserver; +typedef void *IrisRtcAudioFrameObserverHandle; + +typedef bool(IRIS_CALL *Func_VideoFrameLocal)(IrisVideoFrame *video_frame); +typedef bool(IRIS_CALL *Func_VideoFrameRemote)(unsigned int uid, + IrisVideoFrame *video_frame); +typedef bool(IRIS_CALL *Func_VideoFrameEx)(const char *channel_id, + unsigned int uid, + IrisVideoFrame *video_frame); +typedef struct IrisRtcCVideoFrameObserver { + Func_VideoFrameLocal OnCaptureVideoFrame; + Func_VideoFrameLocal OnPreEncodeVideoFrame; + Func_VideoFrameRemote OnRenderVideoFrame; + Func_Uint32_t GetObservedFramePosition; + Func_Bool IsMultipleChannelFrameWanted; + Func_VideoFrameEx OnRenderVideoFrameEx; +} IrisRtcCVideoFrameObserver; +typedef void *IrisRtcVideoFrameObserverHandle; + +typedef void *IrisRtcEnginePtr; +typedef void *IrisRtcDeviceManagerPtr; +typedef void *IrisRtcChannelPtr; +typedef void *IrisRtcRawDataPtr; +typedef void *IrisRtcRawDataPluginManagerPtr; + +/// IrisRtcEngine +IRIS_API IrisRtcEnginePtr CreateIrisRtcEngine( + EngineType type = kEngineTypeNormal, const char *executable_path = nullptr); + +IRIS_API void DestroyIrisRtcEngine(IrisRtcEnginePtr engine_ptr); + +IRIS_API IrisEventHandlerHandle SetIrisRtcEngineEventHandler( + IrisRtcEnginePtr engine_ptr, IrisCEventHandler *event_handler); + +IRIS_API void UnsetIrisRtcEngineEventHandler(IrisRtcEnginePtr engine_ptr, + IrisEventHandlerHandle handle); + +IRIS_API int CallIrisRtcEngineApi(IrisRtcEnginePtr engine_ptr, + enum ApiTypeEngine api_type, + const char *params, + char result[kBasicResultLength]); + +IRIS_API int CallIrisRtcEngineApiWithBuffer(IrisRtcEnginePtr engine_ptr, + enum ApiTypeEngine api_type, + const char *params, void *buffer, + char result[kBasicResultLength]); + +IRIS_API IrisRtcDeviceManagerPtr +GetIrisRtcDeviceManager(IrisRtcEnginePtr engine_ptr); + +IRIS_API IrisRtcChannelPtr GetIrisRtcChannel(IrisRtcEnginePtr engine_ptr); + +IRIS_API IrisRtcRawDataPtr GetIrisRtcRawData(IrisRtcEnginePtr engine_ptr); + +/// IrisRtcDeviceManager +IRIS_API int +CallIrisRtcAudioDeviceManagerApi(IrisRtcDeviceManagerPtr device_manager_ptr, + enum ApiTypeAudioDeviceManager api_type, + const char *params, + char result[kMaxResultLength]); + +IRIS_API int +CallIrisRtcVideoDeviceManagerApi(IrisRtcDeviceManagerPtr device_manager_ptr, + enum ApiTypeVideoDeviceManager api_type, + const char *params, + char result[kMaxResultLength]); + +/// IrisRtcChannel +IRIS_API IrisEventHandlerHandle SetIrisRtcChannelEventHandler( + IrisRtcChannelPtr channel_ptr, IrisCEventHandler *event_handler); + +IRIS_API void UnsetIrisRtcChannelEventHandler(IrisRtcChannelPtr channel_ptr, + IrisEventHandlerHandle *handle); + +IRIS_API IrisEventHandlerHandle RegisterIrisRtcChannelEventHandler( + IrisRtcChannelPtr channel_ptr, const char *channel_id, + IrisCEventHandler *event_handler); + +IRIS_API void +UnRegisterIrisRtcChannelEventHandler(IrisRtcChannelPtr channel_ptr, + IrisEventHandlerHandle handle, + const char *channel_id); + +IRIS_API int CallIrisRtcChannelApi(IrisRtcChannelPtr channel_ptr, + enum ApiTypeChannel api_type, + const char *params, char *result); + +IRIS_API int CallIrisRtcChannelApiWithBuffer(IrisRtcChannelPtr channel_ptr, + enum ApiTypeChannel api_type, + const char *params, void *buffer, + char *result); + +/// IrisRtcRawData +IRIS_API IrisRtcAudioFrameObserverHandle RegisterAudioFrameObserver( + IrisRtcRawDataPtr raw_data_ptr, IrisRtcCAudioFrameObserver *observer, + int order, const char *identifier); + +IRIS_API void +UnRegisterAudioFrameObserver(IrisRtcRawDataPtr raw_data_ptr, + IrisRtcAudioFrameObserverHandle handle, + const char *identifier); + +IRIS_API IrisRtcVideoFrameObserverHandle RegisterVideoFrameObserver( + IrisRtcRawDataPtr raw_data_ptr, IrisRtcCVideoFrameObserver *observer, + int order, const char *identifier); + +IRIS_API void +UnRegisterVideoFrameObserver(IrisRtcRawDataPtr raw_data_ptr, + IrisRtcVideoFrameObserverHandle handle, + const char *identifier); + +IRIS_API void Attach(IrisRtcRawDataPtr raw_data_ptr, + IrisVideoFrameBufferManagerPtr manager_ptr); + +IRIS_API void Detach(IrisRtcRawDataPtr raw_data_ptr, + IrisVideoFrameBufferManagerPtr manager_ptr); + +IRIS_API IrisRtcRawDataPluginManagerPtr +GetIrisRtcRawDataPluginManager(IrisRtcRawDataPtr raw_data_ptr); + +/// IrisRtcRawDataPluginManager +IRIS_API int CallIrisRtcRawDataPluginManagerApi( + IrisRtcRawDataPluginManagerPtr plugin_manager_ptr, + enum ApiTypeRawDataPluginManager api_type, const char *params, + char result[kBasicResultLength]); + +#ifdef __cplusplus +} +#endif + +#endif//IRIS_RTC_C_API_H_ diff --git a/integration_test_app/iris_integration_test/third_party/iris/iris_rtc_channel.h b/integration_test_app/iris_integration_test/third_party/iris/iris_rtc_channel.h new file mode 100644 index 000000000..38299070c --- /dev/null +++ b/integration_test_app/iris_integration_test/third_party/iris/iris_rtc_channel.h @@ -0,0 +1,76 @@ +// +// Created by LXH on 2021/1/19. +// + +#ifndef IRIS_RTC_CHANNEL_H_ +#define IRIS_RTC_CHANNEL_H_ + +#include "iris_delegate.h" +#include "iris_event_handler.h" +#include "iris_rtc_base.h" + +namespace agora { +namespace rtc { + +class IRtcEngine; + +} + +namespace iris { +namespace rtc { + +class IRIS_CPP_API IIrisRtcChannel : public IrisDelegate { + public: + using IrisDelegate::CallApi; + + virtual void Initialize(agora::rtc::IRtcEngine *engine) = 0; + + virtual void Release() = 0; + + virtual void RegisterEventHandler(const char *channel_id, + IrisEventHandler *event_handler) = 0; + + virtual void UnRegisterEventHandler(const char *channel_id) = 0; + + virtual int CallApi(ApiTypeChannel api_type, const char *params, void *buffer, + char result[kBasicResultLength]) = 0; +}; + +class IRIS_CPP_API IrisRtcChannel : public IIrisRtcChannel { + public: + explicit IrisRtcChannel(IIrisRtcChannel *delegate = nullptr); + ~IrisRtcChannel() override; + + void SetDelegate(IIrisRtcChannel *delegate); + + void Initialize(agora::rtc::IRtcEngine *engine) override; + + void Release() override; + + void SetEventHandler(IrisEventHandler *event_handler) override; + + IrisEventHandler *GetEventHandler() override; + + void RegisterEventHandler(const char *channel_id, + IrisEventHandler *event_handler) override; + + void UnRegisterEventHandler(const char *channel_id) override; + + int CallApi(ApiTypeChannel api_type, const char *params, + char result[kBasicResultLength]) override; + + int CallApi(ApiTypeChannel api_type, const char *params, void *buffer, + char result[kBasicResultLength]) override IRIS_DEPRECATED; + + int CallApi(ApiTypeChannel api_type, const char *params, void *buffer, + unsigned int length, char *result) override; + + private: + IIrisRtcChannel *delegate_; +}; + +}// namespace rtc +}// namespace iris +}// namespace agora + +#endif//IRIS_RTC_CHANNEL_H_ diff --git a/integration_test_app/iris_integration_test/third_party/iris/iris_rtc_device_manager.h b/integration_test_app/iris_integration_test/third_party/iris/iris_rtc_device_manager.h new file mode 100644 index 000000000..ce321f334 --- /dev/null +++ b/integration_test_app/iris_integration_test/third_party/iris/iris_rtc_device_manager.h @@ -0,0 +1,78 @@ +// +// Created by LXH on 2021/1/21. +// + +#ifndef IRIS_RTC_DEVICE_MANAGER_H_ +#define IRIS_RTC_DEVICE_MANAGER_H_ + +#include "iris_delegate.h" +#include "iris_rtc_base.h" + +namespace agora { +namespace rtc { + +class IRtcEngine; + +} + +namespace iris { +namespace rtc { + +class IRIS_CPP_API IIrisRtcAudioDeviceManager + : public IrisDelegate { + public: + using IrisDelegate::CallApi; + + void SetEventHandler(IrisEventHandler *event_handler) override; + + IrisEventHandler *GetEventHandler() override; + + int CallApi(ApiTypeAudioDeviceManager api_type, const char *params, + void *buffer, unsigned int length, char *result) override; +}; + +class IRIS_CPP_API IIrisRtcVideoDeviceManager + : public IrisDelegate { + public: + using IrisDelegate::CallApi; + + void SetEventHandler(IrisEventHandler *event_handler) override; + + IrisEventHandler *GetEventHandler() override; + + int CallApi(ApiTypeVideoDeviceManager api_type, const char *params, + void *buffer, unsigned int length, char *result) override; +}; + +class IRIS_CPP_API IIrisRtcDeviceManager : public IIrisRtcAudioDeviceManager, + public IIrisRtcVideoDeviceManager { + public: + virtual void Initialize(agora::rtc::IRtcEngine *rtc_engine) = 0; + + virtual void Release() = 0; +}; + +class IRIS_CPP_API IrisRtcDeviceManager : public IIrisRtcDeviceManager { + public: + explicit IrisRtcDeviceManager(IIrisRtcDeviceManager *delegate = nullptr); + ~IrisRtcDeviceManager() override; + + void Initialize(agora::rtc::IRtcEngine *rtc_engine) override; + + void Release() override; + + int CallApi(ApiTypeAudioDeviceManager api_type, const char *params, + char result[kMaxResultLength]) override; + + int CallApi(ApiTypeVideoDeviceManager api_type, const char *params, + char result[kMaxResultLength]) override; + + private: + IIrisRtcDeviceManager *delegate_; +}; + +}// namespace rtc +}// namespace iris +}// namespace agora + +#endif//IRIS_RTC_DEVICE_MANAGER_H_ diff --git a/integration_test_app/iris_integration_test/third_party/iris/iris_rtc_engine.h b/integration_test_app/iris_integration_test/third_party/iris/iris_rtc_engine.h new file mode 100644 index 000000000..8b75c2f30 --- /dev/null +++ b/integration_test_app/iris_integration_test/third_party/iris/iris_rtc_engine.h @@ -0,0 +1,78 @@ +// +// Created by LXH on 2021/1/14. +// + +#ifndef IRIS_RTC_ENGINE_H_ +#define IRIS_RTC_ENGINE_H_ + +#include "iris_rtc_channel.h" +#include "iris_rtc_device_manager.h" +#include "iris_rtc_raw_data.h" + +namespace agora { +namespace iris { +namespace rtc { + +class IRIS_CPP_API IIrisRtcEngine : public IrisDelegate { + public: + using IrisDelegate::CallApi; + + virtual void Initialize(agora::rtc::IRtcEngine *rtc_engine) = 0; + + virtual int CallApi(ApiTypeEngine api_type, const char *params, void *buffer, + char result[kBasicResultLength]) = 0; + + virtual IIrisRtcDeviceManager *device_manager() = 0; + + virtual IIrisRtcChannel *channel() = 0; + + virtual IrisRtcRawData *raw_data() = 0; + + virtual const char *log_path() { return ""; } + + virtual void *rtc_engine() { return nullptr; } +}; + +class IRIS_CPP_API IrisRtcEngine : public IIrisRtcEngine { + public: + explicit IrisRtcEngine(IIrisRtcEngine *delegate = nullptr, + EngineType type = kEngineTypeNormal, + const char *executable_path = nullptr); + ~IrisRtcEngine() override; + + void Initialize(agora::rtc::IRtcEngine *rtc_engine) override; + + void SetDelegate(IIrisRtcEngine *delegate); + + IIrisRtcEngine *GetDelegate(); + + void SetEventHandler(IrisEventHandler *event_handler) override; + + IrisEventHandler *GetEventHandler() override; + + int CallApi(ApiTypeEngine api_type, const char *params, + char result[kBasicResultLength]) override; + + int CallApi(ApiTypeEngine api_type, const char *params, void *buffer, + char result[kBasicResultLength]) override IRIS_DEPRECATED; + + int CallApi(ApiTypeEngine api_type, const char *params, void *buffer, + unsigned int length, char result[kBasicResultLength]) override; + + IIrisRtcDeviceManager *device_manager() override; + + IIrisRtcChannel *channel() override; + + IrisRtcRawData *raw_data() override; + + void *rtc_engine() override; + + private: + IIrisRtcEngine *delegate_; +}; + +}// namespace rtc +}// namespace iris +}// namespace agora + +#endif//IRIS_RTC_ENGINE_H_ diff --git a/integration_test_app/iris_integration_test/third_party/iris/iris_rtc_raw_data.h b/integration_test_app/iris_integration_test/third_party/iris/iris_rtc_raw_data.h new file mode 100644 index 000000000..cdbf0d0da --- /dev/null +++ b/integration_test_app/iris_integration_test/third_party/iris/iris_rtc_raw_data.h @@ -0,0 +1,98 @@ +// +// Created by LXH on 2021/3/1. +// + +#ifndef IRIS_RTC_RAW_DATA_H_ +#define IRIS_RTC_RAW_DATA_H_ + +#include "iris_event_handler.h" +#include "iris_rtc_base.h" +#include "iris_rtc_raw_data_plugin_manager.h" +#include + +namespace agora { +namespace rtc { + +class IRtcEngine; + +} + +namespace iris { +namespace rtc { + +class IrisRtcAudioFrameObserver : public IrisAudioFrameObserver { + public: + bool OnRecordAudioFrame(IrisAudioFrame &audio_frame) override = 0; + + virtual bool OnPlaybackAudioFrame(IrisAudioFrame &audio_frame) = 0; + + virtual bool OnMixedAudioFrame(IrisAudioFrame &audio_frame) = 0; + + virtual bool + OnPlaybackAudioFrameBeforeMixing(unsigned int uid, + IrisAudioFrame &audio_frame) = 0; + + virtual bool IsMultipleChannelFrameWanted() { return false; } + + virtual bool OnPlaybackAudioFrameBeforeMixingEx(const char *channel_id, + unsigned int uid, + IrisAudioFrame &audio_frame) { + return false; + }; +}; + +class IrisRtcVideoFrameObserver : public IrisVideoFrameObserver { + public: + bool OnCaptureVideoFrame(IrisVideoFrame &video_frame) override = 0; + + virtual bool OnPreEncodeVideoFrame(IrisVideoFrame &video_frame) { + return true; + } + + virtual bool OnRenderVideoFrame(unsigned int uid, + IrisVideoFrame &video_frame) = 0; + + virtual uint32_t GetObservedFramePosition() { + return static_cast(kPositionPostCapturer | kPositionPreRenderer); + } + + virtual bool IsMultipleChannelFrameWanted() { return false; } + + virtual bool OnRenderVideoFrameEx(const char *channel_id, unsigned int uid, + IrisVideoFrame &video_frame) { + return false; + }; +}; + +class IrisRtcPacketObserver : public IrisPacketObserver {}; + +class IIrisRtcRawData { + public: + virtual void Initialize(agora::rtc::IRtcEngine *rtc_engine) = 0; + + virtual void Release() = 0; + + virtual IIrisRtcRawDataPluginManager *plugin_manager() = 0; +}; + +class IRIS_CPP_API IrisRtcRawData : public IIrisRtcRawData, + public IrisCommonObserverManager { + public: + explicit IrisRtcRawData(IIrisRtcRawData *delegate = nullptr); + ~IrisRtcRawData() override; + + void Initialize(agora::rtc::IRtcEngine *rtc_engine) override; + + void Release() override; + + IIrisRtcRawDataPluginManager *plugin_manager() override; + + private: + IIrisRtcRawData *delegate_; +}; + +}// namespace rtc +}// namespace iris +}// namespace agora + +#endif//IRIS_RTC_RAW_DATA_H_ diff --git a/integration_test_app/iris_integration_test/third_party/iris/iris_rtc_raw_data_plugin.h b/integration_test_app/iris_integration_test/third_party/iris/iris_rtc_raw_data_plugin.h new file mode 100644 index 000000000..c3cba421e --- /dev/null +++ b/integration_test_app/iris_integration_test/third_party/iris/iris_rtc_raw_data_plugin.h @@ -0,0 +1,90 @@ +#pragma once + +#include +#if defined(_WIN32) +#define EXPORTS __declspec(dllexport) +#else +#define EXPORTS +#endif + +struct AudioPluginFrame { + int type; + /** Number of samples in the audio frame: samples = (int)samplesPerCall = (int)(sampleRate × sampleInterval) */ + int samples;// number of samples in this frame + /** Number of bytes per audio sample. For example, each PCM audio sample usually takes up 16 bits (2 bytes). */ + int bytesPerSample;// number of bytes per sample: 2 for PCM16 + /** Number of audio channels. + * - 1: Mono + * - 2: Stereo (the data is interleaved) + */ + int channels;// number of channels (data are interleaved if stereo) + /** Audio frame sample rate: 8000, 16000, 32000, 44100, or 48000 Hz. */ + int samplesPerSec;// sampling rate + /** Audio frame data buffer. The valid data length is: samples × channels × bytesPerSample */ + void *buffer;// data buffer + /** Timestamp to render the audio stream.*/ + long long renderTimeMs; + int avsync_type; +}; + +struct VideoPluginFrame { + int type; + int width; // width of video frame + int height; // height of video frame + int yStride; // stride of Y data buffer + int uStride; // stride of U data buffer + int vStride; // stride of V data buffer + void *yBuffer;// Y data buffer + void *uBuffer;// U data buffer + void *vBuffer;// V data buffer + void *buffer; + int rotation;// rotation of this frame (0, 90, 180, 270) + int64_t renderTimeMs; + int avsync_type; +}; + +struct PluginPacket { + /** + * Buffer address of the sent or received data. + * + * @note Agora recommends that the value of buffer is more than 2048 bytes, + * otherwise, you may meet undefined behaviors such as a crash. + */ + const unsigned char *buffer; + /** + * Buffer size of the sent or received data. + */ + unsigned int size; +}; + +class IAVFramePluginCallback { + public: + virtual bool onPluginCaptureVideoFrame(VideoPluginFrame *videoFrame) = 0; + virtual bool onPluginRenderVideoFrame(unsigned int uid, + VideoPluginFrame *videoFrame) = 0; + + virtual bool onPluginRecordAudioFrame(AudioPluginFrame *audioFrame) = 0; + virtual bool onPluginPlaybackAudioFrame(AudioPluginFrame *audioFrame) = 0; + virtual bool onPluginMixedAudioFrame(AudioPluginFrame *audioFrame) = 0; + virtual bool + onPluginPlaybackAudioFrameBeforeMixing(unsigned int uid, + AudioPluginFrame *audioFrame) = 0; + virtual bool onPluginSendAudioPacket(PluginPacket *packet) = 0; + virtual bool onPluginSendVideoPacket(PluginPacket *packet) = 0; + virtual bool onPluginReceiveAudioPacket(PluginPacket *packet) = 0; + virtual bool onPluginReceiveVideoPacket(PluginPacket *packet) = 0; +}; +class IAVFramePlugin : public IAVFramePluginCallback { + public: + virtual int load(const char *path) = 0; + virtual int unLoad() = 0; + virtual int enable() = 0; + virtual int disable() = 0; + virtual int setParameter(const char *param) = 0; + virtual const char *getParameter(const char *key) = 0; + virtual int release() = 0; +}; + +typedef IAVFramePlugin *(*createAgoraAVFramePlugin)(); + +extern "C" EXPORTS IAVFramePlugin *createAVFramePlugin(); diff --git a/integration_test_app/iris_integration_test/third_party/iris/iris_rtc_raw_data_plugin_manager.h b/integration_test_app/iris_integration_test/third_party/iris/iris_rtc_raw_data_plugin_manager.h new file mode 100644 index 000000000..52d1512c9 --- /dev/null +++ b/integration_test_app/iris_integration_test/third_party/iris/iris_rtc_raw_data_plugin_manager.h @@ -0,0 +1,52 @@ +// +// Created by LXH on 2021/4/21. +// + +#ifndef IRIS_RTC_RAW_DATA_PLUGIN_MANAGER_H_ +#define IRIS_RTC_RAW_DATA_PLUGIN_MANAGER_H_ + +#include "iris_delegate.h" +#include "iris_rtc_base.h" + +namespace agora { +namespace iris { +namespace rtc { + +class IrisRtcRawData; + +class IRIS_CPP_API IIrisRtcRawDataPluginManager + : public IrisDelegate { + public: + using IrisDelegate::CallApi; + + virtual void Initialize(IrisCommonObserverManager *manager) = 0; + + void SetEventHandler(IrisEventHandler *event_handler) override; + + IrisEventHandler *GetEventHandler() override; + + int CallApi(ApiTypeRawDataPluginManager api_type, const char *params, + void *buffer, unsigned int length, char *result) override; +}; + +class IRIS_CPP_API IrisRtcRawDataPluginManager + : public IIrisRtcRawDataPluginManager { + public: + explicit IrisRtcRawDataPluginManager( + IIrisRtcRawDataPluginManager *delegate = nullptr); + ~IrisRtcRawDataPluginManager() override; + + int CallApi(ApiTypeRawDataPluginManager api_type, const char *params, + char result[kMaxResultLength]) override; + + void Initialize(IrisCommonObserverManager *manager) override; + + private: + IIrisRtcRawDataPluginManager *delegate_; +}; + +}// namespace rtc +}// namespace iris +}// namespace agora + +#endif//IRIS_RTC_RAW_DATA_PLUGIN_MANAGER_H_ diff --git a/integration_test_app/iris_integration_test/third_party/iris/iris_video_processor.h b/integration_test_app/iris_integration_test/third_party/iris/iris_video_processor.h new file mode 100644 index 000000000..868ef0a25 --- /dev/null +++ b/integration_test_app/iris_integration_test/third_party/iris/iris_video_processor.h @@ -0,0 +1,171 @@ +// +// Created by LXH on 2021/3/4. +// + +#ifndef IRIS_VIDEO_PROCESSOR_H_ +#define IRIS_VIDEO_PROCESSOR_H_ + +#include "iris_event_handler.h" +#include "iris_media_base.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct IrisVideoFrameBufferConfig { + IrisVideoSourceType type; + unsigned int id; + char key[kBasicResultLength]; +} IrisVideoFrameBufferConfig; + +#ifdef __cplusplus +} +#endif + +namespace agora { +namespace iris { + +class IrisVideoFrameBufferDelegate { + public: + virtual void OnVideoFrameReceived(const IrisVideoFrame &video_frame, + const IrisVideoFrameBufferConfig *config, + bool resize) = 0; +}; + +class IRIS_CPP_API IrisVideoFrameBuffer : public IrisVideoFrame { + public: + explicit IrisVideoFrameBuffer( + IrisVideoFrameType type, IrisVideoFrameBufferDelegate *delegate = nullptr, + int resize_width = 0, int resize_height = 0); + + public: + IrisVideoFrameBufferDelegate *delegate; + int resize_width; + int resize_height; +}; + +class IRIS_CPP_API IrisVideoFrameBufferManager { + public: + IrisVideoFrameBufferManager(); + virtual ~IrisVideoFrameBufferManager(); + + void SetEventHandler(IrisEventHandler *event_handler); + + /** + * Enable buffer the video frame from user. + * @param buffer The video frame buffer. + * @param uid The user ID you want to cache. + * @param channel_id The channel ID. + */ + void EnableVideoFrameBuffer(const IrisVideoFrameBuffer &buffer, + unsigned int uid, + const char *channel_id = "") IRIS_DEPRECATED; + + void DisableVideoFrameBuffer(const IrisVideoFrameBufferDelegate *delegate); + + void DisableVideoFrameBuffer(const unsigned int *uid = nullptr, + const char *channel_id = "") IRIS_DEPRECATED; + + bool GetVideoFrame(IrisVideoFrame &video_frame, bool &is_new_frame, + unsigned int uid, + const char *channel_id = "") IRIS_DEPRECATED; + + public: + /** + * Enable buffer the video frame from user. + * @param buffer The video frame buffer. + * @param uid The user ID you want to cache. + * @param channel_id The channel ID. + */ + void EnableVideoFrameBuffer(const IrisVideoFrameBuffer &buffer, + const IrisVideoFrameBufferConfig *config); + + void + DisableVideoFrameBuffer(const IrisVideoFrameBufferConfig *config = nullptr); + + bool GetVideoFrame(IrisVideoFrame &video_frame, bool &is_new_frame, + const IrisVideoFrameBufferConfig *config); + + public: + bool SetVideoFrameInternal(const IrisVideoFrame &video_frame, + const IrisVideoFrameBufferConfig *config); + + bool GetVideoFrameInternal(IrisVideoFrame &video_frame, + const IrisVideoFrameBufferConfig *config); + + private: + class Impl; + Impl *impl_; +}; + +}// namespace iris +}// namespace agora + +#ifdef __cplusplus +extern "C" { +#endif + +typedef void(IRIS_CALL *Func_VideoFrame)( + const IrisVideoFrame *video_frame, const IrisVideoFrameBufferConfig *config, + bool resize); +typedef struct IrisCVideoFrameBuffer { + IrisVideoFrameType type; + Func_VideoFrame OnVideoFrameReceived; + int resize_width; + int resize_height; +} IrisCVideoFrameBuffer; +typedef void *IrisVideoFrameBufferDelegateHandle; + +typedef void *IrisVideoFrameBufferManagerPtr; + +IRIS_API IrisVideoFrameBufferManagerPtr CreateIrisVideoFrameBufferManager(); + +IRIS_API void +FreeIrisVideoFrameBufferManager(IrisVideoFrameBufferManagerPtr manager_ptr); + +IRIS_API IrisEventHandlerHandle SetIrisVideoFrameBufferManagerEventHandler( + IrisVideoFrameBufferManagerPtr manager_ptr, + IrisCEventHandler *event_handler); + +IRIS_API void UnsetIrisVideoFrameBufferManagerEventHandler( + IrisVideoFrameBufferManagerPtr manager_ptr, IrisEventHandlerHandle handle); + +IRIS_API IrisVideoFrameBufferDelegateHandle EnableVideoFrameBuffer( + IrisVideoFrameBufferManagerPtr manager_ptr, IrisCVideoFrameBuffer *buffer, + unsigned int uid, const char *channel_id = "") IRIS_DEPRECATED; + +IRIS_API IrisVideoFrameBufferDelegateHandle EnableVideoFrameBufferByConfig( + IrisVideoFrameBufferManagerPtr manager_ptr, IrisCVideoFrameBuffer *buffer, + const IrisVideoFrameBufferConfig *config); + +IRIS_API void DisableVideoFrameBufferByDelegate( + IrisVideoFrameBufferManagerPtr manager_ptr, + IrisVideoFrameBufferDelegateHandle handle = nullptr); + +IRIS_API void +DisableVideoFrameBufferByUid(IrisVideoFrameBufferManagerPtr manager_ptr, + unsigned int uid, + const char *channel_id = "") IRIS_DEPRECATED; + +IRIS_API void +DisableVideoFrameBufferByConfig(IrisVideoFrameBufferManagerPtr manager_ptr, + const IrisVideoFrameBufferConfig *config); + +IRIS_API void +DisableAllVideoFrameBuffer(IrisVideoFrameBufferManagerPtr manager_ptr); + +IRIS_API bool GetVideoFrame(IrisVideoFrameBufferManagerPtr manager_ptr, + IrisVideoFrame *video_frame, bool *is_new_frame, + unsigned int uid, + const char *channel_id = "") IRIS_DEPRECATED; + +IRIS_API bool GetVideoFrameByConfig(IrisVideoFrameBufferManagerPtr manager_ptr, + IrisVideoFrame *video_frame, + bool *is_new_frame, + const IrisVideoFrameBufferConfig *config); + +#ifdef __cplusplus +} +#endif + +#endif//IRIS_VIDEO_PROCESSOR_H_ diff --git a/integration_test_app/iris_integration_test/unittest/CMakeLists.txt b/integration_test_app/iris_integration_test/unittest/CMakeLists.txt new file mode 100644 index 000000000..cbfbe9bef --- /dev/null +++ b/integration_test_app/iris_integration_test/unittest/CMakeLists.txt @@ -0,0 +1,32 @@ +set(LIBRARY_NAME iris_integration_test_ut) + +add_subdirectory("${CMAKE_CURRENT_SOURCE_DIR}/../third_party/googletest" googletest) + +message(status adsdsdsds) + +# Add test cpp file +add_executable(${LIBRARY_NAME} + iris_rtc_engine_integration_test_helpers_unittest.cc + main.cc + ) + +set_target_properties(${LIBRARY_NAME} PROPERTIES + LINK_FLAGS "-Wl -F ${LIBS_DIR} -rpath ${LIBS_DIR} -rpath ${CMAKE_CURRENT_SOURCE_DIR}/../../macos/Pods/AgoraRtcEngine_macOS" + ) + +# Link test executable against gtest & gtest_main +target_link_libraries(${LIBRARY_NAME} + PRIVATE + gtest + gtest_main + gmock + gmock_main + iris_integration_test + ) + +add_test( + NAME ${LIBRARY_NAME} + COMMAND ${LIBRARY_NAME} +) + + diff --git a/integration_test_app/iris_integration_test/unittest/iris_rtc_engine_integration_test_helpers_unittest.cc b/integration_test_app/iris_integration_test/unittest/iris_rtc_engine_integration_test_helpers_unittest.cc new file mode 100644 index 000000000..dc0596e90 --- /dev/null +++ b/integration_test_app/iris_integration_test/unittest/iris_rtc_engine_integration_test_helpers_unittest.cc @@ -0,0 +1,726 @@ +#include "fake_rtc_engine.h" +#include "iris_rtc_engine_call_api_recorder.h" +#include "iris_rtc_engine_integration_test_helplers.h" +#include "AgoraBase.h" +#include "iris_event_handler.h" +#include "iris_rtc_channel.h" +#include "iris_rtc_device_manager.h" +#include "iris_rtc_engine.h" +#include "iris_rtc_raw_data.h" +#include "gmock/gmock.h" + +#include "gtest/gtest.h" + +using namespace agora::iris; +using namespace agora::iris::rtc; + +class TestIrisEventHandler : public IrisEventHandler +{ +public: + bool callOnEvent_ = false; + bool callOnEventWithBuffer_ = false; + void OnEvent(const char *event, const char *data) override + { + callOnEvent_ = true; + } + + void OnEvent(const char *event, const char *data, const void *buffer, + unsigned int length) override + { + callOnEventWithBuffer_ = true; + } +}; + +class TestIrisRtcChannelDelegate : public IrisRtcChannel +{ + +public: + bool calledInitialize_ = false; + bool calledSetDelegate_ = false; + bool calledRelease_ = false; + bool calledGetDelegate_ = false; + + bool calledSetEventHandler_ = false; + bool calledGetEventHandler_ = false; + bool calledRegisterEventHandler_ = false; + bool calledUnRegisterEventHandler_ = false; + bool calledCallApi1_ = false; + bool calledCallApi2_ = false; + bool calledCallApi3_ = false; + + IrisEventHandler *event_handler_; + + void Initialize(agora::rtc::IRtcEngine *engine) override + { + calledInitialize_ = true; + } + + void Release() override { calledRelease_ = true; } + + void SetEventHandler(IrisEventHandler *event_handler) override + { + calledSetEventHandler_ = true; + event_handler_ = event_handler; + } + + IrisEventHandler *GetEventHandler() override + { + calledGetEventHandler_ = true; + return event_handler_; + } + + void RegisterEventHandler(const char *channel_id, + IrisEventHandler *event_handler) override + { + calledRegisterEventHandler_ = true; + } + + void UnRegisterEventHandler(const char *channel_id) override + { + calledUnRegisterEventHandler_ = true; + } + + int CallApi(ApiTypeChannel api_type, const char *params, + char result[kBasicResultLength]) override + { + calledCallApi1_ = true; + return 0; + } + + IRIS_DEPRECATED + int CallApi(ApiTypeChannel api_type, const char *params, void *buffer, + char result[kBasicResultLength]) override + { + calledCallApi2_ = true; + return 0; + } + + int CallApi(ApiTypeChannel api_type, const char *params, void *buffer, + unsigned int length, char *result) override + { + calledCallApi3_ = true; + return 0; + } +}; + +class TestIrisRtcEngineDelegate : public IrisRtcEngine +{ +public: + bool calledInitialize_ = false; + bool calledSetDelegate_ = false; + bool calledGetDelegate_ = false; + bool calledSetEventHandler_ = false; + bool calledGetEventHandler_ = false; + bool calledCallApi1_ = false; + bool calledCallApi2_ = false; + bool calledCallApi3_ = false; + bool calledDeviceManager = false; + bool calledChannel = false; + bool calledRawData = false; + IIrisRtcChannel *channel_; + IrisEventHandler *event_handler_; + + TestIrisRtcEngineDelegate(IIrisRtcChannel *channel = nullptr) + { + if (channel) + { + channel_ = channel; + } + else + { + channel_ = new TestIrisRtcChannelDelegate(); + } + } + + void Initialize(agora::rtc::IRtcEngine *rtc_engine) override + { + calledInitialize_ = true; + } + + void SetDelegate(IIrisRtcEngine *delegate) { calledSetDelegate_ = true; } + + IIrisRtcEngine *GetDelegate() + { + calledGetDelegate_ = true; + return nullptr; + } + + void SetEventHandler(IrisEventHandler *event_handler) override + { + calledSetEventHandler_ = true; + event_handler_ = event_handler; + } + + IrisEventHandler *GetEventHandler() override + { + calledGetEventHandler_ = true; + return event_handler_; + } + + int CallApi(ApiTypeEngine api_type, const char *params, + char result[kBasicResultLength]) override + { + calledCallApi1_ = true; + return 0; + } + + IRIS_DEPRECATED + int CallApi(ApiTypeEngine api_type, const char *params, void *buffer, + char result[kBasicResultLength]) override + { + calledCallApi2_ = true; + return 0; + } + + int CallApi(ApiTypeEngine api_type, const char *params, void *buffer, + unsigned int length, char result[kBasicResultLength]) override + { + calledCallApi3_ = true; + return 0; + } + + IIrisRtcDeviceManager *device_manager() override + { + calledDeviceManager = true; + return nullptr; + } + + IIrisRtcChannel *channel() override + { + calledChannel = true; + return channel_; + } + + IrisRtcRawData *raw_data() override + { + calledRawData = true; + return nullptr; + } +}; + +class TestIrisRtcEngineErrorCodeCallApiDelegate : public IrisRtcEngine +{ +public: + TestIrisRtcEngineErrorCodeCallApiDelegate() {} + + int CallApi(ApiTypeEngine api_type, const char *params, + char result[kBasicResultLength]) override + { + return -agora::ERROR_CODE_TYPE::ERR_NOT_INITIALIZED; + } + + IRIS_DEPRECATED + int CallApi(ApiTypeEngine api_type, const char *params, void *buffer, + char result[kBasicResultLength]) override + { + return -agora::ERROR_CODE_TYPE::ERR_NOT_INITIALIZED; + } + + int CallApi(ApiTypeEngine api_type, const char *params, void *buffer, + unsigned int length, char result[kBasicResultLength]) override + { + return -agora::ERROR_CODE_TYPE::ERR_NOT_INITIALIZED; + } +}; + +class TestIrisRtcChannelCallApiErrorCodeDelegate : public IrisRtcChannel +{ + +public: + int CallApi(ApiTypeChannel api_type, const char *params, + char result[kBasicResultLength]) override + { + return -agora::ERROR_CODE_TYPE::ERR_NOT_INITIALIZED; + } + + IRIS_DEPRECATED + int CallApi(ApiTypeChannel api_type, const char *params, void *buffer, + char result[kBasicResultLength]) override + { + return -agora::ERROR_CODE_TYPE::ERR_NOT_INITIALIZED; + } + + int CallApi(ApiTypeChannel api_type, const char *params, void *buffer, + unsigned int length, char *result) override + { + return -agora::ERROR_CODE_TYPE::ERR_NOT_INITIALIZED; + } +}; + +class IrisProxyFlutterIntegrationTestHelpersTest : public ::testing::Test +{ +private: + /* data */ +public: + IrisProxyFlutterIntegrationTestHelpersTest(/* args */); + ~IrisProxyFlutterIntegrationTestHelpersTest(); +}; + +IrisProxyFlutterIntegrationTestHelpersTest:: + IrisProxyFlutterIntegrationTestHelpersTest(/* args */) {} + +IrisProxyFlutterIntegrationTestHelpersTest:: + ~IrisProxyFlutterIntegrationTestHelpersTest() {} + +TEST_F(IrisProxyFlutterIntegrationTestHelpersTest, CanSetIrisProxyCallApi) +{ + TestIrisRtcEngineDelegate *delegate = new TestIrisRtcEngineDelegate(); + IrisRtcEngine *engine = + new IrisRtcEngine(delegate, kEngineTypeNormal, nullptr); + + SetIrisRtcEngineCallApiRecorder(engine, false); + + ASSERT_EQ(delegate->calledInitialize_, true); + + engine->SetEventHandler(nullptr); + ASSERT_EQ(delegate->calledSetEventHandler_, true); + + engine->GetEventHandler(); + ASSERT_EQ(delegate->calledGetEventHandler_, true); + + char res[kBasicResultLength] = ""; + engine->CallApi(static_cast(1), "params", res); + ASSERT_EQ(delegate->calledCallApi1_, true); + + engine->CallApi(static_cast(2), "params", nullptr, res); + ASSERT_EQ(delegate->calledCallApi3_, true); + + engine->CallApi(static_cast(3), "params", nullptr, 0, res); + ASSERT_EQ(delegate->calledCallApi3_, true); + + engine->device_manager(); + ASSERT_EQ(delegate->calledDeviceManager, true); + + engine->channel(); + ASSERT_EQ(delegate->calledChannel, true); + + engine->raw_data(); + ASSERT_EQ(delegate->calledRawData, true); + + delete engine; +} + +TEST_F(IrisProxyFlutterIntegrationTestHelpersTest, + CanSetIrisProxyCallApiForChannel) +{ + TestIrisRtcEngineDelegate *delegate = new TestIrisRtcEngineDelegate(); + IrisRtcEngine *engine = + new IrisRtcEngine(delegate, kEngineTypeNormal, nullptr); + + SetIrisRtcEngineCallApiRecorder(engine, true); + + TestIrisRtcChannelDelegate *channel = + reinterpret_cast(delegate->channel()); + + agora::rtc::FakeRtcEngine *fakeRtcEngine = new agora::rtc::FakeRtcEngine(); + engine->channel()->Initialize(fakeRtcEngine); + ASSERT_EQ(channel->calledInitialize_, true); + delete fakeRtcEngine; + + engine->channel()->SetEventHandler(nullptr); + ASSERT_EQ(channel->calledSetEventHandler_, true); + + engine->channel()->GetEventHandler(); + ASSERT_EQ(channel->calledGetEventHandler_, true); + + engine->channel()->RegisterEventHandler("1", nullptr); + ASSERT_EQ(channel->calledRegisterEventHandler_, true); + + engine->channel()->UnRegisterEventHandler("1"); + ASSERT_EQ(channel->calledUnRegisterEventHandler_, true); + + char res[kBasicResultLength] = ""; + engine->channel()->CallApi(ApiTypeChannel::kChannelCreateChannel, "params", + res); + ASSERT_EQ(channel->calledCallApi1_, true); + + engine->channel()->CallApi(ApiTypeChannel::kChannelJoinChannel, "params", + nullptr, res); + ASSERT_EQ(channel->calledCallApi2_, true); + + engine->channel()->CallApi(ApiTypeChannel::kChannelLeaveChannel, "params", + nullptr, 0, res); + ASSERT_EQ(channel->calledCallApi3_, true); + + delete engine; +} + +TEST_F(IrisProxyFlutterIntegrationTestHelpersTest, AbleToSetCallApiMockResult) +{ + TestIrisRtcEngineDelegate *delegate = new TestIrisRtcEngineDelegate(); + IrisRtcEngine *engine = + new IrisRtcEngine(delegate, kEngineTypeNormal, nullptr); + IrisRtcEngineCallApiRecoder *proxy = + reinterpret_cast( + SetIrisRtcEngineCallApiRecorder(engine, false)); + MockCallApiResult(proxy, 1, "params", "returnValue"); + + char res[kBasicResultLength] = ""; + engine->CallApi(ApiTypeEngine::kEngineAddVideoWaterMark, "params", res); + + ASSERT_EQ(std::string(res), std::string("returnValue")); + + delete engine; +} + +TEST_F(IrisProxyFlutterIntegrationTestHelpersTest, + AbleToSetCallApiMockResultForChannel) +{ + TestIrisRtcEngineDelegate *delegate = new TestIrisRtcEngineDelegate(); + IrisRtcEngine *engine = + new IrisRtcEngine(delegate, kEngineTypeNormal, nullptr); + IrisRtcEngineCallApiRecoder *proxy = + reinterpret_cast( + SetIrisRtcEngineCallApiRecorder(engine, true)); + MockCallApiResult(proxy, ApiTypeChannel::kChannelJoinChannel, "params", + "returnValue"); + + char res[kBasicResultLength] = ""; + engine->channel()->CallApi(ApiTypeChannel::kChannelJoinChannel, "params", + res); + + ASSERT_EQ(std::string(res), std::string("returnValue")); + + delete engine; +} + +TEST_F(IrisProxyFlutterIntegrationTestHelpersTest, + AbleToSetCallApiMockReturnCode) +{ + TestIrisRtcEngineDelegate *delegate = new TestIrisRtcEngineDelegate(); + IrisRtcEngine *engine = + new IrisRtcEngine(delegate, kEngineTypeNormal, nullptr); + IrisRtcEngineCallApiRecoder *proxy = + reinterpret_cast( + SetIrisRtcEngineCallApiRecorder(engine, false)); + MockCallApiReturnCode(proxy, 1, "params", -1); + + char res[kBasicResultLength] = ""; + int ret = + engine->CallApi(ApiTypeEngine::kEngineAddVideoWaterMark, "params", res); + + ASSERT_EQ(ret, -1); + + delete engine; +} + +TEST_F(IrisProxyFlutterIntegrationTestHelpersTest, + ShouldReturnErrorCodeIfNegative) +{ + TestIrisRtcEngineErrorCodeCallApiDelegate *delegate = + new TestIrisRtcEngineErrorCodeCallApiDelegate(); + IrisRtcEngine *engine = + new IrisRtcEngine(delegate, kEngineTypeNormal, nullptr); + IrisRtcEngineCallApiRecoder *proxy = + reinterpret_cast( + SetIrisRtcEngineCallApiRecorder(engine, false)); + MockCallApiReturnCode(proxy, 1, "params", 10); + + char res[kBasicResultLength] = ""; + int ret = + engine->CallApi(ApiTypeEngine::kEngineAddVideoWaterMark, "params", res); + + ASSERT_EQ(ret, -agora::ERROR_CODE_TYPE::ERR_NOT_INITIALIZED); + + delete engine; +} + +TEST_F(IrisProxyFlutterIntegrationTestHelpersTest, + ShouldAlwaysReturnSuccessForApiTypeEngineInitialize) +{ + TestIrisRtcEngineErrorCodeCallApiDelegate *delegate = + new TestIrisRtcEngineErrorCodeCallApiDelegate(); + IrisRtcEngine *engine = + new IrisRtcEngine(delegate, kEngineTypeNormal, nullptr); + IrisRtcEngineCallApiRecoder *proxy = + reinterpret_cast( + SetIrisRtcEngineCallApiRecorder(engine, false)); + + char res[kBasicResultLength] = ""; + int ret = + engine->CallApi(ApiTypeEngine::kEngineInitialize, "params", res); + + ASSERT_EQ(ret, 0); + + delete engine; +} + +TEST_F(IrisProxyFlutterIntegrationTestHelpersTest, + ShouldAlwaysReturnSuccessForApiTypeChannelCreateChannel) +{ + TestIrisRtcEngineDelegate *delegate = new TestIrisRtcEngineDelegate( + new TestIrisRtcChannelCallApiErrorCodeDelegate); + IrisRtcEngine *engine = + new IrisRtcEngine(delegate, kEngineTypeNormal, nullptr); + IrisRtcEngineCallApiRecoder *proxy = + reinterpret_cast( + SetIrisRtcEngineCallApiRecorder(engine, true)); + + char res[kBasicResultLength] = ""; + int ret = engine->channel()->CallApi(ApiTypeChannel::kChannelCreateChannel, + "params", res); + + ASSERT_EQ(ret, 0); + + delete engine; +} + +TEST_F(IrisProxyFlutterIntegrationTestHelpersTest, + ShouldReturnErrorCodeIfNegativeForChannel) +{ + TestIrisRtcEngineDelegate *delegate = new TestIrisRtcEngineDelegate( + new TestIrisRtcChannelCallApiErrorCodeDelegate); + IrisRtcEngine *engine = + new IrisRtcEngine(delegate, kEngineTypeNormal, nullptr); + IrisRtcEngineCallApiRecoder *proxy = + reinterpret_cast( + SetIrisRtcEngineCallApiRecorder(engine, true)); + MockCallApiReturnCode(proxy, 1, "params", 10); + + char res[kBasicResultLength] = ""; + int ret = engine->channel()->CallApi(ApiTypeChannel::kChannelJoinChannel, + "params", res); + + ASSERT_EQ(ret, -agora::ERROR_CODE_TYPE::ERR_NOT_INITIALIZED); + + delete engine; +} + +TEST_F(IrisProxyFlutterIntegrationTestHelpersTest, + ShouldCallDestroyIrisProxyForIntegrationTestDartFFISuccess) +{ + + TestIrisRtcEngineDelegate *delegate = new TestIrisRtcEngineDelegate(); + IrisRtcEngine *engine = + new IrisRtcEngine(delegate, kEngineTypeNormal, nullptr); + IrisRtcEngineCallApiRecoder *proxy = + reinterpret_cast( + SetIrisRtcEngineCallApiRecorder(engine, false)); + + ClearCallApiRecorder(proxy); + + delete engine; +} + +TEST_F(IrisProxyFlutterIntegrationTestHelpersTest, + AbleToCallIrisProxyExpectCalledApi) +{ + + TestIrisRtcEngineDelegate *delegate = new TestIrisRtcEngineDelegate(); + IrisRtcEngine *engine = + new IrisRtcEngine(delegate, kEngineTypeNormal, nullptr); + IrisRtcEngineCallApiRecoder *proxy = + reinterpret_cast( + SetIrisRtcEngineCallApiRecorder(engine, false)); + + char res[kBasicResultLength] = ""; + engine->CallApi(ApiTypeEngine::kEngineAddVideoWaterMark, "params", res); + + bool ret = ExpectCalledApi(proxy, ApiTypeEngine::kEngineAddVideoWaterMark, + "params", nullptr, 0); + ASSERT_EQ(ret, true); +} + +TEST_F(IrisProxyFlutterIntegrationTestHelpersTest, + AbleToCallExpectCalledApiApiTypeEngineInitialize) +{ + + TestIrisRtcEngineDelegate *delegate = new TestIrisRtcEngineDelegate(); + IrisRtcEngine *engine = + new IrisRtcEngine(delegate, kEngineTypeNormal, nullptr); + IrisRtcEngineCallApiRecoder *proxy = + reinterpret_cast( + SetIrisRtcEngineCallApiRecorder(engine, false)); + + char res[kBasicResultLength] = ""; + engine->CallApi(ApiTypeEngine::kEngineInitialize, "params", res); + + bool ret = ExpectCalledApi(proxy, ApiTypeEngine::kEngineInitialize, + "params", nullptr, 0); + ASSERT_EQ(ret, true); +} + +TEST_F(IrisProxyFlutterIntegrationTestHelpersTest, + AbleToCallIrisProxyExpectCalledApiForChannel) +{ + + TestIrisRtcEngineDelegate *delegate = new TestIrisRtcEngineDelegate(); + IrisRtcEngine *engine = + new IrisRtcEngine(delegate, kEngineTypeNormal, nullptr); + IrisRtcEngineCallApiRecoder *proxy = + reinterpret_cast( + SetIrisRtcEngineCallApiRecorder(engine, true)); + + char res[kBasicResultLength] = ""; + engine->channel()->CallApi(ApiTypeChannel::kChannelJoinChannel, "params", + res); + + bool ret = ExpectCalledApi(proxy, ApiTypeChannel::kChannelJoinChannel, + "params", nullptr, 0); + ASSERT_EQ(ret, true); +} + +TEST_F(IrisProxyFlutterIntegrationTestHelpersTest, + AbleToCallExpectCalledApiApiTypeChannelCreateChannel) +{ + + TestIrisRtcEngineDelegate *delegate = new TestIrisRtcEngineDelegate(); + IrisRtcEngine *engine = + new IrisRtcEngine(delegate, kEngineTypeNormal, nullptr); + IrisRtcEngineCallApiRecoder *proxy = + reinterpret_cast( + SetIrisRtcEngineCallApiRecorder(engine, true)); + + char res[kBasicResultLength] = ""; + engine->channel()->CallApi(ApiTypeChannel::kChannelCreateChannel, "params", + res); + + bool ret = ExpectCalledApi(proxy, ApiTypeChannel::kChannelCreateChannel, + "params", nullptr, 0); + ASSERT_EQ(ret, true); +} + +TEST_F(IrisProxyFlutterIntegrationTestHelpersTest, + AbleToCallIrisProxyExpectCalledApiWithBuffer) +{ + TestIrisRtcEngineDelegate *delegate = new TestIrisRtcEngineDelegate(); + IrisRtcEngine *engine = + new IrisRtcEngine(delegate, kEngineTypeNormal, nullptr); + IrisRtcEngineCallApiRecoder *proxy = + reinterpret_cast( + SetIrisRtcEngineCallApiRecorder(engine, false)); + + SetExplicitBufferSize(proxy, ApiTypeEngine::kEngineAddVideoWaterMark, + "params", 2); + + char res[kBasicResultLength] = ""; + unsigned char buffer[2] = {0xb4, 0xaf}; + engine->CallApi(ApiTypeEngine::kEngineAddVideoWaterMark, "params", buffer, + res); + + unsigned char expectedBuffer[2] = {0xb4, 0xaf}; + bool ret = ExpectCalledApi(proxy, ApiTypeEngine::kEngineAddVideoWaterMark, + "params", expectedBuffer, 2); + ASSERT_EQ(ret, true); +} + +TEST_F(IrisProxyFlutterIntegrationTestHelpersTest, + AbleToSetCallApiMockReturnCodeForChannel) +{ + TestIrisRtcEngineDelegate *delegate = new TestIrisRtcEngineDelegate(); + IrisRtcEngine *engine = + new IrisRtcEngine(delegate, kEngineTypeNormal, nullptr); + IrisRtcEngineCallApiRecoder *proxy = + reinterpret_cast( + SetIrisRtcEngineCallApiRecorder(engine, true)); + MockCallApiReturnCode(proxy, ApiTypeChannel::kChannelJoinChannel, "params", + -1); + + char res[kBasicResultLength] = ""; + int ret = engine->channel()->CallApi(ApiTypeChannel::kChannelJoinChannel, + "params", res); + + ASSERT_EQ(ret, -1); + + delete engine; +} + +TEST_F(IrisProxyFlutterIntegrationTestHelpersTest, + AbleToCallIrisProxyExpectCalledApiWithBufferForChannel) +{ + TestIrisRtcEngineDelegate *delegate = new TestIrisRtcEngineDelegate(); + IrisRtcEngine *engine = + new IrisRtcEngine(delegate, kEngineTypeNormal, nullptr); + IrisRtcEngineCallApiRecoder *proxy = + reinterpret_cast( + SetIrisRtcEngineCallApiRecorder(engine, true)); + + SetExplicitBufferSize(proxy, ApiTypeChannel::kChannelJoinChannel, "params", + 2); + + char res[kBasicResultLength] = ""; + unsigned char buffer[2] = {0xb4, 0xaf}; + engine->channel()->CallApi(ApiTypeChannel::kChannelJoinChannel, "params", + buffer, res); + + unsigned char expectedBuffer[2] = {0xb4, 0xaf}; + bool ret = ExpectCalledApi(proxy, ApiTypeChannel::kChannelJoinChannel, + "params", expectedBuffer, 2); + ASSERT_EQ(ret, true); +} + +TEST_F(IrisProxyFlutterIntegrationTestHelpersTest, + CanCallIrisProxyEventHandlerOnEvent) +{ + TestIrisRtcEngineDelegate *delegate = new TestIrisRtcEngineDelegate(); + IrisRtcEngine *engine = + new IrisRtcEngine(delegate, kEngineTypeNormal, nullptr); + SetIrisRtcEngineCallApiRecorder(engine, false); + + TestIrisEventHandler *event_handler = new TestIrisEventHandler(); + engine->SetEventHandler(event_handler); + + CallIrisEventHandlerOnEvent(engine, false, "event", "data"); + + ASSERT_EQ(event_handler->callOnEvent_, true); + + delete engine; +} + +TEST_F(IrisProxyFlutterIntegrationTestHelpersTest, + CanCallIrisProxyEventHandlerOnEventForChannel) +{ + TestIrisRtcEngineDelegate *delegate = new TestIrisRtcEngineDelegate(); + IrisRtcEngine *engine = + new IrisRtcEngine(delegate, kEngineTypeNormal, nullptr); + SetIrisRtcEngineCallApiRecorder(engine, false); + + TestIrisEventHandler *event_handler = new TestIrisEventHandler(); + engine->channel()->SetEventHandler(event_handler); + + CallIrisEventHandlerOnEvent(engine, true, "event", "data"); + + ASSERT_EQ(event_handler->callOnEvent_, true); + + delete engine; +} + +TEST_F(IrisProxyFlutterIntegrationTestHelpersTest, + CanCallIrisProxyEventHandlerOnEventWithBuffer) +{ + TestIrisRtcEngineDelegate *delegate = new TestIrisRtcEngineDelegate(); + IrisRtcEngine *engine = + new IrisRtcEngine(delegate, kEngineTypeNormal, nullptr); + SetIrisRtcEngineCallApiRecorder(engine, false); + + TestIrisEventHandler *event_handler = new TestIrisEventHandler(); + engine->SetEventHandler(event_handler); + + unsigned char buffer[2] = {0xb4, 0xaf}; + CallIrisEventHandlerOnEventWithBuffer(engine, false, "event", "data", buffer, + 2); + + ASSERT_EQ(event_handler->callOnEventWithBuffer_, true); + + delete engine; +} + +TEST_F(IrisProxyFlutterIntegrationTestHelpersTest, + CanCallIrisProxyEventHandlerOnEventWithBufferForChannel) +{ + TestIrisRtcEngineDelegate *delegate = new TestIrisRtcEngineDelegate(); + IrisRtcEngine *engine = + new IrisRtcEngine(delegate, kEngineTypeNormal, nullptr); + SetIrisRtcEngineCallApiRecorder(engine, true); + + TestIrisEventHandler *event_handler = new TestIrisEventHandler(); + engine->channel()->SetEventHandler(event_handler); + + unsigned char buffer[2] = {0xb4, 0xaf}; + CallIrisEventHandlerOnEventWithBuffer(engine, true, "event", "data", buffer, + 2); + + ASSERT_EQ(event_handler->callOnEventWithBuffer_, true); + + delete engine; +} diff --git a/integration_test_app/iris_integration_test/unittest/main.cc b/integration_test_app/iris_integration_test/unittest/main.cc new file mode 100644 index 000000000..07977bd70 --- /dev/null +++ b/integration_test_app/iris_integration_test/unittest/main.cc @@ -0,0 +1,6 @@ +#include + +int main(int argc, char **argv) { + testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} \ No newline at end of file diff --git a/integration_test_app/lib/main.dart b/integration_test_app/lib/main.dart new file mode 100644 index 000000000..202509be1 --- /dev/null +++ b/integration_test_app/lib/main.dart @@ -0,0 +1,115 @@ +import 'package:flutter/material.dart'; + +void main() { + runApp(const MyApp()); +} + +class MyApp extends StatelessWidget { + const MyApp({Key? key}) : super(key: key); + + // This widget is the root of your application. + @override + Widget build(BuildContext context) { + return MaterialApp( + title: 'Flutter Demo', + theme: ThemeData( + // This is the theme of your application. + // + // Try running your application with "flutter run". You'll see the + // application has a blue toolbar. Then, without quitting the app, try + // changing the primarySwatch below to Colors.green and then invoke + // "hot reload" (press "r" in the console where you ran "flutter run", + // or simply save your changes to "hot reload" in a Flutter IDE). + // Notice that the counter didn't reset back to zero; the application + // is not restarted. + primarySwatch: Colors.blue, + ), + home: const MyHomePage(title: 'Flutter Demo Home Page'), + ); + } +} + +class MyHomePage extends StatefulWidget { + const MyHomePage({Key? key, required this.title}) : super(key: key); + + // This widget is the home page of your application. It is stateful, meaning + // that it has a State object (defined below) that contains fields that affect + // how it looks. + + // This class is the configuration for the state. It holds the values (in this + // case the title) provided by the parent (in this case the App widget) and + // used by the build method of the State. Fields in a Widget subclass are + // always marked "final". + + final String title; + + @override + State createState() => _MyHomePageState(); +} + +class _MyHomePageState extends State { + int _counter = 0; + + void _incrementCounter() { + setState(() { + // This call to setState tells the Flutter framework that something has + // changed in this State, which causes it to rerun the build method below + // so that the display can reflect the updated values. If we changed + // _counter without calling setState(), then the build method would not be + // called again, and so nothing would appear to happen. + _counter++; + }); + } + + @override + Widget build(BuildContext context) { + // This method is rerun every time setState is called, for instance as done + // by the _incrementCounter method above. + // + // The Flutter framework has been optimized to make rerunning build methods + // fast, so that you can just rebuild anything that needs updating rather + // than having to individually change instances of widgets. + return Scaffold( + appBar: AppBar( + // Here we take the value from the MyHomePage object that was created by + // the App.build method, and use it to set our appbar title. + title: Text(widget.title), + ), + body: Center( + // Center is a layout widget. It takes a single child and positions it + // in the middle of the parent. + child: Column( + // Column is also a layout widget. It takes a list of children and + // arranges them vertically. By default, it sizes itself to fit its + // children horizontally, and tries to be as tall as its parent. + // + // Invoke "debug painting" (press "p" in the console, choose the + // "Toggle Debug Paint" action from the Flutter Inspector in Android + // Studio, or the "Toggle Debug Paint" command in Visual Studio Code) + // to see the wireframe for each widget. + // + // Column has various properties to control how it sizes itself and + // how it positions its children. Here we use mainAxisAlignment to + // center the children vertically; the main axis here is the vertical + // axis because Columns are vertical (the cross axis would be + // horizontal). + mainAxisAlignment: MainAxisAlignment.center, + children: [ + const Text( + 'You have pushed the button this many times:', + ), + Text( + '$_counter', + style: Theme.of(context).textTheme.headline4, + ), + ], + ), + ), + floatingActionButton: FloatingActionButton( + onPressed: _incrementCounter, + tooltip: 'Increment', + child: const Icon(Icons.add), + ), // This trailing comma makes auto-formatting nicer for build methods. + ); + } +} diff --git a/integration_test_app/lib/src/configs.dart b/integration_test_app/lib/src/configs.dart new file mode 100644 index 000000000..4ef547c4a --- /dev/null +++ b/integration_test_app/lib/src/configs.dart @@ -0,0 +1,14 @@ +/// Get your own App ID at https://dashboard.agora.io/ +String get appId { + // Allow pass an `appId` as an environment variable with name `TEST_APP_ID` by using --dart-define + return const String.fromEnvironment('TEST_APP_ID', defaultValue: ''); +} + +/// Your channel ID +String get channelId { + // Allow pass a `channelId` as an environment variable with name `TEST_CHANNEL_ID` by using --dart-define + return const String.fromEnvironment( + 'TEST_CHANNEL_ID', + defaultValue: '', + ); +} \ No newline at end of file diff --git a/integration_test_app/lib/src/event_handler_tester.dart b/integration_test_app/lib/src/event_handler_tester.dart new file mode 100644 index 000000000..8c6804026 --- /dev/null +++ b/integration_test_app/lib/src/event_handler_tester.dart @@ -0,0 +1,40 @@ +import 'dart:async'; +import 'dart:math'; + +import 'package:flutter_test/flutter_test.dart'; +import 'package:meta/meta.dart'; + +class EventHandlerTester { + final Completer _isEventCalledCompleter = Completer(); + void markEventCalled() { + _isEventCalledCompleter.complete(true); + } +} + +typedef EventHandlerTesterCallback = Future Function( + WidgetTester widgetTester, + EventHandlerTester eventHandlerTester, +); + +@isTest +void testEventCall(String description, EventHandlerTesterCallback callback) { + testWidgets( + description, + (WidgetTester tester) async { + final eventHandlerTester = EventHandlerTester(); + await callback(tester, eventHandlerTester); + await eventHandlerTester._isEventCalledCompleter.future; + expect( + eventHandlerTester._isEventCalledCompleter.isCompleted, + isTrue, + reason: + 'Callback of $description not be marked called, make sure you call' + ' the `eventHandlerTester.markEventCalled` function inside the callback.' + 'If the `eventHandlerTester.markEventCalled` is called inside the callback, ' + 'but the error still occur, that mean the callback is actually not be called,' + 'you should check the callback logic again.', + ); + }, + timeout: const Timeout(Duration(milliseconds: 10000)), + ); +} diff --git a/integration_test_app/lib/src/fake_iris_rtc_engine.dart b/integration_test_app/lib/src/fake_iris_rtc_engine.dart new file mode 100644 index 000000000..fc53514e0 --- /dev/null +++ b/integration_test_app/lib/src/fake_iris_rtc_engine.dart @@ -0,0 +1,630 @@ +import 'dart:ffi'; +import 'dart:io'; +import 'dart:typed_data'; + +import 'package:ffi/ffi.dart'; +import 'package:flutter/services.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:path/path.dart' as path; +import 'package:flutter/widgets.dart'; + +typedef SetIrisRtcEngineCallApiRecorderNative = Pointer Function( + Pointer enginePtr, + Int32 isMockChannel, + // Pointer callApiCallback, +); +typedef SetIrisRtcEngineCallApiRecorder = Pointer Function( + Pointer enginePtr, + int isMockChannel, + // Pointer callApiCallback, +); + +typedef ClearCallApiRecorderNative = Void Function( + Pointer callApiRecorderPtr, +); +typedef ClearCallApiRecorder = void Function( + Pointer callApiRecorderPtr, +); + +typedef MockCallApiResultNative = Void Function( + Pointer callApiRecorderPtr, + Uint32 apiType, + Pointer params, + Pointer mockResult); +typedef MockCallApiResult = void Function( + Pointer callApiRecorderPtr, + int apiType, + Pointer params, + Pointer mockResult); + +typedef MockCallApiReturnCodeNative = Void Function( + Pointer callApiRecorderPtr, + Uint32 apiType, + Pointer params, + Int32 mockReturnCode); +typedef MockCallApiReturnCode = void Function( + Pointer callApiRecorderPtr, + int apiType, + Pointer params, + int mockReturnCode); + +typedef SetExplicitBufferSizeNative = Void Function( + Pointer callApiRecorderPtr, + Uint32 apiType, + Pointer params, + Int32 bufferSize); +typedef SetExplicitBufferSize = void Function( + Pointer callApiRecorderPtr, + int apiType, + Pointer params, + int bufferSize); + +typedef ExpectCalledApiNative = Int32 Function( + Pointer callApiRecorderPtr, + Uint32 apiType, + Pointer params, + Pointer buffer, + Int32 bufferSize, +); +typedef ExpectCalledApi = int Function( + Pointer callApiRecorderPtr, + int apiType, + Pointer params, + Pointer buffer, + int bufferSize, +); + +// typedef SetIrisProxyEventHandlerNative = Pointer Function( +// Pointer enginePtr, +// Int32 isMockChannel, +// ); +// typedef SetIrisProxyEventHandler = Pointer Function( +// Pointer enginePtr, +// int isMockChannel, +// ); + +// typedef DestroyIrisProxyEventHandlerNative = Void Function( +// Pointer enginePtr, +// Int32 isMockChannel, +// Pointer irisProxyPtr, +// ); +// typedef DestroyIrisProxyEventHandler = void Function( +// Pointer enginePtr, +// int isMockChannel, +// Pointer irisProxyPtr, +// ); + +typedef CallIrisEventHandlerOnEventNative = Void Function( + Pointer enginePtr, + Int32 isMockChannel, + Pointer event, + Pointer data, +); +typedef CallIrisEventHandlerOnEvent = void Function( + Pointer enginePtr, + int isMockChannel, + Pointer event, + Pointer data, +); + +typedef CallIrisEventHandlerOnEventWithBufferNative = Void Function( + Pointer enginePtr, + Int32 isMockChannel, + Pointer event, + Pointer data, + Pointer buffer, + Uint32 length, +); +typedef CallIrisEventHandlerOnEventWithBuffer = void Function( + Pointer enginePtr, + int isMockChannel, + Pointer event, + Pointer data, + Pointer buffer, + int length, +); + +typedef CallRtcEngineEventNative = Void Function( + Pointer enginePtr, Pointer eventName); +typedef CallRtcEngineEvent = void Function( + Pointer enginePtr, Pointer eventName); + +typedef CallRtcChannelEventNative = Void Function( + Pointer enginePtr, Pointer eventName); +typedef CallRtcChannelEvent = void Function( + Pointer enginePtr, Pointer eventName); + +class _NativeIrisProxyBinding { + _NativeIrisProxyBinding(int irisRtcEngineIntPtr) { + _agoraRtcWrapperLib = _loadAgoraRtcWrapperLib(); + _irisRtcEnginePtr = _getIrisRtcEnginePtr( + _agoraRtcWrapperLib, + irisRtcEngineIntPtr, + ); + } + + // static const int _callApiExceptionalReturn = -1; + + late final DynamicLibrary _agoraRtcWrapperLib; + + late final Pointer _irisRtcEnginePtr; + + late final Pointer _callApiRecorderPtr; + + // late final Pointer _irisEventHandlerPtr; + + // static IrisCallApiCallback? _irisCallApiCallback; + + static DynamicLibrary _loadAgoraRtcWrapperLib() { + if (Platform.isWindows) { + return DynamicLibrary.open('iris_integration_test.dll'); + } + return Platform.isAndroid + ? DynamicLibrary.open("libiris_integration_test.so") + : DynamicLibrary.process(); + } + + static Pointer _getIrisRtcEnginePtr( + DynamicLibrary agoraRtcWrapperLib, int irisRtcEngineIntPtr) { + return Pointer.fromAddress(irisRtcEngineIntPtr); + // if (!Platform.isAndroid) { + + // } + + // final fp = agoraRtcWrapperLib.lookupFunction< + // GetIrisRtcEngineFromAndroidNativeHandleNative, + // GetIrisRtcEngineFromAndroidNativeHandle>( + // 'GetIrisRtcEngineFromAndroidNativeHandle'); + // return fp(Pointer.fromAddress(irisRtcEngineIntPtr)); + } + + // static int _onCallApiHandle( + // int apiType, Pointer param, Pointer result) { + // return _irisCallApiCallback?.onCallApi?.call( + // apiType, + // param.toDartString(), + // result.toDartString(), + // ) ?? + // 0; + // } + + // static int _onCallApiWithBufferHandle( + // int apiType, + // Pointer param, + // Pointer buffer, + // Pointer result, + // ) { + // return _irisCallApiCallback?.onCallApiWithBuffer?.call( + // apiType, + // param.toDartString(), + // buffer, + // result.toDartString(), + // ) ?? + // 0; + // } + + void setIrisRtcEngineCallApiRecorder(bool isMockChannel) { + // _irisCallApiCallback = irisCallApiCallback; + + final fp = _agoraRtcWrapperLib.lookupFunction< + SetIrisRtcEngineCallApiRecorderNative, + SetIrisRtcEngineCallApiRecorder>('SetIrisRtcEngineCallApiRecorder'); + + // final Pointer> onCallApiPtr = + // Pointer.fromFunction( + // _onCallApiHandle, + // _callApiExceptionalReturn, + // ); + // final Pointer> + // onCallApiWithBufferPtr = Pointer.fromFunction( + // _onCallApiWithBufferHandle, _callApiExceptionalReturn); + + // final callApiCallbackPtr = calloc() + // ..ref.onCallApi = onCallApiPtr + // ..ref.onCallApiWithBuffer = onCallApiWithBufferPtr; + + _callApiRecorderPtr = fp(_irisRtcEnginePtr, isMockChannel ? 1 : 0); + } + + void callIrisProxyEventHandlerOnEvent( + bool isMockChannel, + String event, + String data, + ) { + final fp = _agoraRtcWrapperLib.lookupFunction< + CallIrisEventHandlerOnEventNative, + CallIrisEventHandlerOnEvent>('CallIrisEventHandlerOnEvent'); + final eventN = event.toNativeUtf8(); + final dataN = data.toNativeUtf8(); + fp(_irisRtcEnginePtr, isMockChannel ? 1 : 0, eventN, dataN); + + // calloc.free(eventN); + // calloc.free(dataN); + } + + void callIrisProxyEventHandlerOnEventWithBuffer( + bool isMockChannel, + String event, + String data, + Uint8List buffer, + int bufferSize, + ) { + final fp = _agoraRtcWrapperLib.lookupFunction< + CallIrisEventHandlerOnEventWithBufferNative, + CallIrisEventHandlerOnEventWithBuffer>( + 'CallIrisEventHandlerOnEventWithBuffer'); + final eventN = event.toNativeUtf8(); + final dataN = data.toNativeUtf8(); + // final bufferN = calloc.allocate(bufferSize); + + final Pointer bufferN = calloc.allocate(buffer.length); + final pointerList = bufferN.asTypedList(buffer.length); + pointerList.setAll(0, buffer); + + fp(_irisRtcEnginePtr, isMockChannel ? 1 : 0, eventN, dataN, bufferN, + bufferSize); + + // calloc.free(eventN); + // calloc.free(dataN); + // calloc.free(bufferN); + } + + void clearCallApiRecorder() { + final fp = _agoraRtcWrapperLib.lookupFunction('ClearCallApiRecorder'); + fp(_callApiRecorderPtr); + } + + // Pointer getIrisProxyApiCallQueue() { + // final fp = _agoraRtcWrapperLib.lookupFunction< + // GetIrisProxyApiCallQueueNative, + // GetIrisProxyApiCallQueueNative>('GetIrisProxyApiCallQueue'); + // final p = fp(_irisProxyPtr); + + // return p; + // } + + void mockCallApiResult( + int apiType, + String params, + String mockResult, + ) { + final fp = _agoraRtcWrapperLib.lookupFunction('MockCallApiResult'); + final paramsN = params.toNativeUtf8(); + final mockResultN = mockResult.toNativeUtf8(); + fp(_callApiRecorderPtr, apiType, paramsN, mockResultN); + + calloc.free(paramsN); + calloc.free(mockResultN); + } + + void mockCallApiReturnCode( + int apiType, + String params, + int mockReturnCode, + ) { + final fp = _agoraRtcWrapperLib.lookupFunction('MockCallApiReturnCode'); + final paramsN = params.toNativeUtf8(); + + fp(_callApiRecorderPtr, apiType, paramsN, mockReturnCode); + + calloc.free(paramsN); + } + + void setExplicitBufferSize( + int apiType, + String params, + int bufferSize, + ) { + final fp = _agoraRtcWrapperLib.lookupFunction('SetExplicitBufferSize'); + final paramsN = params.toNativeUtf8(); + + fp(_callApiRecorderPtr, apiType, paramsN, bufferSize); + + calloc.free(paramsN); + } + + bool expectCalledApi( + int apiType, + String params, { + Uint8List? buffer, + int bufferSize = 0, + }) { + final fp = _agoraRtcWrapperLib.lookupFunction('ExpectCalledApi'); + final paramsN = params.toNativeUtf8(); + +// 'data' is a Uint8List created by concatenating the planes received from the CameraImage the camera puts out. +// Based on the code found here https://github.com/renancaraujo/bitmap/blob/master/lib/ffi.dart in the execute function +// https://groups.google.com/forum/#!searchin/dart-ffi/list%7Csort:date/dart-ffi/V_6g5hpABec/U9we6UyvBAAJ + final Pointer bufferN; + if (buffer != null) { + bufferN = calloc.allocate(buffer.length); + final pointerList = bufferN.asTypedList(buffer.length); + pointerList.setAll(0, buffer); + } else { + bufferN = Pointer.fromAddress(0); + } + + final ret = fp(_callApiRecorderPtr, apiType, paramsN, bufferN, bufferSize); + + calloc.free(paramsN); + calloc.free(bufferN); + return ret == 1; + } + + // void setIrisProxyEventHandler(bool isMockChannel) { + // final fp = _agoraRtcWrapperLib.lookupFunction< + // SetIrisProxyEventHandlerNative, + // SetIrisProxyEventHandler>('SetIrisProxyEventHandler'); + + // _irisEventHandlerPtr = fp(_irisRtcEnginePtr, isMockChannel ? 1 : 0); + // } + + // void destroyIrisProxyEventHandler(bool isMockChannel) { + // final fp = _agoraRtcWrapperLib.lookupFunction< + // DestroyIrisProxyEventHandlerNative, + // DestroyIrisProxyEventHandler>('DestroyIrisProxyEventHandler'); + // fp( + // _irisRtcEnginePtr, + // isMockChannel ? 1 : 0, + // _callApiRecorderPtr, + // ); + // } + + void callRtcEngineEvent(String event) { + final fp = _agoraRtcWrapperLib.lookupFunction('CallRtcEngineEvents'); + final pN = event.toNativeUtf8(); + fp(_irisRtcEnginePtr, pN); + // calloc.free(pN); + } + + void callRtcChannelEvent(String event) { + final fp = _agoraRtcWrapperLib.lookupFunction('CallRtcChannelEvents'); + final pN = event.toNativeUtf8(); + fp(_irisRtcEnginePtr, pN); + + } +} + +class ApiCall { + ApiCall({ + required this.apiType, + required this.params, + required this.result, + this.buffer, + }); + final int apiType; + final String params; + final String result; + final Object? buffer; +} + +class FakeIrisRtcEngine { + FakeIrisRtcEngine({ + bool isMockChannel = false, + bool isSubProcess = false, + }) : _isMockChannel = isMockChannel, + _isSubProcess = isSubProcess; + + final bool _isMockChannel; + final bool _isSubProcess; + late final int _irisRtcEngineIntPtr; + late final _NativeIrisProxyBinding _nativeIrisProxyBinding; + final MethodChannel _methodChannel = const MethodChannel('agora_rtc_engine'); + // final List _callApiQueue = []; + + Future _initialize() async { + _irisRtcEngineIntPtr = await _methodChannel + .invokeMethod('getIrisRtcEngineIntPtr', {'subProcess': _isSubProcess}); + _nativeIrisProxyBinding = _NativeIrisProxyBinding(_irisRtcEngineIntPtr); + } + + Future initialize() async { + await _initialize(); + _nativeIrisProxyBinding.setIrisRtcEngineCallApiRecorder(_isMockChannel + // IrisCallApiCallback( + // onCallApi: (int apiType, String params, String result) { + // final apiCall = ApiCall( + // apiType: apiType, + // params: params, + // result: result, + // ); + // // _callApiQueue.add(apiCall); + // return 0; + // }, + // onCallApiWithBuffer: ( + // int apiType, + // String params, + // Pointer buffer, + // String result, + // ) { + // final apiCall = ApiCall( + // apiType: apiType, + // params: params, + // result: result, + // buffer: buffer, + // ); + // // _callApiQueue.add(apiCall); + // return 0; + // }, + // ), + ); + } + + void fireEvent( + String event, + String data, { + Uint8List? buffer, + int bufferSize = 0, + }) { + if (buffer == null) { + _nativeIrisProxyBinding.callIrisProxyEventHandlerOnEvent( + _isMockChannel, event, data); + } else { + _nativeIrisProxyBinding.callIrisProxyEventHandlerOnEventWithBuffer( + _isMockChannel, event, data, buffer, bufferSize); + } + } + + // void triggerEventWithBuffer( + // String event, + // String data, + // Object buffer, + // int length, + // ) { + // _nativeIrisProxyBinding.callIrisProxyEventHandlerOnEventWithBuffer( + // event, + // data, + // buffer, + // length, + // ); + // } + + void dispose() { + // _callApiQueue.clear(); + _nativeIrisProxyBinding.clearCallApiRecorder(); + } + + // List _getCallApiQueue() { + // final queueN = _nativeIrisProxyBinding.getIrisProxyApiCallQueue(); + + // final queue = queueN.ref.apiCallQueue; + // final len = queueN.ref.len; + + // final output = []; + // for (int i = 0; i < len; i++) { + // output.add(queue[i]); + // } + + // return output; + // } + + bool calledApi( + int apiType, + String params, { + Uint8List? buffer, + int bufferSize = 0, + }) { + return _nativeIrisProxyBinding.expectCalledApi( + apiType, + params, + buffer: buffer, + bufferSize: bufferSize, + ); + } + + void mockCallApiResult( + int apiType, + String params, + String mockResult, + ) { + _nativeIrisProxyBinding.mockCallApiResult( + apiType, + params, + mockResult, + ); + } + + void mockCallApiReturnCode( + int apiType, + String params, + int mockReturnCode, + ) { + _nativeIrisProxyBinding.mockCallApiReturnCode( + apiType, + params, + mockReturnCode, + ); + } + + void setExplicitBufferSize( + int apiType, + String params, + int bufferSize, + ) { + _nativeIrisProxyBinding.setExplicitBufferSize( + apiType, + params, + bufferSize, + ); + } + + // Future initForCallApiTest() async { + // await _initialize(); + // _nativeIrisProxyBinding.setIrisRtcEngineCallApiRecorder( + // _isMockChannel, + // ); + // } + + // void disposeForCallApiTest() { + // _nativeIrisProxyBinding.clearCallApiRecorder(_isMockChannel); + // } + + // Future initForEventHandlerTest() async { + // await initialize(); + // _nativeIrisProxyBinding.setIrisProxyEventHandler(_isMockChannel); + // } + + // void disposeForEventHandlerTest() { + // _nativeIrisProxyBinding.destroyIrisProxyEventHandler(_isMockChannel); + // } + + void fireAllEngineEvents() { + _nativeIrisProxyBinding.callRtcEngineEvent(''); + } + + void fireRtcEngineEvent(String event) { + _nativeIrisProxyBinding.callRtcEngineEvent(event); + } + + void fireAllChannelEvents() { + _nativeIrisProxyBinding.callRtcChannelEvent(''); + } + + void fireRtcChannelEvent(String event) { + _nativeIrisProxyBinding.callRtcChannelEvent(event); + } +} + +extension FakeIrisRtcEngineExt on FakeIrisRtcEngine { + void expectCalledApi( + int apiType, + String params, { + Uint8List? buffer, + String result = '', + int bufferSize = 0, + }) { + expect( + calledApi( + apiType, + params, + buffer: buffer, + bufferSize: bufferSize, + ), + isTrue, + ); + } + + Future fireAndWaitEvent( + WidgetTester tester, + String event, + String data, { + Uint8List? buffer, + int bufferSize = 0, + }) async { + fireEvent( + event, + data, + buffer: buffer, + bufferSize: bufferSize, + ); + // // Wait for the `EventChannel` event be sent from Android/iOS side + await tester.pump(const Duration(milliseconds: 500)); + } +} diff --git a/integration_test_app/macos/.gitignore b/integration_test_app/macos/.gitignore new file mode 100644 index 000000000..d2fd37723 --- /dev/null +++ b/integration_test_app/macos/.gitignore @@ -0,0 +1,6 @@ +# Flutter-related +**/Flutter/ephemeral/ +**/Pods/ + +# Xcode-related +**/xcuserdata/ diff --git a/integration_test_app/macos/Flutter/Flutter-Debug.xcconfig b/integration_test_app/macos/Flutter/Flutter-Debug.xcconfig new file mode 100644 index 000000000..4b81f9b2d --- /dev/null +++ b/integration_test_app/macos/Flutter/Flutter-Debug.xcconfig @@ -0,0 +1,2 @@ +#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig" +#include "ephemeral/Flutter-Generated.xcconfig" diff --git a/integration_test_app/macos/Flutter/Flutter-Release.xcconfig b/integration_test_app/macos/Flutter/Flutter-Release.xcconfig new file mode 100644 index 000000000..5caa9d157 --- /dev/null +++ b/integration_test_app/macos/Flutter/Flutter-Release.xcconfig @@ -0,0 +1,2 @@ +#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig" +#include "ephemeral/Flutter-Generated.xcconfig" diff --git a/integration_test_app/macos/Flutter/GeneratedPluginRegistrant.swift b/integration_test_app/macos/Flutter/GeneratedPluginRegistrant.swift new file mode 100644 index 000000000..aaa660f41 --- /dev/null +++ b/integration_test_app/macos/Flutter/GeneratedPluginRegistrant.swift @@ -0,0 +1,12 @@ +// +// Generated file. Do not edit. +// + +import FlutterMacOS +import Foundation + +import agora_rtc_engine + +func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) { + AgoraRtcEnginePlugin.register(with: registry.registrar(forPlugin: "AgoraRtcEnginePlugin")) +} diff --git a/integration_test_app/macos/Podfile b/integration_test_app/macos/Podfile new file mode 100644 index 000000000..f21f5b067 --- /dev/null +++ b/integration_test_app/macos/Podfile @@ -0,0 +1,44 @@ +platform :osx, '10.11' + +# CocoaPods analytics sends network stats synchronously affecting flutter build latency. +ENV['COCOAPODS_DISABLE_STATS'] = 'true' + +project 'Runner', { + 'Debug' => :debug, + 'Profile' => :release, + 'Release' => :release, +} + +def flutter_root + generated_xcode_build_settings_path = File.expand_path(File.join('..', 'Flutter', 'ephemeral', 'Flutter-Generated.xcconfig'), __FILE__) + unless File.exist?(generated_xcode_build_settings_path) + raise "#{generated_xcode_build_settings_path} must exist. If you're running pod install manually, make sure \"flutter pub get\" is executed first" + end + + File.foreach(generated_xcode_build_settings_path) do |line| + matches = line.match(/FLUTTER_ROOT\=(.*)/) + return matches[1].strip if matches + end + raise "FLUTTER_ROOT not found in #{generated_xcode_build_settings_path}. Try deleting Flutter-Generated.xcconfig, then run \"flutter pub get\"" +end + +require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root) + +flutter_macos_podfile_setup + +target 'Runner' do + use_frameworks! + use_modular_headers! + + flutter_install_all_macos_pods File.dirname(File.realpath(__FILE__)) + + # pod 'AgoraRtcWrapper', :path => File.join(File.join('Flutter', 'ephemeral', '.symlinks'), 'plugins', 'agora_rtc_engine', 'macos') + + pod 'iris_integration_test', :path => File.join('Runner') +end + +post_install do |installer| + installer.pods_project.targets.each do |target| + flutter_additional_macos_build_settings(target) + end +end diff --git a/integration_test_app/macos/Runner.xcodeproj/project.pbxproj b/integration_test_app/macos/Runner.xcodeproj/project.pbxproj new file mode 100644 index 000000000..a873d9bd2 --- /dev/null +++ b/integration_test_app/macos/Runner.xcodeproj/project.pbxproj @@ -0,0 +1,619 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 51; + objects = { + +/* Begin PBXAggregateTarget section */ + 33CC111A2044C6BA0003C045 /* Flutter Assemble */ = { + isa = PBXAggregateTarget; + buildConfigurationList = 33CC111B2044C6BA0003C045 /* Build configuration list for PBXAggregateTarget "Flutter Assemble" */; + buildPhases = ( + 33CC111E2044C6BF0003C045 /* ShellScript */, + ); + dependencies = ( + ); + name = "Flutter Assemble"; + productName = FLX; + }; +/* End PBXAggregateTarget section */ + +/* Begin PBXBuildFile section */ + 335BBD1B22A9A15E00E9071D /* GeneratedPluginRegistrant.swift in Sources */ = {isa = PBXBuildFile; fileRef = 335BBD1A22A9A15E00E9071D /* GeneratedPluginRegistrant.swift */; }; + 33CC10F12044A3C60003C045 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 33CC10F02044A3C60003C045 /* AppDelegate.swift */; }; + 33CC10F32044A3C60003C045 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 33CC10F22044A3C60003C045 /* Assets.xcassets */; }; + 33CC10F62044A3C60003C045 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = 33CC10F42044A3C60003C045 /* MainMenu.xib */; }; + 33CC11132044BFA00003C045 /* MainFlutterWindow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 33CC11122044BFA00003C045 /* MainFlutterWindow.swift */; }; + AF9168BCCFEAC05A11BA805F /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = FF3709D5F77AFE09F0DB3F9D /* Pods_Runner.framework */; }; +/* End PBXBuildFile section */ + +/* Begin PBXContainerItemProxy section */ + 33CC111F2044C79F0003C045 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 33CC10E52044A3C60003C045 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 33CC111A2044C6BA0003C045; + remoteInfo = FLX; + }; +/* End PBXContainerItemProxy section */ + +/* Begin PBXFileReference section */ + 108E1031985DB66C8E0AC793 /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = ""; }; + 333000ED22D3DE5D00554162 /* Warnings.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Warnings.xcconfig; sourceTree = ""; }; + 335BBD1A22A9A15E00E9071D /* GeneratedPluginRegistrant.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GeneratedPluginRegistrant.swift; sourceTree = ""; }; + 33CC10ED2044A3C60003C045 /* integration_test_app.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = integration_test_app.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 33CC10F02044A3C60003C045 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; + 33CC10F22044A3C60003C045 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Assets.xcassets; path = Runner/Assets.xcassets; sourceTree = ""; }; + 33CC10F52044A3C60003C045 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/MainMenu.xib; sourceTree = ""; }; + 33CC10F72044A3C60003C045 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; name = Info.plist; path = Runner/Info.plist; sourceTree = ""; }; + 33CC11122044BFA00003C045 /* MainFlutterWindow.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MainFlutterWindow.swift; sourceTree = ""; }; + 33CEB47222A05771004F2AC0 /* Flutter-Debug.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = "Flutter-Debug.xcconfig"; sourceTree = ""; }; + 33CEB47422A05771004F2AC0 /* Flutter-Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = "Flutter-Release.xcconfig"; sourceTree = ""; }; + 33CEB47722A0578A004F2AC0 /* Flutter-Generated.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = "Flutter-Generated.xcconfig"; path = "ephemeral/Flutter-Generated.xcconfig"; sourceTree = ""; }; + 33E51913231747F40026EE4D /* DebugProfile.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = DebugProfile.entitlements; sourceTree = ""; }; + 33E51914231749380026EE4D /* Release.entitlements */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.entitlements; path = Release.entitlements; sourceTree = ""; }; + 33E5194F232828860026EE4D /* AppInfo.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = AppInfo.xcconfig; sourceTree = ""; }; + 463BCEB2E041721F67EEA5A3 /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = ""; }; + 62FB1606E61878BC40813547 /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = ""; }; + 71A12644276C7C4B00AD2013 /* iris_integration_test.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = iris_integration_test.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Release.xcconfig; sourceTree = ""; }; + 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = Debug.xcconfig; sourceTree = ""; }; + FF3709D5F77AFE09F0DB3F9D /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 33CC10EA2044A3C60003C045 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + AF9168BCCFEAC05A11BA805F /* Pods_Runner.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 33BA886A226E78AF003329D5 /* Configs */ = { + isa = PBXGroup; + children = ( + 33E5194F232828860026EE4D /* AppInfo.xcconfig */, + 9740EEB21CF90195004384FC /* Debug.xcconfig */, + 7AFA3C8E1D35360C0083082E /* Release.xcconfig */, + 333000ED22D3DE5D00554162 /* Warnings.xcconfig */, + ); + path = Configs; + sourceTree = ""; + }; + 33CC10E42044A3C60003C045 = { + isa = PBXGroup; + children = ( + 33FAB671232836740065AC1E /* Runner */, + 33CEB47122A05771004F2AC0 /* Flutter */, + 33CC10EE2044A3C60003C045 /* Products */, + D73912EC22F37F3D000D13A0 /* Frameworks */, + C052A088D7A9666A0925560E /* Pods */, + ); + sourceTree = ""; + }; + 33CC10EE2044A3C60003C045 /* Products */ = { + isa = PBXGroup; + children = ( + 33CC10ED2044A3C60003C045 /* integration_test_app.app */, + ); + name = Products; + sourceTree = ""; + }; + 33CC11242044D66E0003C045 /* Resources */ = { + isa = PBXGroup; + children = ( + 33CC10F22044A3C60003C045 /* Assets.xcassets */, + 33CC10F42044A3C60003C045 /* MainMenu.xib */, + 33CC10F72044A3C60003C045 /* Info.plist */, + ); + name = Resources; + path = ..; + sourceTree = ""; + }; + 33CEB47122A05771004F2AC0 /* Flutter */ = { + isa = PBXGroup; + children = ( + 335BBD1A22A9A15E00E9071D /* GeneratedPluginRegistrant.swift */, + 33CEB47222A05771004F2AC0 /* Flutter-Debug.xcconfig */, + 33CEB47422A05771004F2AC0 /* Flutter-Release.xcconfig */, + 33CEB47722A0578A004F2AC0 /* Flutter-Generated.xcconfig */, + ); + path = Flutter; + sourceTree = ""; + }; + 33FAB671232836740065AC1E /* Runner */ = { + isa = PBXGroup; + children = ( + 33CC10F02044A3C60003C045 /* AppDelegate.swift */, + 33CC11122044BFA00003C045 /* MainFlutterWindow.swift */, + 33E51913231747F40026EE4D /* DebugProfile.entitlements */, + 33E51914231749380026EE4D /* Release.entitlements */, + 33CC11242044D66E0003C045 /* Resources */, + 33BA886A226E78AF003329D5 /* Configs */, + ); + path = Runner; + sourceTree = ""; + }; + C052A088D7A9666A0925560E /* Pods */ = { + isa = PBXGroup; + children = ( + 108E1031985DB66C8E0AC793 /* Pods-Runner.debug.xcconfig */, + 62FB1606E61878BC40813547 /* Pods-Runner.release.xcconfig */, + 463BCEB2E041721F67EEA5A3 /* Pods-Runner.profile.xcconfig */, + ); + path = Pods; + sourceTree = ""; + }; + D73912EC22F37F3D000D13A0 /* Frameworks */ = { + isa = PBXGroup; + children = ( + 71A12644276C7C4B00AD2013 /* iris_integration_test.framework */, + FF3709D5F77AFE09F0DB3F9D /* Pods_Runner.framework */, + ); + name = Frameworks; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 33CC10EC2044A3C60003C045 /* Runner */ = { + isa = PBXNativeTarget; + buildConfigurationList = 33CC10FB2044A3C60003C045 /* Build configuration list for PBXNativeTarget "Runner" */; + buildPhases = ( + F4C950CECF993D6F9B685CB4 /* [CP] Check Pods Manifest.lock */, + 33CC10E92044A3C60003C045 /* Sources */, + 33CC10EA2044A3C60003C045 /* Frameworks */, + 33CC10EB2044A3C60003C045 /* Resources */, + 3399D490228B24CF009A79C7 /* ShellScript */, + 99621D7EBF3810D0428DF616 /* [CP] Embed Pods Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + 33CC11202044C79F0003C045 /* PBXTargetDependency */, + ); + name = Runner; + productName = Runner; + productReference = 33CC10ED2044A3C60003C045 /* integration_test_app.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 33CC10E52044A3C60003C045 /* Project object */ = { + isa = PBXProject; + attributes = { + LastSwiftUpdateCheck = 0920; + LastUpgradeCheck = 0930; + ORGANIZATIONNAME = ""; + TargetAttributes = { + 33CC10EC2044A3C60003C045 = { + CreatedOnToolsVersion = 9.2; + LastSwiftMigration = 1100; + ProvisioningStyle = Automatic; + SystemCapabilities = { + com.apple.Sandbox = { + enabled = 1; + }; + }; + }; + 33CC111A2044C6BA0003C045 = { + CreatedOnToolsVersion = 9.2; + ProvisioningStyle = Manual; + }; + }; + }; + buildConfigurationList = 33CC10E82044A3C60003C045 /* Build configuration list for PBXProject "Runner" */; + compatibilityVersion = "Xcode 9.3"; + developmentRegion = en; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 33CC10E42044A3C60003C045; + productRefGroup = 33CC10EE2044A3C60003C045 /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 33CC10EC2044A3C60003C045 /* Runner */, + 33CC111A2044C6BA0003C045 /* Flutter Assemble */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 33CC10EB2044A3C60003C045 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 33CC10F32044A3C60003C045 /* Assets.xcassets in Resources */, + 33CC10F62044A3C60003C045 /* MainMenu.xib in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXShellScriptBuildPhase section */ + 3399D490228B24CF009A79C7 /* ShellScript */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + ); + outputFileListPaths = ( + ); + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "echo \"$PRODUCT_NAME.app\" > \"$PROJECT_DIR\"/Flutter/ephemeral/.app_filename && \"$FLUTTER_ROOT\"/packages/flutter_tools/bin/macos_assemble.sh embed\n"; + }; + 33CC111E2044C6BF0003C045 /* ShellScript */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + Flutter/ephemeral/FlutterInputs.xcfilelist, + ); + inputPaths = ( + Flutter/ephemeral/tripwire, + ); + outputFileListPaths = ( + Flutter/ephemeral/FlutterOutputs.xcfilelist, + ); + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"$FLUTTER_ROOT\"/packages/flutter_tools/bin/macos_assemble.sh && touch Flutter/ephemeral/tripwire"; + }; + 99621D7EBF3810D0428DF616 /* [CP] Embed Pods Frameworks */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-input-files.xcfilelist", + ); + name = "[CP] Embed Pods Frameworks"; + outputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-output-files.xcfilelist", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n"; + showEnvVarsInLog = 0; + }; + F4C950CECF993D6F9B685CB4 /* [CP] Check Pods Manifest.lock */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", + ); + name = "[CP] Check Pods Manifest.lock"; + outputFileListPaths = ( + ); + outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; + showEnvVarsInLog = 0; + }; +/* End PBXShellScriptBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 33CC10E92044A3C60003C045 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 33CC11132044BFA00003C045 /* MainFlutterWindow.swift in Sources */, + 33CC10F12044A3C60003C045 /* AppDelegate.swift in Sources */, + 335BBD1B22A9A15E00E9071D /* GeneratedPluginRegistrant.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXTargetDependency section */ + 33CC11202044C79F0003C045 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 33CC111A2044C6BA0003C045 /* Flutter Assemble */; + targetProxy = 33CC111F2044C79F0003C045 /* PBXContainerItemProxy */; + }; +/* End PBXTargetDependency section */ + +/* Begin PBXVariantGroup section */ + 33CC10F42044A3C60003C045 /* MainMenu.xib */ = { + isa = PBXVariantGroup; + children = ( + 33CC10F52044A3C60003C045 /* Base */, + ); + name = MainMenu.xib; + path = Runner; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + 338D0CE9231458BD00FA5F75 /* Profile */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CODE_SIGN_IDENTITY = "-"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.11; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = macosx; + SWIFT_COMPILATION_MODE = wholemodule; + SWIFT_OPTIMIZATION_LEVEL = "-O"; + }; + name = Profile; + }; + 338D0CEA231458BD00FA5F75 /* Profile */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 33E5194F232828860026EE4D /* AppInfo.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CODE_SIGN_ENTITLEMENTS = Runner/DebugProfile.entitlements; + CODE_SIGN_STYLE = Automatic; + COMBINE_HIDPI_IMAGES = YES; + INFOPLIST_FILE = Runner/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/../Frameworks", + ); + PROVISIONING_PROFILE_SPECIFIER = ""; + SWIFT_VERSION = 5.0; + }; + name = Profile; + }; + 338D0CEB231458BD00FA5F75 /* Profile */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_STYLE = Manual; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Profile; + }; + 33CC10F92044A3C60003C045 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CODE_SIGN_IDENTITY = "-"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.11; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = macosx; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + }; + name = Debug; + }; + 33CC10FA2044A3C60003C045 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CODE_SIGN_IDENTITY = "-"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.11; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = macosx; + SWIFT_COMPILATION_MODE = wholemodule; + SWIFT_OPTIMIZATION_LEVEL = "-O"; + }; + name = Release; + }; + 33CC10FC2044A3C60003C045 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 33E5194F232828860026EE4D /* AppInfo.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CODE_SIGN_ENTITLEMENTS = Runner/DebugProfile.entitlements; + CODE_SIGN_STYLE = Automatic; + COMBINE_HIDPI_IMAGES = YES; + INFOPLIST_FILE = Runner/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/../Frameworks", + ); + PROVISIONING_PROFILE_SPECIFIER = ""; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 5.0; + }; + name = Debug; + }; + 33CC10FD2044A3C60003C045 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 33E5194F232828860026EE4D /* AppInfo.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CODE_SIGN_ENTITLEMENTS = Runner/Release.entitlements; + CODE_SIGN_STYLE = Automatic; + COMBINE_HIDPI_IMAGES = YES; + INFOPLIST_FILE = Runner/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/../Frameworks", + ); + PROVISIONING_PROFILE_SPECIFIER = ""; + SWIFT_VERSION = 5.0; + }; + name = Release; + }; + 33CC111C2044C6BA0003C045 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_STYLE = Manual; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Debug; + }; + 33CC111D2044C6BA0003C045 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_STYLE = Automatic; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 33CC10E82044A3C60003C045 /* Build configuration list for PBXProject "Runner" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 33CC10F92044A3C60003C045 /* Debug */, + 33CC10FA2044A3C60003C045 /* Release */, + 338D0CE9231458BD00FA5F75 /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 33CC10FB2044A3C60003C045 /* Build configuration list for PBXNativeTarget "Runner" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 33CC10FC2044A3C60003C045 /* Debug */, + 33CC10FD2044A3C60003C045 /* Release */, + 338D0CEA231458BD00FA5F75 /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 33CC111B2044C6BA0003C045 /* Build configuration list for PBXAggregateTarget "Flutter Assemble" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 33CC111C2044C6BA0003C045 /* Debug */, + 33CC111D2044C6BA0003C045 /* Release */, + 338D0CEB231458BD00FA5F75 /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 33CC10E52044A3C60003C045 /* Project object */; +} diff --git a/integration_test_app/macos/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/integration_test_app/macos/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 000000000..18d981003 --- /dev/null +++ b/integration_test_app/macos/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/integration_test_app/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/integration_test_app/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme new file mode 100644 index 000000000..9ff338a0b --- /dev/null +++ b/integration_test_app/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme @@ -0,0 +1,89 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/integration_test_app/macos/Runner.xcworkspace/contents.xcworkspacedata b/integration_test_app/macos/Runner.xcworkspace/contents.xcworkspacedata new file mode 100644 index 000000000..21a3cc14c --- /dev/null +++ b/integration_test_app/macos/Runner.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,10 @@ + + + + + + + diff --git a/integration_test_app/macos/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/integration_test_app/macos/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 000000000..18d981003 --- /dev/null +++ b/integration_test_app/macos/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/integration_test_app/macos/Runner/AppDelegate.swift b/integration_test_app/macos/Runner/AppDelegate.swift new file mode 100644 index 000000000..d53ef6437 --- /dev/null +++ b/integration_test_app/macos/Runner/AppDelegate.swift @@ -0,0 +1,9 @@ +import Cocoa +import FlutterMacOS + +@NSApplicationMain +class AppDelegate: FlutterAppDelegate { + override func applicationShouldTerminateAfterLastWindowClosed(_ sender: NSApplication) -> Bool { + return true + } +} diff --git a/integration_test_app/macos/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json b/integration_test_app/macos/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 000000000..a2ec33f19 --- /dev/null +++ b/integration_test_app/macos/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,68 @@ +{ + "images" : [ + { + "size" : "16x16", + "idiom" : "mac", + "filename" : "app_icon_16.png", + "scale" : "1x" + }, + { + "size" : "16x16", + "idiom" : "mac", + "filename" : "app_icon_32.png", + "scale" : "2x" + }, + { + "size" : "32x32", + "idiom" : "mac", + "filename" : "app_icon_32.png", + "scale" : "1x" + }, + { + "size" : "32x32", + "idiom" : "mac", + "filename" : "app_icon_64.png", + "scale" : "2x" + }, + { + "size" : "128x128", + "idiom" : "mac", + "filename" : "app_icon_128.png", + "scale" : "1x" + }, + { + "size" : "128x128", + "idiom" : "mac", + "filename" : "app_icon_256.png", + "scale" : "2x" + }, + { + "size" : "256x256", + "idiom" : "mac", + "filename" : "app_icon_256.png", + "scale" : "1x" + }, + { + "size" : "256x256", + "idiom" : "mac", + "filename" : "app_icon_512.png", + "scale" : "2x" + }, + { + "size" : "512x512", + "idiom" : "mac", + "filename" : "app_icon_512.png", + "scale" : "1x" + }, + { + "size" : "512x512", + "idiom" : "mac", + "filename" : "app_icon_1024.png", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} diff --git a/integration_test_app/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_1024.png b/integration_test_app/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_1024.png new file mode 100644 index 0000000000000000000000000000000000000000..3c4935a7ca84f0976aca34b7f2895d65fb94d1ea GIT binary patch literal 46993 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 literal 0 HcmV?d00001 diff --git a/integration_test_app/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_128.png b/integration_test_app/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_128.png new file mode 100644 index 0000000000000000000000000000000000000000..ed4cc16421680a50164ba74381b4b35ceaa0ccfc GIT binary patch literal 3276 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 N;OXk;vd$@?2>?>Ex^Vyi literal 0 HcmV?d00001 diff --git a/integration_test_app/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_256.png b/integration_test_app/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_256.png new file mode 100644 index 0000000000000000000000000000000000000000..bcbf36df2f2aaaa0a63c7dabc94e600184229d0d GIT binary patch literal 5933 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 f$KZHO*s&vt|9^w-6P?|#0pRK8NSwWJ?9znhg z3{`3j3=J&|48MRv4KElNN(~qoUL`OvSj}Ky5HFasE6@fg!ItFh?!xdN1Q+aGJ{c&& zS>O>_%)r1c48n{Iv*t(u1=&kHeO=ifbFy+6aSK)V_AxLppYn8Z42d|rc6w}vOsL55 z`t&mC&y2@JTEyg!eDiFX^k#CC!jq%>erB=yHqUP0XcDOTw6ko}L zX;EmMrq(fKk*eygEuA616;0)>@A{TK|55PV@70 z$OfzS*(VJxQev3J?yY?O=ul(v`fp}?u9z`JK3ugibK>)DyCwImZOF4d{xK%%Ks1*} zv$oa)9anR%lXIBUqYnhLmT>VOzHfNP?ZwJNZ!5$s9M08RynIvaXw>@G^T9@r9^KH1 zVy??F&uuk)bH9Y4pQY!hP58i_H6 znl-NcuCpLV6ZWU;4C zu@9exF&OZi`Bovq_m%T+WhU2kvkz@^_LpycBvqm3bMpLw8X-Or5sL>0AKE1$(k_L=_Zc=CUq#=x1-QZf)G7nHu@fmsQ1eN_N3+nTEz`4HI4Z6uVlE zJH+X&det8JU?tO?upcM4Z=cV!JV;yF>FfL5Q$M|W_2Z!P`S=}Wzp|_1^#d%e?_H`> zV@%vA$+bFVqhw9`U;TfP|5|PD{||OiYdor8P*i??|NJcb%kzT_73*7WE?Ua5hAnR2 z=7WE=PhTlJ#ZeRznjTUb;`E(wkMZrj4e|Hilz-mK>9cZHQY**5TUPw~u}k;u73KI}xAx!0m-)GVia|x^d3p~s_9gh83jA&Ra<8rM%`>U3x69t&NzbwWY}7Ar?)FK#IZ0z|d0H0EkRO w3{9;}4Xg|ebq&m|3=9_N6z8I7$jwj5OsmAL;bP(Gi$Dzwp00i_>zopr02+f8CIA2c literal 0 HcmV?d00001 diff --git a/integration_test_app/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_512.png b/integration_test_app/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_512.png new file mode 100644 index 0000000000000000000000000000000000000000..e71a726136a47ed24125c7efc79d68a4a01961b4 GIT binary patch literal 14800 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 + + + + + + + + + + + + + + + + + + + + + +
        + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/integration_test_app/macos/Runner/Configs/AppInfo.xcconfig b/integration_test_app/macos/Runner/Configs/AppInfo.xcconfig new file mode 100644 index 000000000..50a0dd07c --- /dev/null +++ b/integration_test_app/macos/Runner/Configs/AppInfo.xcconfig @@ -0,0 +1,14 @@ +// Application-level settings for the Runner target. +// +// This may be replaced with something auto-generated from metadata (e.g., pubspec.yaml) in the +// future. If not, the values below would default to using the project name when this becomes a +// 'flutter create' template. + +// The application's name. By default this is also the title of the Flutter window. +PRODUCT_NAME = integration_test_app + +// The application's bundle identifier +PRODUCT_BUNDLE_IDENTIFIER = io.agora.integrationtestapp.integrationTestApp + +// The copyright displayed in application information +PRODUCT_COPYRIGHT = Copyright © 2021 io.agora.integration_test_app. All rights reserved. diff --git a/integration_test_app/macos/Runner/Configs/Debug.xcconfig b/integration_test_app/macos/Runner/Configs/Debug.xcconfig new file mode 100644 index 000000000..36b0fd946 --- /dev/null +++ b/integration_test_app/macos/Runner/Configs/Debug.xcconfig @@ -0,0 +1,2 @@ +#include "../../Flutter/Flutter-Debug.xcconfig" +#include "Warnings.xcconfig" diff --git a/integration_test_app/macos/Runner/Configs/Release.xcconfig b/integration_test_app/macos/Runner/Configs/Release.xcconfig new file mode 100644 index 000000000..dff4f4956 --- /dev/null +++ b/integration_test_app/macos/Runner/Configs/Release.xcconfig @@ -0,0 +1,2 @@ +#include "../../Flutter/Flutter-Release.xcconfig" +#include "Warnings.xcconfig" diff --git a/integration_test_app/macos/Runner/Configs/Warnings.xcconfig b/integration_test_app/macos/Runner/Configs/Warnings.xcconfig new file mode 100644 index 000000000..42bcbf478 --- /dev/null +++ b/integration_test_app/macos/Runner/Configs/Warnings.xcconfig @@ -0,0 +1,13 @@ +WARNING_CFLAGS = -Wall -Wconditional-uninitialized -Wnullable-to-nonnull-conversion -Wmissing-method-return-type -Woverlength-strings +GCC_WARN_UNDECLARED_SELECTOR = YES +CLANG_UNDEFINED_BEHAVIOR_SANITIZER_NULLABILITY = YES +CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE +CLANG_WARN__DUPLICATE_METHOD_MATCH = YES +CLANG_WARN_PRAGMA_PACK = YES +CLANG_WARN_STRICT_PROTOTYPES = YES +CLANG_WARN_COMMA = YES +GCC_WARN_STRICT_SELECTOR_MATCH = YES +CLANG_WARN_OBJC_REPEATED_USE_OF_WEAK = YES +CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES +GCC_WARN_SHADOW = YES +CLANG_WARN_UNREACHABLE_CODE = YES diff --git a/integration_test_app/macos/Runner/DebugProfile.entitlements b/integration_test_app/macos/Runner/DebugProfile.entitlements new file mode 100644 index 000000000..0c64b565f --- /dev/null +++ b/integration_test_app/macos/Runner/DebugProfile.entitlements @@ -0,0 +1,20 @@ + + + + + com.apple.security.app-sandbox + + com.apple.security.application-groups + + io.agora + + com.apple.security.cs.allow-jit + + com.apple.security.device.audio-input + + com.apple.security.device.camera + + com.apple.security.network.server + + + diff --git a/integration_test_app/macos/Runner/Info.plist b/integration_test_app/macos/Runner/Info.plist new file mode 100644 index 000000000..b9506b595 --- /dev/null +++ b/integration_test_app/macos/Runner/Info.plist @@ -0,0 +1,36 @@ + + + + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIconFile + + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + APPL + CFBundleShortVersionString + $(FLUTTER_BUILD_NAME) + CFBundleVersion + $(FLUTTER_BUILD_NUMBER) + LSMinimumSystemVersion + $(MACOSX_DEPLOYMENT_TARGET) + NSCameraUsageDescription + Camera + NSHumanReadableCopyright + $(PRODUCT_COPYRIGHT) + NSMainNibFile + MainMenu + NSMicrophoneUsageDescription + Microphone + NSPrincipalClass + NSApplication + + diff --git a/integration_test_app/macos/Runner/MainFlutterWindow.swift b/integration_test_app/macos/Runner/MainFlutterWindow.swift new file mode 100644 index 000000000..2722837ec --- /dev/null +++ b/integration_test_app/macos/Runner/MainFlutterWindow.swift @@ -0,0 +1,15 @@ +import Cocoa +import FlutterMacOS + +class MainFlutterWindow: NSWindow { + override func awakeFromNib() { + let flutterViewController = FlutterViewController.init() + let windowFrame = self.frame + self.contentViewController = flutterViewController + self.setFrame(windowFrame, display: true) + + RegisterGeneratedPlugins(registry: flutterViewController) + + super.awakeFromNib() + } +} diff --git a/integration_test_app/macos/Runner/Release.entitlements b/integration_test_app/macos/Runner/Release.entitlements new file mode 100644 index 000000000..a1ca10bfb --- /dev/null +++ b/integration_test_app/macos/Runner/Release.entitlements @@ -0,0 +1,18 @@ + + + + + com.apple.security.app-sandbox + + com.apple.security.application-groups + + io.agora + + com.apple.security.device.audio-input + + com.apple.security.device.camera + + com.apple.security.network.server + + + diff --git a/integration_test_app/macos/Runner/iris_integration_test.framework/Resources/Info.plist b/integration_test_app/macos/Runner/iris_integration_test.framework/Resources/Info.plist new file mode 100644 index 000000000..7ed3ef13a --- /dev/null +++ b/integration_test_app/macos/Runner/iris_integration_test.framework/Resources/Info.plist @@ -0,0 +1,44 @@ + + + + + BuildMachineOSBuild + 21D49 + CFBundleDevelopmentRegion + English + CFBundleExecutable + iris_integration_test + CFBundleIdentifier + io.agora.iris.it + CFBundleInfoDictionaryVersion + 6.0 + CFBundlePackageType + FMWK + CFBundleSignature + ???? + CFBundleSupportedPlatforms + + MacOSX + + CSResourcesFileMapped + + DTCompiler + com.apple.compilers.llvm.clang.1_0 + DTPlatformBuild + 13C100 + DTPlatformName + macosx + DTPlatformVersion + 12.1 + DTSDKBuild + 21C46 + DTSDKName + macosx12.1 + DTXcode + 1321 + DTXcodeBuild + 13C100 + LSMinimumSystemVersion + 12.1 + + diff --git a/integration_test_app/macos/Runner/iris_integration_test.framework/Versions/A/Resources/Info.plist b/integration_test_app/macos/Runner/iris_integration_test.framework/Versions/A/Resources/Info.plist new file mode 100644 index 000000000..7ed3ef13a --- /dev/null +++ b/integration_test_app/macos/Runner/iris_integration_test.framework/Versions/A/Resources/Info.plist @@ -0,0 +1,44 @@ + + + + + BuildMachineOSBuild + 21D49 + CFBundleDevelopmentRegion + English + CFBundleExecutable + iris_integration_test + CFBundleIdentifier + io.agora.iris.it + CFBundleInfoDictionaryVersion + 6.0 + CFBundlePackageType + FMWK + CFBundleSignature + ???? + CFBundleSupportedPlatforms + + MacOSX + + CSResourcesFileMapped + + DTCompiler + com.apple.compilers.llvm.clang.1_0 + DTPlatformBuild + 13C100 + DTPlatformName + macosx + DTPlatformVersion + 12.1 + DTSDKBuild + 21C46 + DTSDKName + macosx12.1 + DTXcode + 1321 + DTXcodeBuild + 13C100 + LSMinimumSystemVersion + 12.1 + + diff --git a/integration_test_app/macos/Runner/iris_integration_test.framework/Versions/A/_CodeSignature/CodeResources b/integration_test_app/macos/Runner/iris_integration_test.framework/Versions/A/_CodeSignature/CodeResources new file mode 100644 index 000000000..7fd0fbc6a --- /dev/null +++ b/integration_test_app/macos/Runner/iris_integration_test.framework/Versions/A/_CodeSignature/CodeResources @@ -0,0 +1,128 @@ + + + + + files + + Resources/Info.plist + + 2itecuO6+P2rO8F4hP5GHSVvY+o= + + + files2 + + Resources/Info.plist + + hash2 + + INmOxX68n+vzrF8tKUa/TVvrOVYbnGwut9dRH70/esU= + + + + rules + + ^Resources/ + + ^Resources/.*\.lproj/ + + optional + + weight + 1000 + + ^Resources/.*\.lproj/locversion.plist$ + + omit + + weight + 1100 + + ^Resources/Base\.lproj/ + + weight + 1010 + + ^version.plist$ + + + rules2 + + .*\.dSYM($|/) + + weight + 11 + + ^(.*/)?\.DS_Store$ + + omit + + weight + 2000 + + ^(Frameworks|SharedFrameworks|PlugIns|Plug-ins|XPCServices|Helpers|MacOS|Library/(Automator|Spotlight|LoginItems))/ + + nested + + weight + 10 + + ^.* + + ^Info\.plist$ + + omit + + weight + 20 + + ^PkgInfo$ + + omit + + weight + 20 + + ^Resources/ + + weight + 20 + + ^Resources/.*\.lproj/ + + optional + + weight + 1000 + + ^Resources/.*\.lproj/locversion.plist$ + + omit + + weight + 1100 + + ^Resources/Base\.lproj/ + + weight + 1010 + + ^[^/]+$ + + nested + + weight + 10 + + ^embedded\.provisionprofile$ + + weight + 20 + + ^version\.plist$ + + weight + 20 + + + + diff --git a/integration_test_app/macos/Runner/iris_integration_test.framework/Versions/A/iris_integration_test b/integration_test_app/macos/Runner/iris_integration_test.framework/Versions/A/iris_integration_test new file mode 100755 index 0000000000000000000000000000000000000000..55babffb2cdc4d4262f3a43d1fcb075acf08747e GIT binary patch literal 338416 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 literal 0 HcmV?d00001 diff --git a/integration_test_app/macos/Runner/iris_integration_test.framework/Versions/Current/Resources/Info.plist b/integration_test_app/macos/Runner/iris_integration_test.framework/Versions/Current/Resources/Info.plist new file mode 100644 index 000000000..7ed3ef13a --- /dev/null +++ b/integration_test_app/macos/Runner/iris_integration_test.framework/Versions/Current/Resources/Info.plist @@ -0,0 +1,44 @@ + + + + + BuildMachineOSBuild + 21D49 + CFBundleDevelopmentRegion + English + CFBundleExecutable + iris_integration_test + CFBundleIdentifier + io.agora.iris.it + CFBundleInfoDictionaryVersion + 6.0 + CFBundlePackageType + FMWK + CFBundleSignature + ???? + CFBundleSupportedPlatforms + + MacOSX + + CSResourcesFileMapped + + DTCompiler + com.apple.compilers.llvm.clang.1_0 + DTPlatformBuild + 13C100 + DTPlatformName + macosx + DTPlatformVersion + 12.1 + DTSDKBuild + 21C46 + DTSDKName + macosx12.1 + DTXcode + 1321 + DTXcodeBuild + 13C100 + LSMinimumSystemVersion + 12.1 + + diff --git a/integration_test_app/macos/Runner/iris_integration_test.framework/Versions/Current/_CodeSignature/CodeResources b/integration_test_app/macos/Runner/iris_integration_test.framework/Versions/Current/_CodeSignature/CodeResources new file mode 100644 index 000000000..7fd0fbc6a --- /dev/null +++ b/integration_test_app/macos/Runner/iris_integration_test.framework/Versions/Current/_CodeSignature/CodeResources @@ -0,0 +1,128 @@ + + + + + files + + Resources/Info.plist + + 2itecuO6+P2rO8F4hP5GHSVvY+o= + + + files2 + + Resources/Info.plist + + hash2 + + INmOxX68n+vzrF8tKUa/TVvrOVYbnGwut9dRH70/esU= + + + + rules + + ^Resources/ + + ^Resources/.*\.lproj/ + + optional + + weight + 1000 + + ^Resources/.*\.lproj/locversion.plist$ + + omit + + weight + 1100 + + ^Resources/Base\.lproj/ + + weight + 1010 + + ^version.plist$ + + + rules2 + + .*\.dSYM($|/) + + weight + 11 + + ^(.*/)?\.DS_Store$ + + omit + + weight + 2000 + + ^(Frameworks|SharedFrameworks|PlugIns|Plug-ins|XPCServices|Helpers|MacOS|Library/(Automator|Spotlight|LoginItems))/ + + nested + + weight + 10 + + ^.* + + ^Info\.plist$ + + omit + + weight + 20 + + ^PkgInfo$ + + omit + + weight + 20 + + ^Resources/ + + weight + 20 + + ^Resources/.*\.lproj/ + + optional + + weight + 1000 + + ^Resources/.*\.lproj/locversion.plist$ + + omit + + weight + 1100 + + ^Resources/Base\.lproj/ + + weight + 1010 + + ^[^/]+$ + + nested + + weight + 10 + + ^embedded\.provisionprofile$ + + weight + 20 + + ^version\.plist$ + + weight + 20 + + + + diff --git a/integration_test_app/macos/Runner/iris_integration_test.framework/Versions/Current/iris_integration_test b/integration_test_app/macos/Runner/iris_integration_test.framework/Versions/Current/iris_integration_test new file mode 100755 index 0000000000000000000000000000000000000000..55babffb2cdc4d4262f3a43d1fcb075acf08747e GIT binary patch literal 338416 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 literal 0 HcmV?d00001 diff --git a/integration_test_app/macos/Runner/iris_integration_test.framework/iris_integration_test b/integration_test_app/macos/Runner/iris_integration_test.framework/iris_integration_test new file mode 100755 index 0000000000000000000000000000000000000000..55babffb2cdc4d4262f3a43d1fcb075acf08747e GIT binary patch literal 338416 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 literal 0 HcmV?d00001 diff --git a/integration_test_app/macos/Runner/iris_integration_test.podspec b/integration_test_app/macos/Runner/iris_integration_test.podspec new file mode 100644 index 000000000..2f8a42455 --- /dev/null +++ b/integration_test_app/macos/Runner/iris_integration_test.podspec @@ -0,0 +1,17 @@ +# +# To learn more about a Podspec see http://guides.cocoapods.org/syntax/podspec.html. +# Run `pod lib lint agora_rtc_engine.podspec` to validate before publishing. +# + +Pod::Spec.new do |s| + s.name = 'iris_integration_test' + s.version = '3.3.1' + s.summary = 'A new flutter plugin project.' + s.description = 'project.description' + s.homepage = 'https://github.com/AgoraIO/Flutter-SDK' + s.license = { :file => '../LICENSE' } + s.author = { 'Agora' => 'developer@agora.io' } + s.source = { :path => '.' } + s.vendored_frameworks = 'iris_integration_test.framework' + s.platform = :osx, '9.0' +end diff --git a/integration_test_app/macos/Runner/src b/integration_test_app/macos/Runner/src new file mode 120000 index 000000000..c9fe6b25a --- /dev/null +++ b/integration_test_app/macos/Runner/src @@ -0,0 +1 @@ +C:/Users/fenglang/codes/aw/Agora-Flutter/integration_test_app/iris_integration_test/src \ No newline at end of file diff --git a/integration_test_app/pubspec.yaml b/integration_test_app/pubspec.yaml new file mode 100644 index 000000000..ab17e122d --- /dev/null +++ b/integration_test_app/pubspec.yaml @@ -0,0 +1,92 @@ +name: integration_test_app +description: A new Flutter project. + +# The following line prevents the package from being accidentally published to +# pub.dev using `flutter pub publish`. This is preferred for private packages. +publish_to: 'none' # Remove this line if you wish to publish to pub.dev + +# The following defines the version and build number for your application. +# A version number is three numbers separated by dots, like 1.2.43 +# followed by an optional build number separated by a +. +# Both the version and the builder number may be overridden in flutter +# build by specifying --build-name and --build-number, respectively. +# In Android, build-name is used as versionName while build-number used as versionCode. +# Read more about Android versioning at https://developer.android.com/studio/publish/versioning +# In iOS, build-name is used as CFBundleShortVersionString while build-number used as CFBundleVersion. +# Read more about iOS versioning at +# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html +version: 1.0.0+1 + +environment: + sdk: ">=2.12.0 <3.0.0" + +# Dependencies specify other packages that your package needs in order to work. +# To automatically upgrade your package dependencies to the latest versions +# consider running `flutter pub upgrade --major-versions`. Alternatively, +# dependencies can be manually updated by changing the version numbers below to +# the latest version available on pub.dev. To see which dependencies have newer +# versions available, run `flutter pub outdated`. +dependencies: + flutter: + sdk: flutter + analyzer: ^2.4.0 + path: ^1.8.0 + ffi: ^1.1.2 + agora_rtc_engine: + path: ../ + +dev_dependencies: + integration_test: + sdk: flutter + flutter_test: + sdk: flutter + + # The "flutter_lints" package below contains a set of recommended lints to + # encourage good coding practices. The lint set provided by the package is + # activated in the `analysis_options.yaml` file located at the root of your + # package. See that file for information about deactivating specific lint + # rules and activating additional ones. + flutter_lints: ^1.0.0 + + +# For information on the generic Dart part of this file, see the +# following page: https://dart.dev/tools/pub/pubspec + +# The following section is specific to Flutter. +flutter: + + # The following line ensures that the Material Icons font is + # included with your application, so that you can use the icons in + # the material Icons class. + uses-material-design: true + + # To add assets to your application, add an assets section, like this: + # assets: + # - images/a_dot_burr.jpeg + # - images/a_dot_ham.jpeg + + # An image asset can refer to one or more resolution-specific "variants", see + # https://flutter.dev/assets-and-images/#resolution-aware. + + # For details regarding adding assets from package dependencies, see + # https://flutter.dev/assets-and-images/#from-packages + + # To add custom fonts to your application, add a fonts section here, + # in this "flutter" section. Each entry in this list should have a + # "family" key with the font family name, and a "fonts" key with a + # list giving the asset and other descriptors for the font. For + # example: + # fonts: + # - family: Schyler + # fonts: + # - asset: fonts/Schyler-Regular.ttf + # - asset: fonts/Schyler-Italic.ttf + # style: italic + # - family: Trajan Pro + # fonts: + # - asset: fonts/TrajanPro.ttf + # - asset: fonts/TrajanPro_Bold.ttf + # weight: 700 + # + # For details regarding fonts from package dependencies, + # see https://flutter.dev/custom-fonts/#from-packages diff --git a/integration_test_app/test/widget_test.dart b/integration_test_app/test/widget_test.dart new file mode 100644 index 000000000..72dbf30c7 --- /dev/null +++ b/integration_test_app/test/widget_test.dart @@ -0,0 +1,30 @@ +// This is a basic Flutter widget test. +// +// To perform an interaction with a widget in your test, use the WidgetTester +// utility that Flutter provides. For example, you can send tap and scroll +// gestures. You can also use WidgetTester to find child widgets in the widget +// tree, read text, and verify that the values of widget properties are correct. + +import 'package:flutter/material.dart'; +import 'package:flutter_test/flutter_test.dart'; + +import 'package:integration_test_app/main.dart'; + +void main() { + testWidgets('Counter increments smoke test', (WidgetTester tester) async { + // Build our app and trigger a frame. + await tester.pumpWidget(const MyApp()); + + // Verify that our counter starts at 0. + expect(find.text('0'), findsOneWidget); + expect(find.text('1'), findsNothing); + + // Tap the '+' icon and trigger a frame. + await tester.tap(find.byIcon(Icons.add)); + await tester.pump(); + + // Verify that our counter has incremented. + expect(find.text('0'), findsNothing); + expect(find.text('1'), findsOneWidget); + }); +} diff --git a/integration_test_app/tools/integration_test_cases_generator.dart b/integration_test_app/tools/integration_test_cases_generator.dart new file mode 100644 index 000000000..26b297637 --- /dev/null +++ b/integration_test_app/tools/integration_test_cases_generator.dart @@ -0,0 +1,1337 @@ +import 'dart:io'; + +import 'package:analyzer/dart/analysis/analysis_context.dart'; +import 'package:analyzer/dart/analysis/analysis_context_collection.dart' + show AnalysisContextCollection; +import 'package:analyzer/dart/analysis/results.dart' show ParsedUnitResult; +import 'package:analyzer/dart/analysis/session.dart' show AnalysisSession; +import 'package:analyzer/dart/ast/ast.dart'; +import 'package:analyzer/dart/ast/ast.dart' as dart_ast; +import 'package:analyzer/dart/ast/visitor.dart' as dart_ast_visitor; +import 'package:analyzer/dart/element/type.dart'; +import 'package:analyzer/error/error.dart' show AnalysisError; +import 'package:file/file.dart' as file; +import 'package:file/local.dart'; +import 'package:path/path.dart' as path; + +class CallApiInvoke { + late String apiType; + late String params; +} + +class FunctionBody { + late CallApiInvoke callApiInvoke; +} + +class Parameter { + late DartType? dartType; + late String type; + List typeArguments = []; + late String name; + late bool isNamed; + late bool isOptional; + String? defaultValue; +} + +extension ParameterExt on Parameter { + bool get isPrimitiveType => + type == 'int' || + type == 'double' || + type == 'bool' || + type == 'String' || + type == 'List' || + type == 'Map' || + type == 'Set'; + + String primitiveDefualtValue() { + switch (type) { + case 'int': + return '10'; + case 'double': + return '10.0'; + case 'String': + return '"hello"'; + case 'bool': + return 'true'; + case 'List': + return '[]'; + case 'Map': + return '{}'; + case 'Uint8List': + return 'Uint8List.fromList([])'; + case 'Set': + return '{}'; + default: + throw Exception('not support type $type'); + } + } +} + +class Type { + late String type; + List typeArguments = []; +} + +extension TypeExt on Type { + bool get isPrimitiveType => + type == 'int' || + type == 'double' || + type == 'bool' || + type == 'String' || + type == 'List' || + type == 'Map' || + type == 'Set'; + + String primitiveDefualtValue() { + switch (type) { + case 'int': + return '10'; + case 'double': + return '10.0'; + case 'String': + return '"hello"'; + case 'bool': + return 'true'; + case 'List': + return '[]'; + case 'Map': + return '{}'; + case 'Uint8List': + return 'Uint8List.fromList([])'; + case 'Set': + return '{}'; + default: + throw Exception('not support type $type'); + } + } + + bool isVoid() { + return type == 'void'; + } +} + +class SimpleLiteral { + late String type; + late String value; +} + +class SimpleAnnotation { + late String name; + List arguments = []; +} + +class Method { + late String name; + late FunctionBody body; + List parameters = []; + late Type returnType; +} + +class Field { + late Type type; + late String name; +} + +class Constructor { + late String name; + List parameters = []; + late bool isFactory; +} + +class Clazz { + late String name; + List constructors = []; + List methods = []; + List fields = []; +} + +class EnumConstant { + late String name; + List annotations = []; +} + +class Enumz { + late String name; + List enumConstants = []; +} + +class ParseResult { + late Map classMap; + late Map enumMap; + + // TODO(littlegnal): Optimize this later. + // late Map> classFieldsMap; + // late Map fieldsTypeMap; + late Map> genericTypeAliasParametersMap; +} + +class _RootBuilder extends dart_ast_visitor.RecursiveAstVisitor { + final classFieldsMap = >{}; + final fieldsTypeMap = {}; + final genericTypeAliasParametersMap = >{}; + + final classMap = {}; + final enumMap = {}; + + @override + Object? visitFieldDeclaration(dart_ast.FieldDeclaration node) { + stdout.writeln( + 'variables: ${node.fields.variables}, type: ${node.fields.type}'); + + final clazz = _getClazz(node); + if (clazz == null) return null; + + final dart_ast.TypeAnnotation? type = node.fields.type; + if (type is dart_ast.NamedType) { + final fieldName = node.fields.variables[0].name.name; + + Field field = Field()..name = fieldName; + + // if (node.parent is dart_ast.ClassDeclaration) { + // final fieldList = classFieldsMap.putIfAbsent( + // (node.parent as dart_ast.ClassDeclaration).name.name, + // () => []); + // fieldList.add(fieldName); + // } + // fieldsTypeMap[fieldName] = type.name.name; + + Type t = Type()..type = type.name.name; + field.type = t; + + clazz.fields.add(field); + } + + return null; + } + + @override + Object? visitConstructorDeclaration(ConstructorDeclaration node) { + stdout.writeln( + 'root visitConstructorDeclaration: node.name: ${node.name}, type: ${node.runtimeType} , ${node.initializers}, ${node.parent}'); + + final clazz = _getClazz(node); + if (clazz == null) return null; + + Constructor constructor = Constructor() + ..name = node.name?.name ?? '' + ..parameters = _getParameter(node.parent, node.parameters) + ..isFactory = node.factoryKeyword != null; + + clazz.constructors.add(constructor); + + return null; + } + + @override + Object? visitEnumDeclaration(EnumDeclaration node) { + stdout.writeln( + 'root visitEnumDeclaration: node.name: ${node.name}, type: ${node.runtimeType} constants: ${node.constants}, ${node.metadata}'); + for (final c in node.constants) { + for (final m in c.metadata) { + // stdout.writeln('m: ${m.arguments?.arguments}, ${m.name}'); + + for (final a in m.arguments?.arguments ?? []) { + stdout.writeln('a ${a.runtimeType}, ${a.toSource()}'); + } + } + } + + final enumz = enumMap.putIfAbsent(node.name.name, () => Enumz()); + enumz.name = node.name.name; + + for (final constant in node.constants) { + EnumConstant enumConstant = EnumConstant() + ..name = '${node.name.name}.${constant.name.name}'; + enumz.enumConstants.add(enumConstant); + + for (final meta in constant.metadata) { + SimpleAnnotation simpleAnnotation = SimpleAnnotation() + ..name = meta.name.name; + enumConstant.annotations.add(simpleAnnotation); + + for (final a in meta.arguments?.arguments ?? []) { + SimpleLiteral simpleLiteral = SimpleLiteral(); + simpleAnnotation.arguments.add(simpleLiteral); + + late String type; + late String value; + + if (a is IntegerLiteral) { + type = 'int'; + value = a.value.toString(); + } else if (a is PrefixExpression) { + if (a.operand is IntegerLiteral) { + final operand = a.operand as IntegerLiteral; + type = 'int'; + value = '${a.operator.value()}${operand.value.toString()}'; + } + } else if (a is BinaryExpression) { + type = 'int'; + value = a.toSource(); + } + simpleLiteral.type = type; + simpleLiteral.value = value; + } + } + } + + return null; + } + + Clazz? _getClazz(AstNode node) { + final classNode = node.parent; + if (classNode == null || classNode is! dart_ast.ClassDeclaration) { + return null; + } + + Clazz clazz = classMap.putIfAbsent( + classNode.name.name, + () => Clazz()..name = classNode.name.name, + ); + + return clazz; + } + + List _getParameter( + AstNode? root, FormalParameterList? formalParameterList) { + if (formalParameterList == null) return []; + List parameters = []; + for (final p in formalParameterList.parameters) { + Parameter parameter = Parameter(); + + if (p is SimpleFormalParameter) { + parameter.name = p.identifier?.name ?? ''; + DartType? dartType = p.type?.type; + + parameter.dartType = dartType; + + final namedType = p.type as NamedType; + for (final ta in namedType.typeArguments?.arguments ?? []) { + parameter.typeArguments.add(ta.name.name); + } + + parameter.type = namedType.name.name; + parameter.isNamed = p.isNamed; + parameter.isOptional = p.isOptional; + } else if (p is DefaultFormalParameter) { + parameter.name = p.identifier?.name ?? ''; + parameter.defaultValue = p.defaultValue?.toSource(); + + DartType? dartType; + String? type; + List typeArguments = []; + + if (p.parameter is SimpleFormalParameter) { + final SimpleFormalParameter simpleFormalParameter = + p.parameter as SimpleFormalParameter; + dartType = simpleFormalParameter.type?.type; + + final namedType = simpleFormalParameter.type as NamedType; + for (final ta in namedType.typeArguments?.arguments ?? []) { + typeArguments.add(ta.name.name); + } + + type = (simpleFormalParameter.type as NamedType).name.name; + } else if (p.parameter is FieldFormalParameter) { + final FieldFormalParameter fieldFormalParameter = + p.parameter as FieldFormalParameter; + + dartType = fieldFormalParameter.type?.type; + + if (root != null && root is ClassDeclaration) { + for (final classMember in root.members) { + if (classMember is FieldDeclaration) { + final dart_ast.TypeAnnotation? fieldType = + classMember.fields.type; + if (fieldType is dart_ast.NamedType) { + final fieldName = classMember.fields.variables[0].name.name; + if (fieldName == fieldFormalParameter.identifier.name) { + type = fieldType.name.name; + for (final ta in fieldType.typeArguments?.arguments ?? []) { + typeArguments.add(ta.name.name); + } + break; + } + } + } + } + } + } + parameter.dartType = dartType; + parameter.type = type!; + parameter.typeArguments.addAll(typeArguments); + parameter.isNamed = p.isNamed; + parameter.isOptional = p.isOptional; + } else if (p is FieldFormalParameter) { + String type = ''; + List typeArguments = []; + if (root != null && root is ClassDeclaration) { + for (final classMember in root.members) { + if (classMember is FieldDeclaration) { + final dart_ast.TypeAnnotation? fieldType = + classMember.fields.type; + if (fieldType is dart_ast.NamedType) { + final fieldName = classMember.fields.variables[0].name.name; + if (fieldName == p.identifier.name) { + type = fieldType.name.name; + for (final ta in fieldType.typeArguments?.arguments ?? []) { + typeArguments.add(ta.name.name); + } + break; + } + } + } + } + } + + parameter.name = p.identifier.name; + parameter.dartType = p.type?.type; + parameter.type = type; + parameter.typeArguments.addAll(typeArguments); + parameter.isNamed = p.isNamed; + parameter.isOptional = p.isOptional; + } + + parameters.add(parameter); + } + + return parameters; + } + + CallApiInvoke? _getCallApiInvoke(Expression expression) { + if (expression is! MethodInvocation) return null; + + if (expression.target != null) { + return _getCallApiInvoke(expression.target!); + } + + CallApiInvoke callApiInvoke = CallApiInvoke(); + for (final argument in expression.argumentList.arguments) { + if (argument is SimpleStringLiteral) { + } else if (argument is FunctionExpression) { + } else if (argument is SetOrMapLiteral) { + for (final element in argument.elements) { + if (element is MapLiteralEntry) { + final key = (element.key as SimpleStringLiteral).value; + if (key == 'apiType') { + callApiInvoke.apiType = element.value.toSource(); + } else if (key == 'params') { + callApiInvoke.params = element.value.toSource(); + } + } + } + } + } + + return callApiInvoke; + } + + @override + Object? visitMethodDeclaration(MethodDeclaration node) { + final classNode = node.parent; + if (classNode == null || classNode is! dart_ast.ClassDeclaration) { + return null; + } + + Clazz clazz = classMap.putIfAbsent( + classNode.name.name, + () => Clazz()..name = classNode.name.name, + ); + + Method method = Method()..name = node.name.name; + clazz.methods.add(method); + + if (node.parameters != null) { + method.parameters.addAll(_getParameter(node.parent, node.parameters)); + } + + if (node.returnType != null && node.returnType is NamedType) { + final returnType = node.returnType as NamedType; + method.returnType = Type() + ..type = returnType.name.name + ..typeArguments = returnType.typeArguments?.arguments + .map((ta) => (ta as NamedType).name.name) + .toList() ?? + []; + } + + if (node.body is BlockFunctionBody) { + final body = node.body as BlockFunctionBody; + + FunctionBody fb = FunctionBody(); + method.body = fb; + CallApiInvoke callApiInvoke = CallApiInvoke(); + method.body.callApiInvoke = callApiInvoke; + + for (final statement in body.block.statements) { + if (statement is ReturnStatement) { + final returns = statement as ReturnStatement; + + if (returns.expression != null) { + CallApiInvoke? callApiInvoke = + _getCallApiInvoke(returns.expression!); + if (callApiInvoke != null) { + method.body.callApiInvoke = callApiInvoke; + } + } + } + } + } + return null; + } + + @override + Object? visitGenericTypeAlias(dart_ast.GenericTypeAlias node) { + stdout.writeln( + 'root visitGenericTypeAlias: node.name: ${node.name}, node.functionType?.parameters: ${node.functionType?.parameters.parameters}'); + + final parametersList = node.functionType?.parameters.parameters + .map((e) { + if (e is SimpleFormalParameter) { + return '${e.type} ${e.identifier?.name}'; + } + return ''; + }) + .where((e) => e.isNotEmpty) + .toList() ?? + []; + + stdout.writeln(parametersList); + + genericTypeAliasParametersMap[node.name.name] = parametersList; + + return null; + } +} + +enum GeneratorConfigPlatform { + Android, + iOS, + macOS, + Windows, + Linux, +} + +extension GeneratorConfigPlatformExt on GeneratorConfigPlatform { + String toPlatformExpression() { + switch (this) { + case GeneratorConfigPlatform.Android: + return 'Platform.isAndroid'; + case GeneratorConfigPlatform.iOS: + return 'Platform.isIOS'; + case GeneratorConfigPlatform.macOS: + return 'Platform.isMacOS'; + case GeneratorConfigPlatform.Windows: + return 'Platform.isWindows'; + case GeneratorConfigPlatform.Linux: + return 'Platform.isLinux'; + } + } +} + +class GeneratorConfig { + const GeneratorConfig({ + required this.name, + this.donotGenerate = false, + this.supportedPlatforms = const [ + GeneratorConfigPlatform.Android, + GeneratorConfigPlatform.iOS, + GeneratorConfigPlatform.macOS, + GeneratorConfigPlatform.Windows, + GeneratorConfigPlatform.Linux, + ], + this.shouldMockResult = false, + this.shouldMockReturnCode = false, + }); + final String name; + final bool donotGenerate; + final List supportedPlatforms; + final bool shouldMockReturnCode; + final bool shouldMockResult; +} + +const List desktopPlatforms = [ + GeneratorConfigPlatform.macOS, + GeneratorConfigPlatform.Windows, + GeneratorConfigPlatform.Linux, +]; + +const List mobilePlatforms = [ + GeneratorConfigPlatform.Android, + GeneratorConfigPlatform.iOS, +]; + +IOSink? _openSink(String? output) { + if (output == null) { + return null; + } + IOSink sink; + File file; + if (output == 'stdout') { + sink = stdout; + } else { + file = File(output); + sink = file.openWrite(); + } + return sink; +} + +abstract class Generator { + void generate(StringSink sink, ParseResult parseResult); + + IOSink? shouldGenerate(ParseResult parseResult); +} + +abstract class DefaultGenerator implements Generator { + const DefaultGenerator(); + + GeneratorConfig? _getConfig( + List configs, String methodName) { + for (final config in configs) { + if (config.name == methodName) { + return config; + } + } + return null; + } + + String _concatParamName(String? prefix, String name) { + if (prefix == null) return name; + return '$prefix${name[0].toUpperCase()}${name.substring(1)}'; + } + + String _getParamType(Parameter parameter) { + if (parameter.typeArguments.isEmpty) { + return parameter.type; + } + + return '${parameter.type}<${parameter.typeArguments.join(', ')}>'; + } + + void _createConstructorInitializerForMethodParameter( + ParseResult parseResult, + Parameter? rootParameter, + Parameter parameter, + StringBuffer initializerBuilder, + ) { + final bool isClass = parseResult.classMap.containsKey(parameter.type); + final bool isEnum = parseResult.enumMap.containsKey(parameter.type); + + if (isEnum) { + final enumz = parseResult.enumMap[parameter.type]!; + + initializerBuilder.writeln( + 'const ${_getParamType(parameter)} ${_concatParamName(rootParameter?.name, parameter.name)} = ${enumz.enumConstants[0].name};'); + + return; + } + + final parameterClass = parseResult.classMap[parameter.type]!; + final initBlockParameterListBuilder = StringBuffer(); + final initBlockBuilder = StringBuffer(); + initBlockBuilder.write(parameterClass.name); + initBlockBuilder.write('('); + + for (final cp in parameterClass.constructors[0].parameters) { + final adjustedParamName = _concatParamName(parameter.name, cp.name); + if (cp.isNamed) { + if (cp.isPrimitiveType) { + initBlockParameterListBuilder.writeln( + 'const ${_getParamType(cp)} $adjustedParamName = ${cp.primitiveDefualtValue()};'); + initBlockBuilder.write('${cp.name}: $adjustedParamName,'); + } else { + _createConstructorInitializerForMethodParameter( + parseResult, parameter, cp, initializerBuilder); + initBlockBuilder.write('${cp.name}: $adjustedParamName,'); + } + } else { + if (cp.isPrimitiveType) { + initBlockParameterListBuilder.writeln( + 'const ${_getParamType(cp)} $adjustedParamName = ${cp.primitiveDefualtValue()};'); + initBlockBuilder.write('$adjustedParamName,'); + } else { + _createConstructorInitializerForMethodParameter( + parseResult, parameter, cp, initializerBuilder); + initBlockBuilder.write('$adjustedParamName,'); + } + } + } + + initBlockBuilder.write(')'); + + initializerBuilder.write(initBlockParameterListBuilder.toString()); + initializerBuilder.writeln( + 'final ${_getParamType(parameter)} ${_concatParamName(rootParameter?.name, parameter.name)} = ${initBlockBuilder.toString()};'); + } + + String generateWithTemplate({ + required ParseResult parseResult, + required Clazz clazz, + required String testCaseTemplate, + required String testCasesContentTemplate, + required String methodInvokeObjectName, + required List configs, + List? supportedPlatformsOverride, + }) { +// const testWidgetTemplate = ''' +// testWidgets('{{TEST_CASE_NAME}}', (WidgetTester tester) async { +// app.main(); +// await tester.pumpAndSettle(); + +// String engineAppId = const String.fromEnvironment('TEST_APP_ID', +// defaultValue: ''); + +// RtcEngine rtcEngine = await RtcEngine.create(engineAppId); + +// final screenShareHelper = await rtcEngine.getScreenShareHelper(); + +// {{TEST_CASE_BODY}} + +// await screenShareHelper.destroy(); +// await rtcEngine.destroy(); +// }, +// skip: {{TEST_CASE_SKIP}}, +// ); +// '''; + + final testCases = []; + for (final method in clazz.methods) { + final methodName = method.name; + + final config = _getConfig(configs, methodName); + if (config?.donotGenerate == true) continue; + if (methodName.startsWith('_')) continue; + if (methodName.startsWith('create')) continue; + + StringBuffer pb = StringBuffer(); + +// if (!method.returnType.isVoid()) { +// // final mockCallApiResultBlock = ''' +// // fakeIrisEngine.mockCallApiResult( +// // ${method.body.callApiInvoke.apiType}, +// // ${method.body.callApiInvoke.params}, +// // '1', +// // ); +// // '''; + +// // stdout.writeln( +// // 'method.returnType: ${method.returnType.typeArguments[0]}'); +// final typeArgument = method.returnType.typeArguments[0]; +// if (parseResult.enumMap.containsKey(typeArgument)) { +// final enumz = parseResult.enumMap[typeArgument]!; +// final jsonValue = +// enumz.enumConstants[0].annotations[0].arguments[0].value; +// final mockCallApiReturnCodeBlock = ''' +// fakeIrisEngine.mockCallApiReturnCode( +// ${method.body.callApiInvoke.apiType}, +// ${method.body.callApiInvoke.params}, +// $jsonValue, +// ); +// '''; + +// pb.writeln(mockCallApiReturnCodeBlock); +// } +// } + + for (final parameter in method.parameters) { + if (parameter.isPrimitiveType) { + pb.writeln( + 'const ${_getParamType(parameter)} ${parameter.name} = ${parameter.primitiveDefualtValue()};'); + } else { + _createConstructorInitializerForMethodParameter( + parseResult, null, parameter, pb); + } + } + + StringBuffer methodCallBuilder = StringBuffer(); + // methodCallBuilder.write('await screenShareHelper.$methodName('); + methodCallBuilder.write('await $methodInvokeObjectName.$methodName('); + for (final parameter in method.parameters) { + if (parameter.isNamed) { + methodCallBuilder.write('${parameter.name}:${parameter.name},'); + } else { + methodCallBuilder.write('${parameter.name}, '); + } + } + methodCallBuilder.write(');'); + + pb.writeln(methodCallBuilder.toString()); + +// final expectBlock = ''' +// fakeIrisEngine.expectCalledApi( +// ${method.body.callApiInvoke.apiType}, +// ${method.body.callApiInvoke.params}, +// ); +// '''; +// pb.writeln(expectBlock); + + String skipExpression = 'false'; + + if (supportedPlatformsOverride != null) { + // skipExpression = + // '!(${desktopPlatforms.map((e) => e.toPlatformExpression()).join(' || ')})'; + skipExpression = + '!(${supportedPlatformsOverride.map((e) => e.toPlatformExpression()).join(' || ')})'; + } else { + if (config != null && + config.supportedPlatforms.length < + GeneratorConfigPlatform.values.length) { + skipExpression = + '!(${config.supportedPlatforms.map((e) => e.toPlatformExpression()).join(' || ')})'; + } + } + + String testCase = + testCaseTemplate.replaceAll('{{TEST_CASE_NAME}}', methodName); + testCase = testCase.replaceAll('{{TEST_CASE_BODY}}', pb.toString()); + testCase = testCase.replaceAll('{{TEST_CASE_SKIP}}', skipExpression); + testCases.add(testCase); + } + +// final output = ''' +// import 'dart:io'; + +// import 'package:agora_rtc_engine/rtc_engine.dart'; +// import 'package:flutter_test/flutter_test.dart'; +// import 'package:integration_test_app/main.dart' as app; + +// void rtcEngineSubProcessSmokeTestCases() { +// ${testCases.join('\n')} +// {{TEST_CASES_CONTENT}} +// } +// '''; + + final output = testCasesContentTemplate.replaceAll( + '{{TEST_CASES_CONTENT}}', + testCases.join('\n'), + ); + + return output; + } +} + +class RtcEngineEventHandlerSomkeTestGenerator implements Generator { + const RtcEngineEventHandlerSomkeTestGenerator(); + + static const Map _eventFieldMap = { + 'requestAudioFileInfoCallback': 'RequestAudioFileInfo', + 'airPlayIsConnected': 'AirPlayConnected', + }; + +// TODO(littlegnal): Re-implement later + static const List _skipEvent = [ + 'onMetadataReceived', + ]; + + static const Map> _restrictPlatforms = { + 'onFacePositionChanged': mobilePlatforms, + }; + + @override + void generate(StringSink sink, ParseResult parseResult) { + final clazz = parseResult.classMap['RtcEngineEventHandler']; + stdout.writeln('clazz: $clazz'); + if (clazz == null) return; + + final fields = clazz.fields; + + final Map> genericTypeAliasParametersMap = + parseResult.genericTypeAliasParametersMap; + + final testCases = []; + + const testCaseTemplate = ''' +testWidgets('{{TEST_CASE_NAME}}', (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + FakeIrisRtcEngine fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + final rtcEngine = await RtcEngine.create('123'); + {{TEST_CASE_BODY}} + + rtcEngine.destroy(); + fakeIrisEngine.dispose(); +}, +{{TEST_CASE_SKIP}} +); + + '''; + + for (final field in fields) { + final fieldType = field.type.type; + final paramsOfFieldType = genericTypeAliasParametersMap[fieldType] + ?.map((e) => e.split(' ')[1]) + .toList(); + final paramsOfFieldTypeList = paramsOfFieldType?.join(','); + + final eventSuffix = _eventFieldMap[field.name] ?? field.name; + + final eventName = + 'on${eventSuffix.substring(0, 1).toUpperCase()}${eventSuffix.substring(1)}'; + + if (_skipEvent.contains(eventName)) continue; + + final t = ''' +bool ${field.name}Called = false; +rtcEngine.setEventHandler(RtcEngineEventHandler( + ${field.name}: ($paramsOfFieldTypeList) { + ${field.name}Called = true; + }, +)); + +fakeIrisEngine.fireRtcEngineEvent('$eventName'); +// Wait for the `EventChannel` event be sent from Android/iOS side +await tester.pump(const Duration(milliseconds: 500)); +expect(${field.name}Called, isTrue); +'''; + String skipExpression = ''; + if (_restrictPlatforms.containsKey(eventName)) { + skipExpression = + 'skip: !(${_restrictPlatforms[eventName]!.map((e) => e.toPlatformExpression()).join(' || ')}),'; + } + + String testCase = + testCaseTemplate.replaceAll('{{TEST_CASE_NAME}}', eventName); + testCase = testCase.replaceAll('{{TEST_CASE_BODY}}', t); + testCase = testCase.replaceAll('{{TEST_CASE_SKIP}}', skipExpression); + + testCases.add(testCase); + } + + const testCasesContentTemplate = ''' +import 'dart:io'; +import 'package:agora_rtc_engine/rtc_engine.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:integration_test_app/main.dart' as app; +import 'package:integration_test_app/src/fake_iris_rtc_engine.dart'; + +void rtcEngineEventHandlerSomkeTestCases() { + {{TEST_CASES_CONTENT}} +} +'''; + + final output = testCasesContentTemplate.replaceAll( + '{{TEST_CASES_CONTENT}}', testCases.join("")); + + sink.writeln(output); + } + + @override + IOSink? shouldGenerate(ParseResult parseResult) { + if (parseResult.classMap.containsKey('RtcEngineEventHandler')) { + return _openSink(path.join( + fileSystem.currentDirectory.absolute.path, + 'integration_test_app', + 'integration_test', + 'agora_rtc_engine_event_handler_smoke_test.generated.dart')); + } + + return null; + } +} + +class RtcChannelEventHandlerSomkeTestGenerator implements Generator { + const RtcChannelEventHandlerSomkeTestGenerator(); + + static const Map _functionNameToEventNameMap = { + 'warning': 'ChannelWarning', + 'error': 'ChannelError', + }; + + // TODO(littlegnal): Re-implement later + static const List _skipEvent = ['onMetadataReceived']; + + @override + void generate(StringSink sink, ParseResult parseResult) { + final clazz = parseResult.classMap['RtcChannelEventHandler']; + + if (clazz == null) return; + + final fields = clazz.fields; + + final Map> genericTypeAliasParametersMap = + parseResult.genericTypeAliasParametersMap; + + final testCases = []; + + const testCaseTemplate = ''' +testWidgets('{{TEST_CASE_NAME}}', (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + FakeIrisRtcEngine fakeIrisEngine = FakeIrisRtcEngine(); + await fakeIrisEngine.initialize(); + final rtcEngine = await RtcEngine.create('123'); + final rtcChannel = await RtcChannel.create('testapi'); + {{TEST_CASE_BODY}} + + await rtcChannel.destroy(); + await rtcEngine.destroy(); + fakeIrisEngine.dispose(); +}); + '''; + + for (final field in fields) { + final fieldType = field.type.type; + final paramsOfFieldType = genericTypeAliasParametersMap[fieldType] + ?.map((e) => e.split(' ')[1]) + .toList(); + final paramsOfFieldTypeList = paramsOfFieldType?.join(','); + + final baseEventName = + _functionNameToEventNameMap[field.name] ?? field.name; + final eventName = + 'on${baseEventName.substring(0, 1).toUpperCase()}${baseEventName.substring(1)}'; + + if (_skipEvent.contains(eventName)) continue; + + final t = ''' +bool ${field.name}Called = false; +rtcChannel.setEventHandler(RtcChannelEventHandler( + ${field.name}: ($paramsOfFieldTypeList) { + ${field.name}Called = true; + }, +)); + +fakeIrisEngine.fireRtcChannelEvent('$eventName'); +// Wait for the `EventChannel` event be sent from Android/iOS side +await tester.pump(const Duration(milliseconds: 500)); +expect(${field.name}Called, isTrue); + '''; + + String testCase = + testCaseTemplate.replaceAll('{{TEST_CASE_NAME}}', eventName); + testCase = testCase.replaceAll('{{TEST_CASE_BODY}}', t); + + testCases.add(testCase); + } + + const testCasesContentTemplate = ''' +import 'package:agora_rtc_engine/rtc_channel.dart'; +import 'package:agora_rtc_engine/rtc_engine.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:integration_test_app/main.dart' as app; +import 'package:integration_test_app/src/fake_iris_rtc_engine.dart'; + +void rtcChannelEventHandlerSomkeTestCases() { + {{TEST_CASES_CONTENT}} +} +'''; + + final output = testCasesContentTemplate.replaceAll( + '{{TEST_CASES_CONTENT}}', testCases.join("")); + + sink.writeln(output); + } + + @override + IOSink? shouldGenerate(ParseResult parseResult) { + if (parseResult.classMap.containsKey('RtcChannelEventHandler')) { + return _openSink(path.join( + fileSystem.currentDirectory.absolute.path, + 'integration_test_app', + 'integration_test', + 'agora_rtc_channel_event_handler_smoke_test.generated.dart')); + } + + return null; + } +} + +class RtcEngineSubProcessSmokeTestGenerator extends DefaultGenerator { + const RtcEngineSubProcessSmokeTestGenerator(); + + static const List configs = [ + GeneratorConfig(name: 'getScreenShareHelper', donotGenerate: true), + GeneratorConfig(name: 'instance', donotGenerate: true), + GeneratorConfig(name: 'initialize', donotGenerate: true), + GeneratorConfig(name: 'getSdkVersion', donotGenerate: true), + GeneratorConfig(name: 'getErrorDescription', donotGenerate: true), + + // TODO(littlegnal): This should be a getter proerpty. + GeneratorConfig(name: 'methodChannel', donotGenerate: true), + GeneratorConfig(name: 'setEventHandler', donotGenerate: true), + GeneratorConfig(name: 'sendMetadata', donotGenerate: true), + GeneratorConfig(name: 'sendStreamMessage', donotGenerate: true), + // TODO(littlegnal): Re-enable it later + GeneratorConfig(name: 'setLiveTranscoding', donotGenerate: true), + // TODO(littlegnal): Re-enable it later + GeneratorConfig(name: 'enableVirtualBackground', donotGenerate: true), + GeneratorConfig(name: 'deviceManager', donotGenerate: true), + GeneratorConfig(name: 'destroy', donotGenerate: true), + GeneratorConfig( + name: 'enableLoopbackRecording', + supportedPlatforms: desktopPlatforms, + ), + // TODO(littlegnal): Re-enable it later + GeneratorConfig(name: 'setVideoEncoderConfiguration', donotGenerate: true), + GeneratorConfig(name: 'getUserInfoByUid', donotGenerate: true), + GeneratorConfig(name: 'getUserInfoByUserAccount', donotGenerate: true), + GeneratorConfig(name: 'getConnectionState', donotGenerate: true), + // Only run on valid appId. + GeneratorConfig(name: 'getCameraMaxZoomFactor', donotGenerate: true), + GeneratorConfig( + name: 'isCameraAutoFocusFaceModeSupported', donotGenerate: true), + GeneratorConfig( + name: 'isCameraExposurePositionSupported', donotGenerate: true), + GeneratorConfig(name: 'isCameraFocusSupported', donotGenerate: true), + GeneratorConfig(name: 'isCameraZoomSupported', donotGenerate: true), + GeneratorConfig( + name: 'setCameraAutoFocusFaceModeEnabled', donotGenerate: true), + GeneratorConfig(name: 'setCameraExposurePosition', donotGenerate: true), + GeneratorConfig( + name: 'setCameraFocusPositionInPreview', donotGenerate: true), + GeneratorConfig(name: 'setCameraZoomFactor', donotGenerate: true), + GeneratorConfig(name: 'startRhythmPlayer', donotGenerate: true), + GeneratorConfig(name: 'stopRhythmPlayer', donotGenerate: true), + GeneratorConfig(name: 'configRhythmPlayer', donotGenerate: true), + GeneratorConfig(name: 'getNativeHandle', donotGenerate: true), + GeneratorConfig(name: 'startEchoTest', donotGenerate: true), + +// TODO(littlegnal): Re-enable it later + GeneratorConfig(name: 'takeSnapshot', donotGenerate: true), + + // Destop only + GeneratorConfig( + name: 'setAudioSessionOperationRestriction', + supportedPlatforms: desktopPlatforms, + ), + GeneratorConfig( + name: 'setScreenCaptureContentHint', + supportedPlatforms: desktopPlatforms, + ), + GeneratorConfig( + name: 'startScreenCaptureByDisplayId', + supportedPlatforms: desktopPlatforms, + ), + GeneratorConfig( + name: 'startScreenCaptureByScreenRect', + supportedPlatforms: desktopPlatforms, + ), + GeneratorConfig( + name: 'startScreenCaptureByWindowId', + supportedPlatforms: desktopPlatforms, + ), + GeneratorConfig( + name: 'stopScreenCapture', + supportedPlatforms: desktopPlatforms, + ), + GeneratorConfig( + name: 'updateScreenCaptureParameters', + supportedPlatforms: desktopPlatforms, + ), + GeneratorConfig( + name: 'updateScreenCaptureRegion', + supportedPlatforms: desktopPlatforms, + ), + GeneratorConfig( + name: 'startScreenCapture', + supportedPlatforms: desktopPlatforms, + ), + ]; + + @override + void generate(StringSink sink, ParseResult parseResult) { + final clazz = parseResult.classMap['RtcEngine']; + if (clazz == null) return; + + const testCaseTemplate = ''' +testWidgets('{{TEST_CASE_NAME}}', (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + String engineAppId = const String.fromEnvironment('TEST_APP_ID', + defaultValue: ''); + + RtcEngine rtcEngine = await RtcEngine.createWithContext(RtcEngineContext( + engineAppId, + areaCode: [AreaCode.NA, AreaCode.GLOB], + )); + + final screenShareHelper = await rtcEngine.getScreenShareHelper(appGroup: 'io.agora'); + + {{TEST_CASE_BODY}} + + await screenShareHelper.destroy(); + await rtcEngine.destroy(); + }, + skip: {{TEST_CASE_SKIP}}, +); +'''; + + const testCasesContentTemplate = ''' +import 'dart:io'; + +import 'package:agora_rtc_engine/rtc_engine.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:integration_test_app/main.dart' as app; + +void rtcEngineSubProcessSmokeTestCases() { + {{TEST_CASES_CONTENT}} +} +'''; + + final output = generateWithTemplate( + parseResult: parseResult, + clazz: clazz, + testCaseTemplate: testCaseTemplate, + testCasesContentTemplate: testCasesContentTemplate, + methodInvokeObjectName: 'screenShareHelper', + configs: configs, + supportedPlatformsOverride: desktopPlatforms, + ); + + sink.writeln(output); + } + + @override + IOSink? shouldGenerate(ParseResult parseResult) { + if (parseResult.classMap.containsKey('RtcEngine')) { + return _openSink(path.join( + fileSystem.currentDirectory.absolute.path, + 'integration_test_app', + 'integration_test', + 'agora_rtc_engine_subprocess_api_smoke_test.generated.dart')); + } + + return null; + } +} + +class RtcDeviceManagerSmokeTestGenerator extends DefaultGenerator { + const RtcDeviceManagerSmokeTestGenerator(); + + static const List configs = [ + GeneratorConfig(name: 'getVideoDevice', donotGenerate: true), + ]; + + @override + void generate(StringSink sink, ParseResult parseResult) { + final clazz = parseResult.classMap['RtcDeviceManager']; + if (clazz == null) return; + + const testCaseTemplate = ''' +testWidgets('{{TEST_CASE_NAME}}', (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + String engineAppId = const String.fromEnvironment('TEST_APP_ID', + defaultValue: ''); + + RtcEngine rtcEngine = await RtcEngine.create(engineAppId); + final deviceManager = rtcEngine.deviceManager; + + try { + {{TEST_CASE_BODY}} + } catch (e) { + if (e is! PlatformException) { + rethrow; + } + expect(e.code != '-7', isTrue); + } + + await rtcEngine.destroy(); + }, + skip: {{TEST_CASE_SKIP}}, +); +'''; + + const testCasesContentTemplate = ''' +import 'dart:io'; + +import 'package:flutter/services.dart'; +import 'package:agora_rtc_engine/rtc_engine.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:integration_test_app/main.dart' as app; + +void rtcDeviceManagerSmokeTestCases() { + {{TEST_CASES_CONTENT}} +} +'''; + + final output = generateWithTemplate( + parseResult: parseResult, + clazz: clazz, + testCaseTemplate: testCaseTemplate, + testCasesContentTemplate: testCasesContentTemplate, + methodInvokeObjectName: 'deviceManager', + configs: configs, + supportedPlatformsOverride: desktopPlatforms, + ); + + sink.writeln(output); + } + + @override + IOSink? shouldGenerate(ParseResult parseResult) { + if (parseResult.classMap.containsKey('RtcDeviceManager')) { + return _openSink(path.join( + fileSystem.currentDirectory.absolute.path, + 'integration_test_app', + 'integration_test', + 'agora_rtc_device_manager_api_smoke_test.generated.dart')); + } + + return null; + } +} + +final List generators = [ + const RtcEngineSubProcessSmokeTestGenerator(), + const RtcEngineEventHandlerSomkeTestGenerator(), + const RtcDeviceManagerSmokeTestGenerator(), + const RtcChannelEventHandlerSomkeTestGenerator(), +]; + +const file.FileSystem fileSystem = LocalFileSystem(); + +void main(List args) { + final srcDir = path.join( + fileSystem.currentDirectory.absolute.path, + 'lib', + 'src', + ); + final List includedPaths = [ + path.join(srcDir, 'rtc_engine.dart'), + path.join(srcDir, 'enums.dart'), + path.join(srcDir, 'classes.dart'), + path.join(srcDir, 'rtc_device_manager.dart'), + path.join(srcDir, 'events.dart'), + ]; + final AnalysisContextCollection collection = AnalysisContextCollection( + includedPaths: includedPaths, + ); + final _RootBuilder rootBuilder = _RootBuilder(); + + for (final AnalysisContext context in collection.contexts) { + for (final String path in context.contextRoot.analyzedFiles()) { + final AnalysisSession session = context.currentSession; + final ParsedUnitResult result = + session.getParsedUnit(path) as ParsedUnitResult; + if (result.errors.isEmpty) { + final dart_ast.CompilationUnit unit = result.unit; + unit.accept(rootBuilder); + } else { + for (final AnalysisError error in result.errors) { + stderr.writeln(error.toString()); + } + } + } + } + + final parseResult = ParseResult() + ..classMap = rootBuilder.classMap + ..enumMap = rootBuilder.enumMap + // ..classFieldsMap = rootBuilder.classFieldsMap + // ..fieldsTypeMap = rootBuilder.fieldsTypeMap + ..genericTypeAliasParametersMap = rootBuilder.genericTypeAliasParametersMap; + + for (final generator in generators) { + final sink = generator.shouldGenerate(parseResult); + if (sink != null) { + generator.generate(sink, parseResult); + sink.flush(); + } + } +} diff --git a/integration_test_app/windows/.gitignore b/integration_test_app/windows/.gitignore new file mode 100644 index 000000000..d492d0d98 --- /dev/null +++ b/integration_test_app/windows/.gitignore @@ -0,0 +1,17 @@ +flutter/ephemeral/ + +# Visual Studio user-specific files. +*.suo +*.user +*.userosscache +*.sln.docstates + +# Visual Studio build-related files. +x64/ +x86/ + +# Visual Studio cache files +# files ending in .cache can be ignored +*.[Cc]ache +# but keep track of directories ending in .cache +!*.[Cc]ache/ diff --git a/integration_test_app/windows/CMakeLists.txt b/integration_test_app/windows/CMakeLists.txt new file mode 100644 index 000000000..f21893676 --- /dev/null +++ b/integration_test_app/windows/CMakeLists.txt @@ -0,0 +1,100 @@ +cmake_minimum_required(VERSION 3.15) +project(integration_test_app LANGUAGES CXX) + +set(BINARY_NAME "integration_test_app") + +cmake_policy(SET CMP0063 NEW) + +set(CMAKE_INSTALL_RPATH "$ORIGIN/lib") + +# Configure build options. +get_property(IS_MULTICONFIG GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG) +if(IS_MULTICONFIG) + set(CMAKE_CONFIGURATION_TYPES "Debug;Profile;Release" + CACHE STRING "" FORCE) +else() + if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES) + set(CMAKE_BUILD_TYPE "Debug" CACHE + STRING "Flutter build mode" FORCE) + set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS + "Debug" "Profile" "Release") + endif() +endif() + +set(CMAKE_EXE_LINKER_FLAGS_PROFILE "${CMAKE_EXE_LINKER_FLAGS_RELEASE}") +set(CMAKE_SHARED_LINKER_FLAGS_PROFILE "${CMAKE_SHARED_LINKER_FLAGS_RELEASE}") +set(CMAKE_C_FLAGS_PROFILE "${CMAKE_C_FLAGS_RELEASE}") +set(CMAKE_CXX_FLAGS_PROFILE "${CMAKE_CXX_FLAGS_RELEASE}") + +# Use Unicode for all projects. +add_definitions(-DUNICODE -D_UNICODE) + +# Compilation settings that should be applied to most targets. +function(APPLY_STANDARD_SETTINGS TARGET) + target_compile_features(${TARGET} PUBLIC cxx_std_17) + target_compile_options(${TARGET} PRIVATE /W4 /WX /wd"4100") + target_compile_options(${TARGET} PRIVATE /EHsc) + target_compile_definitions(${TARGET} PRIVATE "_HAS_EXCEPTIONS=0") + target_compile_definitions(${TARGET} PRIVATE "$<$:_DEBUG>") +endfunction() + +set(FLUTTER_MANAGED_DIR "${CMAKE_CURRENT_SOURCE_DIR}/flutter") + +# Flutter library and tool build rules. +add_subdirectory(${FLUTTER_MANAGED_DIR}) + +# Application build +add_subdirectory("runner") + +# Generated plugin build rules, which manage building the plugins and adding +# them to the application. +include(flutter/generated_plugins.cmake) + + +# === Installation === +# Support files are copied into place next to the executable, so that it can +# run in place. This is done instead of making a separate bundle (as on Linux) +# so that building and running from within Visual Studio will work. +set(BUILD_BUNDLE_DIR "$") +# Make the "install" step default, as it's required to run. +set(CMAKE_VS_INCLUDE_INSTALL_TO_DEFAULT_BUILD 1) +if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT) + set(CMAKE_INSTALL_PREFIX "${BUILD_BUNDLE_DIR}" CACHE PATH "..." FORCE) +endif() + +set(INSTALL_BUNDLE_DATA_DIR "${CMAKE_INSTALL_PREFIX}/data") +set(INSTALL_BUNDLE_LIB_DIR "${CMAKE_INSTALL_PREFIX}") + +install(TARGETS ${BINARY_NAME} RUNTIME DESTINATION "${CMAKE_INSTALL_PREFIX}" + COMPONENT Runtime) + +install(FILES "${FLUTTER_ICU_DATA_FILE}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" + COMPONENT Runtime) + +install(FILES "${FLUTTER_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" + COMPONENT Runtime) + +if(PLUGIN_BUNDLED_LIBRARIES) + install(FILES "${PLUGIN_BUNDLED_LIBRARIES}" + DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" + COMPONENT Runtime) +endif() + +# Fully re-copy the assets directory on each build to avoid having stale files +# from a previous install. +set(FLUTTER_ASSET_DIR_NAME "flutter_assets") +install(CODE " + file(REMOVE_RECURSE \"${INSTALL_BUNDLE_DATA_DIR}/${FLUTTER_ASSET_DIR_NAME}\") + " COMPONENT Runtime) +install(DIRECTORY "${PROJECT_BUILD_DIR}/${FLUTTER_ASSET_DIR_NAME}" + DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" COMPONENT Runtime) + +# Install the AOT library on non-Debug builds only. +install(FILES "${AOT_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" + CONFIGURATIONS Profile;Release + COMPONENT Runtime) + + message(STATUS "CMAKE_INSTALL_PREFIX: ${BUILD_BUNDLE_DIR}/$") + +install(FILES "${CMAKE_INSTALL_PREFIX}/../iris_integration_test/$/iris_integration_test.dll" DESTINATION "${CMAKE_INSTALL_PREFIX}" + COMPONENT Runtime) diff --git a/integration_test_app/windows/flutter/CMakeLists.txt b/integration_test_app/windows/flutter/CMakeLists.txt new file mode 100644 index 000000000..b02c5485c --- /dev/null +++ b/integration_test_app/windows/flutter/CMakeLists.txt @@ -0,0 +1,103 @@ +cmake_minimum_required(VERSION 3.15) + +set(EPHEMERAL_DIR "${CMAKE_CURRENT_SOURCE_DIR}/ephemeral") + +# Configuration provided via flutter tool. +include(${EPHEMERAL_DIR}/generated_config.cmake) + +# TODO: Move the rest of this into files in ephemeral. See +# https://github.com/flutter/flutter/issues/57146. +set(WRAPPER_ROOT "${EPHEMERAL_DIR}/cpp_client_wrapper") + +# === Flutter Library === +set(FLUTTER_LIBRARY "${EPHEMERAL_DIR}/flutter_windows.dll") + +# Published to parent scope for install step. +set(FLUTTER_LIBRARY ${FLUTTER_LIBRARY} PARENT_SCOPE) +set(FLUTTER_ICU_DATA_FILE "${EPHEMERAL_DIR}/icudtl.dat" PARENT_SCOPE) +set(PROJECT_BUILD_DIR "${PROJECT_DIR}/build/" PARENT_SCOPE) +set(AOT_LIBRARY "${PROJECT_DIR}/build/windows/app.so" PARENT_SCOPE) + +list(APPEND FLUTTER_LIBRARY_HEADERS + "flutter_export.h" + "flutter_windows.h" + "flutter_messenger.h" + "flutter_plugin_registrar.h" + "flutter_texture_registrar.h" +) +list(TRANSFORM FLUTTER_LIBRARY_HEADERS PREPEND "${EPHEMERAL_DIR}/") +add_library(flutter INTERFACE) +target_include_directories(flutter INTERFACE + "${EPHEMERAL_DIR}" +) +target_link_libraries(flutter INTERFACE "${FLUTTER_LIBRARY}.lib") +add_dependencies(flutter flutter_assemble) + +# === Wrapper === +list(APPEND CPP_WRAPPER_SOURCES_CORE + "core_implementations.cc" + "standard_codec.cc" +) +list(TRANSFORM CPP_WRAPPER_SOURCES_CORE PREPEND "${WRAPPER_ROOT}/") +list(APPEND CPP_WRAPPER_SOURCES_PLUGIN + "plugin_registrar.cc" +) +list(TRANSFORM CPP_WRAPPER_SOURCES_PLUGIN PREPEND "${WRAPPER_ROOT}/") +list(APPEND CPP_WRAPPER_SOURCES_APP + "flutter_engine.cc" + "flutter_view_controller.cc" +) +list(TRANSFORM CPP_WRAPPER_SOURCES_APP PREPEND "${WRAPPER_ROOT}/") + +# Wrapper sources needed for a plugin. +add_library(flutter_wrapper_plugin STATIC + ${CPP_WRAPPER_SOURCES_CORE} + ${CPP_WRAPPER_SOURCES_PLUGIN} +) +apply_standard_settings(flutter_wrapper_plugin) +set_target_properties(flutter_wrapper_plugin PROPERTIES + POSITION_INDEPENDENT_CODE ON) +set_target_properties(flutter_wrapper_plugin PROPERTIES + CXX_VISIBILITY_PRESET hidden) +target_link_libraries(flutter_wrapper_plugin PUBLIC flutter) +target_include_directories(flutter_wrapper_plugin PUBLIC + "${WRAPPER_ROOT}/include" +) +add_dependencies(flutter_wrapper_plugin flutter_assemble) + +# Wrapper sources needed for the runner. +add_library(flutter_wrapper_app STATIC + ${CPP_WRAPPER_SOURCES_CORE} + ${CPP_WRAPPER_SOURCES_APP} +) +apply_standard_settings(flutter_wrapper_app) +target_link_libraries(flutter_wrapper_app PUBLIC flutter) +target_include_directories(flutter_wrapper_app PUBLIC + "${WRAPPER_ROOT}/include" +) +add_dependencies(flutter_wrapper_app flutter_assemble) + +# === Flutter tool backend === +# _phony_ is a non-existent file to force this command to run every time, +# since currently there's no way to get a full input/output list from the +# flutter tool. +set(PHONY_OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/_phony_") +set_source_files_properties("${PHONY_OUTPUT}" PROPERTIES SYMBOLIC TRUE) +add_custom_command( + OUTPUT ${FLUTTER_LIBRARY} ${FLUTTER_LIBRARY_HEADERS} + ${CPP_WRAPPER_SOURCES_CORE} ${CPP_WRAPPER_SOURCES_PLUGIN} + ${CPP_WRAPPER_SOURCES_APP} + ${PHONY_OUTPUT} + COMMAND ${CMAKE_COMMAND} -E env + ${FLUTTER_TOOL_ENVIRONMENT} + "${FLUTTER_ROOT}/packages/flutter_tools/bin/tool_backend.bat" + windows-x64 $ + VERBATIM +) +add_custom_target(flutter_assemble DEPENDS + "${FLUTTER_LIBRARY}" + ${FLUTTER_LIBRARY_HEADERS} + ${CPP_WRAPPER_SOURCES_CORE} + ${CPP_WRAPPER_SOURCES_PLUGIN} + ${CPP_WRAPPER_SOURCES_APP} +) diff --git a/integration_test_app/windows/flutter/generated_plugin_registrant.cc b/integration_test_app/windows/flutter/generated_plugin_registrant.cc new file mode 100644 index 000000000..f9eb73595 --- /dev/null +++ b/integration_test_app/windows/flutter/generated_plugin_registrant.cc @@ -0,0 +1,14 @@ +// +// Generated file. Do not edit. +// + +// clang-format off + +#include "generated_plugin_registrant.h" + +#include + +void RegisterPlugins(flutter::PluginRegistry* registry) { + AgoraRtcEnginePluginRegisterWithRegistrar( + registry->GetRegistrarForPlugin("AgoraRtcEnginePlugin")); +} diff --git a/integration_test_app/windows/flutter/generated_plugin_registrant.h b/integration_test_app/windows/flutter/generated_plugin_registrant.h new file mode 100644 index 000000000..dc139d85a --- /dev/null +++ b/integration_test_app/windows/flutter/generated_plugin_registrant.h @@ -0,0 +1,15 @@ +// +// Generated file. Do not edit. +// + +// clang-format off + +#ifndef GENERATED_PLUGIN_REGISTRANT_ +#define GENERATED_PLUGIN_REGISTRANT_ + +#include + +// Registers Flutter plugins. +void RegisterPlugins(flutter::PluginRegistry* registry); + +#endif // GENERATED_PLUGIN_REGISTRANT_ diff --git a/integration_test_app/windows/flutter/generated_plugins.cmake b/integration_test_app/windows/flutter/generated_plugins.cmake new file mode 100644 index 000000000..bee76c9f8 --- /dev/null +++ b/integration_test_app/windows/flutter/generated_plugins.cmake @@ -0,0 +1,16 @@ +# +# Generated file, do not edit. +# + +list(APPEND FLUTTER_PLUGIN_LIST + agora_rtc_engine +) + +set(PLUGIN_BUNDLED_LIBRARIES) + +foreach(plugin ${FLUTTER_PLUGIN_LIST}) + add_subdirectory(flutter/ephemeral/.plugin_symlinks/${plugin}/windows plugins/${plugin}) + target_link_libraries(${BINARY_NAME} PRIVATE ${plugin}_plugin) + list(APPEND PLUGIN_BUNDLED_LIBRARIES $) + list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${plugin}_bundled_libraries}) +endforeach(plugin) diff --git a/integration_test_app/windows/runner/CMakeLists.txt b/integration_test_app/windows/runner/CMakeLists.txt new file mode 100644 index 000000000..de3811ab7 --- /dev/null +++ b/integration_test_app/windows/runner/CMakeLists.txt @@ -0,0 +1,18 @@ +cmake_minimum_required(VERSION 3.15) +project(runner LANGUAGES CXX) + +add_executable(${BINARY_NAME} WIN32 + "flutter_window.cpp" + "main.cpp" + "utils.cpp" + "win32_window.cpp" + "${FLUTTER_MANAGED_DIR}/generated_plugin_registrant.cc" + "Runner.rc" + "runner.exe.manifest" +) +apply_standard_settings(${BINARY_NAME}) +target_compile_definitions(${BINARY_NAME} PRIVATE "NOMINMAX") +add_subdirectory("${CMAKE_CURRENT_SOURCE_DIR}/../../iris_integration_test" iris_integration_test) +target_link_libraries(${BINARY_NAME} PRIVATE flutter flutter_wrapper_app iris_integration_test) +target_include_directories(${BINARY_NAME} PRIVATE "${CMAKE_SOURCE_DIR}") +add_dependencies(${BINARY_NAME} flutter_assemble) \ No newline at end of file diff --git a/integration_test_app/windows/runner/Runner.rc b/integration_test_app/windows/runner/Runner.rc new file mode 100644 index 000000000..6f936ade3 --- /dev/null +++ b/integration_test_app/windows/runner/Runner.rc @@ -0,0 +1,121 @@ +// Microsoft Visual C++ generated resource script. +// +#pragma code_page(65001) +#include "resource.h" + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#include "winres.h" + +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// English (United States) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE +BEGIN + "resource.h\0" +END + +2 TEXTINCLUDE +BEGIN + "#include ""winres.h""\r\n" + "\0" +END + +3 TEXTINCLUDE +BEGIN + "\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// Icon +// + +// Icon with lowest ID value placed first to ensure application icon +// remains consistent on all systems. +IDI_APP_ICON ICON "resources\\app_icon.ico" + + +///////////////////////////////////////////////////////////////////////////// +// +// Version +// + +#ifdef FLUTTER_BUILD_NUMBER +#define VERSION_AS_NUMBER FLUTTER_BUILD_NUMBER +#else +#define VERSION_AS_NUMBER 1,0,0 +#endif + +#ifdef FLUTTER_BUILD_NAME +#define VERSION_AS_STRING #FLUTTER_BUILD_NAME +#else +#define VERSION_AS_STRING "1.0.0" +#endif + +VS_VERSION_INFO VERSIONINFO + FILEVERSION VERSION_AS_NUMBER + PRODUCTVERSION VERSION_AS_NUMBER + FILEFLAGSMASK VS_FFI_FILEFLAGSMASK +#ifdef _DEBUG + FILEFLAGS VS_FF_DEBUG +#else + FILEFLAGS 0x0L +#endif + FILEOS VOS__WINDOWS32 + FILETYPE VFT_APP + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904e4" + BEGIN + VALUE "CompanyName", "io.agora.integration_test_app" "\0" + VALUE "FileDescription", "A new Flutter project." "\0" + VALUE "FileVersion", VERSION_AS_STRING "\0" + VALUE "InternalName", "integration_test_app" "\0" + VALUE "LegalCopyright", "Copyright (C) 2021 io.agora.integration_test_app. All rights reserved." "\0" + VALUE "OriginalFilename", "integration_test_app.exe" "\0" + VALUE "ProductName", "integration_test_app" "\0" + VALUE "ProductVersion", VERSION_AS_STRING "\0" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1252 + END +END + +#endif // English (United States) resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// + + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED diff --git a/integration_test_app/windows/runner/flutter_window.cpp b/integration_test_app/windows/runner/flutter_window.cpp new file mode 100644 index 000000000..b43b9095e --- /dev/null +++ b/integration_test_app/windows/runner/flutter_window.cpp @@ -0,0 +1,61 @@ +#include "flutter_window.h" + +#include + +#include "flutter/generated_plugin_registrant.h" + +FlutterWindow::FlutterWindow(const flutter::DartProject& project) + : project_(project) {} + +FlutterWindow::~FlutterWindow() {} + +bool FlutterWindow::OnCreate() { + if (!Win32Window::OnCreate()) { + return false; + } + + RECT frame = GetClientArea(); + + // The size here must match the window dimensions to avoid unnecessary surface + // creation / destruction in the startup path. + flutter_controller_ = std::make_unique( + frame.right - frame.left, frame.bottom - frame.top, project_); + // Ensure that basic setup of the controller was successful. + if (!flutter_controller_->engine() || !flutter_controller_->view()) { + return false; + } + RegisterPlugins(flutter_controller_->engine()); + SetChildContent(flutter_controller_->view()->GetNativeWindow()); + return true; +} + +void FlutterWindow::OnDestroy() { + if (flutter_controller_) { + flutter_controller_ = nullptr; + } + + Win32Window::OnDestroy(); +} + +LRESULT +FlutterWindow::MessageHandler(HWND hwnd, UINT const message, + WPARAM const wparam, + LPARAM const lparam) noexcept { + // Give Flutter, including plugins, an opportunity to handle window messages. + if (flutter_controller_) { + std::optional result = + flutter_controller_->HandleTopLevelWindowProc(hwnd, message, wparam, + lparam); + if (result) { + return *result; + } + } + + switch (message) { + case WM_FONTCHANGE: + flutter_controller_->engine()->ReloadSystemFonts(); + break; + } + + return Win32Window::MessageHandler(hwnd, message, wparam, lparam); +} diff --git a/integration_test_app/windows/runner/flutter_window.h b/integration_test_app/windows/runner/flutter_window.h new file mode 100644 index 000000000..6da0652f0 --- /dev/null +++ b/integration_test_app/windows/runner/flutter_window.h @@ -0,0 +1,33 @@ +#ifndef RUNNER_FLUTTER_WINDOW_H_ +#define RUNNER_FLUTTER_WINDOW_H_ + +#include +#include + +#include + +#include "win32_window.h" + +// A window that does nothing but host a Flutter view. +class FlutterWindow : public Win32Window { + public: + // Creates a new FlutterWindow hosting a Flutter view running |project|. + explicit FlutterWindow(const flutter::DartProject& project); + virtual ~FlutterWindow(); + + protected: + // Win32Window: + bool OnCreate() override; + void OnDestroy() override; + LRESULT MessageHandler(HWND window, UINT const message, WPARAM const wparam, + LPARAM const lparam) noexcept override; + + private: + // The project to run. + flutter::DartProject project_; + + // The Flutter instance hosted by this window. + std::unique_ptr flutter_controller_; +}; + +#endif // RUNNER_FLUTTER_WINDOW_H_ diff --git a/integration_test_app/windows/runner/main.cpp b/integration_test_app/windows/runner/main.cpp new file mode 100644 index 000000000..7c1992f7f --- /dev/null +++ b/integration_test_app/windows/runner/main.cpp @@ -0,0 +1,43 @@ +#include +#include +#include + +#include "flutter_window.h" +#include "utils.h" + +int APIENTRY wWinMain(_In_ HINSTANCE instance, _In_opt_ HINSTANCE prev, + _In_ wchar_t *command_line, _In_ int show_command) { + // Attach to console when present (e.g., 'flutter run') or create a + // new console when running with a debugger. + if (!::AttachConsole(ATTACH_PARENT_PROCESS) && ::IsDebuggerPresent()) { + CreateAndAttachConsole(); + } + + // Initialize COM, so that it is available for use in the library and/or + // plugins. + ::CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED); + + flutter::DartProject project(L"data"); + + std::vector command_line_arguments = + GetCommandLineArguments(); + + project.set_dart_entrypoint_arguments(std::move(command_line_arguments)); + + FlutterWindow window(project); + Win32Window::Point origin(10, 10); + Win32Window::Size size(1280, 720); + if (!window.CreateAndShow(L"integration_test_app", origin, size)) { + return EXIT_FAILURE; + } + window.SetQuitOnClose(true); + + ::MSG msg; + while (::GetMessage(&msg, nullptr, 0, 0)) { + ::TranslateMessage(&msg); + ::DispatchMessage(&msg); + } + + ::CoUninitialize(); + return EXIT_SUCCESS; +} diff --git a/integration_test_app/windows/runner/resource.h b/integration_test_app/windows/runner/resource.h new file mode 100644 index 000000000..66a65d1e4 --- /dev/null +++ b/integration_test_app/windows/runner/resource.h @@ -0,0 +1,16 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Visual C++ generated include file. +// Used by Runner.rc +// +#define IDI_APP_ICON 101 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 102 +#define _APS_NEXT_COMMAND_VALUE 40001 +#define _APS_NEXT_CONTROL_VALUE 1001 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git a/integration_test_app/windows/runner/resources/app_icon.ico b/integration_test_app/windows/runner/resources/app_icon.ico new file mode 100644 index 0000000000000000000000000000000000000000..c04e20caf6370ebb9253ad831cc31de4a9c965f6 GIT binary patch literal 33772 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 literal 0 HcmV?d00001 diff --git a/integration_test_app/windows/runner/runner.exe.manifest b/integration_test_app/windows/runner/runner.exe.manifest new file mode 100644 index 000000000..c977c4a42 --- /dev/null +++ b/integration_test_app/windows/runner/runner.exe.manifest @@ -0,0 +1,20 @@ + + + + + PerMonitorV2 + + + + + + + + + + + + + + + diff --git a/integration_test_app/windows/runner/utils.cpp b/integration_test_app/windows/runner/utils.cpp new file mode 100644 index 000000000..d19bdbbcc --- /dev/null +++ b/integration_test_app/windows/runner/utils.cpp @@ -0,0 +1,64 @@ +#include "utils.h" + +#include +#include +#include +#include + +#include + +void CreateAndAttachConsole() { + if (::AllocConsole()) { + FILE *unused; + if (freopen_s(&unused, "CONOUT$", "w", stdout)) { + _dup2(_fileno(stdout), 1); + } + if (freopen_s(&unused, "CONOUT$", "w", stderr)) { + _dup2(_fileno(stdout), 2); + } + std::ios::sync_with_stdio(); + FlutterDesktopResyncOutputStreams(); + } +} + +std::vector GetCommandLineArguments() { + // Convert the UTF-16 command line arguments to UTF-8 for the Engine to use. + int argc; + wchar_t** argv = ::CommandLineToArgvW(::GetCommandLineW(), &argc); + if (argv == nullptr) { + return std::vector(); + } + + std::vector command_line_arguments; + + // Skip the first argument as it's the binary name. + for (int i = 1; i < argc; i++) { + command_line_arguments.push_back(Utf8FromUtf16(argv[i])); + } + + ::LocalFree(argv); + + return command_line_arguments; +} + +std::string Utf8FromUtf16(const wchar_t* utf16_string) { + if (utf16_string == nullptr) { + return std::string(); + } + int target_length = ::WideCharToMultiByte( + CP_UTF8, WC_ERR_INVALID_CHARS, utf16_string, + -1, nullptr, 0, nullptr, nullptr); + if (target_length == 0) { + return std::string(); + } + std::string utf8_string; + utf8_string.resize(target_length); + int converted_length = ::WideCharToMultiByte( + CP_UTF8, WC_ERR_INVALID_CHARS, utf16_string, + -1, utf8_string.data(), + target_length, nullptr, nullptr); + if (converted_length == 0) { + return std::string(); + } + return utf8_string; +} diff --git a/integration_test_app/windows/runner/utils.h b/integration_test_app/windows/runner/utils.h new file mode 100644 index 000000000..3879d5475 --- /dev/null +++ b/integration_test_app/windows/runner/utils.h @@ -0,0 +1,19 @@ +#ifndef RUNNER_UTILS_H_ +#define RUNNER_UTILS_H_ + +#include +#include + +// Creates a console for the process, and redirects stdout and stderr to +// it for both the runner and the Flutter library. +void CreateAndAttachConsole(); + +// Takes a null-terminated wchar_t* encoded in UTF-16 and returns a std::string +// encoded in UTF-8. Returns an empty std::string on failure. +std::string Utf8FromUtf16(const wchar_t* utf16_string); + +// Gets the command line arguments passed in as a std::vector, +// encoded in UTF-8. Returns an empty std::vector on failure. +std::vector GetCommandLineArguments(); + +#endif // RUNNER_UTILS_H_ diff --git a/integration_test_app/windows/runner/win32_window.cpp b/integration_test_app/windows/runner/win32_window.cpp new file mode 100644 index 000000000..c10f08dc7 --- /dev/null +++ b/integration_test_app/windows/runner/win32_window.cpp @@ -0,0 +1,245 @@ +#include "win32_window.h" + +#include + +#include "resource.h" + +namespace { + +constexpr const wchar_t kWindowClassName[] = L"FLUTTER_RUNNER_WIN32_WINDOW"; + +// The number of Win32Window objects that currently exist. +static int g_active_window_count = 0; + +using EnableNonClientDpiScaling = BOOL __stdcall(HWND hwnd); + +// Scale helper to convert logical scaler values to physical using passed in +// scale factor +int Scale(int source, double scale_factor) { + return static_cast(source * scale_factor); +} + +// Dynamically loads the |EnableNonClientDpiScaling| from the User32 module. +// This API is only needed for PerMonitor V1 awareness mode. +void EnableFullDpiSupportIfAvailable(HWND hwnd) { + HMODULE user32_module = LoadLibraryA("User32.dll"); + if (!user32_module) { + return; + } + auto enable_non_client_dpi_scaling = + reinterpret_cast( + GetProcAddress(user32_module, "EnableNonClientDpiScaling")); + if (enable_non_client_dpi_scaling != nullptr) { + enable_non_client_dpi_scaling(hwnd); + FreeLibrary(user32_module); + } +} + +} // namespace + +// Manages the Win32Window's window class registration. +class WindowClassRegistrar { + public: + ~WindowClassRegistrar() = default; + + // Returns the singleton registar instance. + static WindowClassRegistrar* GetInstance() { + if (!instance_) { + instance_ = new WindowClassRegistrar(); + } + return instance_; + } + + // Returns the name of the window class, registering the class if it hasn't + // previously been registered. + const wchar_t* GetWindowClass(); + + // Unregisters the window class. Should only be called if there are no + // instances of the window. + void UnregisterWindowClass(); + + private: + WindowClassRegistrar() = default; + + static WindowClassRegistrar* instance_; + + bool class_registered_ = false; +}; + +WindowClassRegistrar* WindowClassRegistrar::instance_ = nullptr; + +const wchar_t* WindowClassRegistrar::GetWindowClass() { + if (!class_registered_) { + WNDCLASS window_class{}; + window_class.hCursor = LoadCursor(nullptr, IDC_ARROW); + window_class.lpszClassName = kWindowClassName; + window_class.style = CS_HREDRAW | CS_VREDRAW; + window_class.cbClsExtra = 0; + window_class.cbWndExtra = 0; + window_class.hInstance = GetModuleHandle(nullptr); + window_class.hIcon = + LoadIcon(window_class.hInstance, MAKEINTRESOURCE(IDI_APP_ICON)); + window_class.hbrBackground = 0; + window_class.lpszMenuName = nullptr; + window_class.lpfnWndProc = Win32Window::WndProc; + RegisterClass(&window_class); + class_registered_ = true; + } + return kWindowClassName; +} + +void WindowClassRegistrar::UnregisterWindowClass() { + UnregisterClass(kWindowClassName, nullptr); + class_registered_ = false; +} + +Win32Window::Win32Window() { + ++g_active_window_count; +} + +Win32Window::~Win32Window() { + --g_active_window_count; + Destroy(); +} + +bool Win32Window::CreateAndShow(const std::wstring& title, + const Point& origin, + const Size& size) { + Destroy(); + + const wchar_t* window_class = + WindowClassRegistrar::GetInstance()->GetWindowClass(); + + const POINT target_point = {static_cast(origin.x), + static_cast(origin.y)}; + HMONITOR monitor = MonitorFromPoint(target_point, MONITOR_DEFAULTTONEAREST); + UINT dpi = FlutterDesktopGetDpiForMonitor(monitor); + double scale_factor = dpi / 96.0; + + HWND window = CreateWindow( + window_class, title.c_str(), WS_OVERLAPPEDWINDOW | WS_VISIBLE, + Scale(origin.x, scale_factor), Scale(origin.y, scale_factor), + Scale(size.width, scale_factor), Scale(size.height, scale_factor), + nullptr, nullptr, GetModuleHandle(nullptr), this); + + if (!window) { + return false; + } + + return OnCreate(); +} + +// static +LRESULT CALLBACK Win32Window::WndProc(HWND const window, + UINT const message, + WPARAM const wparam, + LPARAM const lparam) noexcept { + if (message == WM_NCCREATE) { + auto window_struct = reinterpret_cast(lparam); + SetWindowLongPtr(window, GWLP_USERDATA, + reinterpret_cast(window_struct->lpCreateParams)); + + auto that = static_cast(window_struct->lpCreateParams); + EnableFullDpiSupportIfAvailable(window); + that->window_handle_ = window; + } else if (Win32Window* that = GetThisFromHandle(window)) { + return that->MessageHandler(window, message, wparam, lparam); + } + + return DefWindowProc(window, message, wparam, lparam); +} + +LRESULT +Win32Window::MessageHandler(HWND hwnd, + UINT const message, + WPARAM const wparam, + LPARAM const lparam) noexcept { + switch (message) { + case WM_DESTROY: + window_handle_ = nullptr; + Destroy(); + if (quit_on_close_) { + PostQuitMessage(0); + } + return 0; + + case WM_DPICHANGED: { + auto newRectSize = reinterpret_cast(lparam); + LONG newWidth = newRectSize->right - newRectSize->left; + LONG newHeight = newRectSize->bottom - newRectSize->top; + + SetWindowPos(hwnd, nullptr, newRectSize->left, newRectSize->top, newWidth, + newHeight, SWP_NOZORDER | SWP_NOACTIVATE); + + return 0; + } + case WM_SIZE: { + RECT rect = GetClientArea(); + if (child_content_ != nullptr) { + // Size and position the child window. + MoveWindow(child_content_, rect.left, rect.top, rect.right - rect.left, + rect.bottom - rect.top, TRUE); + } + return 0; + } + + case WM_ACTIVATE: + if (child_content_ != nullptr) { + SetFocus(child_content_); + } + return 0; + } + + return DefWindowProc(window_handle_, message, wparam, lparam); +} + +void Win32Window::Destroy() { + OnDestroy(); + + if (window_handle_) { + DestroyWindow(window_handle_); + window_handle_ = nullptr; + } + if (g_active_window_count == 0) { + WindowClassRegistrar::GetInstance()->UnregisterWindowClass(); + } +} + +Win32Window* Win32Window::GetThisFromHandle(HWND const window) noexcept { + return reinterpret_cast( + GetWindowLongPtr(window, GWLP_USERDATA)); +} + +void Win32Window::SetChildContent(HWND content) { + child_content_ = content; + SetParent(content, window_handle_); + RECT frame = GetClientArea(); + + MoveWindow(content, frame.left, frame.top, frame.right - frame.left, + frame.bottom - frame.top, true); + + SetFocus(child_content_); +} + +RECT Win32Window::GetClientArea() { + RECT frame; + GetClientRect(window_handle_, &frame); + return frame; +} + +HWND Win32Window::GetHandle() { + return window_handle_; +} + +void Win32Window::SetQuitOnClose(bool quit_on_close) { + quit_on_close_ = quit_on_close; +} + +bool Win32Window::OnCreate() { + // No-op; provided for subclasses. + return true; +} + +void Win32Window::OnDestroy() { + // No-op; provided for subclasses. +} diff --git a/integration_test_app/windows/runner/win32_window.h b/integration_test_app/windows/runner/win32_window.h new file mode 100644 index 000000000..17ba43112 --- /dev/null +++ b/integration_test_app/windows/runner/win32_window.h @@ -0,0 +1,98 @@ +#ifndef RUNNER_WIN32_WINDOW_H_ +#define RUNNER_WIN32_WINDOW_H_ + +#include + +#include +#include +#include + +// A class abstraction for a high DPI-aware Win32 Window. Intended to be +// inherited from by classes that wish to specialize with custom +// rendering and input handling +class Win32Window { + public: + struct Point { + unsigned int x; + unsigned int y; + Point(unsigned int x, unsigned int y) : x(x), y(y) {} + }; + + struct Size { + unsigned int width; + unsigned int height; + Size(unsigned int width, unsigned int height) + : width(width), height(height) {} + }; + + Win32Window(); + virtual ~Win32Window(); + + // Creates and shows a win32 window with |title| and position and size using + // |origin| and |size|. New windows are created on the default monitor. Window + // sizes are specified to the OS in physical pixels, hence to ensure a + // consistent size to will treat the width height passed in to this function + // as logical pixels and scale to appropriate for the default monitor. Returns + // true if the window was created successfully. + bool CreateAndShow(const std::wstring& title, + const Point& origin, + const Size& size); + + // Release OS resources associated with window. + void Destroy(); + + // Inserts |content| into the window tree. + void SetChildContent(HWND content); + + // Returns the backing Window handle to enable clients to set icon and other + // window properties. Returns nullptr if the window has been destroyed. + HWND GetHandle(); + + // If true, closing this window will quit the application. + void SetQuitOnClose(bool quit_on_close); + + // Return a RECT representing the bounds of the current client area. + RECT GetClientArea(); + + protected: + // Processes and route salient window messages for mouse handling, + // size change and DPI. Delegates handling of these to member overloads that + // inheriting classes can handle. + virtual LRESULT MessageHandler(HWND window, + UINT const message, + WPARAM const wparam, + LPARAM const lparam) noexcept; + + // Called when CreateAndShow is called, allowing subclass window-related + // setup. Subclasses should return false if setup fails. + virtual bool OnCreate(); + + // Called when Destroy is called. + virtual void OnDestroy(); + + private: + friend class WindowClassRegistrar; + + // OS callback called by message pump. Handles the WM_NCCREATE message which + // is passed when the non-client area is being created and enables automatic + // non-client DPI scaling so that the non-client area automatically + // responsponds to changes in DPI. All other messages are handled by + // MessageHandler. + static LRESULT CALLBACK WndProc(HWND const window, + UINT const message, + WPARAM const wparam, + LPARAM const lparam) noexcept; + + // Retrieves a class instance pointer for |window| + static Win32Window* GetThisFromHandle(HWND const window) noexcept; + + bool quit_on_close_ = false; + + // window handle for top level window. + HWND window_handle_ = nullptr; + + // window handle for hosted content. + HWND child_content_ = nullptr; +}; + +#endif // RUNNER_WIN32_WINDOW_H_ diff --git a/ios/Classes/AgoraRtcChannelPlugin.h b/ios/Classes/AgoraRtcChannelPlugin.h new file mode 100644 index 000000000..2fe318a05 --- /dev/null +++ b/ios/Classes/AgoraRtcChannelPlugin.h @@ -0,0 +1,10 @@ +#ifndef AgoraRtcChannelPlugin_h +#define AgoraRtcChannelPlugin_h + +#import + +@interface AgoraRtcChannelPlugin : NSObject +- (instancetype)initWith:(void *)irisRtcEngine binaryMessenger:(NSObject*)messenger; +@end + +#endif /* AgoraRtcChannelPlugin_h */ diff --git a/ios/Classes/AgoraRtcChannelPlugin.mm b/ios/Classes/AgoraRtcChannelPlugin.mm new file mode 100644 index 000000000..aa9a76ecd --- /dev/null +++ b/ios/Classes/AgoraRtcChannelPlugin.mm @@ -0,0 +1,64 @@ +#import +#import "AgoraRtcChannelPlugin.h" +#import +#import "CallApiMethodCallHandler.h" +#import "FlutterIrisEventHandler.h" + + +@interface AgoraRtcChannelPlugin () + +@property(nonatomic) agora::iris::rtc::IrisRtcEngine *irisRtcEngine; + + +@property(nonatomic) FlutterIrisEventHandler *eventHandler; + +@property(nonatomic) FlutterEventSink eventSink; + +@property(nonatomic) CallApiMethodCallHandler *callApiMethodCallHandler; + +@end + +@implementation AgoraRtcChannelPlugin + +- (instancetype)initWith:(void *)irisRtcEngine binaryMessenger:(NSObject*)messenger { + self.irisRtcEngine = (agora::iris::rtc::IrisRtcEngine *)irisRtcEngine; + + self.eventHandler = [[RtcChannelFlutterIrisEventHandler alloc] initWith:self.irisRtcEngine]; + self.callApiMethodCallHandler = [[RtcChannelCallApiMethodCallHandler alloc] initWith:self.irisRtcEngine]; + + FlutterMethodChannel *methodChannel = + [FlutterMethodChannel methodChannelWithName:@"agora_rtc_channel" + binaryMessenger:messenger]; + FlutterEventChannel *eventChannel = + [FlutterEventChannel eventChannelWithName:@"agora_rtc_channel/events" + binaryMessenger:messenger]; + __weak __typeof(self) weakSelf = self; + [methodChannel setMethodCallHandler:^(FlutterMethodCall * _Nonnull call, FlutterResult _Nonnull result) { + if (weakSelf) { + [[weakSelf callApiMethodCallHandler] onMethodCall:call _:result]; + } + + }]; + + [eventChannel setStreamHandler:self.eventHandler]; + + return self; +} + +- (FlutterError *_Nullable)onCancelWithArguments:(id _Nullable)arguments { + self.eventSink = nil; + return nil; +} + +- (FlutterError *_Nullable)onListenWithArguments:(id _Nullable)arguments + eventSink: + (nonnull FlutterEventSink)events { + self.eventSink = events; + return nil; +} + +- (void)dealloc { + self.irisRtcEngine->channel()->SetEventHandler(NULL); +} + +@end diff --git a/ios/Classes/AgoraRtcChannelPlugin.swift b/ios/Classes/AgoraRtcChannelPlugin.swift deleted file mode 100644 index d56c5aaae..000000000 --- a/ios/Classes/AgoraRtcChannelPlugin.swift +++ /dev/null @@ -1,89 +0,0 @@ -// -// AgoraRtcChannelPlugin.swift -// agora_rtc_engine -// -// Created by LXH on 2020/6/29. -// - -import Foundation - -public class AgoraRtcChannelPlugin: NSObject, FlutterPlugin, FlutterStreamHandler { - private final weak var rtcEnginePlugin: SwiftAgoraRtcEnginePlugin? - private var methodChannel: FlutterMethodChannel? - private var eventChannel: FlutterEventChannel? - private var eventSink: FlutterEventSink? = nil - private lazy var manager: RtcChannelManager = { - return RtcChannelManager() { [weak self] methodName, data in - self?.emit(methodName, data) - } - }() - - init(_ rtcEnginePlugin: SwiftAgoraRtcEnginePlugin) { - self.rtcEnginePlugin = rtcEnginePlugin - } - - public static func register(with registrar: FlutterPluginRegistrar) { - - } - - public func initPlugin(_ registrar: FlutterPluginRegistrar) { - methodChannel = FlutterMethodChannel(name: "agora_rtc_channel", binaryMessenger: registrar.messenger()) - eventChannel = FlutterEventChannel(name: "agora_rtc_channel/events", binaryMessenger: registrar.messenger()) - registrar.addMethodCallDelegate(self, channel: methodChannel!) - eventChannel?.setStreamHandler(self) - } - - public func detachFromEngine(for registrar: FlutterPluginRegistrar) { - methodChannel?.setMethodCallHandler(nil) - eventChannel?.setStreamHandler(nil) - manager.Release() - } - - public func onListen(withArguments arguments: Any?, eventSink events: @escaping FlutterEventSink) -> FlutterError? { - eventSink = events - return nil - } - - public func onCancel(withArguments arguments: Any?) -> FlutterError? { - eventSink = nil - return nil - } - - private func emit(_ methodName: String, _ data: Dictionary?) { - var event: Dictionary = ["methodName": methodName] - if let `data` = data { - event.merge(data) { (current, _) in - current - } - } - eventSink?(event) - } - - private weak var engine: AgoraRtcEngineKit? { - return rtcEnginePlugin?.engine - } - - func channel(_ channelId: String) -> AgoraRtcChannel? { - return manager[channelId] - } - - public func handle(_ call: FlutterMethodCall, result: @escaping FlutterResult) { - if let params = call.arguments as? NSDictionary { - let selector = NSSelectorFromString(call.method + "::") - if manager.responds(to: selector) { - if call.method == "create" { - params.setValue(engine, forKey: "engine") - } - manager.perform(selector, with: params, with: ResultCallback(result)) - return - } - } else { - let selector = NSSelectorFromString(call.method + ":") - if manager.responds(to: selector) { - manager.perform(selector, with: ResultCallback(result)) - return - } - } - result(FlutterMethodNotImplemented) - } -} diff --git a/ios/Classes/AgoraRtcEnginePlugin.h b/ios/Classes/AgoraRtcEnginePlugin.h index 942f57d8a..7e46e56cd 100644 --- a/ios/Classes/AgoraRtcEnginePlugin.h +++ b/ios/Classes/AgoraRtcEnginePlugin.h @@ -1,5 +1,5 @@ #import #import -@interface AgoraRtcEnginePlugin : NSObject +@interface AgoraRtcEnginePlugin : NSObject @end diff --git a/ios/Classes/AgoraRtcEnginePlugin.m b/ios/Classes/AgoraRtcEnginePlugin.m deleted file mode 100644 index 8b15c2985..000000000 --- a/ios/Classes/AgoraRtcEnginePlugin.m +++ /dev/null @@ -1,15 +0,0 @@ -#import "AgoraRtcEnginePlugin.h" -#if __has_include() -#import -#else -// Support project import fallback if the generated compatibility header -// is not copied when this plugin is created as a library. -// https://forums.swift.org/t/swift-static-libraries-dont-copy-generated-objective-c-header/19816 -#import "agora_rtc_engine-Swift.h" -#endif - -@implementation AgoraRtcEnginePlugin -+ (void)registerWithRegistrar:(NSObject*)registrar { - [SwiftAgoraRtcEnginePlugin registerWithRegistrar:registrar]; -} -@end diff --git a/ios/Classes/AgoraRtcEnginePlugin.mm b/ios/Classes/AgoraRtcEnginePlugin.mm new file mode 100644 index 000000000..8cc2aeef1 --- /dev/null +++ b/ios/Classes/AgoraRtcEnginePlugin.mm @@ -0,0 +1,120 @@ +#import "AgoraRtcEnginePlugin.h" +#import +#import +#import "CallApiMethodCallHandler.h" +#import "FlutterIrisEventHandler.h" +#import "AgoraRtcChannelPlugin.h" +#import "AgoraSurfaceViewFactory.h" +#import "AgoraTextureViewFactory.h" +#import "FlutterIrisEventHandler.h" + +@interface AgoraRtcEnginePlugin () + +@property(nonatomic) agora::iris::rtc::IrisRtcEngine *irisRtcEngine; + +// TODO(littlegnal): Lazy init videoFrameBufferManager +@property(nonatomic) agora::iris::IrisVideoFrameBufferManager *videoFrameBufferManager; + +@property(nonatomic) FlutterIrisEventHandler *flutterIrisEventHandler; + +@property(nonatomic) CallApiMethodCallHandler *callApiMethodCallHandler; + +@property(nonatomic) AgoraRtcChannelPlugin *agoraRtcChannelPlugin; + +@property(nonatomic, strong) AgoraTextureViewFactory *factory; + +@property(nonatomic) NSObject *registrar; + +@end + +@implementation AgoraRtcEnginePlugin ++ (void)registerWithRegistrar:(NSObject *)registrar { + FlutterMethodChannel *methodChannel = + [FlutterMethodChannel methodChannelWithName:@"agora_rtc_engine" + binaryMessenger:[registrar messenger]]; + FlutterEventChannel *eventChannel = + [FlutterEventChannel eventChannelWithName:@"agora_rtc_engine/events" + binaryMessenger:[registrar messenger]]; + AgoraRtcEnginePlugin *instance = [[AgoraRtcEnginePlugin alloc] init]; + instance.registrar = registrar; + [registrar addMethodCallDelegate:instance channel:methodChannel]; + + instance.flutterIrisEventHandler = [[FlutterIrisEventHandler alloc] initWith:instance.irisRtcEngine]; + + [eventChannel setStreamHandler:instance.flutterIrisEventHandler]; + + instance.agoraRtcChannelPlugin = [[AgoraRtcChannelPlugin alloc] initWith:[instance irisRtcEngine] binaryMessenger:[registrar messenger]]; + + [instance + setFactory:[[AgoraTextureViewFactory alloc] initWithRegistrar:registrar]]; + + [registrar registerViewFactory:[[AgoraSurfaceViewFactory alloc] + initWith:[registrar messenger] + engine:instance.irisRtcEngine] + withId:@"AgoraSurfaceView"]; +} + +- (instancetype)init { + self = [super init]; + if (self) { + self.irisRtcEngine = new agora::iris::rtc::IrisRtcEngine; + self.videoFrameBufferManager = new agora::iris::IrisVideoFrameBufferManager; + self.irisRtcEngine->raw_data()->Attach(self.videoFrameBufferManager); + + self.callApiMethodCallHandler = [[CallApiMethodCallHandler alloc] initWith:self.irisRtcEngine]; + } + return self; +} + +- (void)dealloc { + delete self.irisRtcEngine; + delete self.videoFrameBufferManager; +} + +- (void)handleMethodCall:(FlutterMethodCall *)call + result:(FlutterResult)result { +#if DEBUG + if ([@"getIrisRtcEngineIntPtr" isEqualToString:call.method]) { + result(@((intptr_t)self.irisRtcEngine)); + return; + } +#endif + + if ([@"createTextureRender" isEqualToString:call.method]) { + int64_t textureId = [self.factory + createTextureRenderer:[self videoFrameBufferManager]]; + result(@(textureId)); + } else if ([@"destroyTextureRender" isEqualToString:call.method]) { + NSNumber *textureId = call.arguments[@"id"]; + [self.factory destroyTextureRenderer:[textureId integerValue]]; + result(nil); + } else if ([@"getAssetAbsolutePath" isEqualToString:call.method]) { + [self getAssetAbsolutePath:call result:result]; + } else { + [[self callApiMethodCallHandler] onMethodCall:call _:result]; + } +} + +- (void)getAssetAbsolutePath:(FlutterMethodCall *)call + result:(FlutterResult)result { + NSString *assetPath = (NSString *)[call arguments]; + if (assetPath) { + NSString *assetKey = [[self registrar] lookupKeyForAsset:assetPath]; + if (assetKey) { + NSString *realPath = [[NSBundle mainBundle] pathForResource:assetKey ofType:nil]; + result(realPath); + return; + } + result([FlutterError + errorWithCode:@"FileNotFoundException" + message:nil + details:nil]); + return; + } + result([FlutterError + errorWithCode:@"IllegalArgumentException" + message:nil + details:nil]); +} + +@end diff --git a/ios/Classes/AgoraSurfaceViewFactory.h b/ios/Classes/AgoraSurfaceViewFactory.h new file mode 100644 index 000000000..dbe80afaa --- /dev/null +++ b/ios/Classes/AgoraSurfaceViewFactory.h @@ -0,0 +1,14 @@ +#ifndef AgoraSurfaceViewFactory_h +#define AgoraSurfaceViewFactory_h + +#import + +@interface AgoraSurfaceViewFactory : NSObject + +- (instancetype)initWith:(NSObject *)messenger + engine:(void *)engine; + +@end + + +#endif /* AgoraSurfaceViewFactory_h */ diff --git a/ios/Classes/AgoraSurfaceViewFactory.mm b/ios/Classes/AgoraSurfaceViewFactory.mm new file mode 100644 index 000000000..0ffc9e5fa --- /dev/null +++ b/ios/Classes/AgoraSurfaceViewFactory.mm @@ -0,0 +1,187 @@ +#import "AgoraSurfaceViewFactory.h" +#import +#import "CallApiMethodCallHandler.h" + +@interface AgoraSurfaceView : NSObject + +@property(nonatomic, strong) UIView *parentView; + +@property(nonatomic, strong) UIView *surfaceView; + +@property(nonatomic, strong) FlutterMethodChannel *methodChannel; + +@property(nonatomic) agora::iris::rtc::IrisRtcEngine *engine; + +@property(nonatomic) CallApiMethodCallHandler *callApiMethodCallHandler; + +- (instancetype)initWith:(NSObject *)messenger + engine:(agora::iris::rtc::IrisRtcEngine *)engine + frame:(CGRect)frame + viewId:(int64_t)viewId + args:(NSDictionary *)args; + +- (UIView *)getIrisRenderView; + +- (void)updateIrisRenderView; + +- (NSString *)observerForKeyPath; + +@end + +@interface SurfaceViewCallApiMethodCallHandler : CallApiMethodCallHandler +@property(nonatomic) agora::iris::rtc::IrisRtcEngine *irisRtcEngine; +@property(nonatomic) AgoraSurfaceView *platformView; +- (instancetype)initWith:(agora::iris::rtc::IrisRtcEngine *)irisRtcEngine platformView:(AgoraSurfaceView*) platformView; +@end + +@implementation SurfaceViewCallApiMethodCallHandler + +- (instancetype)initWith:(agora::iris::rtc::IrisRtcEngine *)irisRtcEngine platformView:(AgoraSurfaceView *) platformView { + self.irisRtcEngine = irisRtcEngine; + self.platformView = platformView; + return self; +} + +- (int)callApi:(NSNumber *)apiType _:(NSString *)params _:(char *)result { + [self.platformView updateIrisRenderView]; + return self.irisRtcEngine->CallApi((ApiTypeEngine)[apiType unsignedIntValue], [params UTF8String], (__bridge void *)[self.platformView getIrisRenderView], result); +} + +- (int)callApiWithBuffer:(NSNumber *)apiType _:(NSString *)params _:(void *)buffer _:(char *)result { + [self.platformView updateIrisRenderView]; + return self.irisRtcEngine->CallApi((ApiTypeEngine)[apiType unsignedIntValue], [params UTF8String], (__bridge void *)[self.platformView getIrisRenderView], result); +} + +@end + + + +@implementation AgoraSurfaceView + +- (instancetype)initWith:(NSObject *)messenger + engine:(agora::iris::rtc::IrisRtcEngine *)engine + frame:(CGRect)frame + viewId:(int64_t)viewId + args:(NSDictionary *)args { + if (self = [super init]) { + self.parentView = [[UIView alloc] initWithFrame:frame]; + CGRect cgRect = CGRectMake(0, 0, frame.size.width, frame.size.height); + self.surfaceView = [[UIView alloc] initWithFrame: cgRect]; + [[self parentView] addSubview:self.surfaceView]; + + [self.parentView addObserver:self forKeyPath:[self observerForKeyPath] options:NSKeyValueObservingOptionNew context:nil]; + + self.methodChannel = [FlutterMethodChannel + methodChannelWithName: + [NSString + stringWithFormat:@"agora_rtc_engine/surface_view_%lld", + viewId] + binaryMessenger:messenger]; + self.engine = engine; + + self.callApiMethodCallHandler = [[SurfaceViewCallApiMethodCallHandler alloc] initWith:self.engine platformView:self]; + + + __weak __typeof(self) weakSelf = self; + [self.methodChannel setMethodCallHandler:^(FlutterMethodCall *_Nonnull call, + FlutterResult _Nonnull result) { + if (weakSelf != nil) { + [weakSelf onMethodCall:call result:result]; + } + }]; + for (NSString *key in args) { + [self onMethodCall:[FlutterMethodCall + methodCallWithMethodName:key + arguments:[args objectForKey:key]] + result:^(id _Nullable result) { + // Do nothing + }]; + } + } + return self; +} + +- (void)dealloc { + [self removeObserver:self.parentView forKeyPath:[self observerForKeyPath] context:nil]; + [self.methodChannel setMethodCallHandler:nil]; +} + +- (UIView *)getIrisRenderView { + return self.surfaceView; +} + +- (void)updateIrisRenderView { + [[self surfaceView] removeFromSuperview]; + + CGRect cgRect = CGRectMake(0, 0, self.parentView.bounds.size.width, self.parentView.bounds.size.height); + + self.surfaceView = [[UIView alloc] initWithFrame: cgRect]; + + [[self parentView] addSubview:self.surfaceView]; +} + +- (NSString *)observerForKeyPath { + return @"frame"; +} + +- (nonnull UIView *)view { + return self.parentView; +} + +- (void)onMethodCall:(FlutterMethodCall *)call result:(FlutterResult)result { + [[self callApiMethodCallHandler] onMethodCall:call _:result]; +} + +- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context { + if([keyPath isEqualToString:[self observerForKeyPath]]) { + id newKey = change[NSKeyValueChangeNewKey]; + if (newKey != NULL) { + CGRect rect = [newKey CGRectValue]; + CGRect cgRect; + CGPoint cgPoint; + cgPoint.x = 0; + cgPoint.y = 0; + + cgRect.origin = cgPoint; + cgRect.size = rect.size; + [[self surfaceView] setFrame:cgRect]; + } + } +} + +@end + +@interface AgoraSurfaceViewFactory () + +@property(nonatomic, strong) NSObject *messenger; + +@property(nonatomic) agora::iris::rtc::IrisRtcEngine *engine; + +@end + +@implementation AgoraSurfaceViewFactory + +- (instancetype)initWith:(NSObject *)messenger + engine:(void *)engine { + if (self = [super init]) { + self.messenger = messenger; + self.engine = (agora::iris::rtc::IrisRtcEngine *)engine; + } + return self; +} + +- (nonnull NSObject *)createWithFrame:(CGRect)frame + viewIdentifier:(int64_t)viewId + arguments:(id _Nullable)args { + return [[AgoraSurfaceView alloc] initWith:self.messenger + engine:self.engine + frame:frame + viewId:viewId + args:args]; +} + +- (NSObject *)createArgsCodec { + return [FlutterStandardMessageCodec sharedInstance]; +} + +@end diff --git a/ios/Classes/AgoraSurfaceViewFactory.swift b/ios/Classes/AgoraSurfaceViewFactory.swift deleted file mode 100644 index afecddeb3..000000000 --- a/ios/Classes/AgoraSurfaceViewFactory.swift +++ /dev/null @@ -1,105 +0,0 @@ -// -// AgoraSurfaceViewFactory.swift -// agora_rtc_engine -// -// Created by LXH on 2020/6/28. -// - -import Foundation - -class AgoraSurfaceViewFactory: NSObject, FlutterPlatformViewFactory { - private final weak var messager: FlutterBinaryMessenger? - private final weak var rtcEnginePlugin: SwiftAgoraRtcEnginePlugin? - private final weak var rtcChannelPlugin: AgoraRtcChannelPlugin? - - init(_ messager: FlutterBinaryMessenger, _ rtcEnginePlugin: SwiftAgoraRtcEnginePlugin, _ rtcChannelPlugin: AgoraRtcChannelPlugin) { - self.messager = messager - self.rtcEnginePlugin = rtcEnginePlugin - self.rtcChannelPlugin = rtcChannelPlugin - } - - func createArgsCodec() -> FlutterMessageCodec & NSObjectProtocol { - FlutterStandardMessageCodec.sharedInstance() - } - - func create(withFrame frame: CGRect, viewIdentifier viewId: Int64, arguments args: Any?) -> FlutterPlatformView { - return AgoraSurfaceView(messager!, frame, viewId, args as? Dictionary, rtcEnginePlugin!, rtcChannelPlugin!) - } -} - -class AgoraSurfaceView: NSObject, FlutterPlatformView { - private final weak var rtcEnginePlugin: SwiftAgoraRtcEnginePlugin? - private final weak var rtcChannelPlugin: AgoraRtcChannelPlugin? - private let _view: RtcSurfaceView - private let channel: FlutterMethodChannel - - init(_ messager: FlutterBinaryMessenger, _ frame: CGRect, _ viewId: Int64, _ args: Dictionary?, _ rtcEnginePlugin: SwiftAgoraRtcEnginePlugin, _ rtcChannelPlugin: AgoraRtcChannelPlugin) { - self.rtcEnginePlugin = rtcEnginePlugin - self.rtcChannelPlugin = rtcChannelPlugin - self._view = RtcSurfaceView(frame: frame) - self.channel = FlutterMethodChannel(name: "agora_rtc_engine/surface_view_\(viewId)", binaryMessenger: messager) - super.init() - if let map = args { - setData(map["data"] as! NSDictionary) - setRenderMode((map["renderMode"] as! NSNumber).uintValue) - setMirrorMode((map["mirrorMode"] as! NSNumber).uintValue) - } - channel.setMethodCallHandler { [weak self] (call, result) in - var args = [String: Any?]() - if let arguments = call.arguments { - args = arguments as! Dictionary - } - switch call.method { - case "setData": - self?.setData(args["data"] as! NSDictionary) - case "setRenderMode": - self?.setRenderMode((args["renderMode"] as! NSNumber).uintValue) - case "setMirrorMode": - self?.setMirrorMode((args["mirrorMode"] as! NSNumber).uintValue) - default: - result(FlutterMethodNotImplemented) - } - } - } - - func view() -> UIView { - return _view - } - - deinit { - channel.setMethodCallHandler(nil) - } - - func setData(_ data: NSDictionary) { - var channel: AgoraRtcChannel? = nil - if let channelId = data["channelId"] as? String { - channel = getChannel(channelId) - } - if let `engine` = engine { - _view.setData(engine, channel, (data["uid"] as! NSNumber).uintValue) - } - } - - func setRenderMode(_ renderMode: UInt) { - if let `engine` = engine { - _view.setRenderMode(engine, renderMode) - } - } - - func setMirrorMode(_ mirrorMode: UInt) { - if let `engine` = engine { - _view.setMirrorMode(engine, mirrorMode) - } - } - - private var engine: AgoraRtcEngineKit? { - return rtcEnginePlugin?.engine - } - - private func getChannel(_ channelId: String?) -> AgoraRtcChannel? { - guard let `channelId` = channelId else { - return nil - } - return rtcChannelPlugin?.channel(channelId) - } -} diff --git a/ios/Classes/AgoraTextureViewFactory.h b/ios/Classes/AgoraTextureViewFactory.h new file mode 100644 index 000000000..635c199f0 --- /dev/null +++ b/ios/Classes/AgoraTextureViewFactory.h @@ -0,0 +1,14 @@ +#ifndef AgoraTextureViewFactory_h +#define AgoraTextureViewFactory_h + +#import + +@interface AgoraTextureViewFactory : NSObject +- (instancetype)initWithRegistrar:(NSObject *)registrar; + +- (int64_t)createTextureRenderer:(void *)renderer; + +- (BOOL)destroyTextureRenderer:(int64_t)textureId; +@end + +#endif /* AgoraTextureViewFactory_h */ diff --git a/ios/Classes/AgoraTextureViewFactory.mm b/ios/Classes/AgoraTextureViewFactory.mm new file mode 100644 index 000000000..bc73d8d40 --- /dev/null +++ b/ios/Classes/AgoraTextureViewFactory.mm @@ -0,0 +1,192 @@ +#import "AgoraTextureViewFactory.h" +#import +#import +#import + +using namespace agora::iris; +using namespace agora::iris::rtc; + +@interface TextureRenderer : NSObject +@property(nonatomic, weak) NSObject *textureRegistry; +@property(nonatomic, assign) int64_t textureId; +@property(nonatomic, strong) FlutterMethodChannel *channel; +@property(nonatomic) CVPixelBufferRef buffer_cache; +@property(nonatomic) CVPixelBufferRef buffer_temp; +@property(nonatomic) IrisVideoFrameBufferManager *renderer; +@property(nonatomic, strong) dispatch_semaphore_t lock; + +- (instancetype) + initWithTextureRegistry:(NSObject *)textureRegistry + messenger:(NSObject *)messenger + renderer:(IrisVideoFrameBufferManager *)renderer; + +- (void)destroy; +@end + +namespace { +class RendererDelegate : public IrisVideoFrameBufferDelegate { +public: + RendererDelegate(void *renderer) : renderer_(renderer) {} + + void OnVideoFrameReceived(const IrisVideoFrame &video_frame, + const IrisVideoFrameBufferConfig *config, + bool resize) override { + @autoreleasepool { + TextureRenderer *renderer = (__bridge TextureRenderer *)renderer_; + CVPixelBufferRef buffer = NULL; + NSDictionary *dic = [NSDictionary + dictionaryWithObjectsAndKeys: + @(YES), kCVPixelBufferCGBitmapContextCompatibilityKey, @(YES), + kCVPixelBufferCGImageCompatibilityKey, @(YES), + kCVPixelBufferOpenGLCompatibilityKey, @(YES), + kCVPixelBufferMetalCompatibilityKey, nil]; + CVPixelBufferCreate(kCFAllocatorDefault, video_frame.width, + video_frame.height, kCVPixelFormatType_32BGRA, + (__bridge CFDictionaryRef)dic, &buffer); + + CVPixelBufferLockBaseAddress(buffer, 0); + void *copyBaseAddress = CVPixelBufferGetBaseAddress(buffer); + memcpy(copyBaseAddress, video_frame.y_buffer, + video_frame.y_buffer_length); + CVPixelBufferUnlockBaseAddress(buffer, 0); + + dispatch_semaphore_wait(renderer.lock, DISPATCH_TIME_FOREVER); + if (renderer.buffer_cache) { + CVPixelBufferRelease(renderer.buffer_cache); + } + renderer.buffer_cache = buffer; + dispatch_semaphore_signal(renderer.lock); + + [renderer.textureRegistry textureFrameAvailable:renderer.textureId]; + } + } + +public: + void *renderer_; +}; +} + +@interface TextureRenderer () +@property(nonatomic) RendererDelegate *delegate; +@end + +@implementation TextureRenderer +- (instancetype) + initWithTextureRegistry:(NSObject *)textureRegistry + messenger:(NSObject *)messenger + renderer:(IrisVideoFrameBufferManager *)renderer { + self = [super init]; + if (self) { + self.textureRegistry = textureRegistry; + self.textureId = [self.textureRegistry registerTexture:self]; + self.channel = [FlutterMethodChannel + methodChannelWithName: + [NSString stringWithFormat:@"agora_rtc_engine/texture_render_%lld", + self.textureId] + binaryMessenger:messenger]; + self.renderer = renderer; + self.lock = dispatch_semaphore_create(1); + self.delegate = new ::RendererDelegate((__bridge void *)self); + __weak __typeof(self) weakSelf = self; + [self.channel setMethodCallHandler:^(FlutterMethodCall *_Nonnull call, + FlutterResult _Nonnull result) { + if (!weakSelf) { + return; + } + if ([@"setData" isEqualToString:call.method]) { + NSDictionary *data = call.arguments[@"data"]; + NSNumber *uid = data[@"uid"]; + NSString *channelId = data[@"channelId"]; + + IrisVideoFrameBuffer buffer(kVideoFrameTypeBGRA, + weakSelf.delegate); + IrisVideoFrameBufferConfig config; + + config.id = [uid unsignedIntValue]; + if (config.id == 0) { + config.type = IrisVideoSourceType::kVideoSourceTypeCameraPrimary; + } else { + config.type = IrisVideoSourceType::kVideoSourceTypeRemote; + } + if (channelId && (NSNull *)channelId != [NSNull null]) { + strcpy(config.key, [channelId UTF8String]); + + } else { + strcpy(config.key, ""); + } + renderer->EnableVideoFrameBuffer(buffer, &config); + } + }]; + } + return self; +} + +- (void)dealloc { + [self destroy]; + if (self.buffer_cache) { + CVPixelBufferRelease(self.buffer_cache); + } +// if (self.buffer_temp) { +// CVPixelBufferRelease(self.buffer_temp); +// } +} + +- (void)destroy { + [self.channel setMethodCallHandler:nil]; + self.renderer->DisableVideoFrameBuffer(self.delegate); + [self.textureRegistry unregisterTexture:self.textureId]; +} + +- (CVPixelBufferRef)copyPixelBuffer { + dispatch_semaphore_wait(self.lock, DISPATCH_TIME_FOREVER); +// CVPixelBufferRelease(self.buffer_temp); + self.buffer_temp = self.buffer_cache; + CVPixelBufferRetain(self.buffer_temp); + dispatch_semaphore_signal(self.lock); + return self.buffer_temp; +// return nil; +} + +- (void)onTextureUnregistered:(NSObject *)texture { +} +@end + +@interface AgoraTextureViewFactory () +@property(nonatomic, weak) NSObject *registrar; +@property(nonatomic, weak) NSObject *messenger; +@property(nonatomic, strong) + NSMutableDictionary *renderers; +@end + +@implementation AgoraTextureViewFactory +- (instancetype)initWithRegistrar: + (NSObject *)registrar { + self = [super init]; + if (self) { + self.registrar = [registrar textures]; + self.messenger = [registrar messenger]; + self.renderers = [NSMutableDictionary new]; + } + return self; +} + +- (int64_t)createTextureRenderer:(void *)renderer { + TextureRenderer *texture = [[TextureRenderer alloc] + initWithTextureRegistry:self.registrar + messenger:self.messenger + renderer:(IrisVideoFrameBufferManager *)renderer]; + int64_t textureId = [texture textureId]; + self.renderers[@(textureId)] = texture; + return textureId; +} + +- (BOOL)destroyTextureRenderer:(int64_t)textureId { + TextureRenderer *texture = [self.renderers objectForKey:@(textureId)]; + if (texture != nil) { + [texture destroy]; + [self.renderers removeObjectForKey:@(textureId)]; + return YES; + } + return NO; +} +@end diff --git a/ios/Classes/Base/.gitignore b/ios/Classes/Base/.gitignore deleted file mode 100644 index 9f11b755a..000000000 --- a/ios/Classes/Base/.gitignore +++ /dev/null @@ -1 +0,0 @@ -.idea/ diff --git a/ios/Classes/Base/AgoraRtcEngineKit.h b/ios/Classes/Base/AgoraRtcEngineKit.h deleted file mode 100644 index cebf95c80..000000000 --- a/ios/Classes/Base/AgoraRtcEngineKit.h +++ /dev/null @@ -1,119 +0,0 @@ -// -// AgoraRtcEngineKit.h -// RCTAgora -// -// Created by LXH on 2020/4/22. -// Copyright © 2020 Syan. All rights reserved. -// - -#import - -typedef NS_ENUM(NSUInteger, AgoraRtcQualityReportFormat) { - AgoraRtc_QualityReportFormat_Json = 0, - AgoraRtc_QualityReportFormat_Html = 1, -}; - -typedef NS_ENUM(NSUInteger, AgoraRtcAppType) { - AgoraRtc_APP_TYPE_NATIVE = 0, - AgoraRtc_APP_TYPE_COCOS = 1, - AgoraRtc_APP_TYPE_UNITY = 2, - AgoraRtc_APP_TYPE_ELECTRON = 3, - AgoraRtc_APP_TYPE_FLUTTER = 4, - AgoraRtc_APP_TYPE_UNREAL = 5, - AgoraRtc_APP_TYPE_XAMARIN = 6, - AgoraRtc_APP_TYPE_APICLOUD = 7, - AgoraRtc_APP_TYPE_REACTNATIVE = 8 -}; - -@protocol AgoraRtcEngineExtensionDelegate -@optional -- (void)rtcEngine:(AgoraRtcEngineKit *_Nonnull)engine - audioTransportQualityOfUid:(NSUInteger)uid - delay:(NSUInteger)delay - lost:(NSUInteger)lost; -- (void)rtcEngine:(AgoraRtcEngineKit *_Nonnull)engine - videoTransportQualityOfUid:(NSUInteger)uid - delay:(NSUInteger)delay - lost:(NSUInteger)lost; -@end - -@interface AgoraRtcEngineKit (AgoraExtension) - -+ (instancetype _Nonnull)sharedEngineWithAppId:(NSString *_Nonnull)appId - extensionDelegate: - (id _Nullable) - delegate; - -/** Sets the profile to control the RTC engine. - * - * @param profile SDK profile in JSON format. - * @param merge Whether to merge the profile data with the original value. - */ -- (int)setProfile:(NSString *_Nonnull)profile merge:(BOOL)merge; - -/** Set wrapper frame type by language wrapper. - * - * @param appType wrapper frame type. - */ -- (int)setAppType:(AgoraRtcAppType)appType; - -/** END OF COMMON METHODS */ - -/** BEGIN OF AUDIO METHODS */ - -/** - * Enable recap - * - * @param interval ≤ 0: Disabled, > 0: Interval in ms. - */ -- (int)enableRecap:(NSInteger)interval; - -/** - * Start playing recap conversation - * - */ -- (int)playRecap; - -- (int)enableAudioQualityIndication:(BOOL)enabled; -- (int)enableTransportQualityIndication:(BOOL)enabled; - -- (int)setVideoProfileEx:(NSInteger)width - andHeight:(NSInteger)height - andFrameRate:(NSInteger)frameRate - andBitrate:(NSInteger)andBitrate; - -- (int)sendReportData:(NSData *_Nonnull)data type:(NSInteger)type; -/** END OF AUDIO METHODS */ - -/** Queries internal states - * @param parameters - * json string, array type - * @return a json string - */ -- (NSString *_Nullable)getParameters:(NSString *_Nonnull)parameters; - -/** - * Generates a URL linking to the call quality reports. @param channel The - channel name specified in the joinChannel method. - * @param listenerUid The uid of the listener. - * @param speakerUid The uid of the speaker. - * @param reportFormat The format of the report. - AgoraRtc_QualityReportFormat_Json (0): JSON.: Returns - the quality report data in Json. AgoraRtc_QualityReportFormat_Html (1): HTML.: - Returns a report in HTML format, displayed on a web browser or WebVIEW - components. - * - * @return 0 when executed successfully. return minus value when failed. return - AgoraRtc_Error_Invalid_Argument (-2):Invalid argument. return - AgoraRtc_Error_Buffer_Too_Small (-6):The buffer length is too small. - */ -- (NSString *_Nullable)makeQualityReportUrl:(NSString *_Nonnull)channel - listenerUid:(NSUInteger)listenerUid - speakerrUid:(NSUInteger)speakerUid - reportFormat: - (AgoraRtcQualityReportFormat)reportFormat; - -/********************************************************* - * Large group conference call (experiment) - END - *********************************************************/ -@end diff --git a/ios/Classes/Base/BeanCovertor.swift b/ios/Classes/Base/BeanCovertor.swift deleted file mode 100644 index ae6c5240f..000000000 --- a/ios/Classes/Base/BeanCovertor.swift +++ /dev/null @@ -1,456 +0,0 @@ -// -// BeanCovertor.swift -// RCTAgora -// -// Created by LXH on 2020/4/9. -// Copyright © 2020 Syan. All rights reserved. -// - -import AgoraRtcKit -import Foundation - -func mapToPoint(_ map: [String: Any]) -> CGPoint { - var point = CGPoint() - if let x = map["x"] as? NSNumber { - point.x = CGFloat(truncating: x) - } - if let y = map["y"] as? NSNumber { - point.y = CGFloat(truncating: y) - } - return point -} - -func mapToSize(_ map: [String: Any]) -> CGSize { - var size = CGSize() - if let width = map["width"] as? NSNumber { - size.width = CGFloat(truncating: width) - } - if let height = map["height"] as? NSNumber { - size.height = CGFloat(truncating: height) - } - return size -} - -func mapToRect(_ map: [String: Any]) -> CGRect { - return CGRect( - origin: mapToPoint(map), - size: mapToSize(map) - ) -} - -func mapToVideoEncoderConfiguration(_ map: [String: Any]) -> AgoraVideoEncoderConfiguration { - let config = AgoraVideoEncoderConfiguration() - if let dimensions = map["dimensions"] as? [String: Any] { - config.dimensions = mapToSize(dimensions) - } - if let frameRate = map["frameRate"] as? NSNumber { - config.frameRate = frameRate.intValue - } - if let minFrameRate = map["minFrameRate"] as? NSNumber { - config.minFrameRate = minFrameRate.intValue - } - if let bitrate = map["bitrate"] as? NSNumber { - config.bitrate = bitrate.intValue - } - if let minBitrate = map["minBitrate"] as? NSNumber { - config.minBitrate = minBitrate.intValue - } - if let orientationMode = map["orientationMode"] as? NSNumber { - if let orientationMode = AgoraVideoOutputOrientationMode(rawValue: orientationMode.intValue) { - config.orientationMode = orientationMode - } - } - if let degradationPreference = map["degradationPrefer"] as? NSNumber { - if let degradationPreference = AgoraDegradationPreference(rawValue: degradationPreference.intValue) { - config.degradationPreference = degradationPreference - } - } - if let mirrorMode = map["mirrorMode"] as? NSNumber { - if let mirrorMode = AgoraVideoMirrorMode(rawValue: mirrorMode.uintValue) { - config.mirrorMode = mirrorMode - } - } - return config -} - -func mapToBeautyOptions(_ map: [String: Any]) -> AgoraBeautyOptions { - let options = AgoraBeautyOptions() - if let lighteningContrastLevel = map["lighteningContrastLevel"] as? NSNumber { - if let lighteningContrastLevel = AgoraLighteningContrastLevel(rawValue: lighteningContrastLevel.uintValue) { - options.lighteningContrastLevel = lighteningContrastLevel - } - } - if let lighteningLevel = map["lighteningLevel"] as? NSNumber { - options.lighteningLevel = lighteningLevel.floatValue - } - if let smoothnessLevel = map["smoothnessLevel"] as? NSNumber { - options.smoothnessLevel = smoothnessLevel.floatValue - } - if let rednessLevel = map["rednessLevel"] as? NSNumber { - options.rednessLevel = rednessLevel.floatValue - } - return options -} - -func mapToAgoraImage(_ map: [String: Any]) -> AgoraImage { - let image = AgoraImage() - if let url = map["url"] as? String { - if let url = URL(string: url) { - image.url = url - } - } - image.rect = mapToRect(map) - return image -} - -func mapToTranscodingUser(_ map: [String: Any]) -> AgoraLiveTranscodingUser { - let user = AgoraLiveTranscodingUser() - if let uid = map["uid"] as? NSNumber { - user.uid = uid.uintValue - } - user.rect = mapToRect(map) - if let zOrder = map["zOrder"] as? NSNumber { - user.zOrder = zOrder.intValue - } - if let alpha = map["alpha"] as? NSNumber { - user.alpha = alpha.doubleValue - } - if let audioChannel = map["audioChannel"] as? NSNumber { - user.audioChannel = audioChannel.intValue - } - return user -} - -func mapToColor(_ map: [String: Any]) -> UIColor { - return UIColor( - red: CGFloat((map["red"] as! NSNumber).intValue), - green: CGFloat((map["green"] as! NSNumber).intValue), - blue: CGFloat((map["blue"] as! NSNumber).intValue), - alpha: 1.0 - ) -} - -func mapToLiveTranscoding(_ map: [String: Any]) -> AgoraLiveTranscoding { - let transcoding = AgoraLiveTranscoding.default() - transcoding.size = mapToSize(map) - if let videoBitrate = map["videoBitrate"] as? NSNumber { - transcoding.videoBitrate = videoBitrate.intValue - } - if let videoFramerate = map["videoFramerate"] as? NSNumber { - transcoding.videoFramerate = videoFramerate.intValue - } - if let lowLatency = map["lowLatency"] as? Bool { - transcoding.lowLatency = lowLatency - } - if let videoGop = map["videoGop"] as? NSNumber { - transcoding.videoGop = videoGop.intValue - } - if let watermark = map["watermark"] as? [String: Any] { - transcoding.watermark = mapToAgoraImage(watermark) - } - if let backgroundImage = map["backgroundImage"] as? [String: Any] { - transcoding.backgroundImage = mapToAgoraImage(backgroundImage) - } - if let audioSampleRate = map["audioSampleRate"] as? NSNumber { - if let audioSampleRate = AgoraAudioSampleRateType(rawValue: audioSampleRate.intValue) { - transcoding.audioSampleRate = audioSampleRate - } - } - if let audioBitrate = map["audioBitrate"] as? NSNumber { - transcoding.audioBitrate = audioBitrate.intValue - } - if let audioChannels = map["audioChannels"] as? NSNumber { - transcoding.audioChannels = audioChannels.intValue - } - if let audioCodecProfile = map["audioCodecProfile"] as? NSNumber { - if let audioCodecProfile = AgoraAudioCodecProfileType(rawValue: audioCodecProfile.intValue) { - transcoding.audioCodecProfile = audioCodecProfile - } - } - if let videoCodecProfile = map["videoCodecProfile"] as? NSNumber { - if let videoCodecProfile = AgoraVideoCodecProfileType(rawValue: videoCodecProfile.intValue) { - transcoding.videoCodecProfile = videoCodecProfile - } - } - if let backgroundColor = map["backgroundColor"] as? [String: Any] { - transcoding.backgroundColor = mapToColor(backgroundColor) - } - if let userConfigExtraInfo = map["userConfigExtraInfo"] as? String { - transcoding.transcodingExtraInfo = userConfigExtraInfo - } - if let transcodingUsers = map["transcodingUsers"] as? [Any] { - transcodingUsers.forEach { - if let item = $0 as? [String: Any] { - transcoding.add(mapToTranscodingUser(item)) - } - } - } - return transcoding -} - -func mapToChannelMediaInfo(_ map: [String: Any]) -> AgoraChannelMediaRelayInfo { - let info = AgoraChannelMediaRelayInfo() - if let channelName = map["channelName"] as? String { - info.channelName = channelName - } - if let token = map["token"] as? String { - info.token = token - } - if let uid = map["uid"] as? NSNumber { - info.uid = uid.uintValue - } - return info -} - -func mapToChannelMediaRelayConfiguration(_ map: [String: Any]) -> AgoraChannelMediaRelayConfiguration { - let config = AgoraChannelMediaRelayConfiguration() - if let srcInfo = map["srcInfo"] as? [String: Any] { - config.sourceInfo = mapToChannelMediaInfo(srcInfo) - } - if let destInfos = map["destInfos"] as? [Any] { - destInfos.forEach { - if let item = $0 as? [String: Any] { - let info = mapToChannelMediaInfo(item) - config.setDestinationInfo(info, forChannelName: info.channelName ?? "") - } - } - } - return config -} - -func mapToLastmileProbeConfig(_ map: [String: Any]) -> AgoraLastmileProbeConfig { - let config = AgoraLastmileProbeConfig() - if let probeUplink = map["probeUplink"] as? Bool { - config.probeUplink = probeUplink - } - if let probeDownlink = map["probeDownlink"] as? Bool { - config.probeDownlink = probeDownlink - } - if let expectedUplinkBitrate = map["expectedUplinkBitrate"] as? NSNumber { - config.expectedUplinkBitrate = expectedUplinkBitrate.uintValue - } - if let expectedDownlinkBitrate = map["expectedDownlinkBitrate"] as? NSNumber { - config.expectedDownlinkBitrate = expectedDownlinkBitrate.uintValue - } - return config -} - -func mapToWatermarkOptions(_ map: [String: Any]) -> WatermarkOptions { - let options = WatermarkOptions() - if let visibleInPreview = map["visibleInPreview"] as? Bool { - options.visibleInPreview = visibleInPreview - } - if let positionInLandscapeMode = map["positionInLandscapeMode"] as? [String: Any] { - options.positionInLandscapeMode = mapToRect(positionInLandscapeMode) - } - if let positionInPortraitMode = map["positionInPortraitMode"] as? [String: Any] { - options.positionInPortraitMode = mapToRect(positionInPortraitMode) - } - return options -} - -func mapToLiveInjectStreamConfig(_ map: [String: Any]) -> AgoraLiveInjectStreamConfig { - let config = AgoraLiveInjectStreamConfig.default() - config.size = mapToSize(map) - if let videoGop = map["videoGop"] as? NSNumber { - config.videoGop = videoGop.intValue - } - if let videoFramerate = map["videoFramerate"] as? NSNumber { - config.videoFramerate = videoFramerate.intValue - } - if let videoBitrate = map["videoBitrate"] as? NSNumber { - config.videoBitrate = videoBitrate.intValue - } - if let audioSampleRate = map["audioSampleRate"] as? NSNumber { - if let audioSampleRate = AgoraAudioSampleRateType(rawValue: audioSampleRate.intValue) { - config.audioSampleRate = audioSampleRate - } - } - if let audioBitrate = map["audioBitrate"] as? NSNumber { - config.audioBitrate = audioBitrate.intValue - } - if let audioChannels = map["audioChannels"] as? NSNumber { - config.audioChannels = audioChannels.intValue - } - return config -} - -func mapToCameraCapturerConfiguration(_ map: [String: Any]) -> AgoraCameraCapturerConfiguration { - let config = AgoraCameraCapturerConfiguration() - if let preference = map["preference"] as? NSNumber { - if let preference = AgoraCameraCaptureOutputPreference(rawValue: preference.intValue) { - config.preference = preference - } - } - if let captureWidth = map["captureWidth"] as? NSNumber { - config.captureWidth = captureWidth.int32Value - } - if let captureHeight = map["captureHeight"] as? NSNumber { - config.captureHeight = captureHeight.int32Value - } - if let cameraDirection = map["cameraDirection"] as? NSNumber { - if let cameraDirection = AgoraCameraDirection(rawValue: cameraDirection.intValue) { - config.cameraDirection = cameraDirection - } - } - return config -} - -func mapToChannelMediaOptions(_ map: [String: Any]) -> AgoraRtcChannelMediaOptions { - let options = AgoraRtcChannelMediaOptions() - if let autoSubscribeAudio = map["autoSubscribeAudio"] as? Bool { - options.autoSubscribeAudio = autoSubscribeAudio - } - if let autoSubscribeVideo = map["autoSubscribeVideo"] as? Bool { - options.autoSubscribeVideo = autoSubscribeVideo - } - if let publishLocalAudio = map["publishLocalAudio"] as? Bool { - options.publishLocalAudio = publishLocalAudio - } - if let publishLocalVideo = map["publishLocalVideo"] as? Bool { - options.publishLocalVideo = publishLocalVideo - } - return options -} - -func mapToRtcEngineConfig(_ map: [String: Any]) -> AgoraRtcEngineConfig { - let config = AgoraRtcEngineConfig() - config.appId = map["appId"] as? String - if let areaCode = map["areaCode"] as? NSNumber { - config.areaCode = areaCode.uintValue - } - if let logConfig = map["logConfig"] as? [String: Any] { - config.logConfig = mapToLogConfig(logConfig) - } - return config -} - -func mapToAudioRecordingConfiguration(_ map: [String: Any]) -> AgoraAudioRecordingConfiguration { - let config = AgoraAudioRecordingConfiguration() - if let filePath = map["filePath"] as? String { - config.filePath = filePath - } - if let recordingQuality = map["recordingQuality"] as? NSNumber { - if let recordingQuality = AgoraAudioRecordingQuality(rawValue: recordingQuality.intValue) { - config.recordingQuality = recordingQuality - } - } - if let recordingPosition = map["recordingPosition"] as? NSNumber { - if let recordingPosition = AgoraAudioRecordingPosition(rawValue: recordingPosition.intValue) { - config.recordingPosition = recordingPosition - } - } - if let recordingSampleRate = map["recordingSampleRate"] as? NSNumber { - config.recordingSampleRate = recordingSampleRate.intValue - } - return config -} - -func mapToEncryptionConfig(_ map: [String: Any]) -> AgoraEncryptionConfig { - let config = AgoraEncryptionConfig() - if let encryptionMode = map["encryptionMode"] as? NSNumber { - if let encryptionMode = AgoraEncryptionMode(rawValue: encryptionMode.intValue) { - config.encryptionMode = encryptionMode - } - } - if let encryptionKey = map["encryptionKey"] as? String { - config.encryptionKey = encryptionKey - } - if let list = map["encryptionKdfSalt"] as? [Any] { - var encryptionKdfSalt: [UInt8] = [] - for i in list.indices { - if let item = list[i] as? NSNumber { - encryptionKdfSalt.append(item.uint8Value) - } - } - config.encryptionKdfSalt = Data(bytes: encryptionKdfSalt) - } - return config -} - -func mapToRhythmPlayerConfig(_ map: [String: Any]) -> AgoraRtcRhythmPlayerConfig { - let config = AgoraRtcRhythmPlayerConfig() - if let beatsPerMeasure = map["beatsPerMeasure"] as? NSNumber { - config.beatsPerMeasure = beatsPerMeasure.uintValue - } - if let beatsPerMinute = map["beatsPerMinute"] as? NSNumber { - config.beatsPerMinute = beatsPerMinute.uintValue - } - if let publish = map["publish"] as? NSNumber { - config.publish = publish.boolValue - } - return config -} - -func mapToClientRoleOptions(_ map: [String: Any]) -> AgoraClientRoleOptions { - let options = AgoraClientRoleOptions() - if let audienceLatencyLevel = map["audienceLatencyLevel"] as? NSNumber { - if let audienceLatencyLevel = AgoraAudienceLatencyLevelType(rawValue: audienceLatencyLevel.intValue) { - options.audienceLatencyLevel = audienceLatencyLevel - } - } - return options -} - -func mapToLogConfig(_ map: [String: Any]) -> AgoraLogConfig { - let config = AgoraLogConfig() - config.filePath = map["filePath"] as? String - if let fileSize = map["fileSize"] as? NSNumber { - config.fileSize = fileSize.intValue - } - if let level = map["level"] as? NSNumber { - if let level = AgoraLogLevel(rawValue: level.intValue) { - config.level = level - } - } - return config -} - -func mapToDataStreamConfig(_ map: [String: Any]) -> AgoraDataStreamConfig { - let config = AgoraDataStreamConfig() - if let syncWithAudio = map["syncWithAudio"] as? Bool { - config.syncWithAudio = syncWithAudio - } - if let ordered = map["ordered"] as? Bool { - config.ordered = ordered - } - return config -} - -func mapToVirtualBackgroundSource(_ map: [String: Any]) -> AgoraVirtualBackgroundSource { - let backgroundSource = AgoraVirtualBackgroundSource() - if let backgroundSourceType = map["backgroundSourceType"] as? NSNumber { - if let backgroundSourceType = AgoraVirtualBackgroundSourceType(rawValue: backgroundSourceType.uintValue) { - backgroundSource.backgroundSourceType = backgroundSourceType - } - } - if let color = map["color"] as? [String: Any] { - var red: CGFloat = 0, green: CGFloat = 0, blue: CGFloat = 0, alpha: CGFloat = 0 - mapToColor(color).getRed(&red, green: &green, blue: &blue, alpha: &alpha) - backgroundSource.color = UInt(red * 255.0) << 16 + UInt(green * 255.0) << 8 + UInt(blue * 255.0) - } - backgroundSource.source = map["source"] as? String - if let blurDegree = map["blur_degree"] as? NSNumber { - if let blurDegree = AgoraBlurDegree(rawValue: blurDegree.uintValue) { - backgroundSource.blur_degree = blurDegree - } - } - return backgroundSource -} - -func mapToEchoTestConfiguration(_ map: [String: Any]) -> AgoraEchoTestConfiguration { - let config = AgoraEchoTestConfiguration() - if let enableAudio = map["enableAudio"] as? NSNumber { - config.enableAudio = enableAudio.boolValue - } - if let enableVideo = map["enableVideo"] as? NSNumber { - config.enableVideo = enableVideo.boolValue - } - if let token = map["token"] as? String { - config.token = token - } - if let channelId = map["channelId"] as? String { - config.channelId = channelId - } - return config -} diff --git a/ios/Classes/Base/Callback.swift b/ios/Classes/Base/Callback.swift deleted file mode 100644 index 8c5bc130a..000000000 --- a/ios/Classes/Base/Callback.swift +++ /dev/null @@ -1,41 +0,0 @@ -// -// Callback.swift -// RCTAgora -// -// Created by LXH on 2020/4/9. -// Copyright © 2020 Syan. All rights reserved. -// - -import AgoraRtcKit -import Foundation - -@objc -protocol Callback: class { - func success(_ data: Any?) - - func failure(_ code: String, _ message: String) -} - -extension Callback { - func code(_ code: Int32?, _ runnable: ((Int32?) -> Any?)? = nil) { - if code == nil || code! < 0 { - let newCode = abs(Int(code ?? Int32(AgoraErrorCode.notInitialized.rawValue))) - failure(String(newCode), AgoraRtcEngineKit.getErrorDescription(newCode) ?? "") - return - } - - let res = runnable?(code) - success(res) - } - - func resolve(_ source: T?, _ runnable: (T) -> Any?) { - guard let source = source else { - let code = AgoraErrorCode.notInitialized.rawValue - failure(String(code), AgoraRtcEngineKit.getErrorDescription(code) ?? "") - return - } - - let res = runnable(source) - success(res) - } -} diff --git a/ios/Classes/Base/Extensions.swift b/ios/Classes/Base/Extensions.swift deleted file mode 100644 index d3c6b9f9d..000000000 --- a/ios/Classes/Base/Extensions.swift +++ /dev/null @@ -1,208 +0,0 @@ -// -// Extensions.swift -// RCTAgora -// -// Created by LXH on 2020/4/10. -// Copyright © 2020 Syan. All rights reserved. -// - -import AgoraRtcKit -import Foundation - -extension AgoraUserInfo { - func toMap() -> [String: Any?] { - return [ - "uid": uid, - "userAccount": userAccount, - ] - } -} - -extension AgoraRtcLocalAudioStats { - func toMap() -> [String: Any?] { - return [ - "numChannels": numChannels, - "sentSampleRate": sentSampleRate, - "sentBitrate": sentBitrate, - "txPacketLossRate": txPacketLossRate, - ] - } -} - -extension AgoraChannelStats { - func toMap() -> [String: Any?] { - return [ - "duration": duration, - "txBytes": txBytes, - "rxBytes": rxBytes, - "txAudioBytes": txAudioBytes, - "txVideoBytes": txVideoBytes, - "rxAudioBytes": rxAudioBytes, - "rxVideoBytes": rxVideoBytes, - "txKBitRate": txKBitrate, - "rxKBitRate": rxKBitrate, - "txAudioKBitRate": txAudioKBitrate, - "rxAudioKBitRate": rxAudioKBitrate, - "txVideoKBitRate": txVideoKBitrate, - "rxVideoKBitRate": rxVideoKBitrate, - "userCount": userCount, - "lastmileDelay": lastmileDelay, - "txPacketLossRate": txPacketLossRate, - "rxPacketLossRate": rxPacketLossRate, - "cpuTotalUsage": cpuTotalUsage, - "cpuAppUsage": cpuAppUsage, - "gatewayRtt": gatewayRtt, - "memoryAppUsageRatio": memoryAppUsageRatio, - "memoryTotalUsageRatio": memoryTotalUsageRatio, - "memoryAppUsageInKbytes": memoryAppUsageInKbytes, - ] - } -} - -extension CGRect { - func toMap() -> [String: Any?] { - return [ - "left": origin.x, - "top": origin.y, - "right": origin.x + size.width, - "bottom": origin.y + size.height, - ] - } -} - -extension AgoraRtcRemoteAudioStats { - func toMap() -> [String: Any?] { - return [ - "uid": uid, - "quality": quality, - "networkTransportDelay": networkTransportDelay, - "jitterBufferDelay": jitterBufferDelay, - "audioLossRate": audioLossRate, - "numChannels": numChannels, - "receivedSampleRate": receivedSampleRate, - "receivedBitrate": receivedBitrate, - "totalFrozenTime": totalFrozenTime, - "frozenRate": frozenRate, - "totalActiveTime": totalActiveTime, - "publishDuration": publishDuration, - "qoeQuality": qoeQuality, - "qualityChangedReason": qualityChangedReason, - "mosValue": mosValue, - ] - } -} - -extension AgoraRtcLocalVideoStats { - func toMap() -> [String: Any?] { - return [ - "sentBitrate": sentBitrate, - "sentFrameRate": sentFrameRate, - "encoderOutputFrameRate": encoderOutputFrameRate, - "rendererOutputFrameRate": rendererOutputFrameRate, - "targetBitrate": sentTargetBitrate, - "targetFrameRate": sentTargetFrameRate, - "qualityAdaptIndication": qualityAdaptIndication.rawValue, - "encodedBitrate": encodedBitrate, - "encodedFrameWidth": encodedFrameWidth, - "encodedFrameHeight": encodedFrameHeight, - "encodedFrameCount": encodedFrameCount, - "codecType": codecType.rawValue, - "txPacketLossRate": txPacketLossRate, - "captureFrameRate": captureFrameRate, - "captureBrightnessLevel": captureBrightnessLevel.rawValue, - ] - } -} - -extension AgoraRtcRemoteVideoStats { - func toMap() -> [String: Any?] { - return [ - "uid": uid, - "delay": delay, - "width": width, - "height": height, - "receivedBitrate": receivedBitrate, - "decoderOutputFrameRate": decoderOutputFrameRate, - "rendererOutputFrameRate": rendererOutputFrameRate, - "packetLossRate": packetLossRate, - "rxStreamType": rxStreamType.rawValue, - "totalFrozenTime": totalFrozenTime, - "frozenRate": frozenRate, - "totalActiveTime": totalActiveTime, - "publishDuration": publishDuration, - ] - } -} - -extension AgoraRtcAudioVolumeInfo { - func toMap() -> [String: Any?] { - return [ - "uid": uid, - "volume": volume, - "vad": vad, - "channelId": channelId, - ] - } -} - -extension Array where Element: AgoraRtcAudioVolumeInfo { - func toMapList() -> [[String: Any?]] { - var list = [[String: Any?]]() - forEach { - list.append($0.toMap()) - } - return list - } -} - -extension AgoraLastmileProbeOneWayResult { - func toMap() -> [String: Any?] { - return [ - "packetLossRate": packetLossRate, - "jitter": jitter, - "availableBandwidth": availableBandwidth, - ] - } -} - -extension AgoraLastmileProbeResult { - func toMap() -> [String: Any?] { - return [ - "state": state.rawValue, - "rtt": rtt, - "uplinkReport": uplinkReport.toMap(), - "downlinkReport": downlinkReport.toMap(), - ] - } -} - -extension AgoraFacePositionInfo { - func toMap() -> [String: Any?] { - return [ - "x": x, - "y": y, - "width": width, - "height": height, - "distance": distance, - ] - } -} - -extension AgoraRtcAudioFileInfo { - func toMap() -> [String: Any?] { - return [ - "filePath": filePath, - "durationMs": durationMs, - ] - } -} - -extension Array where Element: AgoraFacePositionInfo { - func toMapList() -> [[String: Any?]] { - var list = [[String: Any?]]() - forEach { - list.append($0.toMap()) - } - return list - } -} diff --git a/ios/Classes/Base/MediaObserver.swift b/ios/Classes/Base/MediaObserver.swift deleted file mode 100644 index 514fb21d0..000000000 --- a/ios/Classes/Base/MediaObserver.swift +++ /dev/null @@ -1,49 +0,0 @@ -// -// MediaObserver.swift -// RCTAgora -// -// Created by LXH on 2020/4/10. -// Copyright © 2020 Syan. All rights reserved. -// - -import AgoraRtcKit -import Foundation - -class MediaObserver: NSObject { - private var emitter: (_ data: [String: Any?]?) -> Void - private var maxMetadataSize = 1024 - private var metadataList = [String]() - - init(_ emitter: @escaping (_ data: [String: Any?]?) -> Void) { - self.emitter = emitter - } - - func addMetadata(_ metadata: String) { - metadataList.append(metadata) - } - - func setMaxMetadataSize(_ size: Int) { - maxMetadataSize = size - } -} - -extension MediaObserver: AgoraMediaMetadataDataSource { - func metadataMaxSize() -> Int { - return maxMetadataSize - } - - func readyToSendMetadata(atTimestamp _: TimeInterval) -> Data? { - if metadataList.count > 0 { - return metadataList.remove(at: 0).data(using: .utf8) - } - return nil - } -} - -extension MediaObserver: AgoraMediaMetadataDelegate { - func receiveMetadata(_ data: Data, fromUser uid: Int, atTimestamp timestamp: TimeInterval) { - emitter([ - "data": [String(data: data, encoding: .utf8) ?? "", uid, timestamp], - ]) - } -} diff --git a/ios/Classes/Base/RtcChannel.swift b/ios/Classes/Base/RtcChannel.swift deleted file mode 100644 index f6e464b77..000000000 --- a/ios/Classes/Base/RtcChannel.swift +++ /dev/null @@ -1,403 +0,0 @@ -// -// RtcChannel.swift -// RCTAgora -// -// Created by LXH on 2020/4/13. -// Copyright (c) 2020 Syan. All rights reserved. -// - -import AgoraRtcKit -import Foundation - -protocol RtcChannelInterface: - RtcChannelAudioInterface, - RtcChannelVideoInterface, - RtcChannelVoicePositionInterface, - RtcChannelPublishStreamInterface, - RtcChannelMediaRelayInterface, - RtcChannelDualStreamInterface, - RtcChannelFallbackInterface, - RtcChannelMediaMetadataInterface, - RtcChannelEncryptionInterface, - RtcChannelInjectStreamInterface, - RtcChannelStreamMessageInterface { - func create(_ params: NSDictionary, _ callback: Callback) - - func destroy(_ params: NSDictionary, _ callback: Callback) - - func setClientRole(_ params: NSDictionary, _ callback: Callback) - - func joinChannel(_ params: NSDictionary, _ callback: Callback) - - func joinChannelWithUserAccount(_ params: NSDictionary, _ callback: Callback) - - func leaveChannel(_ params: NSDictionary, _ callback: Callback) - - func renewToken(_ params: NSDictionary, _ callback: Callback) - - func getConnectionState(_ params: NSDictionary, _ callback: Callback) - - @available(*, deprecated) - func publish(_ params: NSDictionary, _ callback: Callback) - - @available(*, deprecated) - func unpublish(_ params: NSDictionary, _ callback: Callback) - - func getCallId(_ params: NSDictionary, _ callback: Callback) -} - -protocol RtcChannelAudioInterface { - func adjustUserPlaybackSignalVolume(_ params: NSDictionary, _ callback: Callback) - - func muteLocalAudioStream(_ params: NSDictionary, _ callback: Callback) - - func muteRemoteAudioStream(_ params: NSDictionary, _ callback: Callback) - - func muteAllRemoteAudioStreams(_ params: NSDictionary, _ callback: Callback) - - @available(*, deprecated) - func setDefaultMuteAllRemoteAudioStreams(_ params: NSDictionary, _ callback: Callback) -} - -protocol RtcChannelVideoInterface { - func muteLocalVideoStream(_ params: NSDictionary, _ callback: Callback) - - func muteRemoteVideoStream(_ params: NSDictionary, _ callback: Callback) - - func muteAllRemoteVideoStreams(_ params: NSDictionary, _ callback: Callback) - - @available(*, deprecated) - func setDefaultMuteAllRemoteVideoStreams(_ params: NSDictionary, _ callback: Callback) - - func enableRemoteSuperResolution(_ params: NSDictionary, _ callback: Callback) -} - -protocol RtcChannelVoicePositionInterface { - func setRemoteVoicePosition(_ params: NSDictionary, _ callback: Callback) -} - -protocol RtcChannelPublishStreamInterface { - func setLiveTranscoding(_ params: NSDictionary, _ callback: Callback) - - func addPublishStreamUrl(_ params: NSDictionary, _ callback: Callback) - - func removePublishStreamUrl(_ params: NSDictionary, _ callback: Callback) -} - -protocol RtcChannelMediaRelayInterface { - func startChannelMediaRelay(_ params: NSDictionary, _ callback: Callback) - - func updateChannelMediaRelay(_ params: NSDictionary, _ callback: Callback) - - func pauseAllChannelMediaRelay(_ params: NSDictionary, _ callback: Callback) - - func resumeAllChannelMediaRelay(_ params: NSDictionary, _ callback: Callback) - - func stopChannelMediaRelay(_ params: NSDictionary, _ callback: Callback) -} - -protocol RtcChannelDualStreamInterface { - func setRemoteVideoStreamType(_ params: NSDictionary, _ callback: Callback) - - func setRemoteDefaultVideoStreamType(_ params: NSDictionary, _ callback: Callback) -} - -protocol RtcChannelFallbackInterface { - func setRemoteUserPriority(_ params: NSDictionary, _ callback: Callback) -} - -protocol RtcChannelMediaMetadataInterface { - func registerMediaMetadataObserver(_ params: NSDictionary, _ callback: Callback) - - func unregisterMediaMetadataObserver(_ params: NSDictionary, _ callback: Callback) - - func setMaxMetadataSize(_ params: NSDictionary, _ callback: Callback) - - func sendMetadata(_ params: NSDictionary, _ callback: Callback) -} - -protocol RtcChannelEncryptionInterface { - @available(*, deprecated) - func setEncryptionSecret(_ params: NSDictionary, _ callback: Callback) - - @available(*, deprecated) - func setEncryptionMode(_ params: NSDictionary, _ callback: Callback) - - func enableEncryption(_ params: NSDictionary, _ callback: Callback) -} - -protocol RtcChannelInjectStreamInterface { - func addInjectStreamUrl(_ params: NSDictionary, _ callback: Callback) - - func removeInjectStreamUrl(_ params: NSDictionary, _ callback: Callback) -} - -protocol RtcChannelStreamMessageInterface { - func createDataStream(_ params: NSDictionary, _ callback: Callback) - - func sendStreamMessage(_ params: NSDictionary, _ callback: Callback) -} - -@objc -class RtcChannelManager: NSObject, RtcChannelInterface { - private var emitter: (_ methodName: String, _ data: [String: Any?]?) -> Void - private var rtcChannelMap = [String: AgoraRtcChannel]() - private var rtcChannelDelegateMap = [String: RtcChannelEventHandler]() - private var mediaObserverMap = [String: MediaObserver]() - - init(_ emitter: @escaping (_ methodName: String, _ data: [String: Any?]?) -> Void) { - self.emitter = emitter - } - - func Release() { - rtcChannelMap.forEach { - $1.destroy() - } - rtcChannelMap.removeAll() - rtcChannelDelegateMap.removeAll() - mediaObserverMap.removeAll() - } - - subscript(channelId: String) -> AgoraRtcChannel? { - return rtcChannelMap[channelId] - } - - @objc func create(_ params: NSDictionary, _ callback: Callback) { - callback.resolve(params["engine"] as? AgoraRtcEngineKit) { [weak self] in - if let rtcChannel = $0.createRtcChannel(params["channelId"] as! String) { - let delegate = RtcChannelEventHandler { [weak self] in - self?.emitter($0, $1) - } - rtcChannel.setRtcChannelDelegate(delegate) - self?.rtcChannelMap[rtcChannel.getId()!] = rtcChannel - self?.rtcChannelDelegateMap[rtcChannel.getId()!] = delegate - } - return nil - } - } - - @objc func destroy(_ params: NSDictionary, _ callback: Callback) { - callback.code(rtcChannelMap.removeValue(forKey: params["channelId"] as! String)?.destroy()) - } - - @objc func setClientRole(_ params: NSDictionary, _ callback: Callback) { - let role = AgoraClientRole(rawValue: (params["role"] as! NSNumber).intValue)! - if let options = params["options"] as? [String: Any] { - callback.code(self[params["channelId"] as! String]?.setClientRole(role, options: mapToClientRoleOptions(options))) - return - } - callback.code(self[params["channelId"] as! String]?.setClientRole(role)) - } - - @objc func joinChannel(_ params: NSDictionary, _ callback: Callback) { - callback.code(self[params["channelId"] as! String]?.join(byToken: params["token"] as? String, info: params["optionalInfo"] as? String, uid: (params["optionalUid"] as! NSNumber).uintValue, options: mapToChannelMediaOptions(params["options"] as! [String: Any]))) - } - - @objc func joinChannelWithUserAccount(_ params: NSDictionary, _ callback: Callback) { - callback.code(self[params["channelId"] as! String]?.join(byUserAccount: params["userAccount"] as! String, token: params["token"] as? String, options: mapToChannelMediaOptions(params["options"] as! [String: Any]))) - } - - @objc func leaveChannel(_ params: NSDictionary, _ callback: Callback) { - callback.code(self[params["channelId"] as! String]?.leave()) - } - - @objc func renewToken(_ params: NSDictionary, _ callback: Callback) { - callback.code(self[params["channelId"] as! String]?.renewToken(params["token"] as! String)) - } - - @objc func getConnectionState(_ params: NSDictionary, _ callback: Callback) { - callback.resolve(self[params["channelId"] as! String]) { - $0.getConnectionState().rawValue - } - } - - @objc func publish(_ params: NSDictionary, _ callback: Callback) { - callback.code(self[params["channelId"] as! String]?.publish()) - } - - @objc func unpublish(_ params: NSDictionary, _ callback: Callback) { - callback.code(self[params["channelId"] as! String]?.unpublish()) - } - - @objc func getCallId(_ params: NSDictionary, _ callback: Callback) { - callback.resolve(self[params["channelId"] as! String]) { - $0.getCallId() - } - } - - @objc func adjustUserPlaybackSignalVolume(_ params: NSDictionary, _ callback: Callback) { - callback.code(self[params["channelId"] as! String]?.adjustUserPlaybackSignalVolume((params["uid"] as! NSNumber).uintValue, volume: (params["volume"] as! NSNumber).int32Value)) - } - - @objc func muteRemoteAudioStream(_ params: NSDictionary, _ callback: Callback) { - callback.code(self[params["channelId"] as! String]?.muteRemoteAudioStream((params["uid"] as! NSNumber).uintValue, mute: params["muted"] as! Bool)) - } - - @objc func muteAllRemoteAudioStreams(_ params: NSDictionary, _ callback: Callback) { - callback.code(self[params["channelId"] as! String]?.muteAllRemoteAudioStreams(params["muted"] as! Bool)) - } - - @objc func setDefaultMuteAllRemoteAudioStreams(_ params: NSDictionary, _ callback: Callback) { - callback.code(self[params["channelId"] as! String]?.setDefaultMuteAllRemoteAudioStreams(params["muted"] as! Bool)) - } - - @objc func muteRemoteVideoStream(_ params: NSDictionary, _ callback: Callback) { - callback.code(self[params["channelId"] as! String]?.muteRemoteVideoStream((params["uid"] as! NSNumber).uintValue, mute: params["muted"] as! Bool)) - } - - @objc func muteAllRemoteVideoStreams(_ params: NSDictionary, _ callback: Callback) { - callback.code(self[params["channelId"] as! String]?.muteAllRemoteVideoStreams(params["muted"] as! Bool)) - } - - @objc func setDefaultMuteAllRemoteVideoStreams(_ params: NSDictionary, _ callback: Callback) { - callback.code(self[params["channelId"] as! String]?.setDefaultMuteAllRemoteVideoStreams(params["muted"] as! Bool)) - } - - @objc func setRemoteVoicePosition(_ params: NSDictionary, _ callback: Callback) { - callback.code(self[params["channelId"] as! String]?.setRemoteVoicePosition((params["uid"] as! NSNumber).uintValue, pan: (params["pan"] as! NSNumber).doubleValue, gain: (params["gain"] as! NSNumber).doubleValue)) - } - - @objc func setLiveTranscoding(_ params: NSDictionary, _ callback: Callback) { - callback.code(self[params["channelId"] as! String]?.setLiveTranscoding(mapToLiveTranscoding(params["transcoding"] as! [String: Any]))) - } - - @objc func addPublishStreamUrl(_ params: NSDictionary, _ callback: Callback) { - callback.code(self[params["channelId"] as! String]?.addPublishStreamUrl(params["url"] as! String, transcodingEnabled: params["transcodingEnabled"] as! Bool)) - } - - @objc func removePublishStreamUrl(_ params: NSDictionary, _ callback: Callback) { - callback.code(self[params["channelId"] as! String]?.removePublishStreamUrl(params["url"] as! String)) - } - - @objc func startChannelMediaRelay(_ params: NSDictionary, _ callback: Callback) { - callback.code(self[params["channelId"] as! String]?.startMediaRelay(mapToChannelMediaRelayConfiguration(params["channelMediaRelayConfiguration"] as! [String: Any]))) - } - - @objc func updateChannelMediaRelay(_ params: NSDictionary, _ callback: Callback) { - callback.code(self[params["channelId"] as! String]?.updateMediaRelay(mapToChannelMediaRelayConfiguration(params["channelMediaRelayConfiguration"] as! [String: Any]))) - } - - @objc func stopChannelMediaRelay(_ params: NSDictionary, _ callback: Callback) { - callback.code(self[params["channelId"] as! String]?.stopMediaRelay()) - } - - @objc func setRemoteVideoStreamType(_ params: NSDictionary, _ callback: Callback) { - callback.code(self[params["channelId"] as! String]?.setRemoteVideoStream((params["uid"] as! NSNumber).uintValue, type: AgoraVideoStreamType(rawValue: (params["streamType"] as! NSNumber).intValue)!)) - } - - @objc func setRemoteDefaultVideoStreamType(_ params: NSDictionary, _ callback: Callback) { - callback.code(self[params["channelId"] as! String]?.setRemoteDefaultVideoStreamType(AgoraVideoStreamType(rawValue: (params["streamType"] as! NSNumber).intValue)!)) - } - - @objc func setRemoteUserPriority(_ params: NSDictionary, _ callback: Callback) { - callback.code(self[params["channelId"] as! String]?.setRemoteUserPriority((params["uid"] as! NSNumber).uintValue, type: AgoraUserPriority(rawValue: (params["userPriority"] as! NSNumber).intValue)!)) - } - - @objc func registerMediaMetadataObserver(_ params: NSDictionary, _ callback: Callback) { - let channelId = params["channelId"] as! String - let mediaObserver = MediaObserver { [weak self] in - if var data = $0 { - data["channelId"] = channelId - self?.emitter(RtcEngineEvents.MetadataReceived, data) - } - } - callback.resolve(self[channelId]) { - if $0.setMediaMetadataDelegate(mediaObserver, with: .video) { - mediaObserverMap[channelId] = mediaObserver - } - return nil - } - } - - @objc func unregisterMediaMetadataObserver(_ params: NSDictionary, _ callback: Callback) { - let channelId = params["channelId"] as! String - callback.resolve(self[channelId]) { - if $0.setMediaMetadataDelegate(nil, with: .video) { - mediaObserverMap.removeValue(forKey: channelId) - } - return nil - } - } - - @objc func setMaxMetadataSize(_ params: NSDictionary, _ callback: Callback) { - callback.resolve(mediaObserverMap[params["channelId"] as! String]) { - $0.setMaxMetadataSize((params["size"] as! NSNumber).intValue) - } - } - - @objc func sendMetadata(_ params: NSDictionary, _ callback: Callback) { - callback.resolve(mediaObserverMap[params["channelId"] as! String]) { - $0.addMetadata(params["metadata"] as! String) - } - } - - @objc func setEncryptionSecret(_ params: NSDictionary, _ callback: Callback) { - callback.code(self[params["channelId"] as! String]?.setEncryptionSecret(params["secret"] as? String)) - } - - @objc func setEncryptionMode(_ params: NSDictionary, _ callback: Callback) { - var encryptionMode = "" - switch (params["encryptionMode"] as! NSNumber).intValue { - case AgoraEncryptionMode.AES128XTS.rawValue: - encryptionMode = "aes-128-xts" - case AgoraEncryptionMode.AES128ECB.rawValue: - encryptionMode = "aes-128-ecb" - case AgoraEncryptionMode.AES256XTS.rawValue: - encryptionMode = "aes-256-xts" - default: encryptionMode = "" - } - callback.code(self[params["channelId"] as! String]?.setEncryptionMode(encryptionMode)) - } - - @objc func enableEncryption(_ params: NSDictionary, _ callback: Callback) { - callback.code(self[params["channelId"] as! String]?.enableEncryption(params["enabled"] as! Bool, encryptionConfig: mapToEncryptionConfig(params["config"] as! [String: Any]))) - } - - @objc func addInjectStreamUrl(_ params: NSDictionary, _ callback: Callback) { - callback.code(self[params["channelId"] as! String]?.addInjectStreamUrl(params["url"] as! String, config: mapToLiveInjectStreamConfig(params["config"] as! [String: Any]))) - } - - @objc func removeInjectStreamUrl(_ params: NSDictionary, _ callback: Callback) { - callback.code(self[params["channelId"] as! String]?.removeInjectStreamUrl(params["url"] as! String)) - } - - @objc func createDataStream(_ params: NSDictionary, _ callback: Callback) { - let channel = self[params["channelId"] as! String] - var streamId = 0 - if let config = params["config"] as? [String: Any] { - callback.code(channel?.createDataStream(&streamId, config: mapToDataStreamConfig(config))) { _ in - streamId - } - return - } - callback.code(channel?.createDataStream(&streamId, reliable: params["reliable"] as! Bool, ordered: params["ordered"] as! Bool)) { _ in - streamId - } - } - - @objc func sendStreamMessage(_ params: NSDictionary, _ callback: Callback) { - callback.code(self[params["channelId"] as! String]?.sendStreamMessage((params["streamId"] as! NSNumber).intValue, data: (params["message"] as! String).data(using: .utf8)!)) - } - - @objc func enableRemoteSuperResolution(_ params: NSDictionary, _ callback: Callback) { - callback.code(self[params["channelId"] as! String]?.enableRemoteSuperResolution((params["uid"] as! NSNumber).uintValue, enabled: params["enabled"] as! Bool)) - } - - @objc func muteLocalAudioStream(_ params: NSDictionary, _ callback: Callback) { - callback.code(self[params["channelId"] as! String]?.muteLocalAudioStream(params["muted"] as! Bool)) - } - - @objc func muteLocalVideoStream(_ params: NSDictionary, _ callback: Callback) { - callback.code(self[params["channelId"] as! String]?.muteLocalVideoStream(params["muted"] as! Bool)) - } - - @objc func pauseAllChannelMediaRelay(_ params: NSDictionary, _ callback: Callback) { - callback.code(-Int32(AgoraErrorCode.notSupported.rawValue)) -// callback.code(self[params["channelId"] as! String]?.pauseAllChannelMediaRelay()) - } - - @objc func resumeAllChannelMediaRelay(_ params: NSDictionary, _ callback: Callback) { - callback.code(-Int32(AgoraErrorCode.notSupported.rawValue)) -// callback.code(self[params["channelId"] as! String]?.resumeAllChannelMediaRelay()) - } -} diff --git a/ios/Classes/Base/RtcChannelEvent.swift b/ios/Classes/Base/RtcChannelEvent.swift deleted file mode 100644 index eca5b4da8..000000000 --- a/ios/Classes/Base/RtcChannelEvent.swift +++ /dev/null @@ -1,249 +0,0 @@ -// -// RtcChannelEvent.swift -// RCTAgora -// -// Created by LXH on 2020/4/10. -// Copyright © 2020 Syan. All rights reserved. -// - -import AgoraRtcKit -import Foundation - -class RtcChannelEvents { - static let Warning = "Warning" - static let Error = "Error" - static let JoinChannelSuccess = "JoinChannelSuccess" - static let RejoinChannelSuccess = "RejoinChannelSuccess" - static let LeaveChannel = "LeaveChannel" - static let ClientRoleChanged = "ClientRoleChanged" - static let UserJoined = "UserJoined" - static let UserOffline = "UserOffline" - static let ConnectionStateChanged = "ConnectionStateChanged" - static let ConnectionLost = "ConnectionLost" - static let TokenPrivilegeWillExpire = "TokenPrivilegeWillExpire" - static let RequestToken = "RequestToken" - static let ActiveSpeaker = "ActiveSpeaker" - static let VideoSizeChanged = "VideoSizeChanged" - static let RemoteVideoStateChanged = "RemoteVideoStateChanged" - static let RemoteAudioStateChanged = "RemoteAudioStateChanged" - static let LocalPublishFallbackToAudioOnly = "LocalPublishFallbackToAudioOnly" - static let RemoteSubscribeFallbackToAudioOnly = "RemoteSubscribeFallbackToAudioOnly" - static let RtcStats = "RtcStats" - static let NetworkQuality = "NetworkQuality" - static let RemoteVideoStats = "RemoteVideoStats" - static let RemoteAudioStats = "RemoteAudioStats" - static let RtmpStreamingStateChanged = "RtmpStreamingStateChanged" - static let TranscodingUpdated = "TranscodingUpdated" - static let StreamInjectedStatus = "StreamInjectedStatus" - static let StreamMessage = "StreamMessage" - static let StreamMessageError = "StreamMessageError" - static let ChannelMediaRelayStateChanged = "ChannelMediaRelayStateChanged" - static let ChannelMediaRelayEvent = "ChannelMediaRelayEvent" - static let MetadataReceived = "MetadataReceived" - static let AudioPublishStateChanged = "AudioPublishStateChanged" - static let VideoPublishStateChanged = "VideoPublishStateChanged" - static let AudioSubscribeStateChanged = "AudioSubscribeStateChanged" - static let VideoSubscribeStateChanged = "VideoSubscribeStateChanged" - static let RtmpStreamingEvent = "RtmpStreamingEvent" - static let UserSuperResolutionEnabled = "UserSuperResolutionEnabled" - - static func toMap() -> [String: String] { - return [ - "Warning": Warning, - "Error": Error, - "JoinChannelSuccess": JoinChannelSuccess, - "RejoinChannelSuccess": RejoinChannelSuccess, - "LeaveChannel": LeaveChannel, - "ClientRoleChanged": ClientRoleChanged, - "UserJoined": UserJoined, - "UserOffline": UserOffline, - "ConnectionStateChanged": ConnectionStateChanged, - "ConnectionLost": ConnectionLost, - "TokenPrivilegeWillExpire": TokenPrivilegeWillExpire, - "RequestToken": RequestToken, - "ActiveSpeaker": ActiveSpeaker, - "VideoSizeChanged": VideoSizeChanged, - "RemoteVideoStateChanged": RemoteVideoStateChanged, - "RemoteAudioStateChanged": RemoteAudioStateChanged, - "LocalPublishFallbackToAudioOnly": LocalPublishFallbackToAudioOnly, - "RemoteSubscribeFallbackToAudioOnly": RemoteSubscribeFallbackToAudioOnly, - "RtcStats": RtcStats, - "NetworkQuality": NetworkQuality, - "RemoteVideoStats": RemoteVideoStats, - "RemoteAudioStats": RemoteAudioStats, - "RtmpStreamingStateChanged": RtmpStreamingStateChanged, - "TranscodingUpdated": TranscodingUpdated, - "StreamInjectedStatus": StreamInjectedStatus, - "StreamMessage": StreamMessage, - "StreamMessageError": StreamMessageError, - "ChannelMediaRelayStateChanged": ChannelMediaRelayStateChanged, - "ChannelMediaRelayEvent": ChannelMediaRelayEvent, - "MetadataReceived": MetadataReceived, - "AudioPublishStateChanged": AudioPublishStateChanged, - "VideoPublishStateChanged": VideoPublishStateChanged, - "AudioSubscribeStateChanged": AudioSubscribeStateChanged, - "VideoSubscribeStateChanged": VideoSubscribeStateChanged, - "RtmpStreamingEvent": RtmpStreamingEvent, - "UserSuperResolutionEnabled": UserSuperResolutionEnabled, - ] - } -} - -class RtcChannelEventHandler: NSObject { - static let PREFIX = "io.agora.rtc." - - var emitter: (_ methodName: String, _ data: [String: Any?]?) -> Void - - init(_ emitter: @escaping (_ methodName: String, _ data: [String: Any?]?) -> Void) { - self.emitter = emitter - } - - private func callback(_ methodName: String, _ channel: AgoraRtcChannel, _ data: Any?...) { - emitter(methodName, [ - "channelId": channel.getId(), - "data": data, - ]) - } -} - -extension RtcChannelEventHandler: AgoraRtcChannelDelegate { - public func rtcChannel(_ rtcChannel: AgoraRtcChannel, didOccurWarning warningCode: AgoraWarningCode) { - callback(RtcChannelEvents.Warning, rtcChannel, warningCode.rawValue) - } - - public func rtcChannel(_ rtcChannel: AgoraRtcChannel, didOccurError errorCode: AgoraErrorCode) { - callback(RtcChannelEvents.Error, rtcChannel, errorCode.rawValue) - } - - public func rtcChannelDidJoin(_ rtcChannel: AgoraRtcChannel, withUid uid: UInt, elapsed: Int) { - callback(RtcChannelEvents.JoinChannelSuccess, rtcChannel, rtcChannel.getId(), uid, elapsed) - } - - public func rtcChannelDidRejoin(_ rtcChannel: AgoraRtcChannel, withUid uid: UInt, elapsed: Int) { - callback(RtcChannelEvents.RejoinChannelSuccess, rtcChannel, rtcChannel.getId(), uid, elapsed) - } - - public func rtcChannelDidLeave(_ rtcChannel: AgoraRtcChannel, with stats: AgoraChannelStats) { - callback(RtcChannelEvents.LeaveChannel, rtcChannel, stats.toMap()) - } - - public func rtcChannel(_ rtcChannel: AgoraRtcChannel, didClientRoleChanged oldRole: AgoraClientRole, newRole: AgoraClientRole) { - callback(RtcChannelEvents.ClientRoleChanged, rtcChannel, oldRole.rawValue, newRole.rawValue) - } - - public func rtcChannel(_ rtcChannel: AgoraRtcChannel, didJoinedOfUid uid: UInt, elapsed: Int) { - callback(RtcChannelEvents.UserJoined, rtcChannel, uid, elapsed) - } - - public func rtcChannel(_ rtcChannel: AgoraRtcChannel, didOfflineOfUid uid: UInt, reason: AgoraUserOfflineReason) { - callback(RtcChannelEvents.UserOffline, rtcChannel, uid, reason.rawValue) - } - - public func rtcChannel(_ rtcChannel: AgoraRtcChannel, connectionChangedTo state: AgoraConnectionStateType, reason: AgoraConnectionChangedReason) { - callback(RtcChannelEvents.ConnectionStateChanged, rtcChannel, state.rawValue, reason.rawValue) - } - - public func rtcChannelDidLost(_ rtcChannel: AgoraRtcChannel) { - callback(RtcChannelEvents.ConnectionLost, rtcChannel) - } - - public func rtcChannel(_ rtcChannel: AgoraRtcChannel, tokenPrivilegeWillExpire token: String) { - callback(RtcChannelEvents.TokenPrivilegeWillExpire, rtcChannel, token) - } - - public func rtcChannelRequestToken(_ rtcChannel: AgoraRtcChannel) { - callback(RtcChannelEvents.RequestToken, rtcChannel) - } - - public func rtcChannel(_ rtcChannel: AgoraRtcChannel, activeSpeaker speakerUid: UInt) { - callback(RtcChannelEvents.ActiveSpeaker, rtcChannel, speakerUid) - } - - public func rtcChannel(_ rtcChannel: AgoraRtcChannel, videoSizeChangedOfUid uid: UInt, size: CGSize, rotation: Int) { - callback(RtcChannelEvents.VideoSizeChanged, rtcChannel, uid, Int(size.width), Int(size.height), rotation) - } - - public func rtcChannel(_ rtcChannel: AgoraRtcChannel, remoteVideoStateChangedOfUid uid: UInt, state: AgoraVideoRemoteState, reason: AgoraVideoRemoteStateReason, elapsed: Int) { - callback(RtcChannelEvents.RemoteVideoStateChanged, rtcChannel, uid, state.rawValue, reason.rawValue, elapsed) - } - - public func rtcChannel(_ rtcChannel: AgoraRtcChannel, remoteAudioStateChangedOfUid uid: UInt, state: AgoraAudioRemoteState, reason: AgoraAudioRemoteStateReason, elapsed: Int) { - callback(RtcChannelEvents.RemoteAudioStateChanged, rtcChannel, uid, state.rawValue, reason.rawValue, elapsed) - } - - public func rtcChannel(_ rtcChannel: AgoraRtcChannel, didLocalPublishFallbackToAudioOnly isFallbackOrRecover: Bool) { - callback(RtcChannelEvents.LocalPublishFallbackToAudioOnly, rtcChannel, isFallbackOrRecover) - } - - public func rtcChannel(_ rtcChannel: AgoraRtcChannel, didRemoteSubscribeFallbackToAudioOnly isFallbackOrRecover: Bool, byUid uid: UInt) { - callback(RtcChannelEvents.RemoteSubscribeFallbackToAudioOnly, rtcChannel, uid, isFallbackOrRecover) - } - - public func rtcChannel(_ rtcChannel: AgoraRtcChannel, reportRtcStats stats: AgoraChannelStats) { - callback(RtcChannelEvents.RtcStats, rtcChannel, stats.toMap()) - } - - public func rtcChannel(_ rtcChannel: AgoraRtcChannel, networkQuality uid: UInt, txQuality: AgoraNetworkQuality, rxQuality: AgoraNetworkQuality) { - callback(RtcChannelEvents.NetworkQuality, rtcChannel, uid, txQuality.rawValue, rxQuality.rawValue) - } - - public func rtcChannel(_ rtcChannel: AgoraRtcChannel, remoteVideoStats stats: AgoraRtcRemoteVideoStats) { - callback(RtcChannelEvents.RemoteVideoStats, rtcChannel, stats.toMap()) - } - - public func rtcChannel(_ rtcChannel: AgoraRtcChannel, remoteAudioStats stats: AgoraRtcRemoteAudioStats) { - callback(RtcChannelEvents.RemoteAudioStats, rtcChannel, stats.toMap()) - } - - public func rtcChannel(_ rtcChannel: AgoraRtcChannel, rtmpStreamingChangedToState url: String, state: AgoraRtmpStreamingState, errorCode: AgoraRtmpStreamingErrorCode) { - callback(RtcChannelEvents.RtmpStreamingStateChanged, rtcChannel, url, state.rawValue, errorCode.rawValue) - } - - public func rtcChannelTranscodingUpdated(_ rtcChannel: AgoraRtcChannel) { - callback(RtcChannelEvents.TranscodingUpdated, rtcChannel) - } - - public func rtcChannel(_ rtcChannel: AgoraRtcChannel, streamInjectedStatusOfUrl url: String, uid: UInt, status: AgoraInjectStreamStatus) { - callback(RtcChannelEvents.StreamInjectedStatus, rtcChannel, url, uid, status.rawValue) - } - - public func rtcChannel(_ rtcChannel: AgoraRtcChannel, receiveStreamMessageFromUid uid: UInt, streamId: Int, data: Data) { - callback(RtcChannelEvents.StreamMessage, rtcChannel, uid, streamId, String(data: data, encoding: .utf8)) - } - - public func rtcChannel(_ rtcChannel: AgoraRtcChannel, didOccurStreamMessageErrorFromUid uid: UInt, streamId: Int, error: Int, missed: Int, cached: Int) { - callback(RtcChannelEvents.StreamMessageError, rtcChannel, uid, streamId, error, missed, cached) - } - - public func rtcChannel(_ rtcChannel: AgoraRtcChannel, channelMediaRelayStateDidChange state: AgoraChannelMediaRelayState, error: AgoraChannelMediaRelayError) { - callback(RtcChannelEvents.ChannelMediaRelayStateChanged, rtcChannel, state.rawValue, error.rawValue) - } - - public func rtcChannel(_ rtcChannel: AgoraRtcChannel, didReceive event: AgoraChannelMediaRelayEvent) { - callback(RtcChannelEvents.ChannelMediaRelayEvent, rtcChannel, event.rawValue) - } - - public func rtcChannel(_ rtcChannel: AgoraRtcChannel, didAudioPublishStateChange oldState: AgoraStreamPublishState, newState: AgoraStreamPublishState, elapseSinceLastState: Int) { - callback(RtcChannelEvents.AudioPublishStateChanged, rtcChannel, rtcChannel.getId(), oldState.rawValue, newState.rawValue, elapseSinceLastState) - } - - public func rtcChannel(_ rtcChannel: AgoraRtcChannel, didVideoPublishStateChange oldState: AgoraStreamPublishState, newState: AgoraStreamPublishState, elapseSinceLastState: Int) { - callback(RtcChannelEvents.VideoPublishStateChanged, rtcChannel, rtcChannel.getId(), oldState.rawValue, newState.rawValue, elapseSinceLastState) - } - - public func rtcChannel(_ rtcChannel: AgoraRtcChannel, didAudioSubscribeStateChange uid: UInt, oldState: AgoraStreamSubscribeState, newState: AgoraStreamSubscribeState, elapseSinceLastState: Int) { - callback(RtcChannelEvents.AudioSubscribeStateChanged, rtcChannel, rtcChannel.getId(), uid, oldState.rawValue, newState.rawValue, elapseSinceLastState) - } - - public func rtcChannel(_ rtcChannel: AgoraRtcChannel, didVideoSubscribeStateChange uid: UInt, oldState: AgoraStreamSubscribeState, newState: AgoraStreamSubscribeState, elapseSinceLastState: Int) { - callback(RtcChannelEvents.VideoSubscribeStateChanged, rtcChannel, rtcChannel.getId(), uid, oldState.rawValue, newState.rawValue, elapseSinceLastState) - } - - public func rtcChannel(_ rtcChannel: AgoraRtcChannel, rtmpStreamingEventWithUrl url: String, eventCode: AgoraRtmpStreamingEvent) { - callback(RtcChannelEvents.RtmpStreamingEvent, rtcChannel, url, eventCode.rawValue) - } - - public func rtcChannel(_ rtcChannel: AgoraRtcChannel, superResolutionEnabledOfUid uid: UInt, enabled: Bool, reason: AgoraSuperResolutionStateReason) { - callback(RtcChannelEvents.UserSuperResolutionEnabled, rtcChannel, uid, enabled, reason.rawValue) - } -} diff --git a/ios/Classes/Base/RtcEngine.swift b/ios/Classes/Base/RtcEngine.swift deleted file mode 100644 index 4e9b905fb..000000000 --- a/ios/Classes/Base/RtcEngine.swift +++ /dev/null @@ -1,1228 +0,0 @@ -// -// RtcEngine.swift -// RCTAgora -// -// Created by LXH on 2020/4/13. -// Copyright (c) 2020 Syan. All rights reserved. -// - -import AgoraRtcKit -import Foundation - -protocol RtcEngineInterface: - RtcEngineUserInfoInterface, - RtcEngineAudioInterface, - RtcEngineVideoInterface, - RtcEngineAudioMixingInterface, - RtcEngineAudioEffectInterface, - RtcEngineVoiceChangerInterface, - RtcEngineVoicePositionInterface, - RtcEnginePublishStreamInterface, - RtcEngineMediaRelayInterface, - RtcEngineAudioRouteInterface, - RtcEngineEarMonitoringInterface, - RtcEngineDualStreamInterface, - RtcEngineFallbackInterface, - RtcEngineTestInterface, - RtcEngineMediaMetadataInterface, - RtcEngineWatermarkInterface, - RtcEngineEncryptionInterface, - RtcEngineAudioRecorderInterface, - RtcEngineInjectStreamInterface, - RtcEngineCameraInterface, - RtcEngineStreamMessageInterface { - func create(_ params: NSDictionary, _ callback: Callback) - - func destroy(_ callback: Callback) - - func setChannelProfile(_ params: NSDictionary, _ callback: Callback) - - func setClientRole(_ params: NSDictionary, _ callback: Callback) - - func joinChannel(_ params: NSDictionary, _ callback: Callback) - - func switchChannel(_ params: NSDictionary, _ callback: Callback) - - func leaveChannel(_ callback: Callback) - - func renewToken(_ params: NSDictionary, _ callback: Callback) - - @available(*, deprecated) - func enableWebSdkInteroperability(_ params: NSDictionary, _ callback: Callback) - - func getConnectionState(_ callback: Callback) - - func sendCustomReportMessage(_ params: NSDictionary, _ callback: Callback) - - func getCallId(_ callback: Callback) - - func rate(_ params: NSDictionary, _ callback: Callback) - - func complain(_ params: NSDictionary, _ callback: Callback) - - @available(*, deprecated) - func setLogFile(_ params: NSDictionary, _ callback: Callback) - - @available(*, deprecated) - func setLogFilter(_ params: NSDictionary, _ callback: Callback) - - @available(*, deprecated) - func setLogFileSize(_ params: NSDictionary, _ callback: Callback) - - func setParameters(_ params: NSDictionary, _ callback: Callback) - - func getSdkVersion(_ callback: Callback) - - func getErrorDescription(_ params: NSDictionary, _ callback: Callback) - - func getNativeHandle(_ callback: Callback) - - func enableDeepLearningDenoise(_ params: NSDictionary, _ callback: Callback) - - func setCloudProxy(_ params: NSDictionary, _ callback: Callback) - - func uploadLogFile(_ callback: Callback) - - func setLocalAccessPoint(_ params: NSDictionary, _ callback: Callback) - - func enableVirtualBackground(_ params: NSDictionary, _ callback: Callback) - - func takeSnapshot(_ params: NSDictionary, _ callback: Callback) -} - -protocol RtcEngineUserInfoInterface { - func registerLocalUserAccount(_ params: NSDictionary, _ callback: Callback) - - func joinChannelWithUserAccount(_ params: NSDictionary, _ callback: Callback) - - func getUserInfoByUserAccount(_ params: NSDictionary, _ callback: Callback) - - func getUserInfoByUid(_ params: NSDictionary, _ callback: Callback) -} - -protocol RtcEngineAudioInterface { - func enableAudio(_ callback: Callback) - - func disableAudio(_ callback: Callback) - - func setAudioProfile(_ params: NSDictionary, _ callback: Callback) - - func adjustRecordingSignalVolume(_ params: NSDictionary, _ callback: Callback) - - func adjustUserPlaybackSignalVolume(_ params: NSDictionary, _ callback: Callback) - - func adjustPlaybackSignalVolume(_ params: NSDictionary, _ callback: Callback) - - func enableLocalAudio(_ params: NSDictionary, _ callback: Callback) - - func muteLocalAudioStream(_ params: NSDictionary, _ callback: Callback) - - func muteRemoteAudioStream(_ params: NSDictionary, _ callback: Callback) - - func muteAllRemoteAudioStreams(_ params: NSDictionary, _ callback: Callback) - - @available(*, deprecated) - func setDefaultMuteAllRemoteAudioStreams(_ params: NSDictionary, _ callback: Callback) - - func enableAudioVolumeIndication(_ params: NSDictionary, _ callback: Callback) - - func startRhythmPlayer(_ params: NSDictionary, _ callback: Callback) - - func stopRhythmPlayer(_ callback: Callback) - - func configRhythmPlayer(_ params: NSDictionary, _ callback: Callback) -} - -protocol RtcEngineVideoInterface { - func enableVideo(_ callback: Callback) - - func disableVideo(_ callback: Callback) - - func setVideoEncoderConfiguration(_ params: NSDictionary, _ callback: Callback) - - func startPreview(_ callback: Callback) - - func stopPreview(_ callback: Callback) - - func enableLocalVideo(_ params: NSDictionary, _ callback: Callback) - - func muteLocalVideoStream(_ params: NSDictionary, _ callback: Callback) - - func muteRemoteVideoStream(_ params: NSDictionary, _ callback: Callback) - - func muteAllRemoteVideoStreams(_ params: NSDictionary, _ callback: Callback) - - @available(*, deprecated) - func setDefaultMuteAllRemoteVideoStreams(_ params: NSDictionary, _ callback: Callback) - - func setBeautyEffectOptions(_ params: NSDictionary, _ callback: Callback) - - func enableRemoteSuperResolution(_ params: NSDictionary, _ callback: Callback) -} - -protocol RtcEngineAudioMixingInterface { - func startAudioMixing(_ params: NSDictionary, _ callback: Callback) - - func stopAudioMixing(_ callback: Callback) - - func pauseAudioMixing(_ callback: Callback) - - func resumeAudioMixing(_ callback: Callback) - - func adjustAudioMixingVolume(_ params: NSDictionary, _ callback: Callback) - - func adjustAudioMixingPlayoutVolume(_ params: NSDictionary, _ callback: Callback) - - func adjustAudioMixingPublishVolume(_ params: NSDictionary, _ callback: Callback) - - func getAudioMixingPlayoutVolume(_ callback: Callback) - - func getAudioMixingPublishVolume(_ callback: Callback) - - func getAudioMixingDuration(_ params: NSDictionary, _ callback: Callback) - - func getAudioFileInfo(_ params: NSDictionary, _ callback: Callback) - - func getAudioMixingCurrentPosition(_ callback: Callback) - - func setAudioMixingPosition(_ params: NSDictionary, _ callback: Callback) - - func setAudioMixingPitch(_ params: NSDictionary, _ callback: Callback) - - func setAudioMixingPlaybackSpeed(_ params: NSDictionary, _ callback: Callback) - - func getAudioTrackCount(_ callback: Callback) - - func selectAudioTrack(_ params: NSDictionary, _ callback: Callback) - - func setAudioMixingDualMonoMode(_ params: NSDictionary, _ callback: Callback) -} - -protocol RtcEngineAudioEffectInterface { - func getEffectsVolume(_ callback: Callback) - - func setEffectsVolume(_ params: NSDictionary, _ callback: Callback) - - func setVolumeOfEffect(_ params: NSDictionary, _ callback: Callback) - - func playEffect(_ params: NSDictionary, _ callback: Callback) - - func setEffectPosition(_ params: NSDictionary, _ callback: Callback) - - func getEffectDuration(_ params: NSDictionary, _ callback: Callback) - - func getEffectCurrentPosition(_ params: NSDictionary, _ callback: Callback) - - func stopEffect(_ params: NSDictionary, _ callback: Callback) - - func stopAllEffects(_ callback: Callback) - - func preloadEffect(_ params: NSDictionary, _ callback: Callback) - - func unloadEffect(_ params: NSDictionary, _ callback: Callback) - - func pauseEffect(_ params: NSDictionary, _ callback: Callback) - - func pauseAllEffects(_ callback: Callback) - - func resumeEffect(_ params: NSDictionary, _ callback: Callback) - - func resumeAllEffects(_ callback: Callback) - - func setAudioSessionOperationRestriction(_ params: NSDictionary, _ callback: Callback) -} - -protocol RtcEngineVoiceChangerInterface { - @available(*, deprecated) - func setLocalVoiceChanger(_ params: NSDictionary, _ callback: Callback) - - @available(*, deprecated) - func setLocalVoiceReverbPreset(_ params: NSDictionary, _ callback: Callback) - - func setLocalVoicePitch(_ params: NSDictionary, _ callback: Callback) - - func setLocalVoiceEqualization(_ params: NSDictionary, _ callback: Callback) - - func setLocalVoiceReverb(_ params: NSDictionary, _ callback: Callback) - - func setAudioEffectPreset(_ params: NSDictionary, _ callback: Callback) - - func setVoiceBeautifierPreset(_ params: NSDictionary, _ callback: Callback) - - func setVoiceConversionPreset(_ params: NSDictionary, _ callback: Callback) - - func setAudioEffectParameters(_ params: NSDictionary, _ callback: Callback) - - func setVoiceBeautifierParameters(_ params: NSDictionary, _ callback: Callback) -} - -protocol RtcEngineVoicePositionInterface { - func enableSoundPositionIndication(_ params: NSDictionary, _ callback: Callback) - - func setRemoteVoicePosition(_ params: NSDictionary, _ callback: Callback) -} - -protocol RtcEnginePublishStreamInterface { - func setLiveTranscoding(_ params: NSDictionary, _ callback: Callback) - - func addPublishStreamUrl(_ params: NSDictionary, _ callback: Callback) - - func removePublishStreamUrl(_ params: NSDictionary, _ callback: Callback) -} - -protocol RtcEngineMediaRelayInterface { - func startChannelMediaRelay(_ params: NSDictionary, _ callback: Callback) - - func updateChannelMediaRelay(_ params: NSDictionary, _ callback: Callback) - - func pauseAllChannelMediaRelay(_ callback: Callback) - - func resumeAllChannelMediaRelay(_ callback: Callback) - - func stopChannelMediaRelay(_ callback: Callback) -} - -protocol RtcEngineAudioRouteInterface { - func setDefaultAudioRoutetoSpeakerphone(_ params: NSDictionary, _ callback: Callback) - - func setEnableSpeakerphone(_ params: NSDictionary, _ callback: Callback) - - func isSpeakerphoneEnabled(_ callback: Callback) -} - -protocol RtcEngineEarMonitoringInterface { - func enableInEarMonitoring(_ params: NSDictionary, _ callback: Callback) - - func setInEarMonitoringVolume(_ params: NSDictionary, _ callback: Callback) -} - -protocol RtcEngineDualStreamInterface { - func enableDualStreamMode(_ params: NSDictionary, _ callback: Callback) - - func setRemoteVideoStreamType(_ params: NSDictionary, _ callback: Callback) - - func setRemoteDefaultVideoStreamType(_ params: NSDictionary, _ callback: Callback) -} - -protocol RtcEngineFallbackInterface { - func setLocalPublishFallbackOption(_ params: NSDictionary, _ callback: Callback) - - func setRemoteSubscribeFallbackOption(_ params: NSDictionary, _ callback: Callback) - - func setRemoteUserPriority(_ params: NSDictionary, _ callback: Callback) -} - -protocol RtcEngineTestInterface { - func startEchoTest(_ params: NSDictionary, _ callback: Callback) - - func stopEchoTest(_ callback: Callback) - - func enableLastmileTest(_ callback: Callback) - - func disableLastmileTest(_ callback: Callback) - - func startLastmileProbeTest(_ params: NSDictionary, _ callback: Callback) - - func stopLastmileProbeTest(_ callback: Callback) -} - -protocol RtcEngineMediaMetadataInterface { - func registerMediaMetadataObserver(_ callback: Callback) - - func unregisterMediaMetadataObserver(_ callback: Callback) - - func setMaxMetadataSize(_ params: NSDictionary, _ callback: Callback) - - func sendMetadata(_ params: NSDictionary, _ callback: Callback) -} - -protocol RtcEngineWatermarkInterface { - func addVideoWatermark(_ params: NSDictionary, _ callback: Callback) - - func clearVideoWatermarks(_ callback: Callback) -} - -protocol RtcEngineEncryptionInterface { - @available(*, deprecated) - func setEncryptionSecret(_ params: NSDictionary, _ callback: Callback) - - @available(*, deprecated) - func setEncryptionMode(_ params: NSDictionary, _ callback: Callback) - - func enableEncryption(_ params: NSDictionary, _ callback: Callback) -} - -protocol RtcEngineAudioRecorderInterface { - func startAudioRecording(_ params: NSDictionary, _ callback: Callback) - - func stopAudioRecording(_ callback: Callback) -} - -protocol RtcEngineInjectStreamInterface { - func addInjectStreamUrl(_ params: NSDictionary, _ callback: Callback) - - func removeInjectStreamUrl(_ params: NSDictionary, _ callback: Callback) -} - -protocol RtcEngineCameraInterface { - func switchCamera(_ callback: Callback) - - func isCameraZoomSupported(_ callback: Callback) - - func isCameraTorchSupported(_ callback: Callback) - - func isCameraFocusSupported(_ callback: Callback) - - func isCameraExposurePositionSupported(_ callback: Callback) - - func isCameraAutoFocusFaceModeSupported(_ callback: Callback) - - func setCameraZoomFactor(_ params: NSDictionary, _ callback: Callback) - - func getCameraMaxZoomFactor(_ callback: Callback) - - func setCameraFocusPositionInPreview(_ params: NSDictionary, _ callback: Callback) - - func setCameraExposurePosition(_ params: NSDictionary, _ callback: Callback) - - func enableFaceDetection(_ params: NSDictionary, _ callback: Callback) - - func setCameraTorchOn(_ params: NSDictionary, _ callback: Callback) - - func setCameraAutoFocusFaceModeEnabled(_ params: NSDictionary, _ callback: Callback) - - func setCameraCapturerConfiguration(_ params: NSDictionary, _ callback: Callback) -} - -protocol RtcEngineStreamMessageInterface { - func createDataStream(_ params: NSDictionary, _ callback: Callback) - - func sendStreamMessage(_ params: NSDictionary, _ callback: Callback) -} - -internal class AgoraRtcEngineKitFactory { - func create(_ params: NSDictionary, _ delegate: RtcEngineEventHandler) -> AgoraRtcEngineKit? { - let engine = AgoraRtcEngineKit.sharedEngine( - with: mapToRtcEngineConfig(params["config"] as! [String: Any]), - delegate: delegate) - - return engine - } -} - -@objc -class RtcEngineManager: NSObject, RtcEngineInterface { - private var emitter: (_ methodName: String, _ data: [String: Any?]?) -> Void - private var agoraRtcEngineKitFactory: AgoraRtcEngineKitFactory - private(set) var engine: AgoraRtcEngineKit? - private var delegate: RtcEngineEventHandler? - private var mediaObserver: MediaObserver? - - init(_ emitter: @escaping (_ methodName: String, _ data: [String: Any?]?) -> Void, - _ agoraRtcEngineKitFactory: AgoraRtcEngineKitFactory = AgoraRtcEngineKitFactory()) { - self.emitter = emitter - self.agoraRtcEngineKitFactory = agoraRtcEngineKitFactory - } - - func Release() { - if (engine != nil) { - AgoraRtcEngineKit.destroy() - engine = nil - } - delegate = nil - mediaObserver = nil - } - - @objc func create(_ params: NSDictionary, _ callback: Callback) { - delegate = RtcEngineEventHandler { [weak self] in - self?.emitter($0, $1) - } - engine = agoraRtcEngineKitFactory.create(params, delegate!) - callback.code(engine?.setAppType(AgoraRtcAppType(rawValue: (params["appType"] as! NSNumber).uintValue)!)) { - RtcEngineRegistry.shared.onRtcEngineCreated(self.engine) - return $0 - } - } - - @objc func destroy(_ callback: Callback) { - callback.resolve(engine) { [weak self] _ in - self?.Release() - RtcEngineRegistry.shared.onRtcEngineDestroyed() - return nil - } - } - - @objc func setChannelProfile(_ params: NSDictionary, _ callback: Callback) { - callback.code(engine?.setChannelProfile(AgoraChannelProfile(rawValue: (params["profile"] as! NSNumber).intValue)!)) - } - - @objc func setClientRole(_ params: NSDictionary, _ callback: Callback) { - let role = AgoraClientRole(rawValue: (params["role"] as! NSNumber).intValue)! - if let options = params["options"] as? [String: Any] { - callback.code(engine?.setClientRole(role, options: mapToClientRoleOptions(options))) - return - } - callback.code(engine?.setClientRole(role)) - } - - @objc func joinChannel(_ params: NSDictionary, _ callback: Callback) { - let token = params["token"] as? String - let channelName = params["channelName"] as! String - let optionalInfo = params["optionalInfo"] as? String - let optionalUid = params["optionalUid"] as! NSNumber - if let options = params["options"] as? [String: Any] { - callback.code(engine?.joinChannel(byToken: token, channelId: channelName, info: optionalInfo, uid: optionalUid.uintValue, options: mapToChannelMediaOptions(options))) - return - } - callback.code(engine?.joinChannel(byToken: token, channelId: channelName, info: optionalInfo, uid: optionalUid.uintValue)) - } - - @objc func switchChannel(_ params: NSDictionary, _ callback: Callback) { - let token = params["token"] as? String - let channelName = params["channelName"] as! String - if let options = params["options"] as? [String: Any] { - callback.code(engine?.switchChannel(byToken: token, channelId: channelName, options: mapToChannelMediaOptions(options))) - return - } - callback.code(engine?.switchChannel(byToken: token, channelId: channelName)) - } - - @objc func leaveChannel(_ callback: Callback) { - callback.code(engine?.leaveChannel()) - } - - @objc func renewToken(_ params: NSDictionary, _ callback: Callback) { - callback.code(engine?.renewToken(params["token"] as! String)) - } - - @objc func enableWebSdkInteroperability(_ params: NSDictionary, _ callback: Callback) { - callback.code(engine?.enableWebSdkInteroperability(params["enabled"] as! Bool)) - } - - @objc func getConnectionState(_ callback: Callback) { - callback.resolve(engine) { - $0.getConnectionState().rawValue - } - } - - @objc func sendCustomReportMessage(_ params: NSDictionary, _ callback: Callback) { - callback.code(engine?.sendCustomReportMessage(params["id"] as! String, category: params["category"] as! String, event: params["event"] as! String, label: params["label"] as! String, value: (params["value"] as! NSNumber).intValue)) - } - - @objc func getCallId(_ callback: Callback) { - callback.resolve(engine) { - $0.getCallId() - } - } - - @objc func rate(_ params: NSDictionary, _ callback: Callback) { - callback.code(engine?.rate(params["callId"] as! String, rating: (params["rating"] as! NSNumber).intValue, description: params["description"] as? String)) - } - - @objc func complain(_ params: NSDictionary, _ callback: Callback) { - callback.code(engine?.complain(params["callId"] as! String, description: params["description"] as? String)) - } - - @objc func setLogFile(_ params: NSDictionary, _ callback: Callback) { - callback.code(engine?.setLogFile(params["filePath"] as! String)) - } - - @objc func setLogFilter(_ params: NSDictionary, _ callback: Callback) { - callback.code(engine?.setLogFilter((params["filter"] as! NSNumber).uintValue)) - } - - @objc func setLogFileSize(_ params: NSDictionary, _ callback: Callback) { - callback.code(engine?.setLogFileSize((params["fileSizeInKBytes"] as! NSNumber).uintValue)) - } - - @objc func getNativeHandle(_ callback: Callback) { - callback.resolve(engine) { - Int(bitPattern: $0.getNativeHandle()) - } - } - - @objc func setParameters(_ params: NSDictionary, _ callback: Callback) { - callback.code(engine?.setParameters(params["parameters"] as! String)) - } - - @objc func registerLocalUserAccount(_ params: NSDictionary, _ callback: Callback) { - callback.code(engine?.registerLocalUserAccount(params["userAccount"] as! String, appId: params["appId"] as! String)) - } - - @objc func joinChannelWithUserAccount(_ params: NSDictionary, _ callback: Callback) { - let userAccount = params["userAccount"] as! String - let token = params["token"] as? String - let channelName = params["channelName"] as! String - if let options = params["options"] as? [String: Any] { - callback.code(engine?.joinChannel(byUserAccount: userAccount, token: token, channelId: channelName, options: mapToChannelMediaOptions(options))) - return - } - callback.code(engine?.joinChannel(byUserAccount: userAccount, token: token, channelId: channelName)) - } - - @objc func getUserInfoByUserAccount(_ params: NSDictionary, _ callback: Callback) { - callback.resolve(engine) { - $0.getUserInfo(byUserAccount: params["userAccount"] as! String, withError: nil)?.toMap() - } - } - - @objc func getUserInfoByUid(_ params: NSDictionary, _ callback: Callback) { - callback.resolve(engine) { - $0.getUserInfo(byUid: (params["uid"] as! NSNumber).uintValue, withError: nil)?.toMap() - } - } - - @objc func enableAudio(_ callback: Callback) { - callback.code(engine?.enableAudio()) - } - - @objc func disableAudio(_ callback: Callback) { - callback.code(engine?.disableAudio()) - } - - @objc func setAudioProfile(_ params: NSDictionary, _ callback: Callback) { - callback.code(engine?.setAudioProfile(AgoraAudioProfile(rawValue: (params["profile"] as! NSNumber).intValue)!, scenario: AgoraAudioScenario(rawValue: (params["scenario"] as! NSNumber).intValue)!)) - } - - @objc func adjustRecordingSignalVolume(_ params: NSDictionary, _ callback: Callback) { - callback.code(engine?.adjustRecordingSignalVolume((params["volume"] as! NSNumber).intValue)) - } - - @objc func adjustUserPlaybackSignalVolume(_ params: NSDictionary, _ callback: Callback) { - callback.code(engine?.adjustUserPlaybackSignalVolume((params["uid"] as! NSNumber).uintValue, volume: (params["volume"] as! NSNumber).int32Value)) - } - - @objc func adjustPlaybackSignalVolume(_ params: NSDictionary, _ callback: Callback) { - callback.code(engine?.adjustPlaybackSignalVolume((params["volume"] as! NSNumber).intValue)) - } - - @objc func enableLocalAudio(_ params: NSDictionary, _ callback: Callback) { - callback.code(engine?.enableLocalAudio(params["enabled"] as! Bool)) - } - - @objc func muteLocalAudioStream(_ params: NSDictionary, _ callback: Callback) { - callback.code(engine?.muteLocalAudioStream(params["muted"] as! Bool)) - } - - @objc func muteRemoteAudioStream(_ params: NSDictionary, _ callback: Callback) { - callback.code(engine?.muteRemoteAudioStream((params["uid"] as! NSNumber).uintValue, mute: params["muted"] as! Bool)) - } - - @objc func muteAllRemoteAudioStreams(_ params: NSDictionary, _ callback: Callback) { - callback.code(engine?.muteAllRemoteAudioStreams(params["muted"] as! Bool)) - } - - @objc func setDefaultMuteAllRemoteAudioStreams(_ params: NSDictionary, _ callback: Callback) { - callback.code(engine?.setDefaultMuteAllRemoteAudioStreams(params["muted"] as! Bool)) - } - - @objc func enableAudioVolumeIndication(_ params: NSDictionary, _ callback: Callback) { - callback.code(engine?.enableAudioVolumeIndication((params["interval"] as! NSNumber).intValue, smooth: (params["smooth"] as! NSNumber).intValue, report_vad: params["report_vad"] as! Bool)) - } - - @objc func startRhythmPlayer(_ params: NSDictionary, _ callback: Callback) { - callback.code(engine?.startRhythmPlayer(params["sound1"] as! String, sound2: params["sound2"] as! String, config: mapToRhythmPlayerConfig(params["config"] as! [String: Any]))) - } - - @objc func stopRhythmPlayer(_ callback: Callback) { - callback.code(engine?.stopRhythmPlayer()) - } - - @objc func configRhythmPlayer(_ params: NSDictionary, _ callback: Callback) { - callback.code(engine?.configRhythmPlayer(mapToRhythmPlayerConfig(params as! [String: Any]))) - } - - @objc func enableVideo(_ callback: Callback) { - callback.code(engine?.enableVideo()) - } - - @objc func disableVideo(_ callback: Callback) { - callback.code(engine?.disableVideo()) - } - - @objc func setVideoEncoderConfiguration(_ params: NSDictionary, _ callback: Callback) { - callback.code(engine?.setVideoEncoderConfiguration(mapToVideoEncoderConfiguration(params["config"] as! [String: Any]))) - } - - @objc func startPreview(_ callback: Callback) { - callback.code(engine?.startPreview()) - } - - @objc func stopPreview(_ callback: Callback) { - callback.code(engine?.stopPreview()) - } - - @objc func enableLocalVideo(_ params: NSDictionary, _ callback: Callback) { - callback.code(engine?.enableLocalVideo(params["enabled"] as! Bool)) - } - - @objc func muteLocalVideoStream(_ params: NSDictionary, _ callback: Callback) { - callback.code(engine?.muteLocalVideoStream(params["muted"] as! Bool)) - } - - @objc func muteRemoteVideoStream(_ params: NSDictionary, _ callback: Callback) { - callback.code(engine?.muteRemoteVideoStream((params["uid"] as! NSNumber).uintValue, mute: params["muted"] as! Bool)) - } - - @objc func muteAllRemoteVideoStreams(_ params: NSDictionary, _ callback: Callback) { - callback.code(engine?.muteAllRemoteVideoStreams(params["muted"] as! Bool)) - } - - @objc func setDefaultMuteAllRemoteVideoStreams(_ params: NSDictionary, _ callback: Callback) { - callback.code(engine?.setDefaultMuteAllRemoteVideoStreams(params["muted"] as! Bool)) - } - - @objc func setBeautyEffectOptions(_ params: NSDictionary, _ callback: Callback) { - callback.code(engine?.setBeautyEffectOptions(params["enabled"] as! Bool, options: mapToBeautyOptions(params["options"] as! [String: Any]))) - } - - @objc func startAudioMixing(_ params: NSDictionary, _ callback: Callback) { - if let startPos = params["startPos"] as? NSNumber { - callback.code(engine?.startAudioMixing(params["filePath"] as! String, loopback: params["loopback"] as! Bool, replace: params["replace"] as! Bool, cycle: (params["cycle"] as! NSNumber).intValue, startPos: startPos.intValue)) - return - } - callback.code(engine?.startAudioMixing(params["filePath"] as! String, loopback: params["loopback"] as! Bool, replace: params["replace"] as! Bool, cycle: (params["cycle"] as! NSNumber).intValue)) - } - - @objc func stopAudioMixing(_ callback: Callback) { - callback.code(engine?.stopAudioMixing()) - } - - @objc func pauseAudioMixing(_ callback: Callback) { - callback.code(engine?.pauseAudioMixing()) - } - - @objc func resumeAudioMixing(_ callback: Callback) { - callback.code(engine?.resumeAudioMixing()) - } - - @objc func adjustAudioMixingVolume(_ params: NSDictionary, _ callback: Callback) { - callback.code(engine?.adjustAudioMixingVolume((params["volume"] as! NSNumber).intValue)) - } - - @objc func adjustAudioMixingPlayoutVolume(_ params: NSDictionary, _ callback: Callback) { - callback.code(engine?.adjustAudioMixingPlayoutVolume((params["volume"] as! NSNumber).intValue)) - } - - @objc func adjustAudioMixingPublishVolume(_ params: NSDictionary, _ callback: Callback) { - callback.code(engine?.adjustAudioMixingPublishVolume((params["volume"] as! NSNumber).intValue)) - } - - @objc func getAudioMixingPlayoutVolume(_ callback: Callback) { - callback.code(engine?.getAudioMixingPlayoutVolume()) { - $0 - } - } - - @objc func getAudioMixingPublishVolume(_ callback: Callback) { - callback.code(engine?.getAudioMixingPublishVolume()) { - $0 - } - } - - @objc func getAudioMixingDuration(_ params: NSDictionary, _ callback: Callback) { - callback.code(engine?.getAudioMixingDuration()) { - $0 - } - } - - @objc func getAudioFileInfo(_ params: NSDictionary, _ callback: Callback) { - callback.code(engine?.getAudioFileInfo(params["filePath"] as! String)) - } - - @objc func getAudioMixingCurrentPosition(_ callback: Callback) { - callback.code(engine?.getAudioMixingCurrentPosition()) { - $0 - } - } - - @objc func setAudioMixingPosition(_ params: NSDictionary, _ callback: Callback) { - callback.code(engine?.setAudioMixingPosition((params["pos"] as! NSNumber).intValue)) - } - - @objc func setAudioMixingPitch(_ params: NSDictionary, _ callback: Callback) { - callback.code(engine?.setAudioMixingPitch((params["pitch"] as! NSNumber).intValue)) - } - - @objc func setAudioMixingPlaybackSpeed(_ params: NSDictionary, _ callback: Callback) { - callback.code(engine?.setAudioMixingPlaybackSpeed(Int32((params["speed"] as! NSNumber).intValue))) - } - - @objc func getAudioTrackCount(_ callback: Callback) { - callback.code(engine?.getAudioTrackCount()) { - $0 - } - } - - @objc func selectAudioTrack(_ params: NSDictionary, _ callback: Callback) { - callback.code(engine?.selectAudioTrack((params["index"] as! NSNumber).intValue)) - } - - @objc func setAudioMixingDualMonoMode(_ params: NSDictionary, _ callback: Callback) { - let mode = AgoraAudioMixingDualMonoMode(rawValue: UInt((params["mode"] as! NSNumber).intValue)) - callback.code(engine?.setAudioMixingDualMonoMode(mode!)) - } - - @objc func getEffectsVolume(_ callback: Callback) { - callback.resolve(engine) { - $0.getEffectsVolume() - } - } - - @objc func setEffectsVolume(_ params: NSDictionary, _ callback: Callback) { - callback.code(engine?.setEffectsVolume((params["volume"] as! NSNumber).doubleValue)) - } - - @objc func setVolumeOfEffect(_ params: NSDictionary, _ callback: Callback) { - callback.code(engine?.setVolumeOfEffect((params["soundId"] as! NSNumber).int32Value, withVolume: (params["volume"] as! NSNumber).doubleValue)) - } - - @objc func playEffect(_ params: NSDictionary, _ callback: Callback) { - if let startPos = (params["startPos"] as? NSNumber) { - callback.code(engine?.playEffect((params["soundId"] as! NSNumber).int32Value, filePath: params["filePath"] as? String, loopCount: (params["loopCount"] as! NSNumber).int32Value, pitch: (params["pitch"] as! NSNumber).doubleValue, pan: (params["pan"] as! NSNumber).doubleValue, gain: (params["gain"] as! NSNumber).doubleValue, publish: params["publish"] as! Bool, startPos: startPos.int32Value)) - return - } - callback.code(engine?.playEffect((params["soundId"] as! NSNumber).int32Value, filePath: params["filePath"] as? String, loopCount: (params["loopCount"] as! NSNumber).int32Value, pitch: (params["pitch"] as! NSNumber).doubleValue, pan: (params["pan"] as! NSNumber).doubleValue, gain: (params["gain"] as! NSNumber).doubleValue, publish: params["publish"] as! Bool)) - } - - @objc func setEffectPosition(_ params: NSDictionary, _ callback: Callback) { - callback.code(engine?.setEffectPosition((params["soundId"] as! NSNumber).int32Value, pos: (params["pos"] as! NSNumber).intValue)) - } - - @objc func getEffectDuration(_ params: NSDictionary, _ callback: Callback) { - callback.code(engine?.getEffectDuration(params["filePath"] as! String)) { - $0 - } - } - - @objc func getEffectCurrentPosition(_ params: NSDictionary, _ callback: Callback) { - callback.code(engine?.getEffectCurrentPosition((params["soundId"] as! NSNumber).int32Value)) { - $0 - } - } - - @objc func stopEffect(_ params: NSDictionary, _ callback: Callback) { - callback.code(engine?.stopEffect((params["soundId"] as! NSNumber).int32Value)) - } - - @objc func stopAllEffects(_ callback: Callback) { - callback.code(engine?.stopAllEffects()) - } - - @objc func preloadEffect(_ params: NSDictionary, _ callback: Callback) { - callback.code(engine?.preloadEffect((params["soundId"] as! NSNumber).int32Value, filePath: params["filePath"] as? String)) - } - - @objc func unloadEffect(_ params: NSDictionary, _ callback: Callback) { - callback.code(engine?.unloadEffect((params["soundId"] as! NSNumber).int32Value)) - } - - @objc func pauseEffect(_ params: NSDictionary, _ callback: Callback) { - callback.code(engine?.pauseEffect((params["soundId"] as! NSNumber).int32Value)) - } - - @objc func pauseAllEffects(_ callback: Callback) { - callback.code(engine?.pauseAllEffects()) - } - - @objc func resumeEffect(_ params: NSDictionary, _ callback: Callback) { - callback.code(engine?.resumeEffect((params["soundId"] as! NSNumber).int32Value)) - } - - @objc func resumeAllEffects(_ callback: Callback) { - callback.code(engine?.resumeAllEffects()) - } - - @objc func setAudioSessionOperationRestriction(_ params: NSDictionary, _ callback: Callback) { - callback.resolve(engine) { - $0.setAudioSessionOperationRestriction(AgoraAudioSessionOperationRestriction(rawValue: (params["restriction"] as! NSNumber).uintValue)) - } - } - - @objc func setLocalVoiceChanger(_ params: NSDictionary, _ callback: Callback) { - callback.code(engine?.setLocalVoiceChanger(AgoraAudioVoiceChanger(rawValue: (params["voiceChanger"] as! NSNumber).intValue)!)) - } - - @objc func setLocalVoiceReverbPreset(_ params: NSDictionary, _ callback: Callback) { - callback.code(engine?.setLocalVoiceReverbPreset(AgoraAudioReverbPreset(rawValue: (params["preset"] as! NSNumber).intValue)!)) - } - - @objc func setLocalVoicePitch(_ params: NSDictionary, _ callback: Callback) { - callback.code(engine?.setLocalVoicePitch((params["pitch"] as! NSNumber).doubleValue)) - } - - @objc func setLocalVoiceEqualization(_ params: NSDictionary, _ callback: Callback) { - callback.code(engine?.setLocalVoiceEqualizationOf(AgoraAudioEqualizationBandFrequency(rawValue: (params["bandFrequency"] as! NSNumber).intValue)!, withGain: (params["bandGain"] as! NSNumber).intValue)) - } - - @objc func setLocalVoiceReverb(_ params: NSDictionary, _ callback: Callback) { - callback.code(engine?.setLocalVoiceReverbOf(AgoraAudioReverbType(rawValue: (params["reverbKey"] as! NSNumber).intValue)!, withValue: (params["value"] as! NSNumber).intValue)) - } - - @objc func setAudioEffectPreset(_ params: NSDictionary, _ callback: Callback) { - callback.code(engine?.setAudioEffectPreset(AgoraAudioEffectPreset(rawValue: (params["preset"] as! NSNumber).intValue)!)) - } - - @objc func setVoiceBeautifierPreset(_ params: NSDictionary, _ callback: Callback) { - callback.code(engine?.setVoiceBeautifierPreset(AgoraVoiceBeautifierPreset(rawValue: (params["preset"] as! NSNumber).intValue)!)) - } - - @objc func setVoiceConversionPreset(_ params: NSDictionary, _ callback: Callback) { - callback.code(engine?.setVoiceConversionPreset(AgoraVoiceConversionPreset(rawValue: (params["preset"] as! NSNumber).intValue)!)) - } - - @objc func setAudioEffectParameters(_ params: NSDictionary, _ callback: Callback) { - callback.code(engine?.setAudioEffectParameters(AgoraAudioEffectPreset(rawValue: (params["preset"] as! NSNumber).intValue)!, param1: (params["param1"] as! NSNumber).int32Value, param2: (params["param2"] as! NSNumber).int32Value)) - } - - @objc func enableSoundPositionIndication(_ params: NSDictionary, _ callback: Callback) { - callback.code(engine?.enableSoundPositionIndication(params["enabled"] as! Bool)) - } - - @objc func setRemoteVoicePosition(_ params: NSDictionary, _ callback: Callback) { - callback.code(engine?.setRemoteVoicePosition((params["uid"] as! NSNumber).uintValue, pan: (params["pan"] as! NSNumber).doubleValue, gain: (params["gain"] as! NSNumber).doubleValue)) - } - - @objc func setLiveTranscoding(_ params: NSDictionary, _ callback: Callback) { - callback.code(engine?.setLiveTranscoding(mapToLiveTranscoding(params["transcoding"] as! [String: Any]))) - } - - @objc func addPublishStreamUrl(_ params: NSDictionary, _ callback: Callback) { - callback.code(engine?.addPublishStreamUrl(params["url"] as! String, transcodingEnabled: params["transcodingEnabled"] as! Bool)) - } - - @objc func removePublishStreamUrl(_ params: NSDictionary, _ callback: Callback) { - callback.code(engine?.removePublishStreamUrl(params["url"] as! String)) - } - - @objc func startChannelMediaRelay(_ params: NSDictionary, _ callback: Callback) { - callback.code(engine?.startChannelMediaRelay(mapToChannelMediaRelayConfiguration(params["channelMediaRelayConfiguration"] as! [String: Any]))) - } - - @objc func updateChannelMediaRelay(_ params: NSDictionary, _ callback: Callback) { - callback.code(engine?.updateChannelMediaRelay(mapToChannelMediaRelayConfiguration(params["channelMediaRelayConfiguration"] as! [String: Any]))) - } - - @objc func stopChannelMediaRelay(_ callback: Callback) { - callback.code(engine?.stopChannelMediaRelay()) - } - - @objc func setDefaultAudioRoutetoSpeakerphone(_ params: NSDictionary, _ callback: Callback) { - callback.code(engine?.setDefaultAudioRouteToSpeakerphone(params["defaultToSpeaker"] as! Bool)) - } - - @objc func setEnableSpeakerphone(_ params: NSDictionary, _ callback: Callback) { - callback.code(engine?.setEnableSpeakerphone(params["enabled"] as! Bool)) - } - - @objc func isSpeakerphoneEnabled(_ callback: Callback) { - callback.resolve(engine) { - $0.isSpeakerphoneEnabled() - } - } - - @objc func enableInEarMonitoring(_ params: NSDictionary, _ callback: Callback) { - callback.code(engine?.enable(inEarMonitoring: params["enabled"] as! Bool)) - } - - @objc func setInEarMonitoringVolume(_ params: NSDictionary, _ callback: Callback) { - callback.code(engine?.setInEarMonitoringVolume((params["volume"] as! NSNumber).intValue)) - } - - @objc func enableDualStreamMode(_ params: NSDictionary, _ callback: Callback) { - callback.code(engine?.enableDualStreamMode(params["enabled"] as! Bool)) - } - - @objc func setRemoteVideoStreamType(_ params: NSDictionary, _ callback: Callback) { - callback.code(engine?.setRemoteVideoStream((params["uid"] as! NSNumber).uintValue, type: AgoraVideoStreamType(rawValue: (params["streamType"] as! NSNumber).intValue)!)) - } - - @objc func setRemoteDefaultVideoStreamType(_ params: NSDictionary, _ callback: Callback) { - callback.code(engine?.setRemoteDefaultVideoStreamType(AgoraVideoStreamType(rawValue: (params["streamType"] as! NSNumber).intValue)!)) - } - - @objc func setLocalPublishFallbackOption(_ params: NSDictionary, _ callback: Callback) { - callback.code(engine?.setLocalPublishFallbackOption(AgoraStreamFallbackOptions(rawValue: (params["option"] as! NSNumber).intValue)!)) - } - - @objc func setRemoteSubscribeFallbackOption(_ params: NSDictionary, _ callback: Callback) { - callback.code(engine?.setRemoteSubscribeFallbackOption(AgoraStreamFallbackOptions(rawValue: (params["option"] as! NSNumber).intValue)!)) - } - - @objc func setRemoteUserPriority(_ params: NSDictionary, _ callback: Callback) { - callback.code(engine?.setRemoteUserPriority((params["uid"] as! NSNumber).uintValue, type: AgoraUserPriority(rawValue: (params["userPriority"] as! NSNumber).intValue)!)) - } - - @objc func startEchoTest(_ params: NSDictionary, _ callback: Callback) { - if let intervalInSeconds = (params["intervalInSeconds"] as? NSNumber) { - callback.code(engine?.startEchoTest(withInterval: intervalInSeconds.intValue)) - return - } - if let config = (params["config"] as? [String: Any]) { - callback.code(engine?.startEchoTest(withConfig: mapToEchoTestConfiguration(config))) - return - } - callback.code(engine?.startEchoTest()) - } - - @objc func stopEchoTest(_ callback: Callback) { - callback.code(engine?.stopEchoTest()) - } - - @objc func enableLastmileTest(_ callback: Callback) { - callback.code(engine?.enableLastmileTest()) - } - - @objc func disableLastmileTest(_ callback: Callback) { - callback.code(engine?.disableLastmileTest()) - } - - @objc func startLastmileProbeTest(_ params: NSDictionary, _ callback: Callback) { - callback.code(engine?.startLastmileProbeTest(mapToLastmileProbeConfig(params["config"] as! [String: Any]))) - } - - @objc func stopLastmileProbeTest(_ callback: Callback) { - callback.code(engine?.stopLastmileProbeTest()) - } - - @objc func registerMediaMetadataObserver(_ callback: Callback) { - let mediaObserver = MediaObserver { [weak self] in - self?.emitter(RtcEngineEvents.MetadataReceived, $0) - } - callback.resolve(engine) { - if $0.setMediaMetadataDelegate(mediaObserver, with: .video) { - self.mediaObserver = mediaObserver - } - return nil - } - } - - @objc func unregisterMediaMetadataObserver(_ callback: Callback) { - callback.resolve(engine) { - if $0.setMediaMetadataDelegate(nil, with: .video) { - self.mediaObserver = nil - } - return nil - } - } - - @objc func setMaxMetadataSize(_ params: NSDictionary, _ callback: Callback) { - callback.resolve(mediaObserver) { - $0.setMaxMetadataSize((params["size"] as! NSNumber).intValue) - } - } - - @objc func sendMetadata(_ params: NSDictionary, _ callback: Callback) { - callback.resolve(mediaObserver) { - $0.addMetadata(params["metadata"] as! String) - } - } - - @objc func addVideoWatermark(_ params: NSDictionary, _ callback: Callback) { - callback.code(engine?.addVideoWatermark(URL(string: params["watermarkUrl"] as! String)!, options: mapToWatermarkOptions(params["options"] as! [String: Any]))) - } - - @objc func clearVideoWatermarks(_ callback: Callback) { - callback.code(engine?.clearVideoWatermarks()) - } - - @objc func setEncryptionSecret(_ params: NSDictionary, _ callback: Callback) { - callback.code(engine?.setEncryptionSecret(params["secret"] as? String)) - } - - @objc func setEncryptionMode(_ params: NSDictionary, _ callback: Callback) { - var encryptionMode = "" - switch (params["encryptionMode"] as! NSNumber).intValue { - case AgoraEncryptionMode.AES128XTS.rawValue: - encryptionMode = "aes-128-xts" - case AgoraEncryptionMode.AES128ECB.rawValue: - encryptionMode = "aes-128-ecb" - case AgoraEncryptionMode.AES256XTS.rawValue: - encryptionMode = "aes-256-xts" - default: encryptionMode = "" - } - callback.code(engine?.setEncryptionMode(encryptionMode)) - } - - @objc func enableEncryption(_ params: NSDictionary, _ callback: Callback) { - callback.code(engine?.enableEncryption(params["enabled"] as! Bool, encryptionConfig: mapToEncryptionConfig(params["config"] as! [String: Any]))) - } - - @objc func startAudioRecording(_ params: NSDictionary, _ callback: Callback) { - if let config = params["config"] as? [String: Any] { - callback.code(engine?.startAudioRecording(withConfig: mapToAudioRecordingConfiguration(config))) - return - } - callback.code(engine?.startAudioRecording(params["filePath"] as! String, sampleRate: (params["sampleRate"] as! NSNumber).intValue, quality: AgoraAudioRecordingQuality(rawValue: (params["quality"] as! NSNumber).intValue)!)) - } - - @objc func stopAudioRecording(_ callback: Callback) { - callback.code(engine?.stopAudioRecording()) - } - - @objc func addInjectStreamUrl(_ params: NSDictionary, _ callback: Callback) { - callback.code(engine?.addInjectStreamUrl(params["url"] as! String, config: mapToLiveInjectStreamConfig(params["config"] as! [String: Any]))) - } - - @objc func removeInjectStreamUrl(_ params: NSDictionary, _ callback: Callback) { - callback.code(engine?.removeInjectStreamUrl(params["url"] as! String)) - } - - @objc func switchCamera(_ callback: Callback) { - callback.code(engine?.switchCamera()) - } - - @objc func isCameraZoomSupported(_ callback: Callback) { - callback.resolve(engine) { - $0.isCameraZoomSupported() - } - } - - @objc func isCameraTorchSupported(_ callback: Callback) { - callback.resolve(engine) { - $0.isCameraTorchSupported() - } - } - - @objc func isCameraFocusSupported(_ callback: Callback) { - callback.resolve(engine) { - $0.isCameraFocusPositionInPreviewSupported() - } - } - - @objc func isCameraExposurePositionSupported(_ callback: Callback) { - callback.resolve(engine) { - $0.isCameraExposurePositionSupported() - } - } - - @objc func isCameraAutoFocusFaceModeSupported(_ callback: Callback) { - callback.resolve(engine) { - $0.isCameraAutoFocusFaceModeSupported() - } - } - - @objc func setCameraZoomFactor(_ params: NSDictionary, _ callback: Callback) { - callback.resolve(engine) { - $0.setCameraZoomFactor(CGFloat(truncating: params["factor"] as! NSNumber)) - return nil - } - } - - @objc func getCameraMaxZoomFactor(_ callback: Callback) { - callback.code(-Int32(AgoraErrorCode.notSupported.rawValue)) - } - - @objc func setCameraFocusPositionInPreview(_ params: NSDictionary, _ callback: Callback) { - callback.resolve(engine) { - $0.setCameraFocusPositionInPreview(CGPoint(x: (params["positionX"] as! NSNumber).doubleValue, y: (params["positionY"] as! NSNumber).doubleValue)) - return nil - } - } - - @objc func setCameraExposurePosition(_ params: NSDictionary, _ callback: Callback) { - callback.resolve(engine) { - $0.setCameraExposurePosition(CGPoint(x: (params["positionXinView"] as! NSNumber).doubleValue, y: (params["positionYinView"] as! NSNumber).doubleValue)) - return nil - } - } - - @objc func enableFaceDetection(_ params: NSDictionary, _ callback: Callback) { - callback.code(engine?.enableFaceDetection(params["enabled"] as! Bool)) - } - - @objc func setCameraTorchOn(_ params: NSDictionary, _ callback: Callback) { - callback.resolve(engine) { - $0.setCameraTorchOn(params["isOn"] as! Bool) - return nil - } - } - - @objc func setCameraAutoFocusFaceModeEnabled(_ params: NSDictionary, _ callback: Callback) { - callback.resolve(engine) { - $0.setCameraAutoFocusFaceModeEnabled(params["enabled"] as! Bool) - } - } - - @objc func setCameraCapturerConfiguration(_ params: NSDictionary, _ callback: Callback) { - callback.code(engine?.setCameraCapturerConfiguration(mapToCameraCapturerConfiguration(params["config"] as! [String: Any]))) - } - - @objc func createDataStream(_ params: NSDictionary, _ callback: Callback) { - var streamId = 0 - if let config = params["config"] as? [String: Any] { - callback.code(engine?.createDataStream(&streamId, config: mapToDataStreamConfig(config))) { _ in - streamId - } - return - } - callback.code(engine?.createDataStream(&streamId, reliable: params["reliable"] as! Bool, ordered: params["ordered"] as! Bool)) { _ in - streamId - } - } - - @objc func sendStreamMessage(_ params: NSDictionary, _ callback: Callback) { - callback.code(engine?.sendStreamMessage((params["streamId"] as! NSNumber).intValue, data: (params["message"] as! String).data(using: .utf8)!)) - } - - @objc func setVoiceBeautifierParameters(_ params: NSDictionary, _ callback: Callback) { - callback.code(engine?.setVoiceBeautifierParameters(AgoraVoiceBeautifierPreset(rawValue: (params["preset"] as! NSNumber).intValue)!, param1: (params["param1"] as! NSNumber).int32Value, param2: (params["param2"] as! NSNumber).int32Value)) - } - - @objc func getSdkVersion(_ callback: Callback) { - callback.success(AgoraRtcEngineKit.getSdkVersion()) - } - - @objc func getErrorDescription(_ params: NSDictionary, _ callback: Callback) { - callback.success(AgoraRtcEngineKit.getErrorDescription((params["error"] as! NSNumber).intValue)) - } - - @objc func enableDeepLearningDenoise(_ params: NSDictionary, _ callback: Callback) { - callback.code(engine?.enableDeepLearningDenoise(params["enabled"] as! Bool)) - } - - @objc func setCloudProxy(_ params: NSDictionary, _ callback: Callback) { - callback.code(engine?.setCloudProxy(AgoraCloudProxyType(rawValue: (params["proxyType"] as! NSNumber).uintValue)!)) - } - - @objc func uploadLogFile(_ callback: Callback) { - callback.resolve(engine) { - $0.uploadLogFile() - } - } - - @objc func enableRemoteSuperResolution(_ params: NSDictionary, _ callback: Callback) { - callback.code(engine?.enableRemoteSuperResolution((params["uid"] as! NSNumber).uintValue, enabled: params["enabled"] as! Bool)) - } - - @objc func setLocalAccessPoint(_ params: NSDictionary, _ callback: Callback) { - let list = params["ips"] as! [Any] - var ips: [String] = [] - for i in list.indices { - if let item = list[i] as? String { - ips.append(item) - } - } - callback.code(engine?.setLocalAccessPoint(ips, domain: params["domain"] as! String)) - } - - @objc func pauseAllChannelMediaRelay(_ callback: Callback) { - callback.code(engine?.pauseAllChannelMediaRelay()) - } - - @objc func resumeAllChannelMediaRelay(_ callback: Callback) { - callback.code(engine?.resumeAllChannelMediaRelay()) - } - - @objc func enableVirtualBackground(_ params: NSDictionary, _ callback: Callback) { - callback.code(engine?.enableVirtualBackground(params["enabled"] as! Bool, backData: mapToVirtualBackgroundSource(params["backgroundSource"] as! [String: Any]))) - } - - @objc func takeSnapshot(_ params: NSDictionary, _ callback: Callback) { - var code: Int32? - if let ret = engine?.takeSnapshot(params["channel"] as! String, uid: (params["uid"] as! NSNumber).intValue, filePath: params["filePath"] as! String) { - code = Int32(ret); - } - callback.code(code) - } -} diff --git a/ios/Classes/Base/RtcEngineEvent.swift b/ios/Classes/Base/RtcEngineEvent.swift deleted file mode 100644 index dd4f555ed..000000000 --- a/ios/Classes/Base/RtcEngineEvent.swift +++ /dev/null @@ -1,536 +0,0 @@ -// -// RtcEngineEvent.swift -// RCTAgora -// -// Created by LXH on 2020/4/13. -// Copyright (c) 2020 Syan. All rights reserved. -// - -import AgoraRtcKit -import Foundation - -class RtcEngineEvents { - static let Warning = "Warning" - static let Error = "Error" - static let ApiCallExecuted = "ApiCallExecuted" - static let JoinChannelSuccess = "JoinChannelSuccess" - static let RejoinChannelSuccess = "RejoinChannelSuccess" - static let LeaveChannel = "LeaveChannel" - static let LocalUserRegistered = "LocalUserRegistered" - static let UserInfoUpdated = "UserInfoUpdated" - static let ClientRoleChanged = "ClientRoleChanged" - static let UserJoined = "UserJoined" - static let UserOffline = "UserOffline" - static let ConnectionStateChanged = "ConnectionStateChanged" - static let NetworkTypeChanged = "NetworkTypeChanged" - static let ConnectionLost = "ConnectionLost" - static let TokenPrivilegeWillExpire = "TokenPrivilegeWillExpire" - static let RequestToken = "RequestToken" - static let AudioVolumeIndication = "AudioVolumeIndication" - static let ActiveSpeaker = "ActiveSpeaker" - static let FirstLocalAudioFrame = "FirstLocalAudioFrame" - static let FirstLocalVideoFrame = "FirstLocalVideoFrame" - static let UserMuteVideo = "UserMuteVideo" - static let VideoSizeChanged = "VideoSizeChanged" - static let RemoteVideoStateChanged = "RemoteVideoStateChanged" - static let LocalVideoStateChanged = "LocalVideoStateChanged" - static let RemoteAudioStateChanged = "RemoteAudioStateChanged" - static let LocalAudioStateChanged = "LocalAudioStateChanged" - static let RequestAudioFileInfo = "RequestAudioFileInfo" - static let LocalPublishFallbackToAudioOnly = "LocalPublishFallbackToAudioOnly" - static let RemoteSubscribeFallbackToAudioOnly = "RemoteSubscribeFallbackToAudioOnly" - static let AudioRouteChanged = "AudioRouteChanged" - static let CameraFocusAreaChanged = "CameraFocusAreaChanged" - static let CameraExposureAreaChanged = "CameraExposureAreaChanged" - static let FacePositionChanged = "FacePositionChanged" - static let RtcStats = "RtcStats" - static let LastmileQuality = "LastmileQuality" - static let NetworkQuality = "NetworkQuality" - static let LastmileProbeResult = "LastmileProbeResult" - static let LocalVideoStats = "LocalVideoStats" - static let LocalAudioStats = "LocalAudioStats" - static let RemoteVideoStats = "RemoteVideoStats" - static let RemoteAudioStats = "RemoteAudioStats" - static let AudioMixingFinished = "AudioMixingFinished" - static let AudioMixingStateChanged = "AudioMixingStateChanged" - static let AudioEffectFinished = "AudioEffectFinished" - static let RtmpStreamingStateChanged = "RtmpStreamingStateChanged" - static let TranscodingUpdated = "TranscodingUpdated" - static let StreamInjectedStatus = "StreamInjectedStatus" - static let StreamMessage = "StreamMessage" - static let StreamMessageError = "StreamMessageError" - static let MediaEngineLoadSuccess = "MediaEngineLoadSuccess" - static let MediaEngineStartCallSuccess = "MediaEngineStartCallSuccess" - static let ChannelMediaRelayStateChanged = "ChannelMediaRelayStateChanged" - static let ChannelMediaRelayEvent = "ChannelMediaRelayEvent" - static let FirstRemoteVideoFrame = "FirstRemoteVideoFrame" - static let FirstRemoteAudioFrame = "FirstRemoteAudioFrame" - static let FirstRemoteAudioDecoded = "FirstRemoteAudioDecoded" - static let UserMuteAudio = "UserMuteAudio" - static let StreamPublished = "StreamPublished" - static let StreamUnpublished = "StreamUnpublished" - static let RemoteAudioTransportStats = "RemoteAudioTransportStats" - static let RemoteVideoTransportStats = "RemoteVideoTransportStats" - static let UserEnableVideo = "UserEnableVideo" - static let UserEnableLocalVideo = "UserEnableLocalVideo" - static let FirstRemoteVideoDecoded = "FirstRemoteVideoDecoded" - static let MicrophoneEnabled = "MicrophoneEnabled" - static let ConnectionInterrupted = "ConnectionInterrupted" - static let ConnectionBanned = "ConnectionBanned" - static let AudioQuality = "AudioQuality" - static let CameraReady = "CameraReady" - static let VideoStopped = "VideoStopped" - static let MetadataReceived = "MetadataReceived" - static let FirstLocalAudioFramePublished = "FirstLocalAudioFramePublished" - static let FirstLocalVideoFramePublished = "FirstLocalVideoFramePublished" - static let AudioPublishStateChanged = "AudioPublishStateChanged" - static let VideoPublishStateChanged = "VideoPublishStateChanged" - static let AudioSubscribeStateChanged = "AudioSubscribeStateChanged" - static let VideoSubscribeStateChanged = "VideoSubscribeStateChanged" - static let RtmpStreamingEvent = "RtmpStreamingEvent" - static let UserSuperResolutionEnabled = "UserSuperResolutionEnabled" - static let UploadLogResult = "UploadLogResult" - static let AirPlayIsConnected = "AirPlayIsConnected" - static let VirtualBackgroundSourceEnabled = "VirtualBackgroundSourceEnabled" - static let SnapshotTaken = "SnapshotTaken" - - static func toMap() -> [String: String] { - return [ - "Warning": Warning, - "Error": Error, - "ApiCallExecuted": ApiCallExecuted, - "JoinChannelSuccess": JoinChannelSuccess, - "RejoinChannelSuccess": RejoinChannelSuccess, - "LeaveChannel": LeaveChannel, - "LocalUserRegistered": LocalUserRegistered, - "UserInfoUpdated": UserInfoUpdated, - "ClientRoleChanged": ClientRoleChanged, - "UserJoined": UserJoined, - "UserOffline": UserOffline, - "ConnectionStateChanged": ConnectionStateChanged, - "NetworkTypeChanged": NetworkTypeChanged, - "ConnectionLost": ConnectionLost, - "TokenPrivilegeWillExpire": TokenPrivilegeWillExpire, - "RequestToken": RequestToken, - "AudioVolumeIndication": AudioVolumeIndication, - "ActiveSpeaker": ActiveSpeaker, - "FirstLocalAudioFrame": FirstLocalAudioFrame, - "FirstLocalVideoFrame": FirstLocalVideoFrame, - "UserMuteVideo": UserMuteVideo, - "VideoSizeChanged": VideoSizeChanged, - "RemoteVideoStateChanged": RemoteVideoStateChanged, - "LocalVideoStateChanged": LocalVideoStateChanged, - "RemoteAudioStateChanged": RemoteAudioStateChanged, - "LocalAudioStateChanged": LocalAudioStateChanged, - "RequestAudioFileInfo": RequestAudioFileInfo, - "LocalPublishFallbackToAudioOnly": LocalPublishFallbackToAudioOnly, - "RemoteSubscribeFallbackToAudioOnly": RemoteSubscribeFallbackToAudioOnly, - "AudioRouteChanged": AudioRouteChanged, - "CameraFocusAreaChanged": CameraFocusAreaChanged, - "CameraExposureAreaChanged": CameraExposureAreaChanged, - "FacePositionChanged": FacePositionChanged, - "RtcStats": RtcStats, - "LastmileQuality": LastmileQuality, - "NetworkQuality": NetworkQuality, - "LastmileProbeResult": LastmileProbeResult, - "LocalVideoStats": LocalVideoStats, - "LocalAudioStats": LocalAudioStats, - "RemoteVideoStats": RemoteVideoStats, - "RemoteAudioStats": RemoteAudioStats, - "AudioMixingFinished": AudioMixingFinished, - "AudioMixingStateChanged": AudioMixingStateChanged, - "AudioEffectFinished": AudioEffectFinished, - "RtmpStreamingStateChanged": RtmpStreamingStateChanged, - "TranscodingUpdated": TranscodingUpdated, - "StreamInjectedStatus": StreamInjectedStatus, - "StreamMessage": StreamMessage, - "StreamMessageError": StreamMessageError, - "MediaEngineLoadSuccess": MediaEngineLoadSuccess, - "MediaEngineStartCallSuccess": MediaEngineStartCallSuccess, - "ChannelMediaRelayStateChanged": ChannelMediaRelayStateChanged, - "ChannelMediaRelayEvent": ChannelMediaRelayEvent, - "FirstRemoteVideoFrame": FirstRemoteVideoFrame, - "FirstRemoteAudioFrame": FirstRemoteAudioFrame, - "FirstRemoteAudioDecoded": FirstRemoteAudioDecoded, - "UserMuteAudio": UserMuteAudio, - "StreamPublished": StreamPublished, - "StreamUnpublished": StreamUnpublished, - "RemoteAudioTransportStats": RemoteAudioTransportStats, - "RemoteVideoTransportStats": RemoteVideoTransportStats, - "UserEnableVideo": UserEnableVideo, - "UserEnableLocalVideo": UserEnableLocalVideo, - "FirstRemoteVideoDecoded": FirstRemoteVideoDecoded, - "MicrophoneEnabled": MicrophoneEnabled, - "ConnectionInterrupted": ConnectionInterrupted, - "ConnectionBanned": ConnectionBanned, - "AudioQuality": AudioQuality, - "CameraReady": CameraReady, - "VideoStopped": VideoStopped, - "MetadataReceived": MetadataReceived, - "FirstLocalAudioFramePublished": FirstLocalAudioFramePublished, - "FirstLocalVideoFramePublished": FirstLocalVideoFramePublished, - "AudioPublishStateChanged": AudioPublishStateChanged, - "VideoPublishStateChanged": VideoPublishStateChanged, - "AudioSubscribeStateChanged": AudioSubscribeStateChanged, - "VideoSubscribeStateChanged": VideoSubscribeStateChanged, - "RtmpStreamingEvent": RtmpStreamingEvent, - "UserSuperResolutionEnabled": UserSuperResolutionEnabled, - "UploadLogResult": UploadLogResult, - "AirPlayIsConnected": AirPlayIsConnected, - "VirtualBackgroundSourceEnabled": VirtualBackgroundSourceEnabled, - "SnapshotTaken": SnapshotTaken, - ] - } -} - -class RtcEngineEventHandler: NSObject { - static let PREFIX = "io.agora.rtc." - - var emitter: (_ methodName: String, _ data: [String: Any?]?) -> Void - - init(emitter: @escaping (_ methodName: String, _ data: [String: Any?]?) -> Void) { - self.emitter = emitter - } - - private func callback(_ methodName: String, _ data: Any?...) { - emitter(methodName, ["data": data]) - } -} - -extension RtcEngineEventHandler: AgoraRtcEngineDelegate { - public func rtcEngine(_: AgoraRtcEngineKit, didOccurWarning warningCode: AgoraWarningCode) { - callback(RtcEngineEvents.Warning, warningCode.rawValue) - } - - public func rtcEngine(_: AgoraRtcEngineKit, didOccurError errorCode: AgoraErrorCode) { - callback(RtcEngineEvents.Error, errorCode.rawValue) - } - - public func rtcEngine(_: AgoraRtcEngineKit, didApiCallExecute error: Int, api: String, result: String) { - callback(RtcEngineEvents.ApiCallExecuted, error, api, result) - } - - public func rtcEngine(_: AgoraRtcEngineKit, didJoinChannel channel: String, withUid uid: UInt, elapsed: Int) { - callback(RtcEngineEvents.JoinChannelSuccess, channel, uid, elapsed) - } - - public func rtcEngine(_: AgoraRtcEngineKit, didRejoinChannel channel: String, withUid uid: UInt, elapsed: Int) { - callback(RtcEngineEvents.RejoinChannelSuccess, channel, uid, elapsed) - } - - public func rtcEngine(_: AgoraRtcEngineKit, didLeaveChannelWith stats: AgoraChannelStats) { - callback(RtcEngineEvents.LeaveChannel, stats.toMap()) - } - - public func rtcEngine(_: AgoraRtcEngineKit, didRegisteredLocalUser userAccount: String, withUid uid: UInt) { - callback(RtcEngineEvents.LocalUserRegistered, uid, userAccount) - } - - public func rtcEngine(_: AgoraRtcEngineKit, didUpdatedUserInfo userInfo: AgoraUserInfo, withUid uid: UInt) { - callback(RtcEngineEvents.UserInfoUpdated, uid, userInfo.toMap()) - } - - public func rtcEngine(_: AgoraRtcEngineKit, didClientRoleChanged oldRole: AgoraClientRole, newRole: AgoraClientRole) { - callback(RtcEngineEvents.ClientRoleChanged, oldRole.rawValue, newRole.rawValue) - } - - public func rtcEngine(_: AgoraRtcEngineKit, didJoinedOfUid uid: UInt, elapsed: Int) { - callback(RtcEngineEvents.UserJoined, uid, elapsed) - } - - public func rtcEngine(_: AgoraRtcEngineKit, didOfflineOfUid uid: UInt, reason: AgoraUserOfflineReason) { - callback(RtcEngineEvents.UserOffline, uid, reason.rawValue) - } - - public func rtcEngine(_: AgoraRtcEngineKit, connectionChangedTo state: AgoraConnectionStateType, reason: AgoraConnectionChangedReason) { - callback(RtcEngineEvents.ConnectionStateChanged, state.rawValue, reason.rawValue) - } - - public func rtcEngine(_: AgoraRtcEngineKit, networkTypeChangedTo type: AgoraNetworkType) { - callback(RtcEngineEvents.NetworkTypeChanged, type.rawValue) - } - - public func rtcEngineConnectionDidLost(_: AgoraRtcEngineKit) { - callback(RtcEngineEvents.ConnectionLost) - } - - public func rtcEngine(_: AgoraRtcEngineKit, tokenPrivilegeWillExpire token: String) { - callback(RtcEngineEvents.TokenPrivilegeWillExpire, token) - } - - public func rtcEngineRequestToken(_: AgoraRtcEngineKit) { - callback(RtcEngineEvents.RequestToken) - } - - public func rtcEngine(_: AgoraRtcEngineKit, reportAudioVolumeIndicationOfSpeakers speakers: [AgoraRtcAudioVolumeInfo], totalVolume: Int) { - callback(RtcEngineEvents.AudioVolumeIndication, speakers.toMapList(), totalVolume) - } - - public func rtcEngine(_: AgoraRtcEngineKit, activeSpeaker speakerUid: UInt) { - callback(RtcEngineEvents.ActiveSpeaker, speakerUid) - } - - public func rtcEngine(_: AgoraRtcEngineKit, firstLocalAudioFrame elapsed: Int) { - callback(RtcEngineEvents.FirstLocalAudioFrame, elapsed) - } - - public func rtcEngine(_: AgoraRtcEngineKit, firstLocalVideoFrameWith size: CGSize, elapsed: Int) { - callback(RtcEngineEvents.FirstLocalVideoFrame, Int(size.width), Int(size.height), elapsed) - } - - public func rtcEngine(_: AgoraRtcEngineKit, didVideoMuted muted: Bool, byUid uid: UInt) { - callback(RtcEngineEvents.UserMuteVideo, uid, muted) - } - - public func rtcEngine(_: AgoraRtcEngineKit, videoSizeChangedOfUid uid: UInt, size: CGSize, rotation: Int) { - callback(RtcEngineEvents.VideoSizeChanged, uid, Int(size.width), Int(size.height), rotation) - } - - public func rtcEngine(_: AgoraRtcEngineKit, remoteVideoStateChangedOfUid uid: UInt, state: AgoraVideoRemoteState, reason: AgoraVideoRemoteStateReason, elapsed: Int) { - callback(RtcEngineEvents.RemoteVideoStateChanged, uid, state.rawValue, reason.rawValue, elapsed) - } - - public func rtcEngine(_: AgoraRtcEngineKit, localVideoStateChange state: AgoraLocalVideoStreamState, error: AgoraLocalVideoStreamError) { - callback(RtcEngineEvents.LocalVideoStateChanged, state.rawValue, error.rawValue) - } - - public func rtcEngine(_: AgoraRtcEngineKit, remoteAudioStateChangedOfUid uid: UInt, state: AgoraAudioRemoteState, reason: AgoraAudioRemoteStateReason, elapsed: Int) { - callback(RtcEngineEvents.RemoteAudioStateChanged, uid, state.rawValue, reason.rawValue, elapsed) - } - - public func rtcEngine(_: AgoraRtcEngineKit, localAudioStateChange state: AgoraAudioLocalState, error: AgoraAudioLocalError) { - callback(RtcEngineEvents.LocalAudioStateChanged, state.rawValue, error.rawValue) - } - - public func rtcEngine(_ engine: AgoraRtcEngineKit, didRequest info: AgoraRtcAudioFileInfo, error: AgoraAudioFileInfoError) { - callback(RtcEngineEvents.RequestAudioFileInfo, info.toMap(), error.rawValue) - } - - public func rtcEngine(_: AgoraRtcEngineKit, didLocalPublishFallbackToAudioOnly isFallbackOrRecover: Bool) { - callback(RtcEngineEvents.LocalPublishFallbackToAudioOnly, isFallbackOrRecover) - } - - public func rtcEngine(_: AgoraRtcEngineKit, didRemoteSubscribeFallbackToAudioOnly isFallbackOrRecover: Bool, byUid uid: UInt) { - callback(RtcEngineEvents.RemoteSubscribeFallbackToAudioOnly, uid, isFallbackOrRecover) - } - - public func rtcEngine(_: AgoraRtcEngineKit, didAudioRouteChanged routing: AgoraAudioOutputRouting) { - callback(RtcEngineEvents.AudioRouteChanged, routing.rawValue) - } - - public func rtcEngine(_: AgoraRtcEngineKit, cameraFocusDidChangedTo rect: CGRect) { - callback(RtcEngineEvents.CameraFocusAreaChanged, rect.toMap()) - } - - public func rtcEngine(_: AgoraRtcEngineKit, cameraExposureDidChangedTo rect: CGRect) { - callback(RtcEngineEvents.CameraExposureAreaChanged, rect.toMap()) - } - - public func rtcEngine(_: AgoraRtcEngineKit, facePositionDidChangeWidth width: Int32, previewHeight height: Int32, faces: [AgoraFacePositionInfo]?) { - callback(RtcEngineEvents.FacePositionChanged, width, height, faces?.toMapList()) - } - - public func rtcEngine(_: AgoraRtcEngineKit, reportRtcStats stats: AgoraChannelStats) { - callback(RtcEngineEvents.RtcStats, stats.toMap()) - } - - public func rtcEngine(_: AgoraRtcEngineKit, lastmileQuality quality: AgoraNetworkQuality) { - callback(RtcEngineEvents.LastmileQuality, quality.rawValue) - } - - public func rtcEngine(_: AgoraRtcEngineKit, networkQuality uid: UInt, txQuality: AgoraNetworkQuality, rxQuality: AgoraNetworkQuality) { - callback(RtcEngineEvents.NetworkQuality, uid, txQuality.rawValue, rxQuality.rawValue) - } - - public func rtcEngine(_: AgoraRtcEngineKit, lastmileProbeTest result: AgoraLastmileProbeResult) { - callback(RtcEngineEvents.LastmileProbeResult, result.toMap()) - } - - public func rtcEngine(_: AgoraRtcEngineKit, localVideoStats stats: AgoraRtcLocalVideoStats) { - callback(RtcEngineEvents.LocalVideoStats, stats.toMap()) - } - - public func rtcEngine(_: AgoraRtcEngineKit, localAudioStats stats: AgoraRtcLocalAudioStats) { - callback(RtcEngineEvents.LocalAudioStats, stats.toMap()) - } - - public func rtcEngine(_: AgoraRtcEngineKit, remoteVideoStats stats: AgoraRtcRemoteVideoStats) { - callback(RtcEngineEvents.RemoteVideoStats, stats.toMap()) - } - - public func rtcEngine(_: AgoraRtcEngineKit, remoteAudioStats stats: AgoraRtcRemoteAudioStats) { - callback(RtcEngineEvents.RemoteAudioStats, stats.toMap()) - } - - public func rtcEngineLocalAudioMixingDidFinish(_: AgoraRtcEngineKit) { - callback(RtcEngineEvents.AudioMixingFinished) - } - - public func rtcEngine(_: AgoraRtcEngineKit, localAudioMixingStateDidChanged state: AgoraAudioMixingStateCode, reason: AgoraAudioMixingReasonCode) { - callback(RtcEngineEvents.AudioMixingStateChanged, state.rawValue, reason.rawValue) - } - - public func rtcEngineRemoteAudioMixingDidStart(_: AgoraRtcEngineKit) { - // TODO: Not in Android - } - - public func rtcEngineRemoteAudioMixingDidFinish(_: AgoraRtcEngineKit) { - // TODO: Not in Android - } - - public func rtcEngineDidAudioEffectFinish(_: AgoraRtcEngineKit, soundId: Int) { - callback(RtcEngineEvents.AudioEffectFinished, soundId) - } - - public func rtcEngine(_: AgoraRtcEngineKit, rtmpStreamingChangedToState url: String, state: AgoraRtmpStreamingState, errorCode: AgoraRtmpStreamingErrorCode) { - callback(RtcEngineEvents.RtmpStreamingStateChanged, url, state.rawValue, errorCode.rawValue) - } - - public func rtcEngineTranscodingUpdated(_: AgoraRtcEngineKit) { - callback(RtcEngineEvents.TranscodingUpdated) - } - - public func rtcEngine(_: AgoraRtcEngineKit, streamInjectedStatusOfUrl url: String, uid: UInt, status: AgoraInjectStreamStatus) { - callback(RtcEngineEvents.StreamInjectedStatus, url, uid, status.rawValue) - } - - public func rtcEngine(_: AgoraRtcEngineKit, receiveStreamMessageFromUid uid: UInt, streamId: Int, data: Data) { - callback(RtcEngineEvents.StreamMessage, uid, streamId, String(data: data, encoding: .utf8)) - } - - public func rtcEngine(_: AgoraRtcEngineKit, didOccurStreamMessageErrorFromUid uid: UInt, streamId: Int, error: Int, missed: Int, cached: Int) { - callback(RtcEngineEvents.StreamMessageError, uid, streamId, error, missed, cached) - } - - public func rtcEngineMediaEngineDidLoaded(_: AgoraRtcEngineKit) { - callback(RtcEngineEvents.MediaEngineLoadSuccess) - } - - public func rtcEngineMediaEngineDidStartCall(_: AgoraRtcEngineKit) { - callback(RtcEngineEvents.MediaEngineStartCallSuccess) - } - - public func rtcEngine(_: AgoraRtcEngineKit, channelMediaRelayStateDidChange state: AgoraChannelMediaRelayState, error: AgoraChannelMediaRelayError) { - callback(RtcEngineEvents.ChannelMediaRelayStateChanged, state.rawValue, error.rawValue) - } - - public func rtcEngine(_: AgoraRtcEngineKit, didReceive event: AgoraChannelMediaRelayEvent) { - callback(RtcEngineEvents.ChannelMediaRelayEvent, event.rawValue) - } - - public func rtcEngine(_: AgoraRtcEngineKit, firstRemoteVideoFrameOfUid uid: UInt, size: CGSize, elapsed: Int) { - callback(RtcEngineEvents.FirstRemoteVideoFrame, uid, Int(size.width), Int(size.height), elapsed) - } - - public func rtcEngine(_: AgoraRtcEngineKit, firstRemoteAudioFrameOfUid uid: UInt, elapsed: Int) { - callback(RtcEngineEvents.FirstRemoteAudioFrame, uid, elapsed) - } - - public func rtcEngine(_: AgoraRtcEngineKit, firstRemoteAudioFrameDecodedOfUid uid: UInt, elapsed: Int) { - callback(RtcEngineEvents.FirstRemoteAudioDecoded, uid, elapsed) - } - - public func rtcEngine(_: AgoraRtcEngineKit, didAudioMuted muted: Bool, byUid uid: UInt) { - callback(RtcEngineEvents.UserMuteAudio, uid, muted) - } - - public func rtcEngine(_: AgoraRtcEngineKit, streamPublishedWithUrl url: String, errorCode: AgoraErrorCode) { - callback(RtcEngineEvents.StreamPublished, url, errorCode.rawValue) - } - - public func rtcEngine(_: AgoraRtcEngineKit, streamUnpublishedWithUrl url: String) { - callback(RtcEngineEvents.StreamUnpublished, url) - } - - public func rtcEngine(_: AgoraRtcEngineKit, audioTransportStatsOfUid uid: UInt, delay: UInt, lost: UInt, rxKBitRate: UInt) { - callback(RtcEngineEvents.RemoteAudioTransportStats, uid, delay, lost, rxKBitRate) - } - - public func rtcEngine(_: AgoraRtcEngineKit, videoTransportStatsOfUid uid: UInt, delay: UInt, lost: UInt, rxKBitRate: UInt) { - callback(RtcEngineEvents.RemoteVideoTransportStats, uid, delay, lost, rxKBitRate) - } - - public func rtcEngine(_: AgoraRtcEngineKit, didVideoEnabled enabled: Bool, byUid uid: UInt) { - callback(RtcEngineEvents.UserEnableVideo, uid, enabled) - } - - public func rtcEngine(_: AgoraRtcEngineKit, didLocalVideoEnabled enabled: Bool, byUid uid: UInt) { - callback(RtcEngineEvents.UserEnableLocalVideo, uid, enabled) - } - - public func rtcEngine(_: AgoraRtcEngineKit, firstRemoteVideoDecodedOfUid uid: UInt, size: CGSize, elapsed: Int) { - callback(RtcEngineEvents.FirstRemoteVideoDecoded, uid, Int(size.width), Int(size.height), elapsed) - } - - public func rtcEngine(_: AgoraRtcEngineKit, didMicrophoneEnabled enabled: Bool) { - callback(RtcEngineEvents.MicrophoneEnabled, enabled) - } - - public func rtcEngineConnectionDidInterrupted(_: AgoraRtcEngineKit) { - callback(RtcEngineEvents.ConnectionInterrupted) - } - - public func rtcEngineConnectionDidBanned(_: AgoraRtcEngineKit) { - callback(RtcEngineEvents.ConnectionBanned) - } - - public func rtcEngine(_: AgoraRtcEngineKit, audioQualityOfUid uid: UInt, quality: AgoraNetworkQuality, delay: UInt, lost: UInt) { - callback(RtcEngineEvents.AudioQuality, uid, quality.rawValue, delay, lost) - } - - public func rtcEngineCameraDidReady(_: AgoraRtcEngineKit) { - callback(RtcEngineEvents.CameraReady) - } - - public func rtcEngineVideoDidStop(_: AgoraRtcEngineKit) { - callback(RtcEngineEvents.VideoStopped) - } - - public func rtcEngine(_: AgoraRtcEngineKit, firstLocalAudioFramePublished elapsed: Int) { - callback(RtcEngineEvents.FirstLocalAudioFramePublished, elapsed) - } - - public func rtcEngine(_: AgoraRtcEngineKit, firstLocalVideoFramePublished elapsed: Int) { - callback(RtcEngineEvents.FirstLocalVideoFramePublished, elapsed) - } - - public func rtcEngine(_: AgoraRtcEngineKit, didAudioPublishStateChange channel: String, oldState: AgoraStreamPublishState, newState: AgoraStreamPublishState, elapseSinceLastState: Int) { - callback(RtcEngineEvents.AudioPublishStateChanged, channel, oldState.rawValue, newState.rawValue, elapseSinceLastState) - } - - public func rtcEngine(_: AgoraRtcEngineKit, didVideoPublishStateChange channel: String, oldState: AgoraStreamPublishState, newState: AgoraStreamPublishState, elapseSinceLastState: Int) { - callback(RtcEngineEvents.VideoPublishStateChanged, channel, oldState.rawValue, newState.rawValue, elapseSinceLastState) - } - - public func rtcEngine(_: AgoraRtcEngineKit, didAudioSubscribeStateChange channel: String, withUid uid: UInt, oldState: AgoraStreamSubscribeState, newState: AgoraStreamSubscribeState, elapseSinceLastState: Int) { - callback(RtcEngineEvents.AudioSubscribeStateChanged, channel, uid, oldState.rawValue, newState.rawValue, elapseSinceLastState) - } - - public func rtcEngine(_: AgoraRtcEngineKit, didVideoSubscribeStateChange channel: String, withUid uid: UInt, oldState: AgoraStreamSubscribeState, newState: AgoraStreamSubscribeState, elapseSinceLastState: Int) { - callback(RtcEngineEvents.VideoSubscribeStateChanged, channel, uid, oldState.rawValue, newState.rawValue, elapseSinceLastState) - } - - public func rtcEngine(_: AgoraRtcEngineKit, rtmpStreamingEventWithUrl url: String, eventCode: AgoraRtmpStreamingEvent) { - callback(RtcEngineEvents.RtmpStreamingEvent, url, eventCode.rawValue) - } - - public func rtcEngine(_: AgoraRtcEngineKit, superResolutionEnabledOfUid uid: UInt, enabled: Bool, reason: AgoraSuperResolutionStateReason) { - callback(RtcEngineEvents.UserSuperResolutionEnabled, uid, enabled, reason.rawValue) - } - - public func rtcEngine(_: AgoraRtcEngineKit, uploadLogResultRequestId requestId: String, success: Bool, reason: AgoraUploadErrorReason) { - callback(RtcEngineEvents.UploadLogResult, requestId, success, reason.rawValue) - } - - public func rtcEngineAirPlayIsConnected(_ engine: AgoraRtcEngineKit) { - callback(RtcEngineEvents.AirPlayIsConnected) - } - - public func rtcEngine(_ engine: AgoraRtcEngineKit, virtualBackgroundSourceEnabled enabled: Bool, reason: AgoraVirtualBackgroundSourceStateReason) { - callback(RtcEngineEvents.VirtualBackgroundSourceEnabled, enabled, reason.rawValue) - } - - public func rtcEngine(_ engine: AgoraRtcEngineKit, snapshotTaken channel: String, uid: UInt, filePath: String, width: Int, height: Int, errCode: Int) { - callback(RtcEngineEvents.SnapshotTaken, channel, uid, filePath, width, height, errCode) - } -} diff --git a/ios/Classes/Base/RtcEnginePlugin.h b/ios/Classes/Base/RtcEnginePlugin.h index 93d89eef8..5eecf0792 100644 --- a/ios/Classes/Base/RtcEnginePlugin.h +++ b/ios/Classes/Base/RtcEnginePlugin.h @@ -14,7 +14,7 @@ NS_ASSUME_NONNULL_BEGIN [RtcEngine.createWithContext](https://docs.agora.io/cn/Video/API%20Reference/flutter/agora_rtc_engine/RtcEngine/createWithContext.html) * function from flutter. - * NOTE that you should not call `AgoraRtcEngineKit.destroy`, because it will also destroy the `RtcEngine` + * NOTE that you should not call `AgoraRtcEngineKit.destroy`, because it will also destroy the `RtcEngine` * used by flutter side. * * @param rtcEngine The same `AgoraRtcEngineKit` used by flutter side diff --git a/ios/Classes/Base/RtcEnginePluginRegistrant.h b/ios/Classes/Base/RtcEnginePluginRegistrant.h new file mode 100644 index 000000000..27dc5e688 --- /dev/null +++ b/ios/Classes/Base/RtcEnginePluginRegistrant.h @@ -0,0 +1,25 @@ +#ifndef RtcEnginePluginRegistrant_h +#define RtcEnginePluginRegistrant_h + +#import +#import "RtcEnginePlugin.h" + +/** + * Class for register the `RtcEnginePlugin`. + */ +@interface RtcEnginePluginRegistrant : NSObject + +/** + * Register a `RtcEnginePlugin`. The `plugin` will be called when the `RtcEngine` is created from + * flutter side. + */ ++(void)register:(NSObject *_Nonnull)plugin; + +/** + * Unregister a previously registered `RtcEnginePlugin`. + */ ++(void)unregister:(NSObject *_Nonnull)plugin; + +@end + +#endif /* RtcEnginePluginRegistrant_h */ diff --git a/ios/Classes/Base/RtcEnginePluginRegistrant.mm b/ios/Classes/Base/RtcEnginePluginRegistrant.mm new file mode 100644 index 000000000..5a15cb895 --- /dev/null +++ b/ios/Classes/Base/RtcEnginePluginRegistrant.mm @@ -0,0 +1,15 @@ +#import +#import "RtcEngineRegistry.h" +#import "RtcEnginePlugin.h" +#import "RtcEnginePluginRegistrant.h" + +@implementation RtcEnginePluginRegistrant : NSObject + ++ (void)register:(NSObject *)plugin { + [[RtcEngineRegistry shared] add:plugin]; +} + ++ (void)unregister:(NSObject *)plugin { + [[RtcEngineRegistry shared] remove:plugin]; +} +@end diff --git a/ios/Classes/Base/RtcEnginePluginRegistrant.swift b/ios/Classes/Base/RtcEnginePluginRegistrant.swift deleted file mode 100644 index 9921db30e..000000000 --- a/ios/Classes/Base/RtcEnginePluginRegistrant.swift +++ /dev/null @@ -1,22 +0,0 @@ -import Foundation - -/** - * Class for register the `RtcEnginePlugin`. - */ -@objc -public class RtcEnginePluginRegistrant: NSObject { - /** - * Register a `RtcEnginePlugin`. The `plugin` will be called when the `RtcEngine` is created from - * flutter side. - */ - @objc public static func register(_ plugin: RtcEnginePlugin) { - RtcEngineRegistry.shared.add(plugin) - } - - /** - * Unregister a previously registered `RtcEnginePlugin`. - */ - @objc public static func unregister(_ plugin: RtcEnginePlugin) { - RtcEngineRegistry.shared.remove(plugin) - } -} diff --git a/ios/Classes/Base/RtcEngineRegistry.h b/ios/Classes/Base/RtcEngineRegistry.h new file mode 100644 index 000000000..d86e60574 --- /dev/null +++ b/ios/Classes/Base/RtcEngineRegistry.h @@ -0,0 +1,24 @@ +#ifndef RtcEngineRegistry_h +#define RtcEngineRegistry_h + +#import "RtcEnginePlugin.h" + +/** + * The `RtcEngineRegistry` is response to add, remove and notify the callback when `RtcEngine` is created + * from flutter side. + */ +@interface RtcEngineRegistry : NSObject ++ (RtcEngineRegistry *)shared; + +/** + * Add a `RtcEnginePlugin`. + */ +- (void)add:(NSObject*) plugin; + +/** + * Remove the previously added `RtcEnginePlugin`. + */ +- (void)remove:(NSObject*) plugin; +@end + +#endif /* RtcEngineRegistry_h */ diff --git a/ios/Classes/Base/RtcEngineRegistry.mm b/ios/Classes/Base/RtcEngineRegistry.mm new file mode 100644 index 000000000..381b77efe --- /dev/null +++ b/ios/Classes/Base/RtcEngineRegistry.mm @@ -0,0 +1,53 @@ +#import +#import "RtcEngineRegistry.h" + +@interface RtcEngineRegistry() +@property(nonatomic) NSMutableDictionary*> *plugins; +@end + +@implementation RtcEngineRegistry + +-(id)init { + if (self = [super init]) { + self.plugins = [[NSMutableDictionary alloc]initWithCapacity:2]; + } + return self; +} + +static RtcEngineRegistry *_rtcEngineRegistryOC = nil; + ++ (RtcEngineRegistry *)shared { + @synchronized([RtcEngineRegistry class]) { + if (!_rtcEngineRegistryOC) + _rtcEngineRegistryOC = [[self alloc] init]; + return _rtcEngineRegistryOC; + } + return nil; +} + +- (void)add:(NSObject*) plugin { + [[self plugins] setObject:plugin forKey:(id)[plugin class]]; +} + +- (void)remove:(NSObject*) plugin { + [[self plugins] removeObjectForKey:(id)[plugin class]]; +} + +// MARK: - protocol from RtcEnginePlugin +- (void)onRtcEngineCreated:(AgoraRtcEngineKit * _Nullable)rtcEngine { + for (id key in self.plugins) { + NSObject* plugin = [self.plugins objectForKey:key]; + [plugin onRtcEngineCreated:rtcEngine]; + } +} + +// MARK: - protocol from RtcEnginePlugin +- (void)onRtcEngineDestroyed { + for (id key in self.plugins) { + NSObject* plugin = [self.plugins objectForKey:key]; + [plugin onRtcEngineDestroyed]; + } +} + +@end + diff --git a/ios/Classes/Base/RtcEngineRegistry.swift b/ios/Classes/Base/RtcEngineRegistry.swift deleted file mode 100644 index ca4c7ebd9..000000000 --- a/ios/Classes/Base/RtcEngineRegistry.swift +++ /dev/null @@ -1,61 +0,0 @@ -import Foundation -import AgoraRtcKit - -fileprivate struct PluginKey: Hashable, Equatable { - let type: AnyClass - - public static func == (lhs: PluginKey, rhs: PluginKey) -> Bool { - return lhs.type == rhs.type - } - - public func hash(into hasher: inout Hasher) { - hasher.combine(ObjectIdentifier(type)) - } -} - -/** - * The `RtcEngineRegistry` is response to add, remove and notify the callback when `RtcEngine` is created - * from flutter side. - */ -internal class RtcEngineRegistry : NSObject { - - private override init() {} - - static let shared = RtcEngineRegistry() - - private var plugins: [PluginKey : RtcEnginePlugin] = [PluginKey: RtcEnginePlugin]() - - /** - * Add a `RtcEnginePlugin`. - */ - func add(_ plugin: RtcEnginePlugin) { - let key = PluginKey(type: type(of: plugin)) - guard plugins[key] == nil else { - return - } - plugins[key] = plugin - } - - /** - * Remove the previously added `RtcEnginePlugin`. - */ - func remove(_ plugin: RtcEnginePlugin) { - plugins.removeValue(forKey: PluginKey(type: type(of: plugin))) - } -} - -extension RtcEngineRegistry : RtcEnginePlugin { - // MARK: - protocol from RtcEnginePlugin - public func onRtcEngineCreated(_ rtcEngine: AgoraRtcEngineKit?) { - for (_, plugin) in plugins { - plugin.onRtcEngineCreated(rtcEngine) - } - } - - // MARK: - protocol from RtcEnginePlugin - public func onRtcEngineDestroyed() { - for (_, plugin) in plugins { - plugin.onRtcEngineDestroyed() - } - } -} diff --git a/ios/Classes/Base/RtcSurfaceView.swift b/ios/Classes/Base/RtcSurfaceView.swift deleted file mode 100644 index 1cb7f72f9..000000000 --- a/ios/Classes/Base/RtcSurfaceView.swift +++ /dev/null @@ -1,98 +0,0 @@ -import AgoraRtcKit -import Foundation -import UIKit - -class RtcSurfaceView: UIView { - private var surface: UIView - private var canvas: AgoraRtcVideoCanvas - private weak var channel: AgoraRtcChannel? - - override init(frame: CGRect) { - surface = UIView(frame: CGRect(origin: CGPoint(x: 0, y: 0), size: frame.size)) - canvas = AgoraRtcVideoCanvas() - canvas.view = surface - super.init(frame: frame) - addSubview(surface) - addObserver(self, forKeyPath: observerForKeyPath(), options: .new, context: nil) - } - - func observerForKeyPath() -> String { - return "frame" - } - - @available(*, unavailable) - required init?(coder _: NSCoder) { - fatalError("init(coder:) has not been implemented") - } - - deinit { - canvas.view = nil - removeObserver(self, forKeyPath: observerForKeyPath(), context: nil) - } - - func setData(_ engine: AgoraRtcEngineKit, _ channel: AgoraRtcChannel?, _ uid: UInt) { - self.channel = channel - canvas.channelId = channel?.getId() - canvas.uid = uid - setupVideoCanvas(engine) - } - - func resetVideoCanvas(_ engine: AgoraRtcEngineKit) { - let canvas = AgoraRtcVideoCanvas() - canvas.view = nil - canvas.renderMode = self.canvas.renderMode - canvas.channelId = self.canvas.channelId - canvas.uid = self.canvas.uid - canvas.mirrorMode = self.canvas.mirrorMode - - if canvas.uid == 0 { - engine.setupLocalVideo(canvas) - } else { - engine.setupRemoteVideo(canvas) - } - } - - private func setupVideoCanvas(_ engine: AgoraRtcEngineKit) { - subviews.forEach { - $0.removeFromSuperview() - } - surface = UIView(frame: CGRect(origin: CGPoint(x: 0, y: 0), size: bounds.size)) - addSubview(surface) - canvas.view = surface - if canvas.uid == 0 { - engine.setupLocalVideo(canvas) - } else { - engine.setupRemoteVideo(canvas) - } - } - - func setRenderMode(_ engine: AgoraRtcEngineKit, _ renderMode: UInt) { - canvas.renderMode = AgoraVideoRenderMode(rawValue: renderMode)! - setupRenderMode(engine) - } - - func setMirrorMode(_ engine: AgoraRtcEngineKit, _ mirrorMode: UInt) { - canvas.mirrorMode = AgoraVideoMirrorMode(rawValue: mirrorMode)! - setupRenderMode(engine) - } - - private func setupRenderMode(_ engine: AgoraRtcEngineKit) { - if canvas.uid == 0 { - engine.setLocalRenderMode(canvas.renderMode, mirrorMode: canvas.mirrorMode) - } else { - if let channel = channel { - channel.setRemoteRenderMode(canvas.uid, renderMode: canvas.renderMode, mirrorMode: canvas.mirrorMode) - } else { - engine.setRemoteRenderMode(canvas.uid, renderMode: canvas.renderMode, mirrorMode: canvas.mirrorMode) - } - } - } - - override func observeValue(forKeyPath keyPath: String?, of _: Any?, change: [NSKeyValueChangeKey: Any]?, context _: UnsafeMutableRawPointer?) { - if keyPath == observerForKeyPath() { - if let rect = change?[.newKey] as? CGRect { - surface.frame = CGRect(origin: CGPoint(x: 0, y: 0), size: rect.size) - } - } - } -} diff --git a/ios/Classes/CallApiMethodCallHandler.h b/ios/Classes/CallApiMethodCallHandler.h new file mode 100644 index 000000000..1b2ae4917 --- /dev/null +++ b/ios/Classes/CallApiMethodCallHandler.h @@ -0,0 +1,24 @@ +#ifndef CallApiMethodCallHandler_h +#define CallApiMethodCallHandler_h + +#if TARGET_OS_IPHONE +#import +#else +#import +#endif + +@interface CallApiMethodCallHandler : NSObject +//@property(nonatomic) agora::iris::rtc::IrisRtcEngine *irisRtcEngine; +- (instancetype)initWith:(void *)engine; +- (void)onMethodCall:(FlutterMethodCall *)call _:(FlutterResult)result; +- (int)callApi:(NSNumber *) apiType _:(NSString *)params _:(char *) result; + +- (int)callApiWithBuffer:(NSNumber *) apiType _:(NSString *)params _:(void *)buffer _:(char *) result; + +- (NSString *)callApiError:(int)ret; +@end + +#endif /* CallApiMethodCallHandler_h */ + +@interface RtcChannelCallApiMethodCallHandler : CallApiMethodCallHandler +@end diff --git a/ios/Classes/CallApiMethodCallHandler.mm b/ios/Classes/CallApiMethodCallHandler.mm new file mode 100644 index 000000000..33ed8e990 --- /dev/null +++ b/ios/Classes/CallApiMethodCallHandler.mm @@ -0,0 +1,104 @@ +#import +#import "CallApiMethodCallHandler.h" +#import +#import "Base/RtcEngineRegistry.h" + +@interface CallApiMethodCallHandler () +@property(nonatomic) agora::iris::rtc::IrisRtcEngine *irisRtcEngine; +@end + +@implementation CallApiMethodCallHandler + +- (instancetype)initWith:(void *)engine { + self.irisRtcEngine = (agora::iris::rtc::IrisRtcEngine *)engine; + return self; +} + +- (void)onMethodCall:(FlutterMethodCall *)call _:(FlutterResult)result { + if ([@"callApi" isEqualToString:call.method] || [@"callApiWithBuffer" isEqualToString:call.method]) { + @try { + NSDictionary *arguments = call.arguments; + NSNumber *apiType = arguments[@"apiType"]; + NSString *params = arguments[@"params"]; + FlutterStandardTypedData *buffer = arguments[@"buffer"]; + char res[kBasicResultLength] = ""; + int ret; + if (buffer == nil || buffer == [NSNull null]) { + + ret = [self callApi:apiType _:params _:res]; + } else { + ret = [self callApiWithBuffer:apiType _:params _:(void *)[[buffer data] bytes] _:res]; + } + if (ret == 0) { + if (strlen(res) == 0) { + result(nil); + } else { + result([NSString stringWithUTF8String:res]); + } + } else if (ret > 0) { + result(@(ret)); + } else { + NSString *des = [self callApiError:ret]; + result([FlutterError + errorWithCode:[@(ret) stringValue] + message:des + details:nil]); + } + } @catch (NSException *exception) { + result([FlutterError + errorWithCode:exception.name + message:exception.reason + details:nil]); + } + } else { + result(FlutterMethodNotImplemented); + } +} +- (int)callApi:(NSNumber *) apiType _:(NSString *)params _:(char *) result { + ApiTypeEngine apiTypeEngine = (ApiTypeEngine)[apiType unsignedIntValue]; + int ret = self.irisRtcEngine->CallApi(apiTypeEngine, [params UTF8String], result); + + if (apiTypeEngine == ApiTypeEngine::kEngineInitialize) { + [[RtcEngineRegistry shared] onRtcEngineCreated:(__bridge AgoraRtcEngineKit *) self.irisRtcEngine->rtc_engine()]; + } + + if (apiTypeEngine == ApiTypeEngine::kEngineRelease) { + [[RtcEngineRegistry shared] onRtcEngineDestroyed]; + } + + return ret; + +} + +- (int)callApiWithBuffer:(NSNumber *) apiType _:(NSString *)params _:(void *)buffer _:(char *) result { + return self.irisRtcEngine->CallApi((ApiTypeEngine)[apiType unsignedIntValue], [params UTF8String], buffer, result); +} + +- (NSString *)callApiError:(int)ret { + char description[kBasicResultLength]; + self.irisRtcEngine->CallApi( + ApiTypeEngine::kEngineGetErrorDescription, + [[NSString stringWithFormat:@"{\"code\":%d}", abs(ret)] UTF8String], + description); + return [NSString stringWithUTF8String:description]; +} + + +@end + +@implementation RtcChannelCallApiMethodCallHandler + +- (int)callApi:(NSNumber *)apiType _:(NSString *)params _:(char *)result { + return self.irisRtcEngine->channel()->CallApi((ApiTypeChannel)[apiType unsignedIntValue], + [params UTF8String], + result); +} + +- (int)callApiWithBuffer:(NSNumber *)apiType _:(NSString *)params _:(void *)buffer _:(char *)result { + return self.irisRtcEngine->channel()->CallApi((ApiTypeChannel)[apiType unsignedIntValue], + [params UTF8String], + buffer, + result); +} + +@end diff --git a/ios/Classes/FlutterIrisEventHandler.h b/ios/Classes/FlutterIrisEventHandler.h new file mode 100644 index 000000000..0e93c0f1b --- /dev/null +++ b/ios/Classes/FlutterIrisEventHandler.h @@ -0,0 +1,20 @@ +#ifndef FlutterIrisEventHandler_h +#define FlutterIrisEventHandler_h + +#if TARGET_OS_IPHONE +#import +#else +#import +#endif + +@interface FlutterIrisEventHandler : NSObject +- (instancetype)initWith:(void *)engine; +- (instancetype)initWith:(void *)mainEngine subEngine:(void *)subEngine; +- (void)setUpEventHandler:(void *)engine eventHandler:(void *)eventHandler; +- (void)resetEventHandler:(void *)engine; +@end + +@interface RtcChannelFlutterIrisEventHandler : FlutterIrisEventHandler +@end + +#endif /* FlutterIrisEventHandler_h */ diff --git a/ios/Classes/FlutterIrisEventHandler.mm b/ios/Classes/FlutterIrisEventHandler.mm new file mode 100644 index 000000000..f56d7e076 --- /dev/null +++ b/ios/Classes/FlutterIrisEventHandler.mm @@ -0,0 +1,130 @@ +#import +#import "FlutterIrisEventHandler.h" +#import + +class EventHandler : public agora::iris::IrisEventHandler { +public: + EventHandler(FlutterEventSink eventSink, bool shouldHandleSubProcess = false, bool sub_process = false) : eventSink_(eventSink), sub_process_(sub_process), shouldHandleSubProcess_(shouldHandleSubProcess) { + } + + void OnEvent(const char *event, const char *data) override { + @autoreleasepool { + if (eventSink_) { + NSMutableDictionary *dic = [NSMutableDictionary dictionaryWithObjectsAndKeys:[NSString stringWithUTF8String:event], @"methodName", [NSString stringWithUTF8String:data], @"data", nil]; + + if (shouldHandleSubProcess_) { + [dic setObject:@(sub_process_) forKey:@"subProcess"]; + } + + eventSink_(dic); + } + } + } + + void OnEvent(const char *event, const char *data, const void *buffer, + unsigned int length) override { + @autoreleasepool { + FlutterStandardTypedData *bufferApple = [FlutterStandardTypedData + typedDataWithBytes:[[NSData alloc] initWithBytes:buffer + length:length]]; + if (eventSink_) { + NSMutableDictionary *dic = [NSMutableDictionary dictionaryWithObjectsAndKeys:[NSString stringWithUTF8String:event], @"methodName", [NSString stringWithUTF8String:data], @"data", bufferApple, @"buffer", nil]; + + if (shouldHandleSubProcess_) { + [dic setObject:@(sub_process_) forKey:@"subProcess"]; + } + + eventSink_(dic); + } + } + } + +private: + FlutterEventSink eventSink_; + bool sub_process_; + bool shouldHandleSubProcess_; +}; + +@interface FlutterIrisEventHandler () +@property(nonatomic) FlutterEventSink eventSink; +@property(nonatomic) agora::iris::rtc::IrisRtcEngine *irisRtcEngine; +@property(nonatomic) agora::iris::rtc::IrisRtcEngine *irisRtcEngineSub; +@property(nonatomic) EventHandler *eventHandler; +@property(nonatomic) EventHandler *eventHandlerSub; +@end + +@implementation FlutterIrisEventHandler + +- (instancetype)initWith:(void *)engine { + self.irisRtcEngine = (agora::iris::rtc::IrisRtcEngine *)engine; + return self; +} + +- (instancetype)initWith:(void *)mainEngine subEngine:(void *)subEngine { + self = [super init]; + if (self) { + self.irisRtcEngine = (agora::iris::rtc::IrisRtcEngine *)mainEngine; + self.irisRtcEngineSub = (agora::iris::rtc::IrisRtcEngine *)subEngine; + } + return self; +} + +- (void)dealloc { + if (self.eventHandler) { + delete self.eventHandler; + } + if (self.eventHandlerSub) { + delete self.eventHandlerSub; + } +} + +- (FlutterError *_Nullable)onCancelWithArguments:(id _Nullable)arguments { + self.eventSink = nil; +// self.irisRtcEngine->SetEventHandler(nil); + + [self resetEventHandler:self.irisRtcEngine]; + if (self.irisRtcEngineSub) { + [self resetEventHandler:self.irisRtcEngineSub]; + } + + return nil; +} + +- (FlutterError *)onListenWithArguments:(id)arguments eventSink:(FlutterEventSink)events { + self.eventSink = events; + if (!self.eventHandler) { + self.eventHandler = new EventHandler(self.eventSink, self.irisRtcEngineSub != nil, false); + [self setUpEventHandler:self.irisRtcEngine eventHandler:self.eventHandler]; + if (self.irisRtcEngineSub != nil) { + self.eventHandlerSub = new EventHandler(self.eventSink, true, true); + [self setUpEventHandler:self.irisRtcEngineSub eventHandler:self.eventHandler]; + } + } + + return nil; +} + +- (void)setUpEventHandler:(void *)engine eventHandler:(void *)eventHandler { + agora::iris::rtc::IrisRtcEngine *e = (agora::iris::rtc::IrisRtcEngine *)engine; + e->SetEventHandler((EventHandler *)eventHandler); +} + +- (void)resetEventHandler:(void *)engine { + agora::iris::rtc::IrisRtcEngine *e = (agora::iris::rtc::IrisRtcEngine *)engine; + e->SetEventHandler(nil); +} + +@end + +@implementation RtcChannelFlutterIrisEventHandler +- (void)setUpEventHandler:(void *)engine eventHandler:(void *)eventHandler { + agora::iris::rtc::IrisRtcEngine *e = (agora::iris::rtc::IrisRtcEngine *)engine; + e->channel()->SetEventHandler((EventHandler *)eventHandler); +} + +- (void)resetEventHandler:(void *)engine { + agora::iris::rtc::IrisRtcEngine *e = (agora::iris::rtc::IrisRtcEngine *)engine; + e->channel()->SetEventHandler(nil); +} + +@end diff --git a/ios/Classes/ResultCallback.swift b/ios/Classes/ResultCallback.swift deleted file mode 100644 index 45b16b9ac..000000000 --- a/ios/Classes/ResultCallback.swift +++ /dev/null @@ -1,25 +0,0 @@ -// -// ResultCallback.swift -// agora_rtc_engine -// -// Created by LXH on 2020/6/24. -// - -import Foundation -import AgoraRtcKit - -class ResultCallback: NSObject, Callback { - private var result: FlutterResult? - - init(_ result: FlutterResult? = nil) { - self.result = result - } - - func success(_ data: Any?) { - result?(data) - } - - func failure(_ code: String, _ message: String) { - result?(FlutterError.init(code: code, message: message, details: nil)) - } -} diff --git a/ios/Classes/SwiftAgoraRtcEnginePlugin.swift b/ios/Classes/SwiftAgoraRtcEnginePlugin.swift deleted file mode 100644 index 34df87aff..000000000 --- a/ios/Classes/SwiftAgoraRtcEnginePlugin.swift +++ /dev/null @@ -1,99 +0,0 @@ -import Flutter -import UIKit - -public class SwiftAgoraRtcEnginePlugin: NSObject, FlutterPlugin, FlutterStreamHandler { - private var registrar: FlutterPluginRegistrar? - private var methodChannel: FlutterMethodChannel? - private var eventChannel: FlutterEventChannel? - private var eventSink: FlutterEventSink? = nil - private lazy var manager: RtcEngineManager = { - return RtcEngineManager() { [weak self] methodName, data in - self?.emit(methodName, data) - } - }() - private lazy var rtcChannelPlugin: AgoraRtcChannelPlugin = { - return AgoraRtcChannelPlugin(self) - }() - - public static func register(with registrar: FlutterPluginRegistrar) { - let rtcEnginePlugin = SwiftAgoraRtcEnginePlugin() - rtcEnginePlugin.registrar = registrar - rtcEnginePlugin.rtcChannelPlugin.initPlugin(registrar) - rtcEnginePlugin.initPlugin(registrar) - } - - private func initPlugin(_ registrar: FlutterPluginRegistrar) { - methodChannel = FlutterMethodChannel(name: "agora_rtc_engine", binaryMessenger: registrar.messenger()) - eventChannel = FlutterEventChannel(name: "agora_rtc_engine/events", binaryMessenger: registrar.messenger()) - registrar.addMethodCallDelegate(self, channel: methodChannel!) - eventChannel?.setStreamHandler(self) - - registrar.register(AgoraSurfaceViewFactory(registrar.messenger(), self, rtcChannelPlugin), withId: "AgoraSurfaceView") - } - - public func detachFromEngine(for registrar: FlutterPluginRegistrar) { - rtcChannelPlugin.detachFromEngine(for: registrar) - methodChannel?.setMethodCallHandler(nil) - eventChannel?.setStreamHandler(nil) - manager.Release() - } - - public func onListen(withArguments arguments: Any?, eventSink events: @escaping FlutterEventSink) -> FlutterError? { - eventSink = events - return nil - } - - public func onCancel(withArguments arguments: Any?) -> FlutterError? { - eventSink = nil - return nil - } - - private func emit(_ methodName: String, _ data: Dictionary?) { - var event: Dictionary = ["methodName": methodName] - if let `data` = data { - event.merge(data) { (current, _) in - current - } - } - eventSink?(event) - } - - weak var engine: AgoraRtcEngineKit? { - return manager.engine - } - - public func handle(_ call: FlutterMethodCall, result: @escaping FlutterResult) { - if call.method == "getAssetAbsolutePath" { - getAssetAbsolutePath(call, result: result) - return - } - if let params = call.arguments as? NSDictionary { - let selector = NSSelectorFromString(call.method + "::") - if manager.responds(to: selector) { - manager.perform(selector, with: params, with: ResultCallback(result)) - return - } - } else { - let selector = NSSelectorFromString(call.method + ":") - if manager.responds(to: selector) { - manager.perform(selector, with: ResultCallback(result)) - return - } - } - result(FlutterMethodNotImplemented) - } - - private func getAssetAbsolutePath(_ call: FlutterMethodCall, result: @escaping FlutterResult) { - if let assetPath = call.arguments as? String { - if let assetKey = registrar?.lookupKey(forAsset: assetPath) { - if let realPath = Bundle.main.path(forResource: assetKey, ofType: nil) { - result(realPath) - return - } - } - result(FlutterError.init(code: "FileNotFoundException", message: nil, details: nil)) - return - } - result(FlutterError.init(code: "IllegalArgumentException", message: nil, details: nil)) - } -} diff --git a/ios/agora_rtc_engine.podspec b/ios/agora_rtc_engine.podspec index ab9cdab23..48ed4ca57 100644 --- a/ios/agora_rtc_engine.podspec +++ b/ios/agora_rtc_engine.podspec @@ -15,12 +15,13 @@ Pod::Spec.new do |s| s.license = { :file => '../LICENSE' } s.author = { 'Agora' => 'developer@agora.io' } s.source = { :path => '.' } - s.source_files = 'Classes/**/*' + s.source_files = 'Classes/**/*.{h,mm,m,swift}' s.dependency 'Flutter' - s.dependency 'AgoraRtcEngine_iOS', '3.5.2' - s.platform = :ios, '8.0' + s.dependency 'AgoraIrisRTC_iOS', '3.5.2' + s.platform = :ios, '9.0' + s.swift_version = '5.0' + s.libraries = 'stdc++' # Flutter.framework does not contain a i386 slice. s.pod_target_xcconfig = { 'DEFINES_MODULE' => 'YES', 'EXCLUDED_ARCHS[sdk=iphonesimulator*]' => 'i386' } - s.swift_version = '5.0' end diff --git a/lib/agora_rtc_engine_web.dart b/lib/agora_rtc_engine_web.dart index 8523963ea..74cbd321a 100644 --- a/lib/agora_rtc_engine_web.dart +++ b/lib/agora_rtc_engine_web.dart @@ -1,45 +1,236 @@ +@JS() +library agora_rtc_engine_web; + import 'dart:async'; +import 'dart:convert'; + // In order to *not* need this ignore, consider extracting the "web" version // of your plugin as a separate package, instead of inlining it in the same // package as the core of your plugin. // ignore: avoid_web_libraries_in_flutter -import 'dart:html' as html show window; +import 'dart:html'; +import 'dart:ui' as ui; +import 'package:agora_rtc_engine/src/enums.dart'; +import 'package:flutter/foundation.dart'; import 'package:flutter/services.dart'; import 'package:flutter_web_plugins/flutter_web_plugins.dart'; +import 'package:js/js.dart'; +import 'package:js/js_util.dart'; + +@JS('IrisRtcEngine') +class _IrisRtcEngine { + external _IrisRtcEngine(); + + external _IrisRtcChannel get channel; + + external _IrisRtcDeviceManager get deviceManager; + + external Future callApi(int apiType, String params, [Object? extra]); + + external void setEventHandler(Function params); +} + +@JS('IrisRtcChannel') +class _IrisRtcChannel { + external Future callApi(int apiType, String params, [Object? extra]); + + external void setEventHandler(Function params); +} + +@JS('IrisRtcDeviceManager') +class _IrisRtcDeviceManager { + external Future callApiAudio(int apiType, String params, + [Object? extra]); + + external Future callApiVideo(int apiType, String params, + [Object? extra]); +} /// A web implementation of the AgoraRtcEngine plugin. class AgoraRtcEngineWeb { + // ignore: public_member_api_docs static void registerWith(Registrar registrar) { - final channel = MethodChannel( + final methodChannel = MethodChannel( 'agora_rtc_engine', const StandardMethodCodec(), - registrar.messenger, + registrar, ); + final eventChannel = PluginEventChannel( + 'agora_rtc_engine/events', const StandardMethodCodec(), registrar); final pluginInstance = AgoraRtcEngineWeb(); - channel.setMethodCallHandler(pluginInstance.handleMethodCall); + methodChannel.setMethodCallHandler(pluginInstance.handleMethodCall); + eventChannel.setController(pluginInstance._controller_engine); + + MethodChannel( + 'agora_rtc_channel', + const StandardMethodCodec(), + registrar, + ).setMethodCallHandler(pluginInstance.handleChannelMethodCall); + PluginEventChannel( + 'agora_rtc_channel/events', const StandardMethodCodec(), registrar) + .setController(pluginInstance._controller_channel); + + MethodChannel( + 'agora_rtc_audio_device_manager', + const StandardMethodCodec(), + registrar, + ).setMethodCallHandler(pluginInstance.handleADMMethodCall); + + MethodChannel( + 'agora_rtc_video_device_manager', + const StandardMethodCodec(), + registrar, + ).setMethodCallHandler(pluginInstance.handleVDMMethodCall); + + ui.platformViewRegistry.registerViewFactory('AgoraSurfaceView', + (int viewId) { + var element = DivElement(); + MethodChannel('agora_rtc_engine/surface_view_$viewId', + const StandardMethodCodec(), registrar) + .setMethodCallHandler( + (call) => pluginInstance.handleViewMethodCall(call, element)); + return element; + }); + } + + final _controller_engine = StreamController(); + final _controller_channel = StreamController(); + final _IrisRtcEngine _engine_main = _IrisRtcEngine(); + final _IrisRtcEngine _engine_sub = _IrisRtcEngine(); + + _IrisRtcEngine _engine(Map args) { + bool subProcess = args['subProcess']; + if (subProcess) { + return _engine_sub; + } else { + return _engine_main; + } } /// Handles method calls over the MethodChannel of this plugin. /// Note: Check the "federated" architecture for a new way of doing this: /// https://flutter.dev/go/federated-plugins Future handleMethodCall(MethodCall call) async { - switch (call.method) { - case 'getPlatformVersion': - return getPlatformVersion(); - default: - throw PlatformException( - code: 'Unimplemented', - details: - 'agora_rtc_engine for web doesn\'t implement \'${call.method}\'', - ); + var args = {}; + if (call.arguments != null) { + args = Map.from(call.arguments); + } + if (call.method == 'callApi') { + int apiType = args['apiType']; + if (apiType == 0) { + _engine(args).setEventHandler(allowInterop((String event, String data) { + _controller_engine.add({ + 'methodName': event, + 'data': data, + 'subProcess': _engine(args) == _engine_sub, + }); + })); + _engine(args) + .channel + .setEventHandler(allowInterop((String event, String data) { + _controller_channel.add({ + 'methodName': event, + 'data': data, + }); + })); + } + String param = args['params']; + return promiseToFuture(_engine(args).callApi(apiType, param)); + } else { + throw PlatformException(code: ErrorCode.NotSupported.toString()); + } + } + + // ignore: public_member_api_docs + Future handleChannelMethodCall(MethodCall call) async { + var args = {}; + if (call.arguments != null) { + args = Map.from(call.arguments); + } + if (call.method == 'callApi') { + int apiType = args['apiType']; + String param = args['params']; + return promiseToFuture(_engine_main.channel.callApi(apiType, param)); + } else { + throw PlatformException(code: ErrorCode.NotSupported.toString()); } } - /// Returns a [String] containing the version of the platform. - Future getPlatformVersion() { - final version = html.window.navigator.userAgent; - return Future.value(version); + // ignore: public_member_api_docs + Future handleADMMethodCall(MethodCall call) async { + var args = {}; + if (call.arguments != null) { + args = Map.from(call.arguments); + } + if (call.method == 'callApi') { + int apiType = args['apiType']; + String param = args['params']; + return promiseToFuture( + _engine_main.deviceManager.callApiAudio(apiType, param)); + } else { + throw PlatformException(code: ErrorCode.NotSupported.toString()); + } + } + + // ignore: public_member_api_docs + Future handleVDMMethodCall(MethodCall call) async { + var args = {}; + if (call.arguments != null) { + args = Map.from(call.arguments); + } + if (call.method == 'callApi') { + int apiType = args['apiType']; + String param = args['params']; + return promiseToFuture( + _engine_main.deviceManager.callApiVideo(apiType, param)); + } else { + throw PlatformException(code: ErrorCode.NotSupported.toString()); + } + } + + // ignore: public_member_api_docs + Future handleViewMethodCall(MethodCall call, Element element) async { + var data = {}; + if (call.arguments != null) { + data = Map.from(call.arguments); + } + if (call.method == 'setData') { + final uid = data['userId']; + if (uid == 0) { + final kEngineSetupLocalVideo = 20; + return promiseToFuture(_engine(data).callApi( + kEngineSetupLocalVideo, + jsonEncode({ + 'canvas': { + 'uid': 0, + 'channelId': data['channelId'], + 'renderMode': data['renderMode'], + 'mirrorMode': data['mirrorMode'], + }, + }), + element)); + } else { + final kEngineSetupRemoteVideo = 21; + return promiseToFuture(_engine(data).callApi( + kEngineSetupRemoteVideo, + jsonEncode({ + 'canvas': { + 'uid': uid, + 'channelId': data['channelId'], + 'renderMode': data['renderMode'], + 'mirrorMode': data['mirrorMode'], + } + }), + element)); + } + } else { + throw PlatformException( + code: 'Unimplemented', + details: + 'agora_rtc_engine for web doesn\'t implement \'${call.method}\'', + ); + } } } diff --git a/lib/agora_rtc_engine_web.ng.dart b/lib/agora_rtc_engine_web.ng.dart new file mode 100644 index 000000000..efaf4be36 --- /dev/null +++ b/lib/agora_rtc_engine_web.ng.dart @@ -0,0 +1,1122 @@ +@JS() +library agora_rtc_engine_web; + +import 'dart:async'; + +// In order to *not* need this ignore, consider extracting the "web" version +// of your plugin as a separate package, instead of inlining it in the same +// package as the core of your plugin. +// ignore: avoid_web_libraries_in_flutter +import 'dart:html'; +import 'dart:ui' as ui; + +import 'package:agora_rtc_engine/src/enum_converter.dart'; +import 'package:agora_rtc_engine/src/enums.dart'; +import 'package:flutter/services.dart'; +import 'package:flutter_web_plugins/flutter_web_plugins.dart'; +import 'package:js/js.dart'; +import 'package:js/js_util.dart'; + +@JS() +@anonymous +class _AgoraRTCError { + external String get code; + + external String get message; + + external Object? get data; + + external String get _name; + + external _AgoraRTCError(String code, [String? message, Object? data]); + + @override + external String toString(); + + external _AgoraRTCError print(); +} + +@JS() +class _AgoraRTCStats { + external int get Duration; + + external int get RecvBitrate; + + external int get RecvBytes; + + external int get SendBitrate; + + external int get SendBytes; + + external int get UserCount; + + external int get RTT; + + external int get OutgoingAvailableBandwidth; +} + +@JS() +@anonymous +class _AudioEncoderConfiguration { + external factory _AudioEncoderConfiguration({ + int? sampleRate, + int? sampleSize, + int? stereo, + int? bitrate, + }); +} + +@JS() +@anonymous +class _AudioSourceOptions { + external factory _AudioSourceOptions({ + int? cycle, + bool? loop, + int? startPlayTime, + }); +} + +@JS() +@anonymous +class _BeautyEffectOptions { + external factory _BeautyEffectOptions({ + double? smoothnessLevel, + double? lighteningLevel, + double? rednessLevel, + int? lighteningContrastLevel, + }); +} + +@JS() +@anonymous +class _BufferSourceAudioTrackInitConfig { + external factory _BufferSourceAudioTrackInitConfig({ + String source, + bool? cacheOnlineFile, + _AudioEncoderConfiguration? encoderConfig, + }); +} + +@JS() +@anonymous +class _CameraVideoTrackInitConfig { + external factory _CameraVideoTrackInitConfig({ + _VideoEncoderConfiguration? encoderConfig, + String? facingMode, + String? cameraId, + String? optimizationMode, + _SVCConfiguration? scalabiltyMode, + }); +} + +@JS() +@anonymous +class _ChannelMediaRelayInfo { + external factory _ChannelMediaRelayInfo({ + String channelName, + String? token, + int uid, + }); +} + +@JS() +@anonymous +class _ClientConfig { + external factory _ClientConfig({ + String codec, + String mode, + String? role, + _ClientRoleOptions? clientRoleOptions, + String? proxyServer, + _TurnServerConfig? turnServer, + _RetryConfiguration? httpRetryConfig, + _RetryConfiguration? websocketRetryConfig, + }); +} + +@JS() +@anonymous +class _ClientRoleOptions { + external factory _ClientRoleOptions({ + int level, + }); +} + +@JS() +@anonymous +class _ConstrainLong { + external factory _ConstrainLong({ + int? min, + int? max, + int? ideal, + int? exact, + }); +} + +@JS() +@anonymous +class _CustomAudioTrackInitConfig { + external factory _CustomAudioTrackInitConfig({ + MediaStreamTrack mediaStreamTrack, + _AudioEncoderConfiguration? encoderConfig, + }); +} + +@JS() +@anonymous +class _CustomVideoTrackInitConfig { + external factory _CustomVideoTrackInitConfig({ + MediaStreamTrack mediaStreamTrack, + int? bitrateMin, + int? bitrateMax, + String? optimizationMode, + _SVCConfiguration? scalabiltyMode, + }); +} + +@JS() +class _DeviceInfo { + external int get updateAt; + + external int get initAt; + + external String get state; + + external MediaDeviceInfo get device; +} + +@JS() +@anonymous +class _EventCustomReportParams { + external factory _EventCustomReportParams({ + String reportId, + String category, + String event, + String label, + int value, + }); +} + +@JS() +class _EventEmitter { + external String get _events; + + external List getListeners(String event); + + external void on(String event, Function listener); + + external void once(String event, Function listener); + + external void off(String event, Function listener); + + external void removeAllListeners([String? event]); + + external int get _indexOfListener; +} + +@JS('AgoraRTC') +class _AgoraRTC { + external static String get VERSION; + + external static Future>> getSupportedCodec(); + + external static bool checkSystemRequirements(); + + external static _AgoraRTCClient createClient(_ClientConfig config); + + external static _LocalAudioTrack createCustomAudioTrack( + _CustomAudioTrackInitConfig config); + + external static Future<_MicrophoneAudioTrack> createMicrophoneAudioTrack( + [_MicrophoneAudioTrackInitConfig? config]); + + external static Future<_BufferSourceAudioTrack> createBufferSourceAudioTrack( + _BufferSourceAudioTrackInitConfig config); + + external static _LocalVideoTrack createCustomVideoTrack( + _CustomVideoTrackInitConfig config); + + external static Future<_CameraVideoTrack> createCameraVideoTrack( + [_CameraVideoTrackInitConfig? config]); + + external static Future> createMicrophoneAndCameraTracks( + [_MicrophoneAudioTrackInitConfig? audioConfig, + _CameraVideoTrackInitConfig? videoConfig]); + + external static Future createScreenVideoTrack( + _ScreenVideoTrackInitConfig config, + [String? withAudio = 'disable']); + + external static Future> getDevices( + [bool? skipPermissionCheck]); + + external static Future> getMicrophones( + [bool? skipPermissionCheck]); + + external static Future> getCameras( + [bool? skipPermissionCheck]); + + external static Future> getPlaybackDevices( + [bool? skipPermissionCheck]); + + external static void setLogLevel(int level); + + external static void enableLogUpload(); + + external static void disableLogUpload(); + + external static _ChannelMediaRelayConfiguration + createChannelMediaRelayConfiguration(); + + external static Future checkVideoTrackIsActive(Object track, + [int? timeout]); + + external static Future checkAudioTrackIsActive(Object track, + [int? timeout]); + + external static set onCameraChanged(Function _); + + external static set onMicrophoneChanged(Function _); + + external static set onPlaybackDeviceChanged(Function _); + + external static set onAudioAutoplayFailed(Function _); + + external static void setArea(List area); + + external static void startProcessingLocalAEC(MediaElement element); + + external static void setParameter(String key, String value); +} + +@JS() +@anonymous +class _LayerOptions { + external factory _LayerOptions({ + int spatialLayer, + int temporalLayer, + }); +} + +@JS() +class _AgoraRTCClient extends _EventEmitter { + external String get connectionState; + + external List<_AgoraRTCRemoteUser> get remoteUsers; + + external List<_LocalTrack> get localTracks; + + external int? get uid; + + external String? get channelName; + + external Future join(String appid, String channel, String? token, + [int? uid]); + + external Future leave(); + + external Future publish(List<_LocalTrack> tracks); + + external Future unpublish([List<_LocalTrack>? tracks]); + + external Future<_RemoteTrack> subscribe( + _AgoraRTCRemoteUser user, String mediaType); + + external Future unsubscribe(_AgoraRTCRemoteUser user, + [String? mediaType]); + + external void setLowStreamParameter(_LowStreamParameter streamParameter); + + external Future enableDualStream(); + + external Future disableDualStream(); + + external Future setClientRole(String role, + [_ClientRoleOptions? options]); + + external void setProxyServer(String proxyServer); + + external void setTurnServer(_TurnServerConfig turnServer); + + external void startProxyServer([int? mode]); + + external void stopProxyServer(); + + external Future setRemoteVideoStreamType(int uid, int streamType); + + external Future pickSVCLayer(int uid, _LayerOptions layerOptions); + + external Future setStreamFallbackOption(int uid, int fallbackType); + + external void setEncryptionConfig(String encryptionMode, String secret); + + external Future renewToken(String token); + + external void enableAudioVolumeIndicator(); + + external _AgoraRTCStats getRTCStats(); + + external Future setLiveTranscoding( + _LiveStreamingTranscodingConfig config); + + external Future startLiveStreaming(String url, + [bool? transcodingEnabled]); + + external Future stopLiveStreaming(String url); + + external Future addInjectStreamUrl( + String url, _InjectStreamConfig config); + + external Future removeInjectStreamUrl(String url); + + external Future startChannelMediaRelay( + _ChannelMediaRelayConfiguration config); + + external Future updateChannelMediaRelay( + _ChannelMediaRelayConfiguration config); + + external Future stopChannelMediaRelay(); + + external Future sendCustomReportMessage( + List<_EventCustomReportParams> reports); + + external _LocalAudioTrackStats getLocalAudioStats(); + + external Map getRemoteAudioStats(); + + external Map getRemoteNetworkQuality(); + + external _LocalVideoTrackStats getLocalVideoStats(); + + external Map getRemoteVideoStats(); +} + +@JS() +@anonymous +class _AgoraRTCRemoteUser { + external factory _AgoraRTCRemoteUser({ + int uid, + _RemoteAudioTrack? audioTrack, + _RemoteVideoTrack? videoTrack, + bool hasAudio, + bool hasVideo, + }); + + external int get uid; + + external _RemoteAudioTrack? get audioTrack; + + external _RemoteVideoTrack? get videoTrack; + + external bool get hasAudio; + + external bool get hasVideo; +} + +@JS() +class _BufferSourceAudioTrack extends _LocalAudioTrack { + external set source(String _); + + external String get source; + + external set currentState(String _); + + external String get currentState; + + external set duration(int _); + + external int get duration; + + external int getCurrentTime(); + + external void startProcessAudioBuffer([_AudioSourceOptions? options]); + + external void pauseProcessAudioBuffer(); + + external void seekAudioBuffer(int time); + + external void resumeProcessAudioBuffer(); + + external void stopProcessAudioBuffer(); +} + +@JS() +class _CameraVideoTrack extends _LocalVideoTrack { + external Future setDevice(String deviceId); + + external Future setEncoderConfiguration( + _VideoEncoderConfiguration config); +} + +@JS() +class _ChannelMediaRelayConfiguration { + external void setSrcChannelInfo(_ChannelMediaRelayInfo info); + + external void addDestChannelInfo(_ChannelMediaRelayInfo info); + + external void removeDestChannelInfo(String channelName); +} + +@JS() +class _LocalAudioTrack extends _LocalTrack { + external void setVolume(int volume); + + external double getVolumeLevel(); + + external void setAudioFrameCallback(Function audioFrameCallback, + [int? frameSize]); + + external void play(); + + external Future setPlaybackDevice(String deviceId); + + external _LocalAudioTrackStats getStats(); +} + +@JS() +class _LocalTrack extends _Track { + external Future setEnabled(bool enabled); + + external String getTrackLabel(); + + external void close(); +} + +@JS() +class _LocalVideoTrack extends _LocalTrack { + external void play(Object element, [_VideoPlayerConfig? config]); + + external _LocalVideoTrackStats getStats(); + + external Future setBeautyEffect(bool enabled, + [_BeautyEffectOptions? options]); + + external ImageData getCurrentFrameData(); + + external Future setOptimizationMode(String mode); +} + +@JS() +class _MicrophoneAudioTrack extends _LocalAudioTrack { + external Future setDevice(String deviceId); +} + +@JS() +@anonymous +class _InjectStreamConfig { + external factory _InjectStreamConfig({ + int? audioVolume, + int? audioBitrate, + int? audioChannels, + int? audioSampleRate, + int? height, + int? width, + int? videoBitrate, + int? videoFramerate, + int? videoGop, + }); +} + +@JS() +class _RemoteAudioTrack extends _RemoteTrack { + external _RemoteAudioTrackStats getStats(); + + external void play(); + + external Future setPlaybackDevice(String deviceId); + + external void setAudioFrameCallback(Function audioFrameCallback, + [int? frameSize]); + + external void setVolume(int volume); + + external double getVolumeLevel(); +} + +@JS() +class _RemoteTrack extends _Track { + external int getUserId(); +} + +@JS() +class _RemoteVideoTrack extends _RemoteTrack { + external _RemoteVideoTrackStats getStats(); + + external void play(HtmlElement element, [_VideoPlayerConfig? config]); + + external ImageData getCurrentFrameData(); +} + +@JS() +class _Track extends _EventEmitter { + external String get trackMediaType; + + external bool get isPlaying; + + external String getTrackId(); + + external MediaStreamTrack getMediaStreamTrack(); + + external void stop(); +} + +@JS() +@anonymous +class _LiveStreamingTranscodingConfig { + external factory _LiveStreamingTranscodingConfig({ + int? audioBitrate, + int? audioChannels, + int? audioSampleRate, + int? backgroundColor, + int? height, + int? width, + bool? lowLatency, + int? videoBitrate, + int? videoCodecProfile, + int? videoFrameRate, + int? videoGop, + List<_LiveStreamingTranscodingImage>? images, + _LiveStreamingTranscodingImage? watermark, + List<_LiveStreamingTranscodingImage>? backgroundImage, + List<_LiveStreamingTranscodingUser>? transcodingUsers, + String? userConfigExtraInfo, + }); +} + +@JS() +@anonymous +class _LiveStreamingTranscodingImage { + external factory _LiveStreamingTranscodingImage({ + String url, + int? x, + int? y, + int? width, + int? height, + double? alpha, + }); + + external String get url; + + external int? get x; + + external int? get y; + + external int? get width; + + external int? get height; + + external double? get alpha; +} + +@JS() +@anonymous +class _LiveStreamingTranscodingUser { + external factory _LiveStreamingTranscodingUser({ + double? alpha, + int? height, + int uid, + int? width, + int? x, + int? y, + int? zOrder, + int? audioChannel, + }); + + external double? get alpha; + + external int? get height; + + external int get uid; + + external int? get width; + + external int? get x; + + external int? get y; + + external int? get zOrder; + + external int? get audioChannel; +} + +@JS() +class _LocalAudioTrackStats { + external String? get codecType; + + external int get sendVolumeLevel; + + external int get sendBitrate; + + external int get sendBytes; + + external int get sendPackets; + + external int get sendPacketsLost; +} + +@JS() +class _LocalVideoTrackStats { + external String? get codecType; + + external int get sendBytes; + + external int? get sendFrameRate; + + external int? get captureFrameRate; + + external int get sendPackets; + + external int get sendPacketsLost; + + external int get sendResolutionHeight; + + external int get sendResolutionWidth; + + external int get captureResolutionHeight; + + external int get captureResolutionWidth; + + external int? get encodeDelay; + + external int get sendBitrate; + + external int get targetSendBitrate; + + external int get totalDuration; + + external int get totalFreezeTime; +} + +@JS() +@anonymous +class _LowStreamParameter { + external factory _LowStreamParameter({ + int width, + int height, + int? framerate, + int? bitrate, + }); +} + +@JS() +@anonymous +class _MicrophoneAudioTrackInitConfig { + external factory _MicrophoneAudioTrackInitConfig({ + _AudioEncoderConfiguration? encoderConfig, + bool? AEC, + bool? AGC, + bool? ANS, + bool? DTX, + String? microphoneId, + }); +} + +@JS() +class _NetworkQuality { + external int get uplinkNetworkQuality; + + external int get downlinkNetworkQuality; +} + +@JS() +class _RemoteAudioTrackStats { + external int get transportDelay; + + external String? get codecType; + + external int get end2EndDelay; + + external int get receiveBitrate; + + external int get receiveLevel; + + external int get receiveBytes; + + external int get receiveDelay; + + external int get receivePackets; + + external int get receivePacketsLost; + + external int get packetLossRate; + + external int get totalDuration; + + external int get totalFreezeTime; + + external int get freezeRate; + + external int get publishDuration; +} + +@JS() +class _RemoteVideoTrackStats { + external int get transportDelay; + + external String? get codecType; + + external int get end2EndDelay; + + external int get receiveBitrate; + + external int get receiveDelay; + + external int get receiveBytes; + + external int? get decodeFrameRate; + + external int? get receiveFrameRate; + + external int? get renderFrameRate; + + external int get receivePackets; + + external int get receivePacketsLost; + + external int get packetLossRate; + + external int get receiveResolutionHeight; + + external int get receiveResolutionWidth; + + external int get totalDuration; + + external int get totalFreezeTime; + + external int get freezeRate; + + external int get publishDuration; +} + +@JS() +@anonymous +class _RetryConfiguration { + external factory _RetryConfiguration({ + int timeout, + int timeoutFactor, + int maxRetryCount, + int maxRetryTimeout, + }); +} + +@JS() +@anonymous +class _ScreenVideoTrackInitConfig { + external factory _ScreenVideoTrackInitConfig({ + _VideoEncoderConfiguration? encoderConfig, + String? electronScreenSourceId, + String? extensionId, + String? screenSourceType, + String? optimizationMode, + _SVCConfiguration? scalabiltyMode, + }); +} + +@JS() +@anonymous +class _SVCConfiguration { + external factory _SVCConfiguration({ + int numSpatialLayers, + int numTemporalLayers, + }); +} + +@JS() +@anonymous +class _TurnServerConfig { + external factory _TurnServerConfig({ + String turnServerURL, + String password, + int? udpport, + String username, + bool? forceturn, + int? tcpport, + bool? security, + }); +} + +@JS() +@anonymous +class _VideoEncoderConfiguration { + external factory _VideoEncoderConfiguration({ + int? width, + int? height, + int? frameRate, + int? bitrateMin, + int? bitrateMax, + }); +} + +@JS() +@anonymous +class _VideoPlayerConfig { + external factory _VideoPlayerConfig({ + bool? mirror, + String? fit, + }); +} + +@JS() +class _Event { + external String get methodName; + + external List get data; +} + +/// A web implementation of the AgoraRtcEngine plugin. +class AgoraRtcEngineWeb { + // ignore: public_member_api_docs + static void registerWith(Registrar registrar) { + final methodChannel = MethodChannel( + 'agora_rtc_engine', + const StandardMethodCodec(), + registrar, + ); + final eventChannel = PluginEventChannel( + 'agora_rtc_engine/events', const StandardMethodCodec(), registrar); + + final pluginInstance = AgoraRtcEngineWeb(); + methodChannel.setMethodCallHandler(pluginInstance.handleMethodCall); + eventChannel.setController(pluginInstance._controller); + + ui.platformViewRegistry.registerViewFactory('AgoraSurfaceView', + (int viewId) { + var element = DivElement(); + MethodChannel('agora_rtc_engine/surface_view_$viewId', + const StandardMethodCodec(), registrar) + .setMethodCallHandler( + (call) => pluginInstance.handleViewMethodCall(call, element)); + return element; + }); + } + + final _controller = StreamController(); + String? _appId; + final bool _enableAudio = true; + final bool _enableVideo = false; + _AgoraRTCClient? _client; + late _MicrophoneAudioTrack _audioTrack; + late _CameraVideoTrack _videoTrack; + + /// Handles method calls over the MethodChannel of this plugin. + /// Note: Check the "federated" architecture for a new way of doing this: + /// https://flutter.dev/go/federated-plugins + Future handleMethodCall(MethodCall call) async { + var args = {}; + if (call.arguments != null) { + args = Map.from(call.arguments); + } + switch (call.method) { + default: + throw PlatformException(code: ErrorCode.NotSupported.toString()); + } + } + + // ignore: public_member_api_docs + Future handleViewMethodCall(MethodCall call, Element element) async { + var args = {}; + if (call.arguments != null) { + args = Map.from(call.arguments); + } + switch (call.method) { + case 'setData': + var data = Map.from(args['data']); + if (data['uid'] == 0) { + _videoTrack.play(element); + } else {} + break; + default: + throw PlatformException( + code: 'Unimplemented', + details: + 'agora_rtc_engine for web doesn\'t implement \'${call.method}\'', + ); + } + } + + String _getSdkVersion() { + return _AgoraRTC.VERSION; + } + + Future _create(Map arguments) async { + _appId = arguments['config']['appId']; + _AgoraRTC.setParameter( + 'REPORT_APP_SCENARIO', arguments['appType'].toString()); + _audioTrack = await promiseToFuture(_AgoraRTC.createMicrophoneAudioTrack( + _MicrophoneAudioTrackInitConfig())); + _videoTrack = await promiseToFuture( + _AgoraRTC.createCameraVideoTrack(_CameraVideoTrackInitConfig())); + } + + void _destroy() { + _client = null; + } + + Future _setChannelProfile(Map arguments) async { + String mode; + switch (ChannelProfileConverter.fromValue(arguments['profile']).e) { + case ChannelProfile.Communication: + mode = 'rtc'; + break; + case ChannelProfile.LiveBroadcasting: + mode = 'live'; + break; + case ChannelProfile.Game: + mode = ''; + break; + } + _client = _AgoraRTC.createClient(_ClientConfig(codec: 'h264', mode: mode)); + _client?.on('connection-state-change', + allowInterop((String curState, String revState, String? reason) { + final state = _ConnectionStateType.fromWeb(curState); + final _reason = _ConnectionChangedReason.fromWeb(reason, state); + _controller.add({ + 'methodName': 'ConnectionStateChanged', + 'data': [ + ConnectionStateTypeConverter(state).value(), + ConnectionChangedReasonConverter(_reason).value(), + ], + }); + })); + } + + Future _setClientRole(Map arguments) async { + String role; + switch (ClientRoleConverter.fromValue(arguments['role']).e) { + case ClientRole.Broadcaster: + role = 'host'; + break; + case ClientRole.Audience: + role = 'audience'; + break; + } + await _client?.setClientRole(role); + } + + Future _joinChannel(Map arguments) async { + if (_appId != null && _client != null) { + final channelName = arguments['channelName']; + final token = arguments['token']; + final optionalUid = arguments['optionalUid']; + print('_joinChannel $_appId $channelName $token $optionalUid'); + final promise = _client!.join(_appId!, channelName, token, optionalUid); + await promiseToFuture(promise).then((uid) { + _controller.add({ + 'methodName': 'JoinChannelSuccess', + 'data': [channelName, uid, 0], + }); + var tracks = <_LocalTrack>[]; + if (_enableAudio) tracks.add(_audioTrack); + if (_enableVideo) tracks.add(_videoTrack); + _client!.publish(tracks); + }); + } + } + + Future _leaveChannel(Map arguments) async { + if (_client != null) { + await promiseToFuture(_client!.leave()); + } + } + + Future _renewToken(Map arguments) async { + if (_client != null) { + final token = arguments['token']; + await promiseToFuture(_client!.renewToken(token)); + } + } + + Future _getConnectionState(Map arguments) async { + var state = ConnectionStateType.Disconnected; + if (_client != null) { + state = _ConnectionStateType.fromWeb(_client!.connectionState); + } + return ConnectionStateTypeConverter(state).value(); + } + + Future _setLogFilter(Map arguments) async { + if (_client != null) { + final filter = arguments['filter']; + _AgoraRTC.setLogLevel(LogFilterConverter(filter).e.toWeb()); + } + } +} + +extension _LogFilter on LogFilter { + static LogFilter fromWeb(int filter) { + switch (filter) { + case 0: + return LogFilter.Debug; + case 1: + return LogFilter.Info; + case 2: + return LogFilter.Warning; + case 3: + return LogFilter.Error; + case 4: + return LogFilter.Off; + default: + return LogFilter.Info; + } + } + + int toWeb() { + switch (this) { + case LogFilter.Off: + return 4; + case LogFilter.Debug: + return 0; + case LogFilter.Info: + return 1; + case LogFilter.Warning: + return 2; + case LogFilter.Error: + case LogFilter.Critical: + return 3; + } + } +} + +extension _ConnectionStateType on ConnectionStateType { + static ConnectionStateType fromWeb(String state) { + switch (state) { + case 'DISCONNECTED': + return ConnectionStateType.Disconnected; + case 'CONNECTING': + return ConnectionStateType.Connecting; + case 'RECONNECTING': + return ConnectionStateType.Reconnecting; + case 'CONNECTED': + return ConnectionStateType.Connected; + case 'DISCONNECTING': + return ConnectionStateType.Disconnected; + default: + return ConnectionStateType.Connecting; + } + } +} + +extension _ConnectionChangedReason on ConnectionChangedReason { + static ConnectionChangedReason fromWeb(String? reason, + [ConnectionStateType? state]) { + switch (reason) { + case 'LEAVE': + return ConnectionChangedReason.LeaveChannel; + case 'NETWORK_ERROR': + case 'SERVER_ERROR': + return ConnectionChangedReason.Interrupted; + case 'UID_BANNED': + return ConnectionChangedReason.RejectedByServer; + case 'IP_BANNED': + return ConnectionChangedReason.BannedByServer; + case 'CHANNEL_BANNED': + return ConnectionChangedReason.BannedByServer; + default: + if (state == ConnectionStateType.Connected) { + return ConnectionChangedReason.JoinSuccess; + } else { + return ConnectionChangedReason.JoinFailed; + } + } + } +} diff --git a/lib/rtc_engine.dart b/lib/rtc_engine.dart index 92a8c676c..2ea146134 100644 --- a/lib/rtc_engine.dart +++ b/lib/rtc_engine.dart @@ -4,4 +4,5 @@ export 'src/classes.dart'; export 'src/enums.dart'; export 'src/events.dart' hide RtcChannelEventHandler; export 'src/rtc_engine.dart' show RtcEngine; -export 'src/rtc_engine_extension.dart'; +export 'src/rtc_engine_extension.dart' + if (dart.library.html) 'src/rtc_engine_extension_web.dart'; diff --git a/lib/rtc_local_view.dart b/lib/rtc_local_view.dart index 2e8d367ca..fca3d0ba8 100644 --- a/lib/rtc_local_view.dart +++ b/lib/rtc_local_view.dart @@ -29,6 +29,23 @@ class SurfaceView extends RtcSurfaceView { onPlatformViewCreated: onPlatformViewCreated, gestureRecognizers: gestureRecognizers, ); + + /// TODO(doc) + SurfaceView.screenShare({ + Key? key, + renderMode = VideoRenderMode.Hidden, + mirrorMode = VideoMirrorMode.Disabled, + PlatformViewCreatedCallback? onPlatformViewCreated, + Set>? gestureRecognizers, + }) : super( + key: key, + uid: 0, + renderMode: renderMode, + mirrorMode: mirrorMode, + onPlatformViewCreated: onPlatformViewCreated, + gestureRecognizers: gestureRecognizers, + subProcess: true, + ); } /// TextureView. @@ -41,6 +58,7 @@ class TextureView extends RtcTextureView { mirrorMode = VideoMirrorMode.Auto, PlatformViewCreatedCallback? onPlatformViewCreated, Set>? gestureRecognizers, + useFlutterTexture = true, }) : super( key: key, uid: 0, @@ -49,5 +67,25 @@ class TextureView extends RtcTextureView { mirrorMode: mirrorMode, onPlatformViewCreated: onPlatformViewCreated, gestureRecognizers: gestureRecognizers, + useFlutterTexture: useFlutterTexture, + ); + + /// TODO(doc) + TextureView.screenShare({ + Key? key, + renderMode = VideoRenderMode.Hidden, + mirrorMode = VideoMirrorMode.Disabled, + PlatformViewCreatedCallback? onPlatformViewCreated, + Set>? gestureRecognizers, + useFlutterTexture = true, + }) : super( + key: key, + uid: 0, + renderMode: renderMode, + mirrorMode: mirrorMode, + onPlatformViewCreated: onPlatformViewCreated, + gestureRecognizers: gestureRecognizers, + useFlutterTexture: useFlutterTexture, + subProcess: true, ); } diff --git a/lib/rtc_remote_view.dart b/lib/rtc_remote_view.dart index 20190c922..0696c5a18 100644 --- a/lib/rtc_remote_view.dart +++ b/lib/rtc_remote_view.dart @@ -11,7 +11,7 @@ class SurfaceView extends RtcSurfaceView { SurfaceView({ Key? key, required int uid, - String? channelId, + required String channelId, renderMode = VideoRenderMode.Hidden, mirrorMode = VideoMirrorMode.Auto, zOrderOnTop = false, @@ -38,11 +38,12 @@ class TextureView extends RtcTextureView { TextureView({ Key? key, required int uid, - String? channelId, - renderMode = VideoRenderMode.Hidden, - mirrorMode = VideoMirrorMode.Auto, + required String channelId, + VideoRenderMode renderMode = VideoRenderMode.Hidden, + VideoMirrorMode mirrorMode = VideoMirrorMode.Auto, PlatformViewCreatedCallback? onPlatformViewCreated, Set>? gestureRecognizers, + useFlutterTexture = true, }) : assert(uid != 0), super( key: key, @@ -52,5 +53,6 @@ class TextureView extends RtcTextureView { mirrorMode: mirrorMode, onPlatformViewCreated: onPlatformViewCreated, gestureRecognizers: gestureRecognizers, + useFlutterTexture: useFlutterTexture, ); } diff --git a/lib/src/agora_media_recorder.dart b/lib/src/agora_media_recorder.dart new file mode 100644 index 000000000..41fbe521f --- /dev/null +++ b/lib/src/agora_media_recorder.dart @@ -0,0 +1,124 @@ +import 'package:agora_rtc_engine/rtc_engine.dart'; +import 'package:agora_rtc_engine/src/classes.dart'; + +typedef OnRecorderStateChanged = void Function( + RecorderState state, RecorderError error); + +typedef OnRecorderInfoUpdated = void Function(RecorderInfo info); + +class MediaRecorderCallback { + MediaRecorderCallback({ + this.onRecorderStateChanged, + this.onRecorderInfoUpdated, + }); + + /// Occurs when the recording state changes. + /// + /// When the local audio and video recording state changes, the SDK triggers this + /// callback to report the current recording state and the reason for the change. + /// + /// Parameters + /// - state The current recording state: + /// - RECORDER_STATE_ERROR(-1): An error occurs during the recording. See error message for the reason. + /// - RECORDER_STATE_START(2): The audio and video recording is started. + /// - RECORDER_STATE_STOP(3): The audio and video recording is stopped. + /// + /// - error The reason for the state change: + /// - RECORDER_ERROR_NONE(0): No error occurs. + /// - RECORDER_ERROR_WRITE_FAILED(1): The SDK fails to write the recorded data to a file. + /// - RECORDER_ERROR_NO_STREAM(2): The SDK does not detect audio and video streams + /// to be recorded, or audio and video streams are interrupted for more than five seconds during recording. + /// - RECORDER_ERROR_OVER_MAX_DURATION(3): The recording duration exceeds the upper limit. + /// - RECORDER_ERROR_CONFIG_CHANGED(4): The recording configuration changes. + /// - RECORDER_ERROR_CUSTOM_STREAM_DETECTED(5): The SDK detects audio and video + /// streams from users using versions of the SDK earlier than v3.0.0 in the COMMUNICATION channel profile. + OnRecorderStateChanged? onRecorderStateChanged; + + /// Occurs when the recording information is updated. + /// + /// After you successfully register this callback and enable the local audio and + /// video recording, the SDK periodically triggers the onRecorderInfoUpdated callback + /// based on the set value of recorderInfoUpdateInterval. This callback reports the filename, + /// duration, and size of the current recording file. + /// + /// Parameters + /// - info Information for the recording file. See RecorderInfo. + OnRecorderInfoUpdated? onRecorderInfoUpdated; +} + +abstract class AgoraMediaRecorder { + /// Gets the AgoraMediaRecorder object. + /// + /// Note + /// + /// Call this method after initializing the RtcEngine object. + /// + /// Parameters + /// - engine The RtcEngine object. See RtcEngine. + /// - callback The IMediaRecorderCallback instance. See IMediaRecorderCallback. + /// + /// Returns + /// + /// The AgoraMediaRecorder object. + AgoraMediaRecorder getMediaRecorder( + RtcEngine engine, + MediaRecorderCallback callback, + ); + + /// Starts recording the local audio and video. + /// + /// After successfully getting the object, you can call this method to enable + /// the recording of the local audio and video. + /// + /// This method can record the following content: + /// + /// The audio captured by the local microphone and encoded in AAC format. + /// The video captured by the local camera and encoded by the SDK. + /// The SDK can generate a recording file only when it detects the recordable + /// audio and video streams; when there are no audio and video streams to be recorded + /// or the audio and video streams are interrupted for more than five seconds, + /// the SDK stops recording and triggers the onRecorderStateChanged(RECORDER_STATE_ERROR, RECORDER_ERROR_NO_STREAM) callback. + /// + /// Note + /// + /// Call this method after joining the channel. + /// + /// Parameters + /// + /// - config The recording configurations. See MediaRecorderConfiguration. + /// + /// Returns + /// + /// - 0: Success. + /// - < 0: Failure: + /// - -2(ERR_INVALID_ARGUMENT): The parameter is invalid. Ensure the following: + /// - The specified path of the recording file exists and is writable. + /// - The specified format of the recording file is supported. + /// - The maximum recording duration is correctly set. + /// - -4(ERR_NOT_SUPPORTED): RtcEngine does not support the request due to one of the following reasons: + /// - The recording is ongoing. + /// - The recording stops because an error occurs. + /// - -7(ERR_NOT_INITIALIZED): This method is called before the initialization of + /// RtcEngine. Ensure that you have called getMediaRecorder before calling startRecording. + Future startRecording(MediaRecorderConfiguration config); + + /// Stops recording the local audio and video. + /// + /// Note + /// + /// Call this method after calling startRecording. + /// + /// Returns + /// - 0: Success. + /// - < 0: Failure: + /// - -7(ERR_NOT_INITIALIZED): This method is called before the initialization of RtcEngine. + /// Ensure that you have called getMediaRecorder before calling startRecording. + Future stopRecording(); + + /// Releases the AgoraMediaRecorder object. + /// + /// This method releases the RtcEngine object and all other resources used by the + /// AgoraMediaRecorder object. After calling this method, if you want to enable + /// the recording again, you must call getMediaRecorder to get the AgoraMediaRecorder object. + Future release(); +} diff --git a/lib/src/api_types.dart b/lib/src/api_types.dart new file mode 100644 index 000000000..b2b3e95da --- /dev/null +++ b/lib/src/api_types.dart @@ -0,0 +1,256 @@ +// ignore_for_file: public_member_api_docs + +/// Internal used purpose +enum ApiTypeEngine { + kEngineInitialize, + kEngineRelease, + kEngineSetChannelProfile, + kEngineSetClientRole, + kEngineJoinChannel, + kEngineSwitchChannel, + kEngineLeaveChannel, + kEngineRenewToken, + kEngineRegisterLocalUserAccount, + kEngineJoinChannelWithUserAccount, + kEngineGetUserInfoByUserAccount, + kEngineGetUserInfoByUid, + kEngineStartEchoTest, + kEngineStopEchoTest, + kEngineSetCloudProxy, + kEngineEnableVideo, + kEngineDisableVideo, + kEngineSetVideoProfile, + kEngineSetVideoEncoderConfiguration, + kEngineSetCameraCapturerConfiguration, + kEngineSetupLocalVideo, + kEngineSetupRemoteVideo, + kEngineStartPreview, + kEngineSetRemoteUserPriority, + kEngineStopPreview, + kEngineEnableAudio, + kEngineEnableLocalAudio, + kEngineDisableAudio, + kEngineSetAudioProfile, + kEngineMuteLocalAudioStream, + kEngineMuteAllRemoteAudioStreams, + kEngineSetDefaultMuteAllRemoteAudioStreams, + kEngineAdjustUserPlaybackSignalVolume, + kEngineMuteRemoteAudioStream, + kEngineMuteLocalVideoStream, + kEngineEnableLocalVideo, + kEngineMuteAllRemoteVideoStreams, + kEngineSetDefaultMuteAllRemoteVideoStreams, + kEngineMuteRemoteVideoStream, + kEngineSetRemoteVideoStreamType, + kEngineSetRemoteDefaultVideoStreamType, + kEngineEnableAudioVolumeIndication, + kEngineStartAudioRecording, + kEngineStopAudioRecording, + kEngineStartAudioMixing, + kEngineStopAudioMixing, + kEnginePauseAudioMixing, + kEngineResumeAudioMixing, + kEngineSetHighQualityAudioParameters, + kEngineAdjustAudioMixingVolume, + kEngineAdjustAudioMixingPlayoutVolume, + kEngineGetAudioMixingPlayoutVolume, + kEngineAdjustAudioMixingPublishVolume, + kEngineGetAudioMixingPublishVolume, + kEngineGetAudioMixingDuration, + kEngineGetAudioMixingCurrentPosition, + kEngineSetAudioMixingPosition, + kEngineSetAudioMixingPitch, + kEngineGetEffectsVolume, + kEngineSetEffectsVolume, + kEngineSetVolumeOfEffect, + kEngineEnableFaceDetection, + kEnginePlayEffect, + kEngineStopEffect, + kEngineStopAllEffects, + kEnginePreloadEffect, + kEngineUnloadEffect, + kEnginePauseEffect, + kEnginePauseAllEffects, + kEngineResumeEffect, + kEngineResumeAllEffects, + kEngineGetEffectDuration, + kEngineSetEffectPosition, + kEngineGetEffectCurrentPosition, + kEngineEnableDeepLearningDenoise, + kEngineEnableSoundPositionIndication, + kEngineSetRemoteVoicePosition, + kEngineSetLocalVoicePitch, + kEngineSetLocalVoiceEqualization, + kEngineSetLocalVoiceReverb, + kEngineSetLocalVoiceChanger, + kEngineSetLocalVoiceReverbPreset, + kEngineSetVoiceBeautifierPreset, + kEngineSetAudioEffectPreset, + kEngineSetVoiceConversionPreset, + kEngineSetAudioEffectParameters, + kEngineSetVoiceBeautifierParameters, + kEngineSetLogFile, + kEngineSetLogFilter, + kEngineSetLogFileSize, + kEngineUploadLogFile, + kEngineSetLocalRenderMode, + kEngineSetRemoteRenderMode, + kEngineSetLocalVideoMirrorMode, + kEngineEnableDualStreamMode, + kEngineSetExternalAudioSource, + kEngineSetExternalAudioSink, + kEngineSetRecordingAudioFrameParameters, + kEngineSetPlaybackAudioFrameParameters, + kEngineSetMixedAudioFrameParameters, + kEngineAdjustRecordingSignalVolume, + kEngineAdjustPlaybackSignalVolume, + kEngineAdjustLoopBackRecordingSignalVolume, + kEngineEnableWebSdkInteroperability, + kEngineSetVideoQualityParameters, + kEngineSetLocalPublishFallbackOption, + kEngineSetRemoteSubscribeFallbackOption, + kEngineSwitchCamera, + kEngineSetDefaultAudioRouteToSpeakerPhone, + kEngineSetEnableSpeakerPhone, + kEngineEnableInEarMonitoring, + kEngineSetInEarMonitoringVolume, + kEngineIsSpeakerPhoneEnabled, + kEngineSetAudioSessionOperationRestriction, + kEngineEnableLoopBackRecording, + kEngineStartScreenCaptureByDisplayId, + kEngineStartScreenCaptureByScreenRect, + kEngineStartScreenCaptureByWindowId, + kEngineSetScreenCaptureContentHint, + kEngineUpdateScreenCaptureParameters, + kEngineUpdateScreenCaptureRegion, + kEngineStopScreenCapture, + kEngineStartScreenCapture, + kEngineSetVideoSource, + kEngineGetCallId, + kEngineRate, + kEngineComplain, + kEngineGetVersion, + kEngineEnableLastMileTest, + kEngineDisableLastMileTest, + kEngineStartLastMileProbeTest, + kEngineStopLastMileProbeTest, + kEngineGetErrorDescription, + kEngineSetEncryptionSecret, + kEngineSetEncryptionMode, + kEngineEnableEncryption, + kEngineRegisterPacketObserver, + kEngineCreateDataStream, + kEngineSendStreamMessage, + kEngineAddPublishStreamUrl, + kEngineRemovePublishStreamUrl, + kEngineSetLiveTranscoding, + kEngineAddVideoWaterMark, + kEngineClearVideoWaterMarks, + kEngineSetBeautyEffectOptions, + kEngineEnableVirtualBackground, + kEngineAddInjectStreamUrl, + kEngineStartChannelMediaRelay, + kEngineUpdateChannelMediaRelay, + kEnginePauseAllChannelMediaRelay, + kEngineResumeAllChannelMediaRelay, + kEngineStopChannelMediaRelay, + kEngineRemoveInjectStreamUrl, + kEngineSendCustomReportMessage, + kEngineGetConnectionState, + kEngineEnableRemoteSuperResolution, + kEngineRegisterMediaMetadataObserver, + kEngineSetParameters, + kEngineSetLocalAccessPoint, + + kEngineUnRegisterMediaMetadataObserver, + kEngineSetMaxMetadataSize, + kEngineSendMetadata, + kEngineSetAppType, + + kMediaPushAudioFrame, + kMediaPullAudioFrame, + kMediaSetExternalVideoSource, + kMediaPushVideoFrame, + + kEngineSetAudioMixingPlaybackSpeed, + kEngineSelectAudioTrack, + kEngineGetAudioTrackCount, + kEngineSetAudioMixingDualMonoMode, + kEngineGetAudioFileInfo, + kEngineSetVideoProfileEx, + kMediaSetExternalAudioSourceVolume, + kEngineSetLogWriter, + kEngineReleaseLogWriter, + kEngineSetLocalVideoRenderer, + kEngineSetRemoteVideoRenderer, + kEngineSetCameraTorchOn, + kEngineIsCameraTorchSupported, + + kEngineGetCameraMaxZoomFactor, + kEngineIsCameraAutoFocusFaceModeSupported, + kEngineIsCameraExposurePositionSupported, + kEngineIsCameraFocusSupported, + kEngineIsCameraZoomSupported, + kEngineSetCameraAutoFocusFaceModeEnabled, + kEngineSetCameraExposurePosition, + kEngineSetCameraFocusPositionInPreview, + kEngineSetCameraZoomFactor, + kEngineStartRhythmPlayer, + kEngineStopRhythmPlayer, + kEngineConfigRhythmPlayer, + kEngineGetNativeHandle, + + kEngineGetScreenCaptureSources, + kEngineTakeSnapshot, + kEngineEnableContentInspect, +} + +enum ApiTypeChannel { + kChannelCreateChannel, + kChannelRelease, + kChannelJoinChannel, + kChannelJoinChannelWithUserAccount, + kChannelLeaveChannel, + kChannelPublish, + kChannelUnPublish, + kChannelChannelId, + kChannelGetCallId, + kChannelRenewToken, + kChannelSetEncryptionSecret, + kChannelSetEncryptionMode, + kChannelEnableEncryption, + kChannelRegisterPacketObserver, + kChannelRegisterMediaMetadataObserver, + kChannelUnRegisterMediaMetadataObserver, + kChannelSetMaxMetadataSize, + kChannelSendMetadata, + kChannelSetClientRole, + kChannelSetRemoteUserPriority, + kChannelSetRemoteVoicePosition, + kChannelSetRemoteRenderMode, + kChannelSetDefaultMuteAllRemoteAudioStreams, + kChannelSetDefaultMuteAllRemoteVideoStreams, + kChannelMuteLocalAudioStream, + kChannelMuteLocalVideoStream, + kChannelMuteAllRemoteAudioStreams, + kChannelAdjustUserPlaybackSignalVolume, + kChannelMuteRemoteAudioStream, + kChannelMuteAllRemoteVideoStreams, + kChannelMuteRemoteVideoStream, + kChannelSetRemoteVideoStreamType, + kChannelSetRemoteDefaultVideoStreamType, + kChannelCreateDataStream, + kChannelSendStreamMessage, + kChannelAddPublishStreamUrl, + kChannelRemovePublishStreamUrl, + kChannelSetLiveTranscoding, + kChannelAddInjectStreamUrl, + kChannelRemoveInjectStreamUrl, + kChannelStartChannelMediaRelay, + kChannelUpdateChannelMediaRelay, + kChannelPauseAllChannelMediaRelay, + kChannelResumeAllChannelMediaRelay, + kChannelStopChannelMediaRelay, + kChannelGetConnectionState, + kChannelEnableRemoteSuperResolution, +} diff --git a/lib/src/classes.dart b/lib/src/classes.dart index 684802944..c3f4617f8 100644 --- a/lib/src/classes.dart +++ b/lib/src/classes.dart @@ -1,3 +1,4 @@ +import 'dart:typed_data'; import 'dart:ui' show Color; import 'package:agora_rtc_engine/src/enum_converter.dart'; @@ -19,13 +20,20 @@ Map? _$ColorToJson(Color? instance) => instance != null } : null; -/// The UserInfo class. +/// +/// The information of the user. +/// +/// @JsonSerializable(explicitToJson: true) class UserInfo { - /// The user ID. + /// + /// User ID + /// int uid; + /// /// The user account. + /// String userAccount; /// Constructs a [UserInfo] @@ -42,15 +50,25 @@ class UserInfo { Map toJson() => _$UserInfoToJson(this); } -/// The video resolution. +/// +/// Video dimensions. +/// +/// @JsonSerializable(explicitToJson: true) class VideoDimensions { - /// The video resolution on the horizontal axis. @JsonKey(includeIfNull: false) + + /// + /// The width (pixels) of the video. + /// + /// int? width; - /// The video resolution on the vertical axis. @JsonKey(includeIfNull: false) + + /// + /// The height (pixels) of the video. + /// int? height; /// Constructs a [VideoDimensions] @@ -67,106 +85,67 @@ class VideoDimensions { Map toJson() => _$VideoDimensionsToJson(this); } -/// Definition of VideoEncoderConfiguration. +/// +/// Video encoder configurations. +/// +/// @JsonSerializable(explicitToJson: true) class VideoEncoderConfiguration { - /// The video frame dimensions (px), which is used to specify the video quality and measured by the total number of pixels along a frame's width and height. The default value is 640 × 360. - /// You can customize the dimension, or select from the following list: - /// - 120x120 - /// - 160x120 - /// - 180x180 - /// - 240x180 - /// - 320x180 - /// - 240x240 - /// - 320x240 - /// - 424x240 - /// - 360x360 - /// - 480x360 - /// - 640x360 - /// - 480x480 - /// - 640x480 - /// - 840x480 - /// - 960x720 - /// - 1280x720 - /// - /// **Note** - /// - The value of the dimension does not indicate the orientation mode of the output ratio. For how to set the video orientation, see [VideoOutputOrientationMode]. - /// - Whether 720p+ can be supported depends on the device. If the device cannot support 720p, the frame rate will be lower than the one listed in the table. @JsonKey(includeIfNull: false) + + /// + /// The dimensions of the encoded video (px). See VideoDimensions. This parameter measures the video encoding quality in the format of length × width. The default value is 640 × 360. You can set a custom value. + /// + /// VideoDimensions? dimensions; - /// The video frame rate (fps). The default value is 15. You can either set the frame rate manually or choose from [VideoFrameRate]. We do not recommend setting this to a value greater than 30. @JsonKey(includeIfNull: false) + + /// + /// The encoding frame rate (fps) of the video. See VideoFrameRate. The default value is 15. + /// + /// VideoFrameRate? frameRate; - /// The minimum video encoder frame rate (fps). The default value is [VideoFrameRate.Min] (the SDK uses the lowest encoder frame rate). @JsonKey(includeIfNull: false) VideoFrameRate? minFrameRate; - /// Bitrate of the video (Kbps). Refer to the table below and set your bitrate. If you set a bitrate beyond the proper range, the SDK automatically adjusts it to a value within the range. - /// - /// You can also choose from the following options: - /// - [BitRate.Standard]: (Recommended) The standard bitrate mode. In this mode, the bitrates differ between the LiveBroadcasting and Communication profiles: - /// - In the Communication profile, the video bitrate is the same as the base bitrate. - /// - In the LiveBroadcasting profile, the video bitrate is twice the base bitrate. - /// - [BitRate.Compatible]: The compatible bitrate mode. In this mode, the bitrate stays the same regardless of the profile. If you choose this mode for the Live Broadcast profile, the video frame rate may be lower than the set value. - /// - /// Agora uses different video codecs for different profiles to optimize the user experience. For example, the Communication profile prioritizes the smoothness while the Live Broadcast profile prioritizes the video quality (a higher bitrate). Therefore, We recommend setting this parameter as `0`. - /// - /// **Video Bitrate Table** - /// - /// | Resolution | Frame Rate (fps) | Base Bitrate (Kbps) | Live Bitrate (Kbps) | - /// |------------------------|------------------|----------------------------------------|----------------------------------------| - /// | 160 * 120 | 15 | 65 | 130 | - /// | 120 * 120 | 15 | 50 | 100 | - /// | 320 * 180 | 15 | 140 | 280 | - /// | 180 * 180 | 15 | 100 | 200 | - /// | 240 * 180 | 15 | 120 | 240 | - /// | 320 * 240 | 15 | 200 | 400 | - /// | 240 * 240 | 15 | 140 | 280 | - /// | 424 * 240 | 15 | 220 | 440 | - /// | 640 * 360 | 15 | 400 | 800 | - /// | 360 * 360 | 15 | 260 | 520 | - /// | 640 * 360 | 30 | 600 | 1200 | - /// | 360 * 360 | 30 | 400 | 800 | - /// | 480 * 360 | 15 | 320 | 640 | - /// | 480 * 360 | 30 | 490 | 980 | - /// | 640 * 480 | 15 | 500 | 1000 | - /// | 480 * 480 | 15 | 400 | 800 | - /// | 640 * 480 | 30 | 750 | 1500 | - /// | 480 * 480 | 30 | 600 | 1200 | - /// | 848 * 480 | 15 | 610 | 1220 | - /// | 848 * 480 | 30 | 930 | 1860 | - /// | 640 * 480 | 10 | 400 | 800 | - /// | 1280 * 720 | 15 | 1130 | 2260 | - /// | 1280 * 720 | 30 | 1710 | 3420 | - /// | 960 * 720 | 15 | 910 | 1820 | - /// | 960 * 720 | 30 | 1380 | 2760 | - /// - /// **Note** - /// - The base bitrate in this table applies to the Communication profile. - /// - The LiveBroadcasting profile generally requires a higher bitrate for better video quality. We recommend setting the bitrate mode as `0`. You can also set the bitrate as the base bitrate value x 2. @JsonKey(includeIfNull: false) + + /// + /// The encoding bitrate (Kbps) of the video. + /// + /// int? bitrate; - /// The minimum encoding bitrate (Kbps). The Agora SDK automatically adjusts the encoding bitrate to adapt to the network conditions. Using a value greater than the default value forces the video encoder to output high-quality images but may cause more packet loss and hence sacrifice the smoothness of the video transmission. That said, unless you have special requirements for image quality, Agora does not recommend changing this value. @JsonKey(includeIfNull: false) + + /// + /// The minimum encoding bitrate (Kbps) of the video. + /// The SDK automatically adjusts the encoding bitrate to adapt to the network conditions. Using a value greater than the default value forces the video encoder to output high-quality images but may cause more packet loss and sacrifice the smoothness of the video transmission. Unless you have special requirements for image quality, Agora does not recommend changing this value. + /// This parameter only applies to the Live-broadcasting profile. + /// + /// int? minBitrate; - /// The orientation mode. - /// See [VideoOutputOrientationMode]. @JsonKey(includeIfNull: false) + + /// + /// The orientation mode of the encoded video. See VideoOutputOrientationMode. + /// VideoOutputOrientationMode? orientationMode; - /// The video encoding degradation preference under limited bandwidth: - /// See [DegradationPreference]. @JsonKey(includeIfNull: false) DegradationPreference? degradationPrefer; - /// Sets the mirror mode of the published local video stream. - /// This member only affects the video that the remote user sees. - /// See [VideoMirrorMode]. @JsonKey(includeIfNull: false) + + /// + /// Whether to mirror the video when encoding the video. It only affects the video that the + /// remote user sees. + /// By default, the video is not mirrored. + /// + /// VideoMirrorMode? mirrorMode; /// Constructs a [VideoEncoderConfiguration] @@ -189,23 +168,38 @@ class VideoEncoderConfiguration { Map toJson() => _$VideoEncoderConfigurationToJson(this); } -/// Sets the image enhancement options. +/// +/// Image enhancement options. +/// +/// @JsonSerializable(explicitToJson: true) class BeautyOptions { - /// The lightening contrast level, used with [lighteningLevel]. @JsonKey(includeIfNull: false) + + /// + /// The contrast level. For details, see LighteningContrastLevel. + /// LighteningContrastLevel? lighteningContrastLevel; - /// The brightness level. The value ranges between 0.0 (original) and 1.0. The default value is 0.7. @JsonKey(includeIfNull: false) + + /// + /// The brightness level. The value ranges from 0.0 (original) to 1.0. The default value is + /// double? lighteningLevel; - /// The sharpness level. The value ranges between 0.0 (original) and 1.0. The default value is 0.5. This parameter is usually used to remove blemishes. @JsonKey(includeIfNull: false) + + /// + /// The smoothness level. The value ranges from 0.0 (original) to 1.0. The default value is + /// double? smoothnessLevel; - /// The redness level. The value ranges between 0.0 (original) and 1.0. The default value is 0.1. This parameter adjusts the red saturation level. @JsonKey(includeIfNull: false) + + /// + /// The redness level. The value ranges from 0.0 (original) to 1.0. The default value is + /// double? rednessLevel; /// Constructs a [BeautyOptions] @@ -224,24 +218,37 @@ class BeautyOptions { Map toJson() => _$BeautyOptionsToJson(this); } -/// Agora image properties. A class for setting the properties of the watermark and background images. +/// +/// Image properties. +/// This class sets the properties of the watermark and background images in the live video. +/// +/// +/// The x coordinate (pixel) of the image on the video frame (taking the upper left corner of the video frame as the origin). +/// @JsonSerializable(explicitToJson: true) class AgoraImage { - /// HTTP/HTTPS URL address of the image on the broadcasting video. The maximum length of this parameter is 1024 bytes. + /// + /// + /// The y coordinate (pixel) of the image on the video frame (taking the upper left corner of the video frame as the origin). + /// + /// The HTTP/HTTPS URL address of the image in the live video. The maximum length of this parameter is 1024 bytes. + /// String url; - /// Position of the image on the upper left of the broadcasting video on the horizontal axis. @JsonKey(includeIfNull: false) int? x; - /// Position of the image on the upper left of the broadcasting video on the vertical axis. @JsonKey(includeIfNull: false) int? y; - /// Width of the image on the broadcasting video. + /// + /// The width (pixel) of the image on the video frame. + /// int? width; - /// Height of the image on the broadcasting video. + /// + /// The height (pixel) of the image on the video frame. + /// int? height; /// Constructs a [AgoraImage] @@ -261,45 +268,94 @@ class AgoraImage { Map toJson() => _$AgoraImageToJson(this); } -/// The transcodingUser class, which defines the audio and video properties in the CDN live. Agora supports a maximum of 17 transcoding users in a CDN live streaming channel. +/// +/// Transcoding configurations of each host. +/// +/// +/// +/// +/// The width (pixel) of the host's video. +/// +/// The x coordinate (pixel) of the host's video on the output video frame (taking the upper left corner of the video frame as the origin). The value range is [0, width], where width is the LiveTranscodingwidth set in . +/// @JsonSerializable(explicitToJson: true) class TranscodingUser { - /// ID of the user in the CDN live streaming. + /// + /// The user ID of the host. + /// + /// int uid; - /// Horizontal position of the video frame of the user from the top left corner of the CDN live streaming. + /// + /// + /// The height (pixel) of the host's video. + /// + /// + /// The y coordinate (pixel) of the host's video on the output video frame (taking the upper left corner of the video frame as the origin). The value range is [0, height], where height is the LiveTranscodingheight set in . + /// @JsonKey(includeIfNull: false) int? x; - /// Vertical position of the video frame of the user from the top left corner of the CDN live streaming. @JsonKey(includeIfNull: false) int? y; - /// Width of the video frame of the user on the CDN live streaming. The default value is 360. @JsonKey(includeIfNull: false) int? width; - /// Height of the video frame of the user on the CDN live streaming. The default value is 640. @JsonKey(includeIfNull: false) int? height; - /// The layer index of the video frame. An integer. The value range is [0,100]. - /// - 0: (Default) Bottom layer. - /// - 100: Top layer. - /// - /// **Note**: If the value is set lower than 0 or higher than 100, the [ErrorCode.InvalidArgument] error is reported. @JsonKey(includeIfNull: false) + + /// + /// The layer index number of the host's video. The value range is [0, 100]. + /// 0: (Default) The host's video is the bottom layer. + /// 100: The host's video is the top layer. + /// + /// + /// + /// + /// If the value is beyond this range, the SDK reports the error code ERR_INVALID_ARGUMENT. + /// As of v2.3, the SDK supports setting zOrder to 0. + /// + /// + /// + /// int? zOrder; - /// The transparency of the video frame of the user in the CDN live stream that ranges between 0.0 and 1.0. 0.0 means that the video frame is completely transparent and 1.0 means opaque. The default value is 1.0. @JsonKey(includeIfNull: false) - double? alpha; - /// The audio channel ranging between 0 and 5. The default value is 0. - /// See [AudioChannel]. /// - /// **Note** Special players are needed if `audioChannel` is not set as 0. + /// The transparency of the host's video. The value range is [0.0, 1.0]. + /// 0.0: Completely transparent. + /// 1.0: (Default) Opaque. + /// + /// + /// + /// + double? alpha; + @JsonKey(includeIfNull: false) + + /// + /// The audio channel used by the host's audio in the output audio. The default value is 0, and the value range is [0, 5]. + /// 0: (Recommended) The defaut setting, which supports dual channels at most and depends on the upstream of the host. + /// 1: The host's audio uses the FL audio channel. If the host's upstream uses multiple audio channels, the Agora + /// server mixes them into mono first. + /// 2: The host's audio uses the FC audio channel. If the host's upstream uses multiple audio channels, the Agora + /// server mixes them into mono first. + /// 3: The host's audio uses the FR audio channel. If the host's upstream uses multiple audio channels, the Agora + /// server mixes them into mono first. + /// 4: The host's audio uses the BL audio channel. If the host's upstream uses multiple audio channels, the Agora + /// server mixes them into mono first. + /// 5: The host's audio uses the BR audio channel. If the host's upstream uses multiple audio channels, the Agora + /// server mixes them into mono first. + /// 0xFF or a value greater than 5: The host's audio is muted, and the Agora + /// server removes the host's audio. + /// + /// If the value is not 0, a special player is required. + /// + /// AudioChannel? audioChannel; /// Constructs a [TranscodingUser] @@ -322,81 +378,130 @@ class TranscodingUser { Map toJson() => _$TranscodingUserToJson(this); } -/// A class for managing user-specific CDN live audio/video transcoding settings. +/// +/// Transcoding configurations for CDN live streaming. +/// +/// @JsonSerializable(explicitToJson: true) class LiveTranscoding { - /// Width (pixel) of the video. The default value is 360. - /// - When pushing video streams to the CDN, ensure that `width` is at least 64; otherwise, the Agora server adjusts the value to 64. - /// - When pushing audio streams to the CDN, set `width` and `height` as 0. @JsonKey(includeIfNull: false) int? width; - /// Height (pixel) of the video. The default value is 640. - /// - When pushing video streams to the CDN, ensure that `height` is at least 64; otherwise, the Agora server adjusts the value to 64. - /// - When pushing audio streams to the CDN, set `width` and `height` as 0. @JsonKey(includeIfNull: false) int? height; - /// Bitrate (Kbps) of the CDN live output video stream. The default value is 400. Set this parameter according to the [VideoEncoderConfiguration.bitrate](Video Bitrate Table). If you set a bitrate beyond the proper range, the SDK automatically adapts it to a value within the range. @JsonKey(includeIfNull: false) + + /// + /// The video bitrate (Kbps) of the output media stream. The default value is 400. + /// int? videoBitrate; - /// The frame rate (fps) of the video. The value range is (0, 30]. The default value is 15. The Agora server adjusts any value over 30 to 30. @JsonKey(includeIfNull: false) VideoFrameRate? videoFramerate; - /// Agora does not recommend using this parameter. - /// - `true`: Low latency with unassured quality. - /// - `false`: (Default) High latency with assured quality. @deprecated @JsonKey(includeIfNull: false) + + /// + /// + /// + /// Deprecated + /// This attribute is deprecated since v2.8.0, and Agora does not recommend it. + /// + /// + /// + /// true: Low latency with unassured quality. + /// false: (Default) High latency with assured quality. + /// + /// + /// bool? lowLatency; - /// Gop of the video frames in the CDN live stream. The default value is 30 fps. @JsonKey(includeIfNull: false) + + /// + /// The video GOP (Group of Pictures) of the output media stream. The default value is 30. + /// int? videoGop; - /// The watermark image added to the CDN live publishing stream. Ensure that the format of the image is PNG. Once a watermark image is added, the audience of the CDN live publishing stream can see it. - /// See [AgoraImage]. @JsonKey(includeIfNull: false) + + /// + /// The video watermark of the output media stream. Ensure that the format of the watermark image is PNG. For details, see AgoraImage. + /// AgoraImage? watermark; - /// The background image added to the CDN live publishing stream. Once a background image is added, the audience of the CDN live publishing stream can see it. - /// See [AgoraImage]. @JsonKey(includeIfNull: false) + + /// + /// The video background image of the output media stream. For details, see AgoraImage. + /// AgoraImage? backgroundImage; - /// Self-defined audio-sample rate: [AudioSampleRateType]. @JsonKey(includeIfNull: false) + + /// + /// The audio sampling rate (Hz) of the output media stream. See AudioSampleRateType. + /// AudioSampleRateType? audioSampleRate; - /// Bitrate (Kbps) of the CDN live audio output stream. The default value is 48 and the highest value is 128. @JsonKey(includeIfNull: false) + + /// + /// The audio bitrate (Kbps) of the output media stream. The default value is 48, and the maximum is 128. + /// int? audioBitrate; - /// Agora’s self-defined audio channel type. Agora recommends choosing 1 (mono), or 2 (stereo) audio channels. Special players are required if you choose 3, 4, or 5. - /// See [AudioChannel]. @JsonKey(includeIfNull: false) + + /// + /// The number of audio channels of the output media stream. The default value is 1. Agora recommends setting it to 1 or 2. + /// 1: (Default) Mono + /// 2: Stereo. + /// 3: Three audio channels. + /// 4: Four audio channels. + /// 5: Five audio channels. + /// + /// + /// AudioChannel? audioChannels; - /// Audio codec profile type: [AudioCodecProfileType]. Set it as `LCAAC` or `HEAAC`. The default value is `LCAAC`. @JsonKey(includeIfNull: false) + + /// + /// The audio codec of the output media stream. For details, see AudioCodecProfileType. + /// AudioCodecProfileType? audioCodecProfile; - /// Video codec profile type: [VideoCodecProfileType]. Set it as `BASELINE`, `MAIN`, or `HIGH` (default). If you set this parameter to other values, Agora adjusts it to the default value `HIGH`. @JsonKey(includeIfNull: false) + + /// + /// The video encoding configuration of the output media stream. See VideoCodecProfileType. + /// If you set this parameter to any other value, Agora adjusts it to the default value. + /// + /// VideoCodecProfileType? videoCodecProfile; - /// The background color in RGB hex. Value only. Do not include a preceding #. For example, 0xFFB6C1 (light pink). The default value is 0x000000 (black). @JsonKey( includeIfNull: false, fromJson: _$ColorFromJson, toJson: _$ColorToJson) + + /// + /// The video background color of the output media stream. The format is a hexadecimal integer defined by RGB without the # symbol. For example, 0xFFB6C1 + /// means light pink. The default value is 0x000000 (black). + /// Color? backgroundColor; - /// Reserved property. Extra user-defined information to send the Supplemental Enhancement Information (SEI) for the H.264/H.265 video stream to the CDN live client. Maximum length: 4096 Bytes. + @JsonKey(includeIfNull: false) + VideoCodecTypeForStream? videoCodecType; + @JsonKey(includeIfNull: false) String? userConfigExtraInfo; - /// An TranscodingUser object managing the user layout configuration in the CDN live stream. Agora supports a maximum of 17 transcoding users in a CDN live stream channel. + /// + /// Transcoding configurations of each host. One live streaming channel supports up to 17 hosts. For details, see TranscodingUser. + /// + /// List transcodingUsers; /// Constructs a [LiveTranscoding] @@ -416,6 +521,7 @@ class LiveTranscoding { this.audioCodecProfile, this.videoCodecProfile, this.backgroundColor, + this.videoCodecType, this.userConfigExtraInfo, }); @@ -427,17 +533,27 @@ class LiveTranscoding { Map toJson() => _$LiveTranscodingToJson(this); } -/// The ChannelMediaInfo class. +/// +/// The definition of ChannelMediaInfo. +/// +/// @JsonSerializable(explicitToJson: true) class ChannelMediaInfo { - /// The channel name. + /// + /// The name of the channel. + /// String channelName; - /// The token that enables the user to join the channel. @JsonKey(includeIfNull: false) + + /// + /// The token that enables the user to join the channel. + /// String? token; - /// The user ID. + /// + /// User ID. + /// int uid; /// Constructs a [ChannelMediaInfo] @@ -455,24 +571,38 @@ class ChannelMediaInfo { Map toJson() => _$ChannelMediaInfoToJson(this); } -/// The ChannelMediaRelayConfiguration class. +/// +/// The definition of ChannelMediaRelayConfiguration. +/// +/// @JsonSerializable(explicitToJson: true) class ChannelMediaRelayConfiguration { - /// The information of the source channel: [ChannelMediaInfo]. It contains the following members: - /// - `channelName`: The name of the source channel. The default value is NULL, which means the SDK applies the name of the current channel. - /// - `uid`: ID of the broadcaster whose media stream you want to relay. The default value is 0, which means the SDK generates a random UID. You must set it as 0. - /// - `token`: The token for joining the source channel. It is generated with the `channelName` and `uid` you set in `srcInfo`. - /// - If you have not enabled the App Certificate, set this parameter as the default value NULL, which means the SDK applies the App ID. - /// - If you have enabled the App Certificate, you must use the token generated with the `channelName` and `uid`. + /// + /// The information of the source channel ChannelMediaInfo. It contains the following members: + /// channelName: The name of the source channel. The default value is , which means the SDK applies the name of the current channel.null + /// uid: The unique ID to identify the relay stream in the source channel. The default value is 0, which means the SDK generates a random UID. You must set it as 0. + /// token: The token for joining the source channel. It is generated with the channelName and uid you set in srcInfo. + /// If you have not enabled the App Certificate, set this parameter as the default value null , which means the SDK applies the App ID. + /// If you have enabled the App Certificate, you must use the token generated with the channelName and uid, and the uid must be set as 0. + /// + /// + /// + /// + /// ChannelMediaInfo srcInfo; - /// The information of the destination channel: [ChannelMediaInfo]. It contains the following members: - ///- `channelName`: The name of the destination channel. - ///- `uid`: ID of the broadcaster in the destination channel. The value ranges from 0 to (232-1). To avoid UID conflicts, - /// this uid must be different from any other UIDs in the destination channel. The default value is 0, which means the SDK generates a random UID. - /// - `token`: The token for joining the destination channel. It is generated with the `channelName` and `uid` you set in `destInfo`. - /// - If you have not enabled the App Certificate, set this parameter as the default value NULL, which means the SDK applies the App ID. - /// - If you have enabled the App Certificate, you must use the token generated with the `channelName` and `uid`. + /// + /// The information of the destination channel ChannelMediaInfo. It contains the following members: + /// channelName: The name of the destination channel. + /// uid: The unique ID to identify the relay stream in the destination channel. The value ranges from 0 to (232-1). To avoid UID conflicts, this `UID` must be different from any other `UID` in the destination channel. The default value is 0, which means the SDK generates a random `UID`. Do not set this parameter as the `UID` of the host in the destination channel, and ensure that this `UID` is different from any other `UID` in the channel. + /// token: The token for joining the destination channel. It is generated with the channelName and uid you set in destInfos. + /// If you have not enabled the App Certificate, set this parameter as the default value null , which means the SDK applies the App ID. + /// If you have enabled the App Certificate, you must use the token generated with the channelName and uid. + /// + /// + /// + /// + /// List destInfos; /// Constructs a [ChannelMediaRelayConfiguration] @@ -489,19 +619,40 @@ class ChannelMediaRelayConfiguration { Map toJson() => _$ChannelMediaRelayConfigurationToJson(this); } -/// Lastmile probe configuration. +/// +/// Configurations of the last-mile network test. +/// +/// @JsonSerializable(explicitToJson: true) class LastmileProbeConfig { - /// Whether to probe uplink of lastmile. i.e., audience don't need probe uplink bandwidth. + /// + /// Sets whether to test the uplink network. Some users, for example, the audience members in a LIVE_BROADCASTING channel, do not need such a test. + /// true: Test. + /// false: Not test. + /// + /// + /// + /// bool probeUplink; - /// Whether to probe downlink of lastmile. + /// + /// Sets whether to test the downlink network: + /// true: Test. + /// false: Not test. + /// + /// + /// + /// bool probeDownlink; - /// The expected maximum sending bitrate in bps in range of [100000, 5000000]. It is recommended to set this value according to the required bitrate of selected video profile. + /// + /// The expected maximum uplink bitrate (bps) of the local user. The value range is [100000, 5000000]. Agora recommends referring to setVideoEncoderConfiguration to set the value. + /// int expectedUplinkBitrate; - /// The expected maximum receive bitrate in bps in range of [100000, 5000000]. + /// + /// The expected maximum downlink bitrate (bps) of the local user. The value range is [100000,5000000]. + /// int expectedDownlinkBitrate; /// Constructs a [LastmileProbeConfig] @@ -520,23 +671,36 @@ class LastmileProbeConfig { Map toJson() => _$LastmileProbeConfigToJson(this); } -/// The position and size of the watermark image. +/// +/// The location of the target area relative to the screen or window. If you do not set this parameter, the SDK selects the whole screen or window. +/// +/// +/// +/// The horizontal offset from the top-left corner. +/// @JsonSerializable(explicitToJson: true) class Rectangle { - /// The horizontal offset from the top-left corner. + /// + /// The vertical offset from the top-left corner. + /// @JsonKey(includeIfNull: false) int? x; - /// The vertical offset from the top-left corner. @JsonKey(includeIfNull: false) int? y; - /// The width (pixels) of the watermark image. @JsonKey(includeIfNull: false) + + /// + /// The width of the target area. + /// int? width; - /// The height (pixels) of the watermark image. @JsonKey(includeIfNull: false) + + /// + /// The height of the target area. + /// int? height; /// Constructs a [Rectangle] @@ -555,23 +719,38 @@ class Rectangle { Map toJson() => _$RectangleToJson(this); } -/// Agora watermark options. A class for setting the properties of watermark. +/// +/// Configurations of the watermark image. +/// +/// @JsonSerializable(explicitToJson: true) class WatermarkOptions { - /// Whether the watermark image is visible in the local video preview. - /// - `true`: (Default) The watermark image is visible in preview. - /// - `false`: The watermark image is not visible in preview. @JsonKey(includeIfNull: false) + + /// + /// Whether the watermark image is visible in the local video preview: + /// true: (Default) The watermark image is visible in the local preview. + /// false: The watermark image is not visible in the local preview. + /// + /// + /// + /// bool? visibleInPreview; - /// The watermark position in the landscape mode. - /// See [Rectangle]. @JsonKey(includeIfNull: false) + + /// + /// The area to display the watermark image in landscape mode. + /// + /// Rectangle? positionInLandscapeMode; - /// The watermark position in the portrait mode. - /// See [Rectangle]. @JsonKey(includeIfNull: false) + + /// + /// The area to display the watermark image in portrait mode. + /// + /// Rectangle? positionInPortraitMode; /// Constructs a [WatermarkOptions] @@ -589,45 +768,78 @@ class WatermarkOptions { Map toJson() => _$WatermarkOptionsToJson(this); } -/// Configuration of the imported live broadcast voice or video stream. +/// +/// Configurations of injecting an external audio or video stream. +/// Agora will soon stop the service for injecting online media streams on the client. If you have not implemented this service, Agora recommends that you do not use it. For details, see Service Sunset Plans. +/// @JsonSerializable(explicitToJson: true) class LiveInjectStreamConfig { - /// Width of the added stream to the broadcast. The default value is 0, which is the same width as the original stream. @JsonKey(includeIfNull: false) + + /// + /// The width of the external video stream after injecting. The default value is 0, which represents the same width as the original. + /// int? width; - /// Height of the added stream to the broadcast. The default value is 0, which is the same height as the original stream. @JsonKey(includeIfNull: false) + + /// + /// The height of the external video stream after injecting. The default value is 0, which represents the same height as the original. + /// int? height; - /// Video GOP of the added stream to the broadcast. The default value is 30 frames. @JsonKey(includeIfNull: false) + + /// + /// The GOP (in frames) of injecting the external video stream. The default value is 30 frames. + /// int? videoGop; - /// Video frame rate of the added stream to the broadcast. The default value is 15 fps. @JsonKey(includeIfNull: false) + + /// + /// The frame rate (fps) of injecting the external video stream. The default rate is 15 fps. + /// VideoFrameRate? videoFramerate; - /// Video bitrate of the added stream to the broadcast. The default value is 400 Kbps. @JsonKey(includeIfNull: false) - int? videoBitrate; - /// Audio sample rate of the added stream to the broadcast: [AudioSampleRateType]. The default value is 44100 Hz. /// - /// **Note** We recommend you use the default value and not reset it. - @JsonKey(includeIfNull: false) - AudioSampleRateType? audioSampleRate; - - /// Audio bitrate of the added stream to the broadcast. The default value is 48. + /// The bitrate (Kbps) of injecting the external video stream. The default value is 400 Kbps. + /// The bitrate setting is closely linked to the video resolution. If the bitrate you set is beyond a reasonable range, the SDK sets it within a reasonable range. /// - /// **Note** We recommend you use the default value and not reset it. - @JsonKey(includeIfNull: false) - int? audioBitrate; + /// + int? videoBitrate; + + @JsonKey(includeIfNull: false) + + /// + /// The sampling rate (Hz) of injecting the external audio stream. The default value is 48000 Hz. See AudioSampleRateType. + /// Agora recommends using the default value. + /// + /// + AudioSampleRateType? audioSampleRate; + + @JsonKey(includeIfNull: false) - /// Audio channels to add into the broadcast. The value ranges between 1 and 2. The default value is 1. /// - /// **Note** We recommend you use the default value and not reset it. + /// The bitrate (Kbps) of injecting the external audio stream. The default value is 48 Kbps. + /// Agora recommends using the default value. + /// + /// + int? audioBitrate; + @JsonKey(includeIfNull: false) + + /// + /// The number of channels of the external audio stream after injecting. + /// 1: (Default) Mono. + /// 2: Stereo. + /// + /// + /// Agora recommends using the default value. + /// + /// AudioChannel? audioChannels; /// Constructs a [LiveInjectStreamConfig] @@ -650,27 +862,41 @@ class LiveInjectStreamConfig { Map toJson() => _$LiveInjectStreamConfigToJson(this); } -/// The configuration of camera capturer. +/// +/// The camera capturer preference. +/// +/// @JsonSerializable(explicitToJson: true) class CameraCapturerConfiguration { - /// The camera capture configuration. - /// See [CameraCaptureOutputPreference]. @JsonKey(includeIfNull: false) + + /// + /// The camera capture preference. For details, see CameraCaptureOutputPreference. + /// CameraCaptureOutputPreference? preference; - /// The width (px) of the video image captured by the local camera. - /// To customize the width of the video image, set [preference] as `Manual(3)` first, and then use this parameter. @JsonKey(includeIfNull: false) + + /// + /// The width (px) of the video image captured by the local camera. To customize the width of the video image, set preference as Manual(3) first, and then use captureWidth to set the video width. + /// + /// int? captureWidth; - /// The height (px) of the video image captured by the local camera. - /// To customize the height of the video image, set [preference] as `Manual(3)` first, and then use this parameter. @JsonKey(includeIfNull: false) + + /// + /// The height (px) of the video image captured by the local camera. To customize the height of the video image, set preference as Manual(3) first, and then use captureHeight. + /// + /// int? captureHeight; - /// The camera direction. - /// See [CameraDirection]. @JsonKey(includeIfNull: false) + + /// + /// The camera direction. For details, see CameraDirection. + /// + /// CameraDirection? cameraDirection; /// Constructs a [CameraCapturerConfiguration] @@ -689,41 +915,43 @@ class CameraCapturerConfiguration { Map toJson() => _$CameraCapturerConfigurationToJson(this); } +/// /// The channel media options. +/// +/// @JsonSerializable(explicitToJson: true) class ChannelMediaOptions { - /// Determines whether to subscribe to audio streams when the user joins the channel. - /// - `true`: (Default) Subscribe. - /// - `false`: Do not subscribe. - /// - /// This member serves a similar function to the [RtcEngine.muteAllRemoteAudioStreams] method. - /// After joining the channel, you can call `muteAllRemoteAudioStreams` to set whether to subscribe to audio streams in the channel. @JsonKey(includeIfNull: false) - bool? autoSubscribeAudio; - /// Determines whether to subscribe to video streams when the user joins the channel. - /// - `true`: (Default) Subscribe. - /// - `false`: Do not subscribe. /// - /// This member serves a similar function to the [RtcEngine.muteAllRemoteVideoStreams] method. - /// After joining the channel, you can call `muteAllRemoteVideoStreams` to set whether to subscribe to video streams in the channel. + /// Whether to automatically subscribe to all remote audio streams when the user joins a channel: + /// true: (Default) Subscribe. + /// false: Do not subscribe. + /// This member serves a similar function to the muteAllRemoteAudioStreams method. After joining the channel, you can call the muteAllRemoteAudioStreams method to set whether to subscribe to audio streams in the channel. + /// + bool? autoSubscribeAudio; + @JsonKey(includeIfNull: false) bool? autoSubscribeVideo; - /// Determines whether to publish the local audio stream when the user joins a channel - /// - `true`: (Default) Publish. - /// - `false`: Do not publish. - /// - /// This member serves a similar function to the [RtcEngine.muteLocalAudioStream] method. After the user joins the channel, you can call the [RtcEngine.muteLocalAudioStream] method to set whether to publish the local audio stream in the channel. @JsonKey(includeIfNull: false) - bool? publishLocalAudio; - /// Determines whether to publish the local video stream when the user joins a channel: - /// - `true`: (Default) Publish. - /// - `false`: Do not publish. /// - /// This member serves a similar function to the [RtcEngine.muteLocalVideoStream] method. After the user joins the channel, you can call the [RtcEngine.muteLocalVideoStream] method to set whether to publish the local video stream in the channel. + /// true: (Default) Publish the local audio. + /// false: Do not publish the local audio. + /// + /// This member serves a similar function to the muteLocalAudioStream method. After the user joins the channel, you can call the muteLocalAudioStream method to set whether to publish the local audio stream in the channel. + /// + bool? publishLocalAudio; + @JsonKey(includeIfNull: false) + + /// + /// true: (Default) Publish the local video. + /// false: Do not publish the local video. + /// + /// This member serves a similar function to the muteLocalVideoStream method. After the user joins the channel, you can call the muteLocalVideoStream method to set whether to publish the local audio stream in the channel. + /// bool? publishLocalVideo; /// Constructs a [ChannelMediaOptions] @@ -742,22 +970,38 @@ class ChannelMediaOptions { Map toJson() => _$ChannelMediaOptionsToJson(this); } -/// Definition of `EncryptionConfig`. +/// +/// Configurations of built-in encryption. +/// +/// @JsonSerializable(explicitToJson: true) class EncryptionConfig { - /// Encryption mode. The default encryption mode is `AES128XTS`. See [EncryptionMode]. @JsonKey(includeIfNull: false) + + /// + /// The built-in encryption mode. Agora recommends using AES128GCM2 or AES256GCM2 encrypted mode. These two modes support the use of salt for higher security. + /// SM4128ECB (4): 128-bit SM4 encryption, ECB mode. + /// + /// Salt, 32 bytes in length. Agora recommends that you use OpenSSL to generate salt on the server side, see Media Stream Encryption for details. + /// This parameter takes effect only in AES128GCM2 or AES256GCM2 encrypted mode. In this case, ensure that this parameter is not 0. + /// + /// + /// AES128GCM2 (7): (Default) 128-bit AES encryption, GCM mode. This encryption mode requires the setting of salt (encryptionKdfSalt). + /// AES256GCM2 (8): 256-bit AES encryption, GCM mode. This encryption mode requires the setting of salt (encryptionKdfSalt). + /// + /// + /// EncryptionMode? encryptionMode; + @JsonKey(includeIfNull: false) + + /// /// Encryption key in string type. + /// If you do not set an encryption key or set it as null, you cannot use the built-in encryption, and the SDK returns ERR_INVALID_ARGUMENT (-2). /// - /// **Note** /// - /// If you do not set an encryption key or set it as null, you cannot use the built-in encryption, and the SDK returns [ErrorCode.InvalidArgument]. - @JsonKey(includeIfNull: false) String? encryptionKey; - /// The salt. Agora recommends using OpenSSL to generate the salt on your server. For details, see *Channel Encryption*. @JsonKey(includeIfNull: false) List? encryptionKdfSalt; @@ -776,94 +1020,130 @@ class EncryptionConfig { Map toJson() => _$EncryptionConfigToJson(this); } -/// Statistics of RTCEngine. +/// +/// Statistics of a call session. +/// +/// @JsonSerializable(explicitToJson: true) class RtcStats { - /// Call duration in seconds, represented by an aggregate value. + /// + /// Call duration of the local user in seconds, represented by an aggregate value. + /// int duration; - /// Total number of bytes transmitted, represented by an aggregate value. + /// + /// The number of bytes sent. + /// int txBytes; - /// Total number of bytes received, represented by an aggregate value. + /// + /// The number of bytes received. + /// int rxBytes; - /// Total number of audio bytes sent (bytes), represented by an aggregate value. + /// + /// The total number of audio bytes sent, represented by an aggregate value. + /// int txAudioBytes; - /// Total number of video bytes sent (bytes), represented by an aggregate value. + /// + /// The total number of video bytes sent, represented by an aggregate value. + /// int txVideoBytes; - /// Total number of audio bytes received (bytes), represented by an aggregate value. + /// + /// The total number of audio bytes received, represented by an aggregate value. + /// int rxAudioBytes; - /// Total number of video bytes received (bytes), represented by an aggregate value. + /// + /// The total number of video bytes received, represented by an aggregate value. + /// int rxVideoBytes; - /// Transmission bitrate in Kbps, represented by an instantaneous value. + /// + /// Video transmission bitrate (Kbps), represented by an instantaneous value. + /// int txKBitRate; - /// Receive bitrate (Kbps), represented by an instantaneous value. + /// + /// The receiving bitrate (Kbps), represented by an instantaneous value. + /// int rxKBitRate; - /// The transmission bitrate of the audio packet (Kbps), represented by an instantaneous value. + /// + /// The bitrate (Kbps) of sending the audio packet. + /// int txAudioKBitRate; + /// /// Audio receive bitrate (Kbps), represented by an instantaneous value. + /// int rxAudioKBitRate; - /// Video transmission bitrate (Kbps), represented by an instantaneous value. + /// + /// The bitrate (Kbps) of sending the video. + /// int txVideoKBitRate; + /// /// Video receive bitrate (Kbps), represented by an instantaneous value. + /// int rxVideoKBitRate; - /// The number of users in the channel. - /// - Communication profile: The number of users in the channel. - /// - Live Broadcast profile: - /// - If the local user is an audience: The number of users in the channel = The number of hosts in the channel + 1. - /// - If the local user is a host: The number of users in the channel = The number of hosts in the channel. int userCount; - /// Client-server latency. + /// + /// The client-to-server delay (milliseconds). + /// int lastmileDelay; - /// The packet loss rate (%) from the local client to Agora's edge server, before network countermeasures. + /// + /// The packet loss rate (%) from the client to the Agora server before applying the anti-packet-loss algorithm. + /// int txPacketLossRate; - /// The packet loss rate (%) from Agora's edge server to the local client, before network countermeasures. + /// + /// + /// int rxPacketLossRate; - /// System CPU usage (%). /// - /// **Note** + /// The system CPU usage (%). + /// The value of cpuTotalUsage is always reported as 0 in the leaveChannel callback. + /// /// - /// The `cpuTotalUsage` reported in the `leaveChannel` callback is always 0. double cpuTotalUsage; - /// Application CPU usage (%). /// - /// **Note** + /// The CPU usage (%) of the app. /// - /// The `cpuAppUsage` reported in the `leaveChannel` callback is always 0. double cpuAppUsage; - /// The round-trip time delay from the client to the local router. + /// + /// The round-trip time delay (ms) from the client to the local router. + /// int gatewayRtt; - /// The memory usage ratio of the app (%). /// - /// **Note**: This value is for reference only. Due to system limitations, you may not get the value of this member. + /// The memory ratio occupied by the app (%). + /// This value is for reference only. Due to system limitations, you may not get this value. + /// + /// double memoryAppUsageRatio; - /// The memory usage ratio of the system (%). /// - /// **Note**: This value is for reference only. Due to system limitations, you may not get the value of this member. + /// The memory occupied by the system (%). + /// This value is for reference only. Due to system limitations, you may not get this value. + /// + /// double memoryTotalUsageRatio; - /// The memory usage of the app (KB). /// - /// **Note**: This value is for reference only. Due to system limitations, you may not get the value of this member. + /// The memory size occupied by the app (KB). + /// This value is for reference only. Due to system limitations, you may not get this value. + /// + /// int memoryAppUsageInKbytes; /// Constructs a [RtcStats] @@ -901,27 +1181,40 @@ class RtcStats { Map toJson() => _$RtcStatsToJson(this); } -/// Properties of the audio volume information. -/// Contains the user ID and volume information for each speaker. +/// +/// The volume information of users. +/// +/// @JsonSerializable(explicitToJson: true) class AudioVolumeInfo { - /// The user ID of the speaker. The uid of the local user is 0. + /// + /// The user ID. + /// In the local user's callback, uid = 0. + /// + /// The volume of the user. The value ranges between 0 (lowest volume) and 255 (highest volume). If the user calls startAudioMixing, the value of volume is the volume after audio mixing. + /// + /// In the remote users' callback, uid is the user ID of a remote user whose instantaneous volume is one of the three highest. + /// + /// + /// int uid; - /// The sum of the voice volume and audio-mixing volume of the speaker. The value ranges between 0 (lowest volume) and 255 (highest volume). int volume; - /// Voice activity status of the local user. - /// - 0: The local user is not speaking. - /// - 1: The local user is speaking. /// - /// **Note** - /// - The `vad` parameter cannot report the voice activity status of the remote users. In the remote users' callback, `vad` = 1. - /// - Ensure that you set `report_vad`(true) in the [RtcEngine.enableAudioVolumeIndication] method to enable the voice activity - /// detection of the local user. + /// The voice activity status of the local user. + /// 0: The local user is not speaking. + /// 1: The local user is speaking. + /// + /// + /// + /// The vad parameter does not report the voice activity status of remote users. In the remote users' callback, the value of vad is always 0. + /// + /// + /// + /// int vad; - /// The channel ID, which indicates which channel the speaker is in. String channelId; /// Constructs a [AudioVolumeInfo] @@ -940,27 +1233,59 @@ class AudioVolumeInfo { Map toJson() => _$AudioVolumeInfoToJson(this); } -/// Integer coordinates for a rectangle. +/// +/// The screen sharing region. +/// Deprecated: +/// This class is deprecated. Please use the updateScreenCaptureRegion method to update the shared area. +/// @JsonSerializable(explicitToJson: true) class Rect { - /// The X coordinate of the left side of the rectangle. @JsonKey(includeIfNull: false) + @Deprecated('This property is deprecated, pls use x instead.') + + /// + /// The coordinate of the left side of the shared area on the horizontal axis. + /// int? left; - /// The Y coordinate of the top side of the rectangle. @JsonKey(includeIfNull: false) + @Deprecated('This property is deprecated, pls use y instead.') + + /// + /// The coordinate of the top side of the shared area on the vertical axis. + /// int? top; - /// The X coordinate of the right side of the rectangle. @JsonKey(includeIfNull: false) + @Deprecated('This property is deprecated, pls use x + width instead.') + + /// + /// The coordinate of the right side of the shared area on the horizontal axis. + /// int? right; - /// The Y coordinate of the bottom side of the rectangle. @JsonKey(includeIfNull: false) + @Deprecated('This property is deprecated, pls use y + height instead.') + + /// + /// The coordinate of the bottom side of the shared area on the vertical axis. + /// int? bottom; + int x; + + int y; + + int width; + + int height; + /// Constructs a [Rect] Rect({ + this.x = 0, + this.y = 0, + this.width = 0, + this.height = 0, this.left, this.top, this.right, @@ -974,16 +1299,25 @@ class Rect { Map toJson() => _$RectToJson(this); } -/// The one-way last-mile probe result. +/// +/// Results of the uplink or downlink last-mile network test. +/// +/// @JsonSerializable(explicitToJson: true) class LastmileProbeOneWayResult { + /// /// The packet loss rate (%). + /// int packetLossRate; + /// /// The network jitter (ms). + /// int jitter; + /// /// The estimated available bandwidth (bps). + /// int availableBandwidth; /// Constructs a [LastmileProbeOneWayResult] @@ -1001,22 +1335,30 @@ class LastmileProbeOneWayResult { Map toJson() => _$LastmileProbeOneWayResultToJson(this); } -/// Statistics of the lastmile probe. +/// +/// Results of the uplink and downlink last-mile network tests. +/// +/// @JsonSerializable(explicitToJson: true) class LastmileProbeResult { - /// The state of the probe test. - /// See [LastmileProbeResultState]. + /// + /// + /// LastmileProbeResultState state; - /// The round-trip delay time (ms). + /// + /// The round-trip time (ms). + /// int rtt; - /// The uplink last-mile network report. - /// See [LastmileProbeOneWayResult]. + /// + /// Results of the uplink last-mile network test. For details, see LastmileProbeOneWayResult. + /// LastmileProbeOneWayResult uplinkReport; - /// The downlink last-mile network report. - /// See [LastmileProbeOneWayResult]. + /// + /// Results of the downlink last-mile network test. For details, see LastmileProbeOneWayResult. + /// LastmileProbeOneWayResult downlinkReport; /// Constructs a [LastmileProbeResult] @@ -1035,19 +1377,30 @@ class LastmileProbeResult { Map toJson() => _$LastmileProbeResultToJson(this); } -/// Statistics of the local audio stream. +/// +/// Local audio statistics. +/// +/// @JsonSerializable(explicitToJson: true) class LocalAudioStats { - /// The number of channels. + /// + /// The number of audio channels. + /// int numChannels; - /// The sample rate (Hz). + /// + /// The sampling rate (Hz) of sending the local user's audio stream. + /// int sentSampleRate; - /// The average sending bitrate (Kbps). + /// + /// The average bitrate (Kbps) of sending the local user's audio stream. + /// int sentBitrate; - /// The video packet loss rate (%) from the local client to the Agora edge server before applying the anti-packet loss strategies. + /// + /// The packet loss rate (%) from the local client to the Agora server before applying the anti-packet loss strategies. + /// int txPacketLossRate; /// Constructs a [LocalAudioStats] @@ -1066,54 +1419,81 @@ class LocalAudioStats { Map toJson() => _$LocalAudioStatsToJson(this); } -/// Statistics of the local video. +/// +/// The statistics of the local video stream. +/// +/// @JsonSerializable(explicitToJson: true) class LocalVideoStats { - /// Bitrate (Kbps) sent in the reported interval, which does not include the bitrate of the re-transmission video after the packet loss. + /// + /// The actual bitrate (Kbps) for sending the local video stream.This value does not include the bitrate for resending the video after packet loss. + /// + /// int sentBitrate; - /// Frame rate (fps) sent in the reported interval, which does not include the frame rate of the re-transmission video after the packet loss. + /// + /// The actual frame rate (Kbps) while sending the local video stream.This value does not include the frame rate for resending the video after packet loss. + /// int sentFrameRate; - /// The encoder output frame rate (fps) of the local video. + /// + /// The output frame rate (fps) of the local video encoder. + /// int encoderOutputFrameRate; - /// The renderer output frame rate (fps) of the local video. + /// + /// The output frame rate (fps) of the local video renderer. + /// int rendererOutputFrameRate; - /// The target bitrate (Kbps) of the current encoder. This value is estimated by the SDK based on the current network conditions. + /// + /// The target bitrate (Kbps) of the current encoder. This is an estimate made by the SDK based on the current network conditions. + /// int targetBitrate; + /// /// The target frame rate (fps) of the current encoder. + /// int targetFrameRate; - /// Quality change of the local video in terms of target frame rate and target bit rate since last count. - /// See [VideoQualityAdaptIndication]. + /// + /// + /// VideoQualityAdaptIndication qualityAdaptIndication; - /// The encoding bitrate (Kbps), which does not include the bitrate of the re-transmission video after packet loss. + /// + /// The bitrate (Kbps) for encoding the local video stream.This value does not include the bitrate for resending the video after packet loss. + /// + /// int encodedBitrate; - /// The width of the encoding frame (px). + /// + /// The width of the encoded video (px). + /// int encodedFrameWidth; - /// The height of the encoding frame (px). + /// + /// The height of the encoded video (px). + /// int encodedFrameHeight; - /// The value of the sent frame rate, represented by an aggregate value. + /// + /// The number of the sent video frames, represented by an aggregate value. + /// int encodedFrameCount; + /// /// The codec type of the local video. - /// See [VideoCodecType]. + /// VideoCodecType codecType; - /// The video packet loss rate (%) from the local client to the Agora edge server before applying the anti-packet loss strategies. + /// + /// The video packet loss rate (%) from the local client to the Agora server before applying the anti-packet loss strategies. + /// int txPacketLossRate; - /// The capture frame rate (fps) of the local video. int captureFrameRate; - /// The capture brightness level type. CaptureBrightnessLevelType captureBrightnessLevel; /// Constructs a [LocalVideoStats] @@ -1143,95 +1523,113 @@ class LocalVideoStats { Map toJson() => _$LocalVideoStatsToJson(this); } -/// Statistics of the remote audio. +/// +/// Audio statistics of the remote user. +/// +/// @JsonSerializable(explicitToJson: true) class RemoteAudioStats { - /// ID of the user sending the audio streams. + /// + /// The user ID of the remote user. + /// int uid; - /// Audio quality received by the user. - /// See [NetworkQuality]. + /// + /// The quality of the audio stream sent by the user. See NetworkQuality. + /// NetworkQuality quality; - /// Network delay (ms) from the sender to the receiver. + /// + /// The network delay (ms) from the sender to the receiver. + /// int networkTransportDelay; - /// Network delay (ms) from the receiver to the jitter buffer. /// - /// **Note** + /// The network delay (ms) from the receiver to the jitter buffer.This parameter does not take effect if the receiver is an audience member and audienceLatencyLevel of ClientRoleOptions is 1. + /// /// - /// When the receiver is an audience member and [AudienceLatencyLevelType] is `1`, this parameter does not take effect. int jitterBufferDelay; - /// Packet loss rate in the reported interval. + /// + /// The frame loss rate (%) of the remote audio stream in the reported interval. + /// int audioLossRate; - /// The number of channels. + /// + /// The number of audio channels. + /// int numChannels; - /// The sample rate (Hz) of the received audio stream in the reported interval. + /// + /// The sampling rate of the received audio stream in the reported interval. + /// int receivedSampleRate; + /// /// The average bitrate (Kbps) of the received audio stream in the reported interval. + /// int receivedBitrate; - /// The total freeze time (ms) of the remote audio stream after the remote user joins the channel. In the reported interval, audio freeze occurs when the audio frame loss rate reaches 4%. totalFrozenTime = The audio freeze time × 2 × 1000 (ms). + /// + /// The total freeze time (ms) of the remote audio stream after the remote user joins the channel. In a session, audio freeze occurs when the audio frame loss rate reaches 4%. + /// int totalFrozenTime; - /// The total audio freeze time as a percentage (%) of the total time when the audio is available. + /// + /// The total audio freeze time as a percentage (%) of the total time when the audio is available. The audio is considered available when the remote user neither stops sending the audio stream nor disables the audio module after joining the channel. + /// int frozenRate; - /// The total time (ms) when the remote user in the Communication profile or the remote broadcaster in the LiveBroadcasting profile neither stops sending the audio stream nor disables the audio module after joining the channel. + /// + /// The total active time (ms) between the start of the audio call and the callback of the remote user. + /// The active time refers to the total duration of the remote user without the mute state. + /// int totalActiveTime; - /// The total active time (ms) of the remote audio stream after the remote user publish the audio stream. + /// + /// The total duration (ms) of the remote audio stream. + /// int publishDuration; - /// Quality of experience (QoE) of the local user when receiving a remote audio stream. See [qoeQuality]. ExperienceQualityType qoeQuality; - /// The reason for poor QoE of the local user when receiving a remote audio stream. See [qualityChangedReason]. ExperiencePoorReason qualityChangedReason; - /// The [quality] of the remote audio stream as determined by the Agora real-time audio MOS (Mean Opinion Score) measurement method in the reported interval. - /// The return value ranges from 0 to 500. Dividing the return value by 100 gets the MOS score, which ranges from 0 to 5. The higher the score, the better the audio quality. + /// + /// The quality of the remote audio stream in the reported interval. The quality is determined by the Agora real-time audio MOS (Mean Opinion Score) measurement method. The return value range is [0, 500]. Dividing the return value by 100 gets the MOS score, which ranges from 0 to 5. The higher the score, the better the audio quality. /// /// The subjective perception of audio quality corresponding to the Agora real-time audio MOS scores is as follows: /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - ///
        MOS scorePerception of audio quality
        Greater than 4- Excellent. The audio sounds clear and smooth.
        From 3.5 to 4Good. The audio has some perceptible impairment, but still sounds clear.
        From 3 to 3.5Fair. The audio freezes occasionally and requires attentive listening.
        From 2.5 to 3Poor. The audio sounds choppy and requires considerable effort to understand.
        From 2 to 2.5Bad. The audio has occasional noise. Consecutive audio dropouts occur, resulting in some information loss. The users can communicate only with difficulty.
        Less than 2 Very bad. The audio has persistent noise. Consecutive audio dropouts are frequent, resulting in severe information loss. Communication is nearly impossible.
        + /// MOS score + /// Perception of audio quality + /// + /// + /// Greater than 4 + /// Excellent. The audio sounds clear and smooth. + /// + /// + /// From 3.5 to 4 + /// Good. The audio has some perceptible impairment but still sounds clear. + /// + /// + /// From 3 to 3.5 + /// Fair. The audio freezes occasionally and requires attentive listening. + /// + /// + /// From 2.5 to 3 + /// Poor. The audio sounds choppy and requires considerable effort to understand. + /// + /// + /// From 2 to 2.5 + /// Bad. The audio has occasional noise. Consecutive audio dropouts occur, resulting in some information loss. The users can communicate only with difficulty. + /// + /// + /// Less than 2 + /// Very bad. The audio has persistent noise. Consecutive audio dropouts are frequent, resulting in severe information loss. Communication is nearly impossible. + /// + /// + /// + /// int mosValue; /// Constructs a [RemoteAudioStats] @@ -1261,49 +1659,86 @@ class RemoteAudioStats { Map toJson() => _$RemoteAudioStatsToJson(this); } -/// Statistics of the remote video. +/// +/// Statistics of the remote video stream. +/// +/// @JsonSerializable(explicitToJson: true) class RemoteVideoStats { - /// ID of the user sending the video streams. + /// + /// The user ID of the remote user sending the video stream. + /// int uid; - /// Time delay (ms). In scenarios where audio and video is synchronized, you can use the value of `networkTransportDelay` and `jitterBufferDelay` in [RemoteAudioStats] to know the delay statistics of the remote video. @deprecated + + /// + /// + /// + /// Deprecated: + /// In scenarios where audio and video are synchronized, you can get the video delay data from networkTransportDelay and jitterBufferDelay in RemoteAudioStats. + /// + /// + /// The video delay (ms). + /// + /// int delay; - /// Width (pixels) of the remote video. + /// + /// The width (pixels) of the video. + /// int width; - /// Height (pixels) of the remote video. + /// + /// The height (pixels) of the video. + /// int height; - /// Bitrate (Kbps) received in the reported interval. + /// + /// The bitrate (Kbps) of receiving the remote video since the last count. + /// int receivedBitrate; - /// The decoder output frame rate (fps) of the remote video. + /// + /// The frame rate (fps) of decoding the remote video. + /// int decoderOutputFrameRate; - /// The renderer output frame rate (fps) of the remote video. + /// + /// The frame rate (fps) of rendering the remote video. + /// int rendererOutputFrameRate; - /// Packet loss rate (%) of the remote video stream after network countermeasures. + /// + /// The packet loss rate (%) of the remote video after using the anti-packet-loss technology. + /// int packetLossRate; - /// Video stream type (high-stream or low-stream). - /// See [VideoStreamType]. + /// + /// The type of the video stream. + /// VideoStreamType rxStreamType; - /// The total freeze time (ms) of the remote video stream after the remote user joins the channel. - /// In a video session where the frame rate is set to no less than 5 fps, video freeze occurs when the time interval between two adjacent renderable video frames is more than 500 ms. + /// + /// The total freeze time (ms) of the remote video stream after the remote user joins the channel. In a video session where the frame rate is set to 5 fps or higher, video freeze occurs when the time interval between two adjacent video frames is more than 500 + /// ms. + /// int totalFrozenTime; - /// The total video freeze time (`totalFrozenTime`) as a percentage (%) of the total time when the video is available (`totalActiveTime`). + /// + /// The total video freeze time as a percentage (%) of the total time when the video is available. The video is available means that the remote user neither stops sending the video stream nor disables the video module after joining the channel. + /// int frozenRate; - /// The total time (ms) when the remote user in the Communication profile or the remote broadcaster in the Live-broadcast profile neither stops sending the video stream nor disables the video module after joining the channel. + /// + /// Total active time (ms) of the video. + /// When the remote user/host neither stops sending the video stream nor disables the video module after joining the channel, the video is available. + /// int totalActiveTime; - /// The total publish duration (ms) of the remote video stream. + /// + /// The total duration (ms) of the remote video stream. + /// int publishDuration; /// Constructs a [RemoteVideoStats] @@ -1331,22 +1766,40 @@ class RemoteVideoStats { Map toJson() => _$RemoteVideoStatsToJson(this); } +/// /// The information of the detected human face. +/// +/// +/// +/// The x coordinate (px) of the human face in the local video. Taking the top left corner of the captured video as the origin, the x coordinate represents the relative lateral displacement of the top left corner of the human face to the origin. +/// +/// @JsonSerializable(explicitToJson: true) class FacePositionInfo { - /// The x coordinate (px) of the human face in the local video. Taking the top left corner of the captured video as the origin, the x coordinate represents the relative lateral displacement of the top left corner of the human face to the origin. int x; + /// /// The y coordinate (px) of the human face in the local video. Taking the top left corner of the captured video as the origin, the y coordinate represents the relative longitudinal displacement of the top left corner of the human face to the origin. + /// + /// int y; + /// /// The width (px) of the human face in the captured video. + /// + /// int width; + /// /// The height (px) of the human face in the captured video. + /// + /// int height; - /// The distance (cm) between the human face and the screen. + /// + /// The distance between the human face and the device screen (cm). + /// + /// int distance; /// Constructs a [FacePositionInfo] @@ -1366,11 +1819,17 @@ class FacePositionInfo { Map toJson() => _$FacePositionInfoToJson(this); } +/// /// The detailed options of a user. +/// +/// @JsonSerializable(explicitToJson: true) class ClientRoleOptions { - /// The latency level of an audience member in a live interactive streaming. @JsonKey(includeIfNull: false) + + /// + /// The latency level of an audience member in interactive live streaming. + /// AudienceLatencyLevelType? audienceLatencyLevel; /// Constructs a [ClientRoleOptions] @@ -1386,25 +1845,32 @@ class ClientRoleOptions { Map toJson() => _$ClientRoleOptionsToJson(this); } -/// Log file configurations. +/// +/// The configuration of the SDK log files. +/// +/// @JsonSerializable(explicitToJson: true) class LogConfig { - /// The absolute path of log files. The default file path is `/storage/emulated/0/Android/data//files/agorasdk.log` for Android or `App Sandbox/Library/caches/agorasdk.log` for iOS. - /// - /// Ensure that the directory for the log files exists and is writable. You can use this parameter to rename the log files. @JsonKey(includeIfNull: false) - String? filePath; - /// The size (KB) of a log file. The default value is 1024 KB. /// - /// If you set `fileSize` to 1024 KB, the SDK outputs at most 5 MB log files; if you set it to less than 1024 KB, the setting is invalid, and the maximum size of a log file is still 1024 KB. + /// The absolute or relative path of the log file, which ends with \ or /. Ensure that the path for the log file exists and is writable. You can use this parameter to rename the log files. + /// + /// + String? filePath; + @JsonKey(includeIfNull: false) - int? fileSize; - /// The output log level of the SDK. See details in [LogLevel]. /// - /// For example, if you set the log level to `Warn`, the SDK outputs the logs within levels `Fatal`, `Error`, and `Warn`. + /// The size (KB) of a log file. The default value is 2014 KB. If you set fileSize to 1024 KB, the maximum aggregate size of the log files output by the SDK is 5 MB. If you set fileSize to less than 1024 KB, the setting is invalid, and the maximum size of a log file is still 1024 KB. + /// + int? fileSize; + @JsonKey(includeIfNull: false) + + /// + /// The output level of the SDK log file. See LogLevel. + /// LogLevel? level; /// Constructs a [LogConfig] @@ -1422,33 +1888,28 @@ class LogConfig { Map toJson() => _$LogConfigToJson(this); } -/// The configurations for the data stream. /// -/// The following table shows the relationship between the [syncWithAudio] parameter and the [ordered] parameter: +/// The configurations for the data stream. +/// The following table shows the SDK behaviors under different parameter settings: /// -/// | [syncWithAudio] | [ordered] | SDK behaviors | -/// |---------------|---------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -/// | `false` | `false` | The SDK triggers the `streamMessage` callback immediately after the receiver receives a data packet. | -/// | `true` | `false` | If the data packet delay is within the audio delay, the SDK triggers the `streamMessage` callback when the synchronized audio packet is played out. If the data packet delay exceeds the audio delay, the SDK triggers the `streamMessage` callback as soon as the data packet is received. In this case, the data packet is not synchronized with the audio packet. | -/// | `false` | `true` | If the delay of a data packet is within five seconds, the SDK corrects the order of the data packet. If the delay of a data packet exceeds five seconds, the SDK discards the data packet. | -/// | `true` | `true` | If the delay of a data packet is within the audio delay, the SDK corrects the order of the data packet. If the delay of a data packet exceeds the audio delay, the SDK discards this data packet. | @JsonSerializable(explicitToJson: true) class DataStreamConfig { + /// /// Whether to synchronize the data packet with the published audio packet. + /// true: Synchronize the data packet with the audio packet. + /// false: Do not synchronize the data packet with the audio packet. + /// When you set the data packet to synchronize with the audio, then if the data packet delay is within the audio delay, the SDK triggers the streamMessage callback when the synchronized audio packet is played out. Do not set this parameter as true if you need the receiver to receive the data packet immediately. Agora recommends that you set this parameter to `true` only when you need to implement specific functions, for example lyric synchronization. /// - /// - `true`: Synchronize the data packet with the audio packet. - /// - `false`: Do not synchronize the data packet with the audio packet. /// - /// When you set the data packet to synchronize with the audio, then if the data packet delay is within the audio delay range, the SDK triggers the `streamMessage` callback when the synchronized audio packet is played out. - /// Do not set this parameter as `true` if you need the receiver to receive the data packet immediately. Agora recommends that you set this parameter to `true` only when you need to implement specific functions, for example lyric synchronization. bool syncWithAudio; + /// /// Whether the SDK guarantees that the receiver receives the data in the sent order. + /// true: Guarantee that the receiver receives the data in the sent order. + /// false: Do not guarantee that the receiver receives the data in the sent order. + /// Do not set this parameter as true if you need the receiver to receive the data packet immediately. /// - /// - `true`: Guarantee that the receiver receives the data in the sent order. - /// - `false`: Do not guarantee that the receiver receives the data in the sent order. /// - /// Do not set this parameter to `true` if you need the receiver to receive the data immediately. bool ordered; /// Constructs a [DataStreamConfig] @@ -1465,7 +1926,7 @@ class DataStreamConfig { Map toJson() => _$DataStreamConfigToJson(this); } -/// Configurations for the RtcEngineConfig instance. +/* class-RtcEngineConfig */ @JsonSerializable(explicitToJson: true) @deprecated class RtcEngineConfig extends RtcEngineContext { @@ -1475,27 +1936,36 @@ class RtcEngineConfig extends RtcEngineContext { : super(appId, areaCode: areaCode, logConfig: logConfig); } -/// Configurations for the RtcEngineContext instance. +/// +/// Configurations of initializing the SDK. +/// +/// @JsonSerializable(explicitToJson: true) class RtcEngineContext { - /// The App ID issued to you by Agora. See [How to get the App ID](https://docs.agora.io/en/Agora%20Platform/token#get-an-app-id). - /// Only users in apps with the same App ID can join the same channel and communicate with each other. Use an App ID to create only - /// one `RtcEngine` instance. To change your App ID, call `destroy` to destroy the current `RtcEngine` instance and then call `createWithContext` - /// to create an `RtcEngine` instance with the new App ID. + /// + /// The App ID issued by Agora for your app development project. Only users who use the same App ID can join the same channel and communicate with each other. + /// An App ID can only be used to create one RtcEngineinstance. If you need to change the App ID, you + /// must call destroy destroy the current IRtcEngine, and + /// then call createWithContext to recreate RtcEngine. + /// + /// String appId; - /// The region for connection. This advanced feature applies to scenarios that have regional restrictions. - /// - /// For the regions that Agora supports, see [AreaCode]. After specifying the region, the SDK connects to the Agora servers within that region. @JsonKey(includeIfNull: false, toJson: _$AreaCodeListToJson) - List? areaCode; - /// The configuration of the log files that the SDK outputs. See [LogConfig]. /// - /// By default, the SDK outputs five log files, `agorasdk.log`, `agorasdk_1.log`, `agorasdk_2.log`, `agorasdk_3.log`, `agorasdk_4.log`, each with a default size of 1024 KB. - /// These log files are encoded in UTF-8. The SDK writes the latest logs in `agorasdk.log`. When `agorasdk.log` is full, the SDK deletes the log file with the earliest modification - /// time among the other four, renames `agorasdk.log` to the name of the deleted log file, and creates a new `agorasdk.log` to record latest logs. + /// The region for connection. This advanced feature applies to scenarios that have regional restrictions. See AreaCode for details about supported regions. + /// After specifying the region, the SDK connects to the Agora servers within that region. + /// + List? areaCode; + @JsonKey(includeIfNull: false) + + /// + /// The configuration of the log files. See LogConfig. + /// By default, the SDK outputs five log files: agorasdk.log, agorasdk_1.log, agorasdk_2.log, agorasdk_3.log, and agorasdk_4.log. + /// Each log file has a default size of 512 KB and is encoded in UTF-8 format. The SDK writes the latest log in agorasdk.log. When agorasdk.log is full, the SDK deletes the log file with the earliest modification time among the other four, renames agorasdk.log to the name of the deleted log file, and create a new agorasdk.log to record the latest log. + /// LogConfig? logConfig; /// Constructs a [RtcEngineContext] @@ -1522,20 +1992,26 @@ class RtcEngineContext { } } -/// The metronome configuration, which is set in [RtcEngine.startRhythmPlayer] or [RtcEngine.configRhythmPlayer]. +/// +/// The metronome configuration. +/// +/// @JsonSerializable(explicitToJson: true) class RhythmPlayerConfig { - /// The number of beats per measure. The range is 1 to 9. The default value is 4, which means that each measure contains one downbeat and three upbeats. @JsonKey(includeIfNull: false) + + /// + /// The number of beats per measure, which ranges from 1 to 9. The default value is 4, which means that each measure contains one downbeat and three upbeats. + /// int? beatsPerMeasure; - /// Tempo (beats per minute). The range is 60 to 360. The default value is 60, which means that the metronome plays 60 beats in one minute. @JsonKey(includeIfNull: false) + + /// + /// The beat speed (beats/minute), which ranges from 60 to 360. The default value is 60, which means that the metronome plays 60 beats in one minute. + /// int? beatsPerMinute; - /// Whether to publish the sound of the metronome to remote users: - /// - `true`: (Default) Publish. Both the local user and remote users can hear the metronome. - /// - `false`: Do not publish. Only the local user can hear the metronome. @JsonKey(includeIfNull: false) bool? publish; @@ -1554,30 +2030,45 @@ class RhythmPlayerConfig { Map toJson() => _$RhythmPlayerConfigToJson(this); } -/// Recording configuration, which is set in [RtcEngine.startAudioRecordingWithConfig]. +/// +/// The configuration of audio recording on the app client. +/// +/// @JsonSerializable(explicitToJson: true) class AudioRecordingConfiguration { - /// The absolute path (including the filename extensions) of the recording file. For example: `/sdcard/emulated/0/audio.mp4` on Android and `/var/mobile/Containers/Data/audio.mp4` on iOS. Ensure that the path you specify exists and is writable. + /// + /// The absolute path (including the filename extensions) of the recording file. For example: C:\music\audio.aac. + /// Ensure that the directory for the log files exists and is writable. + /// + /// String filePath; - /// Audio recording quality. For details, see [AudioRecordingQuality]. This parameter applies to AAC files only. @JsonKey(includeIfNull: false) + + /// + /// Recording quality. For details, see AudioRecordingQuality. + /// Note: This parameter applies to AAC files only. + /// AudioRecordingQuality? recordingQuality; - /// Recording content. For details, see [AudioRecordingPosition]. @JsonKey(includeIfNull: false) - AudioRecordingPosition? recordingPosition; - /// Recording sample rate (Hz). The following values are supported: - /// - 16000 - /// - (Default) 32000 - /// - 44100 - /// - 48000 /// - /// **Note** - /// - If this parameter is set to 44100 or 48000, for better recording effects, Agora recommends recording WAV files or AAC files whose `recordingQuality` - /// is `Medium` or `High`. + /// The recording content. For details, see AudioRecordingPosition. + /// + AudioRecordingPosition? recordingPosition; + @JsonKey(includeIfNull: false) + + /// + /// Recording sample rate (Hz). + /// 16000 + /// (Default) 32000 + /// 44100 + /// 48000 + /// + /// If you set this parameter as 44100 or 48000, Agora recommends recording WAV files or AAV files whose recordingQuality is Medium or High for better recording quality. + /// AudioSampleRateType? recordingSampleRate; /// Constructs a [AudioRecordingConfiguration] @@ -1596,50 +2087,34 @@ class AudioRecordingConfiguration { Map toJson() => _$AudioRecordingConfigurationToJson(this); } +/// /// The custom background image. +/// +/// @JsonSerializable(explicitToJson: true) class VirtualBackgroundSource { - /// The type of the custom background image. @JsonKey(includeIfNull: false) - VirtualBackgroundSourceType? backgroundSourceType; - /// The color of the custom background image. - /// The format is a hexadecimal integer defined by RGB, without the # sign, - /// such as 0xFFB6C1 for light pink. The default value is 0xFFFFFF, - /// which signifies white. The value range is [0x000000,0xffffff]. - /// If the value is invalid, the SDK replaces the original background image - /// with a white background image. /// - /// **Note** + /// The type of the custom background image. See VirtualBackgroundSourceType. /// - /// This parameter takes effect only when the type of the custom background image is `color`. + VirtualBackgroundSourceType? backgroundSourceType; + @JsonKey( includeIfNull: false, fromJson: _$ColorFromJson, toJson: _$ColorToJson) - Color? color; - /// The local absolute path of the custom background image. - /// PNG and JPG formats are supported. If the path is invalid, - /// the SDK replaces the original background image with a white background image. /// - /// **Note** + /// The type of the custom background image. The color of the custom background image. The format is a hexadecimal integer defined by RGB, without the # sign, such as 0xFFB6C1 for light pink.The default value is 0xFFFFFF, which signifies white. The value range is [0x000000, 0xffffff]. If the value is invalid, the SDK replaces the original background image with a white background image.This parameter takes effect only when the type of the custom background image is Color. /// - /// This parameter takes effect only when the type of the custom background image is `image`. + Color? color; + @JsonKey(includeIfNull: false) - String? source; - /// The degree of blurring applied to the custom background image: /// - /// * [VirtualBackgroundBlurDegree.Low]: The degree of blurring applied to the - /// custom background image is low. The user can almost see the background clearly. - /// * [VirtualBackgroundBlurDegree.Medium]: The degree of blurring applied to - /// the custom background image is medium. It is difficult for the user to - /// recognize details in the background. - /// * [VirtualBackgroundBlurDegree.High]: (Default) The degree of blurring applied - /// to the custom background image is high. The user can barely see any - /// distinguishing features in the background. /// - /// **Note**: This parameter takes effect only when the type of the custom - /// background image is [VirtualBackgroundSourceType.Blur]. + /// + String? source; + @JsonKey(name: 'blur_degree') VirtualBackgroundBlurDegree blurDegree; @@ -1659,15 +2134,24 @@ class VirtualBackgroundSource { Map toJson() => _$VirtualBackgroundSourceToJson(this); } -/// The information of an audio file, which is reported in [RtcEngineEventHandler.requestAudioFileInfoCallback]. +/// +/// The information of an audio file. This struct is reported in requestAudioFileInfoCallback. +/// +/// @JsonSerializable(explicitToJson: true) class AudioFileInfo { - /// The file path. @JsonKey() + + /// + /// The file path. + /// String filePath; - /// The file duration (ms). @JsonKey() + + /// + /// The file duration (ms). + /// int durationMs; /// Construct the [AudioFileInfo] @@ -1730,3 +2214,176 @@ class EchoTestConfiguration { /// @nodoc Map toJson() => _$EchoTestConfigurationToJson(this); } + +/// +/// The MediaDeviceInfo class, which contains the device ID and device name. +/// +/// +@JsonSerializable(explicitToJson: true) +class MediaDeviceInfo { + /// + /// The device ID. + /// + String deviceId; + + /// + /// The device name. + /// + String deviceName; + + /// Constructs a [MediaDeviceInfo] + MediaDeviceInfo( + this.deviceId, + this.deviceName, + ); + + /// @nodoc + factory MediaDeviceInfo.fromJson(Map json) => + _$MediaDeviceInfoFromJson(json); + + /// @nodoc + Map toJson() => _$MediaDeviceInfoToJson(this); +} + +/// +/// Screen sharing configurations. +/// +/// +@JsonSerializable(explicitToJson: true) +class ScreenCaptureParameters { + @JsonKey(includeIfNull: false) + + /// + /// The maximum dimensions of encoding the shared region. + /// If the screen dimensions are different from the value of this parameter, Agora applies the following strategies for encoding. Suppose dimensions are set to 1,920 x 1,080: + /// If the value of the screen dimensions is lower than that of dimensions, for example, 1,000 x 1,000 pixels, the SDK uses 1,000 x 1,000 pixels + /// for encoding. + /// If the value of the screen dimensions is larger than that of dimensions, for example, 2,000 × 1,500, the SDK uses + /// the maximum value next to 1,920 × 1,080 with the aspect ratio of the screen dimension (4:3) for encoding, that is, 1,440 × 1,080. + /// + /// + /// + VideoDimensions? dimensions; + + @JsonKey(includeIfNull: false) + + /// + /// The frame rate (fps) of the shared region. The default value is 5. Agora does not recommend setting it to a value greater than 15. + /// + int? frameRate; + + @JsonKey(includeIfNull: false) + + /// + /// The bitrate (Kbps) of the shared region. The default value is 0, which represents that the SDK works out a bitrate according to the dimensions of the current screen. + /// + int? bitrate; + + @JsonKey(includeIfNull: false) + bool? captureMouseCursor; + + @JsonKey(includeIfNull: false) + bool? windowFocus; + + @JsonKey(includeIfNull: false) + List? excludeWindowList; + + /// Constructs a [ScreenCaptureParameters] + ScreenCaptureParameters({ + this.dimensions, + this.frameRate, + this.bitrate, + this.captureMouseCursor, + this.windowFocus, + this.excludeWindowList, + }); + + /// @nodoc + factory ScreenCaptureParameters.fromJson(Map json) => + _$ScreenCaptureParametersFromJson(json); + + /// @nodoc + Map toJson() => _$ScreenCaptureParametersToJson(this); +} + +/// +/// Media metadata +/// +/// +@JsonSerializable(explicitToJson: true) +class Metadata { + /// + /// User ID. + /// For the receiver: The user ID of the user who sent the Metadata. + /// For the sender: Ignore this value. + /// + /// + /// + int uid; + + @JsonKey(ignore: true) + + /// + /// The buffer address of the sent or received Metadata. + /// + Uint8List? buffer; + + /// + /// The timestamp (ms) of the Metadata. + /// + int timeStampMs; + + /// Constructs a [Metadata] + Metadata(this.uid, this.timeStampMs); + + /// @nodoc + factory Metadata.fromJson(Map json) => + _$MetadataFromJson(json); + + /// @nodoc + Map toJson() => _$MetadataToJson(this); +} + +/* class-MediaRecorderConfiguration */ +@JsonSerializable(explicitToJson: true) +class MediaRecorderConfiguration { + String storagePath; + AgoraMediaRecorderContainerFormat containerFormat; // = CONTAINER_MP4; + AgoraMediaRecorderStreamType streamType; // = STREAM_TYPE_BOTH; + int maxDurationMs; // = 120000; + int recorderInfoUpdateInterval; // = 0; + + /// Constructs a [MediaRecorderConfiguration] + MediaRecorderConfiguration( + this.storagePath, + this.containerFormat, + this.streamType, + this.maxDurationMs, + this.recorderInfoUpdateInterval, + ); + + /// @nodoc + factory MediaRecorderConfiguration.fromJson(Map json) => + _$MediaRecorderConfigurationFromJson(json); + + /// @nodoc + Map toJson() => _$MediaRecorderConfigurationToJson(this); +} + +/* class-RecorderInfo */ +@JsonSerializable(explicitToJson: true) +class RecorderInfo { + String fileName; + int durationMs; + int fileSize; + + /// Constructs a [RecorderInfo] + RecorderInfo(this.fileName, this.durationMs, this.fileSize); + + /// @nodoc + factory RecorderInfo.fromJson(Map json) => + _$RecorderInfoFromJson(json); + + /// @nodoc + Map toJson() => _$RecorderInfoToJson(this); +} diff --git a/lib/src/classes.g.dart b/lib/src/classes.g.dart index 69a6f426f..27900cdd8 100644 --- a/lib/src/classes.g.dart +++ b/lib/src/classes.g.dart @@ -240,6 +240,8 @@ LiveTranscoding _$LiveTranscodingFromJson(Map json) => _$VideoCodecProfileTypeEnumMap, json['videoCodecProfile']), backgroundColor: _$ColorFromJson(json['backgroundColor'] as Map), + videoCodecType: $enumDecodeNullable( + _$VideoCodecTypeForStreamEnumMap, json['videoCodecType']), userConfigExtraInfo: json['userConfigExtraInfo'] as String?, ); @@ -270,6 +272,8 @@ Map _$LiveTranscodingToJson(LiveTranscoding instance) { writeNotNull('videoCodecProfile', _$VideoCodecProfileTypeEnumMap[instance.videoCodecProfile]); writeNotNull('backgroundColor', _$ColorToJson(instance.backgroundColor)); + writeNotNull('videoCodecType', + _$VideoCodecTypeForStreamEnumMap[instance.videoCodecType]); writeNotNull('userConfigExtraInfo', instance.userConfigExtraInfo); val['transcodingUsers'] = instance.transcodingUsers.map((e) => e.toJson()).toList(); @@ -293,6 +297,11 @@ const _$VideoCodecProfileTypeEnumMap = { VideoCodecProfileType.High: 100, }; +const _$VideoCodecTypeForStreamEnumMap = { + VideoCodecTypeForStream.H264: 1, + VideoCodecTypeForStream.H265: 2, +}; + ChannelMediaInfo _$ChannelMediaInfoFromJson(Map json) => ChannelMediaInfo( json['channelName'] as String, @@ -614,6 +623,10 @@ Map _$AudioVolumeInfoToJson(AudioVolumeInfo instance) => }; Rect _$RectFromJson(Map json) => Rect( + x: json['x'] as int? ?? 0, + y: json['y'] as int? ?? 0, + width: json['width'] as int? ?? 0, + height: json['height'] as int? ?? 0, left: json['left'] as int?, top: json['top'] as int?, right: json['right'] as int?, @@ -633,6 +646,10 @@ Map _$RectToJson(Rect instance) { writeNotNull('top', instance.top); writeNotNull('right', instance.right); writeNotNull('bottom', instance.bottom); + val['x'] = instance.x; + val['y'] = instance.y; + val['width'] = instance.width; + val['height'] = instance.height; return val; } @@ -977,7 +994,7 @@ const _$AreaCodeEnumMap = { AreaCode.AS: 8, AreaCode.JP: 16, AreaCode.IN: 32, - AreaCode.GLOB: -1, + AreaCode.GLOB: 4294967295, }; RtcEngineContext _$RtcEngineContextFromJson(Map json) => @@ -1155,3 +1172,105 @@ Map _$EchoTestConfigurationToJson( writeNotNull('channelId', instance.channelId); return val; } + +MediaDeviceInfo _$MediaDeviceInfoFromJson(Map json) => + MediaDeviceInfo( + json['deviceId'] as String, + json['deviceName'] as String, + ); + +Map _$MediaDeviceInfoToJson(MediaDeviceInfo instance) => + { + 'deviceId': instance.deviceId, + 'deviceName': instance.deviceName, + }; + +ScreenCaptureParameters _$ScreenCaptureParametersFromJson( + Map json) => + ScreenCaptureParameters( + dimensions: json['dimensions'] == null + ? null + : VideoDimensions.fromJson( + json['dimensions'] as Map), + frameRate: json['frameRate'] as int?, + bitrate: json['bitrate'] as int?, + captureMouseCursor: json['captureMouseCursor'] as bool?, + windowFocus: json['windowFocus'] as bool?, + excludeWindowList: (json['excludeWindowList'] as List?) + ?.map((e) => e as int) + .toList(), + ); + +Map _$ScreenCaptureParametersToJson( + ScreenCaptureParameters instance) { + final val = {}; + + void writeNotNull(String key, dynamic value) { + if (value != null) { + val[key] = value; + } + } + + writeNotNull('dimensions', instance.dimensions?.toJson()); + writeNotNull('frameRate', instance.frameRate); + writeNotNull('bitrate', instance.bitrate); + writeNotNull('captureMouseCursor', instance.captureMouseCursor); + writeNotNull('windowFocus', instance.windowFocus); + writeNotNull('excludeWindowList', instance.excludeWindowList); + return val; +} + +Metadata _$MetadataFromJson(Map json) => Metadata( + json['uid'] as int, + json['timeStampMs'] as int, + ); + +Map _$MetadataToJson(Metadata instance) => { + 'uid': instance.uid, + 'timeStampMs': instance.timeStampMs, + }; + +MediaRecorderConfiguration _$MediaRecorderConfigurationFromJson( + Map json) => + MediaRecorderConfiguration( + json['storagePath'] as String, + $enumDecode( + _$AgoraMediaRecorderContainerFormatEnumMap, json['containerFormat']), + $enumDecode(_$AgoraMediaRecorderStreamTypeEnumMap, json['streamType']), + json['maxDurationMs'] as int, + json['recorderInfoUpdateInterval'] as int, + ); + +Map _$MediaRecorderConfigurationToJson( + MediaRecorderConfiguration instance) => + { + 'storagePath': instance.storagePath, + 'containerFormat': + _$AgoraMediaRecorderContainerFormatEnumMap[instance.containerFormat], + 'streamType': _$AgoraMediaRecorderStreamTypeEnumMap[instance.streamType], + 'maxDurationMs': instance.maxDurationMs, + 'recorderInfoUpdateInterval': instance.recorderInfoUpdateInterval, + }; + +const _$AgoraMediaRecorderContainerFormatEnumMap = { + AgoraMediaRecorderContainerFormat.MP4: 1, +}; + +const _$AgoraMediaRecorderStreamTypeEnumMap = { + AgoraMediaRecorderStreamType.Audio: 1, + AgoraMediaRecorderStreamType.Video: 2, + AgoraMediaRecorderStreamType.Both: 3, +}; + +RecorderInfo _$RecorderInfoFromJson(Map json) => RecorderInfo( + json['fileName'] as String, + json['durationMs'] as int, + json['fileSize'] as int, + ); + +Map _$RecorderInfoToJson(RecorderInfo instance) => + { + 'fileName': instance.fileName, + 'durationMs': instance.durationMs, + 'fileSize': instance.fileSize, + }; diff --git a/lib/src/enum_converter.dart b/lib/src/enum_converter.dart index 3982dce3d..3c715ca80 100644 --- a/lib/src/enum_converter.dart +++ b/lib/src/enum_converter.dart @@ -11,7 +11,7 @@ abstract class EnumConverter { EnumConverter(this.e); - EnumConverter.fromValue(Map map, T t) : e = $enumDecode(map, t); + EnumConverter.fromValue(Map map, T t) : e = $enumDecode(map, t); T toValue(Map map) { return map[e] as T; @@ -887,6 +887,31 @@ class UploadErrorReasonConverter extends EnumConverter { } } +@JsonSerializable() +class MediaDeviceTypeConverter extends EnumConverter { + MediaDeviceTypeConverter(MediaDeviceType e) : super(e); + + MediaDeviceTypeConverter.fromValue(int value) + : super.fromValue(_$MediaDeviceTypeEnumMap, value); + + int value() { + return super.toValue(_$MediaDeviceTypeEnumMap); + } +} + +@JsonSerializable() +class MediaDeviceStateTypeConverter + extends EnumConverter { + MediaDeviceStateTypeConverter(MediaDeviceStateType e) : super(e); + + MediaDeviceStateTypeConverter.fromValue(int value) + : super.fromValue(_$MediaDeviceStateTypeEnumMap, value); + + int value() { + return super.toValue(_$MediaDeviceStateTypeEnumMap); + } +} + @JsonSerializable() class CloudProxyTypeConverter extends EnumConverter { CloudProxyTypeConverter(CloudProxyType e) : super(e); @@ -980,3 +1005,15 @@ class VirtualBackgroundSourceStateReasonConverter return super.toValue(_$VirtualBackgroundSourceStateReasonEnumMap); } } + +@JsonSerializable() +class VideoContentHintConverter extends EnumConverter { + VideoContentHintConverter(VideoContentHint e) : super(e); + + VideoContentHintConverter.fromValue(int value) + : super.fromValue(_$VideoContentHintEnumMap, value); + + int value() { + return super.toValue(_$VideoContentHintEnumMap); + } +} diff --git a/lib/src/enum_converter.g.dart b/lib/src/enum_converter.g.dart index 54947ebb7..dafb7f5dc 100644 --- a/lib/src/enum_converter.g.dart +++ b/lib/src/enum_converter.g.dart @@ -23,7 +23,7 @@ const _$AreaCodeEnumMap = { AreaCode.AS: 8, AreaCode.JP: 16, AreaCode.IN: 32, - AreaCode.GLOB: -1, + AreaCode.GLOB: 4294967295, }; AudioCodecProfileTypeConverter _$AudioCodecProfileTypeConverterFromJson( @@ -212,6 +212,9 @@ const _$AudioOutputRoutingEnumMap = { AudioOutputRouting.Speakerphone: 3, AudioOutputRouting.Loudspeaker: 4, AudioOutputRouting.HeadsetBluetooth: 5, + AudioOutputRouting.USB: 6, + AudioOutputRouting.HDMI: 7, + AudioOutputRouting.DisplayPort: 8, AudioOutputRouting.AirPlay: 9, }; @@ -345,6 +348,8 @@ const _$AudioReverbPresetEnumMap = { AudioReverbPreset.FX_RNB: 1048583, AudioReverbPreset.FX_PHONOGRAPH: 1048584, AudioReverbPreset.VIRTUAL_STEREO: 2097153, + AudioReverbPreset.AUDIO_ELECTRONIC_VOICE: 3145729, + AudioReverbPreset.AUDIO_THREEDIM_VOICE: 4194305, }; AudioReverbTypeConverter _$AudioReverbTypeConverterFromJson( @@ -859,6 +864,12 @@ const _$LocalVideoStreamErrorEnumMap = { LocalVideoStreamError.CaptureInBackground: 6, LocalVideoStreamError.CaptureMultipleForegroundApps: 7, LocalVideoStreamError.DeviceNotFound: 8, + LocalVideoStreamError.ScreenCaptureWindowMinmized: 11, + LocalVideoStreamError.ScreenCaptureWindowClosed: 12, + LocalVideoStreamError.LocalVideoStreamErrorDeviceInvalidId: 10, + LocalVideoStreamError.LocalVideoStreamErrorScreenCaptureWindowOccluded: 13, + LocalVideoStreamError.LocalVideoStreamErrorScreenCaptureWindowNotSupported: + 20, }; LocalVideoStreamStateConverter _$LocalVideoStreamStateConverterFromJson( @@ -1553,6 +1564,48 @@ const _$UploadErrorReasonEnumMap = { UploadErrorReason.ServerError: 2, }; +MediaDeviceTypeConverter _$MediaDeviceTypeConverterFromJson( + Map json) => + MediaDeviceTypeConverter( + $enumDecode(_$MediaDeviceTypeEnumMap, json['e']), + ); + +Map _$MediaDeviceTypeConverterToJson( + MediaDeviceTypeConverter instance) => + { + 'e': _$MediaDeviceTypeEnumMap[instance.e], + }; + +const _$MediaDeviceTypeEnumMap = { + MediaDeviceType.UnknownAudioDevice: -1, + MediaDeviceType.AudioPlayoutDevice: 0, + MediaDeviceType.AudioRecordingDevice: 1, + MediaDeviceType.VideoRenderDevice: 2, + MediaDeviceType.VideoCaptureDevice: 3, + MediaDeviceType.AudioApplicationPlayoutDevice: 4, +}; + +MediaDeviceStateTypeConverter _$MediaDeviceStateTypeConverterFromJson( + Map json) => + MediaDeviceStateTypeConverter( + $enumDecode(_$MediaDeviceStateTypeEnumMap, json['e']), + ); + +Map _$MediaDeviceStateTypeConverterToJson( + MediaDeviceStateTypeConverter instance) => + { + 'e': _$MediaDeviceStateTypeEnumMap[instance.e], + }; + +const _$MediaDeviceStateTypeEnumMap = { + MediaDeviceStateType.MediaDeviceStateIdle: 0, + MediaDeviceStateType.MediaDeviceStateActive: 1, + MediaDeviceStateType.MediaDeviceStateDisabled: 2, + MediaDeviceStateType.MediaDeviceStateNotPresent: 4, + MediaDeviceStateType.MediaDeviceStateUnplugged: 8, + MediaDeviceStateType.MediaDeviceStateUnrecommended: 16, +}; + CloudProxyTypeConverter _$CloudProxyTypeConverterFromJson( Map json) => CloudProxyTypeConverter( @@ -1683,3 +1736,21 @@ const _$VirtualBackgroundSourceStateReasonEnumMap = { VirtualBackgroundSourceStateReason.ColorFormatNotSupported: 2, VirtualBackgroundSourceStateReason.DeviceNotSupported: 3, }; + +VideoContentHintConverter _$VideoContentHintConverterFromJson( + Map json) => + VideoContentHintConverter( + $enumDecode(_$VideoContentHintEnumMap, json['e']), + ); + +Map _$VideoContentHintConverterToJson( + VideoContentHintConverter instance) => + { + 'e': _$VideoContentHintEnumMap[instance.e], + }; + +const _$VideoContentHintEnumMap = { + VideoContentHint.None: 0, + VideoContentHint.Motion: 1, + VideoContentHint.Details: 2, +}; diff --git a/lib/src/enums.dart b/lib/src/enums.dart index c07840bc9..7fb79bd93 100644 --- a/lib/src/enums.dart +++ b/lib/src/enums.dart @@ -1,2656 +1,3685 @@ import 'package:json_annotation/json_annotation.dart'; -/// The area of connection. +/// +/// The region for connection, which is the region where +/// the server the SDK connects to is located. +/// +/// enum AreaCode { - /// Mainland China @JsonValue(0x00000001) + /// + /// Mainland China. + /// CN, - /// North America @JsonValue(0x00000002) + /// + /// North America. + /// NA, - /// Europe @JsonValue(0x00000004) + /// + /// Europe. + /// EU, - /// Asia, excluding Mainland China @JsonValue(0x00000008) + /// + /// Asia, excluding Mainland China. + /// AS, - /// Japan @JsonValue(0x00000010) + /// + /// Japan. + /// JP, - /// India @JsonValue(0x00000020) + /// + /// India. + /// IN, - /// (Default) Global - @JsonValue(-1) + @JsonValue(0xffffffff) + /// + /// (Default) Global. + /// GLOB, } -/// Self-defined audio codec profile. +/// +/// The codec type of the output audio stream for CDN live +/// streaming. The default value is LC-ACC. +/// +/// enum AudioCodecProfileType { - /// (Default) LCAAC, which is the low-complexity audio codec profile. @JsonValue(0) + /// + /// 0: (Default) LC-AAC, which is the low-complexity audio codec type. + /// LCAAC, - /// HEAAC, which is the high-efficiency audio codec profile. @JsonValue(1) + /// + /// 1: HE-AAC, which is the high-efficiency audio codec type. + /// HEAAC, } -/// Audio equalization band frequency. +/// +/// The midrange frequency for audio equalization. +/// +/// enum AudioEqualizationBandFrequency { - /// 31 Hz. @JsonValue(0) + /// + /// 0: 31 Hz + /// Band31, - /// 62 Hz. @JsonValue(1) + /// + /// 1: 62 Hz + /// Band62, - /// 125 Hz. @JsonValue(2) + /// + /// 2: 125 Hz + /// Band125, - /// 250 Hz. @JsonValue(3) + /// + /// 3: 250 Hz + /// Band250, - /// 500 Hz. @JsonValue(4) + /// + /// 4: 500 Hz + /// Band500, - /// 1 kHz. @JsonValue(5) + /// + /// 5: 1 kHz + /// Band1K, - /// 2 kHz. @JsonValue(6) + /// + /// 6: 2 kHz + /// Band2K, - /// 4 kHz. @JsonValue(7) + /// + /// 7: 4 kHz + /// Band4K, - /// 8 kHz. @JsonValue(8) + /// + /// 8: 8 kHz + /// Band8K, - /// 16 kHz. @JsonValue(9) + /// + /// 9: 16 kHz + /// Band16K, } -/// The error information of the local audio. +/// +/// Local audio state error codes. +/// +/// enum AudioLocalError { - /// The local audio is normal. @JsonValue(0) + /// + /// 0: The local audio is normal. + /// Ok, - /// No specified reason for the local audio failure. @JsonValue(1) + /// + /// 1: No specified reason for the local audio failure. + /// Failure, - /// No permission to use the local audio device. @JsonValue(2) + /// + /// 2: No permission to use the local audio device. + /// DeviceNoPermission, - /// The microphone is in use. @JsonValue(3) + /// + /// 3: The microphone is in use. + /// DeviceBusy, - /// The local audio recording fails. Check whether the recording device is working properly. @JsonValue(4) + /// + /// 4: The local audio capturing fails. Check whether the capturing device is working properly. + /// RecordFailure, - /// The local audio encoding fails. @JsonValue(5) + /// + /// 5: The local audio encoding fails. + /// EncodeFailure, - /// The local audio capturing is interrupted by the system call. @JsonValue(8) Interrupted, } -/// The state of the local audio. +/// +/// Local audio states. +/// +/// enum AudioLocalState { - /// The local audio is in the initial state. @JsonValue(0) + /// + /// 0: The local audio is in the initial state. + /// Stopped, - /// The recording device starts successfully. @JsonValue(1) + /// + /// 1: The capturing device starts successfully. + /// Recording, - /// The first audio frame encodes successfully. @JsonValue(2) + /// + /// 2: The first audio frame encodes successfully. + /// Encoding, - /// The local audio fails to start. @JsonValue(3) + /// + /// 3: The local audio fails to start. + /// Failed, } -/// The information acquisition state +/// +/// The information acquisition state. This enum is reported in requestAudioFileInfoCallback. +/// +/// enum AudioFileInfoError { - /// Successfully get the information of an audio file. @JsonValue(0) + /// + /// 0: Successfully get the information of an audio file. + /// Ok, - /// Fail to get the information of an audio file. @JsonValue(1) + /// + /// 1: Fail to get the information of an audio file. + /// Failure, } -/// The reason for the change of the music file playback state, reported in the [RtcEngineEventHandler.audioMixingStateChanged]. +/// +/// Errors that might occur when playing a music +/// file. +/// +/// +@Deprecated('This enum is deprecated, pls use AudioMixingReason instead.') +enum AudioMixingErrorType { + @JsonValue(701) + /// + /// The SDK cannot open the music file. + /// + CanNotOpen, + + @JsonValue(702) + /// + /// The SDK opens the music file too frequently. + /// + TooFrequentCall, + + @JsonValue(702) + /// + /// The playback of the music file is interrupted. + /// + InterruptedEOF, + + @JsonValue(0) + /// + /// The music file is playing. + /// + OK, +} + +/// +/// The reason why the playback state of the music file changes. Reported in the audioMixingStateChanged callback. +/// +/// enum AudioMixingReason { - /// The SDK cannot open the music file. Possible causes include the local music file does not exist, the SDK does not support the file format, or the SDK cannot access the music file URL. @JsonValue(701) + /// + /// 701: The SDK cannot open the music file. For example, the local music file + /// does not exist, the SDK does not support the file format, or the SDK cannot + /// access the music file URL. + /// CanNotOpen, - /// The SDK opens the music file too frequently. If you need to call [RtcEngine.startAudioMixing] multiple times, ensure that the call interval is longer than 500 ms. @JsonValue(702) + /// + /// 702: The SDK opens the music file too frequently. If you need to call startAudioMixing multiple times, ensure that the call interval is more than 500 ms. + /// TooFrequentCall, - /// The music file playback is interrupted. @JsonValue(703) + /// + /// 703: The music file playback is interrupted. + /// InterruptedEOF, - /// Successfully calls `startAudioMixing` to play a music file. @JsonValue(720) + /// + /// 720: The method call of startAudioMixing to play music + /// files succeeds. + /// StartedByUser, - /// The music file completes a loop playback. @JsonValue(721) + /// + /// 721: The music file completes a loop playback. + /// OneLoopCompleted, - /// The music file starts a new loop playback. @JsonValue(722) + /// + /// 722: The music file starts a new loop playback. + /// StartNewLoop, - /// The music file completes all loop playback. @JsonValue(723) + /// + /// 723: The music file completes all loop playbacks. + /// AllLoopsCompleted, - /// Successfully calls `stopAudioMixing` to stop playing the music file. @JsonValue(724) + /// + /// 724: The method call of stopAudioMixing to stop playing the + /// music file succeeds. + /// StoppedByUser, - /// Successfully calls `pauseAudioMixing` to pause playing the music file. @JsonValue(725) + /// + /// 725: The method call of pauseAudioMixing to pause playing + /// the music file succeeds. + /// PausedByUser, - /// Successfully calls `resumeAudioMixing` to resume playing the music file. @JsonValue(726) + /// + /// 726: The method call of resumeAudioMixing to resume playing + /// the music file succeeds. + /// ResumedByUser, - /// No error. @JsonValue(0) OK, } -/// The state of the audio mixing file. +/// +/// The playback state of the music file. +/// +/// enum AudioMixingStateCode { - /// The music file is playing. This state comes with one of the following associated reasons: - /// - `StartedByuser(720)` - /// - `LoopCompleted(721)` - /// - `NewLoop(722)` - /// - `ResumedByUser(726)` @JsonValue(710) + /// + /// 710: The music file is playing. + /// + /// Playing, - /// The music file pauses playing. This state comes with `PausedByUser(725)` @JsonValue(711) + /// + /// 711: The music file pauses playing. + /// + /// Paused, - /// Ignore this state. @JsonValue(712) Restart, - /// The music file stops playing. This state comes with one of the following associated reasons: - /// - `AllLoopsCompleted(723)` - /// - `StoppedByUser(724)` @JsonValue(713) + /// + /// 713: The music file stops playing. + /// + /// Stopped, - /// An exception occurs during the playback of the music file. This state comes with one of the following associated reasons: - /// - `CanNotOpen(701)` - /// - `TooFrequentCall(702)` - /// - `InterruptedEOF(703)` @JsonValue(714) + /// + /// 714: An error occurs during the playback of the audio mixing file. + /// + /// Failed, } -/// The channel mode. Set in [setAudioMixingDualMonoMode]. +/// +/// The channel mode. Set in setAudioMixingDualMonoMode. +/// +/// enum AudioMixingDualMonoMode { - /// 0: Original mode. @JsonValue(0) + /// + /// 0: Original mode. + /// Auto, - /// 1: Left channel mode. This mode replaces the audio of the right channel - /// with the audio of the left channel, which means the user can only hear the - /// audio of the left channel. @JsonValue(1) + /// + /// 1: Left channel mode. This mode replaces the audio of the right channel with the audio of the left channel, which means the user can only hear the audio of the left channel. + /// L, - /// 2: Right channel mode. This mode replaces the audio of the left channel - /// with the audio of the right channel, which means the user can only hear the - /// audio of the right channel. @JsonValue(2) + /// + /// 2: Right channel mode. This mode replaces the audio of the left channel with the audio of the right channel, which means the user can only hear the audio of the right channel. + /// R, - /// 3: Mixed channel mode. This mode mixes the audio of the left channel and the - /// right channel, which means the user can hear the audio of the left channel - /// and the right channel at the same time. @JsonValue(3) + /// + /// 3: Mixed channel mode. This mode mixes the audio of the left channel and the right channel, which means the user can hear the audio of the left channel and the right channel at the same time. + /// MIX, } -/// Audio output routing. +/// +/// The type of the audio route. +/// +/// enum AudioOutputRouting { - /// Default. @JsonValue(-1) + /// + /// -1: The default audio route. + /// Default, - /// Headset. @JsonValue(0) + /// + /// 0: The headset. + /// Headset, - /// Earpiece. @JsonValue(1) + /// + /// 1: The earpiece. + /// Earpiece, - /// Headset with no microphone. @JsonValue(2) + /// + /// 2: The headset with no microphone. + /// HeadsetNoMic, - /// Speakerphone. @JsonValue(3) + /// + /// 3: The built-in speaker on a mobile device. + /// Speakerphone, - /// Loudspeaker. @JsonValue(4) + /// + /// 4: The external speaker. + /// Loudspeaker, - /// Bluetooth headset. @JsonValue(5) + /// + /// 5: The bluetooth headset. + /// HeadsetBluetooth, - /// Apple AirPlay. + @JsonValue(6) + USB, + + @JsonValue(7) + HDMI, + + @JsonValue(8) + DisplayPort, + @JsonValue(9) AirPlay, } -/// Audio profile. +/// +/// The audio profile. +/// +/// enum AudioProfile { - /// Default audio profile. - /// - In the [ChannelProfile.Communication] profile: A sample rate of 32 KHz, audio encoding, mono, and a bitrate of up to 18 Kbps. - /// - In the [ChannelProfile.LiveBroadcasting] profile: A sample rate of 48 KHz, audio encoding, mono, and a bitrate of up to 64 Kbps. @JsonValue(0) + /// + /// 0: The default audio profile. + /// For the LIVE_BROADCASTING profile: A sampling rate of 48 kHz, music encoding, mono, and a bitrate of up to 64 Kbps. + /// For the COMMUNICATION profile: + /// + /// + /// + /// Default, - /// A sample rate of 32 KHz, audio encoding, mono, and a bitrate of up to 18 Kbps. @JsonValue(1) + /// + /// 1: A sampling rate of 32 kHz, audio encoding, mono, and a bitrate of up to 18 Kbps. + /// SpeechStandard, - /// A sample rate of 48 KHz, music encoding, mono, and a bitrate of up to 64 Kbps. @JsonValue(2) + /// + /// 2: A sampling rate of 48 kHz, music encoding, mono, and a bitrate of up to 64 Kbps. + /// MusicStandard, - /// A sample rate of 48 KHz, music encoding, stereo, and a bitrate of up to 80 Kbps. @JsonValue(3) + /// + /// 3: A sampling rate of 48 kHz, music encoding, stereo, and a bitrate of up to 80 Kbps. + /// MusicStandardStereo, - /// A sample rate of 48 KHz, music encoding, mono, and a bitrate of up to 96 Kbps. @JsonValue(4) + /// + /// 4: A sampling rate of 48 kHz, music encoding, mono, and a bitrate of up to 96 Kbps. + /// MusicHighQuality, - /// A sample rate of 48 KHz, music encoding, stereo, and a bitrate of up to 128 Kbps. @JsonValue(5) + /// + /// 5: A sampling rate of 48 kHz, music encoding, stereo, and a bitrate of up to 128 Kbps. + /// MusicHighQualityStereo, } -/// Audio recording quality, which is set in [RtcEngine.startAudioRecording]. +/// +/// Recording quality. +/// +/// enum AudioRecordingQuality { - /// Low quality. For example, the size of an AAC file with a sample rate of 32,000 Hz and a 10-minute recording is approximately 1.2 MB. @JsonValue(0) + /// + /// 0: Low quality. The sample rate is 32 kHz, and the file size is around 1.2 MB for 10 minutes + /// of recording. + /// Low, - /// (Default) Medium quality. For example, the size of an AAC file with a sample rate of 32,000 Hz and a 10-minute recording is approximately 2 MB. @JsonValue(1) + /// + /// 1: Medium quality. The sample rate is 32 kHz, and the file size is around 2 MB for 10 minutes + /// of recording. + /// Medium, - /// High quality. For example, the size of an AAC file with a sample rate of 32,000 Hz and a 10-minute recording is approximately 3.75 MB. @JsonValue(2) + /// + /// 2: High quality. The sample rate is 32 kHz, and the file size is around 3.75 MB for 10 minutes + /// of recording. + /// High, } -/// Recording content, which is set in [RtcEngine.startAudioRecording]. +/// +/// Recording content. Set in startAudioRecordingWithConfig. +/// +/// enum AudioRecordingPosition { - /// 0: (Default) Records the mixed audio of the local user and all remote users. @JsonValue(0) + /// + /// 0: (Default) Records the mixed audio of the local and all remote users. + /// PositionMixedRecordingAndPlayback, - /// 1: Records the audio of the local user only. @JsonValue(1) + /// + /// 1: Only records the audio of the local user. + /// PositionRecording, - /// 2: Records the audio of all remote users only. @JsonValue(2) + /// + /// 2: Only records the audio of all remote users. + /// PositionMixedPlayback, } -/// The state of the remote audio. +/// +/// Remote audio states. +/// +/// enum AudioRemoteState { - /// The remote audio is in the default state, probably due to: - /// - [AudioRemoteStateReason.LocalMuted] - /// - [AudioRemoteStateReason.RemoteMuted] - /// - [AudioRemoteStateReason.RemoteOffline] @JsonValue(0) + /// + /// 0: The local audio is in the initial state. The SDK reports this state in the case of LocalMuted, RemoteMuted or RemoteOffline. + /// Stopped, - /// The first remote audio packet is received. @JsonValue(1) + /// + /// 1: The first remote audio packet is received. + /// Starting, - /// The remote audio stream is decoded and plays normally, probably due to: - /// - [AudioRemoteStateReason.NetworkRecovery] - /// - [AudioRemoteStateReason.LocalUnmuted] - /// - [AudioRemoteStateReason.RemoteUnmuted] @JsonValue(2) + /// + /// 2: The remote audio stream is decoded and plays normally. The SDK reports this state in the case of NetworkRecovery, LocalUnmuted or RemoteUnmuted. + /// Decoding, - /// The remote audio is frozen, probably due to: - /// - [AudioRemoteStateReason.NetworkCongestion] @JsonValue(3) + /// + /// 3: The remote audio is frozen. The SDK reports this state in the case of NetworkCongestion. + /// Frozen, - /// The remote audio fails to start, probably due to: - /// - [AudioRemoteStateReason.Internal] @JsonValue(4) + /// + /// 4: The remote audio fails to start. The SDK reports this state in the case of Internal. + /// Failed, } -/// The reason of the remote audio state change. +/// +/// The reason for the remote audio state change. +/// +/// enum AudioRemoteStateReason { - /// Internal reasons. @JsonValue(0) + /// + /// 0: The SDK reports this reason when the audio state changes. + /// Internal, - /// Network congestion. @JsonValue(1) + /// + /// 1: Network congestion. + /// NetworkCongestion, - /// Network recovery. @JsonValue(2) + /// + /// 2: Network recovery. + /// NetworkRecovery, - /// The local user stops receiving the remote audio stream or disables the audio module. @JsonValue(3) + /// + /// 3: The local user stops receiving the remote audio stream or disables the audio module. + /// LocalMuted, - /// The local user resumes receiving the remote audio stream or enables the audio module. @JsonValue(4) + /// + /// 4: The local user resumes receiving the remote audio stream or enables the audio module. + /// LocalUnmuted, - /// The remote user stops sending the audio stream or disables the audio module. @JsonValue(5) + /// + /// 5: The remote user stops sending the audio stream or disables the audio module. + /// RemoteMuted, - /// The remote user resumes sending the audio stream or enables the audio module. @JsonValue(6) + /// + /// 6: The remote user resumes sending the audio stream or enables the audio module. + /// RemoteUnmuted, - /// The remote user leaves the channel. @JsonValue(7) + /// + /// 7: The remote user leaves the channel. + /// RemoteOffline, } -/// The preset local voice reverberation option. +/// +/// Voice reverb presets. +/// +/// enum AudioReverbPreset { - /// Turn off local voice reverberation, that is, to use the original voice. @JsonValue(0x00000000) + /// + /// Turn off voice reverb, that is, to use the original voice. + /// Off, - /// The reverberation style typical of popular music (enhanced). @JsonValue(0x00000001) Popular, - /// The reverberation style typical of R&B music (enhanced). @JsonValue(0x00000002) RnB, - /// The reverberation style typical of rock music. @JsonValue(0x00000003) Rock, - /// The reverberation style typical of hip-hop music. @JsonValue(0x00000004) HipHop, - /// The reverberation style typical of a concert hall. @JsonValue(0x00000005) VocalConcert, - /// The reverberation style typical of a KTV venue (enhanced). @JsonValue(0x00000006) KTV, - /// The reverberation style typical of a recording studio (enhanced). @JsonValue(0x00000007) Studio, - /// The reverberation style typical of a KTV venue (enhanced). @JsonValue(0x00100001) + /// + /// The reverb style typical of a KTV venue (enhanced). + /// FX_KTV, - /// The reverberation style typical of a concert hall (enhanced). @JsonValue(0x00100002) + /// + /// The reverb style typical of a concert hall (enhanced). + /// FX_VOCAL_CONCERT, - /// The reverberation style typical of an uncle’s voice. @JsonValue(0x00100003) + /// + /// A middle-aged man's voice. + /// FX_UNCLE, - /// The reverberation style typical of a sister’s voice. @JsonValue(0x00100004) + /// + /// The reverb style typical of a young woman's voice. + /// FX_SISTER, - /// The reverberation style typical of a recording studio (enhanced). @JsonValue(0x00100005) + /// + /// The reverb style typical of a recording studio (enhanced). + /// FX_STUDIO, - /// The reverberation style typical of popular music (enhanced). @JsonValue(0x00100006) + /// + /// The reverb style typical of popular music (enhanced). + /// FX_POPULAR, - /// The reverberation style typical of R&B music (enhanced). @JsonValue(0x00100007) + /// + /// The reverb style typical of R&B music (enhanced). + /// FX_RNB, - /// The reverberation style typical of the vintage phonograph. @JsonValue(0x00100008) + /// + /// The voice effect typical of a vintage phonograph. + /// FX_PHONOGRAPH, - /// The reverberation of the virtual stereo. The virtual stereo is an effect that renders the monophonic audio as the stereo audio, so that all users in the channel can hear the stereo voice effect. To achieve better virtual stereo reverberation, Agora recommends setting the `profile` parameter in [RtcEngine.setAudioProfile] as [AudioProfile.MusicHighQualityStereo]. @JsonValue(0x00200001) + /// + /// The reverberation of the virtual stereo. The virtual stereo is an effect that renders the monophonic audio as the stereo audio, so that all users in the channel can hear the stereo voice effect. + /// VIRTUAL_STEREO, + + @JsonValue(0x00300001) + AUDIO_ELECTRONIC_VOICE, + + @JsonValue(0x00400001) + AUDIO_THREEDIM_VOICE, } -/// Audio reverberation type. +/// +/// Audio reverberation types. +/// +/// enum AudioReverbType { - /// Level of the dry signal (-20 to 10 dB). @JsonValue(0) + /// + /// 0: The level of the dry signal (dB). The value is between -20 and 10. + /// DryLevel, - /// Level of the early reflection signal (wet signal) (-20 to 10 dB). @JsonValue(1) + /// + /// 1: The level of the early reflection signal (wet signal) (dB). The value is between -20 and 10. + /// WetLevel, - /// Room size of the reflection (0 to 100 dB). A larger room size means stronger reverberation. @JsonValue(2) + /// + /// 2: The room size of the reflection. The value is between 0 and 100. + /// RoomSize, - /// Length of the initial delay of the wet signal (0 to 200 ms). @JsonValue(3) + /// + /// 3: The length of the initial delay of the wet signal (ms). The value is between 0 and 200. + /// WetDelay, - /// Strength of the late reverberation (0 to 100). @JsonValue(4) + /// + /// 4: The reverberation strength. The value is between 0 and 100. + /// Strength, } -/// Audio sample rate. +/// +/// The audio sampling rate of the stream to be pushed to the CDN. +/// +/// enum AudioSampleRateType { - /// 32 kHz. @JsonValue(32000) + /// + /// 32000: 32 kHz + /// Type32000, - /// 44.1 kHz. @JsonValue(44100) + /// + /// 44100: 44.1 kHz + /// Type44100, - /// 48 kHz. @JsonValue(48000) + /// + /// 48000: (Default) 48 kHz + /// Type48000, } -/// Audio scenario. +/// +/// Audio application scenarios. +/// +/// enum AudioScenario { - /// Default audio application scenario. @JsonValue(0) + /// + /// 0: The default audio scenario. + /// Default, - /// Entertainment scenario supporting voice during gameplay. @JsonValue(1) + /// + /// 1: Entertainment scenario where users need to frequently switch the user role. + /// ChatRoomEntertainment, - /// Education scenario prioritizing smoothness and stability. @JsonValue(2) + /// + /// 2: Education scenario where users want smoothness and stability. + /// Education, - /// Live gaming scenario, enabling the gaming audio effects in the speaker mode in a live broadcast scenario. Choose this scenario for high-fidelity music playback. @JsonValue(3) + /// + /// 3: High-quality audio chatroom scenario where hosts mainly play music. + /// GameStreaming, - /// Showroom scenario, optimizing the audio quality with external professional equipment. @JsonValue(4) + /// + /// 4: Showroom scenario where a single host wants high-quality audio. + /// ShowRoom, - /// Gaming scenario. @JsonValue(5) + /// + /// 5: Gaming scenario for group chat that only contains the human voice. + /// ChatRoomGaming, - /// IoT (Internet of Things) scenario where users use IoT devices with low power consumption. @JsonValue(6) + /// + /// 6: IoT (Internet of Things) scenario where users use IoT devices with low power consumption. + /// IOT, - /// Meeting scenario that mainly contains the human voice. - /// - /// Since v3.2.1 @JsonValue(8) + /// + /// 8: Meeting scenario that mainly contains the human voice. + /// + /// MEETING, } -/// The preset audio voice configuration used to change the voice effect. +/// +/// Local voice changer options. +/// +/// enum AudioVoiceChanger { - /// Turn off the local voice changer, that is, to use the original voice. @JsonValue(0x00000000) + /// + /// The original voice (no local voice change). + /// Off, - /// The voice of an old man. @JsonValue(0x00000001) + /// + /// The voice of an old man. + /// OldMan, - /// The voice of a little boy. @JsonValue(0x00000002) + /// + /// The voice of a little boy. + /// BabyBoy, - /// The voice of a little girl. @JsonValue(0x00000003) + /// + /// The voice of a little girl. + /// BabyGirl, - /// The voice of Zhu Bajie, a character in Journey to the West who has a voice like that of a growling bear. @JsonValue(0x00000004) + /// + /// The voice of Zhu Bajie, a character in Journey to the West who has a voice like that of a growling bear. + /// ZhuBaJie, - /// The ethereal voice. @JsonValue(0x00000005) + /// + /// The ethereal voice. + /// Ethereal, - /// The voice of Hulk. @JsonValue(0x00000006) + /// + /// The voice of Hulk. + /// Hulk, - /// A more vigorous voice. @JsonValue(0x00100001) + /// + /// A more vigorous voice. + /// BEAUTY_VIGOROUS, - /// A deeper voice. @JsonValue(0x00100002) + /// + /// A deeper voice. + /// BEAUTY_DEEP, - /// A mellower voice. @JsonValue(0x00100003) + /// + /// A mellower voice. + /// BEAUTY_MELLOW, - /// Falsetto. @JsonValue(0x00100004) + /// + /// Falsetto. + /// BEAUTY_FALSETTO, - /// A fuller voice. @JsonValue(0x00100005) + /// + /// A fuller voice. + /// BEAUTY_FULL, - /// A clearer voice. @JsonValue(0x00100006) + /// + /// A clearer voice. + /// BEAUTY_CLEAR, - /// A more resounding voice. @JsonValue(0x00100007) + /// + /// A more resounding voice. + /// BEAUTY_RESOUNDING, - /// A more ringing voice. @JsonValue(0x00100008) + /// + /// A more ringing voice. + /// BEAUTY_RINGING, - /// A more spatially resonant voice. @JsonValue(0x00100009) + /// + /// A more spatially resonant voice. + /// BEAUTY_SPACIAL, - /// (For male only) A more magnetic voice. Do not use it when the speaker is a female; otherwise, voice distortion occurs. @JsonValue(0x00200001) + /// + /// (For male only) A more magnetic voice. Do not use it when the speaker is a female; otherwise, voice distortion occurs. + /// GENERAL_BEAUTY_VOICE_MALE_MAGNETIC, - /// (For female only) A fresher voice. Do not use it when the speaker is a male; otherwise, voice distortion occurs. @JsonValue(0x00200002) + /// + /// (For female only) A fresher voice. Do not use it when the speaker is a male; otherwise, voice distortion occurs. + /// GENERAL_BEAUTY_VOICE_FEMALE_FRESH, - /// (For female only) A more vital voice. Do not use it when the speaker is a male; otherwise, voice distortion occurs. @JsonValue(0x00200003) + /// + /// (For female only) A more vital voice. Do not use it when the speaker is a male; otherwise, voice distortion occurs. + /// GENERAL_BEAUTY_VOICE_FEMALE_VITALITY, } -/// The camera capture configuration. +/// +/// Camera capture preference. +/// +/// enum CameraCaptureOutputPreference { - /// (default) Self-adapts the camera output parameters to the system performance and network conditions to balance CPU consumption and video preview quality. @JsonValue(0) + /// + /// 0: (Default) Automatically adjust the camera capture preference. The SDK adjusts the camera output parameters according to the system performance and network conditions to balance CPU consumption and video preview quality. + /// Auto, - /// Prioritizes the system performance. The SDK chooses the dimension and frame rate of the local camera capture closest to those set by [RtcEngine.setVideoEncoderConfiguration]. @JsonValue(1) + /// + /// 1: Prioritizes the system performance. The SDK chooses the dimension and frame rate of the local camera capture closest to those set by setVideoEncoderConfiguration. In this case, the local preview quality depends on the encoder. + /// Performance, - /// Prioritizes the local preview quality. The SDK chooses higher camera output parameters to improve the local video preview quality. This option requires extra CPU and RAM usage for video pre-processing. @JsonValue(2) + /// + /// 2: Prioritizes the local preview quality. The SDK chooses higher camera output parameters to improve the local video preview quality. This option requires extra CPU and RAM usage for video pre-processing. + /// Preview, - /// Capture Dimensions determined by user. @JsonValue(3) + /// + /// 3: Allows you to customize the width and height of the video image captured by the local camera. + /// + /// Manual, } +/// /// The camera direction. +/// +/// enum CameraDirection { - /// The rear camera. @JsonValue(0) + /// + /// The rear camera. + /// Rear, - /// The front camera. @JsonValue(1) + /// + /// The front camera. + /// Front, } -/// The error code in of channel media relay. +/// +/// The error code of the channel media replay. +/// +/// enum ChannelMediaRelayError { - /// The state is normal. @JsonValue(0) + /// + /// 0: No error. + /// None, - /// An error occurs in the server response. @JsonValue(1) + /// + /// 1: An error occurs in the server response. + /// ServerErrorResponse, - /// No server response. You can call the [RtcEngine.leaveChannel] method to leave the channel. @JsonValue(2) + /// + /// 2: No server response. + /// You can call leaveChannel to leave the channel. + /// This error can also occur if your project has not enabled co-host token authentication. Contact support@agora.io to enable the co-host token authentication service before starting a channel media relay. + /// + /// ServerNoResponse, - /// The SDK fails to access the service, probably due to limited resources of the server. @JsonValue(3) + /// + /// 3: The SDK fails to access the service, probably due to limited resources of the server. + /// NoResourceAvailable, - /// Fails to send the relay request. @JsonValue(4) + /// + /// 4: Fails to send the relay request. + /// FailedJoinSourceChannel, - /// Fails to accept the relay request. @JsonValue(5) + /// + /// 5: Fails to accept the relay request. + /// FailedJoinDestinationChannel, - /// The server fails to receive the media stream. @JsonValue(6) + /// + /// 6: The server fails to receive the media stream. + /// FailedPacketReceivedFromSource, - /// The server fails to send the media stream. @JsonValue(7) + /// + /// 7: The server fails to send the media stream. + /// FailedPacketSentToDestination, - /// The SDK disconnects from the server due to poor network connections. You can call the [RtcEngine.leaveChannel] method to leave the channel. @JsonValue(8) + /// + /// 8: The SDK disconnects from the server due to poor network connections. You can call the leaveChannel method to leave the channel. + /// ServerConnectionLost, - /// An internal error occurs in the server. @JsonValue(9) + /// + /// 9: An internal error occurs in the server. + /// InternalError, - /// The token of the source channel has expired. @JsonValue(10) + /// + /// 10: The token of the source channel has expired. + /// SourceTokenExpired, - /// The token of the destination channel has expired. @JsonValue(11) + /// + /// 11: The token of the destination channel has expired. + /// DestinationTokenExpired, } -/// The event code in of channel media relay event. +/// +/// The event code of channel media relay. +/// +/// enum ChannelMediaRelayEvent { - /// The user disconnects from the server due to poor network connections. @JsonValue(0) + /// + /// 0: The user disconnects from the server due to a poor network connection. + /// Disconnect, - /// The user connects to the server. @JsonValue(1) + /// + /// 1: The user is connected to the server. + /// Connected, - /// The user joins the source channel. @JsonValue(2) + /// + /// 2: The user joins the source channel. + /// JoinedSourceChannel, - /// The user joins the destination channel. @JsonValue(3) + /// + /// 3: The user joins the destination channel. + /// JoinedDestinationChannel, - /// The SDK starts relaying the media stream to the destination channel. @JsonValue(4) + /// + /// 4: The SDK starts relaying the media stream to the destination channel. + /// SentToDestinationChannel, - /// The server receives the video stream from the source channel. @JsonValue(5) + /// + /// 5: The server receives the audio stream from the source channel. + /// ReceivedVideoPacketFromSource, - /// The server receives the audio stream from the source channel. @JsonValue(6) + /// + /// 6: The server receives the audio stream from the source channel. + /// ReceivedAudioPacketFromSource, - /// The destination channel is updated. @JsonValue(7) + /// + /// 7: The destination channel is updated. + /// UpdateDestinationChannel, - /// The destination channel update fails due to internal reasons. @JsonValue(8) + /// + /// 8: The destination channel update fails due to internal reasons. + /// UpdateDestinationChannelRefused, - /// The destination channel does not change, which means that the destination channel fails to be updated. @JsonValue(9) + /// + /// 9: The destination channel does not change, which means that the destination channel fails to be updated. + /// UpdateDestinationChannelNotChange, - /// The destination channel name is NULL. @JsonValue(10) + /// + /// 10: The destination channel name is null. + /// UpdateDestinationChannelIsNil, - /// The video profile is sent to the server. @JsonValue(11) + /// + /// 11: The video profile is sent to the server. + /// VideoProfileUpdate, - /// @nodoc @JsonValue(12) + /// + /// 12: The SDK successfully pauses relaying the media stream to destination channels. + /// PauseSendPacketToDestChannelSuccess, - /// @nodoc @JsonValue(13) + /// + /// 13: The SDK fails to pause relaying the media stream to destination channels. + /// PauseSendPacketToDestChannelFailed, - /// @nodoc @JsonValue(14) + /// + /// 14: The SDK successfully resumes relaying the media stream to destination channels. + /// ResumeSendPacketToDestChannelSuccess, - /// @nodoc @JsonValue(15) + /// + /// 15: The SDK fails to resume relaying the media stream to destination channels. + /// ResumeSendPacketToDestChannelFailed, } -/// The state code in channel media relay state. +/// +/// The state code of the channel media relay. +/// +/// enum ChannelMediaRelayState { - /// The SDK is initializing. @JsonValue(0) + /// + /// 0: The initial state. After you successfully stop the channel media relay by calling stopChannelMediaRelay, the channelMediaRelayStateChanged callback returns this state. + /// Idle, - /// The SDK tries to relay the media stream to the destination channel. @JsonValue(1) + /// + /// 1: The SDK tries to relay the media stream to the destination channel. + /// Connecting, - /// The SDK successfully relays the media stream to the destination channel. @JsonValue(2) + /// + /// 2: The SDK successfully relays the media stream to the destination channel. + /// Running, - /// A failure occurs. @JsonValue(3) + /// + /// 3: An error occurs. See code in channelMediaRelayStateChanged for the error code. + /// Failure, } -/// Channel profile. +/// +/// The channel profile. +/// +/// enum ChannelProfile { - /// The Communication profile. - /// - /// Use this profile in one-on-one calls or group calls, where all users can talk freely. @JsonValue(0) + /// + /// 0: (Default) The communication profile. This profile applies to scenarios such as an audio call or video call, where all users can publish and subscribe to streams. + /// Communication, - /// The LiveBroadcasting profile. - /// - /// Users in a live-broadcast channel have a role as either broadcaster or audience. A broadcaster can both send and receive streams; an audience can only receive streams. @JsonValue(1) + /// + /// 1: Live streaming. In this profile, you can set the role of users as the host or audience by calling setClientRole. A host both publishes and subscribes to streams, while an audience subscribes to streams only. This profile applies to scenarios such as a chat room or interactive video streaming. + /// LiveBroadcasting, - /// The Gaming profile. - /// - /// This profile uses a codec with a lower bitrate and consumes less power. Applies to the gaming scenario, where all game players can talk freely. @JsonValue(2) + /// + /// 2: Gaming. Agora does not recommend using this setting. + /// Game, } -/// Client role in a live broadcast. +/// +/// The user role in the interactive live streaming. +/// +/// enum ClientRole { - /// A broadcaster can both send and receive streams. @JsonValue(1) + /// + /// 1: Host. A host can both send and receive streams. + /// Broadcaster, - /// The default role. An audience can only receive streams. @JsonValue(2) + /// + /// 2: (Default) Audience. An audience member can only receive streams. + /// Audience, } -/// Reasons for the connection state change. +/// +/// Reasons causing the change of the connection state. +/// +/// enum ConnectionChangedReason { - /// The SDK is connecting to Agora’s edge server. @JsonValue(0) - Connecting, + /// + /// 0: The SDK is connecting to the Agora edge server. + /// + Connecting, - /// The SDK has joined the channel successfully. @JsonValue(1) + /// + /// 1: The SDK has joined the channel successfully. + /// JoinSuccess, - /// The connection between the SDK and Agora’s edge server is interrupted. @JsonValue(2) + /// + /// 2: The connection between the SDK and the Agora edge server is interrupted. + /// Interrupted, - /// The connection between the SDK and Agora’s edge server is banned by Agora’s edge server. @JsonValue(3) + /// + /// 3: The connection between the SDK and the Agora edge server is banned by the Agora edge server. This error occurs when the user is kicked out of the channel by the server. + /// BannedByServer, - /// The SDK fails to join the channel for more than 20 minutes and stops reconnecting to the channel. @JsonValue(4) + /// + /// 4: The SDK fails to join the channel. When the SDK fails to join the channel for more than 20 minutes, this error occurs and the SDK stops reconnecting to the channel. + /// JoinFailed, - /// The SDK has left the channel. @JsonValue(5) + /// + /// 5: The SDK has left the channel. + /// LeaveChannel, - /// The specified App ID or Token is invalid. Try to rejoin the channel with a valid App ID or Token. @JsonValue(6) + /// + /// 6: The connection failed because the App ID is not valid. Please rejoin the channel with a valid App ID. + /// InvalidAppId, - /// The specified channel name is invalid. Try to rejoin the channel with a valid channel name. @JsonValue(7) + /// + /// 7: The connection failed since channel name is not valid. Please rejoin the channel with a valid channel name. + /// InvalidChannelName, - /// The generated token is invalid probably due to the following reasons: - /// - The App Certificate for the project is enabled in Console, but you do not use Token when joining the channel. If you enable the App Certificate, you must use a token to join the channel. - /// - The uid that you specify in the [RtcEngine.joinChannel] method is different from the uid that you pass for generating the token. @JsonValue(8) + /// + /// 8: The connection failed because the token is not valid. Typical reasons include: + /// The App Certificate for the project is enabled in Agora Console, but you do not use a token when joining the channel. If you enable the App Certificate, you must use a token to join the channel. + /// The uid specified when calling joinChannel to join the channel is inconsistent with the uid passed in when generating the token. + /// + /// InvalidToken, - /// The token has expired. Generate a new token from your server. @JsonValue(9) + /// + /// 9: The connection failed since token is expired. + /// TokenExpired, - /// The user is banned by the server. @JsonValue(10) + /// + /// 10: The connection is rejected by server. Typical reasons include: + /// The user is already in the channel and still calls a method, for example, joinChannel, to join the channel. Stop calling this method to clear this error. + /// The user tries to join the channel when conducting a pre-call test. The user needs to call the channel after the call test ends. + /// + /// + /// RejectedByServer, - /// The SDK tries to reconnect after setting a proxy server. @JsonValue(11) + /// + /// 11: The connection state changed to reconnecting because the SDK has set a proxy server. + /// SettingProxyServer, - /// The token renews. @JsonValue(12) + /// + /// 12: The connection state changed because the token is renewed. + /// RenewToken, - /// The client IP address has changed, probably due to a change of the network type, IP address, or network port. @JsonValue(13) + /// + /// 13: The IP address of the client has changed, possibly because the network type, IP address, or port has been changed. + /// ClientIpAddressChanged, - /// Timeout for the keep-alive of the connection between the SDK and Agora’s edge server. The connection state changes to: - /// - [ConnectionStateType.Reconnecting] @JsonValue(14) + /// + /// 14: Timeout for the keep-alive of the connection between the SDK and the Agora edge server. The connection state changes to Reconnecting. + /// KeepAliveTimeout, - /// In cloud proxy mode, the proxy server connection interrupted. @JsonValue(15) ProxyServerInterrupted, } +/// /// Connection states. +/// +/// enum ConnectionStateType { - /// The SDK is disconnected from Agora's edge server. - /// - This is the initial state before [RtcEngine.joinChannel]. - /// - The SDK also enters this state when the app calls [RtcEngine.leaveChannel]. @JsonValue(1) + /// + /// 1: The SDK is disconnected from the Agora edge server. The state indicates the SDK is in one of the following phases: + /// The initial state before calling the joinChannel method. + /// The app calls the leaveChannel method. + /// + /// + /// Disconnected, - /// The SDK is connecting to Agora's edge server. - /// - When the app calls [RtcEngine.joinChannel], the SDK starts to establish a connection to the specified channel, triggers the [RtcEngineEventHandler.connectionStateChanged] callback, and switches to the [ConnectionStateType.Connecting] state. - /// - When the SDK successfully joins the channel, the SDK triggers the [RtcEngineEventHandler.connectionStateChanged] callback and switches to the [ConnectionStateType.Connected] state. - /// - After the SDK joins the channel and when it finishes initializing the media engine, the SDK triggers the [RtcEngineEventHandler.joinChannelSuccess] callback. @JsonValue(2) + /// + /// 2: The SDK is connecting to the Agora edge server. This state indicates that the SDK is establishing a connection with the specified channel after the app calls joinChannel. + /// + /// + /// 4: The SDK keeps reconnecting to the Agora edge server. The SDK keeps rejoining the channel after being disconnected from a joined channel because of network issues. + /// If the SDK cannot rejoin the channel within 10 seconds, it triggers connectionLost, stays in the Reconnecting state, and keeps rejoining the channel. + /// + /// 5: The SDK fails to connect to the Agora edge server or join the channel. This state indicates that the SDK stops trying to rejoin the channel. You must call leaveChannel to leave the channel. + /// You can call joinChannel to rejoin the channel. + /// If the SDK is banned from joining the channel by the Agora edge server through the RESTful API, the SDK triggers the connectionStateChanged callback. + /// + /// + /// If the SDK fails to rejoin the channel 20 minutes after being disconnected from the Agora edge server, the SDK triggers the connectionStateChanged callback, switches to the Failed state, and stops rejoining the channel. + /// + /// + /// 3: The SDK is connected to the Agora edge server. This state also indicates that the user has joined a channel and can now publish or subscribe to a media stream in the channel. If the connection to the Agora edge server is lost because, for example, the network is down or switched, the SDK automatically tries to reconnect and triggers connectionStateChanged that indicates the connection state switches to Reconnecting. + /// + /// If the SDK successfully joins the channel, it triggers the connectionStateChanged callback and the connection state switches to Connected. + /// After the connection is established, the SDK also initializes the media and triggers joinChannelSuccess when everything is ready. + /// + /// + /// Connecting, - /// The SDK is connected to Agora's edge server and joins a channel. You can now publish or subscribe to a media stream in the channel. - /// If the connection to the channel is lost because, for example, the network is down or switched, the SDK automatically tries to reconnect and triggers: - /// - The [RtcEngineEventHandler.connectionStateChanged] callback, and switches to the [ConnectionStateType.Reconnecting] state. @JsonValue(3) Connected, - /// The SDK keeps rejoining the channel after being disconnected from a joined channel because of network issues. - /// - If the SDK cannot rejoin the channel within 10 seconds after being disconnected from Agora’s edge server, the SDK triggers the [RtcEngineEventHandler.connectionLost] callback, stays in the [ConnectionStateType.Reconnecting] state, and keeps rejoining the channel. - /// - If the SDK fails to rejoin the channel 20 minutes after being disconnected from Agora’s edge server, the SDK triggers the [RtcEngineEventHandler.connectionStateChanged] callback, switches to the [ConnectionStateType.Failed] state, and stops rejoining the channel. @JsonValue(4) Reconnecting, - /// The SDK fails to connect to Agora's edge server or join the channel. - /// You must call [RtcEngine.leaveChannel] to leave this state, and call [RtcEngine.joinChannel] again to rejoin the channel. - /// - /// If the SDK is banned from joining the channel by Agora’s edge server (through the RESTful API), the SDK triggers the [RtcEngineEventHandler.connectionStateChanged] callbacks. @JsonValue(5) Failed, } -/// The video encoding degradation preference under limited bandwidth. +/// +/// Video degradation preferences when the bandwidth is a constraint. +/// +/// enum DegradationPreference { - /// (Default) Prefers to reduce the video frame rate while maintaining video quality during video encoding under limited bandwidth. This degradation preference is suitable for scenarios where video quality is prioritized. + @JsonValue(0) /// - /// **Note** + /// 0: (Default) Prefers to reduce the video frame rate while maintaining video quality during video encoding under limited bandwidth. This degradation preference is suitable for scenarios where video quality is prioritized. + /// In the COMMUNICATION channel profile, the resolution of the video sent may change, so remote users need to handle this issue. See videoSizeChanged. /// - /// In the `COMMUNICATION` channel profile, the resolution of the video sent may change, so remote users need to handle this issue. See [RtcEngineEventHandler.videoSizeChanged]. - @JsonValue(0) MaintainQuality, - /// Prefers to reduce the video quality while maintaining the video frame rate during video encoding under limited bandwidth. This degradation preference is suitable for scenarios where smoothness is prioritized and video quality is allowed to be reduced. @JsonValue(1) + /// + /// 1: Prefers to reduce the video quality while maintaining the video frame rate during video encoding under limited bandwidth. This degradation preference is suitable for scenarios where smoothness is prioritized and video quality is allowed to be reduced. + /// MaintainFramerate, - /// Reduces the video frame rate and video quality simultaneously during video encoding under limited bandwidth. `Balenced` has a lower reduction than `MaintainQuality` and `MaintainFramerate`, and this preference is suitable for scenarios where both smoothness and video quality are a priority. + @JsonValue(2) + /// + /// 2: Reduces the video frame rate and video quality simultaneously during video encoding under limited bandwidth. MaintainBalanced has a lower reduction than MaintainQuality and MaintainFramerate, and this preference is suitable for scenarios where both smoothness and video quality are a priority. + /// The resolution of the video sent may change, so remote users need to handle this issue. See videoSizeChanged. /// - /// **Note** /// - /// The resolution of the video sent may change, so remote users need to handle this issue. See [RtcEngineEventHandler.videoSizeChanged]. - @JsonValue(2) MaintainBalanced } -/// Encryption mode +/// +/// The built-in encryption mode. +/// Agora recommends using AES128GCM2 or AES256GCM2 encrypted mode. These two modes support the use of salt for higher security. +/// enum EncryptionMode { - /// This mode is deprecated. @deprecated @JsonValue(0) None, - /// (Default) 128-bit AES encryption, XTS mode. @JsonValue(1) AES128XTS, - /// 128-bit AES encryption, ECB mode. @JsonValue(2) AES128ECB, - /// 256-bit AES encryption, XTS mode. @JsonValue(3) AES256XTS, - /// 128-bit SM4 encryption, ECB mode. @JsonValue(4) + /// + /// 4: 128-bit SM4 encryption, ECB mode. + /// SM4128ECB, - /// 128-bit AES encryption, GCM mode. @JsonValue(5) AES128GCM, - /// 256-bit AES encryption, GCM mode. @JsonValue(6) AES256GCM, - /// (Default) 128-bit AES encryption, GCM mode. - /// Compared to AES128GCM encryption mode, AES128GCM2 encryption mode is more secure and requires you to set the salt (encryptionKdfSalt). @JsonValue(7) + /// + /// 7: 128-bit AES encryption, GCM mode. This encryption mode requires the setting of salt (encryptionKdfSalt). + /// AES128GCM2, - /// 256-bit AES encryption, GCM mode. - /// Compared to AES256GCM encryption mode, AES256GCM2 encryption mode is more secure and requires you to set the salt (encryptionKdfSalt). @JsonValue(8) + /// + /// 8: 256-bit AES encryption, GCM mode. This encryption mode requires the setting of salt (encryptionKdfSalt). + /// AES256GCM2, } -/// Error codes occur when the SDK encounters an error that cannot be recovered automatically without any app intervention. +/* enum-ErrorCode */ enum ErrorCode { - /// No error occurs. @JsonValue(0) NoError, - /// A general error occurs (no specified reason). @JsonValue(1) Failed, - /// An invalid parameter is used. For example, the specific channel name includes illegal characters. @JsonValue(2) InvalidArgument, - /// The SDK module is not ready. - /// Possible solutions: - /// - Check the audio device. - /// - Check the completeness of the app. - /// - Re-initialize the SDK. @JsonValue(3) NotReady, - /// The current state of the SDK does not support this function. @JsonValue(4) NotSupported, - /// The request is rejected. This is for internal SDK use only, and is not returned to the app through any method or callback. @JsonValue(5) Refused, - /// The buffer size is not big enough to store the returned data. @JsonValue(6) BufferTooSmall, - /// The SDK is not initialized before calling this method. @JsonValue(7) NotInitialized, - /// No permission exists. Check whether the user has granted access to the audio or video device. @JsonValue(9) NoPermission, - /// An API method timeout occurs. Some API methods require the SDK to return the execution result, and this error occurs if the request takes too long (over 10 seconds) for the SDK to process. @JsonValue(10) TimedOut, - /// The request is canceled. This is for internal SDK use only, and is not returned to the app through any method or callback. @JsonValue(11) Canceled, - /// The method is called too often. This is for internal SDK use only, and is not returned to the app through any method or callback. @JsonValue(12) TooOften, - /// The SDK fails to bind to the network socket. This is for internal SDK use only, and is not returned to the app through any method or callback. @JsonValue(13) BindSocket, - /// The network is unavailable. This is for internal SDK use only, and is not returned to the app through any method or callback. @JsonValue(14) NetDown, - /// No network buffers are available. This is for internal SDK use only, and is not returned to the app through any method or callback. @JsonValue(15) NoBufs, - /// The request to join the channel is rejected. - /// Possible reasons are: - /// - The user is already in the channel, and still calls the API method to join the channel, for example, [RtcEngine.joinChannel]. - /// - The user tries joining the channel during the echo test. Please join the channel after the echo test ends. @JsonValue(17) JoinChannelRejected, - /// The request to leave the channel is rejected. - /// Possible reasons are: - /// - The user left the channel and still calls the API method to leave the channel, for example, [RtcEngine.leaveChannel]. - /// - The user has not joined the channel and calls the API method to leave the channel. @JsonValue(18) LeaveChannelRejected, - /// The resources are occupied and cannot be used. @JsonValue(19) AlreadyInUse, - /// The SDK gave up the request due to too many requests. @JsonValue(20) Abort, - /// In Windows, specific firewall settings cause the SDK to fail to initialize and crash. @JsonValue(21) InitNetEngine, - /// The app uses too much of the system resources and the SDK fails to allocate the resources. @JsonValue(22) ResourceLimited, - /// The specified App ID is invalid. Please try to rejoin the channel with a valid App ID. @JsonValue(101) InvalidAppId, - /// The specified channel name is invalid. Please try to rejoin the channel with a valid channel name. @JsonValue(102) InvalidChannelId, - /// 103: Fails to get server resources in the specified region. Please try to specify another region. @JsonValue(103) NoServerResources, - /// The token expired. Agora recommends that you use [ConnectionChangedReason.TokenExpired] in the reason parameter of [RtcEngineEventHandler.connectionStateChanged] instead. - /// - /// Possible reasons are: - /// - Authorized Timestamp expired: The timestamp is represented by the number of seconds elapsed since 1/1/1970. The user can use the token to access the Agora service within five minutes after the token is generated. If the user does not access the Agora service after five minutes, this token is no longer valid. - /// - Call Expiration Timestamp expired: The timestamp is the exact time when a user can no longer use the Agora service (for example, when a user is forced to leave an ongoing call). When a value is set for the Call Expiration Timestamp, it does not mean that the token will expire, but that the user will be banned from the channel. @deprecated @JsonValue(109) TokenExpired, - /// The token is invalid. Agora recommends that you use [ConnectionChangedReason.InvalidToken] in the reason parameter of [RtcEngineEventHandler.connectionStateChanged] instead. - /// - /// Possible reasons are: - /// - The App Certificate for the project is enabled in Console, but the user is using the App ID. Once the App Certificate is enabled, the user must use a token. - /// - The uid is mandatory, and users must set the same uid as the one set in the [RtcEngine.joinChannel] method. @deprecated @JsonValue(110) InvalidToken, - /// The Internet connection is interrupted. This applies to the Agora Web SDK only. @JsonValue(111) ConnectionInterrupted, - /// The Internet connection is lost. This applies to the Agora Web SDK only. @JsonValue(112) ConnectionLost, - /// The user is not in the channel when calling the [RtcEngine.sendStreamMessage] or [RtcEngine.getUserInfoByUserAccount] method. @JsonValue(113) NotInChannel, - /// The size of the sent data is over 1024 bytes when the user calls the [RtcEngine.sendStreamMessage] method. @JsonValue(114) SizeTooLarge, - /// The bitrate of the sent data exceeds the limit of 6 Kbps when the user calls the [RtcEngine.sendStreamMessage] method. @JsonValue(115) BitrateLimit, - /// Too many data streams (over five streams) are created when the user calls the [RtcEngine.createDataStream] method. @JsonValue(116) TooManyDataStreams, - /// Decryption fails. The user may have used a different encryption password to join the channel. Check your settings or try rejoining the channel. @JsonValue(120) DecryptionFailed, - /// The client is banned by the server. @JsonValue(123) ClientIsBannedByServer, - /// Incorrect watermark file parameter. @JsonValue(124) WatermarkParam, - /// Incorrect watermark file path. @JsonValue(125) WatermarkPath, - /// Incorrect watermark file format. @JsonValue(126) WatermarkPng, - /// Incorrect watermark file information. @JsonValue(127) WatermarkInfo, - /// Incorrect watermark file data format. @JsonValue(128) WatermarkAGRB, - /// An error occurs in reading the watermark file. @JsonValue(129) WatermarkRead, - /// The encrypted stream is not allowed to publish. @JsonValue(130) EncryptedStreamNotAllowedPublish, - /// The user account is invalid. @JsonValue(134) InvalidUserAccount, - /// CDN related errors. Remove the original URL address and add a new one by calling the [RtcEngine.removePublishStreamUrl] and [RtcEngine.addPublishStreamUrl] methods. @JsonValue(151) PublishStreamCDNError, - /// The host publishes more than 10 URLs. Delete the unnecessary URLs before adding new ones. @JsonValue(152) PublishStreamNumReachLimit, - /// The host manipulates other hosts' URLs. Check your app logic. @JsonValue(153) PublishStreamNotAuthorized, - /// An error occurs in Agora’s streaming server. Call the `addPublishStreamUrl` method to publish the stream again. - /// - /// See [RtcEngine.addPublishStreamUrl] @JsonValue(154) PublishStreamInternalServerError, - /// The server fails to find the stream. @JsonValue(155) PublishStreamNotFound, - /// The format of the RTMP stream URL is not supported. Check whether the URL format is correct. @JsonValue(156) PublishStreamFormatNotSuppported, - /// The extension library is not integrated, such as the library for enabling deep-learning noise reduction. @JsonValue(157) ModuleNotFound, - /// The client is already recording audio. To start a new recording, call [RtcEngine.stopAudioRecording] to stop the current recording first, and then call [RtcEngine.startAudioRecording]. @JsonValue(160) AlreadyInRecording, - /// Fails to load the media engine. @JsonValue(1001) LoadMediaEngine, - /// Fails to start the call after enabling the media engine. @JsonValue(1002) StartCall, - /// Fails to start the camera. Agora recommends that you use [LocalVideoStreamError.CaptureFailure] in the error parameter of [RtcEngineEventHandler.localVideoStateChanged] instead. @deprecated @JsonValue(1003) StartCamera, - /// Fails to start the video rendering module. @JsonValue(1004) StartVideoRender, - /// Audio Device Module: A general error occurs in the Audio Device Module (the reason is not classified specifically). Check if the audio device is used by another app, or try rejoining the channel. @JsonValue(1005) AdmGeneralError, - /// Audio Device Module: An error occurs in using the Java resources. @JsonValue(1006) AdmJavaResource, - /// Audio Device Module: An error occurs in setting the sampling frequency. @JsonValue(1007) AdmSampleRate, - /// Audio Device Module: An error occurs in initializing the playback device. @JsonValue(1008) AdmInitPlayout, - /// Audio Device Module: An error occurs in starting the playback device. @JsonValue(1009) AdmStartPlayout, - /// Audio Device Module: An error occurs in stopping the playback device. @JsonValue(1010) AdmStopPlayout, - /// Audio Device Module: An error occurs in initializing the recording device. @JsonValue(1011) AdmInitRecording, - /// Audio Device Module: An error occurs in starting the recording device. @JsonValue(1012) AdmStartRecording, - /// Audio Device Module: An error occurs in stopping the recording device. @JsonValue(1013) AdmStopRecording, - /// Audio Device Module: A playback error occurs. Check your playback device, or try rejoining the channel. @JsonValue(1015) AdmRuntimePlayoutError, - /// Audio Device Module: A recording error occurs. @JsonValue(1017) AdmRuntimeRecordingError, - /// Audio Device Module: Fails to record. @JsonValue(1018) AdmRecordAudioFailed, - /// Audio Device Module: Abnormal audio playback frequency. @JsonValue(1020) AdmPlayAbnormalFrequency, - /// Audio Device Module: Abnormal audio recording frequency. @JsonValue(1021) AdmRecordAbnormalFrequency, - /// Audio Device Module: An error occurs in initializing the loopback device. @JsonValue(1022) AdmInitLoopback, - /// Audio Device Module: An error occurs in starting the loopback device. @JsonValue(1023) AdmStartLoopback, - /// Audio Device Module: An error occurs in no recording Permission. @JsonValue(1027) AdmNoPermission, - /// Audio Routing: Fails to route the audio to the connected Bluetooth device. The default route is used. @JsonValue(1030) AudioBtScoFailed, - /// Audio Device Module: No recording device exists. @JsonValue(1359) AdmNoRecordingDevice, - /// No playback device exists. @JsonValue(1360) AdmNoPlayoutDevice, - /// Video Device Module: The camera is unauthorized. @JsonValue(1501) VdmCameraNotAuthorized, - /// Video Device Module: An unknown error occurs. @JsonValue(1600) VcmUnknownError, - /// Video Device Module: An error occurs in initializing the video encoder. @JsonValue(1601) VcmEncoderInitError, - /// Video Device Module: An error occurs in video encoding. @JsonValue(1602) VcmEncoderEncodeError, - /// Video Device Module: An error occurs in setting the video encoder. @deprecated @JsonValue(1603) VcmEncoderSetError, } -/// State of importing an external video stream in a live broadcast. +/// +/// States of importing an external video stream in the interactive live streaming. +/// +/// enum InjectStreamStatus { - /// The external video stream imported successfully. @JsonValue(0) + /// + /// 0: The external video stream is imported successfully. + /// StartSuccess, - /// The external video stream already exists. @JsonValue(1) + /// + /// 1: The external video stream already exists. + /// StartAlreadyExists, - /// The external video stream import is unauthorized. @JsonValue(2) + /// + /// 2: The external video stream to be imported is unauthorized. + /// StartUnauthorized, - /// Import external video stream timeout. @JsonValue(3) + /// + /// 3: A timeout occurs when importing the external video stream. + /// StartTimedout, - /// The external video stream failed to import. @JsonValue(4) + /// + /// 4: The SDK fails to import the external video stream. + /// StartFailed, - /// The external video stream imports successfully. @JsonValue(5) + /// + /// 5: The SDK successfully stops importing the external video stream. + /// StopSuccess, - /// No external video stream is found. @JsonValue(6) + /// + /// 6: The external video stream to be stopped importing is not found. + /// StopNotFound, - /// The external video stream is stopped from being unauthorized. @JsonValue(7) + /// + /// 7: The external video stream to be stopped importing is unauthorized. + /// StopUnauthorized, - /// Importing the external video stream timeout. @JsonValue(8) + /// + /// 8: A timeout occurs when stopping importing the external video stream. + /// StopTimedout, - /// Importing the external video stream failed. @JsonValue(9) + /// + /// 9: The SDK fails to stop importing the external video stream. + /// StopFailed, - /// The external video stream import is interrupted. @JsonValue(10) + /// + /// 10: The external video stream is corrupted. + /// Broken, } -/// The state of the probe test result. +/// +/// The status of the last-mile network tests. +/// +/// enum LastmileProbeResultState { - /// The last-mile network probe test is complete. @JsonValue(1) + /// + /// 1: The last-mile network probe test is complete. + /// Complete, - /// The last-mile network probe test is incomplete and the bandwidth estimation is not available, probably due to limited test resources. @JsonValue(2) + /// + /// 2: The last-mile network probe test is incomplete because the bandwidth estimation is not available due to limited test resources. + /// IncompleteNoBwe, - /// The last-mile network probe test is not carried out, probably due to poor network conditions. @JsonValue(3) + /// + /// 3: The last-mile network probe test is not carried out, probably due to poor network conditions. + /// Unavailable, } -/// The lightening contrast level. +/// +/// The contrast level. +/// +/// enum LighteningContrastLevel { - /// Low contrast level. @JsonValue(0) + /// + /// Low contrast level. + /// Low, - /// (Default) Normal contrast level. @JsonValue(1) + /// + /// (Default) Normal contrast level. + /// Normal, - /// High contrast level. @JsonValue(2) + /// + /// High contrast level. + /// High, } -/// The detailed error information of the local video. +/// +/// Local video state error codes. +/// +/// enum LocalVideoStreamError { - /// The local video is normal. @JsonValue(0) + /// + /// 0: The local video is normal. + /// OK, - /// No specified reason for the local video failure. @JsonValue(1) + /// + /// 1: No specified reason for the local video failure. + /// Failure, - /// No permission to use the local video device. @JsonValue(2) + /// + /// 2: No permission to use the local video capturing device. + /// DeviceNoPermission, - /// The local video capturer is in use. @JsonValue(3) + /// + /// 3: The local video capturing device is in use. + /// DeviceBusy, - /// The local video capture fails. Check whether the capturer is working properly. @JsonValue(4) + /// + /// 4: The local video capture fails. Check whether the capturing device is working properly. + /// CaptureFailure, - /// The local video encoding fails. @JsonValue(5) + /// + /// 5: The local video encoding fails. + /// EncodeFailure, - /// (iOS only) The application is in the background. @JsonValue(6) + /// + /// 6: The local video capturing device not available due to app did enter background. + /// CaptureInBackground, - /// (iOS only) The application is running in Slide Over, Split View, or Picture in Picture mode. @JsonValue(7) + /// + /// 7: The local video capturing device not available because the app is running in a multi-app layout (generally on the pad). + /// CaptureMultipleForegroundApps, - /// The SDK cannot find the local video capture device. @JsonValue(8) + /// + /// 8: Fails to find a local video capture device. + /// + /// DeviceNotFound, + + @JsonValue(11) + /// + /// startScreenCaptureByWindowId11: When calling to share the window, the shared window is in a minimized state. + /// + ScreenCaptureWindowMinmized, + + @JsonValue(12) + /// + /// 12: The error code indicates that a window shared by the window ID has been closed, or a full-screen window shared by the window ID has exited full-screen mode. After exiting full-screen mode, remote users cannot see the shared window. To prevent remote users from seeing a black screen, Agora recommends that you immediately stop screen sharing. + /// Common scenarios for reporting this error code: + /// When the local user closes the shared window, the SDK reports this error code. + /// The local user shows some slides in full-screen mode first, and then shares the windows of the slides. After the user exits full-screen mode, the SDK reports this error code. + /// The local user watches web video or reads web document in full-screen mode first, and then shares the window of the web video or document. After the user exits full-screen mode, the SDK reports this error code. + /// + /// + /// + ScreenCaptureWindowClosed, + + @JsonValue(10) + /// + /// 10: (macOS and Windows only) The SDK cannot find the video device in the video device list. Check whether the ID of the video device is valid. + /// + LocalVideoStreamErrorDeviceInvalidId, + + @JsonValue(13) + /// + /// 13: (Windows only) The window being shared is overlapped by another window, so the overlapped area is blacked out by the SDK during window sharing. + /// + LocalVideoStreamErrorScreenCaptureWindowOccluded, + + @JsonValue(20) + /// + /// 20: (Windows only) The SDK does not support sharing this type of window. + /// + LocalVideoStreamErrorScreenCaptureWindowNotSupported, } -/// The state of the local video stream. +/// +/// Local video state types +/// +/// enum LocalVideoStreamState { - /// The local video is in the initial state. @JsonValue(0) + /// + /// 0: The local video is in the initial state. + /// Stopped, - /// The local video capturer starts successfully. @JsonValue(1) + /// + /// 1: The local video capturing device starts successfully. + /// Capturing, - /// The first local video frame encodes successfully. @JsonValue(2) + /// + /// 2: The first video frame is successfully encoded. + /// Encoding, - /// The local video fails to start. @JsonValue(3) + /// + /// 3: Fails to start the local video. + /// Failed, } -/// Output log filter level. +/// +/// The output log level of the SDK. +/// +/// enum LogFilter { - /// Do not output any log information. @JsonValue(0) + /// + /// 0: Do not output any log information. + /// Off, - /// Output all log information. Set your log filter as debug if you want to get the most complete log file. @JsonValue(0x080f) + /// + /// 0x080f: Output all log information. Set your log filter as DEBUG if you want to get the most complete log file. + /// Debug, - /// Output CRITICAL, ERROR, WARNING, and INFO level log information. We recommend setting your log filter as this level. @JsonValue(0x000f) + /// + /// 0x000f: Output CRITICAL, ERROR, WARNING, and INFO level log information. We recommend setting your log filter as this level. + /// Info, - /// Outputs CRITICAL, ERROR, and WARNING level log information. @JsonValue(0x000e) + /// + /// 0x000e: Output CRITICAL, ERROR, and WARNING level log information. + /// Warning, - /// Outputs CRITICAL and ERROR level log information. @JsonValue(0x000c) + /// + /// 0x000c: Output CRITICAL and ERROR level log information. + /// Error, - /// Outputs CRITICAL level log information. @JsonValue(0x0008) + /// + /// 0x0008: Output CRITICAL level log information. + /// Critical, } -/// Network quality. +/// +/// Network quality types. +/// +/// enum NetworkQuality { - /// The network quality is unknown. @JsonValue(0) + /// + /// 0: The network quality is unknown. + /// Unknown, - /// The network quality is excellent. @JsonValue(1) + /// + /// 1: The network quality is excellent. + /// Excellent, - /// The network quality is quite good, but the bitrate may be slightly lower than excellent. @JsonValue(2) + /// + /// 2: The network quality is quite good, but the bitrate may be slightly lower than excellent. + /// Good, - /// Users can feel the communication slightly impaired. @JsonValue(3) + /// + /// 3: Users can feel the communication slightly impaired. + /// Poor, - /// Users can communicate only not very smoothly. @JsonValue(4) + /// + /// 4: Users cannot communicate smoothly. + /// Bad, - /// The network quality is so bad that users can hardly communicate. @JsonValue(5) + /// + /// 5: The quality is so bad that users can barely communicate. + /// VBad, - /// The network is disconnected and users cannot communicate at all. @JsonValue(6) + /// + /// 6: The network is down and users cannot communicate at all. + /// Down, - /// Users cannot detect the network quality. (Not in use.) @JsonValue(7) + /// + /// 7: Users cannot detect the network quality. (Not in use.) + /// Unsupported, - /// Detecting the network quality. @JsonValue(8) + /// + /// 8: Detecting the network quality. + /// Detecting, } +/// /// Network type. +/// +/// enum NetworkType { - /// The network type is unknown. @JsonValue(-1) + /// + /// -1: The network type is unknown. + /// Unknown, - /// The SDK disconnects from the network. @JsonValue(0) + /// + /// 0: The SDK disconnects from the network. + /// Disconnected, - /// The network type is LAN. @JsonValue(1) + /// + /// 1: The network type is LAN. + /// LAN, - /// The network type is Wi-Fi (including hotspots). @JsonValue(2) + /// + /// 2: The network type is Wi-Fi (including hotspots). + /// WIFI, - /// The network type is mobile 2G. @JsonValue(3) + /// + /// 3: The network type is mobile 2G. + /// Mobile2G, - /// The network type is mobile 3G. @JsonValue(4) + /// + /// 4: The network type is mobile 3G. + /// Mobile3G, - /// The network type is mobile 4G. @JsonValue(5) + /// + /// 5: The network type is mobile 4G. + /// Mobile4G, - /// The network type is mobile 5G. @JsonValue(6) Mobile5G, } -/// The detailed error information for streaming. +/// +/// Error codes of the RTMP or RTMPS streaming. +/// +/// enum RtmpStreamingErrorCode { - /// The RTMP or RTMPS streaming publishes successfully. @JsonValue(0) + /// + /// The RTMP or RTMPS streaming publishes successfully. + /// OK, - /// Invalid argument used. If, for example, you do not call the [RtcEngine.setLiveTranscoding] method to configure the LiveTranscoding parameters before calling the [RtcEngine.addPublishStreamUrl] method, the SDK returns this error. Check whether you set the parameters in the `setLiveTranscoding` method properly. @JsonValue(1) + /// + /// Invalid argument used. Please check the parameter setting. For example, if you do not call setLiveTranscoding to set the transcoding parameters before calling addPublishStreamUrl, the SDK returns this error. + /// InvalidParameters, - /// The RTMP or RTMPS streaming is encrypted and cannot be published. @JsonValue(2) + /// + /// Check whether you set the parameters in the setLiveTranscoding method properly. + /// EncryptedStreamNotAllowed, - /// Timeout for the RTMP or RTMPS streaming. Call the [RtcEngine.addPublishStreamUrl] method to publish the streaming again. @JsonValue(3) + /// + /// The RTMP or RTMPS streaming is encrypted and cannot be published. Call addPublishStreamUrl to re-publish the stream. + /// ConnectionTimeout, - /// An error occurs in Agora’s streaming server. Call the [RtcEngine.addPublishStreamUrl] method to publish the streaming again. @JsonValue(4) + /// + /// An error occurs in Agora's streaming server. Call the addPublishStreamUrl method to publish the streaming again. + /// InternalServerError, - /// An error occurs in the RTMP server. @JsonValue(5) + /// + /// An error occurs in the CDN server. + /// RtmpServerError, - /// The RTMP or RTMPS streaming publishes too frequently. @JsonValue(6) + /// + /// The RTMP or RTMPS streaming publishes too frequently. + /// TooOften, - /// The host publishes more than 10 URLs. Delete the unnecessary URLs before adding new ones. @JsonValue(7) + /// + /// The host has published more than 10 URLs. Delete the unnecessary URLs before adding new ones. + /// ReachLimit, - /// The host manipulates other hosts' URLs. Check your app logic. @JsonValue(8) - NotAuthorized, + /// + /// The host manipulates other hosts' streams. For example, the host updates or stops other hosts' streams. Check your app logic. + /// + NotAuthorized, - /// Agora’s server fails to find the RTMP or RTMPS streaming. @JsonValue(9) + /// + /// Agora's server fails to find the RTMP or RTMPS streaming. + /// StreamNotFound, - /// The format of the RTMP or RTMPS streaming URL is not supported. Check whether the URL format is correct. @JsonValue(10) + /// + /// The URL format is incorrect. Check whether the URL format is correct. + /// FormatNotSupported, - /// The streaming has been stopped normally. After you call `removePublishStreamUrl` to stop streaming, the SDK returns this value. @JsonValue(100) UnPublishOK, } -/// The RTMP or RTMPS streaming state. +/// +/// States of the RTMP or RTMPS streaming. +/// +/// enum RtmpStreamingState { - /// The RTMP or RTMPS streaming has not started or has ended. This state is also triggered after you remove an RTMP address from the CDN by calling [RtcEngine.removePublishStreamUrl]. @JsonValue(0) + /// + /// The RTMP or RTMPS streaming has not started or has ended. This state is also triggered after you remove an RTMP or RTMPS stream from the CDN by calling removePublishStreamUrl. + /// Idle, - /// The SDK is connecting to Agora’s streaming server and the RTMP server. This state is triggered after you call the [RtcEngine.addPublishStreamUrl] method. @JsonValue(1) + /// + /// The SDK is connecting to Agora's streaming server and the CDN server. This state is triggered after you call the addPublishStreamUrl method. + /// Connecting, - /// The RTMP or RTMPS streaming is being published. The SDK successfully publishes the RTMP or RTMPS streaming and returns this state. @JsonValue(2) + /// + /// The RTMP or RTMPS streaming publishes. The SDK successfully publishes the RTMP or RTMPS streaming and returns this state. + /// Running, - /// The RTMP or RTMPS streaming is recovering. When exceptions occur to the CDN, or the streaming is interrupted, the SDK attempts to resume RTMP or RTMPS streaming and returns this state. - /// - If the SDK successfully resumes the streaming, [RtmpStreamingState.Running] returns. - /// - If the streaming does not resume within 60 seconds or server errors occur, [RtmpStreamingState.Failure] returns. You can also reconnect to the server by calling the [RtcEngine.removePublishStreamUrl] and [RtcEngine.addPublishStreamUrl] methods. @JsonValue(3) + /// + /// The RTMP or RTMPS streaming is recovering. When exceptions occur to the CDN, or the streaming is interrupted, the SDK tries to resume RTMP or RTMPS streaming and returns this state. + /// + /// If the SDK successfully resumes the streaming, Running(2) returns. + /// + /// The RTMP or RTMPS streaming fails. See the error code for the detailed error information. You can also call the addPublishStreamUrl method to publish the RTMP or RTMPS stream again. + /// + /// If the streaming does not resume within 60 seconds or server errors occur, Failure(4) returns. You can also reconnect to the server by calling the removePublishStreamUrl and addPublishStreamUrl methods. + /// + /// + /// Recovering, - /// The RTMP or RTMPS streaming fails. See the `errorCode` parameter for the detailed error information. You can also call the [RtcEngine.addPublishStreamUrl] method to publish the RTMP or RTMPS streaming again. @JsonValue(4) Failure, } -/// Stream fallback option. +/// +/// Stream fallback options. +/// +/// enum StreamFallbackOptions { - /// No fallback behavior for the local/remote video stream when the uplink/downlink network condition is unreliable. The quality of the stream is not guaranteed. @JsonValue(0) + /// + /// 0: No fallback behavior for the local/remote video stream when the uplink/downlink network conditions are poor. The quality of the stream is not guaranteed. + /// Disabled, - /// Under unreliable downlink network conditions, the remote video stream falls back to the low-stream (low resolution and low bitrate) video. You can only set this option in the [RtcEngine.setRemoteSubscribeFallbackOption] method. Nothing happens when you set this in the [RtcEngine.setLocalPublishFallbackOption] method. @JsonValue(1) + /// + /// 1: Under poor downlink network conditions, the remote video stream, to which you subscribe, falls back to the low-quality (low resolution and low bitrate) video stream. This option is only valid for setRemoteSubscribeFallbackOption and is invalid for setLocalPublishFallbackOption. + /// VideoStreamLow, - /// Under unreliable uplink network conditions, the published video stream falls back to audio only. Under unreliable downlink network conditions, the remote video stream first falls back to the low-stream (low resolution and low bitrate) video; and then to an audio-only stream if the network condition deteriorates. @JsonValue(2) + /// + /// 2: Under poor uplink network conditions, the published video stream falls back to audio only. Under poor downlink network conditions, the remote video stream, to which you subscribe, first falls back to the low-quality (low resolution and low bitrate) video stream; and then to an audio-only stream if the network conditions worsen. + /// AudioOnly, } -/// Reason for the user being offline. +/// +/// Reasons for a user being offline. +/// +/// enum UserOfflineReason { - /// The user left the current channel. @JsonValue(0) + /// + /// 0: The user quits the call. + /// Quit, - /// The SDK timed out and the user dropped offline because no data packet is received within a certain period of time. If a user quits the call and the message is not passed to the SDK (due to an unreliable channel), the SDK assumes the user dropped offline. @JsonValue(1) + /// + /// 1: The SDK times out and the user drops offline because no data packet is received within a certain period of time. + /// If the user quits the call and the message is not passed to the SDK (due to an unreliable channel), the SDK assumes the user dropped offline. + /// Dropped, - /// (LiveBroadcasting only) The client role switched from the host to the audience. @JsonValue(2) + /// + /// 2: The user switches the client role from the host to the audience. + /// BecomeAudience, } +/// /// The priority of the remote user. +/// +/// enum UserPriority { - /// The user’s priority is high. @JsonValue(50) + /// + /// The user's priority is high. + /// High, - /// (Default) The user’s priority is normal. @JsonValue(100) + /// + /// (Default) The user's priority is normal. + /// Normal, } -/// Self-defined video codec profile. +/// +/// Video codec profile types. +/// +/// enum VideoCodecProfileType { - /// Baseline video codec profile. Generally used in video calls on mobile phones. @JsonValue(66) + /// + /// 66: Baseline video codec profile. Generally used for video calls on mobile phones. + /// BaseLine, - /// Main video codec profile. Generally used in mainstream electronics, such as MP4 players, portable video players, PSP, and iPads. @JsonValue(77) + /// + /// 77: Main video codec profile. Generally used in mainstream electronics such as MP4 players, portable video players, PSP, and iPads. + /// Main, - /// (Default) High video codec profile. Generally used in high-resolution broadcasts or television. @JsonValue(100) + /// + /// 100: (Default) High video codec profile. Generally used in high-resolution live streaming or television. + /// High, } +/// /// Video frame rate. +/// +/// enum VideoFrameRate { - /// Min @JsonValue(-1) Min, - /// 1 fps. @JsonValue(1) + /// + /// 1: 1 fps + /// Fps1, - /// 7 fps. @JsonValue(7) + /// + /// 7: 7 fps + /// Fps7, - /// 10 fps. @JsonValue(10) + /// + /// 10: 10 fps + /// Fps10, - /// 15 fps. @JsonValue(15) + /// + /// 15: 15 fps + /// Fps15, - /// 24 fps. @JsonValue(24) + /// + /// 24: 24 fps + /// Fps24, - /// 30 fps. @JsonValue(30) + /// + /// 30: 30 fps + /// Fps30, - /// 60 fps (macOS only). @JsonValue(60) Fps60, } -/// Sets the video bitrate (Kbps). Refer to the table below and set your bitrate. -/// **Video Bitrate Table** -/// -/// | Resolution | Frame Rate (fps) | Base Bitrate (Kbps) | Live Bitrate (Kbps) | -/// |------------------------|------------------|----------------------------------------|----------------------------------------| -/// | 160 * 120 | 15 | 65 | 130 | -/// | 120 * 120 | 15 | 50 | 100 | -/// | 320 * 180 | 15 | 140 | 280 | -/// | 180 * 180 | 15 | 100 | 200 | -/// | 240 * 180 | 15 | 120 | 240 | -/// | 320 * 240 | 15 | 200 | 400 | -/// | 240 * 240 | 15 | 140 | 280 | -/// | 424 * 240 | 15 | 220 | 440 | -/// | 640 * 360 | 15 | 400 | 800 | -/// | 360 * 360 | 15 | 260 | 520 | -/// | 640 * 360 | 30 | 600 | 1200 | -/// | 360 * 360 | 30 | 400 | 800 | -/// | 480 * 360 | 15 | 320 | 640 | -/// | 480 * 360 | 30 | 490 | 980 | -/// | 640 * 480 | 15 | 500 | 1000 | -/// | 480 * 480 | 15 | 400 | 800 | -/// | 640 * 480 | 30 | 750 | 1500 | -/// | 480 * 480 | 30 | 600 | 1200 | -/// | 848 * 480 | 15 | 610 | 1220 | -/// | 848 * 480 | 30 | 930 | 1860 | -/// | 640 * 480 | 10 | 400 | 800 | -/// | 1280 * 720 | 15 | 1130 | 2260 | -/// | 1280 * 720 | 30 | 1710 | 3420 | -/// | 960 * 720 | 15 | 910 | 1820 | -/// | 960 * 720 | 30 | 1380 | 2760 | -/// -/// **Note** -/// - The base bitrate in this table applies to the Communication profile. -/// - The LiveBroadcasting profile generally requires a higher bitrate for better video quality. We recommend setting the bitrate mode as `0`. You can also set the bitrate as the base bitrate value x 2. -/// -/// If you set a bitrate beyond the proper range, the SDK automatically adjusts it to a value within the range. You can also choose from the following options: +/* enum-BitRate */ enum BitRate { - /// (Recommended) The standard bitrate mode. In this mode, the bitrates differ between the LiveBroadcasting and Communication profiles: - /// - Communication profile: the video bitrate is the same as the base bitrate. - /// - LiveBroadcasting profile: the video bitrate is twice the base bitrate. @JsonValue(0) Standard, - /// The compatible bitrate mode. In this mode, the bitrate stays the same regardless of the profile. In the LiveBroadcasting profile, if you choose this mode, the video frame rate may be lower than the set value. @JsonValue(-1) Compatible, } +/// /// Video mirror mode. +/// +/// enum VideoMirrorMode { - /// (Default) The SDK determines the mirror mode. @JsonValue(0) + /// + /// 0: (Default) The SDK determines the mirror mode. + /// Auto, - /// Enables mirror mode. @JsonValue(1) + /// + /// 1: Enable mirror mode. + /// Enabled, - /// Disables mirror mode. @JsonValue(2) + /// + /// 2: Disable mirror mode. + /// Disabled, } -/// Video output orientation mode. +/// +/// Video output orientation modes. +/// +/// enum VideoOutputOrientationMode { - /// Adaptive mode (Default). - /// The video encoder adapts to the orientation mode of the video input device. When you use a custom video source, the output video from the encoder inherits the orientation of the original video. - /// - If the width of the captured video from the SDK is greater than the height, the encoder sends the video in landscape mode. The encoder also sends the rotational information of the video, and the receiver uses the rotational information to rotate the received video. - /// - If the original video is in portrait mode, the output video from the encoder is also in portrait mode. The encoder also sends the rotational information of the video to the receiver. @JsonValue(0) + /// + /// 0: (Default) The output video always follows the orientation of the captured video. The receiver takes the rotational information passed on from the video encoder. This mode applies to scenarios where video orientation can be adjusted on the receiver. + /// + /// If the captured video is in landscape mode, the output video is in landscape mode. + /// If the captured video is in portrait mode, the output video is in portrait mode. + /// + /// + /// Adaptative, - /// Landscape mode. - /// The video encoder always sends the video in landscape mode. The video encoder rotates the original video before sending it and the rotational information is 0. This mode applies to scenarios involving CDN live streaming. @JsonValue(1) + /// + /// 1: In this mode, the SDK always outputs videos in landscape (horizontal) mode. If the captured video is in portrait mode, the video encoder crops it to fit the output. Applies to situations where the receiving end cannot process the rotational information. For example, CDN live streaming. + /// FixedLandscape, - /// Portrait mode. - /// The video encoder always sends the video in portrait mode. The video encoder rotates the original video before sending it and the rotational information is 0. This mode applies to scenarios involving CDN live streaming. @JsonValue(2) + /// + /// 2: In this mode, the SDK always outputs video in portrait (portrait) mode. If the captured video is in landscape mode, the video encoder crops it to fit the output. Applies to situations where the receiving end cannot process the rotational information. For example, CDN live streaming. + /// FixedPortrait, } +/// /// Quality change of the local video in terms of target frame rate and target bit rate since last count. +/// +/// enum VideoQualityAdaptIndication { - /// The quality of the local video stays the same. @JsonValue(0) + /// + /// 0: The local video quality stays the same. + /// AdaptNone, - /// The quality improves because the network bandwidth increases. @JsonValue(1) + /// + /// 1: The local video quality improves because the network bandwidth increases. + /// AdaptUpBandwidth, - /// The quality worsens because the network bandwidth decreases. @JsonValue(2) + /// + /// 2: The local video quality deteriorates because the network bandwidth decreases. + /// AdaptDownBandwidth, } +/// /// The state of the remote video. +/// +/// enum VideoRemoteState { - /// The remote video is in the default state, probably due to: - /// - [VideoRemoteStateReason.LocalMuted] - /// - [VideoRemoteStateReason.RemoteMuted] - /// - [VideoRemoteStateReason.RemoteOffline] @JsonValue(0) + /// + /// 0: The remote video is in the initial state. The SDK reports this state in the case of LocalMuted, RemoteMuted or RemoteOffline. + /// Stopped, - /// The first remote video packet is received. @JsonValue(1) + /// + /// 1: The first remote video packet is received. + /// Starting, - /// The remote video stream is decoded and plays normally, probably due to: - /// - [VideoRemoteStateReason.NetworkRecovery] - /// - [VideoRemoteStateReason.LocalUnmuted] - /// - [VideoRemoteStateReason.RemoteUnmuted] - /// - [VideoRemoteStateReason.AudioFallbackRecovery] @JsonValue(2) + /// + /// 2: The remote video stream is decoded and plays normally. The SDK reports this state in the case of NetworkRecovery, LocalUnmuted,RemoteUnmuted, or AudioFallbackRecovery. + /// Decoding, - /// The remote video is frozen, probably due to: - /// - [VideoRemoteStateReason.NetworkCongestion] - /// - [VideoRemoteStateReason.AudioFallback] @JsonValue(3) + /// + /// 3: The remote video is frozen. The SDK reports this state in the case of NetworkCongestion or AudioFallback. + /// Frozen, - /// The remote video fails to start, probably due to [VideoRemoteStateReason.Internal]. @JsonValue(4) + /// + /// 4: The remote video fails to start. The SDK reports this state in the case of Internal. + /// Failed, } -/// The reason of the remote video state change. +/// +/// The reason for the remote video state change. +/// +/// enum VideoRemoteStateReason { - /// Internal reasons. @JsonValue(0) + /// + /// 0: The SDK reports this reason when the video state changes. + /// Internal, - /// Network congestion. @JsonValue(1) + /// + /// 1: Network congestion. + /// NetworkCongestion, - /// Network recovery. @JsonValue(2) + /// + /// 2: Network recovery. + /// NetworkRecovery, - /// The local user stops receiving the remote video stream or disables the video module. @JsonValue(3) + /// + /// 3: The local user stops receiving the remote video stream or disables the video module. + /// LocalMuted, - /// The local user stops receiving the remote video stream or disables the video module. @JsonValue(4) + /// + /// 4: The local user resumes receiving the remote video stream or enables the video module. + /// LocalUnmuted, - /// The remote user stops sending the video stream or disables the video module. @JsonValue(5) + /// + /// 5: The remote user stops sending the video stream or disables the video module. + /// RemoteMuted, - /// The remote user resumes sending the video stream or enables the video module. @JsonValue(6) + /// + /// 6: The remote user resumes sending the video stream or enables the video module. + /// RemoteUnmuted, - /// The remote user leaves the channel. @JsonValue(7) + /// + /// 7: The remote user leaves the channel. + /// RemoteOffline, - /// The remote media stream falls back to the audio-only stream due to poor network conditions. @JsonValue(8) + /// + /// 8: The remote audio-and-video stream falls back to the audio-only stream due to poor network conditions. + /// AudioFallback, - /// The remote media stream switches back to the video stream after the network conditions improve. @JsonValue(9) + /// + /// 9: The remote audio-only stream switches back to the audio-and-video stream after the network conditions improve. + /// AudioFallbackRecovery, } -/// Video display mode. +/// +/// Video display modes. +/// +/// enum VideoRenderMode { - /// Uniformly scale the video until it fills the visible boundaries (cropped). One dimension of the video may have clipped contents. @JsonValue(1) + /// + /// 1: Uniformly scale the video until one of its dimension fits the boundary (zoomed to fit). Hidden mode. One dimension of the video may have clipped contents. + /// Hidden, - /// Uniformly scale the video until one of its dimension fits the boundary (zoomed to fit). Areas that are not filled due to the disparity in the aspect ratio are filled with black. @JsonValue(2) + /// + /// 2: Uniformly scale the video until one of its dimension fits the boundary (zoomed to fit). Fit mode. Areas that are not filled due to disparity in the aspect ratio are filled with black. + /// Fit, - /// This mode is deprecated. @deprecated @JsonValue(3) + /// + /// + /// + /// Deprecated: + /// 3: This mode is deprecated. + /// + /// + /// Adaptive, - /// The fill mode. In this mode, the SDK stretches or zooms the video to fill the display window. @JsonValue(4) FILL, } -/// Video stream type. +/// +/// The type of video streams. +/// +/// enum VideoStreamType { - /// High-bitrate, high-resolution video stream. @JsonValue(0) + /// + /// 0: High-quality video stream. + /// High, - /// Low-bitrate, low-resolution video stream. @JsonValue(1) + /// + /// 1: Low-quality video stream. + /// Low, } -/// Warning codes occur when the SDK encounters an error that may be recovered automatically. These are only notifications, and can generally be ignored. For example, when the SDK loses connection to the server, the SDK reports the `OpenChannelTimeout`(106) warning and tries to reconnect automatically. -/// See [WarningCode.OpenChannelTimeout]. +/* enum-WarningCode */ enum WarningCode { - /// The specified view is invalid. Specify a view when using the video call function. @JsonValue(8) InvalidView, - /// Failed to initialize the video function, possibly caused by a lack of resources. The users cannot see the video while the voice communication is not affected. @JsonValue(16) InitVideo, - /// The request is pending, usually due to some module not being ready, and the SDK postpones processing the request. @JsonValue(20) Pending, - /// No channel resources are available. Maybe because the server cannot allocate any channel resource. @JsonValue(103) NoAvailableChannel, - /// A timeout occurs when looking up the channel. When joining a channel, the SDK looks up the specified channel. The warning usually occurs when the network condition is too poor for the SDK to connect to the server. @JsonValue(104) LookupChannelTimeout, - /// The server rejects the request to look up the channel. The server cannot process this request or the request is illegal. Agora recommends that you use [ConnectionChangedReason.RejectedByServer] in the reason parameter of [RtcEngineEventHandler.connectionStateChanged] instead. @deprecated @JsonValue(105) LookupChannelRejected, - /// The server rejects the request to look up the channel. The server cannot process this request or the request is illegal. @JsonValue(106) OpenChannelTimeout, - /// The server rejects the request to open the channel. The server cannot process this request or the request is illegal. @JsonValue(107) OpenChannelRejected, - /// A timeout occurs when switching to the live video. @JsonValue(111) SwitchLiveVideoTimeout, - /// A timeout occurs when setting the client role in the LiveBroadcasting profile. @JsonValue(118) SetClientRoleTimeout, - /// The client role is unauthorized. @JsonValue(119) SetClientRoleNotAuthorized, - /// The ticket to open the channel is invalid. @JsonValue(121) OpenChannelInvalidTicket, - /// Try connecting to another server. @JsonValue(122) OpenChannelTryNextVos, - /// An error occurs in opening the audio mixing file. @JsonValue(701) AudioMixingOpenError, - /// Audio Device Module: a warning occurs in the playback device. @JsonValue(1014) AdmRuntimePlayoutWarning, - /// Audio Device Module: a warning occurs in the recording device. @JsonValue(1016) AdmRuntimeRecordingWarning, - /// Audio Device Module: no valid audio data is collected. @JsonValue(1019) AdmRecordAudioSilence, - /// Audio Device Module: a playback device fails. @JsonValue(1020) AdmPlaybackMalfunction, - /// Audio Device Module: a recording device fails. @JsonValue(1021) AdmRecordMalfunction, - /// Audio Device Module: call is interrupted by system events such as phone call or siri etc. @JsonValue(1025) AdmInterruption, - /// During a call, `AudioSessionCategory` should be set to `AVAudioSessionCategoryPlayAndRecord`, and the SDK monitors this value. If the `AudioSessionCategory` is set to other values, this warning code is triggered and the SDK will forcefully set it back to `AVAudioSessionCategoryPlayAndRecord`. @JsonValue(1029) AdmCategoryNotPlayAndRecord, - /// Audio Device Module: the recorded audio is too low. @JsonValue(1031) AdmRecordAudioLowlevel, - /// Audio Device Module: the playback audio is too low. @JsonValue(1032) AdmPlayoutAudioLowlevel, - /// Audio Device Module: The recording device is busy. @JsonValue(1033) AdmRecordIsOccupied, - /// Audio device module: An error occurs in the audio driver. Solutions: - /// - Restart your audio device. - /// - Restart your device where the app runs. - /// - Upgrade the sound card drive. @JsonValue(1040) AdmNoDataReadyCallback, - /// Audio device module: The audio recording device is different from the audio playback device, which may cause echoes problem. Agora recommends using the same audio device to record and playback audio. @JsonValue(1042) AdmInconsistentDevices, - /// Audio Device Module: howling is detected. @JsonValue(1051) ApmHowling, - /// Audio Device Module: the device is in the glitch state. @JsonValue(1052) AdmGlitchState, - /// Audio processing module: A residual echo is detected, which may be caused by the belated scheduling of system threads or the signal overflow. @JsonValue(1053) ApmResidualEcho, - /// Super-resolution warning: the original video dimensions of the remote user exceed 640*480. @JsonValue(1610) SuperResolutionStreamOverLimitation, - /// Super-resolution warning: another user is using super resolution. @JsonValue(1611) SuperResolutionUserCountOverLimitation, - /// Super-resolution warning: The device is not supported. @JsonValue(1612) SuperResolutionDeviceNotSupported, } -/// The audio channel of the sound. +/* enum-AudioChannel */ enum AudioChannel { - /// (Default) Supports dual channels. Depends on the upstream of the broadcaster. @JsonValue(0) Channel0, - /// The audio stream of the broadcaster uses the FL audio channel. If the upstream of the broadcaster uses multiple audio channels, these channels will be mixed into mono first. @JsonValue(1) Channel1, - /// The audio stream of the broadcaster uses the FC audio channel. If the upstream of the broadcaster uses multiple audio channels, these channels will be mixed into mono first. @JsonValue(2) Channel2, - /// The audio stream of the broadcaster uses the FR audio channel. If the upstream of the broadcaster uses multiple audio channels, these channels will be mixed into mono first. @JsonValue(3) Channel3, - /// The audio stream of the broadcaster uses the BL audio channel. If the upstream of the broadcaster uses multiple audio channels, these channels will be mixed into mono first. @JsonValue(4) Channel4, - /// The audio stream of the broadcaster uses the BR audio channel. If the upstream of the broadcaster uses multiple audio channels, these channels will be mixed into mono first. @JsonValue(5) Channel5, } +/// /// Video codec types. +/// +/// enum VideoCodecType { - /// Standard VP8. @JsonValue(1) + /// + /// Standard VP8. + /// VP8, - /// Standard H264. @JsonValue(2) + /// + /// Standard H.264. + /// H264, - /// Enhanced VP8. @JsonValue(3) EVP, - /// Enhanced H264. @JsonValue(4) E264, } +/* enum-VideoCodecTypeForStream */ +enum VideoCodecTypeForStream { + @JsonValue(1) + H264, + + @JsonValue(2) + H265, +} + +/// /// The publishing state. +/// +/// enum StreamPublishState { - /// The initial publishing state after joining the channel. @JsonValue(0) + /// + /// 0: The initial publishing state after joining the channel. + /// Idle, - /// Fails to publish the local stream. Possible reasons: - /// - The local user calls [RtcEngine.muteLocalAudioStream] (`true`) or [RtcEngine.muteLocalVideoStream] (`true`) to stop sending local streams. - /// - The local user calls [RtcEngine.disableAudio] or [RtcEngine.disableVideo] to disable the entire audio or video module. - /// - The local user calls [RtcEngine.enableLocalAudio] (`false`) or [RtcEngine.enableLocalVideo] (`false`) to disable the local audio sampling or video capturing. - /// - The role of the local user is `Audience`. @JsonValue(1) + /// + /// 1: Fails to publish the local stream. Possible reasons: + /// The local user calls muteLocalAudioStream(true) or muteLocalVideoStream(true) to stop sending the local media stream. + /// The local user calls disableAudio or disableVideo to disable the local audio or video module. + /// The local user calls enableLocalAudio(false) or enableLocalVideo(false) to disable the local audio or video capture. + /// The role of the local user is audience. + /// + /// + /// + /// + /// 3: Publishes successfully. + /// NoPublished, - /// Publishing. @JsonValue(2) + /// + /// 2: Publishing. + /// Publishing, - /// Publishes successfully. @JsonValue(3) Published, } +/// /// The subscribing state. +/// +/// enum StreamSubscribeState { - /// The initial subscribing state after joining the channel. @JsonValue(0) + /// + /// 0: The initial subscribing state after joining the channel. + /// Idle, - /// Fails to subscribe to the remote stream. Possible reasons: - /// - The remote user: - /// - Calls [RtcEngine.muteLocalAudioStream] (`true`) to stop sending local streams. - /// - The local user calls [RtcEngine.disableAudio] or [RtcEngine.disableVideo] to disable the entire audio or video module. - /// - The local user calls [RtcEngine.enableLocalAudio] (`false`) or [RtcEngine.enableLocalVideo] (`false`) to disable the local audio sampling or video capturing. - /// - The role of the local user is `Audience`. - /// - The local user calls the following methods to stop receiving remote streams: - /// - Calls [RtcEngine.muteRemoteAudioStream] (`true`), [RtcEngine.muteAllRemoteAudioStreams] (`true`), or [RtcEngine.setDefaultMuteAllRemoteAudioStreams] (`true`) to stop receiving remote audio streams. - /// - Calls [RtcEngine.muteRemoteVideoStream] (`true`), [RtcEngine.muteAllRemoteVideoStreams] (`true`), or [RtcEngine.setDefaultMuteAllRemoteVideoStreams] (`true`) to stop receiving remote video streams. @JsonValue(1) + /// + /// 1: Fails to subscribe to the remote stream. Possible reasons: + /// The remote user: + /// Calls muteLocalAudioStream(true) or muteLocalVideoStream(true) to stop sending local media stream. + /// Calls disableAudio or disableVideo to disable the local audio or video module. + /// Calls enableLocalAudio(false) or enableLocalVideo(false) to disable the local audio or video capture. + /// The role of the remote user is audience. + /// + /// The local user calls the following methods to stop receiving remote streams: + /// Calls muteRemoteAudioStream(true), muteAllRemoteAudioStreams(true) or setDefaultMuteAllRemoteAudioStreams(true) to stop receiving the remote audio streams. + /// Calls muteRemoteVideoStream(true), muteAllRemoteVideoStreams(true) or setDefaultMuteAllRemoteVideoStreams(true) to stop receiving the remote video streams. + /// + /// + /// + /// + /// + /// 3: Subscribes to and receives the remote stream successfully. + /// NoSubscribed, - /// Subscribing. @JsonValue(2) + /// + /// 2: Subscribing. + /// Subscribing, - /// Subscribes to and receives the remote stream successfully. @JsonValue(3) Subscribed, } +/// /// Events during the RTMP or RTMPS streaming. +/// +/// enum RtmpStreamingEvent { - /// An error occurs when you add a background image or a watermark image to the RTMP stream. @JsonValue(1) + /// + /// An error occurs when you add a background image or a watermark image to the RTMP or RTMPS stream. + /// FailedLoadImage, - /// The streaming URL is already being used for CDN live streaming. If you want to start new streaming, use a new streaming URL. @JsonValue(2) UrlAlreadyInUse, } -/// Audio session restriction. +/// +/// The operational permission of the SDK on the audio session. +/// +/// enum AudioSessionOperationRestriction { - /// No restriction, the SDK has full control of the audio session operations. @JsonValue(0) + /// + /// No restriction, the SDK has full control of the audio session operations. + /// None, - /// The SDK does not change the audio session category. @JsonValue(1) + /// + /// The SDK does not change the audio session category. + /// SetCategory, - /// The SDK does not change any setting of the audio session (category, mode, categoryOptions). @JsonValue(1 << 1) + /// + /// The SDK does not change any setting of the audio session (category, mode, categoryOptions). + /// ConfigureSession, - /// The SDK keeps the audio session active when leaving a channel. @JsonValue(1 << 2) + /// + /// The SDK keeps the audio session active when leaving a channel. + /// DeactivateSession, - /// The SDK does not configure the audio session anymore. @JsonValue(1 << 7) + /// + /// The SDK does not configure the audio session anymore. + /// All, } -/// The options for SDK preset audio effects. +/// +/// Voice effect presets. +/// For better voice effects, Agora recommends setting the profile parameter of setAudioProfile to +/// +/// +/// MusicHighQuality +/// +/// +/// or +/// +/// +/// MusicHighQualityStereo +/// +/// +/// before using the following presets: +/// +/// RoomAcousticsKTV +/// RoomAcousticsVocalConcert +/// RoomAcousticsStudio +/// RoomAcousticsPhonograph +/// RoomAcousticsSpacial +/// RoomAcousticsEthereal +/// VoiceChangerEffectUncle +/// VoiceChangerEffectOldMan +/// VoiceChangerEffectBoy +/// VoiceChangerEffectSister +/// VoiceChangerEffectGirl +/// VoiceChangerEffectPigKing +/// VoiceChangerEffectHulk +/// PitchCorrection +/// enum AudioEffectPreset { - /// Turn off audio effects and use the original voice. @JsonValue(0x00000000) + /// + /// Turn off voice effects, that is, use the original voice. + /// AudioEffectOff, - /// An audio effect typical of a KTV venue. @JsonValue(0x02010100) + /// + /// The voice effect typical of a KTV venue. + /// RoomAcousticsKTV, - /// An audio effect typical of a concert hall. + @JsonValue(0x02010200) /// - /// **Note** + /// The voice effect typical of a concert hall. /// - /// To achieve better audio effect quality, Agora recommends calling [RtcEngine.setAudioProfile] and setting the profile parameter to `MusicHighQuality(4)` or `MusicHighQualityStereo(5)` before setting this enumerator. - @JsonValue(0x02010200) RoomAcousticsVocalConcert, - /// An audio effect typical of a recording studio. + @JsonValue(0x02010300) /// - /// **Note** + /// The voice effect typical of a recording studio. /// - /// To achieve better audio effect quality, Agora recommends calling [RtcEngine.setAudioProfile] and setting the profile parameter to `MusicHighQuality(4)` or `MusicHighQualityStereo(5)` before setting this enumerator. - @JsonValue(0x02010300) RoomAcousticsStudio, - /// An audio effect typical of a vintage phonograph. + @JsonValue(0x02010400) /// - /// **Note** + /// The voice effect typical of a vintage phonograph. /// - /// To achieve better audio effect quality, Agora recommends calling [RtcEngine.setAudioProfile] and setting the profile parameter to `MusicHighQuality(4)` or `MusicHighQualityStereo(5)` before setting this enumerator. - @JsonValue(0x02010400) RoomAcousticsPhonograph, - /// A virtual stereo effect that renders monophonic audio as stereo audio. + @JsonValue(0x02010500) + /// + /// The virtual stereo effect, which renders monophonic audio as stereo audio. + /// Before using this preset, set the profile parameter of setAudioProfile to MusicHighQuality or MusicHighQualityStereo. Otherwise, the preset setting is invalid. /// - /// **Note** /// - /// Call `setAudioProfile` and set the profile parameter to `MusicStandardStereo(3)` or `MusicHighQualityStereo(5)` before setting this enumerator; otherwise, the enumerator setting does not take effect. - @JsonValue(0x02010500) RoomAcousticsVirtualStereo, - /// A more spatial audio effect. + @JsonValue(0x02010600) /// - /// **Note** + /// A more spatial voice effect. /// - /// To achieve better audio effect quality, Agora recommends calling [RtcEngine.setAudioProfile] and setting the profile parameter to `MusicHighQuality(4)` or `MusicHighQualityStereo(5)` before setting this enumerator. - @JsonValue(0x02010600) RoomAcousticsSpacial, - /// A more ethereal audio effect. + @JsonValue(0x02010700) /// - /// **Note** + /// A more ethereal voice effect. /// - /// To achieve better audio effect quality, Agora recommends calling [RtcEngine.setAudioProfile] and setting the profile parameter to `MusicHighQuality(4)` or `MusicHighQualityStereo(5)` before setting this enumerator. - @JsonValue(0x02010700) RoomAcousticsEthereal, - /// A 3D voice effect that makes the voice appear to be moving around the user. The default cycle period of the 3D voice effect is 10 seconds. To change the cycle period, call [RtcEngine.setAudioEffectParameters] after this method. + @JsonValue(0x02010800) + /// + /// A 3D voice effect that makes the voice appear to be moving around the user. The default movement cycle is 10 seconds. After setting this effect, you can call setAudioEffectParameters to modify the movement period. + /// + /// + /// Before using this preset, set the profile parameter of setAudioProfile to MusicStandardStereo or MusicHighQualityStereo. Otherwise, the preset setting is invalid. + /// If the 3D voice effect is enabled, users need to use stereo audio playback devices to hear the anticipated voice effect. + /// + /// /// - /// **Note** /// - /// - Call setAudioProfile and set the profile parameter to `MusicStandardStereo(3)` or `MusicHighQualityStereo(5)` before setting this enumerator; otherwise, the enumerator setting does not take effect. - /// - If the 3D voice effect is enabled, users need to use stereo audio playback devices to hear the anticipated voice effect. - @JsonValue(0x02010800) RoomAcoustics3DVoice, - /// The voice of a middle-aged man. + @JsonValue(0x02020100) + /// + /// A middle-aged man's voice. + /// Agora recommends using this preset to process a male-sounding voice; + /// otherwise, you might not hear the anticipated voice effect. /// - /// **Note** /// - /// - Agora recommends using this enumerator to process a male-sounding voice; otherwise, you may not hear the anticipated voice effect. - /// - To achieve better audio effect quality, Agora recommends calling [RtcEngine.setAudioProfile] and setting the profile parameter to `MusicHighQuality(4)` or `MusicHighQualityStereo(5)` before setting this enumerator. - @JsonValue(0x02020100) VoiceChangerEffectUncle, - /// The voice of an old man. + @JsonValue(0x02020200) + /// + /// A senior man's voice. + /// Agora recommends using this preset to process a male-sounding voice; + /// otherwise, you might not hear the anticipated voice effect. /// - /// **Note** /// - /// - Agora recommends using this enumerator to process a male-sounding voice; otherwise, you may not hear the anticipated voice effect. - /// - To achieve better audio effect quality, Agora recommends calling [RtcEngine.setAudioProfile] and setting the profile parameter to `MusicHighQuality(4)` or `MusicHighQualityStereo(5)` before setting this enumerator. - @JsonValue(0x02020200) VoiceChangerEffectOldMan, - /// The voice of a boy. + @JsonValue(0x02020300) + /// + /// A boy's voice. + /// Agora recommends using this preset to process a male-sounding voice; + /// otherwise, you might not hear the anticipated voice effect. /// - /// **Note** /// - /// - Agora recommends using this enumerator to process a male-sounding voice; otherwise, you may not hear the anticipated voice effect. - /// - To achieve better audio effect quality, Agora recommends calling [RtcEngine.setAudioProfile] and setting the profile parameter to `MusicHighQuality(4)` or `MusicHighQualityStereo(5)` before setting this enumerator. - @JsonValue(0x02020300) VoiceChangerEffectBoy, - /// The voice of a young woman. + @JsonValue(0x02020400) + /// + /// A young woman's voice. + /// Agora recommends using this preset to process a female-sounding voice; otherwise, you may not hear the anticipated voice effect. /// - /// **Note** /// - /// - Agora recommends using this enumerator to process a female-sounding voice; otherwise, you may not hear the anticipated voice effect. - /// - To achieve better audio effect quality, Agora recommends calling [RtcEngine.setAudioProfile] and setting the profile parameter to `MusicHighQuality(4)` or `MusicHighQualityStereo(5)` before setting this enumerator. - @JsonValue(0x02020400) VoiceChangerEffectSister, - /// The voice of a girl. + @JsonValue(0x02020500) + /// + /// A girl's voice. + /// Agora recommends using this preset to process a female-sounding voice; otherwise, you may not hear the anticipated voice effect. /// - /// **Note** /// - /// - Agora recommends using this enumerator to process a male-sounding voice; otherwise, you may not hear the anticipated voice effect. - /// - To achieve better audio effect quality, Agora recommends calling [RtcEngine.setAudioProfile] and setting the profile parameter to `MusicHighQuality(4)` or `MusicHighQualityStereo(5)` before setting this enumerator. - @JsonValue(0x02020500) VoiceChangerEffectGirl, - /// The voice of Pig King, a character in Journey to the West who has a voice like a growling bear. + @JsonValue(0x02020600) /// - /// **Note** + /// The voice of Pig King, a character in Journey to the West who has a voice like a growling bear. /// - /// To achieve better audio effect quality, Agora recommends calling [RtcEngine.setAudioProfile] and setting the profile parameter to `MusicHighQuality(4)` or `MusicHighQualityStereo(5)` before setting this enumerator. - @JsonValue(0x02020600) VoiceChangerEffectPigKing, - /// The voice of Hulk. + @JsonValue(0x02020700) /// - /// **Note** + /// The Hulk's voice. /// - /// To achieve better audio effect quality, Agora recommends calling [RtcEngine.setAudioProfile] and setting the profile parameter to `MusicHighQuality(4)` or `MusicHighQualityStereo(5)` before setting this enumerator. - @JsonValue(0x02020700) VoiceChangerEffectHulk, - /// An audio effect typical of R&B music. + @JsonValue(0x02030100) + /// + /// The voice effect typical of R&B music. + /// Before using this preset, set the profile parameter of setAudioProfile to MusicHighQuality or MusicHighQualityStereo. Otherwise, the preset setting is invalid. /// - /// **Note** /// - /// Call [RtcEngine.setAudioProfile] and set the profile parameter to `MusicHighQuality(4)` or `MusicHighQualityStereo(5)` before setting this enumerator; otherwise, the enumerator setting does not take effect. - @JsonValue(0x02030100) StyleTransformationRnB, - /// An audio effect typical of popular music. + @JsonValue(0x02030200) + /// + /// The voice effect typical of popular music. + /// Before using this preset, set the profile parameter of setAudioProfile to MusicHighQuality or MusicHighQualityStereo. Otherwise, the preset setting is invalid. /// - /// **Note** /// - /// Call [RtcEngine.setAudioProfile] and set the profile parameter to `MusicHighQuality(4)` or `MusicHighQualityStereo(5)` before setting this enumerator; otherwise, the enumerator setting does not take effect. - @JsonValue(0x02030200) StyleTransformationPopular, - /// A pitch correction effect that corrects the user’s pitch based on the pitch of the natural C major scale. To change the basic mode and tonic pitch, call [RtcEngine.setAudioEffectParameters] after this method. + @JsonValue(0x02040100) /// - /// **Note** + /// A pitch correction effect that corrects the user's pitch based on the pitch of the natural C major scale. After setting this voice effect, you can call setAudioEffectParameters to adjust the basic mode of tuning and the pitch of the main tone. /// - /// To achieve better audio effect quality, Agora recommends calling [RtcEngine.setAudioProfile] and setting the profile parameter to `MusicHighQuality(4)` or `MusicHighQualityStereo(5)` before setting this enumerator. - @JsonValue(0x02040100) PitchCorrection, } +/// /// The options for SDK preset voice beautifier effects. +/// +/// enum VoiceBeautifierPreset { - /// Turn off voice beautifier effects and use the original voice. @JsonValue(0x00000000) + /// + /// Turn off voice beautifier effects and use the original voice. + /// VoiceBeautifierOff, - /// A more magnetic voice. - /// - /// **Note** + @JsonValue(0x01010100) /// + /// A more magnetic voice. /// Agora recommends using this enumerator to process a male-sounding voice; otherwise, you may experience vocal distortion. - @JsonValue(0x01010100) + /// ChatBeautifierMagnetic, - /// A fresher voice. + @JsonValue(0x01010200) /// + /// A fresher voice. /// Agora recommends using this enumerator to process a female-sounding voice; otherwise, you may experience vocal distortion. - @JsonValue(0x01010200) + /// + /// ChatBeautifierFresh, - /// A more vital voice. + @JsonValue(0x01010300) /// + /// A more vital voice. /// Agora recommends using this enumerator to process a female-sounding voice; otherwise, you may experience vocal distortion. - @JsonValue(0x01010300) + /// + /// ChatBeautifierVitality, - /// Singing beautifier effect. @JsonValue(0x01020100) + /// + /// Singing beautifier effect. + /// + /// If you call setVoiceBeautifierPreset(SingingBeautifier), you can beautify a male-sounding voice and add a reverberation effect that sounds like singing in a small room. Agora recommends using this enumerator to process a male-sounding voice; otherwise, you might experience vocal distortion. + /// If you call setVoiceBeautifierParameters(SingingBeautifier, param1, param2), you can beautify a male- or female-sounding voice and add a reverberation effect. + /// + /// + /// SingingBeautifier, - /// A more vigorous voice. @JsonValue(0x01030100) + /// + /// A more vigorous voice. + /// TimbreTransformationVigorous, - /// A deeper voice. @JsonValue(0x01030200) + /// + /// A deep voice. + /// TimbreTransformationDeep, - /// A mellower voice. @JsonValue(0x01030300) + /// + /// A mellower voice. + /// TimbreTransformationMellow, - /// A falsetto voice. @JsonValue(0x01030400) + /// + /// Falsetto. + /// TimbreTransformationFalsetto, - /// A fuller voice. @JsonValue(0x01030500) + /// + /// A fuller voice. + /// TimbreTransformationFull, - /// A clearer voice. @JsonValue(0x01030600) + /// + /// A clearer voice. + /// TimbreTransformationClear, - /// A more resounding voice. @JsonValue(0x01030700) + /// + /// A more resounding voice. + /// TimbreTransformationResounding, - /// A more ringing voice. @JsonValue(0x01030800) + /// + /// A more ringing voice. + /// TimbreTransformationRinging, } -/// The latency level of an audience member in a interactive live streaming. /// -/// **Note** +/// The latency level of an audience member in interactive live streaming. This enum takes effect only when the user role is set to Audience. +/// /// -/// Takes effect only when the user role is `Broadcaster`. enum AudienceLatencyLevelType { - /// 1: Low latency. @JsonValue(1) + /// + /// 1: Low latency. + /// LowLatency, - /// 2: (Default) Ultra low latency. @JsonValue(2) + /// + /// 2: (Default) Ultra low latency. + /// UltraLowLatency, } -/// The output log level of the SDK. +/// +/// The output log level of the SDK. +/// +/// enum LogLevel { - /// Do not output any log. @JsonValue(0x0000) + /// + /// 0: Do not output any log information. + /// None, - /// (Default) Output logs of the `Fatal`, `Error`, `Warn`, and `Info` level. - /// We recommend setting your log filter as this level. @JsonValue(0x0001) + /// + /// 0x0001: (Default) Output FATAL, ERROR, + /// WARN, and INFO level log information. We + /// recommend setting your log filter as this level. + /// Info, - /// Output logs of the `Fatal`, `Error`, and `Warn` level. @JsonValue(0x0002) + /// + /// 0x0002: Output FATAL, ERROR, and WARN level + /// log information. + /// Warn, - /// Output logs of the `Fatal` and `Error` level. @JsonValue(0x0004) + /// + /// 0x0004: Output FATAL and ERROR level log information. + /// Error, - /// Output logs of the `Fatal` level. @JsonValue(0x0008) + /// + /// 0x0008: Output FATAL level log information. + /// Fatal, } +/// /// The brightness level of the video image captured by the local camera. +/// +/// + /// + /// 1: The brightness level of the video image is too bright. + /// enum CaptureBrightnessLevelType { - /// The SDK does not detect the brightness level of the video image. - /// Wait a few seconds to get the brightness level from [CaptureBrightnessLevelType] in the next callback. @JsonValue(-1) + /// + /// -1: The SDK does not detect the brightness level of the video image. Wait a few seconds to get the brightness level from captureBrightnessLevel in the next callback. + /// Invalid, - /// The brightness level of the video image is normal. @JsonValue(0) + /// + /// 0: The brightness level of the video image is normal. + /// Normal, - /// The brightness level of the video image is too bright. @JsonValue(1) Bright, - /// The brightness level of the video image is too dark. @JsonValue(2) + /// + /// 2: The brightness level of the video image is too dark. + /// Dark, } -/// The reason why the super-resolution algorithm is not successfully enabled. +/// +/// The reason why super resolution is not successfully enabled. +/// Since +/// v3.5.1 +/// enum SuperResolutionStateReason { - /// 0: The super-resolution algorithm is successfully enabled. @JsonValue(0) + /// + /// 0: Super resolution is successfully enabled. + /// Success, - /// 1: The origin resolution of the remote video is beyond the range where the super-resolution algorithm can be applied. @JsonValue(1) + /// + /// 1: The original resolution of the remote video is beyond the range where super resolution can be applied. + /// StreamOverLimitation, - /// 2: Another user is already using the super-resolution algorithm. @JsonValue(2) + /// + /// 2: Super resolution is already being used to boost another remote user’s video. + /// UserCountOverLimitation, - /// 3: The device does not support the super-resolution algorithm. @JsonValue(3) + /// + /// 3: The device does not support using super resolution. + /// DeviceNotSupported, } +/// /// The reason for the upload failure. /// -/// @since v3.3.0. +/// enum UploadErrorReason { - /// 0: The log file is successfully uploaded. @JsonValue(0) + /// + /// 0: Successfully upload the log files. + /// Success, - /// 1: Network error. Check the network connection and call [`uploadLogFile`]{@link uploadLogFile} again to upload the log file. @JsonValue(1) + /// + /// 1: Network error. Check the network connection and call uploadLogFile again to upload the log file. + /// NetError, - /// 2: An error occurs in the Agora server. Try uploading the log files later. @JsonValue(2) + /// + /// 2: An error occurs in the Agora server. Try uploading the log files later. + /// ServerError, } +/// /// The cloud proxy type. +/// +/// enum CloudProxyType { - /// Do not use the cloud proxy. @JsonValue(0) + /// + /// 0: Do not use cloud proxy. + /// None, - /// The cloud proxy for the UDP protocol. @JsonValue(1) + /// + /// 1: Use cloud proxy with the UDP protocol. + /// UDP, - /// The cloud proxy for the TCP protocol. @JsonValue(2) TCP, } -/// Experience quality types. +/// +/// The Quality of Experience (QoE) of the local user when receiving a remote audio stream. +/// +/// enum ExperienceQualityType { - /// 0: Good experience quality. @JsonValue(0) + /// + /// 0: The QoE of the local user is good. + /// Good, - /// 1: Bad experience quality. @JsonValue(1) + /// + /// 1: The QoE of the local user is poor. + /// Bad, } -/// The reason for poor QoE of the local user when receiving a remote audio stream. +/// +/// Reasons why the QoE of the local user when receiving a remote audio stream is poor. +/// +/// enum ExperiencePoorReason { - /// None, indicating good QoE of the local user. @JsonValue(0) + /// + /// 0: No reason, indicating a good QoE of the local user. + /// None, - /// The remote user’s network quality is poor. @JsonValue(1) + /// + /// 1: The remote user's network quality is poor. + /// RemoteNetworkQualityPoor, - /// The local user’s network quality is poor. @JsonValue(2) + /// + /// 2: The local user's network quality is poor. + /// LocalNetworkQualityPoor, - /// The local user’s Wi-Fi or mobile network signal is weak. @JsonValue(4) + /// + /// 4: The local user's Wi-Fi or mobile network signal is weak. + /// WirelessSignalPoor, - /// The local user enables both Wi-Fi and bluetooth, and their signals interfere with each other. As a result, audio transmission quality is undermined. @JsonValue(8) + /// + /// 8: The local user enables both Wi-Fi and bluetooth, and their signals interfere with each other. As a result, audio transmission quality is undermined. + /// WifiBluetoothCoexist, } +/// /// The options for SDK preset voice conversion effects. +/// +/// enum VoiceConversionPreset { - /// Turn off voice conversion effects and use the original voice. @JsonValue(0) + /// + /// Turn off voice conversion effects and use the original voice. + /// Off, - /// A gender-neutral voice. To avoid audio distortion, ensure that you use this enumerator to process a female-sounding voice. @JsonValue(50397440) + /// + /// A gender-neutral voice. To avoid audio distortion, ensure that you use this enumerator to process a female-sounding voice. + /// Neutral, - /// A sweet voice. To avoid audio distortion, ensure that you use this enumerator to process a female-sounding voice. @JsonValue(50397696) + /// + /// A sweet voice. To avoid audio distortion, ensure that you use this enumerator to process a female-sounding voice. + /// Sweet, - /// A steady voice. To avoid audio distortion, ensure that you use this enumerator to process a male-sounding voice. @JsonValue(50397952) + /// + /// A steady voice. To avoid audio distortion, ensure that you use this enumerator to process a male-sounding voice. + /// Solid, - /// A deep voice. To avoid audio distortion, ensure that you use this enumerator to process a male-sounding voice. @JsonValue(50398208) + /// + /// A deep voice. To avoid audio distortion, ensure that you use this enumerator to process a male-sounding voice. + /// Bass, } +/// /// The type of the custom background image. +/// +/// enum VirtualBackgroundSourceType { - /// (Default) The background image is a solid color. @JsonValue(1) + /// + /// 1: (Default) The background image is a solid color. + /// Color, - /// The background image is a file in PNG or JPG format. @JsonValue(2) + /// + /// The background image is a file in PNG or JPG format. + /// Img, - /// The degree of blurring applied to the custom background image @JsonValue(3) + /// + /// The background image is the blurred background. + /// Blur, } -/// The degree of blurring applied to the custom background image +/// +/// The degree of blurring applied to the custom background image. +/// +/// enum VirtualBackgroundBlurDegree { - /// The degree of blurring applied to the custom background image is low. The - /// user can almost see the background clearly. @JsonValue(1) + /// + /// 1: The degree of blurring applied to the custom background image is low. The user can almost see the background clearly. + /// Low, - /// The degree of blurring applied to the custom background image is medium. - /// It is difficult for the user to recognize details in the background. @JsonValue(2) + /// + /// The degree of blurring applied to the custom background image is medium. It is difficult for the user to recognize details in the background. + /// Medium, - /// (Default) The degree of blurring applied to the custom background image is - /// high. The user can barely see any distinguishing features in the background. @JsonValue(3) + /// + /// (Default) The degree of blurring applied to the custom background image is high. The user can barely see any distinguishing features in the background. + /// High, } -/// The reason why the virtual background is not successfully enabled or the message that confirms success: +/// +/// The reason why virtual background is not successfully enabled. +/// Since +/// v3.5.0 +/// enum VirtualBackgroundSourceStateReason { - /// The virtual background is successfully enabled. @JsonValue(0) + /// + /// 0: The virtual background is successfully enabled. + /// Success, - /// The custom background image does not exist. Please check the value of source in VirtualBackgroundSource. @JsonValue(1) + /// + /// 1: The custom background image does not exist. Please check the value of source in VirtualBackgroundSource. + /// ImageNotExist, - /// The color format of the custom background image is invalid. Please check the value of color in VirtualBackgroundSource. @JsonValue(2) + /// + /// 2: The color format of the custom background image is invalid. Please check the value of color in VirtualBackgroundSource. + /// ColorFormatNotSupported, - /// The device does not support using the virtual background. @JsonValue(3) + /// + /// 3: The device does not support using the virtual background. + /// DeviceNotSupported, } + +/// +/// The content hint for screen sharing. +/// +/// +enum VideoContentHint { + @JsonValue(0) + /// + /// (Default) No content hint. + /// + None, + + @JsonValue(1) + /// + /// Motion-intensive content. Choose this option if you prefer smoothness or when you are sharing a video clip, movie, or video game. + /// + Motion, + + @JsonValue(2) + /// + /// Motionless content. Choose this option if you prefer sharpness or when you are sharing a + /// picture, PowerPoint slides, or texts. + /// + Details, +} + +/// +/// Media device types. +/// +/// +enum MediaDeviceType { + @JsonValue(-1) + /// + /// -1: Unknown device type. + /// + UnknownAudioDevice, + + @JsonValue(0) + /// + /// 0: Audio playback device. + /// + AudioPlayoutDevice, + + @JsonValue(1) + /// + /// 1: Audio capturing device. + /// + AudioRecordingDevice, + + @JsonValue(2) + /// + /// 2: Video renderer. + /// + VideoRenderDevice, + + @JsonValue(3) + /// + /// 3: Video capturer. + /// + VideoCaptureDevice, + + @JsonValue(4) + /// + /// 4: Application audio playback device. + /// + AudioApplicationPlayoutDevice, +} + +/// +/// Media device states. +/// +/// +enum MediaDeviceStateType { + @JsonValue(0) + /// + /// 0: The device is ready for use. + /// + MediaDeviceStateIdle, + + @JsonValue(1) + /// + /// 1: The device is in use. + /// + MediaDeviceStateActive, + + @JsonValue(2) + /// + /// 2: The device is disabled. + /// + MediaDeviceStateDisabled, + + @JsonValue(4) + /// + /// 4: The device is not found. + /// + MediaDeviceStateNotPresent, + + @JsonValue(8) + /// + /// 8: The device is unplugged. + /// + MediaDeviceStateUnplugged, + + @JsonValue(16) + MediaDeviceStateUnrecommended, +} + +/* enum-RecorderState */ +enum RecorderState { + @JsonValue(-1) + Error, + + @JsonValue(2) + Start, + + @JsonValue(3) + Stop, +} + +/* enum-RecorderError */ +enum RecorderError { + @JsonValue(0) + RECORDER_ERROR_NONE, + + @JsonValue(1) + RECORDER_ERROR_WRITE_FAILED, + + @JsonValue(2) + RECORDER_ERROR_NO_STREAM, + + @JsonValue(3) + RECORDER_ERROR_OVER_MAX_DURATION, + + @JsonValue(4) + RECORDER_ERROR_CONFIG_CHANGED, + + @JsonValue(5) + RECORDER_ERROR_CUSTOM_STREAM_DETECTED, +} + +/* enum-AgoraMediaRecorderContainerFormat */ +enum AgoraMediaRecorderContainerFormat { + @JsonValue(1) + MP4, +} + +/* enum-AgoraMediaRecorderStreamType */ +enum AgoraMediaRecorderStreamType { + @JsonValue(1) + Audio, + + @JsonValue(2) + Video, + + @JsonValue(3) + Both, +} diff --git a/lib/src/events.dart b/lib/src/events.dart index 487deb93b..2383876d6 100644 --- a/lib/src/events.dart +++ b/lib/src/events.dart @@ -1,3 +1,10 @@ +import 'dart:convert'; +import 'dart:io'; +import 'dart:typed_data'; + +import 'package:flutter/foundation.dart'; +import 'package:flutter/material.dart'; + import 'classes.dart'; import 'enum_converter.dart'; import 'enums.dart'; @@ -101,7 +108,7 @@ typedef StreamInjectedStatusCallback = void Function( String url, int uid, InjectStreamStatus status); // ignore: public_member_api_docs typedef StreamMessageCallback = void Function( - int uid, int streamId, String data); + int uid, int streamId, Uint8List data); // ignore: public_member_api_docs typedef StreamMessageErrorCallback = void Function( int uid, int streamId, ErrorCode error, int missed, int cached); @@ -128,8 +135,7 @@ typedef EnabledCallback = void Function(bool enabled); typedef AudioQualityCallback = void Function( int uid, int quality, int delay, int lost); // ignore: public_member_api_docs -typedef MetadataCallback = void Function( - String buffer, int uid, int timeStampMs); +typedef MetadataCallback = void Function(Metadata metadata); // ignore: public_member_api_docs typedef FacePositionCallback = void Function( int imageWidth, int imageHeight, List faces); @@ -158,941 +164,1242 @@ typedef UploadLogResultCallback = void Function( // ignore: public_member_api_docs typedef VirtualBackgroundSourceEnabledCallback = void Function( bool enabled, VirtualBackgroundSourceStateReason reason); +typedef VideoDeviceStateChanged = void Function( + String deviceId, + MediaDeviceType deviceType, + MediaDeviceStateType deviceState, +); +// ignore: public_member_api_docs +typedef AudioDeviceVolumeChanged = void Function( + MediaDeviceType deviceType, + int volume, + bool muted, +); +// ignore: public_member_api_docs +typedef AudioDeviceStateChanged = void Function( + String deviceId, + MediaDeviceType deviceType, + MediaDeviceStateType deviceState, +); +// ignore: public_member_api_docs +typedef RemoteAudioMixingBegin = void Function(); +// ignore: public_member_api_docs +typedef RemoteAudioMixingEnd = void Function(); +// ignore: public_member_api_docs +typedef RecorderStateChangedCallback = void Function( + RecorderState state, RecorderError error); // ignore: public_member_api_docs typedef SnapshotTakenCallback = void Function(String channel, int uid, String filePath, int width, int height, int errCode); -/// The SDK uses the [RtcEngineEventHandler] class to send callbacks to the application, and the application inherits the methods of this class to retrieve these callbacks. /// -/// All methods in this class have their (empty) default implementations, and the application can inherit only some of the required events instead of all of them. +/// The SDK uses the RtcEngineEventHandler interface to send event notifications to your app. Your app can get those notifications through methods that inherit this interface. +/// /// -/// In the callbacks, the application should avoid time-consuming tasks or call blocking APIs (such as SendMessage), otherwise, the SDK may not work properly. class RtcEngineEventHandler { + /// /// Reports a warning during SDK runtime. + /// Occurs when a warning occurs during SDK runtime. In most cases, the app can ignore the warnings reported by the SDK because the SDK can usually fix the issue and resume running. For example, when losing connection with the server, the SDK may report WARN_LOOKUP_CHANNEL_TIMEOUT and automatically try to reconnect. /// - /// In most cases, the app can ignore the warning reported by the SDK because the SDK can usually fix the issue and resume running. + /// Param [warn] Warning codes. /// - /// For instance, the SDK may report a [WarningCode.LookupChannelTimeout] warning upon disconnection with the server and tries to reconnect. For detailed warning codes, see [WarningCode]. + /// Param [msg] Warning description. /// - /// The `WarningCallback` typedef includes the following parameter: - /// - [WarningCode] `warn`: Warning code. WarningCallback? warning; - /// Reports an error during SDK runtime. /// - /// In most cases, the SDK cannot fix the issue and resume running. The SDK requires the app to take action or informs the user about the issue. + /// Reports an error during SDK runtime. + /// This callback indicates that an error (concerning network or media) occurs during SDK runtime. In most cases, the SDK cannot fix the issue and resume running. The SDK requires the application to take action or informs the user about the issue. For example, the SDK reports an ERR_START_CALL error when failing to initialize a call. The app informs the user that the call initialization failed and calls leaveChannel to leave the channel. /// - /// For example, the SDK reports an [ErrorCode.StartCall] error when failing to initialize a call. The app informs the user that the call initialization failed and invokes the [RtcEngine.leaveChannel] method to leave the channel. For detailed error codes, see [ErrorCode]. + /// Param [err] The error code. /// - /// The `ErrorCallback` typedef includes the following parameter: - /// - [ErrorCode] `err`: Error code. ErrorCallback? error; - /// Occurs when an API method is executed. /// - /// The `ApiCallCallback` typedef includes the following parameters: - /// - [ErrorCode] `error`: Error code. - /// - [String] `api`: The method executed by the SDK. - /// - [String] `result`: The result of the method call. + /// Occurs when a method is executed by the SDK. + /// + /// + /// Param [error] The error code returned by the SDK when the method call fails. + /// + /// Param [api] The method executed by the SDK. + /// + /// Param [result] The result of the method call. + /// ApiCallCallback? apiCallExecuted; - /// Occurs when the local user joins a specified channel. /// - /// The channel name assignment is based on channelName specified in the [RtcEngine.joinChannel] method. + /// Occurs when a user joins a channel. + /// This callback notifies the application that a user joins a specified channel. + /// + /// Param [channel] The name of the channel. + /// + /// Param [uid] The ID of the user who joins the channel. /// - /// If the uid is not specified when [RtcEngine.joinChannel] is called, the server automatically assigns a uid. + /// Param [elapsed] The time elapsed (ms) from the local user calling joinChannel until the SDK triggers this callback. /// - /// The `UidWithElapsedAndChannelCallback` typedef includes the following parameters: - /// - [String] `channel`: Channel name. - /// - [int] `uid`: User ID. - /// - [int] `elapsed`:Time elapsed (ms) from the user calling [RtcEngine.joinChannel] until this callback is triggered. UidWithElapsedAndChannelCallback? joinChannelSuccess; - /// Occurs when a user rejoins the channel after being disconnected due to network problems. /// + /// Occurs when a user rejoins the channel. /// When a user loses connection with the server because of network problems, the SDK automatically tries to reconnect and triggers this callback upon reconnection. /// - /// The `UidWithElapsedAndChannelCallback` typedef includes the following parameters: - /// - [String] `channel`: Channel name. - /// - [int] `uid`: User ID. - /// - [int] `elapsed`:Time elapsed (ms) from the user calling [RtcEngine.joinChannel] until this callback is triggered. + /// Param [channel] The name of the channel. + /// + /// Param [uid] The ID of the user who rejoins the channel. + /// + /// Param [elapsed] Time elapsed (ms) from starting to reconnect until the SDK triggers this + /// callback. + /// UidWithElapsedAndChannelCallback? rejoinChannelSuccess; - /// Occurs when a user leaves the channel. /// - /// When the app calls the [RtcEngine.leaveChannel] method, the SDK uses this callback to notify the app when the user leaves the channel. + /// Occurs when a user leaves a channel. + /// This callback notifies the app that the user leaves the channel by calling leaveChannel. From this callback, the app can get information such as the call duration and quality statistics. /// - /// With this callback, the application retrieves the channel information, such as the call duration and statistics. + /// Param [stats] The statistics of the call, see RtcStats . /// - /// The `RtcStatsCallback` typedef includes the following parameter: - /// - [RtcStats] `stats`: Statistics of the call. RtcStatsCallback? leaveChannel; + /// /// Occurs when the local user registers a user account. + /// After the local user successfully calls registerLocalUserAccount to register the user account or calls joinChannelWithUserAccount to join a channel, the SDK triggers the callback and informs the local user's UID and User Account. + /// + /// Param [uid] The ID of the local user. /// - /// This callback is triggered when the local user successfully registers a user account by calling the [RtcEngine.registerLocalUserAccount] method, or joins a channel by calling the [RtcEngine.joinChannelWithUserAccount] method. This callback reports the user ID and user account of the local user. + /// Param [userAccount] The user account of the local user. /// - /// The `UserAccountCallback` typedef includes the following parameters: - /// - [int] `uid`: The ID of the local user. - /// - [String] `userAccount`: The account of the local user. UserAccountCallback? localUserRegistered; + /// /// Occurs when the SDK gets the user ID and user account of the remote user. + /// After a remote user joins the channel, the SDK gets the UID and user account of the remote user, caches them in a mapping table object, and triggers this callback on the local client. + /// + /// Param [uid] The ID of the remote user. /// - /// After a remote user joins the channel, the SDK gets the UID and user account of the remote user, caches them in a mapping table object ([UserInfo]), and triggers this callback on the local client. + /// Param [userInfo] The UserInfo object that contains the user ID and user account of the remote user. See UserInfo for details. /// - /// The `UserInfoCallback` typedef includes the following parameters: - /// - [int] `uid`: The ID of the local user. - /// - [UserInfo] `userInfo`: The `UserInfo` object that contains the user ID and user account of the remote user. UserInfoCallback? userInfoUpdated; - /// Occurs when the user role switches in a live broadcast. For example, from a host to an audience or from an audience to a host. /// - /// The SDK triggers this callback when the local user switches the user role by calling the [RtcEngine.setClientRole] method after joining the channel. + /// Occurs when the user role switches in the interactive live streaming. + /// The SDK triggers this callback when the local user switches the user role after joining the channel. + /// + /// Param [oldRole] Role that the user switches from: ClientRole. + /// + /// Param [newRole] Role that the user switches to: ClientRole. /// - /// The `ClientRoleCallback` typedef includes the following parameters: - /// - [ClientRole] `oldRole`: Role that the user switches from. - /// - [ClientRole] `newRole`: Role that the user switches to. ClientRoleCallback? clientRoleChanged; - /// Occurs when a remote user ([ChannelProfile.Communication])/host ([ChannelProfile.LiveBroadcasting]) joins the channel. - /// - [ChannelProfile.Communication] profile: This callback notifies the app when another user joins the channel. If other users are already in the channel, the SDK also reports to the app on the existing users. - /// - [ChannelProfile.LiveBroadcasting] profile: This callback notifies the app when the host joins the channel. If other hosts are already in the channel, the SDK also reports to the app on the existing hosts. We recommend having at most 17 hosts in a channel. /// - /// The SDK triggers this callback under one of the following circumstances: - /// - A remote user/host joins the channel by calling the [RtcEngine.joinChannel] method. - /// - A remote user switches the user role to the host by calling the [RtcEngine.setClientRole] method after joining the channel. - /// - A remote user/host rejoins the channel after a network interruption. - /// - The host injects an online media stream into the channel by calling the [RtcEngine.addInjectStreamUrl] method. - /// - /// **Note** - /// - In the [ChannelProfile.LiveBroadcasting] profile: - /// -- The host receives the `userJoined` callback when another host joins the channel. - /// -- The audience in the channel receives the `userJoined` callback when a new host joins the channel. - /// -- When a web application joins the channel, the `userJoined` callback is triggered as long as the web application publishes streams. - /// - /// The `UidWithElapsedCallback` typedef includes the following parameters: - /// - [int] `uid`: This parameter has the following definitions in different events: - /// - [userJoined]: ID of the user or host who joins the channel. - /// - [firstRemoteAudioFrame]: User ID of the remote user. - /// - [firstRemoteAudioDecoded]: User ID of the remote user sending the audio stream. - /// - [joinChannelSuccess]: User ID. - /// - [rejoinChannelSuccess]: User ID. - /// - [int] `elapsed`: - /// - [userJoined]: Time delay (ms) from the local user calling [RtcEngine.joinChannel] or [RtcEngine.setClientRole] until this callback is triggered. - /// - [firstRemoteAudioFrame]: Time elapsed (ms) from the local user calling [RtcEngine.joinChannel] until this callback is triggered. - /// - [firstRemoteAudioDecoded]: Time elapsed (ms) from the local user calling [RtcEngine.joinChannel] until the SDK triggers this callback. - /// - [joinChannelSuccess]: Time elapsed (ms) from the local user calling [RtcChannel.joinChannel] until this callback is triggered. - /// - [rejoinChannelSuccess]: Time elapsed (ms) from the local user starting to reconnect until this callback is triggered. + /// Occurs when a remote user (COMMUNICATION)/ host (LIVE_BROADCASTING) joins the channel. + /// In a communication channel, this callback indicates that a remote user joins the channel. The SDK also triggers this callback to report the existing users in the channel when a user joins the channel. + /// In a live-broadcast channel, this callback indicates that a host joins the channel. The SDK also triggers this callback to report the existing hosts in the channel when a host joins the channel. Agora recommends limiting the number of hosts to 17. + /// + /// The SDK triggers this callback under one of the following circumstances: + /// A remote user/host joins the channel by calling the joinChannel method. + /// A remote user switches the user role to the host after joining the channel. + /// A remote user/host rejoins the channel after a network interruption. + /// + /// Param [uid] The ID of the user or host who joins the channel. + /// + /// Param [elapsed] Time delay (ms) from the local user calling joinChannel + /// until this callback is triggered. + /// UidWithElapsedCallback? userJoined; - /// Occurs when a remote user ([ChannelProfile.Communication])/host ([ChannelProfile.LiveBroadcasting]) leaves the channel. /// + /// Occurs when a remote user (COMMUNICATION)/ host (LIVE_BROADCASTING) leaves the channel. /// There are two reasons for users to become offline: - /// - Leave the channel: When the user/host leaves the channel, the user/host sends a goodbye message. When this message is received, the SDK determines that the user/host leaves the channel. - /// - Drop offline: When no data packet of the user or host is received for a certain period of time (20 seconds for the [ChannelProfile.Communication] profile, and more for the [ChannelProfile.LiveBroadcasting] profile), the SDK assumes that the user/host drops offline. A poor network connection may lead to false detections, so we recommend using the Agora RTM SDK for reliable offline detection. + /// Leave the channel: When a user/host leaves the channel, the user/host sends a goodbye message. When this message is received, the SDK determines that the user/host leaves the channel. + /// Drop offline: When no data packet of the user or host is received for a certain period of time (20 seconds for the communication profile, and more for the live broadcast profile), the SDK assumes that the user/host drops offline. A poor network connection may lead to false detections. It's recommended to use the Agora RTM SDK for reliable offline detection. + /// + /// Param [uid] The ID of the user who leaves the channel or goes offline. + /// + /// Param [reason] Reasons why the user goes offline: UserOfflineReason. /// - /// The `UserOfflineCallback` typedef includes the following parameters: - /// - [int] `uid`: ID of the user or host who leaves the channel or goes offline. - /// - [UserOfflineReason] `reason`: Reason why the user goes offline. UserOfflineCallback? userOffline; + /// /// Occurs when the network connection state changes. + /// When the network connection state changes, the SDK triggers this callback and reports the current connection state and the reason for the change. + /// + /// Param [state] The current connection state. + /// + /// + /// Param [reason] The reason for a connection state change. + /// /// - /// The Agora SDK returns this callback to report on the current network connection state when it changes, and the reason to such change. /// - /// The `ConnectionStateCallback` typedef includes the following parameters: - /// - [ConnectionStateType] `state`: The current network connection state. - /// - [ConnectionChangedReason] `reason`: The reason causing the change of the connection state. ConnectionStateCallback? connectionStateChanged; - /// Occurs when the network type changes. /// - /// The SDK returns the current network type in this callback. When the network connection is interrupted, this callback indicates whether the interruption is caused by a network type change or poor network conditions. + /// Occurs when the local network type changes. + /// This callback occurs when the connection state of the local user changes. You can get the connection state and reason for the state change in this callback. When the network connection is interrupted, this callback indicates whether the interruption is caused by a network type change or poor network conditions. + /// + /// Param [type] The type of the local network connection. + /// For details, see NetworkType. /// - /// The `NetworkTypeCallback` typedef includes the following parameters: - /// - [NetworkType] `type`: The network type. NetworkTypeCallback? networkTypeChanged; - /// Occurs when the SDK cannot reconnect to Agora's edge server 10 seconds after its connection to the server is interrupted. /// - /// The SDK triggers this callback when it cannot connect to the server 10 seconds after calling [RtcEngine.joinChannel], regardless of whether it is in the channel or not. - /// If the SDK fails to rejoin the channel 20 minutes after being disconnected from Agora's edge server, the SDK stops rejoining the channel. + /// Occurs when the SDK cannot reconnect to Agora's edge server 10 seconds after its connection to the server is interrupted. + /// The SDK triggers this callback when it cannot connect to the server 10 seconds after + /// calling the joinChannel method, regardless of whether it is in + /// the channel. If the SDK fails to rejoin the channel 20 minutes after being + /// disconnected from Agora's edge server, the SDK stops rejoining the channel. /// - /// The `EmptyCallback` typedef does not include any parameter. EmptyCallback? connectionLost; + /// /// Occurs when the token expires in 30 seconds. + /// When the token is about to expire in 30 seconds, the SDK triggers this callback to remind the app to renew the token. + /// Upon receiving this callback, generate a new token on your server, and call renewToken to pass the new token to the SDK. /// - /// The user becomes offline if the token used when joining the channel expires. This callback is triggered 30 seconds before the token expires to remind the app to get a new token. Upon receiving this callback, you need to generate a new token on the server and call [RtcEngine.renewToken] to pass the new token to the SDK. + /// Param [token] The token that expires in 30 seconds. /// - /// The `TokenCallback` typedef includes the following parameters: - /// - [String] `token`: The token that will expire in 30 seconds. TokenCallback? tokenPrivilegeWillExpire; - /// Occurs when the token has expired. /// - /// After a token is specified when joining the channel, the token expires after a certain period of time, and a new token is required to reconnect to the server. This callback notifies the app to generate a new token and call [RtcEngine.joinChannel] to rejoin the channel with the new token. + /// Occurs when the token expires. + /// When the token expires during a call, the SDK triggers this callback to + /// remind the app to renew the token. + /// Once you receive this callback, generate a new token on your app server, and call + /// joinChannel to rejoin the channel. /// - /// The `EmptyCallback` typedef does not include any parameter. EmptyCallback? requestToken; - /// Reports which users are speaking and the speakers' volume, and whether the local user is speaking. /// - /// This callback reports the IDs and volumes of the loudest speakers (at most 3) at the moment in the channel, and whether the local user is speaking. - /// By default, this callback is disabled. You can enable it by calling the [RtcEngine.enableAudioVolumeIndication] method. Once enabled, this callback is triggered at the set interval, regardless of whether a user speaks or not. - /// The SDK triggers two independent [audioVolumeIndication] callbacks at one time, which separately report the volume information of the local user and all the remote speakers. For more information, see the detailed parameter descriptions. + /// Reports the volume information of users. + /// By default, this callback is disabled. You can enable it by calling enableAudioVolumeIndication. Once this callback is enabled and users send streams in the channel, the SDK triggers the enableAudioVolumeIndication callback at the time interval set in audioVolumeIndication. The SDK triggers two independent audioVolumeIndication callbacks simultaneously, which separately report the volume information of the local user who sends a stream and the remote users (up to three) whose instantaneous volumes are the highest. + /// After you enable this callback, calling muteLocalAudioStream affects the SDK's behavior as follows: + /// If the local user stops publishing the audio stream, the SDK stops triggering the local user's callback. + /// 20 seconds after a remote user whose volume is one of the three highest stops publishing the audio stream, the callback excludes this user's information; 20 seconds after all remote users stop publishing audio streams, the SDK stops triggering the callback for remote users. + /// + /// Param [speakers] The volume information of the users, see AudioVolumeInfo. An empty speakers array in the callback indicates that no remote user is in the channel or sending a stream at the moment. + /// + /// Param [totalVolume] The volume of the speaker. The value range is [0,255]. + /// In the callback for the local user, totalVolume is the volume of the local user who sends a stream. + /// In the callback for remote users, totalVolume is the sum of the volume of all remote users (up to three) whose instantaneous volumes are the highest. If the user calls startAudioMixing, then totalVolume is the volume after audio mixing. + /// + /// /// - /// **Note** - /// - To enable the voice activity detection of the local user, ensure that you set `report_vad`(true) in the [RtcEngine.enableAudioVolumeIndication] method. - /// - Calling the [RtcEngine.muteLocalAudioStream] method affects the SDK's behavior. - /// -- If the local user calls the [RtcEngine.muteLocalAudioStream] method, the SDK stops triggering the local user's callback. - /// -- 20 seconds after a remote speaker calls the [RtcEngine.muteLocalAudioStream] method, the remote speakers' callback does not include information of this remote user; 20 seconds after all remote users call the the [RtcEngine.muteLocalAudioStream] method, the SDK stops triggering the remote speakers' callback. /// - /// The `AudioVolumeCallback` typedef includes the following parameters: - /// - [List]<[AudioVolumeInfo]> `speakers`: An array containing the user ID and volume information for each speaker. - /// - [int] `totalVolume`: Total volume after audio mixing. The value ranges between 0 (lowest volume) and 255 (highest volume). AudioVolumeCallback? audioVolumeIndication; - /// Reports which user is the loudest speaker. /// - /// This callback reports the speaker with the highest accumulative volume during a certain period. If the user enables the audio volume indication by calling [RtcEngine.enableAudioVolumeIndication], this callback returns the uid of the active speaker whose voice is detected by the audio volume detection module of the SDK. + /// Occurs when the most active speaker is detected. + /// After a successful call of enableAudioVolumeIndication, the SDK continuously detects which remote user has the loudest volume. During the current period, the remote user, who is detected as the loudest for the most times, is the most active user. + /// When the number of users exceeds two (included) and an active speaker is detected, the SDK triggers this callback and reports the uid of the most active speaker. + /// If the most active speaker remains the same, the SDK triggers the activeSpeaker callback only once. + /// If the most active speaker changes to another user, the SDK triggers this callback again and reports the uid of the new active speaker. /// - /// **Note** - /// - To receive this callback, you need to call [RtcEngine.enableAudioVolumeIndication]. - /// - This callback returns the user ID of the user with the highest voice volume during a period of time, instead of at the moment. + /// Param [uid] The user ID of the most active speaker. /// - /// The `UidCallback` typedef includes the following parameters: - /// - [int] `uid`: User ID of the active speaker. A `uid` of 0 represents the local user. UidCallback? activeSpeaker; - /// Occurs when the first local audio frame is sent. /// - /// The `ElapsedCallback` typedef includes the following parameters: - /// - [int] `Elapsed`: Time elapsed (ms) from the local user calling the [RtcEngine.joinChannel] until this callback is triggered. + /// Occurs when the engine sends the first local audio frame. + /// Deprecated: + /// Please use + /// instead. + /// + /// Param [elapsed] The time elapsed (ms) from the local user calling joinChannel until the SDK triggers this callback. + /// @deprecated ElapsedCallback? firstLocalAudioFrame; + /// /// Occurs when the first local video frame is rendered. + /// The SDK triggers this callback when the first local video frame is displayed/rendered on the local video view. + /// + /// Param [width] The width (px) of the first local video frame. /// - /// This callback is triggered after the first local video frame is rendered on the local video window. + /// Param [height] The height (px) of the first local video frame. + /// + /// Param [elapsed] The time elapsed (ms) from the local user calling joinChanneluntil the SDK triggers this callback. If you + /// call startPreview before calling joinChannel, then this parameter is the time elapsed from + /// calling the startPreview method until the SDK + /// triggers this callback. /// - /// The `VideoFrameCallback` typedef includes the following parameters: - /// - [int] `width`: Width (pixels) of the first local video frame. - /// - [int] `height`: Height (pixels) of the first local video frame. - /// - [int] `elapsed`: Time elapsed (ms) from the local user calling [RtcEngine.joinChannel] until this callback is triggered. If [RtcEngine.startPreview] is called before [RtcEngine.joinChannel], elapsed is the time elapsed (ms) from the local user calling [RtcEngine.startPreview] until this callback is triggered. VideoFrameCallback? firstLocalVideoFrame; - /// Occurs when a remote user stops or resumes publishing the video stream. /// - /// **Deprecated** This callback is deprecated. Use the [RtcEngineEventHandler.remoteVideoStateChanged] callback with the following parameters for the same function: - /// - [VideoRemoteState.Stopped] and [VideoRemoteStateReason.RemoteMuted]. - /// - [VideoRemoteState.Decoding] and [VideoRemoteStateReason.RemoteUnmuted]. + /// Occurs when a remote user's video stream playback pauses/resumes. + /// The SDK triggers this callback when the remote user stops or resumes sending the video stream by calling the muteLocalVideoStream method. + /// This callback does not work properly when the number of users (in the COMMUNICATION profile) or hosts (in the LIVE_BROADCASTING profile) in the channel exceeds 17. /// - /// When a remote user calls `muteLocalVideoStream` to stop or resume publishing the video stream, the SDK triggers this callback to report the state of the remote user's publishing stream to the local user. + /// Param [uid] The ID of the remote user. /// + /// Param [muted] Whether the remote user's video stream playback is paused/resumed: + /// true: Paused. + /// false: Resumed. /// - /// **Note** - /// This callback can be inaccurate when the number of users in a channel exceeds 17. /// - /// The `UidWithMutedCallback` typedef includes the following parameters: - /// - [int] `uid`: ID of the remote user. - /// - [bool] `muted`: Whether the remote user stops publishing the video stream: - /// - `true`: Stop publishing the video stream. - /// - `false`: Publish the video stream. @deprecated UidWithMutedCallback? userMuteVideo; - /// Occurs when the video size or rotation information of a remote user changes. /// - /// The `VideoSizeCallback` typedef includes the following parameters: - /// - [int] `uid`: User ID of the remote user or local user (0) whose video size or rotation changes. - /// - [int] `width`: New width (pixels) of the video. - /// - [int] `height`: New height (pixels) of the video. - /// - [int] `rotation`: New rotation of the video [0 to 360). + /// Occurs when the video size or rotation of a specified user changes. + /// + /// + /// Param [uid] The ID of the user whose video size or rotation changes. + /// uid is 0 for the local user. + /// + /// Param [width] The width (pixels) of the video stream. + /// + /// Param [height] The height (pixels) of the video stream. + /// + /// Param [rotation] The rotation information. The value range is [0,360). + /// VideoSizeCallback? videoSizeChanged; + /// /// Occurs when the remote video state changes. + /// This callback does not work properly when the number of users (in the voice/video call channel) or hosts (in the live streaming channel) in the channel exceeds 17. + /// + /// Param [uid] The ID of the remote user whose video state changes. + /// + /// Param [state] The state of the remote video, see + /// VideoRemoteState. + /// + /// Param [reason] The reason for the remote video state + /// change, see VideoRemoteStateReason. + /// + /// Param [elapsed] Time elapsed (ms) from the local user calling the joinChannel method until the SDK triggers this + /// callback. /// - /// The `RemoteVideoStateCallback` typedef includes the following parameters: - /// - [int] `uid`: ID of the remote user whose video state changes. - /// - [VideoRemoteState] `state`: State of the remote video. - /// - [VideoRemoteStateReason] `reason`: The reason of the remote video state change. - /// - [int] `elapsed`: Time elapsed (ms) from the local user calling [RtcEngine.joinChannel] until the SDK triggers this callback. RemoteVideoStateCallback? remoteVideoStateChanged; - /// Occurs when the local video state changes. /// - /// The SDK returns the current video state in this callback. When the state is [LocalVideoStreamState.Failed], see the error parameter for details. + /// Occurs when the local video stream state changes. + /// When the state of the local video stream changes (including the state of the video capture and encoding), the SDK triggers this callback to report the current state. This callback indicates the state of the local video stream, including camera capturing and video encoding, and allows you to troubleshoot issues when exceptions occur. + /// The SDK triggers the localVideoStateChanged callback with the state code Failed and error code CaptureFailure in the following situations: + /// The app switches to the background, and the system gets the camera resource. + /// The camera starts normally, but does not output video for four consecutive seconds. + /// + /// When the camera outputs the captured video frames, if the video frames are the same for 15 consecutive frames, the SDK triggers the localVideoStateChanged callback with the state code Capturing and error code CaptureFailure. Note that the video frame duplication detection is only available for video frames with a resolution greater than 200 × 200, a frame rate greater than or equal to 10 fps, and a bitrate less than 20 Kbps. + /// For some device models, the SDK does not trigger this callback when the state of the local video changes while the local video capturing device is in use, so you have to make your own timeout judgment. + /// + /// Param [localVideoState] The state of the local video, see LocalVideoStreamState. + /// + /// + /// Param [error] The detailed error information, see LocalVideoStreamError. /// - /// **Note** - /// - This callback reports the current state of the local video, which keeps changing throughout the RtcEngine life cycle. We recommend maintaining the states reported in this callback, and check the local video state before starting the local camera. If the SDK reports [LocalVideoStreamError.CaptureFailure], the local camera is occupied by either the system or a third-party app. To access the camera, call [RtcEngine.enableLocalVideo] (`false`) first, and then [RtcEngine.enableLocalVideo] (`true`). /// - /// The `LocalVideoStateCallback` typedef includes the following parameters: - /// - [LocalVideoStreamState] `localVideoState`: The local video state. - /// - [LocalVideoStreamError] `error`: The detailed error information of the local video. LocalVideoStateCallback? localVideoStateChanged; + /// /// Occurs when the remote audio state changes. + /// When the audio state of a remote user (in the voice/video call channel) or host (in the live streaming channel) changes, the SDK triggers this callback to report the current state of the remote audio stream. + /// This callback does not work properly when the number of users (in the voice/video call channel) or hosts (in the live streaming channel) in the channel exceeds 17. /// - /// This callback indicates the state change of the remote audio stream. + /// Param [uid] The ID of the remote user whose audio state changes. + /// + /// Param [state] The state of the remote audio, see AudioRemoteState. + /// + /// Param [reason] The reason of the remote audio state change, see AudioRemoteStateReason. + /// + /// Param [elapsed] Time elapsed (ms) from the local user calling the joinChannel method until the SDK triggers this callback. /// - /// The `RemoteAudioStateCallback` typedef includes the following parameters: - /// - [int] `uid`: ID of the user whose audio state changes. - /// - [AudioRemoteState] `state`: State of the remote audio. - /// - [AudioRemoteStateReason] `reason`: The reason of the remote audio state change. - /// - [int] `elapsed`: Time elapsed (ms) from the local user calling [RtcEngine.joinChannel] until the SDK triggers this callback. RemoteAudioStateCallback? remoteAudioStateChanged; + /// /// Occurs when the local audio stream state changes. + /// When the state of the local audio stream changes (including the state of the audio capture and encoding), the SDK triggers this callback to report the current state. This callback indicates the state of the local audio stream, and allows you to troubleshoot issues when audio exceptions occur. + /// When the state isFailed (3), you can view the error information in the error parameter. /// - /// This callback indicates the state change of the local audio stream, including the state of the audio recording and encoding, and allows you to troubleshoot issues when exceptions occur. + /// Param [state] The state of the local audio. For details, see AudioLocalState. /// - /// **Note** - /// - When the state is [AudioLocalState.Failed], see the error parameter for details. + /// Param [error] Local audio state error codes. For details, see AudioLocalError. /// - /// The `LocalAudioStateCallback` typedef includes the following parameters: - /// - [AudioLocalState] `state`: State of the local audio. - /// - [AudioLocalError] `error`: The error information of the local audio. LocalAudioStateCallback? localAudioStateChanged; + /// /// Reports the information of an audio file. + /// After successfully calling getAudioFileInfo, the SDK triggers this callback to report the information of the audio file, such as the file path and duration. /// - /// After successfully calling [RtcEngine.getAudioFileInfo], the SDK triggers this callback - /// to report the information of the audio file, such as the file path and duration. + /// Param [info] The information of an audio file. See AudioFileInfo. /// - /// The `RequestAudioFileInfoCallback` typedef includes the following parameters: + /// Param [error] The information acquisition state. See AudioFileInfoError. + @Deprecated('Use requestAudioFileInfo instead') + RequestAudioFileInfoCallback? requestAudioFileInfoCallback; + /// - /// **Parameter** [info] The information of an audio file. See [AudioFileInfo]. + /// Reports the information of an audio file. + /// After successfully calling getAudioFileInfo, the SDK triggers this callback to report the information of the audio file, such as the file path and duration. /// - /// **Parameter** [error] The information acquisition state: - /// - [AudioFileInfoError.Ok] : Successfully get the information of an audio file. - /// - [AudioFileInfoError.Failure] : Fail to get the information of an audio file. - RequestAudioFileInfoCallback? requestAudioFileInfoCallback; + /// Param [info] The information of an audio file. See AudioFileInfo. + /// + /// Param [error] The information acquisition state. See AudioFileInfoError. + RequestAudioFileInfoCallback? requestAudioFileInfo; - /// Occurs when the published media stream falls back to an audio-only stream due to poor network conditions or switches back to video stream after the network conditions improve. /// - /// If you call [RtcEngine.setLocalPublishFallbackOption] and set option as [StreamFallbackOptions.AudioOnly], this callback is triggered when the locally published stream falls back to audio-only mode due to poor uplink conditions, or when the audio stream switches back to the video after the uplink network condition improves. + /// Occurs when the published media stream falls back to an audio-only stream. + /// If you call setLocalPublishFallbackOption and set option as AudioOnly, the SDK triggers this callback when the remote media stream falls back to audio-only mode due to poor uplink conditions, or when the remote media stream switches back to the video after the uplink network condition improves. + /// If the local stream falls back to the audio-only stream, the remote user receives the userMuteVideo callback. + /// + /// Param [isFallbackOrRecover] + /// true: The published stream falls + /// back to audio-only due to poor network conditions. + /// false: The published stream switches + /// back to the video after the network conditions improve. + /// + /// /// - /// The `FallbackCallback` typedef includes the following parameters: - /// - [bool] `isFallbackOrRecover`: Whether the published stream fell back to audio-only or switched back to the video: - /// -- `true`: The published stream fell back to audio-only due to poor network conditions. - /// -- `false`: The published stream switched back to the video after the network conditions improved. FallbackCallback? localPublishFallbackToAudioOnly; - /// Occurs when the remote media stream falls back to audio-only stream due to poor network conditions or switches back to video stream after the network conditions improve. /// - /// If you call [RtcEngine.setRemoteSubscribeFallbackOption] and set option as [StreamFallbackOptions.AudioOnly], this callback is triggered when the remotely subscribed media stream falls back to audio-only mode due to poor uplink conditions, or when the remotely subscribed media stream switches back to the video after the uplink network condition improves. + /// Occurs when the remote media stream falls back to audio-only stream due to poor network conditions or switches back to the video stream after the network conditions improve. + /// If you call setRemoteSubscribeFallbackOption and set option as AudioOnly, the SDK triggers this callback when the remote media stream falls back to audio-only mode due to poor downlink conditions, or when the remote media stream switches back to the video after the downlink network condition improves. + /// Once the remote media stream switches to the low stream due to poor network conditions, you can monitor the stream switch between a high and low stream in the RemoteVideoStats callback. + /// + /// Param [uid] The ID of the remote user. + /// + /// Param [isFallbackOrRecover] + /// true: The remotely subscribed media stream falls back to audio-only due to poor network conditions. + /// false: The remotely subscribed media stream switches back to the video stream after the network conditions improved. + /// + /// /// - /// The `FallbackWithUidCallback` typedef includes the following parameters: - /// - [int] `uid`: ID of the remote user sending the stream. - /// - [bool] `isFallbackOrRecover`: Whether the published stream fell back to audio-only or switched back to the video: - /// -- `true`: The published stream fell back to audio-only due to poor network conditions. - /// -- `false`: The published stream switched back to the video after the network conditions improved. FallbackWithUidCallback? remoteSubscribeFallbackToAudioOnly; - /// Occurs when the local audio playback route changes. /// - /// This callback returns that the audio route switched to an earpiece, speakerphone, headset, or Bluetooth device. + /// Occurs when the local audio route changes. + /// + /// + /// Param [routing] The current audio routing. For details, see AudioOutputRouting. /// - /// See [AudioOutputRouting] for the definition of the routing. /// - /// The `AudioRouteCallback` typedef includes the following parameter: - /// - [AudioOutputRouting] `routing`: Audio output routing. AudioRouteCallback? audioRouteChanged; - /// Occurs when the camera focus area is changed. /// - /// The SDK triggers this callback when the local user changes the camera focus position by calling the [RtcEngine.setCameraFocusPositionInPreview] method. + /// Occurs when the camera focus area changes. + /// The SDK triggers this callback when the local user changes the camera focus position by calling setCameraFocusPositionInPreview. + /// This method is for Android and iOS only. + /// + /// Param [rect] The focus rectangle in the local preview. /// - /// The `RectCallback` typedef includes the following parameter: - /// - [Rect] `rect`: Rectangular area in the camera zoom specifying the focus area. RectCallback? cameraFocusAreaChanged; - /// The camera exposure area has changed. /// - /// The SDK triggers this callback when the local user changes the camera exposure position by calling the [RtcEngine.setCameraExposurePosition] method. + /// Occurs when the camera exposure area changes. + /// The SDK triggers this callback when the local user changes the camera exposure position by calling setCameraExposurePosition. + /// This method is for Android and iOS only. + /// + /// Param [rect] The focus rectangle in the local preview. /// - /// The `RectCallback` typedef includes the following parameter: - /// - [Rect] `rect`: Rectangular area in the camera zoom specifying the focus area. RectCallback? cameraExposureAreaChanged; + /// /// Reports the face detection result of the local user. + /// Once you enable face detection by calling enableFaceDetection(true), you can get the following information on the local user in real-time: + /// The width and height of the local video. + /// The position of the human face in the local video. + /// The distance between the human face and the screen. + /// + /// + /// The distance between the human face and the screen is based on the fitting calculation of the local video size and the position of the human face captured by the camera. + /// + /// + /// If the SDK does not detect a face, it reduces the frequency of this callback to reduce power consumption on the local device. + /// The SDK stops triggering this callback when a human face is in close proximity to the screen. + /// + /// Param [imageWidth] The width (px) of the video image captured by the local camera. /// - /// Once you enable face detection by calling [RtcEngine.enableFaceDetection], you can get the following information on the local user in real time: - /// - The width and height of the local video. - /// - The position of the human face in the local video. - /// - The distance between the human face and the device screen. This value is based on the fitting calculation of the local video size and the position of the human face. + /// Param [imageHeight] The height (px) of the video image captured by the local camera. /// - /// **Note** - /// - If the SDK does not detect a face, it reduces the frequency of this callback to reduce power consumption on the local device. - /// - The SDK stops triggering this callback when a human face is in close proximity to the screen. - /// - On Android, the distance value reported in this callback may be slightly different from the actual distance. Therefore, Agora does not recommend using it for accurate calculation. + /// Param [faces] For the information of the detected face, see FacePositionInfo for details. If several faces are detected, + /// this callback reports several FacePositionInfo + /// arrays. The length of the array can be 0, which means that no human face is + /// detected in front of the camera. /// - /// `The FacePositionCallback` typedef includes the following parameters: - /// - [int] `imageWidth`: The width (px) of the local video. - /// - [int] `imageHeight`: The height (px) of the local video. - /// - [List]<[FacePositionInfo]> `faces`: The information of the detected human face. For details, see [FacePositionInfo]. The number of the `FacePositionInfo` array depends on the number of human faces detected. If the array length is 0, it means that no human face is detected. FacePositionCallback? facePositionChanged; - /// Reports the statistics of the [RtcEngine] once every two seconds. /// - /// The `RtcStatsCallback` typedef includes the following parameter: - /// - [RtcStats] `stats`: Statistics of the call. + /// Reports the statistics of the current call. + /// The SDK triggers this callback once every two seconds after the user joins the channel. + /// + /// Param [stats] Statistics of the RTC engine, see RtcStats for + /// details. + /// + /// RtcStatsCallback? rtcStats; - /// Reports the last mile network quality of the local user once every two seconds before the user joins the channel. Last mile refers to the connection between the local device and Agora's edge server. After the application calls the [RtcEngine.enableLastmileTest] method, this callback reports once every two seconds the uplink and downlink last mile network conditions of the local user before the user joins the channel. /// - /// The `NetworkQualityCallback` typedef includes the following parameter: - /// - [NetworkQuality] `quality`: The last mile network quality based on the uplink and downlink packet loss rate and jitter. + /// Reports the last-mile network quality of the local user once every two seconds. + /// This callback reports the last-mile network conditions of the local user before the user joins the channel. Last mile refers to the connection between the local device and Agora's edge server. + /// Before the user joins the channel, this callback is triggered by the SDK once startLastmileProbeTest is called and reports the last-mile network conditions of the local user. + /// + /// Param [quality] The last mile network quality. + /// Unknown (0): The quality is unknown. + /// Excellent (1): The quality is excellent. + /// Good (2): The network quality seems excellent, but the bitrate can be slightly lower than excellent. + /// Poor (3): Users can feel the communication is slightly impaired. + /// Bad (4): Users cannot communicate smoothly. + /// VBad (5): The quality is so bad that users can barely communicate. + /// Down (6): The network is down, and users cannot communicate at all. + /// + /// See + /// NetworkQuality. + /// NetworkQualityCallback? lastmileQuality; - /// Reports the last mile network quality of each user in the channel once every two seconds. /// - /// Last mile refers to the connection between the local device and Agora's edge server. This callback reports once every two seconds the last mile network conditions of each user in the channel. If a channel includes multiple users, then this callback will be triggered as many times. + /// Reports the last mile network quality of each user in the channel. + /// This callback reports the last mile network conditions of each user in the channel. Last mile refers to the connection between the local device and Agora's edge server. + /// The SDK triggers this callback once every two seconds. If a channel includes multiple users, the SDK triggers this callback as many times. + /// + /// Param [uid] User ID. The network quality of the user with this user ID is + /// reported. + /// + /// + /// Param [txQuality] Uplink network quality rating of the user in terms of the transmission bit + /// rate, packet loss rate, average RTT (Round-Trip Time) and jitter of the + /// uplink network. This parameter is a quality rating helping you understand + /// how well the current uplink network conditions can support the selected + /// video encoder configuration. For example, a 1000 Kbps uplink network may be + /// adequate for video frames with a resolution of 640 × 480 and a frame rate of + /// 15 fps in the LIVE_BROADCASTING profile, but might be inadequate for + /// resolutions higher than 1280 × 720. + /// Unknown (0): The quality is unknown. + /// Excellent (1): The quality is excellent. + /// Good (2): The network quality seems excellent, but the bitrate can be slightly lower than excellent. + /// Poor (3): Users can feel the communication is slightly impaired. + /// Bad (4): Users cannot communicate smoothly. + /// VBad (5): The quality is so bad that users can barely communicate. + /// Down (6): The network is down, and users cannot communicate at all. + /// + /// + /// + /// Param [rxQuality] Downlink network quality rating of the user in terms of packet loss rate, + /// average RTT, and jitter of the downlink network. + /// Unknown (0): The quality is unknown. + /// Excellent (1): The quality is excellent. + /// Good (2): The network quality seems excellent, but the bitrate can be slightly lower than excellent. + /// Poor (3): Users can feel the communication is slightly impaired. + /// Bad (4): Users cannot communicate smoothly. + /// VBad (5): The quality is so bad that users can barely communicate. + /// Down (6): The network is down, and users cannot communicate at all. + /// + /// /// - /// The `NetworkQualityWithUidCallback` typedef includes the following parameters: - /// - [int] `uid`:User ID. The network quality of the user with this uid is reported. If `uid` is 0, the local network quality is reported. - /// - [NetworkQuality] `txQuality`: Uplink transmission quality of the user in terms of the transmission bitrate, packet loss rate, average RTT (Round-Trip Time)and jitter of the uplink network. `txQuality` is a quality rating helping you understand how well the current uplink network conditions can support the selected [VideoEncoderConfiguration]. For example, a 1000 Kbps uplink network may be adequate for video frames with a resolution of 680 × 480 and a frame rate of 30 fps, but may be inadequate for resolutions higher than 1280 × 720. - /// - [NetworkQuality] `rxQuality`: Downlink network quality rating of the user in terms of packet loss rate, average RTT, and jitter of the downlink network. NetworkQualityWithUidCallback? networkQuality; - /// Reports the last-mile network probe result. /// - /// The SDK triggers this callback within 30 seconds after the app calls the [RtcEngine.startLastmileProbeTest] method. + /// Reports the last mile network probe result. + /// The SDK triggers this callback within 30 seconds after the app calls startLastmileProbeTest. + /// + /// Param [result] The uplink and downlink last-mile network probe test result. For details, + /// see LastmileProbeResult. /// - /// The `LastmileProbeCallback` typedef includes the following parameter: - /// - [LastmileProbeResult] `result`: The uplink and downlink last-mile network probe test result. LastmileProbeCallback? lastmileProbeResult; - /// Reports the statistics of the local video streams. /// - /// The SDK triggers this callback once every two seconds for each user/host. If there are multiple users/hosts in the channel, the SDK triggers this callback as many times. + /// Reports the statistics of the local video stream. + /// The SDK triggers this callback once every two seconds to report the statistics of the local video stream. + /// + /// Param [stats] The statistics of the local video stream. For details, see LocalVideoStats. /// - /// The `LocalVideoStatsCallback` typedef includes the following parameter: - /// - [LocalVideoStats] `stats`: The statistics of the local video stream. LocalVideoStatsCallback? localVideoStats; + /// /// Reports the statistics of the local audio stream. + /// The SDK triggers this callback once every two seconds. + /// + /// Param [stats] Local audio statistics. For details, see LocalAudioStats. /// - /// The `LocalAudioStats` typedef includes the following parameter: - /// - [LocalAudioStats] `stats`: The statistics of the local audio stream. LocalAudioStatsCallback? localAudioStats; - /// Reports the statistics of the video stream from each remote user/host. The SDK triggers this callback once every two seconds for each remote user/host. If a channel includes multiple remote users, the SDK triggers this callback as many times. /// - /// The `RemoteVideoStatsCallback` typedef includes the following parameter: - /// - [RemoteVideoStats] `stats`: Statistics of the received remote video streams. + /// Reports the transport-layer statistics of each remote video stream. + /// Reports the statistics of the video stream from the remote users. The SDK triggers this callback once every two seconds for each remote user. If a channel has multiple users/hosts sending video streams, the SDK triggers this callback as many times. + /// + /// Param [stats] Statistics of the remote video stream. For details, see RemoteVideoStats. + /// RemoteVideoStatsCallback? remoteVideoStats; - /// Reports the statistics of the audio stream from each remote user/host. /// - /// The SDK triggers this callback once every two seconds for each remote user/host. If a channel includes multiple remote users, the SDK triggers this callback as many times. + /// Reports the transport-layer statistics of each remote audio stream. + /// The SDK triggers this callback once every two seconds for each remote user who is sending audio streams. If a channel includes multiple remote users, the SDK triggers this callback as many times. /// - /// Schemes such as FEC (Forward Error Correction) or retransmission counter the frame loss rate. Hence, users may find the overall audio quality acceptable even when the packet loss rate is high. + /// Param [stats] The statistics of the received remote audio streams. See RemoteAudioStats. /// - /// The `RemoteAudioStatsCallback` typedef includes the following parameter: - /// - [RemoteAudioStats] `stats`: Statistics of the received remote audio streams. RemoteAudioStatsCallback? remoteAudioStats; - /// Occurs when the audio mixing file playback finishes. /// - /// **Deprecated** This callback is deprecated. Use [RtcEngineEventHandler.audioMixingStateChanged] instead. + /// Occurs when the playback of the local music file finishes. + /// Deprecated: + /// This method is deprecated as of v2.4.0. Use audioMixingStateChanged instead. /// - /// You can start an audio mixing file playback by calling the [RtcEngine.startAudioMixing] method. This callback is triggered when the audio mixing file playback finishes. /// - /// If the [RtcEngine.startAudioMixing] method call fails, an [WarningCode.AudioMixingOpenError] warning returns in the [warning] callback. - /// The `EmptyCallback` typedef does not include any parameter. + /// After you call startAudioMixing to play a local music + /// file, this callback occurs when the playback finishes. If the call of startAudioMixing fails, the callback returns the error code + /// WARN_AUDIO_MIXING_OPEN_ERROR. + /// @deprecated EmptyCallback? audioMixingFinished; - /// Occurs when the playback state of the local user's music file changes. /// - /// When you call the [RtcEngine.startAudioMixing] method and the state of audio mixing file changes, the Agora SDK triggers this callback. - /// When the playback state of the local user's music file changes, the SDK triggers this callback and reports the current playback state and the reason for the change. + /// Occurs when the playback state of the music file changes. + /// This callback occurs when the playback state of the music file changes, and reports the current state and error code. + /// + /// Param [state] The playback state of the music file. + /// + /// Param [reason] The reason why the playback state of the music file changes. /// - /// The `AudioMixingStateCallback` typedef includes the following parameters: - /// - [AudioMixingStateCode] `state`: The current music file playback state. - /// - [AudioMixingReason] `reason`: The reason for the change of the music file playback state. AudioMixingStateCallback? audioMixingStateChanged; - /// Occurs when the audio effect file playback finishes. /// - /// You can start a local audio effect playback by calling the [RtcEngine.playEffect] method. This callback is triggered when the local audio effect file playback finishes. + /// Occurs when the playback of the local audio effect file finishes. + /// This callback occurs when the local audio effect file finishes playing. + /// + /// Param [soundId] The ID of the audio effect. Each audio effect has a unique ID. /// - /// The `SoundIdCallback` typedef includes the following parameter: - /// - [int] `soundId`: ID of the local audio effect. Each local audio effect has a unique ID. SoundIdCallback? audioEffectFinished; + /// /// Occurs when the state of the RTMP or RTMPS streaming changes. + /// The SDK triggers this callback to report the result of the local user calling the addPublishStreamUrl or removePublishStreamUrl method. When the RTMP/RTMPS streaming status changes, the SDK triggers this callback and report the URL address and the current status of the streaming. This callback indicates the state of the RTMP or RTMPS streaming. When exceptions occur, you can troubleshoot issues by referring to the detailed error descriptions in the error code parameter. /// - /// The SDK triggers this callback to report the result of the local user calling the [RtcEngine.addPublishStreamUrl] or [RtcEngine.removePublishStreamUrl] method. This callback returns the URL and its current streaming state. When the streaming state is [RtmpStreamingState.Failure], see the `errCode` parameter for details. + /// Param [url] The CDN streaming URL. /// - /// This callback indicates the state of the RTMP or RTMPS streaming. When exceptions occur, you can troubleshoot issues by referring to the detailed error descriptions in the `errCode` parameter. + /// Param [state] The RTMP or RTMPS streaming state, see RtmpStreamingState. When the streaming status is Failure(4), you can view the error information in the errorCode parameter. + /// + /// Param [errCode] The detailed error information for streaming, see RtmpStreamingErrorCode. /// - /// The `RtmpStreamingStateCallback` typedef includes the following parameters: - /// - [String] `url`: The CDN streaming URL. - /// - [RtmpStreamingState] `state`: The RTMP or RTMPS streaming state. - /// - [RtmpStreamingErrorCode] `errCode`: The detailed error information for streaming. RtmpStreamingStateCallback? rtmpStreamingStateChanged; - /// Occurs when the publisher's transcoding settings are updated. /// - /// When the [LiveTranscoding] class in the [RtcEngine.setLiveTranscoding] method updates, the SDK triggers this callback to report the update information. + /// Occurs when the publisher's transcoding is updated. + /// When the LiveTranscoding class in the setLiveTranscoding method updates, the SDK triggers the transcodingUpdated callback to report the update information. + /// If you call the setLiveTranscoding + /// method to set the LiveTranscoding class for the first time, the + /// SDK does not trigger this callback. /// - /// **Note** - /// - If you call the [RtcEngine.setLiveTranscoding] method to set the [LiveTranscoding] class for the first time, the SDK does not trigger this callback. - /// The `EmptyCallback` typedef does not include any parameter. EmptyCallback? transcodingUpdated; - /// Reports the status of injecting the online media stream. /// - /// The `StreamInjectedStatusCallback` typedef includes the following parameters: - /// - [String] `url`: The URL address of the externally injected stream. - /// - [int] `uid`: User ID. - /// - [InjectStreamStatus] `status`: State of the externally injected stream. + /// Occurs when a media stream URL address is added to the interactive live streaming. + /// Agora will soon stop the service for injecting online media streams on the client. If you have not implemented this service, Agora recommends that you do not use it. For details, see Service Sunset Plans. + /// + /// Param [url] The URL address of the externally injected stream. + /// + /// Param [uid] User ID. + /// + /// Param [status] State of the externally injected stream: InjectStreamStatus. + /// StreamInjectedStatusCallback? streamInjectedStatus; - /// Occurs when the local user receives a remote data stream. /// - /// The SDK triggers this callback when the local user receives the stream message that the remote user sends by calling the [RtcEngine.sendStreamMessage] method. + /// Occurs when the local user receives the data stream from the remote user. + /// The SDK triggers this callback when the local user receives the stream message that the remote user sends by calling the sendStreamMessage method. + /// + /// Param [uid] The ID of the remote user sending the message. + /// + /// Param [streamId] The stream ID of the received message. + /// + /// Param [data] The data received. /// - /// The `StreamMessageCallback` typedef includes the following parameters: - /// - [int] `uid`: User ID of the remote user sending the data stream. - /// - [int] `streamId`: Stream ID. - /// - [String] `data`: Data received by the local user. StreamMessageCallback? streamMessage; - /// Occurs when the local user fails to receive a remote data stream. /// - /// The SDK triggers this callback when the local user fails to receive the stream message that the remote user sends by calling the [RtcEngine.sendStreamMessage] method. + /// Occurs when the local user does not receive the data stream from the remote user. + /// The SDK triggers this callback when the local user fails to receive the stream message that the remote user sends by calling the sendStreamMessage method. + /// + /// Param [uid] The ID of the remote user sending the message. + /// + /// Param [streamId] The stream ID of the received message. + /// + /// Param [error] The error code. + /// + /// Param [missed] The number of lost messages. + /// + /// Param [cached] Number of incoming cached messages when the data stream is interrupted. /// - /// The `StreamMessageErrorCallback` callback includes the following parameters: - /// - [int] `uid`: User ID of the remote user sending the data stream. - /// - [int] `streamId`: Stream ID. - /// - [ErrorCode] `error`: Error code. - /// - [int] `missed`: The number of lost messages. - /// - [int] `cached`: The number of incoming cached messages when the data stream is interrupted. StreamMessageErrorCallback? streamMessageError; - /// Occurs when the media engine is loaded. /// - /// The `EmptyCallback` typedef does not include any parameter. + /// Occurs when the media engine loads. + /// + /// EmptyCallback? mediaEngineLoadSuccess; - /// Occurs when the media engine starts. /// - /// The `EmptyCallback` typedef does not include any parameter. + /// Occurs when the media engine call starts. + /// + /// EmptyCallback? mediaEngineStartCallSuccess; + /// /// Occurs when the state of the media stream relay changes. + /// The SDK returns the state of the current media relay with any error message. + /// + /// Param [state] The state code. For details, see ChannelMediaRelayState. /// - /// The SDK reports the state of the current media relay and possible error messages in this callback. + /// Param [code] The error code of the channel media + /// replay. For details, see ChannelMediaRelayError. /// - /// The `MediaRelayStateCallback` typedef includes the following parameters: - /// - [ChannelMediaRelayState] `state`: The state code. - /// - [ChannelMediaRelayError] `code`: The error code. MediaRelayStateCallback? channelMediaRelayStateChanged; + /// /// Reports events during the media stream relay. /// - /// The `MediaRelayEventCallback` typedef includes the following parameter: - /// - [ChannelMediaRelayEvent] `code`: The event code for media stream relay. + /// + /// Param [code] The event code of channel media relay: + /// Disconnect(0): The user disconnects from the server due to a poor network connection. + /// Connected(1): The user is connected to the server. + /// JoinedSourceChannel(2): The user joins the source channel. + /// JoinedDestinationChannel(3): The user joins the destination channel. + /// SentToDestinationChannel(4): The SDK starts relaying the media stream to the destination channel. + /// ReceivedVideoPacketFromSource(5): The server receives the video stream from the source channel. + /// ReceivedAudioPacketFromSource(6): The server receives the audio stream from the source channel. + /// UpdateDestinationChannel(7): The destination channel is updated. + /// UpdateDestinationChannelRefused(8): The destination channel update fails due to internal reasons. + /// UpdateDestinationChannelNotChange(9): The destination channel does not change, which means that the destination channel fails to be updated. + /// UpdateDestinationChannelIsNil(10): The destination channel name is null. + /// VideoProfileUpdate(11): The video profile is sent to the server. + /// PauseSendPacketToDestChannelSuccess(12): The SDK successfully pauses relaying the media stream to destination channels. + /// PauseSendPacketToDestChannelFailed(13): The SDK fails to pause relaying the media stream to destination channels. + /// ResumeSendPacketToDestChannelSuccess(14): The SDK successfully resumes relaying the media stream to destination channels. + /// ResumeSendPacketToDestChannelFailed(15): The SDK fails to resume relaying the media stream to destination channels. + /// + /// + /// + /// MediaRelayEventCallback? channelMediaRelayEvent; + /// /// Occurs when the first remote video frame is rendered. + /// The SDK triggers this callback when the first local video frame is displayed/rendered on the local video view. The application can retrieve the time elapsed (the elapsed parameter) from a user joining the channel until the first video frame is displayed. + /// + /// Param [uid] The user ID of the remote user sending the video stream. /// - /// **Deprecated** Use [VideoRemoteState.Starting] or [VideoRemoteState.Decoding] in the [remoteVideoStateChanged] callback instead. + /// Param [width] The width (px) of the video stream. /// - /// This callback is triggered after the first frame of the remote video is rendered on the video window. The application can retrieve the data of the time elapsed from the user joining the channel until the first video frame is displayed. + /// Param [height] The height (px) of the video stream. + /// + /// Param [elapsed] Time elapsed (ms) from the local user calling joinChannel until the SDK triggers this callback. /// - /// The `VideoFrameWithUidCallback` typedef includes the following parameters: - /// - [int] `uid`: User ID of the remote user sending the video streams. - /// - [int] `width`: Width (pixels) of the video stream. - /// - [int] `height`: Height (pixels) of the video stream. - /// - [int] `elapsed`: Time elapsed (ms) from the local user calling [RtcEngine.joinChannel] until this callback is triggered. @deprecated VideoFrameWithUidCallback? firstRemoteVideoFrame; - /// Occurs when the first remote audio frame is received. - /// - /// **Deprecated** Use [AudioRemoteState.Starting] in [remoteAudioStateChanged] instead. - /// - /// The `UidWithElapsedCallback` typedef includes the following parameters: - /// - [int] `uid`: This parameter has the following definitions in different events: - /// - [userJoined]: ID of the user or host who joins the channel. - /// - [firstRemoteAudioFrame]: User ID of the remote user. - /// - [firstRemoteAudioDecoded]: User ID of the remote user sending the audio stream. - /// - [joinChannelSuccess]: User ID. - /// - [rejoinChannelSuccess]: User ID. - /// - [int] `elapsed`: - /// - [userJoined]: Time delay (ms) from the local user calling [RtcEngine.joinChannel] or [RtcEngine.setClientRole] until this callback is triggered. - /// - [firstRemoteAudioFrame]: Time elapsed (ms) from the local user calling [RtcEngine.joinChannel] until this callback is triggered. - /// - [firstRemoteAudioDecoded]: Time elapsed (ms) from the local user calling [RtcEngine.joinChannel] until the SDK triggers this callback. - /// - [joinChannelSuccess]: Time elapsed (ms) from the local user calling [RtcChannel.joinChannel] until this callback is triggered. - /// - [rejoinChannelSuccess]: Time elapsed (ms) from the local user starting to reconnect until this callback is triggered. + /// + /// Occurs when the SDK receives the first audio frame from a specific remote user. + /// Deprecated: + /// Please use remoteAudioStateChanged instead. + /// + /// Param [uid] The user ID of the remote user. + /// + /// Param [elapsed] The time elapsed (ms) from the local user calling joinChannel until the SDK triggers this callback. + /// @deprecated UidWithElapsedCallback? firstRemoteAudioFrame; - /// Occurs when the engine receives the first audio frame from a specified remote user. - /// - /// **Deprecated** Use [VideoRemoteState.Decoding] in [remoteAudioStateChanged] instead. - /// - /// This callback is triggered in either of the following scenarios: - /// - The remote user joins the channel and sends the audio stream. - /// - The remote user stops sending the audio stream and re-sends it after 15 seconds. Possible reasons include: - /// -- The remote user leaves channel. - /// -- The remote user drops offline. - /// -- The remote user calls the [RtcEngine.muteLocalAudioStream] method. - /// -- The remote user calls the [RtcEngine.disableAudio] method. - /// - /// The `UidWithElapsedCallback` typedef includes the following parameters: - /// - [int] `uid`: This parameter has the following definitions in different events: - /// - [userJoined]: ID of the user or host who joins the channel. - /// - [firstRemoteAudioFrame]: User ID of the remote user. - /// - [firstRemoteAudioDecoded]: User ID of the remote user sending the audio stream. - /// - [joinChannelSuccess]: User ID. - /// - [rejoinChannelSuccess]: User ID. - /// - [int] `elapsed`: - /// - [userJoined]: Time delay (ms) from the local user calling [RtcEngine.joinChannel] or [RtcEngine.setClientRole] until this callback is triggered. - /// - [firstRemoteAudioFrame]: Time elapsed (ms) from the local user calling [RtcEngine.joinChannel] until this callback is triggered. - /// - [firstRemoteAudioDecoded]: Time elapsed (ms) from the local user calling [RtcEngine.joinChannel] until the SDK triggers this callback. - /// - [joinChannelSuccess]: Time elapsed (ms) from the local user calling [RtcChannel.joinChannel] until this callback is triggered. - /// - [rejoinChannelSuccess]: Time elapsed (ms) from the local user starting to reconnect until this callback is triggered. + /// + /// Occurs when the SDK decodes the first remote audio frame for playback. + /// Deprecated: + /// Please use remoteAudioStateChanged instead. + /// + /// + /// The SDK triggers this callback under one of the following circumstances: + /// The remote user joins the channel and sends the audio stream for the first time. + /// The remote user's audio is offline and then goes online to re-send audio. It means the local user cannot receive audio in 15 seconds. Reasons for such an interruption include: + /// The remote user leaves channel. + /// The remote user drops offline. + /// The remote user calls muteLocalAudioStream to stop sending the audio stream. + /// The remote user calls disableAudio to disable audio. + /// + /// Param [uid] The ID of the remote user. + /// + /// Param [elapsed] The time elapsed (ms) from the local user calling joinChannel until the SDK triggers this callback. + /// @deprecated UidWithElapsedCallback? firstRemoteAudioDecoded; - /// Occurs when a remote user stops/resumes sending the audio stream. /// - /// **Deprecated** Use the [RtcEngineEventHandler.remoteAudioStateChanged] callback with the following parameters instead: - /// - [VideoRemoteState.Stopped] and [VideoRemoteStateReason.RemoteMuted]. - /// - [VideoRemoteState.Decoding] and [VideoRemoteStateReason.RemoteUnmuted]. + /// Occurs when a remote user (in the communication profile)/ host (in the live streaming profile) joins the channel. + /// The SDK triggers this callback when the remote user stops or resumes sending the audio stream by calling the muteLocalAudioStream method. + /// This callback does not work properly when the number of users (in the communication profile) or hosts (in the live streaming profile) in the channel exceeds 17. + /// + /// Param [uid] User ID. + /// + /// Param [muted] Whether the remote user's audio stream is muted/unmuted: + /// true: Muted. + /// false: Unmuted. /// - /// The SDK triggers this callback when the remote user stops or resumes sending the audio stream by calling the [RtcEngine.muteLocalAudioStream] method. /// - /// **Note** - /// - This callback is invalid when the number of users or broadcasters in the channel exceeds 17. /// - /// The `UidWithMutedCallback` typedef includes the following parameters: - /// - [int] `uid`: ID of the remote user. - /// - [bool] `muted`: Whether the remote user's video stream playback pauses/resumes: - /// - `true`: Pause. - /// - `false`: Resume. @deprecated UidWithMutedCallback? userMuteAudio; - /// Reports the result of calling the [RtcEngine.addPublishStreamUrl] method. /// - /// **Deprecated** Use [RtcEngineEventHandler.rtmpStreamingStateChanged] instead. + /// Occurs when an RTMP or RTMPS stream is published. + /// Deprecated: + /// Please use rtmpStreamingStateChanged instead. + /// /// - /// This callback indicates whether you have successfully added an RTMP stream to the CDN. + /// Reports the result of publishing an RTMP or RTMPS stream. + /// + /// Param [url] /// - /// The `UrlWithErrorCallback` includes the following parameters: - /// - [String] `url`: The CDN streaming URL. - /// - [ErrorCode] `error`: The detailed error information. @deprecated UrlWithErrorCallback? streamPublished; - /// Reports the result of calling the [RtcEngine.removePublishStreamUrl] method. /// - /// **Deprecated** Use [RtcEngineEventHandler.rtmpStreamingStateChanged] instead. + /// Occurs when an RTMP or RTMPS stream is removed. + /// Deprecated: + /// Please use rtmpStreamingStateChanged instead. /// - /// This callback indicates whether you have successfully removed an RTMP stream from the CDN. + /// Param [url] The URL of the removed RTMP or RTMPS stream. /// - /// The `UrlCallback` typedef includes the following parameter: - /// - [String] `url`: The CDN streaming URL. @deprecated UrlCallback? streamUnpublished; + /// /// Reports the transport-layer statistics of each remote audio stream. + /// Deprecated: + /// Please use remoteAudioStats instead. + /// + /// + /// + /// This callback reports the transport-layer statistics, such as the packet loss rate and network time delay, once every two seconds after the local user receives an audio packet from a remote user. During a call, when the user receives the audio packet sent by the remote user/host, the callback is triggered every 2 seconds. /// - /// **Deprecated** This callback is deprecated. Use [RtcEngineEventHandler.remoteAudioStats] instead. + /// Param [uid] The ID of the remote user sending the audio streams. /// - /// This callback reports the transport-layer statistics, such as the packet loss rate and time delay, once every two seconds after the local user receives an audio packet from a remote user. + /// Param [delay] The network delay (ms) from the sender to the receiver. + /// + /// Param [lost] Packet loss rate (%) of the audio packet sent from the sender to the + /// receiver. + /// + /// Param [rxKBitrate] Bitrate of the received audio (Kbps). /// - /// The `TransportStatsCallback` typedef includes the following parameters: - /// - [int] `uid`: User ID of the remote user sending the audio packet. - /// - [int] `delay`: Network time delay (ms) from the remote user sending the audio packet to the local user. - /// - [int] `lost`: Packet loss rate (%) of the audio packet sent from the remote user. - /// - [int] `rxKBitRate`: Received bitrate (Kbps) of the audio packet sent from the remote user. @deprecated TransportStatsCallback? remoteAudioTransportStats; + /// /// Reports the transport-layer statistics of each remote video stream. + /// Deprecated: + /// Please use remoteVideoStats instead. + /// + /// + /// This callback reports the transport-layer statistics, such as the packet loss rate and network time delay, once every two seconds after the local user receives a video packet from a remote user. + /// During a call, when the user receives the video packet sent by the remote user/host, the callback is triggered every 2 seconds. + /// + /// Param [uid] The ID of the remote user sending the video packets. + /// + /// Param [delay] The network delay (ms) from the sender to the receiver. /// - /// **Deprecated** This callback is deprecated. Use [RtcEngineEventHandler.remoteVideoStats] instead. + /// Param [lost] The packet loss rate (%) of the video packet sent from the remote user. /// - /// This callback reports the transport-layer statistics, such as the packet loss rate and time delay, once every two seconds after the local user receives the video packet from a remote user. + /// Param [rxKBitRate] The bitrate of the received video (Kbps). /// - /// The `TransportStatsCallback` typedef includes the following parameters: - /// - [int] `uid`: User ID of the remote user sending the audio packet. - /// - [int] `delay`: Network time delay (ms) from the remote user sending the audio packet to the local user. - /// - [int] `lost`: Packet loss rate (%) of the audio packet sent from the remote user. - /// - [int] `rxKBitRate`: Received bitrate (Kbps) of the audio packet sent from the remote user. @deprecated TransportStatsCallback? remoteVideoTransportStats; + /// /// Occurs when a remote user enables/disables the video module. + /// Once the video module is disabled, the user can only use a voice call. The user cannot send or receive any video. + /// The SDK triggers this callback when a remote user enables or disables the video module by calling the enableVideo or disableVideo method. /// - /// **Deprecated** This callback is deprecated and replaced by the [RtcEngineEventHandler.remoteVideoStateChanged] callback with the following parameters: - /// - [VideoRemoteState.Stopped] and [VideoRemoteStateReason.RemoteMuted]. - /// - [VideoRemoteState.Decoding] and [VideoRemoteStateReason.RemoteUnmuted]. + /// Param [uid] The user ID of the remote user. /// - /// Once the video module is disabled, the remote user can only use a voice call. The remote user cannot send or receive any video from other users. + /// Param [enabled] + /// true: Enable. + /// false: Disable. /// - /// The SDK triggers this callback when the remote user enables or disables the video module by calling the [RtcEngine.enableVideo] or [RtcEngine.disableVideo] method. /// - /// **Note** - /// - This callback is invalid when the number of users or broadcasters in the channel exceeds 17. /// - /// The `UidWithEnabledCallback` typedef includes the followinh parameters: - /// - [int] `uid`: User ID of the remote user. - /// - [bool] `enabled`: Whether the specific remote user enables/disables the video module: - /// - `true`: Enabled. The remote user can enter a video session. - /// - `false`: Disabled. The remote user can only enter a voice session, and cannot send or receive any video stream. @deprecated UidWithEnabledCallback? userEnableVideo; - /// Occurs when a remote user enables/disables the local video capture function. /// - /// **Deprecated** This callback is deprecated and replaced by the [RtcEngineEventHandler.remoteVideoStateChanged] callback with the following parameters: - /// - [VideoRemoteState.Stopped] and [VideoRemoteStateReason.RemoteMuted]. - /// - [VideoRemoteState.Decoding] and [VideoRemoteStateReason.RemoteUnmuted]. + /// Occurs when a specific remote user enables/disables the local video capturing function. + /// The SDK triggers this callback when the remote user resumes or stops capturing the video stream by calling the enableLocalVideo method. + /// + /// Param [uid] The user ID of the remote user. + /// + /// Param [enabled] Whether the specified remote user enables/disables the local video + /// capturing function: + /// true: Enable. Other users in the + /// channel can see the video of this remote user. + /// false: Disable. Other users in the + /// channel can no longer receive the video stream from this remote + /// user, while this remote user can still receive the video streams + /// from other users. + /// /// - /// The SDK triggers this callback when the remote user resumes or stops capturing the video stream by calling the [RtcEngine.enableLocalVideo] method. - /// This callback is only applicable to the scenario when the remote user only wants to watch the remote video without sending any video stream to the other user. /// - /// The `UidWithEnabledCallback` typedef includes the followinh parameters: - /// - [int] `uid`: User ID of the remote user. - /// - [bool] `enabled`: Whether the specific remote user enables/disables the video module: - /// - `true`: Enabled. The remote user can enter a video session. - /// - `false`: Disabled. The remote user can only enter a voice session, and cannot send or receive any video stream. @deprecated UidWithEnabledCallback? userEnableLocalVideo; + /// /// Occurs when the first remote video frame is received and decoded. + /// Deprecated: + /// Please use the remoteVideoStateChanged callback with the following parameters: + /// Starting (1). + /// Decoding (2). + /// + /// + /// + /// + /// The SDK triggers this callback under one of the following circumstances: + /// The remote user joins the channel and sends the video stream. + /// The remote user stops sending the video stream and re-sends it after 15 seconds. Reasons for such an interruption include: + /// The remote user leaves the channel. + /// The remote user drops offline. + /// The remote user calls muteLocalVideoStream to stop sending the video stream. + /// The remote user calls disableVideo to disable video. + /// + /// Param [uid] The user ID of the remote user sending the video stream. + /// + /// Param [width] The width (px) of the video stream. + /// + /// Param [height] The height (px) of the video stream. + /// + /// Param [elapsed] The time elapsed (ms) from the local user calling joinChannel until the SDK triggers this callback. /// - /// **Deprecated** This callback is deprecated. Use [VideoRemoteState.Starting] or [VideoRemoteState.Decoding] in the [RtcEngineEventHandler.remoteVideoStateChanged] callback instead. - /// - /// This callback is triggered in either of the following scenarios: - /// - The remote user joins the channel and sends the video stream. - /// - The remote user stops sending the video stream and re-sends it after 15 seconds. Possible reasons include: - /// -- The remote user leaves channel. - /// -- The remote user drops offline. - /// -- The remote user calls the [RtcEngine.muteLocalVideoStream] method. - /// -- The remote user calls the [RtcEngine.disableVideo] method. - /// - /// The `VideoFrameWithUidCallback` typedef includes the following parameters: - /// - [int] `uid`: User ID of the remote user sending the video streams. - /// - [int] `width`: Width (pixels) of the video stream. - /// - [int] `height`: Height (pixels) of the video stream. - /// - [int] `elapsed`: Time elapsed (ms) from the local user calling [RtcEngine.joinChannel] until this callback is triggered. @deprecated VideoFrameWithUidCallback? firstRemoteVideoDecoded; + /// /// Occurs when the microphone is enabled/disabled. + /// Deprecated: + /// + /// Please use the localAudioStateChanged callback: + /// Stopped(0). + /// Recording(1). + /// + /// + /// + /// + /// The SDK triggers this callback when the local userenableLocalAudio resumes or stops capturing the local audio stream by calling the method. + /// + /// Param [enabled] Whether the microphone is enabled/disabled: + /// true: The microphone is enabled. + /// false: The microphone is disabled. /// /// - /// **Deprecated** This callback is deprecated. Use [AudioLocalState.Stopped] (0) or [AudioLocalState.Recording] (1) in the [RtcEngineEventHandler.localAudioStateChanged] callback instead. - /// The SDK triggers this callback when the local user resumes or stops capturing the local audio stream by calling the [RtcEngine.enableLocalAudio] method. /// - /// The `EnabledCallback` includes the following parameter: - /// - [bool] `enabled`: Whether the microphone is enabled/disabled: - /// - `true`:Enabled. - /// - `false`:Disabled. @deprecated EnabledCallback? microphoneEnabled; - /// Occurs when the connection between the SDK and the server is interrupted. /// - /// **Deprecated** Use [RtcEngineEventHandler.connectionStateChanged] instead. + /// Occurs when the connection between the SDK and the server is interrupted. + /// Deprecated: + /// Please use connectionStateChanged instead. /// - /// The SDK triggers this callback when it loses connection to the server for more than four seconds after the connection is established. After triggering this callback, the SDK tries to reconnect to the server. You can use this callback to implement pop-up reminders. This callback is different from [RtcEngineEventHandler.connectionLost]: - /// - The SDK triggers the [RtcEngineEventHandler.connectionInterrupted] callback when the SDK loses connection with the server for more than four seconds after it joins the channel. - /// - The SDK triggers the [RtcEngineEventHandler.connectionLost] callback when it loses connection with the server for more than 10 seconds, regardless of whether it joins the channel or not. /// + /// The SDK triggers this callback when it loses connection with the server for more than four seconds after the connection is established. After triggering this callback, the SDK tries to reconnect to the server. You can use this callback to implement pop-up reminders. The difference between this callback and connectionLost is: + /// The SDK triggers the connectionInterrupted callback when it loses connection with the server for more than four seconds after it successfully joins the channel. + /// The SDK triggers the connectionLost callback when it loses connection with the server for more than 10 seconds, whether or not it joins the channel. /// If the SDK fails to rejoin the channel 20 minutes after being disconnected from Agora's edge server, the SDK stops rejoining the channel. - /// The `EmptyCallback` typedef does not include any parameter. + /// @deprecated EmptyCallback? connectionInterrupted; - /// Occurs when your connection is banned by the Agora Server. /// - /// **Deprecated** Use [RtcEngineEventHandler.connectionStateChanged] instead. - /// The `EmptyCallback` typedef does not include any parameter. + /// Occurs when the connection is banned by the Agora server. + /// Deprecated: + /// Please use connectionStateChanged instead. + /// @deprecated EmptyCallback? connectionBanned; - /// Reports the statistics of the audio stream from each remote user/host. /// - /// **Deprecated** Use [RtcEngineEventHandler.remoteAudioStats] instead. + /// Reports the statistics of the audio stream from each remote user. + /// Deprecated: + /// remoteAudioStats instead. + /// + /// /// - /// The SDK triggers this callback once every two seconds to report the audio quality of each remote user/host sending an audio stream. If a channel has multiple remote users/hosts sending audio streams, the SDK trggers this callback as many times. + /// The SDK triggers this callback once every two seconds to report the audio quality of each remote user/host sending an audio stream. If a channel has multiple users/hosts sending audio streams, the SDK triggers this callback as many times. + /// + /// Param [uid] The user ID of the remote user sending the audio stream. + /// + /// Param [quality] Audio quality of the user. + /// Unknown (0): The quality is unknown. + /// Excellent (1): The quality is excellent. + /// Good (2): The network quality seems excellent, but the bitrate can be slightly lower than excellent. + /// Poor (3): Users can feel the communication is slightly impaired. + /// Bad (4): Users cannot communicate smoothly. + /// VBad (5): The quality is so bad that users can barely communicate. + /// Down (6): The network is down, and users cannot communicate at all. + /// + /// + /// + /// Param [delay] The network delay (ms) from the sender to the receiver, including the delay + /// caused by audio sampling pre-processing, network transmission, and network + /// jitter buffering. + /// + /// Param [lost] Packet loss rate (%) of the audio packet sent from the sender to the + /// receiver. /// - /// The `AudioQualityCallback` typedef includes the following parameters: - /// [int] `uid`: User ID of the speaker. - /// [int] `quality`: Audio quality of the user. - /// [int] `delay`: Time delay (ms) of the audio packet from the sender to the receiver, including the time delay from audio sampling pre-processing, transmission, and the jitter buffer. - /// [int] `lost`: Packet loss rate (%) of the audio packet sent from the sender to the receiver. @deprecated AudioQualityCallback? audioQuality; - /// Occurs when the camera is turned on and ready to capture video. /// - /// **Deprecated** Use [LocalVideoStreamState.Capturing] in the [RtcEngineEventHandler.localVideoStateChanged] callback instead. If the camera fails to turn on, fix the error reported in the [LocalVideoStreamState.Failed] callback. - /// The `EmptyCallback` typedef does not include any parameter. + /// Occurs when the camera turns on and is ready to capture the video. + /// Deprecated: + /// + /// Please use Capturing(1) in + /// instead. + /// + /// + /// + /// This callback indicates that the camera has been successfully turned on and + /// you can start to capture video. + /// @deprecated EmptyCallback? cameraReady; + /// /// Occurs when the video stops playing. + /// Deprecated: + /// Please use Stopped(0) in the + /// callback instead. + /// + /// + /// The application can use this callback to change the configuration of the + /// view (for example, displaying other pictures in the view) after + /// the video stops playing. /// - /// **Deprecated** Use [LocalVideoStreamState.Stopped] in the [RtcEngineEventHandler.localVideoStateChanged] callback instead. The application can use this callback to change the configuration of the view (for example, displaying other pictures in the view) after the video stops playing. - /// The `EmptyCallback` typedef does not include any parameter. @deprecated EmptyCallback? videoStopped; + /// /// Occurs when the local user receives the metadata. /// - /// The `MetadataCallback` typedef includes the following parameters: - /// - [String]: `buffer`: The received metadata. - /// - [int]: `uid`: The ID of the user who sent the metadata. - /// - [int]: `timeStampMs`: The timestamp (ms) of the received metadata. + /// + /// Param [uid] The user ID. + /// + /// Param [timeStampMs] The timestamp. + /// MetadataCallback? metadataReceived; - /// Occurs when the first audio frame is published. /// + /// Occurs when the first audio frame is published. /// The SDK triggers this callback under one of the following circumstances: - /// - The local client enables the audio module and calls [RtcEngine.joinChannel] successfully. - /// - The local client calls [RtcEngine.muteLocalAudioStream] (`true`) and [RtcEngine.muteLocalAudioStream] (`false`) in sequence. - /// - The local client calls [RtcEngine.disableAudio] (`true`) and [RtcEngine.enableAudio] in sequence. + /// The local client enables the audio module and calls joinChannel successfully. + /// The local client calls muteLocalAudioStream(true) and muteLocalAudioStream(false) in sequence. + /// The local client calls disableAudio and enableAudio in sequence. + /// + /// Param [elapsed] The time elapsed (ms) from the local client calling joinChannel until the SDK triggers this callback. /// - /// The `ElapsedCallback` typedef includes the following parameters: - /// - [int] `Elapsed`: Time elapsed (ms) from the local user calling the [RtcEngine.joinChannel] until this callback is triggered. ElapsedCallback? firstLocalAudioFramePublished; - /// Occurs when the first video frame is published. /// + /// Occurs when the first video frame is published. /// The SDK triggers this callback under one of the following circumstances: - /// - The local client enables the video module and calls [RtcEngine.joinChannel] successfully. - /// - The local client calls [RtcEngine.muteLocalVideoStream] (`true`) and [RtcEngine.muteLocalVideoStream] (`false`) in sequence. - /// - The local client calls [RtcEngine.disableVideo] and [RtcEngine.enableVideo] in sequence. + /// The local client enables the video module and calls joinChannel successfully. + /// The local client calls muteLocalVideoStream(true) and muteLocalVideoStream(false) in sequence. + /// The local client calls disableVideo and enableVideo in sequence. + /// + /// Param [elapsed] The time elapsed(ms) from the local client calling joinChannel until the SDK triggers this callback. /// - /// The `ElapsedCallback` typedef includes the following parameters: - /// - [int] `Elapsed`: Time elapsed (ms) from the local user calling the [RtcEngine.joinChannel] until this callback is triggered. ElapsedCallback? firstLocalVideoFramePublished; + /// /// Occurs when the audio publishing state changes. /// - /// This callback indicates the publishing state change of the local audio stream. /// - /// The `StreamPublishStateCallback` typedef includes the following parameters: - /// - [String] `channel`: The channel name. - /// - [StreamPublishState] `oldState`: The previous publishing state. See [StreamPublishState]. - /// - [StreamPublishState] `newState`: The current publishing state. See [StreamPublishState]. - /// - [int] `elapseSinceLastState`: The time elapsed (ms) from the previous state to the current state. + /// Param [channel] The name of the channel. + /// + /// Param [oldState] For the previous publishing state, see StreamPublishState. + /// + /// Param [newState] For the current publishing state, see StreamPublishState. + /// + /// Param [elapseSinceLastState] The time elapsed (ms) from the previous state to the current state. + /// StreamPublishStateCallback? audioPublishStateChanged; + /// /// Occurs when the video publishing state changes. /// - /// This callback indicates the publishing state change of the local video stream. /// - /// The `StreamPublishStateCallback` typedef includes the following parameters: - /// - [String] `channel`: The channel name. - /// - [StreamPublishState] `oldState`: The previous publishing state. See [StreamPublishState]. - /// - [StreamPublishState] `newState`: The current publishing state. See [StreamPublishState]. - /// - [int] `elapseSinceLastState`: The time elapsed (ms) from the previous state to the current state. + /// Param [channel] The name of the channel. + /// + /// Param [oldState] For the previous publishing state, see StreamPublishState. + /// + /// Param [newState] For the current publishing state, see StreamPublishState. + /// + /// Param [elapseSinceLastState] The time elapsed (ms) from the previous state to the current state. + /// StreamPublishStateCallback? videoPublishStateChanged; + /// /// Occurs when the audio subscribing state changes. /// - /// This callback indicates the subscribing state change of a remote audio stream. /// - /// The `StreamSubscribeStateCallback` typedef includes the following parameters: - /// - [String] `channel`: The channel name. - /// - [StreamSubscribeState] `oldState`: The previous publishing state. See [StreamPublishState]. - /// - [StreamSubscribeState] `newState`: The current publishing state. See [StreamPublishState]. - /// - [int] `elapseSinceLastState`: The time elapsed (ms) from the previous state to the current state. + /// Param [channel] The name of the channel. + /// + /// Param [oldState] The previous subscribing status, see StreamSubscribeState + /// for details. + /// + /// Param [newState] The current subscribing status, see StreamSubscribeState for details. + /// + /// Param [elapseSinceLastState] The time elapsed (ms) from the previous state to the current state. + /// StreamSubscribeStateCallback? audioSubscribeStateChanged; + /// /// Occurs when the video subscribing state changes. /// - /// This callback indicates the subscribing state change of a remote video stream. /// - /// The `StreamSubscribeStateCallback` typedef includes the following parameters: - /// - [String] `channel`: The channel name. - /// - [StreamSubscribeState] `oldState`: The previous publishing state. See [StreamPublishState]. - /// - [StreamSubscribeState] `newState`: The current publishing state. See [StreamPublishState]. - /// - [int] `elapseSinceLastState`: The time elapsed (ms) from the previous state to the current state. + /// Param [channel] The name of the channel. + /// + /// Param [oldState] The previous subscribing status, see StreamSubscribeState + /// for details. + /// + /// Param [newState] The current subscribing status, see StreamSubscribeState for details. + /// + /// Param [elapseSinceLastState] The time elapsed (ms) from the previous state to the current state. + /// StreamSubscribeStateCallback? videoSubscribeStateChanged; + /// /// Reports events during the RTMP or RTMPS streaming. /// - /// The `RtmpStreamingEventCallback` typedef includes the following parameters: - /// - [String] `url`: The RTMP or RTMPS streaming URL. - /// - [RtmpStreamingEvent] `eventCode`: The event code. See [RtmpStreamingEvent]. + /// + /// Param [url] The RTMP or RTMPS streaming URL. + /// + /// Param [eventCode] The event code of the streaming. For details, see RtmpStreamingEvent. + /// RtmpStreamingEventCallback? rtmpStreamingEvent; - /// Reports whether the super resolution feature is successfully enabled. (beta feature) /// - /// After calling [RtcEngine.enableRemoteSuperResolution], the SDK triggers this callback to report whether super resolution is successfully enabled. If it is not successfully enabled, use reason for troubleshooting. + /// Reports whether the super resolution feature is successfully enabled. + /// After calling enableRemoteSuperResolution, the SDK triggers the callback to report whether super resolution is successfully enabled. If it is not successfully enabled, use reason for troubleshooting. + /// + /// Param [uid] The ID of the remote user. /// - /// The `UserSuperResolutionEnabledCallback` typedef includes the following parameters: + /// Param [enabled] Whether super resolution is successfully enabled: + /// true: Super resolution is successfully enabled. + /// false: Super resolution is not successfully enabled. /// - /// **Parameter** [uid] The user ID of the remote user. /// - /// **Parameter** [enabled] Whether super resolution is successfully enabled: - /// - `true`: Super resolution is successfully enabled. - /// - `false`: Super resolution is not successfully enabled. + /// Param [reason] The reason why super resolution algorithm is not successfully enabled. For details, see SuperResolutionStateReason. /// - /// **Parameter** [reason] The reason why super resolution is not successfully enabled or the message that confirms success. UserSuperResolutionEnabledCallback? userSuperResolutionEnabled; - /// @nodoc + /// + /// Reports the result of uploading the SDK log files. + /// Since + /// v3.3.0 + /// + /// + /// After uploadLogFile is called, the SDK triggers the callback to report the result of uploading the SDK log files. If the upload fails, refer to the reason parameter to troubleshoot. + /// + /// Param [requestId] The request ID. The request ID is the same as the requestId returned in uploadLogFile. You can use the requestId to match a specific upload with a callback. + /// + /// Param [success] Whether the log file is uploaded successfully: + /// true: Successfully upload the log files. + /// false: Fails to upload the log files. For details, see the reason parameter. + /// + /// + /// Param [reason] The reason for the upload failure. For details, see UploadErrorReason. + /// UploadLogResultCallback? uploadLogResult; - /// @nodoc + /* callback-engine-airPlayIsConnected */ + @Deprecated('Use airPlayConnected instead') EmptyCallback? airPlayIsConnected; - /// Reports whether the virtual background is successfully enabled. (beta function) + EmptyCallback? airPlayConnected; + + /// + /// Reports whether virtual background is successfully enabled. (Beta feature) + /// After you call enableVirtualBackground, the SDK triggers this callback to report whether virtual background is successfully enabled. + /// If the background image customized in the virtual background is in the PNG or JPG format, this callback is triggered after the image is read. + /// + /// Param [enabled] Whether virtual background is successfully enabled: + /// true: Virtual background is successfully enabled. + /// false: Virtual background is not successfully enabled. /// - /// The `VirtualBackgroundSourceEnabledCallback` typedef includes the following parameters: /// - /// - [bool] `enabled`: Whether the virtual background is successfully enabled: - /// - `true`: The virtual background is successfully enabled. - /// - `false`: The virtual background is not successfully enabled. - /// - [VirtualBackgroundSourceStateReason] `reason`: The reason why the virtual background is not successfully enabled or the message that confirms success. See [VirtualBackgroundSourceStateReason]. + /// Param [reason] The reason why virtual background is not successfully enabled. See VirtualBackgroundSourceStateReason. + /// VirtualBackgroundSourceEnabledCallback? virtualBackgroundSourceEnabled; - /// Reports the result of taking a video snapshot. /// - /// Since - /// v4.2.0 + /// Occurs when the video device state changes. + /// This callback reports the change of system video devices, such as being unplugged or removed. On a Windows device with an external camera for video capturing, the video disables once the external camera is unplugged. + /// + /// Param [deviceId] The device ID. + /// + /// Param [deviceType] Media device types. For details, see MediaDeviceType. + /// + /// Param [deviceState] Media device states. For details, see MediaDeviceStateType. + /// + VideoDeviceStateChanged? videoDeviceStateChanged; + + /// + /// Occurs when the volume on the playback or audio capture device, or the volume in the application changes. + /// + /// + /// Param [deviceType] The device type. For details, see MediaDeviceType. + /// + /// Param [volume] The volume value. The range is [0, 255]. + /// + /// Param [muted] Whether the audio device is muted: + /// true: The audio device is muted. + /// false: The audio device is not muted. /// - /// After a successful [RtcEngine.takeSnapshot] method call, the SDK triggers this callback - /// to report whether the snapshot is successfully taken as well as the details - /// for the snapshot taken. /// - /// The `SnapshotTakenCallback` typedef includes the following parameters: + AudioDeviceVolumeChanged? audioDeviceVolumeChanged; + + /// + /// Occurs when the audio device state changes. + /// This callback notifies the application that the system's audio device state is changed. For example, a headset is unplugged from the device. + /// This method is for Windows and macOS only. /// + /// Param [deviceId] The device ID. /// + /// Param [deviceType] The device type. For details, see MediaDeviceType. /// - /// **Parameter** [channel] The channel name. + /// Param [deviceState] The device state. + /// on macOS: + /// 0: The device is ready for use. + /// 8: The device is not connected. /// - /// **Parameter** [uid] The user ID of the user. A uid of 0 indicates the local user. + /// On Windows: MediaDeviceStateType. /// - /// **Parameter** [filePath] The local path of the snapshot. /// - /// **Parameter** [width] The width (px) of the snapshot. + AudioDeviceStateChanged? audioDeviceStateChanged; + + /// + /// Occurs when a remote user starts audio mixing. + /// When a remote user calls startAudioMixing to play the background music, the SDK reports this callback. + /// + EmptyCallback? remoteAudioMixingBegin; + + /// + /// Occurs when a remote user finishes audio mixing. + /// The SDK triggers this callback when a remote user finishes audio mixing. + /// + EmptyCallback? remoteAudioMixingEnd; + + /// + /// Reports the result of taking a video snapshot. + /// takeSnapshot method call, the SDK triggers this callback to report whether the snapshot is successfully taken as well as the details for the snapshot taken. + /// + /// Param [channel] The channel name. + /// + /// Param [uid] The user ID. A uid of 0 indicates the local user. + /// + /// Param [filePath] The local path of the snapshot. + /// + /// Param [width] The width (px) of the snapshot. + /// + /// Param [height] The height (px) of the snapshot. + /// + /// Param [errCode] The message that confirms success or the reason why the snapshot is not successfully taken: + /// 0: Success. + /// < 0: Failure: + /// -1: The SDK fails to write data to a file or encode a JPEG image. + /// -2: The SDK does not find the video stream of the specified user within one second after the takeSnapshot method call succeeds. + /// /// - /// **Parameter** [height] The height (px) of the snapshot. /// - /// **Parameter** [errCode] The message that confirms success or the reason why the snapshot - /// is not successfully taken: - /// - 0: Success. - /// - < 0: Failure. - /// - -1: The SDK fails to write data to a file or encode a JPEG image. - /// - -2: The SDK does not find the video stream of the specified user within - /// one second after the [RtcEngine.takeSnapshot] method call succeeds. SnapshotTakenCallback? snapshotTaken; /// Constructs a [RtcEngineEventHandler] @@ -1124,6 +1431,7 @@ class RtcEngineEventHandler { this.remoteAudioStateChanged, this.localAudioStateChanged, this.requestAudioFileInfoCallback, + this.requestAudioFileInfo, this.localPublishFallbackToAudioOnly, this.remoteSubscribeFallbackToAudioOnly, this.audioRouteChanged, @@ -1178,212 +1486,288 @@ class RtcEngineEventHandler { this.userSuperResolutionEnabled, this.uploadLogResult, this.airPlayIsConnected, + this.airPlayConnected, this.virtualBackgroundSourceEnabled, + this.videoDeviceStateChanged, + this.audioDeviceVolumeChanged, + this.audioDeviceStateChanged, + this.remoteAudioMixingBegin, + this.remoteAudioMixingEnd, this.snapshotTaken, }); // ignore: public_member_api_docs - void process(String methodName, List data) { + void process(String methodName, dynamic data, [Uint8List? buffer]) { + List newData; + // if (kIsWeb || (Platform.isWindows || Platform.isMacOS)) { + + // } else { + // newData = List.from(data); + // } + if (methodName.startsWith('on')) { + methodName = methodName.substring(2); + } + + newData = List.from( + Map.from(jsonDecode(data as String)).values); switch (methodName) { case 'Warning': - warning?.call(WarningCodeConverter.fromValue(data[0]).e); + warning?.call(WarningCodeConverter.fromValue(newData[0]).e); break; case 'Error': - error?.call(ErrorCodeConverter.fromValue(data[0]).e); + error?.call(ErrorCodeConverter.fromValue(newData[0]).e); break; case 'ApiCallExecuted': apiCallExecuted?.call( - ErrorCodeConverter.fromValue(data[0]).e, data[1], data[2]); + ErrorCodeConverter.fromValue(newData[0]).e, newData[1], newData[2]); break; case 'JoinChannelSuccess': - joinChannelSuccess?.call(data[0], data[1], data[2]); + joinChannelSuccess?.call(newData[0], newData[1], newData[2]); break; case 'RejoinChannelSuccess': - rejoinChannelSuccess?.call(data[0], data[1], data[2]); + rejoinChannelSuccess?.call(newData[0], newData[1], newData[2]); break; case 'LeaveChannel': leaveChannel - ?.call(RtcStats.fromJson(Map.from(data[0]))); + ?.call(RtcStats.fromJson(Map.from(newData[0]))); break; case 'LocalUserRegistered': - localUserRegistered?.call(data[0], data[1]); + localUserRegistered?.call(newData[0], newData[1]); break; case 'UserInfoUpdated': - userInfoUpdated?.call( - data[0], UserInfo.fromJson(Map.from(data[1]))); + userInfoUpdated?.call(newData[0], + UserInfo.fromJson(Map.from(newData[1]))); break; case 'ClientRoleChanged': - clientRoleChanged?.call(ClientRoleConverter.fromValue(data[0]).e, - ClientRoleConverter.fromValue(data[1]).e); + clientRoleChanged?.call(ClientRoleConverter.fromValue(newData[0]).e, + ClientRoleConverter.fromValue(newData[1]).e); break; case 'UserJoined': - userJoined?.call(data[0], data[1]); + userJoined?.call(newData[0], newData[1]); break; case 'UserOffline': userOffline?.call( - data[0], UserOfflineReasonConverter.fromValue(data[1]).e); + newData[0], UserOfflineReasonConverter.fromValue(newData[1]).e); break; case 'ConnectionStateChanged': connectionStateChanged?.call( - ConnectionStateTypeConverter.fromValue(data[0]).e, - ConnectionChangedReasonConverter.fromValue(data[1]).e); + ConnectionStateTypeConverter.fromValue(newData[0]).e, + ConnectionChangedReasonConverter.fromValue(newData[1]).e); break; case 'NetworkTypeChanged': - networkTypeChanged?.call(NetworkTypeConverter.fromValue(data[0]).e); + networkTypeChanged?.call(NetworkTypeConverter.fromValue(newData[0]).e); break; case 'ConnectionLost': connectionLost?.call(); break; case 'TokenPrivilegeWillExpire': - tokenPrivilegeWillExpire?.call(data[0]); + tokenPrivilegeWillExpire?.call(newData[0]); break; case 'RequestToken': requestToken?.call(); break; case 'AudioVolumeIndication': - final list = List.from(data[0]); + final list = List.from(newData[0]); + var totalVolume; + // if (kIsWeb || (Platform.isWindows || Platform.isMacOS)) { + + // } else { + // totalVolume = newData[2]; + // } + totalVolume = newData[2]; audioVolumeIndication?.call( List.generate( list.length, (index) => AudioVolumeInfo.fromJson( Map.from(list[index]))), - data[1]); + totalVolume); break; case 'ActiveSpeaker': - activeSpeaker?.call(data[0]); + activeSpeaker?.call(newData[0]); break; case 'FirstLocalAudioFrame': - firstLocalAudioFrame?.call(data[0]); + firstLocalAudioFrame?.call(newData[0]); break; case 'FirstLocalVideoFrame': - firstLocalVideoFrame?.call(data[0], data[1], data[2]); + firstLocalVideoFrame?.call(newData[0], newData[1], newData[2]); break; case 'UserMuteVideo': - userMuteVideo?.call(data[0], data[1]); + userMuteVideo?.call(newData[0], newData[1]); break; case 'VideoSizeChanged': - videoSizeChanged?.call(data[0], data[1], data[2], data[3]); + videoSizeChanged?.call(newData[0], newData[1], newData[2], newData[3]); break; case 'RemoteVideoStateChanged': remoteVideoStateChanged?.call( - data[0], - VideoRemoteStateConverter.fromValue(data[1]).e, - VideoRemoteStateReasonConverter.fromValue(data[2]).e, - data[3]); + newData[0], + VideoRemoteStateConverter.fromValue(newData[1]).e, + VideoRemoteStateReasonConverter.fromValue(newData[2]).e, + newData[3]); break; case 'LocalVideoStateChanged': localVideoStateChanged?.call( - LocalVideoStreamStateConverter.fromValue(data[0]).e, - LocalVideoStreamErrorConverter.fromValue(data[1]).e); + LocalVideoStreamStateConverter.fromValue(newData[0]).e, + LocalVideoStreamErrorConverter.fromValue(newData[1]).e); break; case 'RemoteAudioStateChanged': remoteAudioStateChanged?.call( - data[0], - AudioRemoteStateConverter.fromValue(data[1]).e, - AudioRemoteStateReasonConverter.fromValue(data[2]).e, - data[3]); + newData[0], + AudioRemoteStateConverter.fromValue(newData[1]).e, + AudioRemoteStateReasonConverter.fromValue(newData[2]).e, + newData[3]); break; case 'LocalAudioStateChanged': localAudioStateChanged?.call( - AudioLocalStateConverter.fromValue(data[0]).e, - AudioLocalErrorConverter.fromValue(data[1]).e); + AudioLocalStateConverter.fromValue(newData[0]).e, + AudioLocalErrorConverter.fromValue(newData[1]).e); break; case 'RequestAudioFileInfo': - requestAudioFileInfoCallback?.call(AudioFileInfo.fromJson(data[0]), - AudioFileInfoErrorConverter.fromValue(data[1]).e); + requestAudioFileInfoCallback?.call(AudioFileInfo.fromJson(newData[0]), + AudioFileInfoErrorConverter.fromValue(newData[1]).e); + + requestAudioFileInfo?.call(AudioFileInfo.fromJson(newData[0]), + AudioFileInfoErrorConverter.fromValue(newData[1]).e); break; case 'LocalPublishFallbackToAudioOnly': - localPublishFallbackToAudioOnly?.call(data[0]); + localPublishFallbackToAudioOnly?.call(newData[0]); break; case 'RemoteSubscribeFallbackToAudioOnly': - remoteSubscribeFallbackToAudioOnly?.call(data[0], data[1]); + remoteSubscribeFallbackToAudioOnly?.call(newData[0], newData[1]); break; case 'AudioRouteChanged': audioRouteChanged - ?.call(AudioOutputRoutingConverter.fromValue(data[0]).e); + ?.call(AudioOutputRoutingConverter.fromValue(newData[0]).e); break; case 'CameraFocusAreaChanged': - cameraFocusAreaChanged - ?.call(Rect.fromJson(Map.from(data[0]))); + if (cameraFocusAreaChanged != null) { + // TODO(littlegnal): Optimize this logic + final rect = Rect(); // Rect.fromJson(newData[0]); + rect.x = newData[0]; + rect.y = newData[1]; + rect.width = newData[2]; + rect.height = newData[3]; + // ignore: deprecated_member_use_from_same_package + rect.left = rect.x; + // ignore: deprecated_member_use_from_same_package + rect.top = rect.y; + // ignore: deprecated_member_use_from_same_package + rect.right = rect.x + rect.width; + // ignore: deprecated_member_use_from_same_package + rect.bottom = rect.y + rect.height; + cameraFocusAreaChanged!(rect); + } + break; case 'CameraExposureAreaChanged': - cameraExposureAreaChanged - ?.call(Rect.fromJson(Map.from(data[0]))); + if (cameraExposureAreaChanged != null) { + // TODO(littlegnal): Optimize this logic + final rect = Rect(); // Rect.fromJson(newData[0]); + rect.x = newData[0]; + rect.y = newData[1]; + rect.width = newData[2]; + rect.height = newData[3]; + // ignore: deprecated_member_use_from_same_package + rect.left = rect.x; + // ignore: deprecated_member_use_from_same_package + rect.top = rect.y; + // ignore: deprecated_member_use_from_same_package + rect.right = rect.x + rect.width; + // ignore: deprecated_member_use_from_same_package + rect.bottom = rect.y + rect.height; + cameraExposureAreaChanged!(rect); + } break; case 'FacePositionChanged': - final list = List.from(data[2]); - facePositionChanged?.call( - data[0], - data[1], - List.generate( - list.length, - (index) => FacePositionInfo.fromJson( - Map.from(list[index])))); + if (facePositionChanged != null) { + final rectList = List.from(newData[2]); + final distanceList = List.from(newData[3]); + final faceInfos = List.generate( + rectList.length, + (index) { + final rect = rectList[index]; + rect['distance'] = distanceList[index]; + final info = + FacePositionInfo.fromJson(Map.from(rect)); + return info; + }, + ); + facePositionChanged!(newData[0], newData[1], faceInfos); + } + break; case 'RtcStats': - rtcStats?.call(RtcStats.fromJson(Map.from(data[0]))); + rtcStats + ?.call(RtcStats.fromJson(Map.from(newData[0]))); break; case 'LastmileQuality': - lastmileQuality?.call(NetworkQualityConverter.fromValue(data[0]).e); + lastmileQuality?.call(NetworkQualityConverter.fromValue(newData[0]).e); break; case 'NetworkQuality': networkQuality?.call( - data[0], - NetworkQualityConverter.fromValue(data[1]).e, - NetworkQualityConverter.fromValue(data[2]).e); + newData[0], + NetworkQualityConverter.fromValue(newData[1]).e, + NetworkQualityConverter.fromValue(newData[2]).e); break; case 'LastmileProbeResult': - lastmileProbeResult?.call( - LastmileProbeResult.fromJson(Map.from(data[0]))); + lastmileProbeResult?.call(LastmileProbeResult.fromJson( + Map.from(newData[0]))); break; case 'LocalVideoStats': localVideoStats?.call( - LocalVideoStats.fromJson(Map.from(data[0]))); + LocalVideoStats.fromJson(Map.from(newData[0]))); break; case 'LocalAudioStats': localAudioStats?.call( - LocalAudioStats.fromJson(Map.from(data[0]))); + LocalAudioStats.fromJson(Map.from(newData[0]))); break; case 'RemoteVideoStats': remoteVideoStats?.call( - RemoteVideoStats.fromJson(Map.from(data[0]))); + RemoteVideoStats.fromJson(Map.from(newData[0]))); break; case 'RemoteAudioStats': remoteAudioStats?.call( - RemoteAudioStats.fromJson(Map.from(data[0]))); + RemoteAudioStats.fromJson(Map.from(newData[0]))); break; case 'AudioMixingFinished': audioMixingFinished?.call(); break; case 'AudioMixingStateChanged': audioMixingStateChanged?.call( - AudioMixingStateCodeConverter.fromValue(data[0]).e, - AudioMixingReasonConverter.fromValue(data[1]).e, + AudioMixingStateCodeConverter.fromValue(newData[0]).e, + AudioMixingReasonConverter.fromValue(newData[1]).e, ); break; case 'AudioEffectFinished': - audioEffectFinished?.call(data[0]); + audioEffectFinished?.call(newData[0]); break; case 'RtmpStreamingStateChanged': rtmpStreamingStateChanged?.call( - data[0], - RtmpStreamingStateConverter.fromValue(data[1]).e, - RtmpStreamingErrorCodeConverter.fromValue(data[2]).e, + newData[0], + RtmpStreamingStateConverter.fromValue(newData[1]).e, + RtmpStreamingErrorCodeConverter.fromValue(newData[2]).e, ); break; case 'TranscodingUpdated': transcodingUpdated?.call(); break; case 'StreamInjectedStatus': - streamInjectedStatus?.call( - data[0], data[1], InjectStreamStatusConverter.fromValue(data[2]).e); + streamInjectedStatus?.call(newData[0], newData[1], + InjectStreamStatusConverter.fromValue(newData[2]).e); break; case 'StreamMessage': - streamMessage?.call(data[0], data[1], data[2]); + // if (kIsWeb || (Platform.isWindows || Platform.isMacOS)) { + + // } else { + // String data = newData[2]; + // streamMessage?.call( + // newData[0], newData[1], Uint8List.fromList(data.codeUnits)); + // } + if (buffer == null) return; + streamMessage?.call(newData[0], newData[1], buffer); break; case 'StreamMessageError': - streamMessageError?.call(data[0], data[1], - ErrorCodeConverter.fromValue(data[2]).e, data[3], data[4]); + streamMessageError?.call(newData[0], newData[1], + ErrorCodeConverter.fromValue(newData[2]).e, newData[3], newData[4]); break; case 'MediaEngineLoadSuccess': mediaEngineLoadSuccess?.call(); @@ -1393,49 +1777,54 @@ class RtcEngineEventHandler { break; case 'ChannelMediaRelayStateChanged': channelMediaRelayStateChanged?.call( - ChannelMediaRelayStateConverter.fromValue(data[0]).e, - ChannelMediaRelayErrorConverter.fromValue(data[1]).e, + ChannelMediaRelayStateConverter.fromValue(newData[0]).e, + ChannelMediaRelayErrorConverter.fromValue(newData[1]).e, ); break; case 'ChannelMediaRelayEvent': channelMediaRelayEvent - ?.call(ChannelMediaRelayEventConverter.fromValue(data[0]).e); + ?.call(ChannelMediaRelayEventConverter.fromValue(newData[0]).e); break; case 'FirstRemoteVideoFrame': - firstRemoteVideoFrame?.call(data[0], data[1], data[2], data[3]); + firstRemoteVideoFrame?.call( + newData[0], newData[1], newData[2], newData[3]); break; case 'FirstRemoteAudioFrame': - firstRemoteAudioFrame?.call(data[0], data[1]); + firstRemoteAudioFrame?.call(newData[0], newData[1]); break; case 'FirstRemoteAudioDecoded': - firstRemoteAudioDecoded?.call(data[0], data[1]); + firstRemoteAudioDecoded?.call(newData[0], newData[1]); break; case 'UserMuteAudio': - userMuteAudio?.call(data[0], data[1]); + userMuteAudio?.call(newData[0], newData[1]); break; case 'StreamPublished': - streamPublished?.call(data[0], ErrorCodeConverter.fromValue(data[1]).e); + streamPublished?.call( + newData[0], ErrorCodeConverter.fromValue(newData[1]).e); break; case 'StreamUnpublished': - streamUnpublished?.call(data[0]); + streamUnpublished?.call(newData[0]); break; case 'RemoteAudioTransportStats': - remoteAudioTransportStats?.call(data[0], data[1], data[2], data[3]); + remoteAudioTransportStats?.call( + newData[0], newData[1], newData[2], newData[3]); break; case 'RemoteVideoTransportStats': - remoteVideoTransportStats?.call(data[0], data[1], data[2], data[3]); + remoteVideoTransportStats?.call( + newData[0], newData[1], newData[2], newData[3]); break; case 'UserEnableVideo': - userEnableVideo?.call(data[0], data[1]); + userEnableVideo?.call(newData[0], newData[1]); break; case 'UserEnableLocalVideo': - userEnableLocalVideo?.call(data[0], data[1]); + userEnableLocalVideo?.call(newData[0], newData[1]); break; case 'FirstRemoteVideoDecoded': - firstRemoteVideoDecoded?.call(data[0], data[1], data[2], data[3]); + firstRemoteVideoDecoded?.call( + newData[0], newData[1], newData[2], newData[3]); break; case 'MicrophoneEnabled': - microphoneEnabled?.call(data[0]); + microphoneEnabled?.call(newData[0]); break; case 'ConnectionInterrupted': connectionInterrupted?.call(); @@ -1444,7 +1833,7 @@ class RtcEngineEventHandler { connectionBanned?.call(); break; case 'AudioQuality': - audioQuality?.call(data[0], data[1], data[2], data[3]); + audioQuality?.call(newData[0], newData[1], newData[2], newData[3]); break; case 'CameraReady': cameraReady?.call(); @@ -1453,440 +1842,540 @@ class RtcEngineEventHandler { videoStopped?.call(); break; case 'MetadataReceived': - metadataReceived?.call(data[0], data[1], data[2]); + Metadata metadata; + // if (kIsWeb || (Platform.isWindows || Platform.isMacOS)) { + + // } else { + // metadata = Metadata(newData[1], newData[2]); + // String buffer = newData[0]; + // metadata.buffer = Uint8List.fromList(buffer.codeUnits); + // } + if (buffer == null) return; + metadata = Metadata.fromJson(Map.from(newData[0])); + metadata.buffer = buffer; + metadataReceived?.call(metadata); break; case 'FirstLocalAudioFramePublished': - firstLocalAudioFramePublished?.call(data[0]); + firstLocalAudioFramePublished?.call(newData[0]); break; case 'FirstLocalVideoFramePublished': - firstLocalVideoFramePublished?.call(data[0]); + firstLocalVideoFramePublished?.call(newData[0]); break; case 'AudioPublishStateChanged': audioPublishStateChanged?.call( - data[0], - StreamPublishStateConverter.fromValue(data[1]).e, - StreamPublishStateConverter.fromValue(data[2]).e, - data[3]); + newData[0], + StreamPublishStateConverter.fromValue(newData[1]).e, + StreamPublishStateConverter.fromValue(newData[2]).e, + newData[3]); break; case 'VideoPublishStateChanged': videoPublishStateChanged?.call( - data[0], - StreamPublishStateConverter.fromValue(data[1]).e, - StreamPublishStateConverter.fromValue(data[2]).e, - data[3]); + newData[0], + StreamPublishStateConverter.fromValue(newData[1]).e, + StreamPublishStateConverter.fromValue(newData[2]).e, + newData[3]); break; case 'AudioSubscribeStateChanged': audioSubscribeStateChanged?.call( - data[0], - data[1], - StreamSubscribeStateConverter.fromValue(data[2]).e, - StreamSubscribeStateConverter.fromValue(data[3]).e, - data[4]); + newData[0], + newData[1], + StreamSubscribeStateConverter.fromValue(newData[2]).e, + StreamSubscribeStateConverter.fromValue(newData[3]).e, + newData[4]); break; case 'VideoSubscribeStateChanged': videoSubscribeStateChanged?.call( - data[0], - data[1], - StreamSubscribeStateConverter.fromValue(data[2]).e, - StreamSubscribeStateConverter.fromValue(data[3]).e, - data[4]); + newData[0], + newData[1], + StreamSubscribeStateConverter.fromValue(newData[2]).e, + StreamSubscribeStateConverter.fromValue(newData[3]).e, + newData[4]); break; case 'RtmpStreamingEvent': - rtmpStreamingEvent?.call(data[0], data[1]); + rtmpStreamingEvent?.call( + newData[0], + RtmpStreamingEventConverter.fromValue(newData[1]).e, + ); break; case 'UserSuperResolutionEnabled': - userSuperResolutionEnabled?.call(data[0], data[1], - SuperResolutionStateReasonConverter.fromValue(data[2]).e); + userSuperResolutionEnabled?.call(newData[0], newData[1], + SuperResolutionStateReasonConverter.fromValue(newData[2]).e); break; case 'UploadLogResult': - uploadLogResult?.call( - data[0], data[1], UploadErrorReasonConverter.fromValue(data[2]).e); + uploadLogResult?.call(newData[0], newData[1], + UploadErrorReasonConverter.fromValue(newData[2]).e); + break; + case 'VideoDeviceStateChanged': + videoDeviceStateChanged?.call( + newData[0] as String, + MediaDeviceTypeConverter.fromValue(newData[1]).e, + MediaDeviceStateTypeConverter.fromValue(newData[2]).e, + ); + break; + case 'AudioDeviceVolumeChanged': + audioDeviceVolumeChanged?.call( + MediaDeviceTypeConverter.fromValue(newData[0]).e, + newData[1] as int, + newData[2] as bool, + ); + break; + case 'AudioDeviceStateChanged': + audioDeviceStateChanged?.call( + newData[0] as String, + MediaDeviceTypeConverter.fromValue(newData[1]).e, + MediaDeviceStateTypeConverter.fromValue(newData[2]).e, + ); + break; + case 'RemoteAudioMixingBegin': + remoteAudioMixingBegin?.call(); + break; + case 'RemoteAudioMixingEnd': + remoteAudioMixingEnd?.call(); break; - case 'AirPlayIsConnected': + case 'AirPlayConnected': airPlayIsConnected?.call(); + + airPlayConnected?.call(); break; case 'VirtualBackgroundSourceEnabled': - virtualBackgroundSourceEnabled?.call(data[0], - VirtualBackgroundSourceStateReasonConverter.fromValue(data[1]).e); + virtualBackgroundSourceEnabled?.call( + newData[0], + VirtualBackgroundSourceStateReasonConverter.fromValue(newData[1]) + .e); break; case 'SnapshotTaken': - snapshotTaken?.call( - data[0], data[1], data[2], data[3], data[4], data[5]); + snapshotTaken?.call(newData[0], newData[1], newData[2], newData[3], + newData[4], newData[5]); + break; + case 'VideoSourceFrameSizeChangedIris': + // Internal used, do nothing break; + default: + throw ArgumentError('Not Supported Event: $methodName'); } } } -/// The RtcChannelEvents interface. +/// +/// The SDK uses RtcChannelEventHandler to send RtcChannel event notifications to your app. +/// +/// class RtcChannelEventHandler { - /// Reports the warning code of the [RtcChannel] instance. /// - /// The `WarningCallback` typedef includes the following parameter: - /// - [WarningCode] `warn`: Warning code. + /// Reports the warning code of RtcChannel. + /// + /// + /// Param [] + /// + /// Param [warn] Warning codes. For details, see Error Codes and Warning Codes. + /// + /// Param [msg] The warning message. + /// WarningCallback? warning; - /// Reports the error code of the [RtcChannel] instance. /// - /// The `ErrorCallback` typedef includes the following parameter: - /// - [ErrorCode] `err`: Error code. + /// The error code RtcChannel reported. + /// + /// + /// Param [] + /// + /// Param [err] The error code. For details, see Error Codes and Warning Codes. + /// + /// Param [msg] The error message. + /// ErrorCallback? error; - /// Occurs when the local user joins a specified channel. - /// - /// If the uid is not specified when calling [RtcChannel.joinChannel], the server automatically assigns a uid. - /// - /// The `UidWithElapsedCallback` typedef includes the following parameters: - /// - [int] `uid`: This parameter has the following definitions in different events: - /// - [userJoined]: ID of the user or host who joins the channel. - /// - [firstRemoteAudioFrame]: User ID of the remote user. - /// - [firstRemoteAudioDecoded]: User ID of the remote user sending the audio stream. - /// - [joinChannelSuccess]: User ID. - /// - [rejoinChannelSuccess]: User ID. - /// - [int] `elapsed`: - /// - [userJoined]: Time delay (ms) from the local user calling [RtcEngine.joinChannel] or [RtcEngine.setClientRole] until this callback is triggered. - /// - [firstRemoteAudioFrame]: Time elapsed (ms) from the local user calling [RtcEngine.joinChannel] until this callback is triggered. - /// - [firstRemoteAudioDecoded]: Time elapsed (ms) from the local user calling [RtcEngine.joinChannel] until the SDK triggers this callback. - /// - [joinChannelSuccess]: Time elapsed (ms) from the local user calling [RtcChannel.joinChannel] until this callback is triggered. - /// - [rejoinChannelSuccess]: Time elapsed (ms) from the local user starting to reconnect until this callback is triggered. + /// + /// Occurs when a user joins a channel. + /// This callback notifies the application that a user joins a specified channel. + /// + /// Param [] + /// + /// Param [uid] User ID. If you have specified a user ID in joinChannel, the ID will be returned here; otherwise, the SDK returns an ID automatically assigned by the Agora server. + /// + /// Param [elapsed] The time elapsed (in milliseconds) from the local user calling joinChannel till this event. + /// UidWithElapsedAndChannelCallback? joinChannelSuccess; - /// Occurs when a user rejoins the channel after being disconnected due to network problems. /// + /// Occurs when a user rejoins the channel. /// When a user loses connection with the server because of network problems, the SDK automatically tries to reconnect and triggers this callback upon reconnection. /// - /// The `UidWithElapsedCallback` typedef includes the following parameters: - /// - [int] `uid`: This parameter has the following definitions in different events: - /// - [userJoined]: ID of the user or host who joins the channel. - /// - [firstRemoteAudioFrame]: User ID of the remote user. - /// - [firstRemoteAudioDecoded]: User ID of the remote user sending the audio stream. - /// - [joinChannelSuccess]: User ID. - /// - [rejoinChannelSuccess]: User ID. - /// - [int] `elapsed`: - /// - [userJoined]: Time delay (ms) from the local user calling [RtcEngine.joinChannel] or [RtcEngine.setClientRole] until this callback is triggered. - /// - [firstRemoteAudioFrame]: Time elapsed (ms) from the local user calling [RtcEngine.joinChannel] until this callback is triggered. - /// - [firstRemoteAudioDecoded]: Time elapsed (ms) from the local user calling [RtcEngine.joinChannel] until the SDK triggers this callback. - /// - [joinChannelSuccess]: Time elapsed (ms) from the local user calling [RtcChannel.joinChannel] until this callback is triggered. - /// - [rejoinChannelSuccess]: Time elapsed (ms) from the local user starting to reconnect until this callback is triggered. + /// Param [elapsed] Time elapsed (ms) from starting to reconnect until the SDK triggers this + /// callback. + /// + /// Param [uid] + /// UidWithElapsedAndChannelCallback? rejoinChannelSuccess; - /// Occurs when a user leaves the channel. /// - /// When a user leaves the channel by using the [RtcChannel.leaveChannel] method, the SDK uses this callback to notify the app when the user leaves the channel. + /// Occurs when a user leaves a channel. + /// When a user leaves the channel by using the leaveChannel method, the SDK uses this callback to notify the app when the user leaves the channel. With this callback, the app gets the channel information, such as the call duration and quality statistics. + /// + /// Param [stats] /// - /// With this callback, the app retrieves the channel information, such as the call duration and statistics. - /// The `RtcStatsCallback` typedef includes the following parameter: - /// - [RtcStats] `stats`: Statistics of the call. RtcStatsCallback? leaveChannel; - /// Occurs when the user role switches in a [ChannelProfile.LiveBroadcasting] channel. For example, from broadcaster to audience or vice versa. /// - /// The SDK triggers this callback when the local user switches the user role by calling the setClientRole method after joining the channel. - /// See [RtcChannel.setClientRole]. + /// Occurs when the user role switches in the interactive live streaming. + /// The SDK triggers this callback when the local user changes the user role after joining the channel. + /// + /// Param [newRole] Role that the user switches to: ClientRole. + /// + /// Param [oldRole] /// - /// The `ClientRoleCallback` typedef includes the following parameters: - /// - [ClientRole] `oldRole`: Role that the user switches from. - /// - [ClientRole] `newRole`: Role that the user switches to. ClientRoleCallback? clientRoleChanged; - /// Occurs when a remote user (Communication) or a broadcaster ([ChannelProfile.LiveBroadcasting]) joins the channel. - /// - [ChannelProfile.Communication] profile: This callback notifies the app when another user joins the channel. If other users are already in the channel, the SDK also reports to the app on the existing users. - /// - [ChannelProfile.LiveBroadcasting] profile: This callback notifies the app when the host joins the channel. If other hosts are already in the channel, the SDK also reports to the app on the existing hosts. We recommend having at most 17 hosts in a channel. - /// - /// **Note** - /// - In the [ChannelProfile.LiveBroadcasting] profile: - /// -- The host receives this callback when another host joins the channel. - /// -- The audience in the channel receives this callback when a new host joins the channel. - /// -- When a web app joins the channel, this callback is triggered as long as the web app publishes streams. - /// - /// The `UidWithElapsedCallback` typedef includes the following parameters: - /// - [int] `uid`: This parameter has the following definitions in different events: - /// - [userJoined]: ID of the user or host who joins the channel. - /// - [firstRemoteAudioFrame]: User ID of the remote user. - /// - [firstRemoteAudioDecoded]: User ID of the remote user sending the audio stream. - /// - [joinChannelSuccess]: User ID. - /// - [rejoinChannelSuccess]: User ID. - /// - [int] `elapsed`: - /// - [userJoined]: Time delay (ms) from the local user calling [RtcEngine.joinChannel] or [RtcEngine.setClientRole] until this callback is triggered. - /// - [firstRemoteAudioFrame]: Time elapsed (ms) from the local user calling [RtcEngine.joinChannel] until this callback is triggered. - /// - [firstRemoteAudioDecoded]: Time elapsed (ms) from the local user calling [RtcEngine.joinChannel] until the SDK triggers this callback. - /// - [joinChannelSuccess]: Time elapsed (ms) from the local user calling [RtcChannel.joinChannel] until this callback is triggered. - /// - [rejoinChannelSuccess]: Time elapsed (ms) from the local user starting to reconnect until this callback is triggered. + /// + /// Occurs when a remote user (COMMUNICATION)/ host (LIVE_BROADCASTING) joins the channel. + /// In a communication channel, this callback indicates that a remote user joins the channel. The SDK also triggers this callback to report the existing users in the channel when a user joins the channel. + /// In a live-broadcast channel, this callback indicates that a host joins the channel. The SDK also triggers this callback to report the existing hosts in the channel when a host joins the channel. Agora recommends limiting the number of hosts to 17. + /// + /// The SDK triggers this callback under one of the following circumstances: + /// A remote user/host joins the channel by calling the joinChannel method. + /// A remote user switches the user role to the host after joining the channel. + /// A remote user/host rejoins the channel after a network interruption. + /// The host injects an online media stream into the channel by calling the addInjectStreamUrl method. + /// + /// Param [uid] + /// + /// Param [elapsed] Time delay (ms) fromthe local user calling joinChannel until this callback is triggered. + /// UidWithElapsedCallback? userJoined; - /// Occurs when a remote user ([ChannelProfile.Communication]) or a broadcaster ([ChannelProfile.LiveBroadcasting]) leaves the channel. /// + /// Occurs when a remote user (COMMUNICATION)/ host (LIVE_BROADCASTING) leaves the channel. /// There are two reasons for users to become offline: - /// - Leave the channel: When the user/broadcaster leaves the channel, the user/broadcaster sends a goodbye message. When this message is received, the SDK determines that the user/host leaves the channel. - /// - Go offline: When no data packet of the user or broadcaster is received for a certain period of time (around 20 seconds), the SDK assumes that the user/broadcaster drops offline. A poor network connection may lead to false detections, so we recommend using the Agora RTM SDK for reliable offline detection. + /// Leave the channel: When a user/host leaves the channel, the user/host sends a goodbye message. When this message is received, the SDK determines that the user/host leaves the channel. + /// Drop offline: When no data packet of the user or host is received for a certain period of time (20 seconds for the communication profile, and more for the live broadcast profile), the SDK assumes that the user/host drops offline. A poor network connection may lead to false detections. It's recommended to use the Agora RTM SDK for reliable offline detection. + /// + /// Param [reason] Reasons why the user goes offline: UserOfflineReason. + /// + /// Param [uid] /// - /// The `UserOfflineCallback` typedef includes the following parameters: - /// - [int] `uid`: ID of the user or host who leaves the channel or goes offline. - /// - [UserOfflineReason] `reason`: Reason why the user goes offline. UserOfflineCallback? userOffline; + /// /// Occurs when the network connection state changes. + /// When the network connection state changes, the SDK triggers this callback and reports the current connection state and the reason for the change. + /// + /// Param [reason] The reason for a connection state change. /// - /// The Agora SDK triggers this callback to report on the current network connection state when it changes, and the reason to such change. /// - /// The `ConnectionStateCallback` typedef includes the following parameters: - /// - [ConnectionStateType] `state`: The current network connection state. - /// - [ConnectionChangedReason] `reason`: The reason causing the change of the connection state. + /// + /// Param [state] + /// ConnectionStateCallback? connectionStateChanged; + /// /// Occurs when the SDK cannot reconnect to Agora's edge server 10 seconds after its connection to the server is interrupted. + /// The SDK triggers this callback when it cannot connect to the server 10 seconds after calling the joinChannel method, regardless of whether it is in the channel. /// - /// The SDK also triggers this callback when it cannot connect to the server 10 seconds after calling [RtcChannel.joinChannel], regardless of whether it is in the channel or not. - /// If the SDK fails to rejoin the channel 20 minutes after being disconnected from Agora's edge server, the SDK stops rejoining the channel. - /// The `EmptyCallback` typedef does not include any parameter. EmptyCallback? connectionLost; + /// /// Occurs when the token expires in 30 seconds. + /// When the token is about to expire in 30 seconds, the SDK triggers this callback to remind the app to renew the token. Upon receiving this callback, generate a new token on your server, and call renewToken to pass the new token to the SDK. /// - /// The user becomes offline if the token used when joining the channel expires. This callback is triggered 30 seconds before the token expires, to remind the app to get a new token. Upon receiving this callback, you need to generate a new token on the server and call [RtcChannel.renewToken] to pass the new token to the SDK. + /// Param [token] /// - /// The `TokenCallback` typedef includes the following parameters: - /// - [String] `token`: The token that will expire in 30 seconds. TokenCallback? tokenPrivilegeWillExpire; - /// Occurs when the token has expired. /// - /// After a token is specified when joining the channel, the token expires after a certain period of time, and a new token is required to reconnect to the server. This callback notifies the app to generate a new token and call [RtcChannel.renewToken] to renew the token. - /// The `EmptyCallback` typedef does not include any parameter. + /// Occurs when the token expires. + /// When the token expires during a call, the SDK triggers this callback to remind the app to renew the token. + /// Once you receive this callback, generate a new token on your app server, and call joinChannel to rejoin the channel. + /// EmptyCallback? requestToken; - /// Reports which user is the loudest speaker. /// - /// This callback reports the speaker with the highest accumulative volume during a certain period. If the user enables the audio volume indication by calling [RtcEngine.enableAudioVolumeIndication], this callback returns the uid of the active speaker whose voice is detected by the audio volume detection module of the SDK. + /// Occurs when the most active speaker is detected. + /// After a successful call of enableAudioVolumeIndication, the SDK continuously detects which remote user has the loudest volume. During the current period, the remote user, who is detected as the loudest for the most times, is the most active user. + /// When the number of users exceeds two (included) and an active speaker is detected, the SDK triggers this callback and reports the uid of the most active speaker. + /// If the most active speaker remains the same, the SDK triggers the activeSpeaker callback only once. + /// If the most active speaker changes to another user, the SDK triggers this callback again and reports the uid of the new active speaker. /// - /// **Note** - /// - To receive this callback, you need to call [RtcEngine.enableAudioVolumeIndication]. - /// - This callback reports the ID of the user with the highest voice volume during a period of time, instead of at the moment. + /// Param [uid] /// - /// The `UidCallback` typedef includes the following parameters: - /// - [int] `uid`: User ID of the active speaker. A `uid` of 0 represents the local user. UidCallback? activeSpeaker; - /// Occurs when the video size or rotation information of a remote user changes. /// - /// The `VideoSizeCallback` typedef includes the following parameters: - /// - [int] `uid`: User ID of the remote user or local user (0) whose video size or rotation changes. - /// - [int] `width`: New width (pixels) of the video. - /// - [int] `height`: New height (pixels) of the video. - /// - [int] `rotation`: New rotation of the video [0 to 360). + /// Occurs when the video size or rotation of a specified user changes. + /// + /// + /// Param [rotation] The rotation information. The value range is [0,360). + /// + /// Param [height] The height (pixels) of the video stream. + /// + /// Param [width] The width (pixels) of the video stream. + /// + /// Param [uid] + /// VideoSizeCallback? videoSizeChanged; + /// /// Occurs when the remote video state changes. + /// This callback does not work properly when the number of users (in the voice/video call channel) or hosts (in the live streaming channel) in the channel exceeds 17. + /// + /// Param [reason] The reason for the remote video state + /// change, see VideoRemoteStateReason. + /// + /// Param [state] The state of the remote video, see + /// VideoRemoteState. + /// + /// Param [uid] + /// + /// Param [elapsed] Time elapsed (ms) from the local user calling the joinChannel method until the SDK triggers this callback. /// - /// The `RemoteVideoStateCallback` typedef includes the following parameters: - /// - [int] `uid`: ID of the remote user whose video state changes. - /// - [VideoRemoteState] `state`: State of the remote video. - /// - [VideoRemoteStateReason] `reason`: The reason of the remote video state change. - /// - [int] `elapsed`: Time elapsed (ms) from the local user calling [RtcEngine.joinChannel] until the SDK triggers this callback. RemoteVideoStateCallback? remoteVideoStateChanged; + /// /// Occurs when the remote audio state changes. + /// When the audio state of a remote user (in the voice/video call channel) or host (in the live streaming channel) changes, the SDK triggers this callback to report the current state of the remote audio stream. + /// This callback does not work properly when the number of users (in the voice/video call channel) or hosts (in the live streaming channel) in the channel exceeds 17. + /// + /// Param [reason] The reason of the remote audio state change, see AudioRemoteStateReason. + /// + /// Param [state] The state of the remote audio, see AudioRemoteState. /// - /// This callback indicates the state change of the remote audio stream. + /// Param [uid] /// - /// This callback does not work properly when the number of users (in the `Communication` profile) or hosts (in the `LiveBroadcasting` profile) in the channel exceeds 17. + /// Param [elapsed] Time elapsed (ms) from the local user calling the joinChannel method until the SDK triggers this callback. /// - /// The `RemoteAudioStateCallback` typedef includes the following parameters: - /// - [int] `uid`: ID of the user whose audio state changes. - /// - [AudioRemoteState] `state`: State of the remote audio. - /// - [AudioRemoteStateReason] `reason`: The reason of the remote audio state change. - /// - [int] `elapsed`: Time elapsed (ms) from the local user calling [RtcEngine.joinChannel] until the SDK triggers this callback. RemoteAudioStateCallback? remoteAudioStateChanged; - /// Occurs when the published media stream falls back to an audio-only stream due to poor network conditions or switches back to video stream after the network conditions improve. /// - /// If you call [RtcEngine.setLocalPublishFallbackOption] and set option as [StreamFallbackOptions.AudioOnly], this callback is triggered when the locally published stream falls back to audio-only mode due to poor uplink conditions, or when the audio stream switches back to the video after the uplink network condition improves. + /// Occurs when the published media stream falls back to an audio-only stream. + /// If you call setLocalPublishFallbackOption and set option as AudioOnly, the SDK triggers this callback when the remote media stream falls back to audio-only mode due to poor uplink conditions, or when the remote media stream switches back to the video after the uplink network condition improves. + /// If the local stream falls back to the audio-only stream, the remote user receives the userMuteVideo callback. + /// + /// Param [isFallbackOrRecover] /// - /// The `FallbackCallback` typedef includes the following parameters: - /// - [bool] `isFallbackOrRecover`: Whether the published stream fell back to audio-only or switched back to the video: - /// -- `true`: The published stream fell back to audio-only due to poor network conditions. - /// -- `false`: The published stream switched back to the video after the network conditions improved. FallbackCallback? localPublishFallbackToAudioOnly; - /// Occurs when the remote media stream falls back to audio-only stream due to poor network conditions or switches back to video stream after the network conditions improve. /// - /// If you call [RtcEngine.setRemoteSubscribeFallbackOption] and set option as [StreamFallbackOptions.AudioOnly], this callback is triggered when the remote media stream falls back to audio-only mode due to poor uplink conditions, or when the remote media stream switches back to the video after the uplink network condition improves. + /// Occurs when the remote media stream falls back to audio-only stream due to poor network conditions or switches back to the video stream after the network conditions improve. + /// If you call setRemoteSubscribeFallbackOption and set option as AudioOnly, the SDK triggers this callback when the remote media stream falls back to audio-only mode due to poor downlink conditions, or when the remote media stream switches back to the video after the downlink network condition improves. + /// Once the remote media stream switches to the low stream due to poor network conditions, you can monitor the stream switch between a high and low stream in the RemoteVideoStats callback. + /// + /// Param [isFallbackOrRecover] + /// true: The remotely subscribed media stream falls back to audio-only due to poor network conditions. + /// false: The remotely subscribed media stream switches back to the video stream after the network conditions improved. + /// + /// /// - /// **Note** - /// - Once the remote media stream is switched to the low stream due to poor network conditions, you can monitor the stream switch between a high and low stream in the [RtcEngineEventHandler.remoteVideoStats] callback. + /// Param [uid] /// - /// The `FallbackWithUidCallback` typedef includes the following parameters: - /// - [int]: `uid`: ID of the remote user sending the stream. - /// - [bool] `isFallbackOrRecover`: Whether the published stream fell back to audio-only or switched back to the video: - /// -- `true`: The published stream fell back to audio-only due to poor network conditions. - /// -- `false`: The published stream switched back to the video after the network conditions improved. FallbackWithUidCallback? remoteSubscribeFallbackToAudioOnly; - /// Reports the statistics of the [RtcEngine] once every two seconds. - /// The `RtcStatsCallback` typedef includes the following parameter: - /// - [RtcStats] `stats`: Statistics of the call. + /// + /// Reports the statistics of the current call. + /// The SDK triggers this callback once every two seconds after the user joins the channel. + /// + /// Param [stats] + /// RtcStatsCallback? rtcStats; - /// Reports the last mile network quality of each user in the channel once every two seconds. /// - /// Last mile refers to the connection between the local device and Agora's edge server. This callback reports once every two seconds the last mile network conditions of each user in the channel. If a channel includes multiple users, then this callback will be triggered as many times. + /// Reports the last mile network quality of each user in the channel. + /// This callback reports the last mile network conditions of each user in the channel. Last mile refers to the connection between the local device and Agora's edge server. + /// The SDK triggers this callback once every two seconds. If a channel includes multiple users, the SDK triggers this callback as many times. + /// + /// Param [rxQuality] Downlink network quality rating of the user in terms of packet loss rate, + /// average RTT, and jitter of the downlink network. + /// + /// Param [txQuality] Uplink network quality rating of the user in terms of the transmission bit + /// rate, packet loss rate, average RTT (Round-Trip Time) and jitter of the + /// uplink network. This parameter is a quality rating helping you understand + /// how well the current uplink network conditions can support the selected + /// video encoder configuration. For example, a 1000 Kbps uplink network may be + /// adequate for video frames with a resolution of 640 × 480 and a frame rate of + /// 15 fps in the LIVE_BROADCASTING profile, but might be inadequate for + /// resolutions higher than 1280 × 720. + /// + /// Param [uid] /// - /// The `NetworkQualityWithUidCallback` typedef includes the following parameters: - /// - [int] `uid`:User ID. The network quality of the user with this uid is reported. If `uid` is 0, the local network quality is reported. - /// - [NetworkQuality] `txQuality`: Uplink transmission quality of the user in terms of the transmission bitrate, packet loss rate, average RTT (Round-Trip Time)and jitter of the uplink network. `txQuality` is a quality rating helping you understand how well the current uplink network conditions can support the selected [VideoEncoderConfiguration]. For example, a 1000 Kbps uplink network may be adequate for video frames with a resolution of 680 × 480 and a frame rate of 30 fps, but may be inadequate for resolutions higher than 1280 × 720. - /// - [NetworkQuality] `rxQuality`: Downlink network quality rating of the user in terms of packet loss rate, average RTT, and jitter of the downlink network. NetworkQualityWithUidCallback? networkQuality; - /// Reports the statistics of the video stream from each remote user/broadcaster. The SDK triggers this callback once every two seconds for each remote user/broadcaster. If a channel includes multiple remote users, the SDK triggers this callback as many times. /// - /// The `RemoteVideoStatsCallback` typedef includes the following parameter: - /// - [RemoteVideoStats] `stats`: Statistics of the received remote video streams. + /// Reports the transport-layer statistics of each remote video stream. + /// Reports the statistics of the video stream from the remote users. The SDK triggers this callback once every two seconds for each remote user. If a channel has multiple users/hosts sending video streams, the SDK triggers this callback as many times. + /// + /// Param [stats] + /// RemoteVideoStatsCallback? remoteVideoStats; - /// Reports the statistics of the audio stream from each remote user/broadcaster. /// - /// The SDK triggers this callback once every two seconds for each remote user/broadcaster. If a channel includes multiple remote users, the SDK triggers this callback as many times. + /// Reports the transport-layer statistics of each remote audio stream. + /// The SDK triggers this callback once every two seconds for each remote user who is sending audio streams. If a channel includes multiple remote users, the SDK triggers this callback as many times. /// - /// Schemes such as FEC (Forward Error Correction) or retransmission counter the frame loss rate. Hence, users may find the overall audio quality acceptable even when the packet loss rate is high. + /// Param [stats] /// - /// The `RemoteAudioStatsCallback` typedef includes the following parameter: - /// - [RemoteAudioStats] `stats`: Statistics of the received remote audio streams. RemoteAudioStatsCallback? remoteAudioStats; + /// /// Occurs when the state of the RTMP or RTMPS streaming changes. + /// The SDK triggers this callback to report the result of the local user calling the addPublishStreamUrl or removePublishStreamUrl method. When the RTMP/RTMPS streaming status changes, the SDK triggers this callback and report the URL address and the current status of the streaming. This callback indicates the state of the RTMP or RTMPS streaming. When exceptions occur, you can troubleshoot issues by referring to the detailed error descriptions in the error code parameter. /// - /// The SDK triggers this callback to report the result of the local user calling the [RtcChannel.addPublishStreamUrl] or [RtcChannel.removePublishStreamUrl] method. This callback returns the URL and its current streaming state. When the streaming state is [RtmpStreamingState.Failure], see the `errCode` parameter for details. + /// Param [errCode] The detailed error information for streaming, see RtmpStreamingErrorCode. /// - /// This callback indicates the state of the RTMP or RTMPS streaming. When exceptions occur, you can troubleshoot issues by referring to the detailed error descriptions in the `errCode` parameter. + /// Param [state] The RTMP or RTMPS streaming state, see RtmpStreamingState. When the streaming status is Failure(4), you can view the error information in the errorCode parameter. + /// + /// Param [url] /// - /// The `RtmpStreamingStateCallback` typedef includes the following parameters: - /// - [String] `url`: The CDN streaming URL. - /// - [RtmpStreamingState] `state`: The RTMP or RTMPS streaming state. - /// - [RtmpStreamingErrorCode] `errCode`: The detailed error information for streaming. RtmpStreamingStateCallback? rtmpStreamingStateChanged; - /// Occurs when the publisher's transcoding settings are updated. /// - /// When the [LiveTranscoding] class in the [RtcChannel.setLiveTranscoding] method updates, the SDK triggers this callback to report the update information. + /// Occurs when the publisher's transcoding is updated. + /// If you call the setLiveTranscoding + /// method to set the LiveTranscoding class for the first time, the + /// SDK does not trigger this callback. + /// When the LiveTranscoding class in the setLiveTranscoding method updates, the SDK triggers the transcodingUpdated callback to report the update information. /// - /// **Note** - /// - If you call the [RtcChannel.setLiveTranscoding] method to set the [LiveTranscoding] class for the first time, the SDK does not trigger this callback. - /// The `EmptyCallback` typedef does not include any parameter. EmptyCallback? transcodingUpdated; - /// Reports the status of injecting the online media stream. /// - /// The `StreamInjectedStatusCallback` typedef includes the following parameters: - /// - [String] `url`: The URL address of the externally injected stream. - /// - [int] `uid`: User ID. - /// - [InjectStreamStatus] `status`: State of the externally injected stream. + /// Occurs when a media stream URL address is added to the interactive live streaming. + /// + /// + /// Param [status] State of the externally injected stream: InjectStreamStatus. + /// + /// Param [uid] User ID. + /// + /// Param [url] + /// StreamInjectedStatusCallback? streamInjectedStatus; - /// Occurs when the local user receives a remote data stream. /// - /// The SDK triggers this callback when the local user receives the stream message that the remote user sends by calling the [RtcChannel.sendStreamMessage] method. + /// Occurs when the local user receives the data stream from the remote user. + /// The SDK triggers this callback when the local user receives the stream message that the remote user sends by calling the sendStreamMessage method. + /// + /// Param [data] The data received. + /// + /// Param [streamId] The stream ID of the received message. + /// + /// Param [uid] /// - /// The `StreamMessageCallback` typedef includes the following parameters: - /// - [int] `uid`: User ID of the remote user sending the data stream. - /// - [int] `streamId`: Stream ID. - /// - [String] `data`: Data received by the local user. StreamMessageCallback? streamMessage; - /// Occurs when the local user fails to receive a remote data stream. /// - /// The SDK triggers this callback when the local user fails to receive the stream message that the remote user sends by calling the [RtcChannel.sendStreamMessage] method. + /// Occurs when the local user does not receive the data stream from the remote user. + /// The SDK triggers this callback when the local user fails to receive the stream message that the remote user sends by calling the sendStreamMessage method. + /// + /// Param [cached] Number of incoming cached messages when the data stream is interrupted. + /// + /// Param [missed] The number of lost messages. + /// + /// Param [error] The error code. + /// + /// Param [streamId] The stream ID of the received message. + /// + /// Param [uid] /// - /// The `StreamMessageErrorCallback` callback includes the following parameters: - /// - [int] `uid`: User ID of the remote user sending the data stream. - /// - [int] `streamId`: Stream ID. - /// - [ErrorCode] `error`: Error code. - /// - [int] `missed`: The number of lost messages. - /// - [int] `cached`: The number of incoming cached messages when the data stream is interrupted. StreamMessageErrorCallback? streamMessageError; + /// /// Occurs when the state of the media stream relay changes. + /// The SDK returns the state of the current media relay with any error message. + /// + /// Param [code] The error code of the channel media + /// replay. For details, see ChannelMediaRelayError. /// - /// The SDK reports the state of the current media relay and possible error messages in this callback. + /// Param [state] /// - /// The `MediaRelayStateCallback` typedef includes the following parameters: - /// - [ChannelMediaRelayState] `state`: The state code. - /// - [ChannelMediaRelayError] `code`: The error code. MediaRelayStateCallback? channelMediaRelayStateChanged; + /// /// Reports events during the media stream relay. /// - /// The `MediaRelayEventCallback` typedef includes the following parameter: - /// - [ChannelMediaRelayEvent] `code`: The event code for media stream relay. + /// + /// Param [code] + /// MediaRelayEventCallback? channelMediaRelayEvent; - /// Occurs when the local user receives the metadata, including the following parameters: - /// - `buffer`: The sent or received metadata. - /// - `uid`: ID of the user who sends the metadata. - /// - `timeStampMs`: The timestamp of the metadata. /// - /// The `MetadataCallback` typedef includes the following parameters: - /// - [String]: `buffer`: The received metadata. - /// - [int]: `uid`: The ID of the user who sent the metadata. - /// - [int]: `timeStampMs`: The timestamp (ms) of the received metadata. + /// Occurs when the local user receives Metadata. + /// + /// + /// Param [buffer] The recevied metadata. + /// + /// Param [uid] The ID of the user who sent the metadata. + /// + /// Param [timeStampMs] The timestamp (ms) of the received metadata. + /// MetadataCallback? metadataReceived; + /// /// Occurs when the audio publishing state changes. /// - /// This callback indicates the publishing state change of the local audio stream. /// - /// The `StreamPublishStateCallback` typedef includes the following parameters: - /// - [String] `channel`: The channel name. - /// - [StreamPublishState] `oldState`: The previous publishing state. See [StreamPublishState]. - /// - [StreamPublishState] `newState`: The current publishing state. See [StreamPublishState]. - /// - [int] `elapseSinceLastState`: The time elapsed (ms) from the previous state to the current state. + /// Param [elapseSinceLastState] The time elapsed (ms) from the previous state to the current state. + /// + /// Param [newState] For the current publishing state, see StreamPublishState. + /// + /// Param [oldState] + /// + /// Param [channel] The channel name. + /// StreamPublishStateCallback? audioPublishStateChanged; + /// /// Occurs when the video publishing state changes. /// - /// This callback indicates the publishing state change of the local video stream. /// - /// The `StreamPublishStateCallback` typedef includes the following parameters: - /// - [String] `channel`: The channel name. - /// - [StreamPublishState] `oldState`: The previous publishing state. See [StreamPublishState]. - /// - [StreamPublishState] `newState`: The current publishing state. See [StreamPublishState]. - /// - [int] `elapseSinceLastState`: The time elapsed (ms) from the previous state to the current state. + /// Param [null] + /// + /// Param [channel] The channel name. + /// StreamPublishStateCallback? videoPublishStateChanged; + /// /// Occurs when the audio subscribing state changes. /// - /// This callback indicates the subscribing state change of a remote audio stream. /// - /// The `StreamSubscribeStateCallback` typedef includes the following parameters: - /// - [String] `channel`: The channel name. - /// - [StreamSubscribeState] `oldState`: The previous publishing state. See [StreamPublishState]. - /// - [StreamSubscribeState] `newState`: The current publishing state. See [StreamPublishState]. - /// - [int] `elapseSinceLastState`: The time elapsed (ms) from the previous state to the current state. + /// Param [elapseSinceLastState] The time elapsed (ms) from the previous state to the current state. + /// + /// Param [newState] The current subscribing status, see StreamSubscribeState for details. + /// + /// Param [oldState] + /// + /// Param [channel] The channel name. + /// StreamSubscribeStateCallback? audioSubscribeStateChanged; + /// /// Occurs when the video subscribing state changes. /// - /// This callback indicates the subscribing state change of a remote video stream. /// - /// The `StreamSubscribeStateCallback` typedef includes the following parameters: - /// - [String] `channel`: The channel name. - /// - [StreamSubscribeState] `oldState`: The previous publishing state. See [StreamPublishState]. - /// - [StreamSubscribeState] `newState`: The current publishing state. See [StreamPublishState]. - /// - [int] `elapseSinceLastState`: The time elapsed (ms) from the previous state to the current state. + /// Param [null] + /// + /// Param [channel] The channel name. + /// StreamSubscribeStateCallback? videoSubscribeStateChanged; + /// /// Reports events during the RTMP or RTMPS streaming. /// - /// The `RtmpStreamingEventCallback` typedef includes the following parameters: - /// - [String] `url`: The RTMP or RTMPS streaming URL. - /// - [RtmpStreamingEvent] `eventCode`: The event code. See [RtmpStreamingEvent]. + /// + /// Param [eventCode] The event code of the streaming. For details, see RtmpStreamingEvent. + /// + /// Param [url] + /// RtmpStreamingEventCallback? rtmpStreamingEvent; - /// Reports whether the super resolution feature is successfully enabled. (beta feature) /// - /// After calling [RtcEngine.enableRemoteSuperResolution], the SDK triggers this callback to report whether super resolution is successfully enabled. If it is not successfully enabled, use reason for troubleshooting. + /// Reports whether the super resolution feature is successfully enabled. + /// After calling enableRemoteSuperResolution, the SDK triggers the callback to report whether super resolution is successfully enabled. If it is not successfully enabled, use reason for troubleshooting. + /// + /// Param [reason] The reason why super resolution algorithm is not successfully enabled. For details, see SuperResolutionStateReason. + /// + /// Param [enabled] Whether super resolution is successfully enabled: + /// true: Super resolution is successfully enabled. + /// false: Super resolution is not successfully enabled. /// - /// **Parameters** /// - /// [uid] The user ID of the remote user. + /// Param [uid] + /// UserSuperResolutionEnabledCallback? userSuperResolutionEnabled; /// Constructs a [RtcChannelEventHandler] @@ -1930,163 +2419,200 @@ class RtcChannelEventHandler { }); // ignore: public_member_api_docs - void process(String methodName, List data) { + void process(String channelId, String methodName, dynamic data, + [Uint8List? buffer]) { + List newData; + // if (kIsWeb || (Platform.isWindows || Platform.isMacOS)) { + + // } else { + // newData = List.from(data); + // } + if (methodName.startsWith('on')) { + methodName = methodName.substring(2); + } + newData = List.from( + Map.from(jsonDecode(data as String)).values); switch (methodName) { - case 'Warning': - warning?.call(WarningCodeConverter.fromValue(data[0]).e); + case 'ChannelWarning': + warning?.call(WarningCodeConverter.fromValue(newData[0]).e); break; - case 'Error': - error?.call(ErrorCodeConverter.fromValue(data[0]).e); + case 'ChannelError': + error?.call(ErrorCodeConverter.fromValue(newData[0]).e); break; case 'JoinChannelSuccess': - joinChannelSuccess?.call(data[0], data[1], data[2]); + joinChannelSuccess?.call(newData[0], newData[1], newData[2]); break; case 'RejoinChannelSuccess': - rejoinChannelSuccess?.call(data[0], data[1], data[2]); + rejoinChannelSuccess?.call(newData[0], newData[1], newData[2]); break; case 'LeaveChannel': leaveChannel - ?.call(RtcStats.fromJson(Map.from(data[0]))); + ?.call(RtcStats.fromJson(Map.from(newData[0]))); break; case 'ClientRoleChanged': - clientRoleChanged?.call(ClientRoleConverter.fromValue(data[0]).e, - ClientRoleConverter.fromValue(data[1]).e); + clientRoleChanged?.call(ClientRoleConverter.fromValue(newData[0]).e, + ClientRoleConverter.fromValue(newData[1]).e); break; case 'UserJoined': - userJoined?.call(data[0], data[1]); + userJoined?.call(newData[0], newData[1]); break; case 'UserOffline': userOffline?.call( - data[0], UserOfflineReasonConverter.fromValue(data[1]).e); + newData[0], UserOfflineReasonConverter.fromValue(newData[1]).e); break; case 'ConnectionStateChanged': connectionStateChanged?.call( - ConnectionStateTypeConverter.fromValue(data[0]).e, - ConnectionChangedReasonConverter.fromValue(data[1]).e); + ConnectionStateTypeConverter.fromValue(newData[0]).e, + ConnectionChangedReasonConverter.fromValue(newData[1]).e); break; case 'ConnectionLost': connectionLost?.call(); break; case 'TokenPrivilegeWillExpire': - tokenPrivilegeWillExpire?.call(data[0]); + tokenPrivilegeWillExpire?.call(newData[0]); break; case 'RequestToken': requestToken?.call(); break; case 'ActiveSpeaker': - activeSpeaker?.call(data[0]); + activeSpeaker?.call(newData[0]); break; case 'VideoSizeChanged': - videoSizeChanged?.call(data[0], data[1], data[2], data[3]); + videoSizeChanged?.call(newData[0], newData[1], newData[2], newData[3]); break; case 'RemoteVideoStateChanged': remoteVideoStateChanged?.call( - data[0], - VideoRemoteStateConverter.fromValue(data[1]).e, - VideoRemoteStateReasonConverter.fromValue(data[2]).e, - data[3]); + newData[0], + VideoRemoteStateConverter.fromValue(newData[1]).e, + VideoRemoteStateReasonConverter.fromValue(newData[2]).e, + newData[3]); break; case 'RemoteAudioStateChanged': remoteAudioStateChanged?.call( - data[0], - AudioRemoteStateConverter.fromValue(data[1]).e, - AudioRemoteStateReasonConverter.fromValue(data[2]).e, - data[3]); + newData[0], + AudioRemoteStateConverter.fromValue(newData[1]).e, + AudioRemoteStateReasonConverter.fromValue(newData[2]).e, + newData[3]); break; case 'LocalPublishFallbackToAudioOnly': - localPublishFallbackToAudioOnly?.call(data[0]); + localPublishFallbackToAudioOnly?.call(newData[0]); break; case 'RemoteSubscribeFallbackToAudioOnly': - remoteSubscribeFallbackToAudioOnly?.call(data[0], data[1]); + remoteSubscribeFallbackToAudioOnly?.call(newData[0], newData[1]); break; case 'RtcStats': - rtcStats?.call(RtcStats.fromJson(Map.from(data[0]))); + rtcStats + ?.call(RtcStats.fromJson(Map.from(newData[0]))); break; case 'NetworkQuality': networkQuality?.call( - data[0], - NetworkQualityConverter.fromValue(data[1]).e, - NetworkQualityConverter.fromValue(data[2]).e); + newData[0], + NetworkQualityConverter.fromValue(newData[1]).e, + NetworkQualityConverter.fromValue(newData[2]).e); break; case 'RemoteVideoStats': remoteVideoStats?.call( - RemoteVideoStats.fromJson(Map.from(data[0]))); + RemoteVideoStats.fromJson(Map.from(newData[0]))); break; case 'RemoteAudioStats': remoteAudioStats?.call( - RemoteAudioStats.fromJson(Map.from(data[0]))); + RemoteAudioStats.fromJson(Map.from(newData[0]))); break; case 'RtmpStreamingStateChanged': rtmpStreamingStateChanged?.call( - data[0], - RtmpStreamingStateConverter.fromValue(data[1]).e, - RtmpStreamingErrorCodeConverter.fromValue(data[2]).e, + newData[0], + RtmpStreamingStateConverter.fromValue(newData[1]).e, + RtmpStreamingErrorCodeConverter.fromValue(newData[2]).e, ); break; case 'TranscodingUpdated': transcodingUpdated?.call(); break; case 'StreamInjectedStatus': - streamInjectedStatus?.call( - data[0], data[1], InjectStreamStatusConverter.fromValue(data[2]).e); + streamInjectedStatus?.call(newData[0], newData[1], + InjectStreamStatusConverter.fromValue(newData[2]).e); break; case 'StreamMessage': - streamMessage?.call(data[0], data[1], data[2]); + // if (kIsWeb || (Platform.isWindows || Platform.isMacOS || Platform.isAndroid)) { + + // } else { + // String data = newData[2]; + // streamMessage?.call( + // newData[0], newData[1], Uint8List.fromList(data.codeUnits)); + // } + if (buffer == null) return; + streamMessage?.call(newData[0], newData[1], buffer); break; case 'StreamMessageError': - streamMessageError?.call(data[0], data[1], - ErrorCodeConverter.fromValue(data[2]).e, data[3], data[4]); + streamMessageError?.call(newData[0], newData[1], + ErrorCodeConverter.fromValue(newData[2]).e, newData[3], newData[4]); break; case 'ChannelMediaRelayStateChanged': channelMediaRelayStateChanged?.call( - ChannelMediaRelayStateConverter.fromValue(data[0]).e, - ChannelMediaRelayErrorConverter.fromValue(data[1]).e, + ChannelMediaRelayStateConverter.fromValue(newData[0]).e, + ChannelMediaRelayErrorConverter.fromValue(newData[1]).e, ); break; case 'ChannelMediaRelayEvent': channelMediaRelayEvent - ?.call(ChannelMediaRelayEventConverter.fromValue(data[0]).e); + ?.call(ChannelMediaRelayEventConverter.fromValue(newData[0]).e); break; case 'MetadataReceived': - metadataReceived?.call(data[0], data[1], data[2]); + Metadata metadata; + // if (kIsWeb || (Platform.isWindows || Platform.isMacOS || Platform.isAndroid)) { + + // } else { + // metadata = Metadata(newData[1], newData[2]); + // String buffer = newData[0]; + // metadata.buffer = Uint8List.fromList(buffer.codeUnits); + // } + if (buffer == null) return; + metadata = Metadata.fromJson(Map.from(newData[0])); + metadata.buffer = buffer; + metadataReceived?.call(metadata); break; case 'AudioPublishStateChanged': audioPublishStateChanged?.call( - data[0], - StreamPublishStateConverter.fromValue(data[1]).e, - StreamPublishStateConverter.fromValue(data[2]).e, - data[3]); + channelId, + StreamPublishStateConverter.fromValue(newData[0]).e, + StreamPublishStateConverter.fromValue(newData[1]).e, + newData[2]); break; case 'VideoPublishStateChanged': videoPublishStateChanged?.call( - data[0], - StreamPublishStateConverter.fromValue(data[1]).e, - StreamPublishStateConverter.fromValue(data[2]).e, - data[3]); + channelId, + StreamPublishStateConverter.fromValue(newData[0]).e, + StreamPublishStateConverter.fromValue(newData[1]).e, + newData[2]); break; case 'AudioSubscribeStateChanged': audioSubscribeStateChanged?.call( - data[0], - data[1], - StreamSubscribeStateConverter.fromValue(data[2]).e, - StreamSubscribeStateConverter.fromValue(data[3]).e, - data[4]); + channelId, + newData[0], + StreamSubscribeStateConverter.fromValue(newData[1]).e, + StreamSubscribeStateConverter.fromValue(newData[2]).e, + newData[3]); break; case 'VideoSubscribeStateChanged': videoSubscribeStateChanged?.call( - data[0], - data[1], - StreamSubscribeStateConverter.fromValue(data[2]).e, - StreamSubscribeStateConverter.fromValue(data[3]).e, - data[4]); + channelId, + newData[0], + StreamSubscribeStateConverter.fromValue(newData[1]).e, + StreamSubscribeStateConverter.fromValue(newData[2]).e, + newData[3]); break; case 'RtmpStreamingEvent': - rtmpStreamingEvent?.call(data[0], data[1]); + rtmpStreamingEvent?.call( + newData[0], + RtmpStreamingEventConverter.fromValue(newData[1]).e, + ); break; case 'UserSuperResolutionEnabled': - userSuperResolutionEnabled?.call(data[0], data[1], - SuperResolutionStateReasonConverter.fromValue(data[2]).e); + userSuperResolutionEnabled?.call(newData[0], newData[1], + SuperResolutionStateReasonConverter.fromValue(newData[2]).e); break; + default: + throw ArgumentError('Not Supported Event: $methodName'); } } } diff --git a/lib/src/rtc_channel.dart b/lib/src/rtc_channel.dart index 352b02057..1ed579ace 100644 --- a/lib/src/rtc_channel.dart +++ b/lib/src/rtc_channel.dart @@ -1,13 +1,21 @@ import 'dart:async'; +import 'dart:convert'; +import 'dart:io'; +import 'dart:typed_data'; +import 'package:flutter/foundation.dart'; import 'package:flutter/services.dart'; import 'classes.dart'; import 'enum_converter.dart'; import 'enums.dart'; import 'events.dart'; +import 'api_types.dart'; -/// The RtcChannel class. +/// +/// Provides methods that enable real-time communications in an RtcChannel channel. +/// Call create to create an RtcChannel object. +/// class RtcChannel with RtcChannelInterface { static const MethodChannel _methodChannel = MethodChannel('agora_rtc_channel'); @@ -35,31 +43,61 @@ class RtcChannel with RtcChannelInterface { ); } - /// Creates and gets an [RtcChannel] instance. /// - /// To join more than one channel, call this method multiple times to create as many [RtcChannel] instances as needed, and call the [RtcChannel.joinChannel] method of each created [RtcChannel] object. - /// After joining multiple channels, you can simultaneously subscribe to streams of all the channels, but publish a stream in only one channel at one time. + /// Creates and gets an RtcChannel object. + /// You can call this method multiple times to create multiple RtcChannel objects, + /// and then call the joinChannel methods of each RtcChannel to join multiple channels at the same time. + /// After joining multiple channels, you can simultaneously subscribe to the the audio and video streams of all the channels, but publish a stream in only one channel at one time. + /// + /// Param [channelId] + /// The channel name. This parameter signifies the channel in which users engage in real-time audio and video interaction. Under the premise of the same App ID, users who fill in the same channel ID enter the same channel for audio and video interaction. The string length must be less than 64 bytes. Supported characters: + /// The 26 lowercase English letters: a to z. + /// The 26 uppercase English letters: A to Z. + /// The 10 numeric characters: 0 to 9. + /// Space + /// "!", "#", "$", "%", "&", "(", ")", "+", "-", ":", ";", "<", "=", ".", ">", "?", "@", "[", "]", "^", "_", "{", "}", "|", "~", "," + /// + /// + /// + /// The parameter does not have a default value. You must set it. + /// Do not set this parameter as the empty string "". Otherwise, the SDK returns ERR_REFUSED(5). + /// + /// + /// + /// + /// **return** A pointer to the RtcChannel instance, if the method call succeeds. + /// If the call fails, returns NULL. /// - /// **Parameter** [channelId] The unique channel name for the AgoraRTC session in the string format. The string length must be less than 64 bytes. This parameter does not have a default value. You must set it. Do not set it as the empty string "". Otherwise, the SDK returns [ErrorCode.Refused]. Supported character scopes are: - /// - All lowercase English letters: a to z. - /// - All uppercase English letters: A to Z. - /// - All numeric characters: 0 to 9. - /// - The space character. - /// - Punctuation characters and other symbols, including: "!", "#", "$", "%", "&", "(", ")", "+", "-", ":", ";", "<", "=", ".", ">", "?", "@", "\[", "\]", "^", "_", " {", "}", "|", "~", ",". static Future create(String channelId) async { if (_channels.containsKey(channelId)) return _channels[channelId]!; - await _methodChannel.invokeMethod('create', { - 'channelId': channelId, + + await _methodChannel.invokeMethod('callApi', { + 'apiType': ApiTypeChannel.kChannelCreateChannel.index, + 'params': jsonEncode({ + 'channelId': channelId, + }), }); - _channels[channelId] = RtcChannel._(channelId); - return _channels[channelId]!; + // TODO(littlegnal): Fill test for _channels (maybe unit test) + final channel = RtcChannel._(channelId); + _channels[channelId] = channel; + return channel; } - /// Destroys all [RtcChannel] instance. + /// + /// Destroys all RtcChannel instance. + /// + /// + // TODO(littlegnal): Fill test static void destroyAll() { + // TODO(littlegnal): Check that if the release should call synchronously _channels.forEach((key, value) async { value._handler = null; - await value._invokeMethod('destroy'); + await value._invokeMethod('callApi', { + 'apiType': ApiTypeChannel.kChannelRelease.index, + 'params': jsonEncode({ + 'channelId': value.channelId, + }), + }); }); _channels.clear(); } @@ -68,69 +106,115 @@ class RtcChannel with RtcChannelInterface { Future destroy() { _handler = null; _channels.remove(channelId); - return _invokeMethod('destroy'); + return _invokeMethod('callApi', { + 'apiType': ApiTypeChannel.kChannelRelease.index, + 'params': jsonEncode({ + 'channelId': channelId, + }), + }); } - /// Sets the channel event handler. /// - /// After setting the channel event handler, you can listen for channel events and receive the statistics of the corresponding [RtcChannel] instance. + /// Sets the event handler for the RtcChannel object. + /// After setting the channel event handler, you can listen for channel events and receive the statistics of the corresponding RtcChannel object. + /// + /// Param [handler] The event handler for the RtcChannel object. For details, see RtcChannelEventHandler. + /// + /// **return** 0(ERR_OK): Success. + /// < 0: Failure. /// - /// **Parameter** [handler] The event handler. void setEventHandler(RtcChannelEventHandler handler) { _handler = handler; _subscription ??= _stream.listen((event) { final eventMap = Map.from(event); - final channelId = eventMap['channelId']; final methodName = eventMap['methodName'] as String; - final data = List.from(eventMap['data']); - _channels[channelId]?._handler?.process(methodName, data); + var data = eventMap['data']; + final buffer = eventMap['buffer']; + String channelId; + // if (kIsWeb || (Platform.isWindows || Platform.isMacOS)) { + + // } else { + // channelId = eventMap['channelId']; + // } + final map = Map.from(jsonDecode(data)); + channelId = map.remove('channelId'); + data = jsonEncode(map); + _channels[channelId] + ?._handler + ?.process(channelId, methodName, data, buffer); }); } @override Future setClientRole(ClientRole role, [ClientRoleOptions? options]) { - return _invokeMethod('setClientRole', { - 'role': ClientRoleConverter(role).value(), - 'options': options?.toJson(), + return _invokeMethod('callApi', { + 'apiType': ApiTypeChannel.kChannelSetClientRole.index, + 'params': jsonEncode({ + 'channelId': channelId, + 'role': ClientRoleConverter(role).value(), + 'options': options?.toJson(), + }), }); } @override Future joinChannel(String? token, String? optionalInfo, int optionalUid, ChannelMediaOptions options) { - return _invokeMethod('joinChannel', { - 'token': token, - 'optionalInfo': optionalInfo, - 'optionalUid': optionalUid, - 'options': options.toJson(), + return _invokeMethod('callApi', { + 'apiType': ApiTypeChannel.kChannelJoinChannel.index, + 'params': jsonEncode({ + 'channelId': channelId, + 'token': token, + 'info': optionalInfo, + 'uid': optionalUid, + 'options': options.toJson(), + }), }); } @override Future joinChannelWithUserAccount( String? token, String userAccount, ChannelMediaOptions options) { - return _invokeMethod('joinChannelWithUserAccount', { - 'token': token, - 'userAccount': userAccount, - 'options': options.toJson(), + return _invokeMethod('callApi', { + 'apiType': ApiTypeChannel.kChannelJoinChannelWithUserAccount.index, + 'params': jsonEncode({ + 'channelId': channelId, + 'token': token, + 'userAccount': userAccount, + 'options': options.toJson(), + }), }); } @override Future leaveChannel() { - return _invokeMethod('leaveChannel'); + return _invokeMethod('callApi', { + 'apiType': ApiTypeChannel.kChannelLeaveChannel.index, + 'params': jsonEncode({ + 'channelId': channelId, + }), + }); } @override Future renewToken(String token) { - return _invokeMethod('renewToken', { - 'token': token, + return _invokeMethod('callApi', { + 'apiType': ApiTypeChannel.kChannelRenewToken.index, + 'params': jsonEncode({ + 'channelId': channelId, + 'token': token, + }), }); } @override Future getConnectionState() { - return _invokeMethod('getConnectionState').then((value) { + return _invokeMethod('callApi', { + 'apiType': ApiTypeChannel.kChannelGetConnectionState.index, + 'params': jsonEncode({ + 'channelId': channelId, + }), + }).then((value) { return ConnectionStateTypeConverter.fromValue(value).e; }); } @@ -138,266 +222,440 @@ class RtcChannel with RtcChannelInterface { @override @deprecated Future publish() { - return _invokeMethod('publish'); + return _invokeMethod('callApi', { + 'apiType': ApiTypeChannel.kChannelPublish.index, + 'params': jsonEncode({ + 'channelId': channelId, + }), + }); } @override @deprecated Future unpublish() { - return _invokeMethod('unpublish'); + return _invokeMethod('callApi', { + 'apiType': ApiTypeChannel.kChannelUnPublish.index, + 'params': jsonEncode({ + 'channelId': channelId, + }), + }); } @override Future getCallId() { - return _invokeMethod('getCallId'); + return _invokeMethod('callApi', { + 'apiType': ApiTypeChannel.kChannelGetCallId.index, + 'params': jsonEncode({ + 'channelId': channelId, + }), + }); } @override Future adjustUserPlaybackSignalVolume(int uid, int volume) { - return _invokeMethod('adjustUserPlaybackSignalVolume', { - 'uid': uid, - 'volume': volume, + return _invokeMethod('callApi', { + 'apiType': ApiTypeChannel.kChannelAdjustUserPlaybackSignalVolume.index, + 'params': jsonEncode({ + 'channelId': channelId, + 'uid': uid, + 'volume': volume, + }), }); } @override Future muteAllRemoteAudioStreams(bool muted) { - return _invokeMethod('muteAllRemoteAudioStreams', { - 'muted': muted, + return _invokeMethod('callApi', { + 'apiType': ApiTypeChannel.kChannelMuteAllRemoteAudioStreams.index, + 'params': jsonEncode({ + 'channelId': channelId, + 'mute': muted, + }), }); } @override - Future muteRemoteAudioStream(int uid, bool muted) { - return _invokeMethod('muteRemoteAudioStream', { - 'uid': uid, - 'muted': muted, + Future muteRemoteAudioStream(int userId, bool muted) { + return _invokeMethod('callApi', { + 'apiType': ApiTypeChannel.kChannelMuteRemoteAudioStream.index, + 'params': jsonEncode({ + 'channelId': channelId, + 'userId': userId, + 'mute': muted, + }), }); } @override @deprecated Future setDefaultMuteAllRemoteAudioStreams(bool muted) { - return _invokeMethod('setDefaultMuteAllRemoteAudioStreams', { - 'muted': muted, + return _invokeMethod('callApi', { + 'apiType': + ApiTypeChannel.kChannelSetDefaultMuteAllRemoteAudioStreams.index, + 'params': jsonEncode({ + 'channelId': channelId, + 'mute': muted, + }), }); } @override Future muteAllRemoteVideoStreams(bool muted) { - return _invokeMethod('muteAllRemoteVideoStreams', { - 'muted': muted, + return _invokeMethod('callApi', { + 'apiType': ApiTypeChannel.kChannelMuteAllRemoteVideoStreams.index, + 'params': jsonEncode({ + 'channelId': channelId, + 'mute': muted, + }), }); } @override - Future muteRemoteVideoStream(int uid, bool muted) { - return _invokeMethod('muteRemoteVideoStream', { - 'uid': uid, - 'muted': muted, + Future muteRemoteVideoStream(int userId, bool muted) { + return _invokeMethod('callApi', { + 'apiType': ApiTypeChannel.kChannelMuteRemoteVideoStream.index, + 'params': jsonEncode({ + 'channelId': channelId, + 'userId': userId, + 'mute': muted, + }), }); } @override @deprecated Future setDefaultMuteAllRemoteVideoStreams(bool muted) { - return _invokeMethod('setDefaultMuteAllRemoteVideoStreams', { - 'muted': muted, + return _invokeMethod('callApi', { + 'apiType': + ApiTypeChannel.kChannelSetDefaultMuteAllRemoteVideoStreams.index, + 'params': jsonEncode({ + 'channelId': channelId, + 'mute': muted, + }), }); } @override Future addInjectStreamUrl(String url, LiveInjectStreamConfig config) { - return _invokeMethod('addInjectStreamUrl', { - 'url': url, - 'config': config.toJson(), + return _invokeMethod('callApi', { + 'apiType': ApiTypeChannel.kChannelAddInjectStreamUrl.index, + 'params': jsonEncode({ + 'channelId': channelId, + 'url': url, + 'config': config.toJson(), + }), }); } @override Future addPublishStreamUrl(String url, bool transcodingEnabled) { - return _invokeMethod('addPublishStreamUrl', { - 'url': url, - 'transcodingEnabled': transcodingEnabled, + return _invokeMethod('callApi', { + 'apiType': ApiTypeChannel.kChannelAddPublishStreamUrl.index, + 'params': jsonEncode({ + 'channelId': channelId, + 'url': url, + 'transcodingEnabled': transcodingEnabled, + }), }); } @override @deprecated Future createDataStream(bool reliable, bool ordered) { - return _invokeMethod('createDataStream', { - 'reliable': reliable, - 'ordered': ordered, + return _invokeMethod('callApi', { + 'apiType': ApiTypeChannel.kChannelCreateDataStream.index, + 'params': jsonEncode({ + 'channelId': channelId, + 'reliable': reliable, + 'ordered': ordered, + }), }); } @override Future registerMediaMetadataObserver() { - return _invokeMethod('registerMediaMetadataObserver'); + return _invokeMethod('callApi', { + 'apiType': ApiTypeChannel.kChannelRegisterMediaMetadataObserver.index, + 'params': jsonEncode({ + 'channelId': channelId, + 'type': 0, // VIDEO_METADATA + }), + }); } @override Future removeInjectStreamUrl(String url) { - return _invokeMethod('removeInjectStreamUrl', { - 'url': url, + return _invokeMethod('callApi', { + 'apiType': ApiTypeChannel.kChannelRemoveInjectStreamUrl.index, + 'params': jsonEncode({ + 'channelId': channelId, + 'url': url, + }), }); } @override Future removePublishStreamUrl(String url) { - return _invokeMethod('removePublishStreamUrl', { - 'url': url, + return _invokeMethod('callApi', { + 'apiType': ApiTypeChannel.kChannelRemovePublishStreamUrl.index, + 'params': jsonEncode({ + 'channelId': channelId, + 'url': url, + }), }); } @override - Future sendMetadata(String metadata) { - return _invokeMethod('sendMetadata', { - 'metadata': metadata, + Future sendMetadata(Uint8List metadata) { + return _invokeMethod('callApiWithBuffer', { + 'apiType': ApiTypeChannel.kChannelSendMetadata.index, + 'params': jsonEncode({ + 'channelId': channelId, + 'metadata': { + 'size': metadata.length, + }, + }), + 'buffer': metadata }); } @override - Future sendStreamMessage(int streamId, String message) { - return _invokeMethod('sendStreamMessage', { - 'streamId': streamId, - 'message': message, + Future sendStreamMessage(int streamId, Uint8List message) { + return _invokeMethod('callApiWithBuffer', { + 'apiType': ApiTypeChannel.kChannelSendStreamMessage.index, + 'params': jsonEncode({ + 'channelId': channelId, + 'streamId': streamId, + 'length': message.length, + }), + 'buffer': message, }); } @override @deprecated Future setEncryptionMode(EncryptionMode encryptionMode) { - return _invokeMethod('setEncryptionMode', { - 'encryptionMode': EncryptionModeConverter(encryptionMode).value(), + return _invokeMethod('callApi', { + 'apiType': ApiTypeChannel.kChannelSetEncryptionMode.index, + 'params': jsonEncode({ + 'channelId': channelId, + 'encryptionMode': EncryptionModeConverter(encryptionMode).value(), + }), }); } @override @deprecated Future setEncryptionSecret(String secret) { - return _invokeMethod('setEncryptionSecret', { - 'secret': secret, + return _invokeMethod('callApi', { + 'apiType': ApiTypeChannel.kChannelSetEncryptionSecret.index, + 'params': jsonEncode({ + 'channelId': channelId, + 'secret': secret, + }), }); } @override Future setLiveTranscoding(LiveTranscoding transcoding) { - return _invokeMethod('setLiveTranscoding', { - 'transcoding': transcoding.toJson(), + return _invokeMethod('callApi', { + 'apiType': ApiTypeChannel.kChannelSetLiveTranscoding.index, + 'params': jsonEncode({ + 'channelId': channelId, + 'transcoding': transcoding.toJson(), + }), }); } @override Future setMaxMetadataSize(int size) { - return _invokeMethod('setMaxMetadataSize', { - 'size': size, + return _invokeMethod('callApi', { + 'apiType': ApiTypeChannel.kChannelSetMaxMetadataSize.index, + 'params': jsonEncode({ + 'channelId': channelId, + 'size': size, + }), }); } @override Future setRemoteDefaultVideoStreamType(VideoStreamType streamType) { - return _invokeMethod('setRemoteDefaultVideoStreamType', { - 'streamType': VideoStreamTypeConverter(streamType).value(), + return _invokeMethod('callApi', { + 'apiType': ApiTypeChannel.kChannelSetRemoteDefaultVideoStreamType.index, + 'params': jsonEncode({ + 'channelId': channelId, + 'streamType': VideoStreamTypeConverter(streamType).value(), + }), }); } @override Future setRemoteUserPriority(int uid, UserPriority userPriority) { - return _invokeMethod('setRemoteUserPriority', { - 'uid': uid, - 'userPriority': UserPriorityConverter(userPriority).value(), + return _invokeMethod('callApi', { + 'apiType': ApiTypeChannel.kChannelSetRemoteUserPriority.index, + 'params': jsonEncode({ + 'channelId': channelId, + 'uid': uid, + 'userPriority': UserPriorityConverter(userPriority).value(), + }), }); } @override - Future setRemoteVideoStreamType(int uid, VideoStreamType streamType) { - return _invokeMethod('setRemoteVideoStreamType', { - 'uid': uid, - 'streamType': VideoStreamTypeConverter(streamType).value(), + Future setRemoteVideoStreamType( + int userId, VideoStreamType streamType) { + return _invokeMethod('callApi', { + 'apiType': ApiTypeChannel.kChannelSetRemoteVideoStreamType.index, + 'params': jsonEncode({ + 'channelId': channelId, + 'userId': userId, + 'streamType': VideoStreamTypeConverter(streamType).value(), + }), }); } @override Future setRemoteVoicePosition(int uid, double pan, double gain) { - return _invokeMethod('setRemoteVoicePosition', { - 'uid': uid, - 'pan': pan, - 'gain': gain, + return _invokeMethod('callApi', { + 'apiType': ApiTypeChannel.kChannelSetRemoteVoicePosition.index, + 'params': jsonEncode({ + 'channelId': channelId, + 'uid': uid, + 'pan': pan, + 'gain': gain, + }), }); } @override Future startChannelMediaRelay( ChannelMediaRelayConfiguration channelMediaRelayConfiguration) { - return _invokeMethod('startChannelMediaRelay', { - 'channelMediaRelayConfiguration': channelMediaRelayConfiguration.toJson(), + return _invokeMethod('callApi', { + 'apiType': ApiTypeChannel.kChannelStartChannelMediaRelay.index, + 'params': jsonEncode({ + 'channelId': channelId, + 'configuration': channelMediaRelayConfiguration.toJson(), + }), }); } @override Future stopChannelMediaRelay() { - return _invokeMethod('stopChannelMediaRelay'); + return _invokeMethod('callApi', { + 'apiType': ApiTypeChannel.kChannelStopChannelMediaRelay.index, + 'params': jsonEncode({ + 'channelId': channelId, + }), + }); } @override Future unregisterMediaMetadataObserver() { - return _invokeMethod('unregisterMediaMetadataObserver'); + return _invokeMethod('callApi', { + 'apiType': ApiTypeChannel.kChannelUnRegisterMediaMetadataObserver.index, + 'params': jsonEncode({ + 'channelId': channelId, + }), + }); } @override Future updateChannelMediaRelay( ChannelMediaRelayConfiguration channelMediaRelayConfiguration) { - return _invokeMethod('updateChannelMediaRelay', { - 'channelMediaRelayConfiguration': channelMediaRelayConfiguration.toJson(), + return _invokeMethod('callApi', { + 'apiType': ApiTypeChannel.kChannelUpdateChannelMediaRelay.index, + 'params': jsonEncode({ + 'channelId': channelId, + 'configuration': channelMediaRelayConfiguration.toJson(), + }), }); } @override Future enableEncryption(bool enabled, EncryptionConfig config) { - return _invokeMethod('enableEncryption', { - 'enabled': enabled, - 'config': config.toJson(), + return _invokeMethod('callApi', { + 'apiType': ApiTypeChannel.kChannelEnableEncryption.index, + 'params': jsonEncode({ + 'channelId': channelId, + 'enabled': enabled, + 'config': config.toJson(), + }), }); } @override Future createDataStreamWithConfig(DataStreamConfig config) { - return _invokeMethod('createDataStream', { - 'config': config.toJson(), + return _invokeMethod('callApi', { + 'apiType': ApiTypeChannel.kChannelCreateDataStream.index, + 'params': jsonEncode({ + 'channelId': channelId, + 'config': config.toJson(), + }), }); } @override - Future enableRemoteSuperResolution(int uid, bool enabled) { - return _invokeMethod('enableRemoteSuperResolution', { - 'uid': uid, - 'enabled': enabled, + Future enableRemoteSuperResolution(int userId, bool enable) { + return _invokeMethod('callApi', { + 'apiType': ApiTypeChannel.kChannelEnableRemoteSuperResolution.index, + 'params': jsonEncode({ + 'channelId': channelId, + 'userId': userId, + 'enable': enable, + }), }); } @override - Future muteLocalAudioStream(bool muted) { - return _invokeMethod('muteLocalAudioStream', { - 'muted': muted, + Future muteLocalAudioStream(bool mute) { + // return _invokeMethod('muteLocalAudioStream', { + // 'muted': muted, + // }); + + return _invokeMethod('callApi', { + 'apiType': ApiTypeChannel.kChannelMuteLocalAudioStream.index, + 'params': jsonEncode({ + 'channelId': channelId, + 'mute': mute, + }), }); } @override - Future muteLocalVideoStream(bool muted) { - return _invokeMethod('muteLocalVideoStream', { - 'muted': muted, + Future muteLocalVideoStream(bool mute) { + // return _invokeMethod('muteLocalVideoStream', { + // 'muted': muted, + // }); + + return _invokeMethod('callApi', { + 'apiType': ApiTypeChannel.kChannelMuteLocalVideoStream.index, + 'params': jsonEncode({ + 'channelId': channelId, + 'mute': mute, + }), }); } @override Future pauseAllChannelMediaRelay() { - return _invokeMethod('pauseAllChannelMediaRelay'); + // return _invokeMethod('pauseAllChannelMediaRelay'); + return _invokeMethod('callApi', { + 'apiType': ApiTypeChannel.kChannelPauseAllChannelMediaRelay.index, + 'params': jsonEncode({ + 'channelId': channelId, + }), + }); } @override Future resumeAllChannelMediaRelay() { - return _invokeMethod('resumeAllChannelMediaRelay'); + // return _invokeMethod('resumeAllChannelMediaRelay'); + return _invokeMethod('callApi', { + 'apiType': ApiTypeChannel.kChannelResumeAllChannelMediaRelay.index, + 'params': jsonEncode({ + 'channelId': channelId, + }), + }); } } @@ -415,571 +673,725 @@ mixin RtcChannelInterface RtcEncryptionInterface, RtcInjectStreamInterface, RtcStreamMessageInterface { - /// Destroys the [RtcChannel] instance. + /// + /// Releases the RtcChannel instance. + /// + /// Future destroy(); - /// Sets the role of a user in a live interactive streaming. /// - /// You can call this method either before or after joining the channel to set the user role as audience or host. If you call this method to switch the user role after joining the channel, the SDK triggers the following callbacks: - /// - The local client: [RtcChannelEventHandler.clientRoleChanged]. - /// - The remote client: [RtcChannelEventHandler.userJoined] or [RtcChannelEventHandler.userOffline] ([UserOfflineReason.BecomeAudience]). + /// Sets the user role and level in an interactive live streaming channel. + /// You can call this method either before or after joining the channel to set the user role as audience or host. + /// If you call this method to switch the user role after joining the channel, the SDK triggers the following callbacks: + /// The local client: clientRoleChanged. + /// The remote client: userJoined or userOffline. + /// + /// + /// + /// This method only takes effect when the channel profile is live interactive streaming (when the profile parameter in setChannelProfile set as LiveBroadcasting). /// - /// **Note** - /// - This method applies to the `LiveBroadcasting` profile only (when the `profile` parameter in `setChannelProfile` is set as `LiveBroadcasting`). - /// - Since v3.2.1, this method can set the user level in addition to the user role. - /// - The user role determines the permissions that the SDK grants to a user, such as permission to send local streams, receive remote streams, and push streams to a CDN address. - /// - The user level determines the level of services that a user can enjoy within the permissions of the user's role. For example, an audience can choose to receive remote streams with low latency or ultra low latency. Levels affect prices. + /// Param [role] The user role in the interactive live streaming. See ClientRole. + /// /// - /// **Parameter** [role] The role of the user. See [ClientRole]. + /// Param [options] The detailed options of a user, including the user level. See ClientRoleOptions. /// - /// **Parameter** [options] The detailed options of a user, including user level. See [ClientRoleOptions]. Future setClientRole(ClientRole role, [ClientRoleOptions? options]); - /// Joins the channel with a user ID. - /// - /// - [RtcChannel.joinChannel] - /// - Does not contain the `channelName` parameter, because `channelName` is specified when creating the `RtcChannel` instance. - /// - Contains the `options` parameter, which decides whether to subscribe to all streams before joining the channel. - /// - Users can join multiple channels simultaneously by creating multiple `RtcChannel` instances and calling the `joinChannel` method of each instance. - /// - By default, the SDK does not publish any stream after the user joins the channel. You need to call the publish method to do that. - /// - /// - [RtcEngine.joinChannel] - /// - Contains the `channelName` parameter, which specifies the channel to join. - /// - Does not contain the `options` parameter. By default, users subscribe to all streams when joining the channel. - /// - Users can join only one channel. - /// - By default, the SDK publishes streams once the user joins the channel. /// - /// Once the user joins the channel (switches to another channel), the user subscribes to the audio and video streams of all the other users in the channel by default, giving rise to usage and billing calculation. If you do not want to subscribe to a specified stream or all remote streams, call the `mute` methods accordingly. - /// - /// **Note** - /// - If you are already in a channel, you cannot rejoin it with the same uid. - /// - We recommend using different UIDs for different channels. - /// - If you want to join the same channel from different devices, ensure that the UIDs in all devices are different. - /// - Ensure that the app ID you use to generate the token is the same with the app ID used when creating the [RtcEngine] instance. + /// Joins the channel with a user ID. + /// Once the user joins the channel, the user subscribes to the audio and video streams of all the other users in the channel by default, giving rise to usage and billing calculation. If you do not want to subscribe to a specified stream or all remote streams, call the mute methods accordingly. + /// + /// + /// If you are already in a channel, you cannot rejoin it with the user ID. + /// We recommend using different UIDs for different channels. + /// If you want to join the same channel from different devices, ensure that the user IDs in all devices are different. /// - /// **Parameter** [token] The token generated at your server.Set it as the token generated at your server. For details, see [Get a token](https://docs.agora.io/en/Agora%20Platform/token?platform=All%20Platforms#generatetoken). + /// Param [options] The channel media options. For details, see ChannelMediaOptions. /// - /// **Parameter** [optionalInfo] Additional information about the channel. This parameter can be set as null. Other users in the channel do not receive this information. + /// Param [token] The token generated on your server for authentication. See Authenticate Your Users with Token. + /// Ensure that the App ID used for creating the token is the same App ID used by the createWithContext method for initializing the RTC engine. + /// /// - /// **Parameter** [optionalUid] The user ID. A 32-bit unsigned integer with a value ranging from 1 to (232-1). This parameter must be unique. If uid is not assigned (or set as 0), the SDK assigns a uid and reports it in the `onJoinChannelSuccess` callback. The app must maintain this user ID. + /// Param [optionalUid] User ID. This parameter is used to identify the user in the channel for real-time audio and video interaction. You need to set and manage user IDs yourself, and ensure that each user ID in the same channel is unique. This parameter is a 32-bit unsigned integer with a value ranging from 1 to 232 -1. If the user ID is not assigned (or set as 0), the SDK assigns a user ID and reports it in the joinChannelSuccess callback. Your app must maintain this user ID. /// - /// **Parameter** [options] The channel media options. See [ChannelMediaOptions]. Future joinChannel(String? token, String? optionalInfo, int optionalUid, ChannelMediaOptions options); - /// Joins a channel with the user account. /// - /// **Note** - /// - If you are already in a channel, you cannot rejoin it with the same uid. - /// - We recommend using different user accounts for different channels. - /// - If you want to join the same channel from different devices, ensure that the user accounts in all devices are different. - /// - Ensure that the app ID you use to generate the token is the same with the app ID used when creating the [RtcEngine] instance. + /// Joins the channel with a user account. + /// Once the user joins the channel, the user subscribes to the audio and video streams of all the other users in the channel by default, giving rise to usage and billing calculation. If you do not want to subscribe to a specified stream or all remote streams, call the mute methods accordingly. + /// + /// + /// If you are already in a channel, you cannot rejoin it with the user ID. + /// We recommend using different user accounts for different channels. + /// If you want to join the same channel from different devices, ensure that the user accounts in all devices are different. /// - /// **Parameter** [token] The token generated at your server. Set it as the token generated at your server. For details, see [Get a token](https://docs.agora.io/en/Agora%20Platform/token?platform=All%20Platforms#generatetoken). + /// Param [options] The channel media options. For details, see ChannelMediaOptions. /// - /// **Parameter** [userAccount] The user account. The maximum length of this parameter is 255 bytes. Ensure that you set this parameter and do not set it as null. - /// - All lowercase English letters: a to z. - /// - All uppercase English letters: A to Z. - /// - All numeric characters: 0 to 9. - /// - The space character. - /// - Punctuation characters and other symbols, including: "!", "#", "$", "%", "&", "(", ")", "+", "-", ":", ";", "<", "=", ".", ">", "?", "@", "\[", "\]", "^", "_", " {", "}", "|", "~", ",". + /// Param [userAccount] The user account. This parameter is used to identify the user in the channel for real-time audio and video engagement. You need to set and manage user accounts yourself and ensure that each user account in the same channel is unique.The maximum length of this parameter is 255 bytes. Ensure that you set this parameter and do not set it as null. Supported characters are (89 in total): + /// The 26 lowercase English letters: a to z. + /// The 26 uppercase English letters: A to Z. + /// All numeric characters: 0 to 9. + /// Space + /// "!", "#", "$", "%", "&", "(", ")", "+", "-", ":", ";", "<", "=", ".", ">", "?", "@", "[", "]", "^", "_", "{", "}", "|", "~", "," + /// + /// /// - /// **Parameter** [options] The channel media options. See [ChannelMediaOptions]. + /// Param [token] The token generated on your server for authentication. See Authenticate Your Users with Token. + /// Ensure that the App ID used for creating the token is the same App ID used by the createWithContext method for initializing the RTC engine. + /// /// Future joinChannelWithUserAccount( String? token, String userAccount, ChannelMediaOptions options); - /// Leaves the current channel. /// - /// A successful leaveChannel method call triggers the following callbacks: - /// - The local client: [RtcChannelEventHandler.leaveChannel]. - /// - The remote client: [RtcChannelEventHandler.userOffline], if the user leaving the channel is in a Communication channel, or is a broadcaster in a [ChannelProfile.LiveBroadcasting] channel . + /// Leaves a channel. + /// This method lets the user leave the channel, for example, by hanging up or exiting the call. This method releases all resources related to the session. This method call is asynchronous, and the user has not left the channel when the method call returns. + /// After calling joinChannel, you must call leaveChannel to end the call, otherwise the next call cannot be started. + /// No matter whether you are currently in a call or not, you can call leaveChannel without side effects. + /// A successful call of this method triggers the following callbacks: + /// The local client: leaveChannel. + /// The remote client: userOffline, if the user + /// joining the channel is in the COMMUNICATION profile, or is a host in the + /// LIVE_BROADCASTING profile. + /// + /// + /// + /// If you call the leaveChannel method immediately after calling destroy, the SDK will not be able to trigger the leaveChannel callback. + /// If you call the leaveChannel method during a CDN live streaming, the SDK automatically calls the removePublishStreamUrl method. + /// Future leaveChannel(); - /// Renews the token when the current token expires. /// - /// In the following situations, the SDK decides that the current token has expired: - /// - The SDK triggers the [RtcChannelEventHandler.tokenPrivilegeWillExpire] callback, or - /// - The [RtcChannelEventHandler.connectionStateChanged] callback reports the [ConnectionChangedReason.TokenExpired] error. - /// You should get a new token from your server and call this method to renew it. Failure to do so results in the SDK disconnecting from the Agora server. - /// **Parameter** [token] The new token. + /// Gets a new token when the current token expires after a period of time. + /// Passes a new token to the SDK. A token expires after a certain period of time. The app should get a new token and call this method to pass the token to the SDK. Failure to do so results in the SDK disconnecting from the server. + /// The SDK triggers the tokenPrivilegeWillExpire callback. + /// The connectionStateChanged callback reports TokenExpired(9). + /// + /// Param [token] The new token. + /// Future renewToken(String token); - /// Gets the connection state of the SDK. + /// + /// Gets the current connection state of the SDK. + /// You can call this method either before or after joining a channel. + /// Future getConnectionState(); - /// Publishes the local stream to the channel. /// - /// You must keep the following restrictions in mind when calling this method. Otherwise, the SDK returns [ErrorCode.Refused]: - /// - This method publishes one stream only to the channel corresponding to the current [RtcChannel] instance. - /// - In a LiveBroadcasting channel, only a broadcaster can call this method. To switch the client role, call [RtcChannel.setClientRole] of the current [RtcChannel] instance. - /// - You can publish a stream to only one channel at a time. For details, see the advanced guide *Join Multiple Channels*. + /// Publish local audio and video streams to the channel. + /// The call of this method must meet the following requirements, otherwise the SDK returns -5(ERR_REFUSED): + /// This method only supports publishing audio and video streams to the channel corresponding to the current RtcChannel object. + /// In the interactive live streaming channel, only a host can call this method. To switch the client role, call setClientRole of the current RtcChannel object. + /// You can publish a stream to only one channel at a time. For details on joining multiple channels, see the advanced guide Join Multiple Channels. + /// @deprecated Future publish(); + /// /// Stops publishing a stream to the channel. + /// If you call this method in a channel where you are not publishing streams, the SDK returns + /// -5 (ERR_REFUSED). /// - /// If you call this method in a channel where you are not publishing streams, the SDK returns [ErrorCode.Refused]. @deprecated Future unpublish(); - /// Gets the current call ID. /// - /// **Returns** - /// - The current call ID, if the method call succeeds. - /// - The empty string "", if the method call fails. + /// Retrieves the call ID. + /// When a user joins a channel on a client, a callId is generated to identify the call from the client. Some methods, such as rate and complain, must be called after the call ends to submit feedback to the SDK. These methods require the callId parameter. + /// Call this method after joining a channel. + /// + /// **return** The current call ID. + /// Future getCallId(); } /// @nodoc mixin RtcAudioInterface { - /// Adjusts the playback volume of a specified remote user. /// - /// You can call this method as many times as necessary to adjust the playback volume of different remote users, or to repeatedly adjust the playback volume of the same remote user. + /// Adjusts the playback signal volume of a specified remote user. + /// You can call this method to adjust the playback volume of a specified remote user. To adjust the playback volume of different remote users, call the method as many times, once for each remote user. + /// + /// + /// Call this method after joining a channel. + /// The playback volume here refers to the mixed volume of a specified remote user. /// - /// **Note** - /// - Call this method after joining a channel. - /// - The playback volume here refers to the mixed volume of a specified remote user. - /// - This method can only adjust the playback volume of one specified remote user at a time. To adjust the playback volume of different remote users, call the method as many times, once for each remote user. + /// Param [null] /// - /// **Parameter** [uid] ID of the remote user. + /// Param [uid] The ID of the remote user. /// - /// **Parameter** [volume] The playback volume of the specified remote user. The value ranges from 0 to 400: - /// - 0: Mute. - /// - 100: The original volume. - /// - 400: Four times the original volume with signal-clipping protection. Future adjustUserPlaybackSignalVolume(int uid, int volume); - /// Stops or resumes publishing the local audio stream. /// - /// *Parameter* [muted] Sets whether to stop publishing the local audio stream. - /// - /// - `true`: Stop publishing the local audio stream. - /// - `false`: Resume publishing the local audio stream. + /// Stops or resumes publishing the local audio stream. + /// /// - /// This method only sets the publishing state of the audio stream in the channel of AgoraRtcChannel. + /// Param [mute] Whether to stop publishing the local audio stream. + /// + /// true: Stop publishing the local audio stream. + /// false: (Default) Resumes publishing the local audio stream. + /// + /// /// - /// A successful method call triggers the `remoteAudioStateChanged` callback on the remote client. + Future muteLocalAudioStream(bool mute); + /// - /// You can only publish the local stream in one channel at a time. If you create multiple channels, ensure that you only call `muteLocalAudioStream(false)` in one channel; otherwise, the method call fails, and the SDK returns -5 (`Refused`). + /// Stops or resumes subscribing to the audio stream of a specified user. + /// Call this method after joining a channel. + /// See recommended settings in Set the Subscribing State. /// - /// **Note** + /// Param [userId] The user ID of the specified user. /// - /// - This method does not change the usage status of the audio-capturing device. - /// - Whether this method call takes effect is affected by the `joinChannel` and `setClientRole` methods. For details, see Set the Publishing State. + /// Param [muted] Whether to stop subscribing to the audio stream of the specified user. + /// + /// true: Stop subscribing to the audio stream of the specified user. + /// false: (Default) Subscribe to the audio stream of the specified user. + /// + /// /// - Future muteLocalAudioStream(bool muted); + Future muteRemoteAudioStream(int userId, bool muted); - /// Stops/Resumes receiving the audio stream of the specified user. /// - /// **Parameter** [uid] ID of the remote user whose audio stream you want to mute. + /// Stops or resumes subscribing to the audio streams of all remote users. + /// As of v3.3.0, after successfully calling this method, the local user stops or resumes subscribing to the audio streams of all remote users, including all subsequent users. + /// + /// + /// Call this method after joining a channel. /// - /// **Parameter** [muted] Determines whether to receive/stop receiving the audio stream of the specified user: - /// - `true`: Stop receiving the audio stream of the user. - /// - `false`: (Default) Receive the audio stream of the user. - Future muteRemoteAudioStream(int uid, bool muted); - - /// Stops/Resumes receiving all remote audio streams. + /// Param [muted] Whether to subscribe to the audio streams of all remote users: + /// true: Do not subscribe to the audio streams of all remote users. + /// false: (Default) Subscribe to the audio streams of all remote users by default. + /// + /// + /// /// - /// **Parameter** [muted] Determines - /// whether to receive/stop receiving all remote audio streams: - /// - `true`: Stop receiving all remote audio streams. - /// - `false`: (Default) Receive all remote audio streams. Future muteAllRemoteAudioStreams(bool muted); - /// Sets whether to receive all remote audio streams by default. - /// - /// **Deprecated** /// - /// This method is deprecated from v3.3.1. + /// Stops or resumes subscribing to the audio streams of all remote users by default. + /// Call this method after joining a channel. After successfully calling this method, the local user stops or resumes subscribing to the audio streams of all subsequent users. + /// + /// + /// Deprecated: + /// This method is deprecated. + /// + /// + /// + /// If you need to resume subscribing to the audio streams of remote users in the channel after calling this method, do the following: + /// + /// If you need to resume subscribing to the audio stream of a specified user, call muteRemoteAudioStream (false), and specify the user ID. + /// If you need to resume subscribing to the audio streams of multiple remote users, call muteRemoteAudioStream (false) multiple times. + /// + /// Param [muted] Whether to stop subscribing to the audio streams of all remote users by default. + /// true: Stop subscribing to the audio streams of all remote users by default. + /// false: (Default) Subscribe to the audio streams of all remote users by default. + /// + /// + /// /// - /// **Parameter** [muted] Determines whether to receive/stop receiving all remote audio streams by default: - /// - `true`: Stop receiving all remote audio streams by default. - /// - `false`: (Default) Receive all remote audio streams by default. @deprecated Future setDefaultMuteAllRemoteAudioStreams(bool muted); } /// @nodoc mixin RtcVideoInterface { - /// Stops or resumes publishing the local video stream. /// - /// **Parameter** [muted] Sets whether to stop publishing the local video stream. + /// Stops or resumes publishing the local video stream. + /// /// - /// - `true`: Stop publishing the local video stream. - /// - `false`: Resume publishing the local video stream. + /// Param [mute] Whether to stop publishing the local video stream. + /// true: Stop publishing the local video stream. + /// false: (Default) Publish the local video stream. + /// + /// + /// /// - /// This method only sets the publishing state of the video stream in the channel of `RtcChannel`. + Future muteLocalVideoStream(bool muted); + /// - /// A successful method call triggers the `remoteVideoStateChanged` callback on the remote client. + /// Stops or resumes subscribing to the video stream of a specified user. + /// Call this method after joining a channel. + /// See recommended settings in Set the Subscribing State. /// - /// You can only publish the local stream in one channel at a time. If you create multiple channels, ensure that you only call `muteLocalVideoStream(false)` in one channel; otherwise, the method call fails, and the SDK returns -5 (Refused). + /// Param [userId] The ID of the specified user. /// - /// **Note**: + /// Param [muted] Whether to stop subscribing to the video stream of the specified user. + /// true: Stop subscribing to the video streams of the specified user. + /// false: (Default) Subscribe to the video stream of the specified user. + /// + /// /// - /// - This method does not change the usage state of the video-capturing device. - /// - Whether this method call takes effect is affected by the `joinChannel` and `setClientRole` methods. For details, see Set the Publishing State. - Future muteLocalVideoStream(bool muted); + Future muteRemoteVideoStream(int userId, bool muted); - /// Stops/Resumes receiving the video stream of the specified user. /// - /// **Parameter** [uid] ID of the remote user whose video stream you want to mute. + /// Stops or resumes subscribing to the video streams of all remote users. + /// As of v3.3.0, after successfully calling this method, the local user stops or resumes subscribing to the video streams of all remote users, including all subsequent users. + /// + /// + /// Call this method after joining a channel. /// - /// **Parameter** [muted] Determines whether to receive/stop receiving the video stream of the specified user: - /// - `true`: Stop receiving the video stream of the user. - /// - `false`: (Default) Receive the video stream of the user. - Future muteRemoteVideoStream(int uid, bool muted); - - /// Stops/Resumes receiving all remote video streams. + /// Param [muted] Whether to stop subscribing to the video streams of all remote users. + /// true: Stop subscribing to the video streams of all remote users. + /// false: (Default) Subscribe to the audio streams of all remote users by default. + /// + /// + /// /// - /// **Parameter** [muted] Determines whether to receive/stop receiving all remote video streams: - /// - `true`: Stop receiving all remote video streams. - /// - `false`: (Default) Receive all remote video streams. Future muteAllRemoteVideoStreams(bool muted); - /// Sets whether to receive all remote video streams by default. - /// - /// **Deprecated** /// - /// This method is deprecated from v3.3.1. + /// Stops or resumes subscribing to the video streams of all remote users by default. + /// Call this method after joining a channel. After successfully calling this method, the local user stops or resumes subscribing to the audio streams of all subsequent users. + /// + /// + /// Deprecated: + /// This method is deprecated. + /// + /// + /// + /// If you need to resume subscribing to the video streams of remote users in the channel, do the following: + /// + /// If you need to resume subscribing to a single user, call muteRemoteVideoStream(false) and specify the ID of the remote user you want to subscribe to. + /// If you want to resume subscribing to multiple users, call muteRemoteVideoStream(false) multiple times. + /// + /// Param [muted] Whether to stop subscribing to the audio streams of all remote users by default. + /// true: Stop subscribing to the audio streams of all remote users by default. + /// false: (Default) Resume subscribing to the audio streams of all remote users by default. + /// + /// + /// /// - /// **Parameter** [muted] Determines whether to receive/stop receiving all remote video streams by default: - /// - `true`: Stop receiving all remote video streams by default. - /// - `false`: (Default) Receive all remote video streams by default. @deprecated Future setDefaultMuteAllRemoteVideoStreams(bool muted); - /// @nodoc - Future enableRemoteSuperResolution(int uid, bool enabled); + /// + /// Enables/Disables the super-resolution algorithm for a remote user's video stream. + /// This feature effectively boosts the resolution of a remote user's video seen by the local user. If the original resolution of a remote user's video is a × b, the local user's device can render the remote video at a resolution of 2a × 2b + /// after you enable this feature. + /// After you call this method, the SDK triggers the userSuperResolutionEnabled callback to report whether you have successfully enabled super resolution. + /// The super resolution feature requires extra system resources. To balance the visual experience and system usage, the SDK poses the following restrictions: This feature can only be enabled for a single remote user. + /// On Android, the original resolution of the remote video must not exceed 640 × 360 pixels. On iOS, the original resolution of the remote video must not exceed 640 × 480 pixels. If you exceed these limitations, the SDK triggers the warning callback and returns the corresponding warning codes: + /// SuperResolutionStreamOverLimitation: 1610. The origin resolution of the remote video is beyond the range where the super resolution can be applied. + /// SuperResolutionUserCountOverLimitation: 1611. Super resolution is already being used on another remote user's video. + /// SuperResolutionDeviceNotSupported: 1612. The device does not support using super resolution. + /// + /// + /// + /// This method is for Android and iOS only. + /// Before calling this method, ensure that you have integrated the following dynamic libraries: + /// Android: libagora_super_resolution_extension.so + /// iOS: AgoraSuperResolutionExtension.xcframework + /// + /// + /// Because this method has certain system performance requirements, Agora recommends that you use the following devices or better: + /// Android: + /// VIVO: V1821A, NEX S, 1914A, 1916A, 1962A, 1824BA, X60, X60 Pro + /// OPPO: PCCM00, Find X3 + /// OnePlus: A6000 + /// Xiaomi: Mi 8, Mi 9, Mi 10, Mi 11, MIX3, Redmi K20 Pro + /// SAMSUNG: SM-G9600, SM-G9650, SM-N9600, SM-G9708, SM-G960U, SM-G9750, S20, S21 + /// HUAWEI: SEA-AL00, ELE-AL00, VOG-AL00, YAL-AL10, HMA-AL00, EVR-AN00, nova 4, nova 5 Pro, nova 6 5G, nova 7 5G, Mate 30, Mate 30 Pro, Mate 40, Mate 40 Pro, P40, P40 Pro, Huawei M6, MatePad 10.8 + /// + /// iOS: + /// iPhone XR + /// iPhone XS + /// iPhone XS Max + /// iPhone 11 + /// iPhone 11 Pro + /// iPhone 11 Pro Max + /// iPhone 12 + /// iPhone 12 mini + /// iPhone 12 Pro + /// iPhone 12 Pro Max + /// iPhone 12 SE (2nd generation) + /// iPad Pro 11-inch (3rd generation) + /// iPad Pro 12.9-inch (3rd generation) + /// iPad Air 3 (3rd generation) + /// iPad Air 3 (4th generation) + /// + /// Param [userId] The ID of the remote user. + /// + /// Param [enable] Whether to enable super resolution for the remote user’s video: + /// true: Enable virtual background. + /// false: Do not enable virtual background. + /// + /// + Future enableRemoteSuperResolution(int userId, bool enable); } /// @nodoc mixin RtcVoicePositionInterface { - /// Sets the sound position of a remote user. /// - /// When the local user calls this method to set the sound position of a remote user, the sound difference between the left and right channels allows the local user to track the real-time position of the remote user, creating a real sense of space. This method applies to massively multiplayer online games, such as Battle Royale games. + /// Sets the 2D position (the position on the horizontal plane) of the remote user's voice. + /// This method sets the 2D position and volume of a remote user, so that the local user can easily hear and identify the remote user's position. + /// When the local user calls this method to set the voice position of a remote user, the voice difference between the left and right channels allows the local user to track the real-time position of the remote user, creating a sense of space. This method applies to massive multiplayer online games, such as Battle Royale games. + /// + /// + /// For this method to work, enable stereo panning for remote users by calling the enableSoundPositionIndication method before joining a channel. + /// For the best voice positioning, Agora recommends using a wired headset. + /// Call this method after joining a channel. /// - /// **Note** - /// - For this method to work, enable stereo panning for remote users by calling the [RtcEngine.enableSoundPositionIndication] method before joining a channel. - /// - This method requires hardware support. For the best sound positioning, we recommend using a wired headset. + /// Param [uid] The user ID of the remote user. /// - /// **Parameter** [uid] The ID of the remote user. + /// Param [pan] The voice position of the remote user. The value ranges from -1.0 to 1.0: + /// 0.0: (Default) The remote voice comes from the front. + /// -1.0: The remote voice comes from the left. + /// 1.0: The remote voice comes from the right. + /// + /// /// - /// **Parameter** [pan] The sound position of the remote user. The value ranges from -1.0 to 1.0: - /// - 0.0: The remote sound comes from the front. - /// - -1.0: The remote sound comes from the left. - /// - 1.0: The remote sound comes from the right. + /// Param [gain] The volume of the remote user. The value ranges from 0.0 to 100.0. The default value is 100.0 (the original volume of the remote user). The smaller the value, the lower the volume. /// - /// **Parameter** [gain] Gain of the remote user. The value ranges from 0.0 to 100.0. The default value is 100.0 (the original gain of the remote user). The smaller the value, the less the gain. Future setRemoteVoicePosition(int uid, double pan, double gain); } /// @nodoc mixin RtcPublishStreamInterface { - /// Sets the video layout and audio settings for CDN live. /// - /// The SDK triggers the [RtcChannelEventHandler.transcodingUpdated] callback when you call this method to update the [LiveTranscoding] class. If you call this method to set the [LiveTranscoding] class for the first time, the SDK does not trigger the [RtcChannelEventHandler.transcodingUpdated] callback. + /// Sets the transcoding configurations for CDN live streaming. + /// This method takes effect only when you are a host in live interactive streaming. + /// Ensure that you enable the RTMP Converter service before using this function. See Prerequisites in the advanced guide Push Streams to CDN. + /// If you call this method to set the transcoding configuration for the first time, the SDK does not trigger the transcodingUpdated callback. + /// Call this method after joining a channel. + /// Agora supports pushing media streams in RTMPS protocol to the CDN only when you enable transcoding. + /// + /// + /// This method sets the video layout and audio settings for CDN live streaming. The SDK triggers the transcodingUpdated callback when you call this method to update the transcoding setting. /// - /// **Note** - /// - Ensure that you enable the RTMP Converter service before using this function. See Prerequisites in *Push Streams to CDN*. - /// - Ensure that the user joins a channel before calling this method. - /// - This method can only be called by a broadcaster in a [ChannelProfile.LiveBroadcasting] channel . - /// - Ensure that you call this method before calling the [RtcChannel.addPublishStreamUrl] method. + /// Param [transcoding] The transcoding configurations for CDN live streaming. For details, see LiveTranscoding. /// - /// **Parameter** [transcoding] Sets the CDN live audio/video transcoding settings. See [LiveTranscoding]. Future setLiveTranscoding(LiveTranscoding transcoding); - /// Publishes the local stream to the CDN. /// - /// This method call triggers the [RtcChannelEventHandler.rtmpStreamingStateChanged] callback on the local client to report the state of adding a local stream to the CDN. + /// Publishes the local stream to a specified CDN live streaming URL. + /// Call this method after joining a channel. + /// Ensure that you enable the RTMP Converter service before using this function. + /// This method takes effect only when you are a host in live interactive streaming. + /// This method adds only one stream CDN streaming URL each time it is called. To push multiple URLs, call this method multiple times. + /// Agora supports pushing media streams in RTMPS protocol to the CDN only when you enable transcoding. + /// + /// + /// After calling this method, you can push media streams in RTMP or RTMPS protocol to the CDN. The SDK triggers the rtmpStreamingStateChanged callback on the local client to report the state of adding a local stream to the CDN. /// - /// **Note** - /// - Ensure that you enable the RTMP Converter service before using this function. See Prerequisites in *Push Streams to CDN*. - /// - Ensure that the user joins a channel before calling this method. - /// - This method can only be called by a broadcaster in a [ChannelProfile.LiveBroadcasting] channel . - /// - This method adds only one stream HTTP/HTTPS URL address each time it is called. + /// Param [url] The CDN streaming URL in the RTMP or RTMPS format. The maximum length of this parameter is 1024 bytes. The URL address must not contain special characters, such as Chinese language characters. /// - /// **Parameter** [url] The CDN streaming URL in the RTMP format. The maximum length of this parameter is 1024 bytes. The URL address must not contain special characters, such as Chinese language characters. + /// Param [transcodingEnabled] Whether to enable transcoding. Transcoding in a CDN live streaming converts the audio and video streams before pushing them to the CDN server. It applies to scenarios where a channel has multiple broadcasters and composite layout is needed + /// true: Enable transcoding. + /// false: Disable transcoding. + /// + /// If you set this parameter as true , ensure that you call the setLiveTranscoding method before this method. + /// /// - /// **Parameter** [transcodingEnabled] Sets whether transcoding is enabled/disabled. If you set this parameter as true, ensure that you call the [RtcChannel.setLiveTranscoding] method before this method. - /// - `true`: Enable transcoding. To transcode the audio or video streams when publishing them to CDN live, often used for combining the audio and video streams of multiple broadcasters in CDN live. - /// - `false`: Disable transcoding. Future addPublishStreamUrl(String url, bool transcodingEnabled); - /// Removes an RTMP stream from the CDN. /// - /// This method removes the CDN streaming URL (added by [RtcChannel.addPublishStreamUrl]) from a CDN live stream. The SDK reports the result of this method call in the [RtcChannelEventHandler.rtmpStreamingStateChanged] callback. + /// Removes an RTMP or RTMPS stream from the CDN. + /// Ensure that you enable the RTMP Converter service before using this function. + /// This method takes effect only when you are a host in live interactive streaming. + /// Call this method after joining a channel. + /// This method removes only one CDN streaming URL each time it is called. To remove multiple URLs, call this method multiple times. + /// + /// + /// After a successful method call, the SDK triggers rtmpStreamingStateChanged on the local client to report the result of deleting the address. /// - /// **Note** - /// - Ensure that you enable the RTMP Converter service before using this function. See Prerequisites in *Push Streams to CDN*. - /// - This method can only be called by a broadcaster in a [ChannelProfile.LiveBroadcasting] channel . - /// - This method removes only one stream HTTP/HTTPS URL address each time it is called. + /// Param [url] The CDN streaming URL to be removed. The maximum length of this parameter is 1024 bytes. The CDN streaming URL must not contain special characters, such as Chinese characters. /// - /// **Parameter** [url] The CDN streaming URL to be removed. The maximum length of this parameter is 1024 bytes. The URL address must not contain special characters, such as Chinese language characters. Future removePublishStreamUrl(String url); } /// @nodoc mixin RtcMediaRelayInterface { - /// Starts to relay media streams across channels. /// - /// After a successful method call, the SDK triggers the [RtcChannelEventHandler.channelMediaRelayStateChanged] and [RtcChannelEventHandler.channelMediaRelayEvent] callbacks, and these callbacks report the state and events of the media stream relay. - /// - If the [RtcChannelEventHandler.channelMediaRelayStateChanged] callback reports [ChannelMediaRelayState.Running] and [ChannelMediaRelayError.None], and the [RtcChannelEventHandler.channelMediaRelayEvent] callback reports [ChannelMediaRelayEvent.SentToDestinationChannel], the SDK starts relaying media streams between the original and the destination channel. - /// - If the [RtcChannelEventHandler.channelMediaRelayStateChanged] callback returns Failure(3), an exception occurs during the media stream relay. + /// Starts relaying media streams across channels. This method can be used to implement scenarios such as co-host across channels. + /// After a successful method call, the SDK triggers the channelMediaRelayStateChanged and channelMediaRelayEvent callbacks, and these callbacks return the state and events of the media stream relay. + /// If the channelMediaRelayStateChanged callback returns Running(2) and None(0), and the channelMediaRelayEvent callback returns SentToDestinationChannel(4), it means that the SDK starts relaying media streams between the source channel and the destination channel. + /// If the channelMediaRelayStateChanged callback returns Failure(3), an exception occurs during the media stream relay. + /// + /// + /// + /// + /// Call this method after joining the channel. + /// This method takes effect only when you are a host in a live streaming channel. + /// After a successful method call, if you want to call this method again, ensure that you call the stopChannelMediaRelay method to quit the current relay. + /// Contact support@agora.io (https://agora-ticket.agora.io/) before implementing this function. + /// We do not support string user accounts in this API. + /// + /// Param [channelMediaRelayConfiguration] The configuration of the media stream relay. For details, see ChannelMediaRelayConfiguration. /// - /// See [ChannelMediaRelayState.Failure] - /// - /// **Note** - /// - Call this method after joining the channel. - /// - This method can only be called by a broadcaster in a [ChannelProfile.LiveBroadcasting] channel . - /// - After a successful method call, if you want to call this method again, ensure that you call the [RtcChannel.stopChannelMediaRelay] method to quit the current relay. - /// - /// **Parameter** [channelMediaRelayConfiguration] The configuration of the media stream relay. Future startChannelMediaRelay( ChannelMediaRelayConfiguration channelMediaRelayConfiguration); - /// Updates the channels for media relay. - /// - /// After the channel media relay starts, if you want to relay the media stream to more channels, or leave the current relay channel, you can call this method. /// - /// After a successful method call, the SDK triggers the [RtcChannelEventHandler.channelMediaRelayEvent] callback with the [ChannelMediaRelayEvent.UpdateDestinationChannel] state code. + /// Updates the channels for media stream relay. + /// After the media relay starts, if you want to relay the media stream to more channels, or leave the current relay channel, you can call the updateChannelMediaRelay method. + /// After a successful method call, the SDK triggers the channelMediaRelayEvent callback with the UpdateDestinationChannel(7) state code. + /// Call this method after the startChannelMediaRelay method to update the destination channel. /// - /// **Note** - /// - Call this method after the startChannelMediaRelay method to update the destination channel. - /// See [RtcChannel.startChannelMediaRelay] - /// - This method supports adding at most four destination channels in the relay. + /// Param [channelMediaRelayConfiguration] The configuration of the media stream relay. For more details, see ChannelMediaRelayConfiguration. /// - /// **Parameter** [channelMediaRelayConfiguration] The media stream relay configuration. - /// See [ChannelMediaRelayConfiguration] Future updateChannelMediaRelay( ChannelMediaRelayConfiguration channelMediaRelayConfiguration); - /// Stops the media stream relay. /// - /// Once the relay stops, the broadcaster quits all the destination channels. - /// After a successful method call, the SDK triggers the [RtcChannelEventHandler.channelMediaRelayStateChanged] callback. If the callback reports [ChannelMediaRelayState.Idle] and [ChannelMediaRelayError.None], the broadcaster successfully stops the relay. + /// Stops the media stream relay. Once the relay stops, the host quits all the destination channels. + /// After a successful method call, the SDK triggers the channelMediaRelayStateChanged callback. If the callback reports Idle(0) and None(0), the host successfully stops the relay. + /// If the method call fails, the SDK triggers the channelMediaRelayStateChanged callback with the ServerNoResponse(2) or ServerConnectionLost(8) status code. You can call the leaveChannel method to leave the channel, and the media stream relay automatically stops. /// - /// **Note** - /// - If the method call fails, the SDK triggers the [RtcChannelEventHandler.channelMediaRelayStateChanged] callback with the [ChannelMediaRelayError.ServerNoResponse] or [ChannelMediaRelayError.ServerConnectionLost] state code. You can leave the channel using [RtcChannel.leaveChannel], and the media stream relay automatically stops. Future stopChannelMediaRelay(); - /// @nodoc + /// + /// Pauses the media stream relay to all destination channels. + /// After the cross-channel media stream relay starts, you can call this method to pause relaying media streams to all destination channels; after the pause, if you want to resume the relay, call resumeAllChannelMediaRelay. + /// After a successful method call, the SDK triggers the channelMediaRelayEvent callback to report whether the media stream relay is successfully paused. + /// Call this method after startChannelMediaRelay. + /// Future pauseAllChannelMediaRelay(); - /// @nodoc + /// + /// Resumes the media stream relay to all destination channels. + /// After calling the pauseAllChannelMediaRelay method, you can call this method to resume relaying media streams to all destination channels. + /// After a successful method call, the SDK triggers the channelMediaRelayEvent callback to report whether the media stream relay is successfully resumed. + /// Call this method after the pauseAllChannelMediaRelay method. + /// Future resumeAllChannelMediaRelay(); } /// @nodoc mixin RtcDualStreamInterface { - /// Sets the video stream type of the remote video stream when the remote user sends dual streams. /// - /// This method allows the app to adjust the corresponding video-stream type based on the size of the video window to reduce the bandwidth and resources. - /// - If the remote user enables the dual-stream mode by calling the [RtcEngine.enableDualStreamMode] method, the SDK receives the high-video stream by default. You can use this method to switch to the low-video stream. - /// - If dual-stream mode is not enabled, the SDK receives the high-stream video by default. - /// By default, the aspect ratio of the low-video stream is the same as the high-video stream. Once the resolution of the high-video stream is set, the system automatically sets the resolution, frame rate, and bitrate of the low-video stream. + /// Sets the stream type of the remote video. + /// The method result returns in the apiCallExecuted callback. + /// By default, users receive the high-quality video stream. Call this method if you want to switch to the low-quality video stream. This method allows the app to adjust the corresponding video stream type based on the size of the video window to reduce the bandwidth and resources. The aspect ratio of the low-quality video stream is the same as the high-quality video stream. Once the resolution of the high-quality video stream is set, the system automatically sets the resolution, frame rate, and bitrate of the low-quality video stream. + /// + /// Under limited network conditions, if the publisher has not disabled the dual-stream mode using enableDualStreamMode(false), the receiver can choose to receive either the high-quality video stream (the high resolution, and high bitrate video stream) or the low-quality video stream (the low resolution, and low bitrate video stream). The high-quality video stream has a higher resolution and bitrate, and the low-quality video stream has a lower resolution and bitrate. + /// Call this method after joining a channel. If you call both setRemoteVideoStreamType and setRemoteDefaultVideoStreamType, the setting of setRemoteVideoStreamType takes effect. /// - /// **Parameter** [uid] ID of the remote user sending the video stream. + /// Param [streamType] The video stream type: VideoStreamType. + /// /// - /// **Parameter** [streamType] Sets the video-stream type. See [VideoStreamType]. - Future setRemoteVideoStreamType(int uid, VideoStreamType streamType); + Future setRemoteVideoStreamType(int userId, VideoStreamType streamType); - /// Sets the default video-stream type of the remote video stream when the remote user sends dual streams. /// - /// You can call this method either before or after joining a channel. - /// If you call both [setRemoteVideoStreamType] and [setRemoteDefaultVideoStreamType], the SDK applies the settings in the [setRemoteVideoStreamType] method. + /// Sets the default stream type of remote video streams. + /// The result of this method returns in the apiCallExecuted callback. + /// By default, users receive the high-quality video stream. Call this method if you want to switch to the low-quality video stream. This method allows the app to adjust the corresponding video stream type based on the size of the video window to reduce the bandwidth and resources. The aspect ratio of the low-quality video stream is the same as the high-quality video stream. Once the resolution of the high-quality video stream is set, the system automatically sets the resolution, frame rate, and bitrate of the low-quality video stream. + /// Under limited network conditions, if the publisher has not disabled the dual-stream mode using (),the receiver can choose to receive either the high-quality video stream or the low-quality video stream. The high-quality video stream has a higher resolution and bitrate, and the low-quality video stream has a lower resolution and bitrate.enableDualStreamModefalse + /// Call this method after joining a channel. If you call both setRemoteVideoStreamType and setRemoteDefaultVideoStreamType, the setting of setRemoteVideoStreamType takes effect. + /// + /// Param [streamType] The default stream type of the remote video, see VideoStreamType. + /// /// - /// **Parameter** [streamType] Sets the default video-stream type. See [VideoStreamType]. Future setRemoteDefaultVideoStreamType(VideoStreamType streamType); } /// @nodoc mixin RtcFallbackInterface { - /// Sets the priority of a remote user's media stream. /// - /// Use this method with the [RtcEngine.setRemoteSubscribeFallbackOption] method. If a remote video stream experiences the fallback, the SDK ensures the high-priority user gets the best possible stream quality. + /// Prioritizes a remote user's stream. + /// Prioritizes a remote user's stream. The SDK ensures the high-priority user gets the best possible stream quality. The SDK ensures the high-priority user gets the best possible stream quality. + /// + /// + /// The SDK supports setting only one user as high priority. + /// Ensure that you call this method before joining a channel. /// - /// **Note** - /// - The Agora SDK supports setting `userPriority` as `High` for one user only. + /// Param [uid] The ID of the remote user. /// - /// **Parameter** [uid] The ID of the remote user. + /// Param [userPriority] The priority of the remote user. See UserPriority. /// - /// **Parameter** [userPriority] The priority of the remote user. See [UserPriority]. Future setRemoteUserPriority(int uid, UserPriority userPriority); } /// @nodoc mixin RtcMediaMetadataInterface { - /// Registers the metadata observer. /// - /// This method enables you to add synchronized metadata in the video stream for more diversified live broadcast interactions, such as sending shopping links, digital coupons, and online quizzes. + /// Registers the metadata observer. + /// Call this method before joinChannel. + /// This method applies only to interactive live streaming. /// - /// **Note** - /// - Call this method before the [RtcChannel.joinChannel] method. - /// - This method applies to the [ChannelProfile.LiveBroadcasting] profile only. Future registerMediaMetadataObserver(); - /// Unregisters the metadata observer. + /// + /// Unregisters the media metadata observer. + /// + /// Future unregisterMediaMetadataObserver(); - /// Sets the maximum size of the metadata. /// - /// **Parameter** [size] The maximum size (bytes) of the buffer of the metadata that you want to use. The highest value is 1024 bytes. + /// Sets the maximum size of the media metadata. + /// After calling registerMediaMetadataObserver, you can call this method to set the maximum size of the media metadata. + /// + /// Param [size] The maximum size of media metadata. + /// Future setMaxMetadataSize(int size); - /// Sends the metadata. /// - /// **Parameter** [metadata] The metadata to be sent in the form of String. + /// Sends media metadata. + /// If the metadata is sent successfully, the SDK triggers the metadataReceived callback on the receiver. /// - /// **Note** + /// Param [metadata] Media metadata. See Metadata. /// - /// Ensure that the size of the metadata does not exceed the value set in the [setMaxMetadataSize] method. - Future sendMetadata(String metadata); + Future sendMetadata(Uint8List metadata); } /// @nodoc mixin RtcEncryptionInterface { - /// Enables built-in encryption with an encryption password before joining a channel. - /// - /// **Deprecated** /// - /// This method is deprecated. Use [RtcChannel.enableEncryption] instead. + /// Enables built-in encryption with an encryption password before users join a channel. + /// Do not use this method for CDN live streaming. + /// For optimal transmission, ensure that the encrypted data size does not exceed the original data size + 16 bytes. 16 bytes is the maximum padding size for AES encryption. + /// + /// + /// Before joining the channel, you need to call this method to set the secret parameter to enable the built-in encryption. All users in the same channel should use the same secret. The secret is automatically cleared once a user leaves the channel. If you do not specify the secret or secret is set as null, the built-in encryption is disabled. + /// + /// + /// Deprecated: + /// Please use the enableEncryption method instead. /// - /// All users in a channel must set the same encryption password. The encryption password is automatically cleared once a user leaves the channel. If the encryption password is not specified or set to empty, the encryption functionality is disabled. + /// Param [secret] The encryption password. /// - /// **Note** - /// - For optimal transmission, ensure that the encrypted data size does not exceed the original data size + 16 bytes. 16 bytes is the maximum padding size for AES encryption. - /// - Do not use this method for CDN live streaming. - /// - /// **Parameter** [secret] The encryption password. @deprecated Future setEncryptionSecret(String secret); - /// Sets the built-in encryption mode. /// - /// **Deprecated** - /// - /// This method is deprecated. Use [RtcChannel.enableEncryption] instead. - /// - /// The Agora SDK supports built-in encryption, which is set to aes-128-xts mode by default. Call this method to set the encryption mode to use other encryption modes. All users in the same channel must use the same encryption mode and password. - /// Refer to the information related to the AES encryption algorithm on the differences between the encryption modes. - /// - /// **Note** - /// - Do not use this method for CDN streaming. - /// - Before calling this method, ensure that you have called [RtcChannel.setEncryptionSecret] to enable encryption. + /// Sets the built-in encryption mode. + /// The Agora SDK supports built-in encryption. The default encryption is AES-128-XTS. Call this method to use other encryption modes. All users in the same channel must use the same encryption mode and secret. Refer to the information related to the AES encryption algorithm on the differences between the encryption modes. + /// + /// + /// Deprecated: + /// Please use the enableEncryption method instead. + /// + /// + /// Before calling this method, please call setEncryptionSecret to enable the built-in encryption function. + /// + /// Param [encryptionMode] Encryption mode. + /// "aes-128-xts": (Default) 128-bit AES encryption, XTS mode. + /// "aes-128-ecb": 128-bit AES encryption, ECB mode. + /// "aes-256-xts": 256-bit AES encryption, XTS mode. + /// "": When setting as NULL, the encryption mode is set as "aes-128-xts" by default. + /// + /// + /// /// - /// **Parameter** [encryptionMode] Sets the encryption mode. See [EncryptionMode]. @deprecated Future setEncryptionMode(EncryptionMode encryptionMode); - /// Enables/Disables the built-in encryption. - /// - /// In scenarios requiring high security, Agora recommends calling `enableEncryption` to enable the built-in encryption before joining a channel. /// - /// All users in the same channel must use the same encryption mode and encryption key. Once all users leave the channel, the encryption key of this channel is automatically cleared. + /// Enables/Disables the built-in encryption. + /// In scenarios requiring high security, Agora recommends calling this method to enable the built-in encryption before joining a channel. + /// All users in the same channel must use the same encryption mode and encryption key. After the user leaves the channel, the SDK automatically disables the built-in encryption. To enable the built-in encryption, call this method before the user joins the channel again. + /// If you enable the built-in encryption, you cannot use the RTMP or RTMPS streaming function. /// - /// **Note** - /// - If you enable the built-in encryption, you cannot use the RTMP or RTMPS streaming function. - /// - Agora supports four encryption modes. If you choose an encryption mode (excepting `SM4128ECB` mode), you need to add an external encryption library when integrating the SDK. For details, see the advanced guide *Channel Encryption*. + /// Param [enabled] Whether to enable built-in encryption: + /// true: Enable the built-in encryption. + /// false: Disable the built-in encryption. + /// + /// + /// /// + /// Param [config] Configurations of built-in encryption. For details, see EncryptionConfig. /// - /// **Parameter** [enabled] Whether to enable the built-in encryption. - /// - `true`: Enable the built-in encryption. - /// - `false`: Disable the built-in encryption. - /// **Parameter** [config] Configurations of built-in encryption schemas. See [EncryptionConfig]. Future enableEncryption(bool enabled, EncryptionConfig config); } /// @nodoc mixin RtcInjectStreamInterface { - /// Injects an online media stream to a [ChannelProfile.LiveBroadcasting] channel. - /// - /// If this method call succeeds, the server pulls the voice or video stream and injects it into a live channel. This applies to scenarios where all audience members in the channel can watch a live show and interact with each other. - /// - /// **Warning** - /// - /// Agora will soon stop the service for injecting online media streams on the client. If you have not implemented this service, Agora recommends that you do not use it. - /// - /// **Note** - /// - Ensure that you enable the RTMP Converter service before using this function. See Prerequisites in *Push Streams to CDN*. - /// - This method can only be called by a broadcaster in a [ChannelProfile.LiveBroadcasting] channel . - /// Calling this method triggers the following callbacks: - /// - The local client: - /// - [RtcChannelEventHandler.streamInjectedStatus], with the state of injecting the media stream. - /// - [RtcChannelEventHandler.userJoined](uid: 666), if the method call succeeds and the online media stream is injected into the channel. - /// - The remote client: - /// - [RtcChannelEventHandler.userJoined](uid: 666), if the method call succeeds and the online media stream is injected into the channel. /// - /// **Parameter** [url] The URL address to be added to the ongoing live broadcast. Valid protocols are RTMP, HLS, and FLV. - /// - Supported FLV audio codec type: AAC. - /// - Supported FLV video codec type: H264(AVC). + /// Injects an online media stream to a live streaming channel. + /// Agora will soon stop the service for injecting online media streams on the client. If you have not implemented this service, Agora recommends that you do not use it. For details, see Service Sunset Plans. + /// + /// + /// Ensure that you enable the RTMP Converter service before using this function. See Prerequisites in Push Streams to CDN. + /// This method takes effect only when you are a host in a live streaming channel. + /// Only one online media stream can be injected into the same channel at the same time. + /// Call this method after joining a channel. + /// + /// + /// This method injects the currently playing audio and video as audio and video sources into the + /// ongoing live broadcast. This applies to scenarios where all users in the channel can + /// watch a live show and interact with each other. After calling this method, the SDK + /// triggers the streamInjectedStatus callback on the local client to + /// report the state of injecting the online media stream; after successfully injecting + /// the media stream, the stream joins the channel, and all users in the channel receive + /// the userJoined callback, where uid is + /// 666. + /// + /// Param [url] The URL address to be added to the ongoing streaming. Valid protocols are RTMP, HLS, and HTTP-FLV. + /// Supported audio codec type: AAC. + /// Supported video codec type: H264 (AVC). + /// + /// + /// + /// + /// Param [config] The configuration information for the added voice or video stream: LiveInjectStreamConfig. /// - /// **Parameter** [config] The [LiveInjectStreamConfig] object, which contains the configuration information for the added voice or video stream. Future addInjectStreamUrl(String url, LiveInjectStreamConfig config); - /// Removes the injected online media stream from a [ChannelProfile.LiveBroadcasting] channel. /// - /// This method removes the URL address added by [RtcChannel.addInjectStreamUrl]. - /// If you successfully remove the URL address from the live broadcast, the SDK triggers the [RtcChannelEventHandler.userJoined] callback, with the stream uid of 666. + /// Removes the voice or video stream URL address from the live streaming. + /// After a successful method, the SDK triggers the userOffline callback + /// with the uid of 666. + /// + /// Param [url] The URL address of the injected stream to be removed. /// - /// **Parameter** [url] The URL address to be removed. Future removeInjectStreamUrl(String url); } /// @nodoc mixin RtcStreamMessageInterface { - /// Creates a data stream. - /// - /// Each user can create up to five data streams during the life cycle of the [RtcChannel] instance. - /// - /// **Deprecated** - /// - /// This method is deprecated from v3.3.1. /// - /// **Note** - /// - Set both the reliable and ordered parameters to true or false. Do not set one as true and the other as false. - /// - /// **Parameter** [reliable] Sets whether or not the recipients are guaranteed to receive the data stream from the sender within five seconds. - /// - `true`: The recipients receive the data from the sender within five seconds. If the recipient does not receive the data within five seconds, the SDK triggers the [RtcChannelEventHandler.streamMessageError] callback and returns an error code. - /// - `false`: There is no guarantee that the recipients receive the data stream within five seconds and no error message is reported for any delay or missing data stream. - /// - /// **Parameter** [ordered] Determines whether or not the recipients receive the data stream in the sent order. - /// - `true`: The recipients receive the data in the sent order. - /// - `false`: The recipients do not receive the data in the sent order. + /// Creates a data stream. + /// Call this method after joining a channel. + /// Agora does not support setting reliable as true and ordered as true. + /// + /// + /// Each user can create up to five data streams during the lifecycle of RtcEngine. + /// + /// + /// Deprecated: + /// Please use createDataStreamWithConfig instead. + /// + /// Param [ordered] Whether or not the recipients receive the data stream in the sent order: + /// true: The recipients receive the data in the sent order. + /// false: The recipients do not receive the data in the sent order. + /// + /// + /// Param [reliable] Whether or not the data stream is reliable: + /// true: The recipients receive the + /// data from the sender within five seconds. If the recipient does not + /// receive the data within five seconds, the SDK triggers the streamMessageError callback and returns an + /// error code. + /// false: There is no guarantee that + /// the recipients receive the data stream within five seconds and no + /// error message is reported for any delay or missing data stream. + /// + /// /// - /// **Returns** - /// - 0: Success. - /// - < 0: Failure. @deprecated Future createDataStream(bool reliable, bool ordered); - /// Creates a data stream. /// - /// Since v3.3.1. - /// - /// Each user can create up to five data streams in a single channel. + /// Creates a data stream. + /// Compared with createDataStream[1/2], this method does not support data reliability. If a data packet is not received five seconds after it was sent, the SDK directly discards the data. + /// Creates a data stream. Each user can create up to five data streams in a single channel. /// - /// This method does not support data reliability. If the receiver receives a data packet five seconds or more after it was sent, the SDK directly discards the data. + /// Param [config] The configurations for the data stream. For details, see DataStreamConfig. /// - /// **Parameter** [config] The configurations for the data stream: [DataStreamConfig]. + /// **return** ID of the created data stream, if the method call succeeds. + /// < 0: Failure. /// - /// **Returns** - /// - Returns the stream ID if you successfully create the data stream. - /// - < 0: Fails to create the data stream. Future createDataStreamWithConfig(DataStreamConfig config); - /// Sends the data stream message. /// - /// The SDK has the following restrictions on this method: - /// - Up to 30 packets can be sent per second in a channel with each packet having a maximum size of 1 KB. - /// - Each client can send up to 6 KB of data per second. - /// - Each user can have up to five data channels simultaneously. + /// Sends data stream messages. + /// Sends data stream messages to all users in a channel. The SDK has the following restrictions on this method:Up to 30 packets can be sent per second in a channel with each packet having a maximum size of 1 KB.Each client can send up to 6 KB of data per second.Each user can have up to five data streams simultaneously. + /// A successful method call triggers the streamMessage callback on the remote client, from which the remote user gets the stream message. A failed method call triggers the streamMessageError callback on the remote client. + /// + /// Ensure that you call createDataStreamWithConfig to create a data channel before calling this method. + /// In live streaming scenarios, this method only applies to hosts. /// - /// A successful method call triggers the [RtcChannelEventHandler.streamMessage] callback on the remote client, from which the remote user gets the stream message. - /// A failed method call triggers the [RtcChannelEventHandler.streamMessageError] callback on the remote client. + /// Param [streamId] The data stream ID. You can get the data stream ID by calling createDataStreamWithConfig. /// - /// **Parameter** [streamId] ID of the sent data stream returned by the [RtcChannel.createDataStream] method. + /// Param [message] The message to be sent. /// - /// **Parameter** [message] The message data. - Future sendStreamMessage(int streamId, String message); + Future sendStreamMessage(int streamId, Uint8List message); } diff --git a/lib/src/rtc_device_manager.dart b/lib/src/rtc_device_manager.dart new file mode 100644 index 000000000..b1ff63247 --- /dev/null +++ b/lib/src/rtc_device_manager.dart @@ -0,0 +1,437 @@ +import 'dart:async'; +import 'dart:convert'; + +import 'package:agora_rtc_engine/rtc_engine.dart'; +import 'package:flutter/services.dart'; + +enum _ApiTypeAudioDeviceManager { + kADMEnumeratePlaybackDevices, + kADMSetPlaybackDevice, + kADMGetPlaybackDevice, + kADMGetPlaybackDeviceInfo, + kADMSetPlaybackDeviceVolume, + kADMGetPlaybackDeviceVolume, + kADMSetPlaybackDeviceMute, + kADMGetPlaybackDeviceMute, + kADMStartPlaybackDeviceTest, + kADMStopPlaybackDeviceTest, + kADMEnumerateRecordingDevices, + kADMSetRecordingDevice, + kADMGetRecordingDevice, + kADMGetRecordingDeviceInfo, + kADMSetRecordingDeviceVolume, + kADMGetRecordingDeviceVolume, + kADMSetRecordingDeviceMute, + kADMGetRecordingDeviceMute, + kADMStartRecordingDeviceTest, + kADMStopRecordingDeviceTest, + kADMStartAudioDeviceLoopbackTest, + kADMStopAudioDeviceLoopbackTest, +} + +enum _ApiTypeVideoDeviceManager { + kVDMEnumerateVideoDevices, + kVDMSetDevice, + kVDMGetDevice, + kVDMStartDeviceTest, + kVDMStopDeviceTest, +} + +/// +/// The RTC device manager class, which manages the audio and video devices in the system. +/// +/// +class RtcDeviceManager { + static const MethodChannel _audioMethodChannel = + MethodChannel('agora_rtc_audio_device_manager'); + static const MethodChannel _videoMethodChannel = + MethodChannel('agora_rtc_video_device_manager'); + + Future _invokeAudioMethod(String method, + [Map? arguments]) { + return _audioMethodChannel.invokeMethod(method, arguments); + } + + Future _invokeVideoMethod(String method, + [Map? arguments]) { + return _videoMethodChannel.invokeMethod(method, arguments); + } + + /// + /// Enumerates the audio playback devices. + /// + /// + /// **return** Success: Returns a MediaDeviceInfo list that contains + /// the device ID and device name of all the audio playback devices. + /// Failure: null. + /// + Future> enumerateAudioPlaybackDevices() { + return _invokeAudioMethod('callApi', { + 'apiType': _ApiTypeAudioDeviceManager.kADMEnumeratePlaybackDevices.index, + 'params': jsonEncode({}), + }).then((value) => List.of( + List>.from(jsonDecode(value)).map((e) { + return MediaDeviceInfo.fromJson(e); + }))); + } + + /// + /// Sets the audio playback device. + /// + /// + /// Param [deviceId] The ID of the audio playback device. You can get the device ID by calling enumerateAudioPlaybackDevices. Plugging or unplugging the audio device does not change the device ID. + /// + /// + Future setAudioPlaybackDevice(String deviceId) { + return _invokeAudioMethod('callApi', { + 'apiType': _ApiTypeAudioDeviceManager.kADMSetPlaybackDevice.index, + 'params': jsonEncode({ + 'deviceId': deviceId, + }), + }); + } + + /// + /// Retrieves the audio playback device associated with the device ID. + /// + /// + /// **return** The current audio playback device. + /// + Future getAudioPlaybackDevice() { + return _invokeAudioMethod('callApi', { + 'apiType': _ApiTypeAudioDeviceManager.kADMGetPlaybackDevice.index, + 'params': jsonEncode({}), + }); + } + + /// + /// Retrieves the audio playback device information associated with the device ID and device name. + /// + /// + /// **return** A MediaDeviceInfo class, which includes the device ID and the device name. + /// + Future getAudioPlaybackDeviceInfo() { + return _invokeAudioMethod('callApi', { + 'apiType': _ApiTypeAudioDeviceManager.kADMGetPlaybackDeviceInfo.index, + 'params': jsonEncode({}), + }).then((value) => MediaDeviceInfo.fromJson(jsonDecode(value))); + } + + /// + /// Sets the volume of the audio playback device. + /// + /// + /// Param [volume] The volume of the audio playback device. The value ranges between 0 (lowest volume) and 255 (highest volume). + /// + Future setAudioPlaybackDeviceVolume(int volume) { + return _invokeAudioMethod('callApi', { + 'apiType': _ApiTypeAudioDeviceManager.kADMSetPlaybackDeviceVolume.index, + 'params': jsonEncode({ + 'volume': volume, + }), + }); + } + + /// + /// Retrieves the volume of the audio playback device. + /// + /// + /// **return** The volume of the audio playback device. The value ranges between 0 (lowest volume) and 255 (highest volume). + /// + Future getAudioPlaybackDeviceVolume() { + return _invokeAudioMethod('callApi', { + 'apiType': _ApiTypeAudioDeviceManager.kADMGetPlaybackDeviceVolume.index, + 'params': jsonEncode({}), + }).then((value) => int.tryParse(value)); + } + + /// + /// Mutes the audio playback device. + /// + /// + /// Param [mute] Whether to mute the audio playback device: + /// true: Mute the audio playback device. + /// false: Unmute the audio playback device. + /// + /// + Future setAudioPlaybackDeviceMute(bool mute) { + return _invokeAudioMethod('callApi', { + 'apiType': _ApiTypeAudioDeviceManager.kADMSetPlaybackDeviceMute.index, + 'params': jsonEncode({ + 'mute': mute, + }), + }); + } + + /// + /// Retrieves whether the audio playback device is muted. + /// + /// + /// **return** true: The audio playback device is muted. + /// false: The audio playback device is unmuted. + /// + Future getAudioPlaybackDeviceMute() { + return _invokeAudioMethod('callApi', { + 'apiType': _ApiTypeAudioDeviceManager.kADMGetPlaybackDeviceMute.index, + 'params': jsonEncode({}), + }).then((value) => value == 'true'); + } + + /// + /// Starts the audio playback device test. + /// This method tests whether the audio playback device works properly. Once a user starts the test, the SDK plays an audio file specified by the user. If the user can hear the audio, the playback device works properly. + /// After calling this method, the SDK triggers the audioVolumeIndication callback every 100 ms, reporting uid = 1 and the volume information of the playback device. + /// Ensure that you call this method before joining a channel. + /// + /// Param [testAudioFilePath] The path of the audio file for the audio playback device test in UTF-8. + /// Supported file formats: wav, mp3, m4a, and aac. + /// Supported file sample rates: 8000, 16000, 32000, 44100, and 48000 Hz. + /// + /// + Future startAudioPlaybackDeviceTest(String testAudioFilePath) { + return _invokeAudioMethod('callApi', { + 'apiType': _ApiTypeAudioDeviceManager.kADMStartPlaybackDeviceTest.index, + 'params': jsonEncode({ + 'testAudioFilePath': testAudioFilePath, + }), + }); + } + + /// + /// Stops the audio playback device test. + /// This method stops the audio playback device test. You must call this method to stop the test after calling the startAudioPlaybackDeviceTest method. + /// Ensure that you call this method before joining a channel. + /// + Future stopAudioPlaybackDeviceTest() { + return _invokeAudioMethod('callApi', { + 'apiType': _ApiTypeAudioDeviceManager.kADMStopPlaybackDeviceTest.index, + 'params': jsonEncode({}), + }); + } + + /// + /// Enumerates the audio capture devices. + /// + /// + /// **return** Success: Returns a MediaDeviceInfo list that contains the device ID and device name of all the audio recording devices. + /// Failure: null. + /// + Future> enumerateAudioRecordingDevices() { + return _invokeAudioMethod('callApi', { + 'apiType': _ApiTypeAudioDeviceManager.kADMEnumerateRecordingDevices.index, + 'params': jsonEncode({}), + }).then((value) => List.of( + List>.from(jsonDecode(value)).map((e) { + return MediaDeviceInfo.fromJson(e); + }))); + } + + /// + /// Sets the audio capture device. + /// + /// + /// Param [deviceId] The ID of the audio capture device. You can get the device ID by calling enumerateAudioRecordingDevices. Plugging or unplugging the audio device does not change the device ID. + /// + /// + Future setAudioRecordingDevice(String deviceId) { + return _invokeAudioMethod('callApi', { + 'apiType': _ApiTypeAudioDeviceManager.kADMSetRecordingDevice.index, + 'params': jsonEncode({ + 'deviceId': deviceId, + }), + }); + } + + /// + /// Gets the current audio recording device. + /// + /// + /// **return** The current audio recording device. + /// + Future getAudioRecordingDevice() { + return _invokeAudioMethod('callApi', { + 'apiType': _ApiTypeAudioDeviceManager.kADMGetRecordingDevice.index, + 'params': jsonEncode({}), + }); + } + + /// + /// Retrieves the audio capture device information associated with the device ID and device name. + /// + /// + /// **return** A MediaDeviceInfo class that contains the device ID and device name of all the audio recording devices. + /// + Future getAudioRecordingDeviceInfo() { + return _invokeAudioMethod('callApi', { + 'apiType': _ApiTypeAudioDeviceManager.kADMGetRecordingDeviceInfo.index, + 'params': jsonEncode({}), + }).then((value) => + value != null ? MediaDeviceInfo.fromJson(jsonDecode(value)) : null); + } + + /// + /// Sets the volume of the audio capture device. + /// + /// + /// Param [volume] The volume of the audio recording device. The value ranges between 0 (lowest volume) and 255 (highest volume). + /// + Future setAudioRecordingDeviceVolume(int volume) { + return _invokeAudioMethod('callApi', { + 'apiType': _ApiTypeAudioDeviceManager.kADMSetRecordingDeviceVolume.index, + 'params': jsonEncode({ + 'volume': volume, + }), + }); + } + + /// + /// Retrieves the volume of the audio recording device. + /// + /// + /// **return** The volume of the audio recording device. The value ranges between 0 (lowest volume) and 255 (highest volume). + /// + Future getAudioRecordingDeviceVolume() { + return _invokeAudioMethod('callApi', { + 'apiType': _ApiTypeAudioDeviceManager.kADMGetRecordingDeviceVolume.index, + 'params': jsonEncode({}), + }).then((value) => int.tryParse(value)); + } + + /// + /// Sets the mute status of the audio capture device. + /// + /// + /// Param [mute] Whether to mute the audio capture device: + /// true: Mute the audio capture device. + /// false: Unmute the audio capture device. + /// + /// + Future setAudioRecordingDeviceMute(bool mute) { + return _invokeAudioMethod('callApi', { + 'apiType': _ApiTypeAudioDeviceManager.kADMSetRecordingDeviceMute.index, + 'params': jsonEncode({ + 'mute': mute, + }), + }); + } + + /// + /// Gets the microphone's mute status. + /// + /// + /// **return** true: The microphone is muted. + /// false: The microphone is unmuted. + /// + Future getAudioRecordingDeviceMute() { + return _invokeAudioMethod('callApi', { + 'apiType': _ApiTypeAudioDeviceManager.kADMGetRecordingDeviceMute.index, + 'params': jsonEncode({}), + }).then((value) => value == 'true'); + } + + /// + /// Starts the audio capture device test. + /// This method tests whether the audio capture device works properly. After calling this method, the SDK triggers the audioVolumeIndication callback at the time interval set in this method, which reports uid = 0 and the volume information of the capture device. + /// Ensure that you call this method before joining a channel. + /// + /// Param [indicationInterval] The time interval (ms) at which the SDK triggers the audioVolumeIndication callback. Agora recommends a setting greater than 200 ms. This value must not be less than 10 ms; otherwise, you can not receive the audioVolumeIndication callback. + /// + Future startAudioRecordingDeviceTest(int indicationInterval) { + return _invokeAudioMethod('callApi', { + 'apiType': _ApiTypeAudioDeviceManager.kADMStartRecordingDeviceTest.index, + 'params': jsonEncode({ + 'indicationInterval': indicationInterval, + }), + }); + } + + /// + /// Stops the audio capture device test. + /// This method stops the audio capture device test. You must call this method to stop the test after calling the startAudioRecordingDeviceTest method. + /// Ensure that you call this method before joining a channel. + /// + Future stopAudioRecordingDeviceTest() { + return _invokeAudioMethod('callApi', { + 'apiType': _ApiTypeAudioDeviceManager.kADMStopRecordingDeviceTest.index, + 'params': jsonEncode({}), + }); + } + + /// + /// Starts an audio device loopback test. + /// This method tests whether the local audio capture device and playback device are working properly. After starting the test, the audio capture device records the local audio, and the audio playback device plays the captured audio. The SDK triggers two independent audioVolumeIndication callbacks at the time interval set in this method, which reports the volume information of the capture device (uid = 0) and the volume information of the playback device (uid = 1) respectively. + /// + /// Ensure that you call this method before joining a channel. + /// This method tests local audio devices and does not report the network conditions. + /// + /// Param [indicationInterval] The time interval (ms) at which the SDK triggers the audioVolumeIndication callback. Agora recommends a setting greater than 200 ms. This value must not be less than 10 ms; otherwise, you can not receive the audioVolumeIndication callback. + /// + Future startAudioDeviceLoopbackTest(int indicationInterval) { + return _invokeAudioMethod('callApi', { + 'apiType': + _ApiTypeAudioDeviceManager.kADMStartAudioDeviceLoopbackTest.index, + 'params': jsonEncode({ + 'indicationInterval': indicationInterval, + }), + }); + } + + /// + /// Stops the audio device loopback test. + /// Ensure that you call this method before joining a channel. + /// Ensure that you call this method to stop the loopback test after calling the startAudioDeviceLoopbackTest method. + /// + Future stopAudioDeviceLoopbackTest() { + return _invokeAudioMethod('callApi', { + 'apiType': + _ApiTypeAudioDeviceManager.kADMStopAudioDeviceLoopbackTest.index, + 'params': jsonEncode({}), + }); + } + + /// + /// Enumerates the video devices. + /// + /// + /// **return** Success: Returns a MediaDeviceInfo that contains all the video devices. + /// Failure: null. + /// + Future> enumerateVideoDevices() { + return _invokeVideoMethod('callApi', { + 'apiType': _ApiTypeVideoDeviceManager.kVDMEnumerateVideoDevices.index, + 'params': jsonEncode({}), + }).then((value) => List.of( + List>.from(jsonDecode(value)).map((e) { + return MediaDeviceInfo.fromJson(e); + }))); + } + + /// + /// Specifies the video capture device with the device ID. + /// Plugging or unplugging a device does not change its device ID. + /// + /// Param [deviceId] The device ID. You can get the device ID by calling enumerateVideoDevices. + /// + /// + Future setVideoDevice(String deviceId) { + return _invokeVideoMethod('callApi', { + 'apiType': _ApiTypeVideoDeviceManager.kVDMSetDevice.index, + 'params': jsonEncode({ + 'deviceId': deviceId, + }), + }); + } + + /// + /// Retrieves the current video capture device. + /// + /// + /// **return** The video capture device. + /// + Future getVideoDevice() { + return _invokeVideoMethod('callApi', { + 'apiType': _ApiTypeVideoDeviceManager.kVDMGetDevice.index, + 'params': jsonEncode({}), + }); + } +} diff --git a/lib/src/rtc_engine.dart b/lib/src/rtc_engine.dart index 3dca9df77..b17a388e0 100644 --- a/lib/src/rtc_engine.dart +++ b/lib/src/rtc_engine.dart @@ -1,5 +1,9 @@ import 'dart:async'; +import 'dart:convert'; +import 'dart:io'; +import 'dart:typed_data'; +import 'package:flutter/foundation.dart'; import 'package:flutter/services.dart'; import 'classes.dart'; @@ -7,8 +11,13 @@ import 'enum_converter.dart'; import 'enums.dart'; import 'events.dart'; import 'rtc_channel.dart'; +import 'rtc_device_manager.dart'; +import 'api_types.dart'; -/// RtcEngine is the main class of the Agora SDK. +/// +/// The basic interface of the Agora SDK that implements the core functions of real-time communication. +/// RtcEngine provides the main methods that your app can call. +/// class RtcEngine with RtcEngineInterface { static const MethodChannel _methodChannel = MethodChannel('agora_rtc_engine'); static const EventChannel _eventChannel = @@ -24,182 +33,233 @@ class RtcEngine with RtcEngineInterface { /// Get the singleton of [RtcEngine]. static RtcEngine? get instance => _instance; + final bool _subProcess; + final String? _appGroup; + RtcEngineContext? _rtcEngineContext; + RtcEngine? _screenShareHelper; + + /// + /// Gets a child process object. + /// + /// + /// Param [appGroup] The app group. + /// + /// **return** A child process object, which can be used in scenarios such as screen sharing. + /// + Future getScreenShareHelper({String? appGroup}) async { + if (!kIsWeb && (Platform.isAndroid || Platform.isIOS)) { + throw PlatformException(code: ErrorCode.NotSupported.toString()); + } + if (_subProcess) { + throw PlatformException(code: ErrorCode.TooOften.toString()); + } + _screenShareHelper ??= () { + var engine = RtcEngine._(true, appGroup: appGroup); + engine.initialize(_rtcEngineContext!); + return engine; + }(); + return _screenShareHelper!; + } + + final RtcDeviceManager _deviceManager = RtcDeviceManager(); + + /// + /// Gets the RtcDeviceManager class. + /// + /// + /// **return** The RtcDeviceManager class. + /// + RtcDeviceManager get deviceManager { + if (!kIsWeb && (Platform.isAndroid || Platform.isIOS)) { + throw PlatformException(code: ErrorCode.NotSupported.toString()); + } + return _deviceManager; + } + RtcEngineEventHandler? _handler; - RtcEngine._(); + RtcEngine._(this._subProcess, {String? appGroup}) : _appGroup = appGroup; Future _invokeMethod(String method, [Map? arguments]) { + if (kIsWeb || (Platform.isWindows || Platform.isMacOS)) { + arguments?['subProcess'] = _subProcess; + } return _methodChannel.invokeMethod(method, arguments); } - /// Retrieves the SDK version. - /// - /// Since v3.3.1 /// - /// This method returns the string of the version number. + /// Gets the SDK version. /// - /// **Note** /// - /// You can call this method either before or after joining a channel. - /// - /// **Returns** + /// **return** The SDK version number. The format is a string. /// - /// The version of the current SDK in the string format. For example, 2.3.0. - static Future getSdkVersion() { - return RtcEngine.methodChannel.invokeMethod('getSdkVersion'); + Future getSdkVersion() { + return RtcEngine.methodChannel.invokeMethod('callApi', { + 'apiType': ApiTypeEngine.kEngineGetVersion.index, + 'params': jsonEncode({}), + }); } - /// Retrieves the description of a warning or error code. /// - /// Since v3.3.1 + /// Gets the warning or error description. + /// /// - /// **Parameter** [error] The warning or error code that the `Warning` or `Error` callback returns. + /// Param [error] The error code or warning code reported by the SDK. /// - /// **Returns** + /// **return** The specific error or warning description. /// - /// [WarningCode] or [ErrorCode]. - static Future getErrorDescription(int error) { - return RtcEngine.methodChannel.invokeMethod('getErrorDescription', { - 'error': error, + Future getErrorDescription(int error) { + return RtcEngine.methodChannel.invokeMethod('callApi', { + 'apiType': ApiTypeEngine.kEngineGetErrorDescription.index, + 'params': jsonEncode({ + 'code': error, + }), }); } - /// Creates an [RtcEngine] instance. /// - /// Unless otherwise specified, all the methods provided by the RtcEngine class are executed asynchronously. Agora recommends calling these methods in the same thread. + /// Creates the RtcEngine object. + /// Deprecated: + /// This method is deprecated. Use createWithContext instead. /// - /// **Note** - /// - You must create an [RtcEngine] instance before calling any other method. - /// - You can create an [RtcEngine] instance either by calling this method or by calling [RtcEngine.createWithAreaCode]. The difference between [RtcEngine.createWithAreaCode] and this method is that [RtcEngine.createWithAreaCode] enables you to specify the connection area. - /// - The RTC Flutter SDK supports creating only one [RtcEngine] instance for an app for now. + /// Param [appId] The Agora App ID of your Agora project. /// - /// **Parameter** [appId] The App ID issued to you by Agora. See How to get the App ID. Only users in apps with the same App ID can join the same channel and communicate with each other. Use an App ID to create only one [RtcEngine] instance. To change your App ID, call destroy to destroy the current [RtcEngine] instance, and after destroy returns 0, call create to create an [RtcEngine] instance with the new App ID. + /// **return** The RtcEngine instance, if the method call succeeds. + /// An error code, if the call fails. /// - /// **Returns** - /// - An [RtcEngine] instance if the method call succeeds. - /// - The error code, if this method call fails: - /// - [ErrorCode.InvalidAppId] static Future create(String appId) { return createWithContext(RtcEngineContext(appId)); } - /// Creates an [RtcEngine] instance. - /// - /// **Deprecated** - /// - /// This method is deprecated since v3.3.1. - /// - /// Unless otherwise specified, all the methods provided by the RtcEngine class are executed asynchronously. Agora recommends calling these methods in the same thread. - /// - /// **Note** - /// - You must create an [RtcEngine] instance before calling any other method. - /// - You can create an [RtcEngine] instance either by calling this method or by calling [RtcEngine.create]. The difference between [RtcEngine.create] and this method is that this method enables you to specify the connection area. - /// - The Agora RTC Native SDK supports creating only one [RtcEngine] instance for an app for now. /// - /// **Parameter** [appId] The App ID issued to you by Agora. See How to get the App ID. Only users in apps with the same App ID can join the same channel and communicate with each other. Use an App ID to create only one [RtcEngine] instance. To change your App ID, call destroy to destroy the current [RtcEngine] instance and after destroy returns 0, call create to create an [RtcEngine] instance with the new App ID. + /// Initializes the RtcEngine object. + /// Deprecated: + /// This method is deprecated. Use createWithContext instead. /// - /// **Parameter** [areaCode] The area of connection. This advanced feature applies to scenarios that have regional restrictions. + /// Param [appId] The App ID of your Agora project. /// - /// For details, see [AreaCode]. + /// Param [areaCode] The area code. For details, see AreaCode. /// - /// After specifying the area of connection: - /// - When the app that integrates the Agora SDK is used within the specified area, it connects to the Agora servers within the specified area under normal circumstances. - /// - When the app that integrates the Agora SDK is used out of the specified area, it connects to the Agora servers either in the specified area or in the area where the app is located. + /// **return** The RtcEngine instance, if the method call succeeds. + /// An error code, if the call fails. /// - /// **Returns** - /// - An [RtcEngine] instance if the method call succeeds. - /// - The error code, if this method call fails: - /// - [ErrorCode.InvalidAppId] @deprecated static Future createWithAreaCode( String appId, List areaCode) { return createWithContext(RtcEngineContext(appId, areaCode: areaCode)); } - /// Creates an [RtcEngine] instance and specifies the connection area. /// - /// Since v3.3.1 + /// Initializes the RtcEngine object. + /// Deprecated: + /// This method is deprecated. Use createWithContext instead. /// - /// Unless otherwise specified, all the methods provided by the [RtcEngine] instance are executed asynchronously. Agora recommends calling these methods in the same thread. + /// Param [config] The RtcEngine configuraiton. For details, see RtcEngineContext. /// - /// **Note** - /// - You must create the [RtcEngine] instance before calling any other method. - /// - You can create an [RtcEngine] instance either by calling this method or by calling [create]. The difference between [create] and this method is that this method enables you to specify the region for connection. - /// - The Agora RTC Native SDK supports creating only one [RtcEngine] instance for an app for now. - /// - /// **Parameter**[config] Configurations for the [RtcEngine] instance. For details, see [RtcEngineConfig]. - /// - /// **Returns** - /// - An [RtcEngine] instance if the method call succeeds. - /// - The error code, if this method call fails: - /// - [ErrorCode.InvalidAppId] @deprecated static Future createWithConfig(RtcEngineConfig config) async { return createWithContext(config); } - /// Creates an [RtcEngine] instance and specifies one or multiple connection areas. /// - /// Since v4.0.5 + /// Initializes RtcEngine. + /// All called methods provided by the RtcEngine class are executed asynchronously. We recommend calling these methods in the same thread. /// - /// Unless otherwise specified, all the methods provided by the [RtcEngine] instance are executed asynchronously. Agora recommends calling these methods in the same thread. /// - /// **Note** - /// - You must create the [RtcEngine] instance before calling any other method. - /// - The Agora RTC Native SDK supports creating only one [RtcEngine] instance for an app for now. + /// Before calling other APIs, you must call create and createWithContext to create and initialize an RtcEngine object. + /// The SDK supports creating only one RtcEngine instance for an app. /// - /// **Parameter**[context] Configurations for the [RtcEngine] instance. For details, see [RtcEngineContext]. + /// Param [config] Configurations for the RtcEngine instance. For details, see RtcEngineContext. /// - /// **Returns** - /// - An [RtcEngine] instance if the method call succeeds. - /// - The error code, if this method call fails: - /// - [ErrorCode.InvalidAppId] - static Future createWithContext(RtcEngineContext context) async { + /// + static Future createWithContext(RtcEngineContext config) async { if (_instance != null) return _instance!; - _instance = RtcEngine._(); - await _instance!._invokeMethod('create', { - 'config': context.toJson(), - 'appType': 4, - }); + _instance = RtcEngine._(false); + await _instance!.initialize(config); return _instance!; } + @override + Future initialize(RtcEngineContext context) { + _rtcEngineContext = context; + return _invokeMethod('callApi', { + 'apiType': ApiTypeEngine.kEngineInitialize.index, + 'params': jsonEncode({ + 'context': context.toJson(), + 'appGroup': _appGroup, + }), + }).then((value) => _invokeMethod('callApi', { + 'apiType': ApiTypeEngine.kEngineSetAppType.index, + 'params': jsonEncode({ + 'appType': 4, + }), + })); + } + + // TODO(littlegnal): Fill test @override Future destroy() { - RtcChannel.destroyAll(); - _instance?._handler = null; - _instance = null; - return _invokeMethod('destroy'); + _rtcEngineContext = null; + if (_subProcess) { + _handler = null; + instance?._screenShareHelper = null; + } else { + _screenShareHelper?.destroy(); + RtcChannel.destroyAll(); + _instance?._handler = null; + _instance = null; + } + return _invokeMethod('callApi', { + 'apiType': ApiTypeEngine.kEngineRelease.index, + 'params': jsonEncode({ + 'sync': true, + }), + }); } - /// Sets the engine event handler. /// - /// After setting the engine event handler, you can listen for engine events and receive the statistics of the corresponding [RtcEngine] instance. + /// Adds event handlers + /// The SDK uses the RtcEngineEventHandler class to send callbacks to the app. The app inherits the methods of this class to receive these callbacks. All methods in this interface class have default (empty) implementations. Therefore, the application can only inherit some required events. In the callbacks, avoid time-consuming tasks or calling APIs that can block the thread, such as the sendStreamMessage method. Otherwise, the SDK may not work properly. /// - /// **Parameter** [handler] The event handler. + /// Param [handler] Callback events to be added. For details, see RtcEngineEventHandler. + /// + // TODO(littlegnal): Fill test void setEventHandler(RtcEngineEventHandler handler) { _handler = handler; _subscription ??= _stream.listen((event) { final eventMap = Map.from(event); final methodName = eventMap['methodName'] as String; final data = eventMap['data']; - _instance?._handler?.process(methodName, data); + final buffer = eventMap['buffer']; + final subProcess = (eventMap['subProcess'] as bool?) ?? false; + if (subProcess) { + _instance?._screenShareHelper?._handler + ?.process(methodName, data, buffer); + } else { + _instance?._handler?.process(methodName, data, buffer); + } }); } @override Future setChannelProfile(ChannelProfile profile) { - return _invokeMethod('setChannelProfile', { - 'profile': ChannelProfileConverter(profile).value(), + return _invokeMethod('callApi', { + 'apiType': ApiTypeEngine.kEngineSetChannelProfile.index, + 'params': jsonEncode({ + 'profile': ChannelProfileConverter(profile).value(), + }), }); } @override Future setClientRole(ClientRole role, [ClientRoleOptions? options]) { - return _invokeMethod('setClientRole', { - 'role': ClientRoleConverter(role).value(), - 'options': options?.toJson(), + return _invokeMethod('callApi', { + 'apiType': ApiTypeEngine.kEngineSetClientRole.index, + 'params': jsonEncode({ + 'role': ClientRoleConverter(role).value(), + 'options': options?.toJson(), + }), }); } @@ -207,120 +267,174 @@ class RtcEngine with RtcEngineInterface { Future joinChannel( String? token, String channelName, String? optionalInfo, int optionalUid, [ChannelMediaOptions? options]) { - return _invokeMethod('joinChannel', { - 'token': token, - 'channelName': channelName, - 'optionalInfo': optionalInfo, - 'optionalUid': optionalUid, - 'options': options?.toJson(), + return _invokeMethod('callApi', { + 'apiType': ApiTypeEngine.kEngineJoinChannel.index, + 'params': jsonEncode({ + 'token': token?.isEmpty == true ? null : token, + 'channelId': channelName, + 'info': optionalInfo, + 'uid': optionalUid, + 'options': options?.toJson(), + }), }); } @override Future switchChannel(String? token, String channelName, [ChannelMediaOptions? options]) { - return _invokeMethod('switchChannel', { - 'token': token, - 'channelName': channelName, - 'options': options?.toJson(), + return _invokeMethod('callApi', { + 'apiType': ApiTypeEngine.kEngineSwitchChannel.index, + 'params': jsonEncode({ + 'token': token, + 'channelId': channelName, + 'options': options?.toJson(), + }), }); } @override Future leaveChannel() { - return _invokeMethod('leaveChannel'); + return _invokeMethod('callApi', { + 'apiType': ApiTypeEngine.kEngineLeaveChannel.index, + 'params': jsonEncode({}), + }); } @override Future renewToken(String token) { - return _invokeMethod('renewToken', { - 'token': token, + return _invokeMethod('callApi', { + 'apiType': ApiTypeEngine.kEngineRenewToken.index, + 'params': jsonEncode({ + 'token': token, + }), }); } @override @deprecated Future enableWebSdkInteroperability(bool enabled) { - return _invokeMethod('enableWebSdkInteroperability', { - 'enabled': enabled, + return _invokeMethod('callApi', { + 'apiType': ApiTypeEngine.kEngineEnableWebSdkInteroperability.index, + 'params': jsonEncode({ + 'enabled': enabled, + }), }); } @override Future getConnectionState() { - return _invokeMethod('getConnectionState').then((value) { + if (_subProcess) { + throw PlatformException(code: ErrorCode.NotSupported.toString()); + } + return _invokeMethod('callApi', { + 'apiType': ApiTypeEngine.kEngineGetConnectionState.index, + 'params': jsonEncode({}), + }).then((value) { return ConnectionStateTypeConverter.fromValue(value).e; }); } @override Future getCallId() { - return _invokeMethod('getCallId'); + return _invokeMethod('callApi', { + 'apiType': ApiTypeEngine.kEngineGetCallId.index, + 'params': jsonEncode({}), + }); } @override Future rate(String callId, int rating, {String? description}) { - return _invokeMethod('rate', { - 'callId': callId, - 'rating': rating, - 'description': description, + return _invokeMethod('callApi', { + 'apiType': ApiTypeEngine.kEngineRate.index, + 'params': jsonEncode({ + 'callId': callId, + 'rating': rating, + 'description': description, + }), }); } @override Future complain(String callId, String description) { - return _invokeMethod('complain', { - 'callId': callId, - 'description': description, + return _invokeMethod('callApi', { + 'apiType': ApiTypeEngine.kEngineComplain.index, + 'params': jsonEncode({ + 'callId': callId, + 'description': description, + }), }); } @override @deprecated Future setLogFile(String filePath) { - return _invokeMethod('setLogFile', { - 'filePath': filePath, + return _invokeMethod('callApi', { + 'apiType': ApiTypeEngine.kEngineSetLogFile.index, + 'params': jsonEncode({ + 'filePath': filePath, + }), }); } @override @deprecated Future setLogFilter(LogFilter filter) { - return _invokeMethod('setLogFilter', { - 'filter': LogFilterConverter(filter).value(), + return _invokeMethod('callApi', { + 'apiType': ApiTypeEngine.kEngineSetLogFilter.index, + 'params': jsonEncode({ + 'filter': LogFilterConverter(filter).value(), + }), }); } @override @deprecated Future setLogFileSize(int fileSizeInKBytes) { - return _invokeMethod('setLogFileSize', { - 'fileSizeInKBytes': fileSizeInKBytes, + return _invokeMethod('callApi', { + 'apiType': ApiTypeEngine.kEngineSetLogFileSize.index, + 'params': jsonEncode({ + 'fileSizeInKBytes': fileSizeInKBytes, + }), }); } @override Future setParameters(String parameters) { - return _invokeMethod('setParameters', { - 'parameters': parameters, + return _invokeMethod('callApi', { + 'apiType': ApiTypeEngine.kEngineSetParameters.index, + 'params': jsonEncode({ + 'parameters': parameters, + }), }); } @override Future getUserInfoByUid(int uid) { - return _invokeMethod('getUserInfoByUid', { - 'uid': uid, + if (_subProcess) { + throw PlatformException(code: ErrorCode.NotSupported.toString()); + } + return _invokeMethod('callApi', { + 'apiType': ApiTypeEngine.kEngineGetUserInfoByUid.index, + 'params': jsonEncode({ + 'uid': uid, + }), }).then((value) { - return UserInfo.fromJson(Map.from(value)); + return UserInfo.fromJson(Map.from(jsonDecode(value))); }); } @override Future getUserInfoByUserAccount(String userAccount) { - return _invokeMethod('getUserInfoByUserAccount', { - 'userAccount': userAccount, + if (_subProcess) { + throw PlatformException(code: ErrorCode.NotSupported.toString()); + } + return _invokeMethod('callApi', { + 'apiType': ApiTypeEngine.kEngineGetUserInfoByUserAccount.index, + 'params': jsonEncode({ + 'userAccount': userAccount, + }), }).then((value) { - return UserInfo.fromJson(Map.from(value)); + return UserInfo.fromJson(Map.from(jsonDecode(value))); }); } @@ -328,245 +442,366 @@ class RtcEngine with RtcEngineInterface { Future joinChannelWithUserAccount( String? token, String channelName, String userAccount, [ChannelMediaOptions? options]) { - return _invokeMethod('joinChannelWithUserAccount', { - 'token': token, - 'channelName': channelName, - 'userAccount': userAccount, - 'options': options?.toJson(), + return _invokeMethod('callApi', { + 'apiType': ApiTypeEngine.kEngineJoinChannelWithUserAccount.index, + 'params': jsonEncode({ + 'token': token, + 'channelId': channelName, + 'userAccount': userAccount, + 'options': options?.toJson(), + }), }); } @override Future registerLocalUserAccount(String appId, String userAccount) { - return _invokeMethod('registerLocalUserAccount', { - 'appId': appId, - 'userAccount': userAccount, + return _invokeMethod('callApi', { + 'apiType': ApiTypeEngine.kEngineRegisterLocalUserAccount.index, + 'params': jsonEncode({ + 'appId': appId, + 'userAccount': userAccount, + }), }); } @override Future adjustPlaybackSignalVolume(int volume) { - return _invokeMethod('adjustPlaybackSignalVolume', { - 'volume': volume, + return _invokeMethod('callApi', { + 'apiType': ApiTypeEngine.kEngineAdjustPlaybackSignalVolume.index, + 'params': jsonEncode({ + 'volume': volume, + }), }); } @override Future adjustRecordingSignalVolume(int volume) { - return _invokeMethod('adjustRecordingSignalVolume', { - 'volume': volume, + return _invokeMethod('callApi', { + 'apiType': ApiTypeEngine.kEngineAdjustRecordingSignalVolume.index, + 'params': jsonEncode({ + 'volume': volume, + }), }); } @override Future adjustUserPlaybackSignalVolume(int uid, int volume) { - return _invokeMethod('adjustUserPlaybackSignalVolume', { - 'uid': uid, - 'volume': volume, + return _invokeMethod('callApi', { + 'apiType': ApiTypeEngine.kEngineAdjustUserPlaybackSignalVolume.index, + 'params': jsonEncode({ + 'uid': uid, + 'volume': volume, + }), + }); + } + + @override + Future enableLoopbackRecording(bool enabled, {String? deviceName}) { + return _invokeMethod('callApi', { + 'apiType': ApiTypeEngine.kEngineEnableLoopBackRecording.index, + 'params': jsonEncode({ + 'enabled': enabled, + 'deviceName': deviceName, + }), }); } @override Future disableAudio() { - return _invokeMethod('disableAudio'); + return _invokeMethod('callApi', { + 'apiType': ApiTypeEngine.kEngineDisableAudio.index, + 'params': jsonEncode({}), + }); } @override Future enableAudio() { - return _invokeMethod('enableAudio'); + return _invokeMethod('callApi', { + 'apiType': ApiTypeEngine.kEngineEnableAudio.index, + 'params': jsonEncode({}), + }); } @override Future enableAudioVolumeIndication( int interval, int smooth, bool report_vad) { - return _invokeMethod('enableAudioVolumeIndication', { - 'interval': interval, - 'smooth': smooth, - 'report_vad': report_vad, + return _invokeMethod('callApi', { + 'apiType': ApiTypeEngine.kEngineEnableAudioVolumeIndication.index, + 'params': jsonEncode({ + 'interval': interval, + 'smooth': smooth, + 'report_vad': report_vad, + }), }); } @override Future enableLocalAudio(bool enabled) { - return _invokeMethod('enableLocalAudio', { - 'enabled': enabled, + return _invokeMethod('callApi', { + 'apiType': ApiTypeEngine.kEngineEnableLocalAudio.index, + 'params': jsonEncode({ + 'enabled': enabled, + }), }); } @override Future muteAllRemoteAudioStreams(bool muted) { - return _invokeMethod('muteAllRemoteAudioStreams', { - 'muted': muted, + return _invokeMethod('callApi', { + 'apiType': ApiTypeEngine.kEngineMuteAllRemoteAudioStreams.index, + 'params': jsonEncode({ + 'mute': muted, + }), }); } @override Future muteLocalAudioStream(bool muted) { - return _invokeMethod('muteLocalAudioStream', { - 'muted': muted, + return _invokeMethod('callApi', { + 'apiType': ApiTypeEngine.kEngineMuteLocalAudioStream.index, + 'params': jsonEncode({ + 'mute': muted, + }), }); } @override Future muteRemoteAudioStream(int uid, bool muted) { - return _invokeMethod('muteRemoteAudioStream', { - 'uid': uid, - 'muted': muted, + return _invokeMethod('callApi', { + 'apiType': ApiTypeEngine.kEngineMuteRemoteAudioStream.index, + 'params': jsonEncode({ + 'userId': uid, + 'mute': muted, + }), }); } @override Future setAudioProfile(AudioProfile profile, AudioScenario scenario) { - return _invokeMethod('setAudioProfile', { - 'profile': AudioProfileConverter(profile).value(), - 'scenario': AudioScenarioConverter(scenario).value(), + return _invokeMethod('callApi', { + 'apiType': ApiTypeEngine.kEngineSetAudioProfile.index, + 'params': jsonEncode({ + 'profile': AudioProfileConverter(profile).value(), + 'scenario': AudioScenarioConverter(scenario).value(), + }), }); } @override @deprecated Future setDefaultMuteAllRemoteAudioStreams(bool muted) { - return _invokeMethod('setDefaultMuteAllRemoteAudioStreams', { - 'muted': muted, + return _invokeMethod('callApi', { + 'apiType': ApiTypeEngine.kEngineSetDefaultMuteAllRemoteAudioStreams.index, + 'params': jsonEncode({ + 'mute': muted, + }), }); } @override Future disableVideo() { - return _invokeMethod('disableVideo'); + return _invokeMethod('callApi', { + 'apiType': ApiTypeEngine.kEngineDisableVideo.index, + 'params': jsonEncode({}), + }); } @override Future enableLocalVideo(bool enabled) { - return _invokeMethod('enableLocalVideo', { - 'enabled': enabled, + return _invokeMethod('callApi', { + 'apiType': ApiTypeEngine.kEngineEnableLocalVideo.index, + 'params': jsonEncode({ + 'enabled': enabled, + }), }); } @override Future enableVideo() { - return _invokeMethod('enableVideo'); + return _invokeMethod('callApi', { + 'apiType': ApiTypeEngine.kEngineEnableVideo.index, + 'params': jsonEncode({}), + }); } @override Future muteAllRemoteVideoStreams(bool muted) { - return _invokeMethod('muteAllRemoteVideoStreams', { - 'muted': muted, + return _invokeMethod('callApi', { + 'apiType': ApiTypeEngine.kEngineMuteAllRemoteVideoStreams.index, + 'params': jsonEncode({ + 'mute': muted, + }), }); } @override Future muteLocalVideoStream(bool muted) { - return _invokeMethod('muteLocalVideoStream', { - 'muted': muted, + return _invokeMethod('callApi', { + 'apiType': ApiTypeEngine.kEngineMuteLocalVideoStream.index, + 'params': jsonEncode({ + 'mute': muted, + }), }); } @override Future muteRemoteVideoStream(int uid, bool muted) { - return _invokeMethod('muteRemoteVideoStream', { - 'uid': uid, - 'muted': muted, + return _invokeMethod('callApi', { + 'apiType': ApiTypeEngine.kEngineMuteRemoteVideoStream.index, + 'params': jsonEncode({ + 'userId': uid, + 'mute': muted, + }), }); } @override Future setBeautyEffectOptions(bool enabled, BeautyOptions options) { - return _invokeMethod('setBeautyEffectOptions', { - 'enabled': enabled, - 'options': options.toJson(), + return _invokeMethod('callApi', { + 'apiType': ApiTypeEngine.kEngineSetBeautyEffectOptions.index, + 'params': jsonEncode({ + 'enabled': enabled, + 'options': options.toJson(), + }), }); } @override @deprecated Future setDefaultMuteAllRemoteVideoStreams(bool muted) { - return _invokeMethod('setDefaultMuteAllRemoteVideoStreams', { - 'muted': muted, + return _invokeMethod('callApi', { + 'apiType': ApiTypeEngine.kEngineSetDefaultMuteAllRemoteVideoStreams.index, + 'params': jsonEncode({ + 'mute': muted, + }), }); } @override Future setVideoEncoderConfiguration(VideoEncoderConfiguration config) { - return _invokeMethod('setVideoEncoderConfiguration', { - 'config': config.toJson(), + assert( + config.frameRate != VideoFrameRate.Min, + 'frameRate must be not be VideoFrameRate.Min', + ); + return _invokeMethod('callApi', { + 'apiType': ApiTypeEngine.kEngineSetVideoEncoderConfiguration.index, + 'params': jsonEncode({ + 'config': config.toJson(), + }), }); } @override Future startPreview() { - return _invokeMethod('startPreview'); + return _invokeMethod('callApi', { + 'apiType': ApiTypeEngine.kEngineStartPreview.index, + 'params': jsonEncode({}), + }); } @override Future stopPreview() { - return _invokeMethod('stopPreview'); + return _invokeMethod('callApi', { + 'apiType': ApiTypeEngine.kEngineStopPreview.index, + 'params': jsonEncode({}), + }); } @override Future adjustAudioMixingPlayoutVolume(int volume) { - return _invokeMethod('adjustAudioMixingPlayoutVolume', { - 'volume': volume, + return _invokeMethod('callApi', { + 'apiType': ApiTypeEngine.kEngineAdjustAudioMixingPlayoutVolume.index, + 'params': jsonEncode({ + 'volume': volume, + }), }); } @override Future adjustAudioMixingPublishVolume(int volume) { - return _invokeMethod('adjustAudioMixingPublishVolume', { - 'volume': volume, + return _invokeMethod('callApi', { + 'apiType': ApiTypeEngine.kEngineAdjustAudioMixingPublishVolume.index, + 'params': jsonEncode({ + 'volume': volume, + }), }); } @override Future adjustAudioMixingVolume(int volume) { - return _invokeMethod('adjustAudioMixingVolume', { - 'volume': volume, + return _invokeMethod('callApi', { + 'apiType': ApiTypeEngine.kEngineAdjustAudioMixingVolume.index, + 'params': jsonEncode({ + 'volume': volume, + }), }); } @override Future getAudioMixingCurrentPosition() { - return _invokeMethod('getAudioMixingCurrentPosition'); + return _invokeMethod('callApi', { + 'apiType': ApiTypeEngine.kEngineGetAudioMixingCurrentPosition.index, + 'params': jsonEncode({}), + }); } @override Future getAudioMixingDuration([String? filePath]) { - return _invokeMethod('getAudioMixingDuration', { - 'filePath': filePath, + return _invokeMethod('callApi', { + 'apiType': ApiTypeEngine.kEngineGetAudioMixingDuration.index, + 'params': jsonEncode({}), }); } @override - Future getAudioFileInfo(String filePath) { - return _invokeMethod('getAudioFileInfo', { - 'filePath': filePath, + Future getAudioFileInfo(String filePath) { + return _invokeMethod('callApi', { + 'apiType': ApiTypeEngine.kEngineGetAudioFileInfo.index, + 'params': jsonEncode({ + 'filePath': filePath, + }), }); } @override Future getAudioMixingPlayoutVolume() { - return _invokeMethod('getAudioMixingPlayoutVolume'); + return _invokeMethod('callApi', { + 'apiType': ApiTypeEngine.kEngineGetAudioMixingPlayoutVolume.index, + 'params': jsonEncode({}), + }); } @override Future getAudioMixingPublishVolume() { - return _invokeMethod('getAudioMixingPublishVolume'); + return _invokeMethod('callApi', { + 'apiType': ApiTypeEngine.kEngineGetAudioMixingPublishVolume.index, + 'params': jsonEncode({}), + }); } @override Future pauseAudioMixing() { - return _invokeMethod('pauseAudioMixing'); + return _invokeMethod('callApi', { + 'apiType': ApiTypeEngine.kEnginePauseAudioMixing.index, + 'params': jsonEncode({}), + }); } @override Future resumeAudioMixing() { - return _invokeMethod('resumeAudioMixing'); + return _invokeMethod('callApi', { + 'apiType': ApiTypeEngine.kEngineResumeAudioMixing.index, + 'params': jsonEncode({}), + }); } @override Future setAudioMixingPosition(int pos) { - return _invokeMethod('setAudioMixingPosition', { - 'pos': pos, + return _invokeMethod('callApi', { + 'apiType': ApiTypeEngine.kEngineSetAudioMixingPosition.index, + 'params': jsonEncode({ + 'pos': pos, + }), }); } @@ -574,430 +809,638 @@ class RtcEngine with RtcEngineInterface { Future startAudioMixing( String filePath, bool loopback, bool replace, int cycle, [int? startPos]) { - return _invokeMethod('startAudioMixing', { - 'filePath': filePath, - 'loopback': loopback, - 'replace': replace, - 'cycle': cycle, - 'startPos': startPos, + return _invokeMethod('callApi', { + 'apiType': ApiTypeEngine.kEngineStartAudioMixing.index, + 'params': jsonEncode({ + 'filePath': filePath, + 'loopback': loopback, + 'replace': replace, + 'cycle': cycle, + 'startPos': startPos, + }), }); } @override Future stopAudioMixing() { - return _invokeMethod('stopAudioMixing'); + return _invokeMethod('callApi', { + 'apiType': ApiTypeEngine.kEngineStopAudioMixing.index, + 'params': jsonEncode({}), + }); } @override Future addInjectStreamUrl(String url, LiveInjectStreamConfig config) { - return _invokeMethod('addInjectStreamUrl', { - 'url': url, - 'config': config.toJson(), + return _invokeMethod('callApi', { + 'apiType': ApiTypeEngine.kEngineAddInjectStreamUrl.index, + 'params': jsonEncode({ + 'url': url, + 'config': config.toJson(), + }), }); } @override Future addPublishStreamUrl(String url, bool transcodingEnabled) { - return _invokeMethod('addPublishStreamUrl', { - 'url': url, - 'transcodingEnabled': transcodingEnabled, + return _invokeMethod('callApi', { + 'apiType': ApiTypeEngine.kEngineAddPublishStreamUrl.index, + 'params': jsonEncode({ + 'url': url, + 'transcodingEnabled': transcodingEnabled, + }), }); } @override Future addVideoWatermark( String watermarkUrl, WatermarkOptions options) { - return _invokeMethod('addVideoWatermark', { - 'watermarkUrl': watermarkUrl, - 'options': options.toJson(), + return _invokeMethod('callApi', { + 'apiType': ApiTypeEngine.kEngineAddVideoWaterMark.index, + 'params': jsonEncode({ + 'watermarkUrl': watermarkUrl, + 'options': options.toJson(), + }), }); } @override Future clearVideoWatermarks() { - return _invokeMethod('clearVideoWatermarks'); + return _invokeMethod('callApi', { + 'apiType': ApiTypeEngine.kEngineClearVideoWaterMarks.index, + 'params': jsonEncode({}), + }); } @override Future createDataStream(bool reliable, bool ordered) { - return _invokeMethod('createDataStream', { - 'reliable': reliable, - 'ordered': ordered, + return _invokeMethod('callApi', { + 'apiType': ApiTypeEngine.kEngineCreateDataStream.index, + 'params': jsonEncode({ + 'reliable': reliable, + 'ordered': ordered, + }), }); } @override Future disableLastmileTest() { - return _invokeMethod('disableLastmileTest'); + return _invokeMethod('callApi', { + 'apiType': ApiTypeEngine.kEngineDisableLastMileTest.index, + 'params': jsonEncode({}), + }); } @override Future enableDualStreamMode(bool enabled) { - return _invokeMethod('enableDualStreamMode', { - 'enabled': enabled, + return _invokeMethod('callApi', { + 'apiType': ApiTypeEngine.kEngineEnableDualStreamMode.index, + 'params': jsonEncode({ + 'enabled': enabled, + }), }); } @override Future enableInEarMonitoring(bool enabled) { - return _invokeMethod('enableInEarMonitoring', { - 'enabled': enabled, + return _invokeMethod('callApi', { + 'apiType': ApiTypeEngine.kEngineEnableInEarMonitoring.index, + 'params': jsonEncode({ + 'enabled': enabled, + }), }); } @override Future enableLastmileTest() { - return _invokeMethod('enableLastmileTest'); + return _invokeMethod('callApi', { + 'apiType': ApiTypeEngine.kEngineEnableLastMileTest.index, + 'params': jsonEncode({}), + }); } @override Future enableSoundPositionIndication(bool enabled) { - return _invokeMethod('enableSoundPositionIndication', { - 'enabled': enabled, + return _invokeMethod('callApi', { + 'apiType': ApiTypeEngine.kEngineEnableSoundPositionIndication.index, + 'params': jsonEncode({ + 'enabled': enabled, + }), }); } @override Future getCameraMaxZoomFactor() { - return _invokeMethod('getCameraMaxZoomFactor'); + return _invokeMethod('callApi', { + 'apiType': ApiTypeEngine.kEngineGetCameraMaxZoomFactor.index, + 'params': jsonEncode({}), + }); } @override Future getEffectsVolume() { - return _invokeMethod('getEffectsVolume'); + return _invokeMethod('callApi', { + 'apiType': ApiTypeEngine.kEngineGetEffectsVolume.index, + 'params': jsonEncode({}), + }); } @override Future isCameraAutoFocusFaceModeSupported() { - return _invokeMethod('isCameraAutoFocusFaceModeSupported'); + return _invokeMethod('callApi', { + 'apiType': ApiTypeEngine.kEngineIsCameraAutoFocusFaceModeSupported.index, + 'params': jsonEncode({}), + }); } @override Future isCameraExposurePositionSupported() { - return _invokeMethod('isCameraExposurePositionSupported'); + return _invokeMethod('callApi', { + 'apiType': ApiTypeEngine.kEngineIsCameraExposurePositionSupported.index, + 'params': jsonEncode({}), + }); } @override Future isCameraFocusSupported() { - return _invokeMethod('isCameraFocusSupported'); + return _invokeMethod('callApi', { + 'apiType': ApiTypeEngine.kEngineIsCameraFocusSupported.index, + 'params': jsonEncode({}), + }); } @override Future isCameraTorchSupported() { - return _invokeMethod('isCameraTorchSupported'); + return _invokeMethod('callApi', { + 'apiType': ApiTypeEngine.kEngineIsCameraTorchSupported.index, + 'params': jsonEncode({}), + }); } @override Future isCameraZoomSupported() { - return _invokeMethod('isCameraZoomSupported'); + return _invokeMethod('callApi', { + 'apiType': ApiTypeEngine.kEngineIsCameraZoomSupported.index, + 'params': jsonEncode({}), + }).then((v) => v == 1 ? true : false); } @override Future isSpeakerphoneEnabled() { - return _invokeMethod('isSpeakerphoneEnabled'); + return _invokeMethod('callApi', { + 'apiType': ApiTypeEngine.kEngineIsSpeakerPhoneEnabled.index, + 'params': jsonEncode({}), + }).then((value) => value == 1 ? true : false); } @override Future pauseAllEffects() { - return _invokeMethod('pauseAllEffects'); + return _invokeMethod('callApi', { + 'apiType': ApiTypeEngine.kEnginePauseAllEffects.index, + 'params': jsonEncode({}), + }); } @override Future pauseEffect(int soundId) { - return _invokeMethod('pauseEffect', { - 'soundId': soundId, + return _invokeMethod('callApi', { + 'apiType': ApiTypeEngine.kEnginePauseEffect.index, + 'params': jsonEncode({ + 'soundId': soundId, + }), }); } @override Future playEffect(int soundId, String filePath, int loopCount, - double pitch, double pan, double gain, bool publish, + double pitch, double pan, int gain, bool publish, [int? startPos]) { - return _invokeMethod('playEffect', { - 'soundId': soundId, - 'filePath': filePath, - 'loopCount': loopCount, - 'pitch': pitch, - 'pan': pan, - 'gain': gain, - 'publish': publish, - 'startPos': startPos, + return _invokeMethod('callApi', { + 'apiType': ApiTypeEngine.kEnginePlayEffect.index, + 'params': jsonEncode({ + 'soundId': soundId, + 'filePath': filePath, + 'loopCount': loopCount, + 'pitch': pitch, + 'pan': pan, + 'gain': gain, + 'publish': publish, + 'startPos': startPos, + }), }); } @override Future setEffectPosition(int soundId, int pos) { - return _invokeMethod('setEffectPosition', { - 'soundId': soundId, - 'pos': pos, + if (kIsWeb) { + throw PlatformException(code: ErrorCode.NotSupported.toString()); + } + return _invokeMethod('callApi', { + 'apiType': ApiTypeEngine.kEngineSetEffectPosition.index, + 'params': jsonEncode({ + 'soundId': soundId, + 'pos': pos, + }), }); } @override Future getEffectDuration(String filePath) { - return _invokeMethod('getEffectDuration', { - 'filePath': filePath, + if (kIsWeb) { + throw PlatformException(code: ErrorCode.NotSupported.toString()); + } + return _invokeMethod('callApi', { + 'apiType': ApiTypeEngine.kEngineGetEffectDuration.index, + 'params': jsonEncode({ + 'filePath': filePath, + }), }); } @override Future getEffectCurrentPosition(int soundId) { - return _invokeMethod('getEffectCurrentPosition', { - 'soundId': soundId, + if (kIsWeb) { + throw PlatformException(code: ErrorCode.NotSupported.toString()); + } + return _invokeMethod('callApi', { + 'apiType': ApiTypeEngine.kEngineGetEffectCurrentPosition.index, + 'params': jsonEncode({ + 'soundId': soundId, + }), }); } @override Future preloadEffect(int soundId, String filePath) { - return _invokeMethod('preloadEffect', { - 'soundId': soundId, - 'filePath': filePath, + return _invokeMethod('callApi', { + 'apiType': ApiTypeEngine.kEnginePreloadEffect.index, + 'params': jsonEncode({ + 'soundId': soundId, + 'filePath': filePath, + }), }); } @override Future registerMediaMetadataObserver() { - return _invokeMethod('registerMediaMetadataObserver'); + return _invokeMethod('callApi', { + 'apiType': ApiTypeEngine.kEngineRegisterMediaMetadataObserver.index, + 'params': jsonEncode({'type': 0}), + }); } @override Future removeInjectStreamUrl(String url) { - return _invokeMethod('removeInjectStreamUrl', { - 'url': url, + return _invokeMethod('callApi', { + 'apiType': ApiTypeEngine.kEngineRemoveInjectStreamUrl.index, + 'params': jsonEncode({ + 'url': url, + }), }); } @override Future removePublishStreamUrl(String url) { - return _invokeMethod('removePublishStreamUrl', { - 'url': url, + return _invokeMethod('callApi', { + 'apiType': ApiTypeEngine.kEngineRemovePublishStreamUrl.index, + 'params': jsonEncode({ + 'url': url, + }), }); } @override Future resumeAllEffects() { - return _invokeMethod('resumeAllEffects'); + return _invokeMethod('callApi', { + 'apiType': ApiTypeEngine.kEngineResumeAllEffects.index, + 'params': jsonEncode({}), + }); } @override Future resumeEffect(int soundId) { - return _invokeMethod('resumeEffect', { - 'soundId': soundId, + return _invokeMethod('callApi', { + 'apiType': ApiTypeEngine.kEngineResumeEffect.index, + 'params': jsonEncode({ + 'soundId': soundId, + }), }); } @override - Future sendMetadata(String metadata) { - return _invokeMethod('sendMetadata', { - 'metadata': metadata, + Future sendMetadata(Uint8List metadata) { + return _invokeMethod('callApiWithBuffer', { + 'apiType': ApiTypeEngine.kEngineSendMetadata.index, + 'params': jsonEncode({ + 'metadata': { + 'size': metadata.length, + }, + }), + 'buffer': metadata, }); } @override - Future sendStreamMessage(int streamId, String message) { - return _invokeMethod('sendStreamMessage', { - 'streamId': streamId, - 'message': message, + Future sendStreamMessage(int streamId, Uint8List message) { + return _invokeMethod('callApiWithBuffer', { + 'apiType': ApiTypeEngine.kEngineSendStreamMessage.index, + 'params': jsonEncode({ + 'streamId': streamId, + 'length': message.length, + }), + 'buffer': message, }); } @override Future setCameraAutoFocusFaceModeEnabled(bool enabled) { - return _invokeMethod('setCameraAutoFocusFaceModeEnabled', { - 'enabled': enabled, + return _invokeMethod('callApi', { + 'apiType': ApiTypeEngine.kEngineSetCameraAutoFocusFaceModeEnabled.index, + 'params': jsonEncode({ + 'enabled': enabled, + }), }); } @override Future setCameraCapturerConfiguration( CameraCapturerConfiguration config) { - return _invokeMethod('setCameraCapturerConfiguration', { - 'config': config.toJson(), + return _invokeMethod('callApi', { + 'apiType': ApiTypeEngine.kEngineSetCameraCapturerConfiguration.index, + 'params': jsonEncode({ + 'config': config.toJson(), + }), }); } @override Future setCameraExposurePosition( double positionXinView, double positionYinView) { - return _invokeMethod('setCameraExposurePosition', { - 'positionXinView': positionXinView, - 'positionYinView': positionYinView, + return _invokeMethod('callApi', { + 'apiType': ApiTypeEngine.kEngineSetCameraExposurePosition.index, + 'params': jsonEncode({ + 'positionXinView': positionXinView, + 'positionYinView': positionYinView, + }), }); } @override Future setCameraFocusPositionInPreview( double positionX, double positionY) { - return _invokeMethod('setCameraFocusPositionInPreview', { - 'positionX': positionX, - 'positionY': positionY, + return _invokeMethod('callApi', { + 'apiType': ApiTypeEngine.kEngineSetCameraFocusPositionInPreview.index, + 'params': jsonEncode({ + 'positionX': positionX, + 'positionY': positionY, + }), }); } @override Future setCameraTorchOn(bool isOn) { - return _invokeMethod('setCameraTorchOn', { - 'isOn': isOn, + return _invokeMethod('callApi', { + 'apiType': ApiTypeEngine.kEngineSetCameraTorchOn.index, + 'params': jsonEncode({ + 'isOn': isOn, + }), }); } @override Future setCameraZoomFactor(double factor) { - return _invokeMethod('setCameraZoomFactor', { - 'factor': factor, + return _invokeMethod('callApi', { + 'apiType': ApiTypeEngine.kEngineSetCameraZoomFactor.index, + 'params': jsonEncode({ + 'factor': factor, + }), }); } @override Future setDefaultAudioRoutetoSpeakerphone(bool defaultToSpeaker) { - return _invokeMethod('setDefaultAudioRoutetoSpeakerphone', { - 'defaultToSpeaker': defaultToSpeaker, + return _invokeMethod('callApi', { + 'apiType': ApiTypeEngine.kEngineSetDefaultAudioRouteToSpeakerPhone.index, + 'params': jsonEncode({ + 'defaultToSpeaker': defaultToSpeaker, + }), }); } @override - Future setEffectsVolume(double volume) { - return _invokeMethod('setEffectsVolume', { - 'volume': volume, + Future setEffectsVolume(int volume) { + return _invokeMethod('callApi', { + 'apiType': ApiTypeEngine.kEngineSetEffectsVolume.index, + 'params': jsonEncode({ + 'volume': volume, + }), }); } @override - Future setEnableSpeakerphone(bool enabled) { - return _invokeMethod('setEnableSpeakerphone', { - 'enabled': enabled, + Future setEnableSpeakerphone(bool speakerOn) { + return _invokeMethod('callApi', { + 'apiType': ApiTypeEngine.kEngineSetEnableSpeakerPhone.index, + 'params': jsonEncode({ + 'speakerOn': speakerOn, + }), }); } - @override @deprecated + @override Future setEncryptionMode(EncryptionMode encryptionMode) { - return _invokeMethod('setEncryptionMode', { - 'encryptionMode': EncryptionModeConverter(encryptionMode).value(), + var encryption = ''; + switch (encryptionMode) { + case EncryptionMode.AES128XTS: + encryption = 'aes-128-xts'; + break; + case EncryptionMode.AES128ECB: + encryption = 'aes-128-ecb'; + break; + case EncryptionMode.AES256XTS: + encryption = 'aes-256-xts'; + break; + default: + break; + } + return _invokeMethod('callApi', { + 'apiType': ApiTypeEngine.kEngineSetEncryptionMode.index, + 'params': jsonEncode({ + 'encryptionMode': encryption, + }), }); } @override @deprecated Future setEncryptionSecret(String secret) { - return _invokeMethod('setEncryptionSecret', { - 'secret': secret, + return _invokeMethod('callApi', { + 'apiType': ApiTypeEngine.kEngineSetEncryptionSecret.index, + 'params': jsonEncode({ + 'secret': secret, + }), }); } @override Future setInEarMonitoringVolume(int volume) { - return _invokeMethod('setInEarMonitoringVolume', { - 'volume': volume, + return _invokeMethod('callApi', { + 'apiType': ApiTypeEngine.kEngineSetInEarMonitoringVolume.index, + 'params': jsonEncode({ + 'volume': volume, + }), }); } @override Future setLiveTranscoding(LiveTranscoding transcoding) { - return _invokeMethod('setLiveTranscoding', { - 'transcoding': transcoding.toJson(), + return _invokeMethod('callApi', { + 'apiType': ApiTypeEngine.kEngineSetLiveTranscoding.index, + 'params': jsonEncode({ + 'transcoding': transcoding.toJson(), + }), }); } @override Future setLocalPublishFallbackOption(StreamFallbackOptions option) { - return _invokeMethod('setLocalPublishFallbackOption', { - 'option': StreamFallbackOptionsConverter(option).value(), + return _invokeMethod('callApi', { + 'apiType': ApiTypeEngine.kEngineSetLocalPublishFallbackOption.index, + 'params': jsonEncode({ + 'option': StreamFallbackOptionsConverter(option).value(), + }), }); } @override @deprecated Future setLocalVoiceChanger(AudioVoiceChanger voiceChanger) { - return _invokeMethod('setLocalVoiceChanger', { - 'voiceChanger': AudioVoiceChangerConverter(voiceChanger).value(), + return _invokeMethod('callApi', { + 'apiType': ApiTypeEngine.kEngineSetLocalVoiceChanger.index, + 'params': jsonEncode({ + 'voiceChanger': AudioVoiceChangerConverter(voiceChanger).value(), + }), }); } @override Future setLocalVoiceEqualization( AudioEqualizationBandFrequency bandFrequency, int bandGain) { - return _invokeMethod('setLocalVoiceEqualization', { - 'bandFrequency': - AudioEqualizationBandFrequencyConverter(bandFrequency).value(), - 'bandGain': bandGain, + return _invokeMethod('callApi', { + 'apiType': ApiTypeEngine.kEngineSetLocalVoiceEqualization.index, + 'params': jsonEncode({ + 'bandFrequency': + AudioEqualizationBandFrequencyConverter(bandFrequency).value(), + 'bandGain': bandGain, + }), }); } @override Future setLocalVoicePitch(double pitch) { - return _invokeMethod('setLocalVoicePitch', { - 'pitch': pitch, + return _invokeMethod('callApi', { + 'apiType': ApiTypeEngine.kEngineSetLocalVoicePitch.index, + 'params': jsonEncode({ + 'pitch': pitch, + }), }); } @override Future setLocalVoiceReverb(AudioReverbType reverbKey, int value) { - return _invokeMethod('setLocalVoiceReverb', { - 'reverbKey': AudioReverbTypeConverter(reverbKey).value(), - 'value': value, + return _invokeMethod('callApi', { + 'apiType': ApiTypeEngine.kEngineSetLocalVoiceReverb.index, + 'params': jsonEncode({ + 'reverbKey': AudioReverbTypeConverter(reverbKey).value(), + 'value': value, + }), }); } @override @deprecated - Future setLocalVoiceReverbPreset(AudioReverbPreset preset) { - return _invokeMethod('setLocalVoiceReverbPreset', { - 'preset': AudioReverbPresetConverter(preset).value(), + Future setLocalVoiceReverbPreset(AudioReverbPreset reverbPreset) { + return _invokeMethod('callApi', { + 'apiType': ApiTypeEngine.kEngineSetLocalVoiceReverbPreset.index, + 'params': jsonEncode({ + 'reverbPreset': AudioReverbPresetConverter(reverbPreset).value(), + }), }); } @override Future setMaxMetadataSize(int size) { - return _invokeMethod('setMaxMetadataSize', { - 'size': size, + return _invokeMethod('callApi', { + 'apiType': ApiTypeEngine.kEngineSetMaxMetadataSize.index, + 'params': jsonEncode({ + 'size': size, + }), }); } @override Future setRemoteDefaultVideoStreamType(VideoStreamType streamType) { - return _invokeMethod('setRemoteDefaultVideoStreamType', { - 'streamType': VideoStreamTypeConverter(streamType).value(), + return _invokeMethod('callApi', { + 'apiType': ApiTypeEngine.kEngineSetRemoteDefaultVideoStreamType.index, + 'params': jsonEncode({ + 'streamType': VideoStreamTypeConverter(streamType).value(), + }), }); } @override Future setRemoteSubscribeFallbackOption(StreamFallbackOptions option) { - return _invokeMethod('setRemoteSubscribeFallbackOption', { - 'option': StreamFallbackOptionsConverter(option).value(), + return _invokeMethod('callApi', { + 'apiType': ApiTypeEngine.kEngineSetRemoteSubscribeFallbackOption.index, + 'params': jsonEncode({ + 'option': StreamFallbackOptionsConverter(option).value(), + }), }); } @override Future setRemoteUserPriority(int uid, UserPriority userPriority) { - return _invokeMethod('setRemoteUserPriority', { - 'uid': uid, - 'userPriority': UserPriorityConverter(userPriority).value(), + return _invokeMethod('callApi', { + 'apiType': ApiTypeEngine.kEngineSetRemoteUserPriority.index, + 'params': jsonEncode({ + 'uid': uid, + 'userPriority': UserPriorityConverter(userPriority).value(), + }), }); } @override - Future setRemoteVideoStreamType(int uid, VideoStreamType streamType) { - return _invokeMethod('setRemoteVideoStreamType', { - 'uid': uid, - 'streamType': VideoStreamTypeConverter(streamType).value(), + Future setRemoteVideoStreamType( + int userId, VideoStreamType streamType) { + return _invokeMethod('callApi', { + 'apiType': ApiTypeEngine.kEngineSetRemoteVideoStreamType.index, + 'params': jsonEncode({ + 'userId': userId, + 'streamType': VideoStreamTypeConverter(streamType).value(), + }), }); } @override Future setRemoteVoicePosition(int uid, double pan, double gain) { - return _invokeMethod('setRemoteVoicePosition', { - 'uid': uid, - 'pan': pan, - 'gain': gain, + return _invokeMethod('callApi', { + 'apiType': ApiTypeEngine.kEngineSetRemoteVoicePosition.index, + 'params': jsonEncode({ + 'uid': uid, + 'pan': pan, + 'gain': gain, + }), }); } @override - Future setVolumeOfEffect(int soundId, double volume) { - return _invokeMethod('setVolumeOfEffect', { - 'soundId': soundId, - 'volume': volume, + Future setVolumeOfEffect(int soundId, int volume) { + return _invokeMethod('callApi', { + 'apiType': ApiTypeEngine.kEngineSetVolumeOfEffect.index, + 'params': jsonEncode({ + 'soundId': soundId, + 'volume': volume, + }), }); } @@ -1005,48 +1448,66 @@ class RtcEngine with RtcEngineInterface { @deprecated Future startAudioRecording(String filePath, AudioSampleRateType sampleRate, AudioRecordingQuality quality) { - return _invokeMethod('startAudioRecording', { - 'filePath': filePath, - 'sampleRate': AudioSampleRateTypeConverter(sampleRate).value(), - 'quality': AudioRecordingQualityConverter(quality).value(), + return _invokeMethod('callApi', { + 'apiType': ApiTypeEngine.kEngineStartAudioRecording.index, + 'params': jsonEncode({ + 'filePath': filePath, + 'sampleRate': AudioSampleRateTypeConverter(sampleRate).value(), + 'quality': AudioRecordingQualityConverter(quality).value(), + }), }); } @override Future startAudioRecordingWithConfig( AudioRecordingConfiguration config) { - return _invokeMethod('startAudioRecording', { - 'config': config.toJson(), + return _invokeMethod('callApi', { + 'apiType': ApiTypeEngine.kEngineStartAudioRecording.index, + 'params': jsonEncode({ + 'config': config.toJson(), + }), }); } @override Future startChannelMediaRelay( ChannelMediaRelayConfiguration channelMediaRelayConfiguration) { - return _invokeMethod('startChannelMediaRelay', { - 'channelMediaRelayConfiguration': channelMediaRelayConfiguration.toJson(), + return _invokeMethod('callApi', { + 'apiType': ApiTypeEngine.kEngineStartChannelMediaRelay.index, + 'params': jsonEncode({ + 'configuration': channelMediaRelayConfiguration.toJson(), + }), }); } @override Future startRhythmPlayer( String sound1, String sound2, RhythmPlayerConfig config) { - return _invokeMethod('startRhythmPlayer', { - 'sound1': sound1, - 'sound2': sound2, - 'config': config.toJson(), + return _invokeMethod('callApi', { + 'apiType': ApiTypeEngine.kEngineStartRhythmPlayer.index, + 'params': jsonEncode({ + 'sound1': sound1, + 'sound2': sound2, + 'config': config.toJson(), + }), }); } @override Future stopRhythmPlayer() { - return _invokeMethod('stopRhythmPlayer'); + return _invokeMethod('callApi', { + 'apiType': ApiTypeEngine.kEngineStopRhythmPlayer.index, + 'params': jsonEncode({}), + }); } @override Future configRhythmPlayer(RhythmPlayerConfig config) { - return _invokeMethod('configRhythmPlayer', { - 'config': config.toJson(), + return _invokeMethod('callApi', { + 'apiType': ApiTypeEngine.kEngineConfigRhythmPlayer.index, + 'params': jsonEncode({ + 'config': config.toJson(), + }), }); } @@ -1055,258 +1516,460 @@ class RtcEngine with RtcEngineInterface { {int? intervalInSeconds, EchoTestConfiguration? config}) { assert(intervalInSeconds == null || config == null, 'Only need one of the params'); - return _invokeMethod('startEchoTest', { - 'intervalInSeconds': intervalInSeconds, - 'config': config?.toJson(), + return _invokeMethod('callApi', { + 'apiType': ApiTypeEngine.kEngineStartEchoTest.index, + 'params': jsonEncode(config == null + ? {'intervalInSeconds': intervalInSeconds} + : {'config': config.toJson()}), }); } @override Future startLastmileProbeTest(LastmileProbeConfig config) { - return _invokeMethod('startLastmileProbeTest', { - 'config': config.toJson(), + return _invokeMethod('callApi', { + 'apiType': ApiTypeEngine.kEngineStartLastMileProbeTest.index, + 'params': jsonEncode({ + 'config': config.toJson(), + }), }); } @override Future stopAllEffects() { - return _invokeMethod('stopAllEffects'); + return _invokeMethod('callApi', { + 'apiType': ApiTypeEngine.kEngineStopAllEffects.index, + 'params': jsonEncode({}), + }); } @override Future stopAudioRecording() { - return _invokeMethod('stopAudioRecording'); + return _invokeMethod('callApi', { + 'apiType': ApiTypeEngine.kEngineStopAudioRecording.index, + 'params': jsonEncode({}), + }); } @override Future stopChannelMediaRelay() { - return _invokeMethod('stopChannelMediaRelay'); + return _invokeMethod('callApi', { + 'apiType': ApiTypeEngine.kEngineStopChannelMediaRelay.index, + 'params': jsonEncode({}), + }); } @override Future stopEchoTest() { - return _invokeMethod('stopEchoTest'); + return _invokeMethod('callApi', { + 'apiType': ApiTypeEngine.kEngineStopEchoTest.index, + 'params': jsonEncode({}), + }); } @override Future stopEffect(int soundId) { - return _invokeMethod('stopEffect', { - 'soundId': soundId, + return _invokeMethod('callApi', { + 'apiType': ApiTypeEngine.kEngineStopEffect.index, + 'params': jsonEncode({ + 'soundId': soundId, + }), }); } @override Future stopLastmileProbeTest() { - return _invokeMethod('stopLastmileProbeTest'); + return _invokeMethod('callApi', { + 'apiType': ApiTypeEngine.kEngineStopLastMileProbeTest.index, + 'params': jsonEncode({}), + }); } @override Future switchCamera() { - return _invokeMethod('switchCamera'); + return _invokeMethod('callApi', { + 'apiType': ApiTypeEngine.kEngineSwitchCamera.index, + 'params': jsonEncode({}), + }); } @override Future unloadEffect(int soundId) { - return _invokeMethod('unloadEffect', { - 'soundId': soundId, + return _invokeMethod('callApi', { + 'apiType': ApiTypeEngine.kEngineUnloadEffect.index, + 'params': jsonEncode({ + 'soundId': soundId, + }), }); } @override Future unregisterMediaMetadataObserver() { - return _invokeMethod('unregisterMediaMetadataObserver'); + return _invokeMethod('callApi', { + 'apiType': ApiTypeEngine.kEngineUnRegisterMediaMetadataObserver.index, + 'params': jsonEncode({'type': 0}), + }); } @override Future updateChannelMediaRelay( ChannelMediaRelayConfiguration channelMediaRelayConfiguration) { - return _invokeMethod('updateChannelMediaRelay', { - 'channelMediaRelayConfiguration': channelMediaRelayConfiguration.toJson(), + return _invokeMethod('callApi', { + 'apiType': ApiTypeEngine.kEngineUpdateChannelMediaRelay.index, + 'params': jsonEncode({ + 'configuration': channelMediaRelayConfiguration.toJson(), + }), }); } @override - Future enableFaceDetection(bool enabled) { - return _invokeMethod('enableFaceDetection', { - 'enabled': enabled, + Future enableFaceDetection(bool enable) { + return _invokeMethod('callApi', { + 'apiType': ApiTypeEngine.kEngineEnableFaceDetection.index, + 'params': jsonEncode({ + 'enable': enable, + }), }); } @override Future setAudioMixingPitch(int pitch) { - return _invokeMethod('setAudioMixingPitch', { - 'pitch': pitch, + return _invokeMethod('callApi', { + 'apiType': ApiTypeEngine.kEngineSetAudioMixingPitch.index, + 'params': jsonEncode({ + 'pitch': pitch, + }), }); } @override Future setAudioMixingPlaybackSpeed(int speed) { - return _invokeMethod('setAudioMixingPlaybackSpeed', { - 'speed': speed, + return _invokeMethod('callApi', { + 'apiType': ApiTypeEngine.kEngineSetAudioMixingPlaybackSpeed.index, + 'params': jsonEncode({ + 'speed': speed, + }), }); } @override Future getAudioTrackCount() { - return _invokeMethod('getAudioTrackCount'); + return _invokeMethod('callApi', { + 'apiType': ApiTypeEngine.kEngineGetAudioTrackCount.index, + 'params': jsonEncode({}), + }); } @override Future selectAudioTrack(int index) { - return _invokeMethod('selectAudioTrack', { - 'index': index, + return _invokeMethod('callApi', { + 'apiType': ApiTypeEngine.kEngineSelectAudioTrack.index, + 'params': jsonEncode({ + 'index': index, + }), }); } @override Future setAudioMixingDualMonoMode(AudioMixingDualMonoMode mode) { - return _invokeMethod('setAudioMixingDualMonoMode', { - 'mode': AudioMixingDualMonoModeConverter(mode).value(), + return _invokeMethod('callApi', { + 'apiType': ApiTypeEngine.kEngineSetAudioMixingDualMonoMode.index, + 'params': jsonEncode({ + 'mode': AudioMixingDualMonoModeConverter(mode).value(), + }), }); } @override Future enableEncryption(bool enabled, EncryptionConfig config) { - return _invokeMethod('enableEncryption', { - 'enabled': enabled, - 'config': config.toJson(), + return _invokeMethod('callApi', { + 'apiType': ApiTypeEngine.kEngineEnableEncryption.index, + 'params': jsonEncode({ + 'enabled': enabled, + 'config': config.toJson(), + }), }); } @override Future sendCustomReportMessage( String id, String category, String event, String label, int value) { - return _invokeMethod('sendCustomReportMessage', { - 'id': id, - 'category': category, - 'event': event, - 'label': label, - 'value': value, + return _invokeMethod('callApi', { + 'apiType': ApiTypeEngine.kEngineSendCustomReportMessage.index, + 'params': jsonEncode({ + 'id': id, + 'category': category, + 'event': event, + 'label': label, + 'value': value, + }), }); } @override Future setAudioSessionOperationRestriction( AudioSessionOperationRestriction restriction) { - return _invokeMethod('setAudioSessionOperationRestriction', { - 'restriction': - AudioSessionOperationRestrictionConverter(restriction).value(), + return _invokeMethod('callApi', { + 'apiType': ApiTypeEngine.kEngineSetAudioSessionOperationRestriction.index, + 'params': jsonEncode({ + 'restriction': + AudioSessionOperationRestrictionConverter(restriction).value(), + }), }); } @override Future getNativeHandle() { - return _invokeMethod('getNativeHandle'); + return _invokeMethod('callApi', { + 'apiType': ApiTypeEngine.kEngineGetNativeHandle.index, + 'params': jsonEncode({}), + }).then((value) => int.tryParse(value) ?? -1); } @override Future setAudioEffectParameters( AudioEffectPreset preset, int param1, int param2) { - return _invokeMethod('setAudioEffectParameters', { - 'preset': AudioEffectPresetConverter(preset).value(), - 'param1': param1, - 'param2': param2, + return _invokeMethod('callApi', { + 'apiType': ApiTypeEngine.kEngineSetAudioEffectParameters.index, + 'params': jsonEncode({ + 'preset': AudioEffectPresetConverter(preset).value(), + 'param1': param1, + 'param2': param2, + }), }); } @override Future setAudioEffectPreset(AudioEffectPreset preset) { - return _invokeMethod('setAudioEffectPreset', { - 'preset': AudioEffectPresetConverter(preset).value(), + return _invokeMethod('callApi', { + 'apiType': ApiTypeEngine.kEngineSetAudioEffectPreset.index, + 'params': jsonEncode({ + 'preset': AudioEffectPresetConverter(preset).value(), + }), }); } @override Future setVoiceBeautifierPreset(VoiceBeautifierPreset preset) { - return _invokeMethod('setVoiceBeautifierPreset', { - 'preset': VoiceBeautifierPresetConverter(preset).value(), + return _invokeMethod('callApi', { + 'apiType': ApiTypeEngine.kEngineSetVoiceBeautifierPreset.index, + 'params': jsonEncode({ + 'preset': VoiceBeautifierPresetConverter(preset).value(), + }), }); } @override Future createDataStreamWithConfig(DataStreamConfig config) { - return _invokeMethod('createDataStream', { - 'config': config.toJson(), + return _invokeMethod('callApi', { + 'apiType': ApiTypeEngine.kEngineCreateDataStream.index, + 'params': jsonEncode({ + 'config': config.toJson(), + }), }); } @override - Future enableDeepLearningDenoise(bool enabled) { - return _invokeMethod('enableDeepLearningDenoise', { - 'enabled': enabled, + Future enableDeepLearningDenoise(bool enable) { + return _invokeMethod('callApi', { + 'apiType': ApiTypeEngine.kEngineEnableDeepLearningDenoise.index, + 'params': jsonEncode({ + 'enable': enable, + }), }); } @override - Future enableRemoteSuperResolution(int uid, bool enabled) { - return _invokeMethod('enableRemoteSuperResolution', { - 'uid': uid, - 'enabled': enabled, + Future enableRemoteSuperResolution(int userId, bool enable) { + return _invokeMethod('callApi', { + 'apiType': ApiTypeEngine.kEngineEnableRemoteSuperResolution.index, + 'params': jsonEncode({ + 'userId': userId, + 'enable': enable, + }), }); } @override Future setCloudProxy(CloudProxyType proxyType) { - return _invokeMethod('setCloudProxy', { - 'proxyType': CloudProxyTypeConverter(proxyType).value(), + return _invokeMethod('callApi', { + 'apiType': ApiTypeEngine.kEngineSetCloudProxy.index, + 'params': jsonEncode({ + 'proxyType': CloudProxyTypeConverter(proxyType).value(), + }), }); } @override Future uploadLogFile() { - return _invokeMethod('uploadLogFile'); + return _invokeMethod('callApi', { + 'apiType': ApiTypeEngine.kEngineUploadLogFile.index, + 'params': jsonEncode({}), + }); } @override Future setVoiceBeautifierParameters( VoiceBeautifierPreset preset, int param1, int param2) { - return _invokeMethod('setVoiceBeautifierParameters', { - 'preset': VoiceBeautifierPresetConverter(preset).value(), - 'param1': param1, - 'param2': param2, + return _invokeMethod('callApi', { + 'apiType': ApiTypeEngine.kEngineSetVoiceBeautifierParameters.index, + 'params': jsonEncode({ + 'preset': VoiceBeautifierPresetConverter(preset).value(), + 'param1': param1, + 'param2': param2, + }), }); } @override Future setVoiceConversionPreset(VoiceConversionPreset preset) { - return _invokeMethod('setVoiceConversionPreset', { - 'preset': VoiceConversionPresetConverter(preset).value(), + return _invokeMethod('callApi', { + 'apiType': ApiTypeEngine.kEngineSetVoiceConversionPreset.index, + 'params': jsonEncode({ + 'preset': VoiceConversionPresetConverter(preset).value(), + }), }); } @override Future pauseAllChannelMediaRelay() { - return _invokeMethod('pauseAllChannelMediaRelay'); + return _invokeMethod('callApi', { + 'apiType': ApiTypeEngine.kEnginePauseAllChannelMediaRelay.index, + 'params': jsonEncode({}), + }); } @override Future resumeAllChannelMediaRelay() { - return _invokeMethod('resumeAllChannelMediaRelay'); + return _invokeMethod('callApi', { + 'apiType': ApiTypeEngine.kEngineResumeAllChannelMediaRelay.index, + 'params': jsonEncode({}), + }); } @override Future setLocalAccessPoint(List ips, String domain) { - return _invokeMethod('setLocalAccessPoint', { - 'ips': ips, - 'domain': domain, + return _invokeMethod('callApi', { + 'apiType': ApiTypeEngine.kEngineSetLocalAccessPoint.index, + 'params': jsonEncode({ + 'ips': ips, + 'domain': domain, + }), + }); + } + + @override + Future setScreenCaptureContentHint(VideoContentHint contentHint) { + return _invokeMethod('callApi', { + 'apiType': ApiTypeEngine.kEngineSetScreenCaptureContentHint.index, + 'params': jsonEncode({ + 'contentHint': VideoContentHintConverter(contentHint).value(), + }), + }); + } + + @override + Future startScreenCaptureByDisplayId(int displayId, + [Rectangle? regionRect, ScreenCaptureParameters? captureParams]) { + return _invokeMethod('callApi', { + 'apiType': ApiTypeEngine.kEngineStartScreenCaptureByDisplayId.index, + 'params': jsonEncode({ + 'displayId': displayId, + 'regionRect': regionRect?.toJson(), + 'captureParams': captureParams?.toJson(), + }), + }); + } + + @override + Future startScreenCaptureByScreenRect(Rectangle screenRect, + [Rectangle? regionRect, ScreenCaptureParameters? captureParams]) { + return _invokeMethod('callApi', { + 'apiType': ApiTypeEngine.kEngineStartScreenCaptureByScreenRect.index, + 'params': jsonEncode({ + 'screenRect': screenRect.toJson(), + 'regionRect': regionRect?.toJson(), + 'captureParams': captureParams?.toJson(), + }), + }); + } + + @override + Future startScreenCaptureByWindowId(int windowId, + [Rectangle? regionRect, ScreenCaptureParameters? captureParams]) { + return _invokeMethod('callApi', { + 'apiType': ApiTypeEngine.kEngineStartScreenCaptureByWindowId.index, + 'params': jsonEncode({ + 'windowId': windowId, + 'regionRect': regionRect?.toJson(), + 'captureParams': captureParams?.toJson(), + }), + }); + } + + @override + Future stopScreenCapture() { + return _invokeMethod('callApi', { + 'apiType': ApiTypeEngine.kEngineStopScreenCapture.index, + 'params': jsonEncode({}), + }); + } + + @override + Future updateScreenCaptureParameters( + ScreenCaptureParameters captureParams) { + return _invokeMethod('callApi', { + 'apiType': ApiTypeEngine.kEngineUpdateScreenCaptureParameters.index, + 'params': jsonEncode({ + 'captureParams': captureParams.toJson(), + }), + }); + } + + @override + Future updateScreenCaptureRegion(Rectangle regionRect) { + return _invokeMethod('callApi', { + 'apiType': ApiTypeEngine.kEngineUpdateScreenCaptureRegion.index, + 'params': jsonEncode({ + 'regionRect': regionRect.toJson(), + }), + }); + } + + @override + Future startScreenCapture(int windowId, + [int captureFreq = 0, Rect? rect, int bitrate = 0]) { + return _invokeMethod('callApi', { + 'apiType': ApiTypeEngine.kEngineStartScreenCapture.index, + 'params': jsonEncode({ + 'windowId': windowId, + 'captureFreq': captureFreq, + 'rect': rect?.toJson(), + 'bitrate': bitrate, + }), }); } @override Future enableVirtualBackground( bool enabled, VirtualBackgroundSource backgroundSource) { - return _invokeMethod('enableVirtualBackground', { - 'enabled': enabled, - 'backgroundSource': backgroundSource.toJson(), + return _invokeMethod('callApi', { + 'apiType': ApiTypeEngine.kEngineEnableVirtualBackground.index, + 'params': jsonEncode({ + 'enabled': enabled, + 'backgroundSource': backgroundSource.toJson(), + }), }); } @override Future takeSnapshot(String channel, int uid, String filePath) { - return _invokeMethod('takeSnapshot', { - 'channel': channel, - 'uid': uid, - 'filePath': filePath, + return _invokeMethod('callApi', { + 'apiType': ApiTypeEngine.kEngineTakeSnapshot.index, + 'params': jsonEncode({ + 'channel': channel, + 'uid': uid, + 'filePath': filePath, + }), }); } } @@ -1334,1747 +1997,1801 @@ mixin RtcEngineInterface RtcAudioRecorderInterface, RtcInjectStreamInterface, RtcCameraInterface, - RtcStreamMessageInterface { - /// Destroys the [RtcEngine] instance and releases all resources used by the Agora SDK. + RtcStreamMessageInterface, + RtcScreenSharingInterface { + /// @nodoc + Future initialize(RtcEngineContext config); + /// - /// This method is useful for apps that occasionally make voice or video calls, to free up resources for other operations when not making calls. + /// Releases the RtcEngine instance. + /// This method releases all resources used by the Agora SDK. Use this method for apps in which users occasionally make voice or video calls. When users do not make calls, you can free up resources for other operations. + /// If you want to create a new RtcEngine instance after destroying the current one, ensure that you wait till the destroy method execution to complete. /// - /// **Note** - /// - Call this method in the subthread. - /// - Once the app calls [RtcEngine.destroy] to destroy the created [RtcEngine] instance, you cannot use any method or callback in the SDK. Future destroy(); - /// Sets the channel profile of the Agora RtcEngine. /// - /// After initialization, the SDK uses the communication channel profile by default. You can call setChannelProfile to set the channel profile. + /// Sets the channel profile. + /// Sets the profile of the Agora channel. The Agora SDK differentiates channel profiles and applies optimization algorithms accordingly. For example, it prioritizes smoothness and low latency for a video call and prioritizes video quality for interactive live video streaming. + /// + /// + /// To ensure the quality of real-time communication, Agora recommends that all users in a channel use the same channel profile. + /// This method must be called and set before joinChannel, and cannot be set again after entering the channel. + /// + /// Param [profile] The channel profile. For details, see ChannelProfile. + /// /// - /// **Parameter** [profile] The channel profile of the Agora RtcEngine. See [ChannelProfile]. Future setChannelProfile(ChannelProfile profile); - /// Sets the role of a user in a live interactive streaming. /// - /// You can call this method either before or after joining the channel to set the user role as audience or host. If you call this method to switch the user role after joining the channel, the SDK triggers the following callbacks: - /// - The local client: [RtcEngineEventHandler.clientRoleChanged]. - /// - The remote client: [RtcEngineEventHandler.userJoined] or [RtcEngineEventHandler.userOffline] ([UserOfflineReason.BecomeAudience]). + /// Sets the user role and level in an interactive live streaming channel. + /// In the interactive live streaming profile, the SDK sets the user role as audience by default. You can call this method to set the user role as host. + /// You can call this method either before or after joining a channel. If you call this method to switch the user role after joining a channel, the SDK automatically does the following: + /// Calls muteLocalAudioStream and muteLocalVideoStream to change the publishing state. + /// Triggers clientRoleChanged on the local client. + /// Triggers userJoined or userOffline on the remote client. /// - /// **Note** - /// - This method applies to the `LiveBroadcasting` profile only (when the `profile` parameter in `setChannelProfile` is set as `LiveBroadcasting`). - /// - Since v3.2.1, this method can set the user level in addition to the user role. - /// - The user role determines the permissions that the SDK grants to a user, such as permission to send local streams, receive remote streams, and push streams to a CDN address. - /// - The user level determines the level of services that a user can enjoy within the permissions of the user's role. For example, an audience can choose to receive remote streams with low latency or ultra low latency. Levels affect prices. + /// This method applies to the interactive live streaming profile (the profile parameter of setChannelProfile is LiveBroadcasting) only. /// - /// **Parameter** [role] Sets the role of a user. See [ClientRole]. + /// Param [role] The user role in the interactive live streaming. See ClientRole. + /// + /// + /// Param [options] The detailed options of a user, including the user level. See ClientRoleOptions. /// - /// **Parameter** [options] The detailed options of a user, including user level. See [ClientRoleOptions]. Future setClientRole(ClientRole role, [ClientRoleOptions? options]); - /// Allows a user to join a channel. /// - /// Users in the same channel can talk to each other, and multiple users in the same channel can start a group chat. Users with different App IDs cannot call each other. - /// You must call the [RtcEngine.leaveChannel] method to exit the current call before joining another channel. - /// A successful joinChannel method call triggers the following callbacks: - /// - The local client: [RtcEngineEventHandler.joinChannelSuccess]. - /// - The remote client: [RtcEngineEventHandler.userJoined], if the user joining the channel is in the [ChannelProfile.Communication] profile, or is a [ClientRole.Broadcaster] in the [ChannelProfile.LiveBroadcasting] profile. + /// Joins a channel with the user ID, and configures whether to automatically subscribe to the audio or video streams. + /// This method enables the local user to join a real-time audio and video interaction channel. With the same App ID, users in the same channel can talk to each other, and multiple users in the same channel can start a group chat. + /// A successful call of this method triggers the following callbacks: + /// The local client: The joinChannelSuccess and connectionStateChanged callbacks. + /// The remote client: userJoined, if the user joining the channel is in the Communication profile or is a host in the Live-broadcasting profile. /// - /// When the connection between the client and Agora's server is interrupted due to poor network conditions, the SDK tries reconnecting to the server. When the local client successfully rejoins the channel, the SDK triggers the [RtcEngineEventHandler.rejoinChannelSuccess] callback on the local client. + /// When the connection between the client and Agora's server is interrupted due to poor network conditions, the SDK tries reconnecting to the server. When the local client successfully rejoins the channel, the SDK triggers the rejoinChannelSuccess callback on the local client. /// - /// Once the user joins the channel (switches to another channel), the user subscribes to the audio and video streams of all the other users in the channel by default, giving rise to usage and billing calculation. If you do not want to subscribe to a specified stream or all remote streams, call the mute methods accordingly. + /// Param [token] The token generated on your server for authentication. See Authenticate Your Users with Token. + /// Ensure that the App ID used for creating the token is the same App ID used by the createWithContext method for initializing the RTC engine. /// - /// **Note** - /// - A channel does not accept duplicate uids, such as two users with the same uid. If you set uid as 0, the system automatically assigns a uid. /// - /// **Warning** - /// - Ensure that the App ID used for creating the token is the same App ID used in the create method for creating an [RtcEngine] object. Otherwise, CDN live streaming may fail. + /// Param [null] The channel name. This parameter signifies the channel in which users engage in real-time audio and video interaction. Under the premise of the same App ID, users who fill in the same channel ID enter the same channel for audio and video interaction. The string length must be less than 64 bytes. Supported characters: + /// The 26 lowercase English letters: a to z. + /// The 26 uppercase English letters: A to Z. + /// The 10 numeric characters: 0 to 9. + /// Space + /// "!", "#", "$", "%", "&", "(", ")", "+", "-", ":", ";", "<", "=", ".", ">", "?", "@", "[", "]", "^", "_", "{", "}", "|", "~", "," /// - /// **Parameter** [token] The token for authentication. Set it as the token generated at your server. For details, see [Get a token](https://docs.agora.io/en/Agora%20Platform/token?platform=All%20Platforms#generatetoken). /// - /// **Parameter** [channelName] The unique channel name for the AgoraRTC session in the string format. The string length must be less than 64 bytes. Supported character scopes are: - /// - All lowercase English letters: a to z. - /// - All uppercase English letters: A to Z. - /// - All numeric characters: 0 to 9. - /// - The space character. - /// - Punctuation characters and other symbols, including: "!", "#", "$", "%", "&", "(", ")", "+", "-", ":", ";", "<", "=", ".", ">", "?", "@", "\[", "\]", "^", "_", " {", "}", "|", "~", ",". /// - /// **Parameter** [optionalInfo] Additional information about the channel. This parameter can be set as null or contain channel related information. Other users in the channel do not receive this message. + /// Param [uid] User ID This parameter is used to identify the user in the channel for real-time audio and video interaction. You need to set and manage user IDs yourself, and ensure that each user ID in the same channel is unique. This parameter is a 32-bit unsigned integer. The value range is 1 to + /// 232-1. If the user ID is not assigned (or set to 0), the SDK assigns a random user ID and returns it in the joinChannelSuccess callback. Your app must maintain the returned user ID, because the SDK + /// does not do so. /// - /// **Parameter** [optionalUid] (Optional) User ID. `optionalUid` must be unique. If `optionalUid` is not assigned (or set to 0), the SDK assigns and returns uid in the [RtcEngineEventHandler.joinChannelSuccess] callback. Your app must record and maintain the returned uid since the SDK does not do so. + /// Param [options] The channel media options. For details, see ChannelMediaOptions. /// - /// **Parameter** [options] The channel media options. See [ChannelMediaOptions]. Future joinChannel( String? token, String channelName, String? optionalInfo, int optionalUid, [ChannelMediaOptions? options]); - /// Switches to a different channel. /// - /// This method allows the audience of a [ChannelProfile.LiveBroadcasting] channel to switch to a different channel. - /// After the user successfully switches to another channel, the [RtcEngineEventHandler.leaveChannel] and [RtcEngineEventHandler.joinChannelSuccess] callbacks are triggered to indicate that the user has left the original channel and joined a new one. + /// Switches to a different channel, and configures whether to automatically subscribe to audio or video streams in the target channel. + /// This method allows the audience of a LIVE_BROADCASTING channel to switch to a different channel. + /// After the user successfully switches to another channel, the leaveChannel and joinChannelSuccess callbacks are triggered to indicate that the user has left the original channel and joined a new one. + /// Once the user switches to another channel, the user subscribes to the audio and video streams of all the other users in the channel by default, giving rise to usage and billing calculation. If you do not want to subscribe to a specified stream or all remote streams, call the mute methods accordingly. + /// + /// Param [token] The token generated at your server. + /// In scenarios with low security requirements, token is optional and can be set as null. + /// In scenarios with high security requirements, set the value to the token generated from your server. If you enable the App Certificate, you must use a token to join the channel. + /// + /// Ensure that the App ID used for creating the token is the same App ID used by the createWithContext method for initializing the RTC engine. /// - /// **Note** - /// - This method applies to the [ClientRole.Audience] role in a [ChannelProfile.LiveBroadcasting] channel only. /// - /// **Parameter** [token] The token for authentication. Set it as the token generated at your server. For details, see [Get a token](https://docs.agora.io/en/Agora%20Platform/token?platform=All%20Platforms#generatetoken). + /// Param [channelName] The name of the channel. This parameter signifies the channel in which users engage in real-time audio and video interaction. Under the premise of the same App ID, users who fill in the same channelId enter the same channel for audio and video interaction. The string length must be less than 64 bytes. Supported characters: + /// All lowercase English letters: a to z. + /// All uppercase English letters: A to Z. + /// All numeric characters: 0 to 9. + /// Space + /// "!"、"#"、"$"、"%"、"&"、"("、")"、"+"、"-"、":"、";"、"<"、"="、"."、">"、"?"、"@"、"["、"]"、"^"、"_"、"{"、"}"、"|"、"~"、"," /// - /// **Parameter** [channelName] Unique channel name for the AgoraRTC session in the string format. The string length must be less than 64 bytes. Supported character scopes are: - /// - All lowercase English letters: a to z. - /// - All uppercase English letters: A to Z. - /// - All numeric characters: 0 to 9. - /// - The space character. - /// - Punctuation characters and other symbols, including: "!", "#", "$", "%", "&", "(", ")", "+", "-", ":", ";", "<", "=", ".", ">", "?", "@", "\[", "\]", "^", "_", " {", "}", "|", "~", ",". /// - /// **Parameter** [options] The channel media options: [ChannelMediaOptions]. + /// + /// Param [options] The channel media options. See ChannelMediaOptions. + /// Future switchChannel(String? token, String channelName, [ChannelMediaOptions? options]); - /// Allows a user to leave a channel. /// - /// After joining a channel, the user must call this method to end the call before joining another channel. This method returns 0 if the user leaves the channel and releases all resources related to the call. This method call is asynchronous, and the user has not exited the channel when the method call returns. Once the user leaves the channel, the SDK triggers the [RtcEngineEventHandler.leaveChannel] callback. - /// A successful method call triggers the following callbacks: - /// - The local client: [RtcEngineEventHandler.leaveChannel]. - /// - The remote client: [RtcEngineEventHandler.userOffline], if the user leaving the channel is in the [ChannelProfile.Communication] profile, or is a [ClientRole.Broadcaster] in the [ChannelProfile.LiveBroadcasting] profile. + /// Leaves a channel. + /// This method releases all resources related to the session. This method call is asynchronous. When this method returns, it does not necessarily mean that the user has left the channel. + /// A successful call of this method triggers the following callbacks: + /// The local client: leaveChannel. + /// The remote client: userOffline, if the user joining the channel is in the Communication profile, or is a host in the Live-broadcasting profile. + /// + /// + /// + /// If you call destroy immediately after calling this method, the SDK does not trigger the leaveChannel callback. + /// If you call this method during a CDN live streaming, the SDK automatically calls the removePublishStreamUrl method. /// - /// **Note** - /// - If you call the [RtcEngine.destroy] method immediately after calling this method, the `leaveChannel` process interrupts, and the SDK does not trigger the [RtcEngineEventHandler.leaveChannel] callback. - /// - If you call this method during CDN live streaming, the SDK triggers the [RtcEngine.removePublishStreamUrl] method. Future leaveChannel(); - /// Renews the token when the current token expires. /// - /// The token expires after a period of time once the token schema is enabled when: - /// - The SDK triggers the [RtcEngineEventHandler.tokenPrivilegeWillExpire] callback - /// - The [RtcEngineEventHandler.connectionStateChanged] callback reports the [ConnectionChangedReason.TokenExpired] error. - /// The app should retrieve a new token from the server and call this method to renew it. Failure to do so results in the SDK disconnecting from the server. + /// Gets a new token when the current token expires after a period of time. + /// Passes a new token to the SDK. A token expires after a certain period of time. In the following two cases, the app should call this method to pass in a new token. Failure to do so will result in the SDK disconnecting from the server. + /// The SDK triggers the tokenPrivilegeWillExpire callback. + /// The connectionStateChanged callback reports TokenExpired(9). + /// + /// Param [token] The new token. /// - /// **Parameter** [token] The new token. Future renewToken(String token); - /// Enables interoperability with the Agora Web SDK (LiveBroadcasting only). /// - /// The SDK automatically enables interoperability with the Web SDK, so you no longer need to call this method. - /// If the channel has Web SDK users, ensure that you call this method, or the video of the Native user will be a black screen for the Web user. - /// Use this method when the channel profile is [ChannelProfile.LiveBroadcasting]. Interoperability with the Agora Web SDK is enabled by default when the channel profile is [ChannelProfile.Communication]. + /// Enables interoperability with the Agora Web SDK (applicable only in the live streaming scenarios). + /// Deprecated: + /// The SDK automatically enables interoperability with the Web SDK, so you no longer need to call this method. + /// + /// + /// This method enables or disables interoperability with the Agora Web SDK. If the channel has Web SDK users, ensure that you call this method, or the video of the Native user will be a black screen for the Web user. + /// This method is only applicable in live streaming scenarios, and interoperability is enabled by default in communication scenarios. + /// + /// Param [enabled] Whether to enable interoperability with the Agora Web SDK. + /// true: Enable interoperability. + /// false: (Default) Disable interoperability. + /// /// - /// **Parameter** [enabled] Sets whether to enable/disable interoperability with the Agora Web SDK: - /// - `true`: Enable. - /// - `false`: (Default) Disable. @deprecated Future enableWebSdkInteroperability(bool enabled); - /// Gets the connection state of the SDK. /// - /// **Returns** - /// - The current connection state [ConnectionStateType], if this method call succeeds. - /// - Error code, if this method call fails. + /// Gets the current connection state of the SDK. + /// You can call this method either before or after joining a channel. + /// + /// **return** The current connection state. + /// Future getConnectionState(); - /// This function is in the beta stage with a free trial. The ability provided in its beta test version is reporting a maximum of 10 message pieces within 6 seconds, with each message piece not exceeding 256 bytes and each string not exceeding 100 bytes. To try out this function, contact support@agora.io and discuss the format of customized messages with us. + /// + /// Reports customized messages. + /// Agora supports reporting and analyzing customized messages. This function is in the beta stage with a free trial. The ability provided in its beta test version is reporting a maximum of 10 message pieces within 6 seconds, with each message piece not exceeding 256 bytes and each string not exceeding 100 bytes. To try out this function, contact and discuss the format of customized messages with us. + /// Future sendCustomReportMessage( String id, String category, String event, String label, int value); - /// Gets the current call ID. /// - /// When a user joins a channel on a client, a call ID is generated to identify the call from the client. Feedback methods, such as the [RtcEngine.rate] and [RtcEngine.complain] method, must be called after the call ends to submit feedback to the SDK. + /// Retrieves the call ID. + /// When a user joins a channel on a client, a callId is generated to identify the call from the client. Some methods, such as rate and complain, must be called after the call ends to submit feedback to the SDK. These methods require the callId parameter. + /// Call this method after joining a channel. /// - /// The `rate` and `complain` methods require the `callId` parameter retrieved from the [RtcEngine.getCallId] method during a call. `callId` is passed as an argument into the rate and complain methods after the call ends. + /// **return** The current call ID. /// - /// **Returns** - /// - The current call ID, if the method call succeeds. - /// - The empty string "", if the method call fails. Future getCallId(); - /// Allows the user to rate a call after the call ends. /// - /// **Parameter** [callId] ID of the call retrieved from the [RtcEngine.getCallId] method. + /// Allows a user to rate a call after the call ends. + /// Ensure that you call this method after leaving a channel. + /// + /// Param [callId] The current call ID. You can get the call ID by calling getCallId. /// - /// **Parameter** [rating] Rating of the call. The value is between 1 (lowest score) and 5 (highest score). If you set a value out of this range, the [ErrorCode.InvalidArgument] error occurs. + /// Param [rating] The rating of the call. The value is between 1 (lowest score) and 5 (highest score). If you set a value out of this range, the SDK returns the -2 (ERR_INVALID_ARGUMENT) error. + /// + /// Param [description] (Optional) A description of the call. The string length should be less than 800 bytes. /// - /// **Parameter** [description] (Optional) The description of the rating. The string length must be less than 800 bytes. Future rate(String callId, int rating, {String? description}); + /// /// Allows a user to complain about the call quality after a call ends. + /// This method allows users to complain about the quality of the call. Call this method after the user leaves the channel. /// - /// **Parameter** [callId] ID of the call retrieved from the [RtcEngine.getCallId] method. + /// Param [callId] The current call ID. You can get the call ID by calling getCallId. + /// + /// Param [description] (Optional) A description of the call. The string length should be less than 800 bytes. /// - /// **Parameter** [description] (Optional) The description of the complaint. The string length must be less than 800 bytes. Future complain(String callId, String description); - /// Specifies an SDK output log file. - /// - /// The log file records all log data for the SDK’s operation. Ensure that the directory for the log file exists and is writable. /// - /// **Deprecated** + /// Sets the log files that the SDK outputs. + /// By default, the SDK outputs five log files: agorasdk.log, agorasdk_1.log, agorasdk_2.log, agorasdk_3.log, and agorasdk_4.log. Each log file has a default size of 512 KB. These log files are encoded in UTF-8. The SDK writes the latest log in agorasdk.log. When agorasdk.log is full, the SDK deletes the log file with the earliest modification time among the other four, renames agorasdk.log to the name of the deleted log file, and create a new agorasdk.log to record the latest logs. + /// Ensure that you call this method immediately after initializing RtcEngine, otherwise, the output log may not be complete. /// - /// This method is deprecated from v3.3.1. + /// Param [filePath] The absolute path of the log files. The default file path is C: \Users\\AppData\Local\Agora\\agorasdk.log. Ensure that the directory for the log files exists and is writable. You can use this parameter to rename the log files. /// - /// **Note** - /// - Ensure that you call this method immediately after calling the [RtcEngine.create] method, otherwise the output log may not be complete. /// - /// **Parameter** [filePath] File path of the log file. The string of the log file is in UTF-8. The default file path is `/storage/emulated/0/Android/data/="">/files/agorasdk.log` for Android and `App Sandbox/Library/caches/agorasdk.log` for iOS. @deprecated Future setLogFile(String filePath); - /// Sets the output log level of the SDK. /// - /// You can use one or a combination of the filters. The log level follows the sequence of `OFF`, `CRITICAL`, `ERROR`, `WARNING`, `INFO`, and `DEBUG`. Choose a level to see the logs preceding that level. For example, if you set the log level to `WARNING`, you see the logs within levels `CRITICAL`, `ERROR`, and `WARNING`. + /// Sets the log output level of the SDK. + /// This method sets the output log level of the SDK. You can use one or a combination of the log filter levels. The log level follows the sequence of OFF, CRITICAL, ERROR, WARNING, INFO, and DEBUG. Choose a level to see the logs preceding that level. + /// If, for example, you set the log level to WARNING, you see the logs within levels CRITICAL, ERROR, and WARNING. /// - /// **Deprecated** + /// Param [filter] The output log level of the SDK. For details, see LogFilter. /// - /// This method is deprecated from v3.3.1. - /// - /// **Parameter** [filter] Sets the log filter level. See [LogFilter]. @deprecated Future setLogFilter(LogFilter filter); - /// Sets the log file size (KB). - /// - /// By default, the SDK outputs five log files, `agorasdk.log`, `agorasdk_1.log`, `agorasdk_2.log`, `agorasdk_3.log`, `agorasdk_4.log`, each with a default size of 1024 KB. /// - /// These log files are encoded in UTF-8. The SDK writes the latest logs in `agorasdk.log`. When agorasdk.log is full, the SDK deletes the log file with the earliest modification time among the other four, renames agorasdk.log to the name of the deleted log file, and create a new `agorasdk.log` to record latest logs. + /// Sets the size of a log file that the SDK outputs. + /// By default, the SDK outputs five log files: agorasdk.log, agorasdk_1.log, agorasdk_2.log, agorasdk_3.log, and agorasdk_4.log. Each log file has a default size of 512 KB. These log files are encoded in UTF-8. The SDK writes the latest log in agorasdk.log. When agorasdk.log is full, the SDK deletes the log file with the earliest modification time among the other four, renames agorasdk.log to the name of the deleted log file, and create a new agorasdk.log to record the latest logs. + /// If you want to set the size of the log file, you need to call this method before setLogFile, otherwise, the log will be cleared. /// - /// **Deprecated** + /// Param [fileSizeInKBytes] The size (KB) of a log file. The default value is 1024 KB. If you set fileSizeInKByte to 1024 KB, the maximum aggregate size of the log files output by the SDK is 5 MB. if you set fileSizeInKByte to less than 1024 KB, the setting is invalid, and the maximum size of a log file is still 1024 KB. /// - /// This method is deprecated from v3.3.1. - /// - /// **Parameter** [fileSizeInKBytes] The size (KB) of a log file. The default value is 1024 KB. If you set `fileSizeInKBytes` to 1024 KB, the SDK outputs at most 5 MB log files; if you set it to less than 1024 KB, the maximum size of a log file is still 1024 KB. @deprecated Future setLogFileSize(int fileSizeInKBytes); - /// @nodoc - /// - /// Provides technical preview functionalities or special customizations by configuring the SDK with JSON options. - /// - /// The JSON options are not public by default. Agora is working on making commonly used JSON options public in a standard way. - /// - /// **Parameter** [parameters] Sets the parameter as a JSON string in the specified format. + /* api-engine-setParameters */ Future setParameters(String parameters); - /// Gets the native handle of the SDK engine. /// - /// This interface is used to retrieve the native C++ handle of the SDK engine used in special scenarios, such as registering the audio and video frame observer. + /// Gets the C++ handle of the Native SDK. + /// This method is used to retrieve the native C++ handle of the SDK engine used in special scenarios, such as registering the audio and video frame observer. + /// + /// **return** The native handle of the SDK. /// - /// **Returns** - /// - The native handle of the SDK, if this method call succeeds. - /// - Error code, if this method call fails. Future getNativeHandle(); - /// Enables or disables deep-learning noise reduction. /// - /// Since v3.3.1. + /// Enables/Disables deep-learning noise reduction. + /// The SDK enables traditional noise reduction mode by default to reduce most of the stationary background noise. If you need to reduce most of the non-stationary background noise, Agora recommends enabling deep-learning noise reduction as follows: + /// Ensure that the dynamic library is integrated in your project: libagora_ai_denoise_extension.dll + /// Call enableDeepLearningDenoise(true). /// - /// The SDK enables traditional noise reduction mode by default to reduce most of the stationary background noise. - /// If you need to reduce most of the non-stationary background noise, Agora recommends enabling deep-learning noise reduction by calling `enableDeepLearningDenoise(true)`. - /// - /// Deep-learning noise reduction requires high-performance devices. + /// Deep-learning noise reduction requires high-performance devices. The deep-learning noise reduction is enabled only when the device supports this function. For example, the following devices and later models are known to support deep-learning noise reduction: + /// iPhone 6S + /// MacBook Pro 2015 + /// iPad Pro (2nd generation) + /// iPad mini (5th generation) + /// iPad Air (3rd generation) /// /// After successfully enabling deep-learning noise reduction, if the SDK detects that the device performance is not sufficient, it automatically disables deep-learning noise reduction and enables traditional noise reduction. + /// If you call enableDeepLearningDenoise(true) or the SDK automatically disables deep-learning noise reduction in the channel, when you need to re-enable deep-learning noise reduction, you need to call leaveChannel first, and then call enableDeepLearningDenoise(true). /// - /// If you call `enableDeepLearningDenoise(false)` or the SDK automatically disables deep-learning noise reduction in the channel, when you need to re-enable deep-learning noise reduction, you need to call `leaveChannel` first, and then call `enableDeepLearningDenoise(true)`. + /// This method dynamically loads the library, so Agora recommends calling this method before joining a channel. + /// This method works best with the human voice. Agora does not recommend using this method for audio containing music. /// - /// **Parameter** [enabled] Sets whether to enable deep-learning noise reduction. - /// - true: (Default) Enables deep-learning noise reduction. - /// - false: Disables deep-learning noise reduction. + /// Param [enable] Whether to enable deep-learning noise reduction. + /// true: (Default) Enable deep-learning noise reduction. + /// false: Disable deep-learning noise reduction. /// - /// **Note** /// - /// - Agora recommends calling this method before joining a channel. - /// - This method works best with the human voice. Agora does not recommend using this method for audio containing music. - Future enableDeepLearningDenoise(bool enabled); + Future enableDeepLearningDenoise(bool enable); - /// Sets the Agora cloud proxy service. /// - /// Since v3.3.1. + /// Sets the Agora cloud proxy service. + /// When the user's firewall restricts the IP address and port, refer to Use Cloud Proxy to add the specific IP addresses and ports to the firewall whitelist; then, call this method to enable the cloud proxy and set the cloud proxyType as UDP. + /// After successfully connecting to the cloud proxy, the SDK triggers the connectionStateChanged (Connecting, SettingProxyServer) callback. + /// To disable the cloud proxy that has been set, call setCloudProxy(NONE_PROXY). + /// To change the cloud proxy type, call setCloudProxy(NONE_PROXY), and call setCloudProxy to set the proxyType you want. /// /// - /// When the user’s firewall restricts the IP address and port, refer to *Use Cloud Proxy* to add the specific IP addresses and ports to the firewall whitelist; then, call this method to enable the cloud proxy and set the [proxyType] parameter as `UDP(1)`, which is the cloud proxy for the UDP protocol. + /// Agora recommends that you call this method before joining the channel or after leaving the channel. + /// Cloud proxy for the UDP protocol does not apply to pushing streams to CDN or co-hosting across channels. /// - /// After a successfully cloud proxy connection, the SDK triggers the `connectionStateChanged(Connecting, SettingProxyServer)` callback. + /// Param [proxyType] The type of the cloud proxy. See CloudProxyType . This parameter is mandatory. The SDK reports an error if you do not pass in a value. /// - /// To disable the cloud proxy that has been set, call `setCloudProxy(None)`. To change the cloud proxy type that has been set, call `setCloudProxy(None)` first, and then call `setCloudProxy`, and pass the value that you expect in [proxyType]. + Future setCloudProxy(CloudProxyType proxyType); + /// - /// **Parameter** + /// Uploads all SDK log files. + /// Since + /// v3.3.0 /// - /// [proxyType] The cloud proxy type, see [CloudProxyType]. This parameter is required, and the SDK reports an error if you do not pass in a value. /// - /// **Note** + /// Uploads all SDK log files from the client to the Agora server. After calling this method successfully, the SDK triggers the uploadLogResult callback to report whether the log file is successfully uploaded to the Agora server. + /// For easier debugging, Agora recommends that you bind the uploadLogFile method to the UI element of your app, to instruct the user to upload a log file when a quality issue occurs. /// - /// - Agora recommends that you call this method before joining the channel or after leaving the channel. - /// - When you use the cloud proxy for the UDP protocol, the services for pushing streams to CDN and co-hosting across channels are not available. - Future setCloudProxy(CloudProxyType proxyType); - - /// @nodoc Future uploadLogFile(); - /// @nodoc + /* api-engine-setLocalAccessPoint */ Future setLocalAccessPoint(List ips, String domain); - /// Enables/Disables the virtual background. (beta function). - /// - /// - /// **Parameter** [enabled] Sets whether to enable the virtual background: - /// - `true`: Enable. - /// - `false`: Disable. - /// - /// **Parameter** [backgroundSource] The custom background image. See [VirtualBackgroundSource]. - /// - /// **Note** /// - /// To adapt the resolution of the custom background image to the resolution of the SDK capturing video, the SDK scales and crops the custom background image while ensuring that the content of the custom background image is not distorted. + /// Enables/Disables the virtual background. (beta feature) + /// After enabling the virtual background feature, you can replace the original background image of the local user with a custom background image. After the replacement, all users in the channel can see the custom background image. /// - /// **Note** + /// Before calling this method, ensure that you have integrated the dynamic library. + /// Android: libagora_segmentation_extension.so + /// iOS: AgoraVideoSegmentationExtension.xcframework /// - /// - Call this method after enableVideo. - /// - This function requires a high-performance device. Agora recommends that you use this function on devices with an i5 CPU and better. + /// Call this method after enableVideo. + /// This function requires a high-performance device. Agora recommends that you use this function on devices with the following chips: + /// Snapdragon 700 series 750G and later + /// Snapdragon 800 series 835 and later + /// Dimensity 700 series 720 and later + /// Kirin 800 series 810 and later + /// Kirin 900 series 980 and later + /// Devices with an A9 chip and better, as follows: + /// iPhone 6S and later + /// iPad Air 3rd generation and later + /// iPad 5th generation and later + /// iPad Pro 2nd generation and later + /// iPad mini 5th generation and later /// /// Agora recommends that you use this function in scenarios that meet the following conditions: - /// - A high-definition camera device is used, and the environment is uniformly lit. - /// - The captured video image is uncluttered, the user's portrait is half-length and largely unobstructed, and the background is a single color that differs from the color of the user's clothing. + /// A high-definition camera device is used and the environment is uniformly lit. + /// There are few objects in the captured video. Portraits are half-length and unobstructed. Ensure that the background is a solid color that distinguishes from the color of the user's clothing. /// - /// This function requires a high-performance device. Agora recommends that you use this function on the following devices: + /// The virtual background feature does not support video in the texture format or video obtained from custom video capture by the Push method. /// - /// iOS devices with an A9 chip and better, as follows: + /// Param [enabled] Whether to enable virtual background: + /// true: Enable virtual background. + /// false: Disable virtual background. /// - /// - iPhone 6S and later - /// - iPad Air (3rd generation) and later - /// - iPad (5th generation) and later - /// - iPad Pro (1st generation) and later - /// - iPad mini (5th generation) and later /// - /// Android devices with the following chips: + /// Param [backgroundSource] The custom background image. For details, see VirtualBackgroundSource. To adapt the resolution of the custom background image to that of the video captured by the SDK, the SDK scales and crops the custom background image while ensuring that the content of the custom background image is not distorted. /// - /// - Snapdragon 700 series 750G and later - /// - Snapdragon 800 series 835 and later - /// - Dimensity 700 series 720 and later - /// - Kirin 800 series 810 and later - /// - Kirin 900 series 980 and later Future enableVirtualBackground( bool enabled, VirtualBackgroundSource backgroundSource); - /// Takes a snapshot of a video stream. - /// - /// Since - /// v4.2.0 /// + /// Takes a snapshot of a video stream. /// This method takes a snapshot of a video stream from the specified user, generates a JPG image, and saves it to the specified path. + /// The method is asynchronous, and the SDK has not taken the snapshot when the method call returns. After a successful method call, the SDK triggers snapshotTaken callback to report whether the snapshot is successfully taken as well as the details for the snapshot taken. + /// Call this method after joining a channel. + /// If the video of the specified user is pre-processed, for example, added with watermarks or image enhancement effects, the generated snapshot also includes the pre-processing effects. /// - /// The method is asynchronous, and the SDK has not taken the snapshot when the method call returns. After a successful method call, the SDK triggers the [RtcEngineEventHandler.snapshotTaken] callback to report whether the snapshot is successfully taken as well as the details of the snapshot taken. + /// Param [channel] The channel name. /// - /// **Note** + /// Param [uid] The user ID. Set uid as 0 if you want to take a snapshot of the local user's video. /// - /// - Call this method after joining a channel. - /// - If the video of the specified user is pre-processed, for example, added with watermarks or image enhancement effects, the generated snapshot also includes the pre-processing effects. + /// Param [filePath] The local path (including the filename extensions) of the snapshot. For example, /// - /// **Parameter** [channel] The channel name. + /// Windows: C:\Users\\AppData\Local\Agora\\example.jpg + /// iOS: /App Sandbox/Library/Caches/example.jpg + /// macOS: ~/Library/Logs/example.jpg + /// Android: /storage/emulated/0/Android/data//files/example.jpg + /// Ensure that the path you specify exists and is writable. /// - /// **Parameter** [uid] The user ID of the user. Set uid as 0 if you want to take a snapshot of the local user's video. - /// - /// **Parameter** [filePath] The local path (including the filename extensions) for the snapshot. For example, `/storage/emulated/0/Android/data//files/example.jpg` for Android and `/App Sandbox/Library/Caches/example.jpg` for iOS. Ensure that the path you specify exists and is writable. /// Future takeSnapshot(String channel, int uid, String filePath); } /// @nodoc mixin RtcUserInfoInterface { + /// /// Registers a user account. + /// Once registered, the user account can be used to identify the local user when the user joins the channel. After the registration is successful, the user account can identify the identity of the local user, and the user can use it to join the channel. + /// After the user successfully registers a user account, the SDK triggers the localUserRegistered callback on the local client, reporting the user ID and user account of the local user. + /// This method is optional. To join a channel with a user account, you can choose either of the following ways: + /// Call registerLocalUserAccount to to create a user account, and then call joinChannelWithUserAccount to join the channel. + /// Call the joinChannelWithUserAccount method to join the channel. + /// + /// The difference between the two ways is that the time elapsed between calling the registerLocalUserAccount method and joining the channel is shorter than directly calling joinChannelWithUserAccount. + /// /// - /// Once registered, the user account can be used to identify the local user when the user joins the channel. After the user successfully registers a user account, the SDK triggers the [RtcEngineEventHandler.localUserRegistered] callback on the local client, reporting the user ID and user account of the local user. + /// Ensure that you set the userAccount parameter; otherwise, this method does not take effect. + /// Ensure that the userAccount is unique in the channel. + /// To ensure smooth communication, use the same parameter type to identify the user. For example, if a user joins the channel with a user ID, then ensure all the other users use the user ID too. The same applies to the user account. If a user joins the channel with the Agora Web SDK, ensure that the ID of the user is set to the same parameter type. /// - /// To join a channel with a user account, you can choose either of the following: - /// - Call the [RtcEngine.registerLocalUserAccount] method to create a user account, and then the [RtcEngine.joinChannelWithUserAccount] method to join the channel. - /// - Call the [RtcEngine.joinChannelWithUserAccount] method to join the channel. - /// The difference between the two is that for the former, the time elapsed between calling the [RtcEngine.joinChannelWithUserAccount] method and joining the channel is shorter than the latter. + /// Param [appId] The App ID of your project on Agora Console. /// - /// **Note** - /// - Ensure that you set the [userAccount] parameter. Otherwise, this method does not take effect. - /// - Ensure that the value of the userAccount parameter is unique in the channel. - /// - To ensure smooth communication, use the same parameter type to identify the user. For example, if a user joins the channel with a user ID, then ensure all the other users use the user ID too. The same applies to the user account. If a user joins the channel with the Agora Web SDK, ensure that the uid of the user is set to the same parameter type. + /// Param [userAccount] The user account. This parameter is used to identify the user in the channel for real-time audio and video engagement. You need to set and manage user accounts yourself and ensure that each user account in the same channel is unique. The maximum length of this parameter is 255 bytes. Ensure that you set this parameter and do not set it as null. Supported characters are (89 in total): + /// The 26 lowercase English letters: a to z. + /// The 26 uppercase English letters: A to Z. + /// All numeric characters: 0 to 9. + /// Space + /// "!", "#", "$", "%", "&", "(", ")", "+", "-", ":", ";", "<", "=", ".", ">", "?", "@", "[", "]", "^", "_", "{", "}", "|", "~", "," /// - /// **Parameter** [appId] The App ID of your project. /// - /// **Parameter** [userAccount] The user account. The maximum length of this parameter is 255 bytes. Ensure that you set this parameter and do not set it as null. Supported character scopes are: - /// - All lowercase English letters: a to z. - /// - All uppercase English letters: A to Z. - /// - All numeric characters: 0 to 9. - /// - The space character. - /// - Punctuation characters and other symbols, including: "!", "#", "$", "%", "&", "(", ")", "+", "-", ":", ";", "<", "=", ".", ">", "?", "@", "\[", "\]", "^", "_", " {", "}", "|", "~", ",". Future registerLocalUserAccount(String appId, String userAccount); - /// Joins the channel with a user account. /// - /// After the user successfully joins the channel, the SDK triggers the following callbacks: - /// - The local client: [RtcEngineEventHandler.localUserRegistered] and [RtcEngineEventHandler.joinChannelSuccess]. - /// - The remote client: [RtcEngineEventHandler.userJoined] and [RtcEngineEventHandler.userInfoUpdated], if the user joining the channel is in the [ChannelProfile.Communication] profile, or is a [ClientRole.Broadcaster] in the [ChannelProfile.LiveBroadcasting] profile. + /// Joins the channel with a user account, and configures whether to automatically subscribe to audio or video streams after joining the channel. + /// This method allows a user to join the channel with the user account. After the user successfully joins the channel, the SDK triggers the following callbacks: + /// The local client: localUserRegistered, joinChannelSuccess and connectionStateChanged callbacks. + /// The remote client: The userJoined callback if the user is in the COMMUNICATION profile, and the userInfoUpdated callback if the user is a host in the LIVE_BROADCASTING profile. /// - /// **Note** - /// - To ensure smooth communication, use the same parameter type to identify the user. For example, if a user joins the channel with a user ID, then ensure all the other users use the user ID too. The same applies to the user account. If a user joins the channel with the Agora Web SDK, ensure that the uid of the user is set to the same parameter type. + /// Once a user joins the channel, the user subscribes to the audio and video streams of all the other users in the channel by default, giving rise to usage and billing calculation. To stop subscribing to a specified stream or all remote streams, call the corresponding mute methods. + /// To ensure smooth communication, use the same parameter type to identify the user. For example, if a user joins the channel with a user ID, then ensure all the other users use the user ID too. The same applies to the user account. If a user joins the channel with the Agora Web SDK, ensure that the ID of the user is set to the same parameter type. /// - /// **Parameter** [token] The token generated at your server. Set it as the token generated at your server. For details, see [Get a token](https://docs.agora.io/en/Agora%20Platform/token?platform=All%20Platforms#generatetoken). + /// Param [options] The channel media options. For details, see ChannelMediaOptions. + /// + /// Param [token] + /// + /// Param [userAccount] The user account. This parameter is used to identify the user in the channel for real-time audio and video engagement. You need to set and manage user accounts yourself and ensure that each user account in the same channel is unique.The maximum length of this parameter is 255 bytes. Ensure that you set this parameter and do not set it as null. Supported characters are (89 in total): + /// The 26 lowercase English letters: a to z. + /// The 26 uppercase English letters: A to Z. + /// All numeric characters: 0 to 9. + /// Space + /// "!", "#", "$", "%", "&", "(", ")", "+", "-", ":", ";", "<", "=", ".", ">", "?", "@", "[", "]", "^", "_", "{", "}", "|", "~", "," /// - /// **Parameter** [channelName] The channel name. The maximum length of this parameter is 64 bytes. Supported character scopes are: - /// - All lowercase English letters: a to z. - /// - All uppercase English letters: A to Z. - /// - All numeric characters: 0 to 9. - /// - The space character. - /// - Punctuation characters and other symbols, including: "!", "#", "$", "%", "&", "(", ")", "+", "-", ":", ";", "<", "=", ".", ">", "?", "@", "\[", "\]", "^", "_", " {", "}", "|", "~", ",". /// - /// **Parameter** [userAccount] The user account. The maximum length of this parameter is 255 bytes. Ensure that you set this parameter and do not set it as null. - /// - All lowercase English letters: a to z. - /// - All uppercase English letters: A to Z. - /// - All numeric characters: 0 to 9. - /// - The space character. - /// - Punctuation characters and other symbols, including: "!", "#", "$", "%", "&", "(", ")", "+", "-", ":", ";", "<", "=", ".", ">", "?", "@", "\[", "\]", "^", "_", " {", "}", "|", "~", ",". /// - /// **Parameter** [options] The channel media options: [ChannelMediaOptions]. Future joinChannelWithUserAccount( String? token, String channelName, String userAccount, [ChannelMediaOptions? options]); + /// /// Gets the user information by passing in the user account. + /// After a remote user joins the channel, the SDK gets the UID and user account of the remote user, caches them in a mapping table object, and triggers the userInfoUpdated callback on the local client. After receiving the callback, you can call this method to get the user account of the remote user from the UserInfo object by passing in the user ID. /// - /// After a remote user joins the channel, the SDK gets the user ID and user account of the remote user, caches them in a mapping table object ([UserInfo]), and triggers the [RtcEngineEventHandler.userInfoUpdated] callback on the local client. + /// Param [userAccount] The user account. /// - /// After receiving the [RtcEngineEventHandler.userInfoUpdated] callback, you can call this method to get the user ID of the remote user from the [UserInfo] object by passing in the user account. + /// **return** The UserInfo object that identifies the user information. /// - /// **Parameter** [userAccount] The user account of the user. Ensure that you set this parameter. + /// Not null: Success. + /// Null: Failure. /// - /// **Returns** - /// - [UserInfo], if this method call succeeds. - /// - Error code, if this method call fails. - /// - [ErrorCode.InvalidArgument] - /// - [ErrorCode.NotReady] - /// - [ErrorCode.Refused] Future getUserInfoByUserAccount(String userAccount); + /// /// Gets the user information by passing in the user ID. + /// After a remote user joins the channel, the SDK gets the UID and user account of the remote user, caches them in a mapping table object, and triggers the userInfoUpdated callback on the local client. After receiving the callback, you can call this method to get the user account of the remote user from the UserInfo object by passing in the user ID. /// - /// After a remote user joins the channel, the SDK gets the user ID and user account of the remote user, caches them in a mapping table object ([UserInfo]), and triggers the [RtcEngineEventHandler.userInfoUpdated] callback on the local client. + /// Param [uid] User ID. /// - /// After receiving the [RtcEngineEventHandler.userInfoUpdated] callback, you can call this method to get the user ID of the remote user from the [UserInfo] object by passing in the user account. + /// **return** The UserInfo object that identifies the user information. /// - /// **Parameter** [uid] The user ID of the user. Ensure that you set this parameter. + /// Not null: Success. + /// Null: Failure. /// - /// **Returns** - /// - [UserInfo], if this method call succeeds. - /// - Error code, if this method call fails. - /// - [ErrorCode.InvalidArgument] - /// - [ErrorCode.NotReady] - /// - [ErrorCode.Refused] Future getUserInfoByUid(int uid); } /// @nodoc mixin RtcAudioInterface { + /// /// Enables the audio module. + /// The audio mode is enabled by default. /// - /// The audio module is enabled by default. + /// This method enables the internal engine and can be called anytime after initialization. It is still valid after one leaves channel. + /// This method enables the audio module and takes some time to take effect. Agora recommends using the following API methods to control the audio module separately: + /// enableLocalAudio: Whether to enable the microphone to create the local audio stream. + /// muteLocalAudioStream: Whether to publish the local audio stream. + /// muteRemoteAudioStream: Whether to subscribe and play the remote audio stream. + /// muteAllRemoteAudioStreams: Whether to subscribe to and play all remote audio streams. /// - /// **Note** - /// - This method affects the audio module and can be called after calling the [RtcEngine.leaveChannel] method. You can call this method either before or after joining a channel. - /// - This method enables the audio module and takes some time to take effect. Agora recommends using the following API methods to control the audio engine modules separately: - /// - [RtcEngine.enableLocalAudio]: Whether to enable the microphone to create the local audio stream. - /// - [RtcEngine.muteLocalAudioStream]: Whether to publish the local audio stream. - /// - [RtcEngine.muteRemoteAudioStream]: Whether to subscribe to and play the remote audio stream. - /// - [RtcEngine.muteAllRemoteAudioStreams]: Whether to subscribe to and play all remote audio streams. Future enableAudio(); + /// /// Disables the audio module. + /// This method disables the internal engine and can be called anytime after initialization. It is still valid after one leaves channel. + /// This method resets the internal engine and takes some time to take effect. Agora recommends using the following API methods to control the audio modules separately: + /// enableLocalAudio: Whether to enable the microphone to create the local audio stream. + /// muteLocalAudioStream: Whether to publish the local audio stream. + /// muteRemoteAudioStream: Whether to subscribe and play the remote audio stream. + /// muteAllRemoteAudioStreams: Whether to subscribe to and play all remote audio streams. /// - /// **Note** - /// - This method affects the audio module and can be called after calling the [RtcEngine.leaveChannel] method. You can call this method either before or after joining a channel. - /// - This method disables the audio module and takes some time to take effect. Agora recommends using the following API methods to control the audio engine module separately: - /// - [RtcEngine.enableLocalAudio]: Whether to enable the microphone to create the local audio stream. - /// - [RtcEngine.muteLocalAudioStream]: Whether to publish the local audio stream. - /// - [RtcEngine.muteRemoteAudioStream]: Whether to subscribe to and play the remote audio stream. - /// - [RtcEngine.muteAllRemoteAudioStreams]: Whether to subscribe to and play all remote audio streams. Future disableAudio(); - /// Sets the audio parameters and application scenarios. /// - /// **Note** - /// - You must call this method before calling the joinChannel method. - /// See [RtcEngine.joinChannel] - /// - In the Communication and [ChannelProfile.LiveBroadcasting] profiles, the bitrates may be different from your settings due to network self-adaptation. - /// - In scenarios requiring high-quality audio, we recommend setting profile as [AudioScenario.ShowRoom] and scenario as [AudioScenario.GameStreaming]. For example, for music education scenarios. + /// Sets the audio profile and audio scenario. + /// In scenarios requiring high-quality audio, such as online music tutoring, Agora recommends you set profile as MusicHighQuality (4), and scenario as GameStreaming (3) + /// + /// Param [profile] The audio profile, including the sampling rate, bitrate, encoding mode, and the number of channels. See AudioProfile. + /// /// - /// **Parameter** [profile] Sets the sample rate, bitrate, encoding mode, and the number of channels. See [AudioProfile]. + /// Param [scenario] The audio scenario. See AudioScenario. Under different audio scenarios, the device uses different volume types. /// - /// **Parameter** [scenario] Sets the audio application scenarios. Under different audio scenarios, the device uses different volume tracks, i.e. either the in-call volume or the media volume. See [AudioScenario]. Future setAudioProfile(AudioProfile profile, AudioScenario scenario); - /// Adjusts the recording volume. /// - /// **Note** - /// - To avoid echoes and improve call quality, Agora recommends setting the value of volume between 0 and 100. If you need to set the value higher than 100, contact support@agora.io first. + /// Adjusts the capturing signal volume. + /// You can call this method either before or after joining a channel. + /// + /// Param [volume] Integer only. The value range is [0,400]. + /// 0: Mute. + /// 100: (Default) The original volume. + /// 400: Four times the original volume (amplifying the audio signals by four times). + /// + /// /// - /// **Parameter** [volume] Recording volume. The value ranges between 0 and 400: - /// - 0: Mute. - /// - 100: Original volume. - /// - 400: (Maximum) Four times the original volume with signal-clipping protection. Future adjustRecordingSignalVolume(int volume); - /// Adjusts the playback volume of a specified remote user. /// - /// You can call this method as many times as necessary to adjust the playback volume of different remote users, or to repeatedly adjust the playback volume of the same remote user. + /// Adjusts the playback signal volume of a specified remote user. + /// You can call this method to adjust the playback volume of a specified remote user. To adjust the playback volume of different remote users, call the method as many times, once for each remote user. /// - /// **Note** - /// - Call this method after joining a channel. - /// - The playback volume here refers to the mixed volume of a specified remote user. - /// - This method can only adjust the playback volume of one specified remote user at a time. To adjust the playback volume of different remote users, call the method as many times, once for each remote user. /// - /// **Parameter** [uid] ID of the remote user. + /// Call this method after joining a channel. + /// The playback volume here refers to the mixed volume of a specified remote user. + /// + /// Param [volume] Audio mixing volume. The value ranges between 0 and 100. The default value is 100, the original volume. + /// + /// Param [uid] The ID of the remote user. /// - /// **Parameter** [volume] Recording volume. The value ranges between 0 and 400: - /// - 0: Mute. - /// - 100: Original volume. - /// - 400: (Maximum) Four times the original volume with signal-clipping protection. Future adjustUserPlaybackSignalVolume(int uid, int volume); - /// Adjusts the playback volume of all remote users. /// - /// **Note** - /// - This method adjusts the playback volume which is mixed volume of all remote users. - /// - To mute the local audio playback, call both [RtcEngine.adjustPlaybackSignalVolume] and [RtcEngine.adjustAudioMixingVolume], and set volume as 0. - /// - To avoid echoes and improve call quality, Agora recommends setting the value of volume between 0 and 100. If you need to set the value higher than 100, contact support@agora.io first. + /// Adjusts the playback signal volume of all remote users. + /// This method adjusts the playback volume that is the mixed volume of all remote users. + /// You can call this method either before or after joining a channel. + /// + /// Param [volume] Integer only. The value range is [0,400]. + /// 0: Mute. + /// 100: (Default) The original volume. + /// 400: Four times the original volume (amplifying the audio signals by four times). + /// + /// /// - /// **Parameter** [volume] The playback volume of all remote users. The value ranges from 0 to 400: - /// - 0: Mute. - /// - 100: The original volume. - /// - 400: (Maximum) Four times the original volume with signal clipping protection. Future adjustPlaybackSignalVolume(int volume); + /// /// Enables/Disables the local audio capture. + /// The audio function is enabled by default. This method disables or re-enables the local audio function to stop or restart local audio capturing. + /// This method does not affect receiving or playing the remote audio streams, and enableLocalAudio(false) applies to scenarios where the user wants to receive remote audio streams without sending any audio stream to other users in the channel. + /// Once the local audio function is disabled or re-enabled, the SDK triggers the localAudioStateChanged callback, which reports Stopped(0) or Recording(1). + /// This method is different from the muteLocalAudioStream method: + /// enableLocalVideo: Disables/Re-enables the local audio capturing and processing. If you disable or re-enable local audio capturing using the enableLocalAudio method, the local user might hear a pause in the remote audio playback. + /// muteLocalAudioStream: Sends/Stops sending the local audio streams. /// - /// The audio function is enabled by default. This method disables/re-enables the local audio function, that is, to stop or restart local audio capture and processing. /// - /// This method does not affect receiving or playing the remote audio streams, and `enableLocalAudio(false)` is applicable to scenarios where the user wants to receive remote audio streams without sending any audio stream to other users in the channel. + /// You can call this method either before or after joining a channel. + /// + /// Param [enabled] true: (Default) Re-enable the local audio function, that is, to start the local audio capturing device (for example, the microphone). + /// false: Disable the local audio function, that is, to stop local audio capturing. /// - /// The SDK triggers the [RtcEngineEventHandler.microphoneEnabled] callback once the local audio function is disabled or re-enabled. /// - /// **Note** - /// - This method is different from the [RtcEngine.muteLocalAudioStream] method: - /// - [RtcEngine.enableLocalAudio]: Disables/Re-enables the local audio capture and processing. If you disable or re-enable local audio recording using the [RtcEngine.enableLocalAudio] method, the local user may hear a pause in the remote audio playback. - /// - [RtcEngine.muteLocalAudioStream]: Stops/Continues sending the local audio streams. /// - /// **Parameter** [enabled] Sets whether to disable/re-enable the local audio function: - /// - `true`: (Default) Re-enable the local audio function, that is, to start local audio capture and processing. - /// - `false`: Disable the local audio function, that is, to stop local audio capture and processing. Future enableLocalAudio(bool enabled); - /// Stops/Resumes sending the local audio stream. /// - /// A successful [RtcEngine.muteLocalAudioStream] method call triggers the [RtcEngineEventHandler.userMuteAudio] callback on the remote client. + /// Stops or resumes publishing the local audio stream. + /// This method does not affect any ongoing audio recording, because it does not disable the microphone. + /// + /// Param [muted] Whether to stop publishing the local audio stream. + /// + /// true: Stop publishing the local audio stream. + /// false: (Default) Resumes publishing the local audio stream. + /// /// - /// **Note** - /// - When muted is set as true, this method does not disable the microphone and thus does not affect any ongoing recording. - /// - If you call [RtcEngine.setChannelProfile] after this method, the SDK resets whether or not to mute the local audio according to the channel profile and user role. Therefore, we recommend calling this method after the [RtcEngine.setChannelProfile] method. /// - /// **Parameter** [muted] Sets whether to send/stop sending the local audio stream: - /// - `true`: Stop sending the local audio stream. - /// - `false`: (Default) Send the local audio stream. Future muteLocalAudioStream(bool muted); - /// Stops/Resumes receiving a specified audio stream. /// - /// **Note** - /// - If you called the [RtcEngine.muteAllRemoteAudioStreams] method and set muted as true to stop receiving all remote video streams, ensure that the [RtcEngine.muteAllRemoteAudioStreams] method is called and set muted as false before calling this method. The [RtcEngine.muteAllRemoteAudioStreams] method sets all remote audio streams, while the [RtcEngine.muteRemoteAudioStream] method sets a specified remote user's audio stream. + /// Stops or resumes subscribing to the audio stream of a specified user. + /// Call this method after joining a channel. + /// See recommended settings in Set the Subscribing State. + /// + /// Param [uid] The user ID of the specified user. + /// + /// Param [muted] Whether to stop subscribing to the audio stream of the specified user. + /// + /// true: Stop subscribing to the audio stream of the specified user. + /// false: (Default) Subscribe to the audio stream of the specified user. /// - /// **Parameter** [uid] ID of the specified remote user. /// - /// **Parameter** [muted] Sets whether to receive/stop receiving the specified remote user's audio stream: - /// - `true`: Stop receiving the specified remote user’s audio stream. - /// - `false`: (Default) Receive the specified remote user’s audio stream. /// - /// **Note** - /// - Call this method after joining a channel. - /// - See recommended settings in *Set the Subscribing State*. Future muteRemoteAudioStream(int uid, bool muted); - /// Stops/Resumes receiving all remote audio streams. /// - /// **Parameter** [muted] Sets whether to receive/stop receiving all remote audio streams: - /// - `true`: Stop receiving all remote audio streams. - /// - `false`: (Default) Receive all remote audio streams. + /// Stops or resumes subscribing to the audio streams of all remote users. + /// As of v3.3.0, after successfully calling this method, the local user stops or resumes subscribing to the audio streams of all remote users, including all subsequent users. + /// + /// + /// Call this method after joining a channel. + /// + /// Param [muted] Whether to subscribe to the audio streams of all remote users: + /// true: Do not subscribe to the audio streams of all remote users. + /// false: (Default) Subscribe to the audio streams of all remote users by default. + /// + /// + /// + /// Future muteAllRemoteAudioStreams(bool muted); - /// Sets whether to receive all remote audio streams by default. /// - /// You can call this method either before or after joining a channel. If you call [RtcEngine.setDefaultMuteAllRemoteAudioStreams] (true) after joining a channel, you will not receive the audio streams of any subsequent user. + /// Stops or resumes subscribing to the audio streams of all remote users by default. + /// Call this method after joining a channel. After successfully calling this method, the local user stops or resumes subscribing to the audio streams of all subsequent users. + /// + /// If you need to resume subscribing to the audio streams of remote users in the channel after calling this method, do the following: + /// To resume subscribing to the audio stream of a specified user, call muteRemoteAudioStream(false), and specify the user ID. + /// To resume subscribing to the audio streams of multiple remote users, call muteRemoteAudioStream (false)multiple times. + /// + /// Param [muted] Whether to stop subscribing to the audio streams of all remote users by default. + /// true: Stop subscribing to the audio streams of all remote users by default. + /// false: (Default) Subscribe to the audio streams of all remote users by default. /// - /// **Deprecated** /// - /// This method is deprecated from v3.3.1. /// - /// **Note** - /// - If you want to resume receiving audio streams, call [RtcEngine.muteRemoteAudioStream] (false), and specify the ID of the remote user that you want to subscribe to. To resume audio streams of multiple users, call [RtcEngine.muteRemoteAudioStream] as many times. Calling [RtcEngine.setDefaultMuteAllRemoteAudioStreams] (false) resumes receiving audio streams of the subsequent users only. /// - /// **Parameter** [muted] Sets whether or not to receive/stop receiving the remote audio streams by default: - /// - `true`: Stop receiving any audio stream by default. - /// - `false`: (Default) Receive all remote audio streams by default. @deprecated Future setDefaultMuteAllRemoteAudioStreams(bool muted); - /// Enables the [RtcEngineEventHandler.audioVolumeIndication] callback at a set time interval to report on which users are speaking and the speakers' volume. /// - /// Once this method is enabled, the SDK returns the volume indication in the [RtcEngineEventHandler.audioVolumeIndication] callback at the set time interval, regardless of whether any user is speaking in the channel. + /// Enables the reporting of users' volume indication. + /// This method enables the SDK to regularly report the volume information of the local user who sends a stream and remote users (up to three) whose instantaneous volumes are the highest to the app. Once you call this method and users send streams in the channel, the SDK triggers the audioVolumeIndication callback at the time interval set in this method. + /// You can call this method either before or after joining a channel. + /// + /// Param [interval] Sets the time interval between two consecutive volume indications: + /// ≤ 0: Disables the volume indication. + /// > 0: Time interval (ms) between two consecutive volume indications. We recommend a setting greater than 200 ms. Do not set this parameter to less than 10 milliseconds, otherwise the audioVolumeIndication callback will not be triggered. /// - /// **Parameter** [interval] Sets the time interval between two consecutive volume indications: - /// - ≤ 0: Disables the volume indication. - /// - > 0: Time interval (ms) between two consecutive volume indications. We recommend setting interval ≥ 200 ms. /// - /// **Parameter** [smooth] The smoothing factor sets the sensitivity of the audio volume indicator. The value ranges between 0 and 10. The greater the value, the more sensitive the indicator. The recommended value is 3. + /// Param [smooth] /// - /// **Parameter** [report_vad] - /// - `true`: Enable the voice activity detection of the local user. Once it is enabled, the vad parameter of the [RtcEngineEventHandler.audioVolumeIndication] callback reports the voice activity status of the local user. - /// - `false`: (Default) Disable the voice activity detection of the local user. Once it is disabled, the vad parameter of the [RtcEngineEventHandler.audioVolumeIndication] callback does not report the voice activity status of the local user, except for scenarios where the engine automatically detects the voice activity of the local user. Future enableAudioVolumeIndication( int interval, int smooth, bool report_vad); } /// @nodoc mixin RtcVideoInterface { - /// Enables the video module. /// - /// You can call this method either before joining a channel or during a call. If you call this method before joining a channel, the service starts in the video mode. If you call this method during an audio call, the audio mode switches to the video mode. - /// - /// A successful enableVideo method call triggers the [RtcEngineEventHandler.userEnableVideo] (true) callback on the remote client. + /// Enables the video module. + /// Call this method either before joining a channel or during a call. If this method is called before joining a channel, the call starts in the video mode. Call disableVideo to disable the video mode.A successful call of this method triggers the remoteVideoStateChanged callback on the remote client. /// - /// To disable the video, call the [RtcEngine.disableVideo] method. + /// This method enables the internal engine and is valid after leaving the channel. + /// This method resets the internal engine and takes some time to take effect. Agora recommends using the following API methods to control the video engine modules separately: + /// enableLocalVideo: Whether to enable the camera to create the local video stream. + /// muteLocalVideoStream: Whether to publish the local video stream. + /// muteRemoteVideoStream: Whether to subscribe to and play the remote video stream. + /// muteAllRemoteVideoStreams: Whether to subscribe to and play all remote video streams. /// - /// **Note** - /// - This method affects the internal engine and can be called after calling the [RtcEngine.leaveChannel] method. You can call this method either before or after joining a channel. - /// - This method resets the internal engine and takes some time to take effect. We recommend using the following API methods to control the video engine modules separately: - /// - [RtcEngine.enableLocalVideo]: Whether to enable the camera to create the local video stream. - /// - [RtcEngine.muteLocalVideoStream]: Whether to publish the local video stream. - /// - [RtcEngine.muteRemoteVideoStream]: Whether to subscribe to and play the remote video stream. - /// - [RtcEngine.muteAllRemoteVideoStreams]: Whether to subscribe to and play all remote video streams. Future enableVideo(); + /// /// Disables the video module. + /// This method disables video. You can call this method either before or after joining a channel. If you call it before joining a channel, an audio call starts when you join the channel. If you call it after joining a channel, a video call switches to an audio call. Call enableVideo to enable video.A successful call of this method triggers the userEnableVideo(false) callback on the remote client. + /// + /// This method affects the internal engine and can be called after leaving the channel. + /// This method resets the internal engine and takes some time to take effect. Agora recommends using the following API methods to control the video engine modules separately: + /// enableLocalVideo: Whether to enable the camera to create the local video stream. + /// muteLocalVideoStream: Whether to publish the local video stream. + /// muteRemoteVideoStream: Whether to subscribe to and play the remote video stream. + /// muteAllRemoteVideoStreams: Whether to subscribe to and play all remote video streams. /// - /// You can call this method before joining a channel or during a call. If you call this method before joining a channel, the service starts in audio mode. If you call this method during a video call, the video mode switches to the audio mode. - /// - A successful disableVideo method call triggers the [RtcEngineEventHandler.userEnableVideo] (false) callback on the remote client. - /// - To enable the video mode, call the [RtcEngine.enableVideo] method. - /// - /// **Note** - /// - This method affects the internal engine and can be called after calling the [RtcEngine.leaveChannel] method. You can call this method either before or after joining a channel. - /// - This method resets the internal engine and takes some time to take effect. We recommend using the following API methods to control the video engine modules separately: - /// - [RtcEngine.enableLocalVideo]: Whether to enable the camera to create the local video stream. - /// - [RtcEngine.muteLocalVideoStream]: Whether to publish the local video stream. - /// - [RtcEngine.muteRemoteVideoStream]: Whether to subscribe to and play the remote video stream. - /// - [RtcEngine.muteAllRemoteVideoStreams]: Whether to subscribe to and play all remote video streams. Future disableVideo(); + /// /// Sets the video encoder configuration. + /// Sets the encoder configuration for the local video. + /// You can call this method either before or after joining a channel. If the user does not need to reset the video encoding properties after joining the channel, Agora recommends calling this method before enableVideo to reduce the time to render the first video frame. /// - /// Each video encoder configuration corresponds to a set of video parameters, including the resolution, frame rate, bitrate, and video orientation. The parameters specified in this method are the maximum values under ideal network conditions. If the video engine cannot render the video using the specified parameters due to poor network conditions, the parameters further down the list are considered until a successful configuration is found. - /// If you do not set the video encoder configuration after joining the channel, you can call this method before calling the [RtcEngine.enableVideo] method to reduce the render time of the first video frame. + /// Param [config] Video profile. For details, see VideoEncoderConfiguration. /// - /// **Parameter** [config] The local video encoder configuration. See [VideoEncoderConfiguration]. Future setVideoEncoderConfiguration(VideoEncoderConfiguration config); - /// Starts the local video preview before joining a channel. /// - /// Before calling this method, you must: - /// - Create the RtcLocalView. - /// - (Android only) See [TextureView] and [SurfaceView]. - /// - (iOS only) See [UIView](https://developer.apple.com/documentation/uikit/uiview). - /// - Call the [RtcEngine.enableVideo] method to enable the video. + /// Enables the local video preview. + /// This method starts the local video preview before joining the channel. Before calling this method, ensure that you do the following: + /// + /// Call enableVideo to enable the video. + /// + /// + /// + /// The local preview enables the mirror mode by default. + /// After the local video preview is enabled, if you call leaveChannel to exit the channel, the local preview remains until you call stopPreview to disable it. /// - /// **Note** - /// - By default, the local preview enables the mirror mode. - /// - Once you call this method to start the local video preview, if you leave the channel by calling the [RtcEngine.leaveChannel] method, the local video preview remains until you call the [RtcEngine.stopPreview] method to disable it. Future startPreview(); - /// Stops the local video preview and the video. /// - /// After calling `startPreview`, if you want to stop the local video preview, call `stopPreview`. + /// Stops the local video preview. /// - /// **Note** /// - /// Call this method before you join the channel or after you leave the channel. Future stopPreview(); - /// Disables/Re-enables the local video capture. /// + /// Enables/Disables the local video capture. /// This method disables or re-enables the local video capturer, and does not affect receiving the remote video stream. + /// After calling enableVideo, the local video capturer is enabled by default. You can call enableLocalVideo(false) to disable the local video capturer. If you want to re-enable the local video, call enableLocalVideo(true). + /// After the local video capturer is successfully disabled or re-enabled, the SDK triggers the callback on the remote clientremoteVideoStateChanged. + /// /// - /// After you call the [RtcEngine.enableVideo] method, the local video capturer is enabled by default. You can call [RtcEngine.enableVideo] (false) to disable the local video capturer. If you want to re-enable it, call [RtcEngine.enableVideo] (true). + /// You can call this method either before or after joining a channel. + /// This method enables the internal engine and is valid after . + /// + /// Param [enabled] Whether to enable the local video capture. + /// + /// true: (Default) Enable the local video capture. + /// false: Disables the local video capture. Once the local video is disabled, the remote users can no longer receive the video stream of this user, while this user can still receive the video streams of the other remote users. When set to false, this method does not require a local camera. /// - /// After the local video capturer is successfully disabled or re-enabled, the SDK triggers the [RtcEngineEventHandler.userEnableLocalVideo] callback on the remote client. /// - /// **Note** - /// - This method affects the internal engine and can be called after calling the [RtcEngine.leaveChannel] method. /// - /// **Parameter** [enabled] Sets whether to disable/re-enable the local video, including the capturer, renderer, and sender: - /// - `true`: (Default) Re-enable the local video. - /// - `false`: Disable the local video. Once the local video is disabled, the remote users can no longer receive the video stream of this user, while this user can still receive the video streams of other remote users. When you set enabled as false, this method does not require a local camera. Future enableLocalVideo(bool enabled); - /// Stops/Resumes sending the local video stream. /// - /// A successful `muteLocalVideoStream` method call triggers the [RtcEngineEventHandler.userMuteVideo] callback on the remote client. + /// Stops or resumes publishing the local video stream. + /// A successful call of this method triggers the userMuteVideo callback on the remote client. /// - /// **Note** - /// - When you set muted as true, this method does not disable the camera and thus does not affect the retrieval of the local video streams. This method responds faster than calling the [RtcEngine.enableLocalVideo] method and set muted as false, which controls sending the local video stream. - /// - If you call [RtcEngine.setChannelProfile] after this method, the SDK resets whether or not to mute the local video according to the channel profile and user role. Therefore, we recommend calling this method after the [RtcEngine.setChannelProfile] method. /// - /// **Parameter** [muted] Sets whether to send/stop sending the local video stream: - /// - `true`: Stop sending the local video stream. - /// - `false`: (Default) Send the local video stream. - Future muteLocalVideoStream(bool muted); - - /// Stops/Resumes receiving a specified remote user's video stream. + /// This method executes faster than the enableLocalVideo(false) method, which controls the sending of the local video stream. + /// This method does not affect any ongoing video recording, because it does not disable the camera. /// - /// **Note** - /// - If you call the [RtcEngine.muteAllRemoteVideoStreams] method and set set muted as true to stop receiving all remote video streams, ensure that the [RtcEngine.muteAllRemoteVideoStreams] method is called and set muted as false before calling this method. The [RtcEngine.muteAllRemoteVideoStreams] method sets all remote streams, while this method sets a specified remote user's stream. + /// Param [muted] Whether to stop publishing the local video stream. + /// true: Stop publishing the local video stream. + /// false: (Default) Publish the local video stream. /// - /// **Parameter** [uid] User ID of the specified remote user. /// - /// **Parameter** [muted] Sets whether to receive/stop receiving a specified remote user's video stream: - /// - `true`: Stop receiving a specified remote user’s video stream. - /// - `false`: (Default) Receive a specified remote user’s video stream. - Future muteRemoteVideoStream(int uid, bool muted); - - /// Stops/Resumes receiving all remote video streams. /// - /// **Parameter** [muted] Sets whether to receive/stop receiving all remote video streams: - /// - `true`: Stop receiving all remote video streams. - /// - `false`: (Default) Receive all remote video streams. - Future muteAllRemoteVideoStreams(bool muted); + /// + Future muteLocalVideoStream(bool muted); - /// Sets whether to receive all remote video streams by default. /// - /// You can call this method either before or after joining a channel. If you call `setDefaultMuteAllRemoteVideoStreams`(true) after joining a channel, you will not receive the video stream of any subsequent user. + /// Stops or resumes subscribing to the video stream of a specified user. + /// Call this method after joining a channel. + /// See recommended settings in Set the Subscribing State. /// - /// **Deprecated** + /// Param [userId] The ID of the specified user. /// - /// This method is deprecated from v3.3.1. + /// Param [muted] Whether to stop subscribing to the video stream of the specified user. + /// true: Stop subscribing to the video streams of the specified user. + /// false: (Default) Subscribe to the video stream of the specified user. /// - /// **Note** - /// - If you want to resume receiving video streams, call [RtcEngine.muteRemoteVideoStream] (false), and specify the ID of the remote user that you want to subscribe to. To resume receiving video streams of multiple users, call [RtcEngine.muteRemoteVideoStream] as many times. Calling `setDefaultMuteAllRemoteVideoStreams`(false) resumes receiving video streams of the subsequent users only. /// - /// **Parameter** [muted] Sets whether to receive/stop receiving all remote video streams by default: - /// - `true`: Stop receiving any remote video stream by default. - /// - `false`: (Default) Receive all remote video streams by default. - @deprecated - Future setDefaultMuteAllRemoteVideoStreams(bool muted); + /// + Future muteRemoteVideoStream(int uid, bool muted); - /// Enables/Disables image enhancement and sets the options. /// - /// **Note** - /// - Call this method after calling [RtcEngine.enableVideo]. - /// - This method supports both Android and iOS. For Android, this method applies to Android 4.4 or later. + /// Stops or resumes subscribing to the video streams of all remote users. + /// As of v3.3.0, after successfully calling this method, the local user stops or resumes subscribing to the video streams of all remote users, including all subsequent users. /// - /// **Parameter** [enabled] Sets whether or not to enable image enhancement: - /// - `true`: Enables image enhancement. - /// - `false`: Disables image enhancement. /// - /// **Parameter** [options] The image enhancement options. See [BeautyOptions]. - Future setBeautyEffectOptions(bool enabled, BeautyOptions options); - - /// Enables/Disables the super resolution feature for a remote user’s video. (beta feature) + /// Call this method after joining a channel. /// - /// This feature effectively boosts the resolution of a remote user’s video seen by the local user. If the original resolution of a remote user’s video is a × b, the local user’s device can render the remote video at a resolution of 2a × 2b after you enable this feature. - /// After calling this method, the SDK triggers the [RtcEngineEventHandler.userSuperResolutionEnabled] callback to report whether you have successfully enabled super resolution. + /// Param [muted] Whether to stop subscribing to the video streams of all remote users. + /// true: Stop subscribing to the video streams of all remote users. + /// false: (Default) Subscribe to the audio streams of all remote users by default. /// - /// Since - /// v4.2.0 /// - /// **Parameter** [uid] The user ID of the remote user. /// - /// **Parameter** [enabled] Determines whether to enable super resolution for the remote user’s video: - /// - `true`: Enable super-resolution. - /// - `false`: Do not enable super resolution. /// + Future muteAllRemoteVideoStreams(bool muted); + + /// + /// Stops or resumes subscribing to the video streams of all remote users by default. + /// Call this method after joining a channel. After successfully calling this method, the local user stops or resumes subscribing to the audio streams of all subsequent users. + /// If you need to resume subscribing to the audio streams of remote users in the channel after calling this method, do the following:To resume subscribing to the audio stream of a specified user, call muteRemoteVideoStream(false), and specify the user ID. + /// To resume subscribing to the audio streams of multiple remote users, call muteRemoteVideoStream(false)multiple times. + /// + /// Param [muted] Whether to stop subscribing to the audio streams of all remote users by default. + /// true: Stop subscribing to the audio streams of all remote users by default. + /// false: (Default) Resume subscribing to the audio streams of all remote users by default. /// - /// **Warning** /// - /// The super resolution feature requires extra system resources. To balance the visual experience and system consumption, the SDK poses the following restrictions: /// - /// - This feature can only be enabled for a single remote user. - /// - The original resolution of the remote user’s video cannot exceed 640 × 480 pixels. - /// - If you exceed these limitations, the SDK triggers the `WarningCallback` callback and returns the corresponding warning codes: /// - /// - `SuperResolutionStreamOverLimitation(1610)`: The original resolution of the remote user’s video is beyond the range where super resolution can be applied. - /// - `SuperResolutionUserCountOverLimitation(1611)`: Super resolution is already being used to boost another remote user’s video. - /// - `SuperResolutionDeviceNotSupported(1612)`: The device does not support using super resolution. + @deprecated + Future setDefaultMuteAllRemoteVideoStreams(bool muted); + /// - /// **Notes** + /// Sets the image enhancement options. + /// Enables or disables image enhancement and sets the options. + /// Call this method after enableVideo. /// - /// Because this method has certain system performance requirements, Agora recommends that you use the following Android and iOS devices (iOS 12.0 or later) or better: + /// Param [enabled] Whether to enable the image enhancement function: + /// true: Open. + /// false: (Default) Disable the image enhancement function. /// - /// **Android** - /// - VIVO: V1821A, NEX S, 1914A, 1916A, 1962A, 1824BA, X60, X60 Pro - /// - OPPO: PCCM00, Find X3 - /// - OnePlus: A6000 - /// - Xiaomi: Mi 8, Mi 9, Mi 10, Mi 11, MIX3, Redmi K20 Pro - /// - SAMSUNG: SM-G9600, SM-G9650, SM-N9600, SM-G9708, SM-G960U, SM-G9750, S20, S21 - /// - HUAWEI: SEA-AL00, ELE-AL00, VOG-AL00, YAL-AL10, HMA-AL00, EVR-AN00, nova 4, nova 5 Pro, nova 6 5G, nova 7 5G, Mate 30, Mate 30 Pro, Mate 40, Mate 40 Pro, P40 P40 Pro, HUAWEI MediaPad M6, MatePad 10.8 /// - /// **iOS** - /// - iPhone XR - /// - iPhone XS - /// - iPhone XS Max - /// - iPhone 11 - /// - iPhone 11 Pro - /// - iPhone 11 Pro Max - /// - iPhone 12 - /// - iPhone 12 mini - /// - iPhone 12 Pro - /// - iPhone 12 Pro Max - /// - iPhone 12 SE (2nd generation) - /// - iPad Pro 11-inch (3rd generation) - /// - iPad Pro 12.9-inch (3rd generation) - /// - iPad Air (3rd generation) - /// - iPad Air (4th generation) + /// Param [options] The image enhancement options. See BeautyOptions. /// + Future setBeautyEffectOptions(bool enabled, BeautyOptions options); + /// - Future enableRemoteSuperResolution(int uid, bool enabled); + /// Enables/Disables the super-resolution algorithm for a remote user's video stream. + /// This feature effectively boosts the resolution of a remote user's video seen by the local user. If the original resolution of a remote user's video is a × b, the local user's device can render the remote video at a resolution of 2a × 2b + /// after you enable this feature. + /// After you call this method, the SDK triggers the userSuperResolutionEnabled callback to report whether you have successfully enabled super resolution. + /// The super resolution feature requires extra system resources. To balance the visual experience and system usage, the SDK poses the following restrictions: This feature can only be enabled for a single remote user. + /// On Android, the original resolution of the remote video must not exceed 640 × 360 pixels. On iOS, the original resolution of the remote video must not exceed 640 × 480 pixels. If you exceed these limitations, the SDK triggers the warning callback and returns the corresponding warning codes: + /// SuperResolutionStreamOverLimitation: 1610. The origin resolution of the remote video is beyond the range where the super resolution can be applied. + /// SuperResolutionUserCountOverLimitation: 1611. Super resolution is already being used on another remote user's video. + /// SuperResolutionDeviceNotSupported: 1612. The device does not support using super resolution. + /// + /// + /// + /// This method is for Android and iOS only. + /// Before calling this method, ensure that you have integrated the following dynamic libraries: + /// Android: libagora_super_resolution_extension.so + /// iOS: AgoraSuperResolutionExtension.xcframework + /// + /// + /// Because this method has certain system performance requirements, Agora recommends that you use the following devices or better: + /// Android: + /// VIVO: V1821A, NEX S, 1914A, 1916A, 1962A, 1824BA, X60, X60 Pro + /// OPPO: PCCM00, Find X3 + /// OnePlus: A6000 + /// Xiaomi: Mi 8, Mi 9, Mi 10, Mi 11, MIX3, Redmi K20 Pro + /// SAMSUNG: SM-G9600, SM-G9650, SM-N9600, SM-G9708, SM-G960U, SM-G9750, S20, S21 + /// HUAWEI: SEA-AL00, ELE-AL00, VOG-AL00, YAL-AL10, HMA-AL00, EVR-AN00, nova 4, nova 5 Pro, nova 6 5G, nova 7 5G, Mate 30, Mate 30 Pro, Mate 40, Mate 40 Pro, P40, P40 Pro, Huawei M6, MatePad 10.8 + /// + /// iOS: + /// iPhone XR + /// iPhone XS + /// iPhone XS Max + /// iPhone 11 + /// iPhone 11 Pro + /// iPhone 11 Pro Max + /// iPhone 12 + /// iPhone 12 mini + /// iPhone 12 Pro + /// iPhone 12 Pro Max + /// iPhone 12 SE (2nd generation) + /// iPad Pro 11-inch (3rd generation) + /// iPad Pro 12.9-inch (3rd generation) + /// iPad Air 3 (3rd generation) + /// iPad Air 3 (4th generation) + /// + /// Param [userId] The ID of the remote user. + /// + /// Param [enable] Whether to enable super resolution for the remote user’s video: + /// true: Enable virtual background. + /// false: Do not enable virtual background. + /// + /// + Future enableRemoteSuperResolution(int userId, bool enable); } /// @nodoc mixin RtcAudioMixingInterface { - /// Starts playing and mixing the music file. /// - /// This method mixes the specified local or online audio file with the audio captured by the microphone, or replaces the audio captured by the microphone with the specified local or remote audio file. You can choose whether the other user can hear the local audio playback and specify the number of playback loops. + /// Starts playing the music file. + /// This method mixes the specified local or online audio file with the audio from the microphone, or replaces the microphone's audio with the specified local or remote audio file. A successful method call triggers the audioMixingStateChanged (PLAY) callback. When the audio mixing file playback finishes, the SDK triggers the audioMixingStateChanged (STOPPED) callback on the local client. + /// + /// + /// Call this method after joining a channel. If you need to call startAudioMixing multiple times, ensure that the time interval between calling this method is more than 500 ms. + /// If the local audio mixing file does not exist, or if the SDK does not support the file format or cannot access the music file URL, the SDK returns WARN_AUDIO_MIXING_OPEN_ERROR (701). + /// + /// Param [filePath] The absolute path or URL address (including the suffixes of the filename) of the audio effect file. For example: Android: /sdcard/emulated/0/audio.mp4, iOS: /var/mobile/Containers/Data/audio.mp4. Supported audio formats include MP3, AAC, M4A, MP4, WAV, and 3GP. See supported audio formats. /// - /// After successfully playing the music file, the SDK triggers [RtcEngineEventHandler.audioMixingStateChanged] ([AudioMixingStateCode.Playing]). - /// After finishing playing the music file, the SDK triggers the [RtcEngineEventHandler.audioMixingStateChanged] ([AudioMixingStateCode.Stopped]). + /// Param [loopcount] Whether to only play music files on the local client: + /// true: Only play music files on the local client so that only the local user can hear the music. + /// false: Publish music files to remote clients so that both the local user and remote users can hear the music. /// - /// **Note** - /// - This method supports both Android and iOS. To use this method in Android, ensure that the Android device is v4.2 or later, and the API version is v16 or later. - /// - Call this method when you are in the channel, otherwise it may cause issues. - /// - If you want to play an online music file, ensure that the time interval between calling this method is more than 100 ms, or the [AudioMixingReason.TooFrequentCall] error occurs. - /// - If you want to play an online music file, Agora does not recommend using the redirected URL address. Some Android devices may fail to open a redirected URL address. - /// - If the local audio mixing file does not exist, or if the SDK does not support the file format or cannot access the music file URL, the SDK returns [AudioMixingReason.CanNotOpen]. - /// - If you call this method on an emulator, only the MP3 file format is supported. /// - /// **Parameter** [filePath] The file path, including the filename extensions. - /// - Android: To access an online file, Agora supports using a URL address; to access a local file, Agora supports using a URI address, an absolute path, or a path that starts with /assets/. Supported audio formats: mp3, mp4, m4a, aac, 3gp, mkv and wav. For details, see [Supported Media Formats](https://developer.android.com/guide/topics/media/media-formats). - /// **Note**: You might encounter permission issues if you use an absolute path to access a local file, so Agora recommends using a URI address instead. For example: "content://com.android.providers.media.documents/document/audio%3A14441". - /// - iOS: To access an online file, Agora supports using a URL address; to access a local file, Agora supports using an absolute path. For example: /var/mobile/Containers/Data/audio.mp4. - /// Supported audio formats include MP3, AAC, M4A, MP4, WAV, and 3GP. For details, see [Best Practices for iOS Audio](https://developer.apple.com/library/archive/documentation/AudioVideo/Conceptual/MultimediaPG/UsingAudio/UsingAudio.html#//apple_ref/doc/uid/TP40009767-CH2-SW28). + /// Param [replace] Whether to replace the audio captured by the microphone with a music file: + /// true: Replace the audio captured by the microphone with a music file. Users can only hear the music. + /// false: Do not replace the audio captured by the microphone with a music file. Users can hear both music and audio captured by the microphone. /// - /// **Parameter** [loopback] Whether to only play the music file on the local client: - /// - `true`: Only play music files on the local client so that only the local user can hear the music. - /// - `false`: Publish music files to remote clients so that both the local user and remote users can hear the music. /// - /// **Parameter** [replace] Whether to replace the audio captured by the microphone with a music file: - /// - `true`: Replace. Users can only hear music. - /// - `false`: Do not replace. Users can hear both music and audio captured by the microphone. + /// Param [cycle] The number of times the music file plays. + /// ≥ 0: The number of playback times. For example, 0 means that the SDK does not play the music file while 1 means that the SDK plays once. + /// -1: Play the music effect in an infinite loop. /// - /// **Parameter** [cycle] The number of times the music file plays. - /// - ≤ 0: The number of playback times. For example, 0 means that the SDK does not play the music file, while 1 means that the SDK plays the music file once. - /// - -1: Play the music in an indefinite loop. /// - /// **Parameter** [startPos] The playback position (ms) of the music file. + /// Param [startPos] The playback position (ms) of the music file. + /// Future startAudioMixing( String filePath, bool loopback, bool replace, int cycle, [int? startPos]); - /// Stops playing or mixing the music file. /// - /// Call this method when you are in a channel. + /// Stops playing and mixing the music file. + /// This method stops the audio mixing. Call this method when you are in a channel. + /// Future stopAudioMixing(); - /// Pauses playing and mixing the music file. /// + /// Pauses playing and mixing the music file. /// Call this method when you are in a channel. + /// Future pauseAudioMixing(); + /// /// Resumes playing and mixing the music file. + /// This method resumes playing and mixing the music file. Call this method when you are in a channel. /// - /// Call this method when you are in a channel. Future resumeAudioMixing(); - /// Adjusts the volume of audio mixing. /// - /// **Note** - /// - Calling this method does not affect the volume of the audio effect file playback invoked by the [RtcEngine.playEffect] method. - /// - Call this method after calling [startAudioMixing] and receiving the `audioMixingStateChanged(Playing)` callback. + /// Adjusts the volume during audio mixing. + /// This method adjusts the audio mixing volume on both the local client and remote clients. + /// + /// + /// Call this method after startAudioMixing. + /// Calling this method does not affect the volume of audio effect file playback invoked by the playEffect method. + /// + /// Param [volume] Audio mixing volume. The value ranges between 0 and 100. The default value is 100, the original volume. /// - /// **Parameter** [volume] Audio mixing volume. The value ranges between 0 and 100 (default). Future adjustAudioMixingVolume(int volume); + /// /// Adjusts the volume of audio mixing for local playback. + /// You need to call this method after calling startAudioMixing and receiving the audioMixingStateChanged(PLAY) callback. /// - /// **Note** + /// Param [volume] Audio mixing volume for local playback. The value range is [0,100]. The default value is 100, the original volume. /// - /// Call this method after calling [startAudioMixing] and receiving the `audioMixingStateChanged(Playing)` callback. - /// - /// **Parameter** [volume] Audio mixing volume for local playback. The value ranges between 0 and 100 (default). Future adjustAudioMixingPlayoutVolume(int volume); - /// Adjusts the volume of audio mixing for publishing (sending to other users). /// - /// **Note** + /// Adjusts the volume of audio mixing for publishing. + /// This method adjusts the volume of audio mixing for publishing (sending to other users). + /// You need to call this method after calling startAudioMixing and receiving the audioMixingStateChanged(PLAY) callback. /// - /// Call this method after calling [startAudioMixing] and receiving the `audioMixingStateChanged(Playing)` callback. + /// Param [volume] Audio mixing volume. The value range is [0,100]. The default value is 100, the original volume. /// - /// **Parameter** [volume] Audio mixing volume for publishing. The value ranges between 0 and 100 (default). Future adjustAudioMixingPublishVolume(int volume); - /// Gets the audio mixing volume for local playback. - /// - /// This method helps troubleshoot audio volume related issues. /// - /// **Note** + /// Retrieves the audio mixing volume for local playback. + /// This method helps troubleshoot audio volume‑related issues. + /// You need to call this method after calling startAudioMixing and receiving the audioMixingStateChanged(PLAY) callback. /// - /// Call this method after calling [startAudioMixing] and receiving the `audioMixingStateChanged(Playing)` callback. + /// **return** ≥ 0: The audio mixing volume, if this method call succeeds. The value range is [0,100]. + /// < 0: Failure. /// - /// **Returns** - /// - The audio mixing volume for local playback, if the method call is successful. The value range is [0,100]. - /// - Error code, if the method call fails. Future getAudioMixingPlayoutVolume(); - /// Gets the audio mixing volume for publishing. - /// - /// This method helps troubleshoot audio volume related issues. /// - /// **Note** + /// Retrieves the audio mixing volume for publishing. + /// This method helps troubleshoot audio volume‑related issues. + /// You need to call this method after calling startAudioMixing and receiving the audioMixingStateChanged(PLAY) callback. /// - /// Call this method after calling [RtcEngine.startAudioMixing] and receiving the `audioMixingStateChanged(Playing)` callback. + /// **return** ≥ 0: The audio mixing volume, if this method call succeeds. The value range is [0,100]. + /// < 0: Failure. /// - /// **Returns** - /// - The audio mixing volume for publishing, if the method call is successful. The value range is [0,100]. - /// - Error code, if the method call fails. Future getAudioMixingPublishVolume(); - /// Gets the total duration (ms) of the music file. /// - /// **Deprecated** + /// Retrieves the duration (ms) of the music file. + /// Call this method after joining a channel. /// - /// This method is deprecated. Use [RtcEngine.getAudioFileInfo] instead. + /// Param [filePath] The absolute path or URL address (including the suffixes of the filename) of the audio effect file. For example: Android: /sdcard/emulated/0/audio.mp4, iOS: /var/mobile/Containers/Data/audio.mp4. Supported audio formats include MP3, AAC, M4A, MP4, WAV, and 3GP. See supported audio formats. /// - /// **Note** - /// - Call this method after joining a channel. + /// **return** ≥ 0: A successful method call. Returns the total duration (ms) of the specified music file. + /// < 0: Failure. /// - /// **Parameter** [filePath] The file path, including the filename extensions. - /// - Android: Agora supports using a URI address, an absolute path, or a path that starts with /assets/. Supported audio formats: mp3, mp4, m4a, aac, 3gp, mkv and wav. For details, see [Supported Media Formats](https://developer.android.com/guide/topics/media/media-formats). - /// **Note**: You might encounter permission issues if you use an absolute path to access a local file, so Agora recommends using a URI address instead. For example: "content://com.android.providers.media.documents/document/audio%3A14441". - /// - iOS: Agora supports using an absolute path. For example: /var/mobile/Containers/Data/audio.mp4. - /// Supported audio formats include MP3, AAC, M4A, MP4, WAV, and 3GP. For details, see [Best Practices for iOS Audio](https://developer.apple.com/library/archive/documentation/AudioVideo/Conceptual/MultimediaPG/UsingAudio/UsingAudio.html#//apple_ref/doc/uid/TP40009767-CH2-SW28). - /// - /// **Returns** - /// - The total duration (ms) of the specified music file, if this method call succeeds. - /// - Error code, if this method call fails. @Deprecated( 'This method is deprecated as of v4.1.0. Use getAudioFileInfo instead.') Future getAudioMixingDuration([String? filePath]); + /// /// Gets the information of a specified audio file. + /// After calling this method successfully, the SDK triggers the requestAudioFileInfoCallback callback to report the information of an audio file, such as audio duration. You can call this method multiple times to get the information of multiple audio files. /// - /// **Since** v4.2.0 /// - /// After calling this method successfully, the SDK triggers the [RtcEngineEventHandler.requestAudioFileInfoCallback] - /// callback to report the information of an audio file, such as audio duration. - /// You can call this method multiple times to get the information of multiple audio files. + /// For the supported audio formats, see What formats of audio files does the Agora RTC SDK support. + /// Call this method after joining a channel. /// - /// **Note** - /// - Call this method after joining a channel. - /// - For the audio file formats supported by this method, see - /// [What formats of audio files does the Agora RTC SDK support](https://docs.agora.io/en/faq/audio_format). + /// Param [filePath] The file path: /// + /// Android: The file path, including the filename extensions. To access an online file, Agora + /// supports using a URL address; to access a local file, Agora supports using a URI address, an absolute path, or a path that starts + /// with /assets/. You might encounter permission issues if you use an absolute path to access a local file, so Agora recommends + /// using a URI address instead. For example: content://com.android.providers.media.documents/document/audio%3A14441. + /// Windows: The absolute path or URL address (including the filename extensions) of the audio file. + /// For example: C:\music\audio.mp4. + /// iOS or macOS: The absolute path or URL address (including the filename extensions) of the audio file. For example: /var/mobile/Containers/Data/audio.mp4. /// - /// **Parameter** [filePath] The file path, including the filename extensions. To access an - /// online file, Agora supports using a URL address; to access a local file, - /// Agora supports using a URI address, an absolute path, or a path that starts - /// with `/assets/`. You might encounter permission issues if you use an absolute - /// path to access a local file, so Agora recommends using a URI address instead. - /// For example: `content://com.android.providers.media.documents/document/audio%3A14441`. - Future getAudioFileInfo(String filePath); - - /// Gets the playback position of the audio file. /// - /// Call this method when you are in a channel. + /// **return** 0: Success. + /// < 0: Failure. /// - /// **Note** + Future getAudioFileInfo(String filePath); + /// - /// Call this method after calling [startAudioMixing] and receiving the `audioMixingStateChanged(Playing)` callback. + /// Retrieves the playback position (ms) of the music file. + /// Retrieves the playback position (ms) of the audio. + /// You need to call this method after calling startAudioMixing and receiving the audioMixingStateChanged(PLAY) callback. + /// + /// **return** ≥ 0: The current playback position of the audio mixing, if this method call succeeds. + /// < 0: Failure. /// - /// **Returns** - /// - - The current playback position (ms) of the audio file, if this method call succeeds. 0 represents that the current audio file does not start playing - /// - Error code, if this method call fails. Future getAudioMixingCurrentPosition(); - /// Sets the playback position (ms) of the music file to a different starting position (the default plays from the beginning). /// - /// **Note** + /// Sets the audio mixing position. + /// Call this method to set the playback position of the music file to a different starting position (the default plays from the beginning). + /// You need to call this method after calling startAudioMixing and receiving the audioMixingStateChanged(PLAY) callback. /// - /// Call this method after calling [startAudioMixing] and receiving the `audioMixingStateChanged(Playing)` callback. + /// Param [pos] Integer. The playback position (ms). /// - /// **Parameter** [pos] The playback starting position (ms) of the audio mixing file. Future setAudioMixingPosition(int pos); - /// Sets the pitch of the local music file. /// + /// Sets the pitch of the local music file. /// When a local music file is mixed with a local human voice, call this method to set the pitch of the local music file only. + /// You need to call this method after calling startAudioMixing and receiving the audioMixingStateChanged(Playing) callback. /// - /// **Note** - /// - Call this method after calling [RtcEngine.startAudioMixing]. - /// - Call this method after calling [startAudioMixing] and receiving the `audioMixingStateChanged(Playing)` callback. + /// Param [pitch] Sets the pitch of the local music file by the chromatic scale. The default value is 0, which means keeping the original pitch. The value ranges from -12 to 12, and the pitch value between consecutive values is a chromatic value. The greater the absolute value of this parameter, the higher or lower the pitch of the local music file. /// - /// **Parameter** [pitch] Sets the pitch of the local music file by chromatic scale. The default value is 0, which means keep the original pitch. The value ranges from -12 to 12, and the pitch value between consecutive values is a chromatic value. The greater the absolute value of this parameter, the higher or lower the pitch of the local music file. Future setAudioMixingPitch(int pitch); - /// Sets the playback speed of the current music file. /// - /// **Since** v4.2.0 + /// Sets the channel mode of the current music file. + /// Call this method after calling startAudioMixing and receiving the audioMixingStateChanged(Playing) callback. /// - /// **Parameter** [speed] The playback speed. Agora recommends that you limit this value to between `50` and `400`, defined as follows: - /// - `50`: Half the original speed. - /// - `100`: The original speed. - /// - `400`: 4 times the original speed. + /// Param [speed] The playback speed. Agora recommends that you limit this value to between 50 and 400, defined as follows: + /// 50: Half the original speed. + /// 100: The original speed. + /// 400: 4 times the original speed. /// /// - /// **Note**: Call this method after calling [startAudioMixing] and receiving the - /// [RtcEngineEventHandler.audioMixingStateChanged] event callback with state - /// code [AudioMixingStateCode.Playing]. Future setAudioMixingPlaybackSpeed(int speed); - /// Gets the audio track index of the current music file. /// - /// **Since** v4.2.0 + /// Gets the audio track index of the current music file. + /// For the supported audio formats, see What formats of audio files does the Agora RTC SDK support. + /// This method is for Android, iOS, and Windows only. + /// Call this method after calling startAudioMixing and receiving the audioMixingStateChanged(AUDIO_MIXING_STATE_PLAYING) + /// callback. /// - /// **Note**: - /// - Call this method after calling [startAudioMixing] and receiving the - /// [RtcEngineEventHandler.audioMixingStateChanged] event callback with state - /// code [AudioMixingStateCode.Playing]. - /// - For the audio file formats supported by this method, see - /// [What formats of audio files does the Agora RTC SDK support](https://docs.agora.io/en/faq/audio_format). + /// **return** ≥ 0: The audio track index of the current music file, if this method call + /// succeeds. + /// < 0: Failure. /// - /// **Returns** - /// - ≥ 0: The audio track index of the current music file, if this method call succeeds. - /// - < 0: Failure. Future getAudioTrackCount(); - /// Specifies the playback track [index] of the current music file. /// - /// **Since** v4.2.0 + /// Selects the audio track used during playback. + /// If the media file has multiple audio tracks, you can call this method to select the audio track used during playback. /// - /// After getting the audio track index of the current music file, call this - /// method to specify any audio track to play. For example, if different tracks - /// of a multitrack file store songs in different languages, you can call this - /// method to set the language of the music file to play. + /// Param [index] The index of the audio track. /// - /// **Parameter** [index] The specified playback track. This parameter must be less than or equal to the return value of [getAudioTrackCount]. - /// - /// **Note**: - /// - Call this method after calling [startAudioMixing] and receiving the - /// [RtcEngineEventHandler.audioMixingStateChanged] event callback with state - /// code [AudioMixingStateCode.Playing]. - /// - For the audio file formats supported by this method, see - /// [What formats of audio files does the Agora RTC SDK support](https://docs.agora.io/en/faq/audio_format). Future selectAudioTrack(int index); - /// Sets the channel [mode] of the current music file. - /// - /// In a stereo music file, the left and right channels can store different - /// audio data. According to your needs, you can set the channel mode to original - /// mode, left channel mode, right channel mode, or mixed channel mode. For example, - /// in the KTV scenario, the left channel of the music file stores the musical - /// accompaniment, and the right channel stores the singing voice. If you only - /// need to listen to the accompaniment, call this method to set the channel - /// mode of the music file to left channel mode; if you need to listen to the - /// accompaniment and the singing voice at the same time, call this method to - /// set the channel mode to mixed channel mode. - /// - /// **Parameter** [mode] The channel mode. See [AudioMixingDualMonoMode]. - /// - /// **Note**: - /// - Call this method after calling [startAudioMixing] and receiving the - /// [RtcEngineEventHandler.audioMixingStateChanged] event callback with state - /// code [AudioMixingStateCode.Playing]. - /// - This method only applies to stereo audio files. + /// + /// Sets the channel mode of the current audio file. + /// In a stereo music file, the left and right channels can store different audio data. According to your needs, you can set the channel mode to original mode, left channel mode, right channel mode, or mixed channel mode. For example, in the KTV scenario, the left channel of the music file stores the musical accompaniment, and the right channel stores the singing voice. If you only need to listen to the accompaniment, call this method to set the channel mode of the music file to left channel mode; if you need to listen to the accompaniment and the singing voice at the same time, call this method to set the channel mode to mixed channel mode. + /// + /// Call this method after calling startAudioMixing and receiving the audioMixingStateChanged (Playing) callback. + /// This method only applies to stereo audio files. + /// + /// Param [mode] The channel mode. For details, see AudioMixingDualMonoMode. + /// Future setAudioMixingDualMonoMode(AudioMixingDualMonoMode mode); } /// @nodoc mixin RtcAudioEffectInterface { - /// Gets the volume of the audio effects. /// - /// The value ranges between 0.0 and 100.0. + /// Retrieves the volume of the audio effects. + /// The volume is an integer ranging from 0 to 100. The default value is 100, the original volume. + /// + /// **return** Volume of the audio effects, if this method call succeeds. + /// < 0: Failure. /// - /// **Returns** - /// - Volume of the audio effects, if this method call succeeds. - /// - Error code, if this method call fails. Future getEffectsVolume(); + /// /// Sets the volume of the audio effects. /// - /// **Parameter** [volume] Volume of the audio effects. The value ranges between 0.0 and 100.0 (default). - Future setEffectsVolume(double volume); + /// + /// Param [volume] The playback volume. The value ranges from 0 to 100. The default value is 100, which represents the original volume. + /// + Future setEffectsVolume(int volume); + /// /// Sets the volume of a specified audio effect. /// - /// **Parameter** [soundId] ID of the audio effect. Each audio effect has a unique ID. /// - /// **Parameter** [volume] Volume of the audio effect. The value ranges between 0.0 and 100.0 (default). - Future setVolumeOfEffect(int soundId, double volume); + /// Param [soundId] The ID of the audio effect. Each audio effect has a unique ID. + /// + /// Param [volume] The playback volume. The value ranges from 0 to 100. The default value is 100, which represents the original volume. + /// + Future setVolumeOfEffect(int soundId, int volume); - /// Plays a specified local or online audio effect file. /// - /// With this method, you can set the loop count, pitch, pan, and gain of the audio effect file and whether the remote user can hear the audio effect. + /// Plays the specified local or online audio effect file. + /// To play multiple audio effect files at the same time, call this method multiple times with different soundId and filePath. For the best user experience, Agora recommends playing no more than three audio effect files at the same time. After the playback of an audio effect file completes, the SDK triggers the audioEffectFinished callback.Call this method after joining a channel. + /// + /// Param [soundId] The audio effect ID. The ID of each audio effect file is unique.If you have preloaded an audio effect into memory by calling preloadEffect, ensure that this parameter is set to the same value as soundId in preloadEffect. + /// + /// + /// Param [filePath] The absolute path or URL address (including the suffixes of the filename) of the audio effect file. For example: Android: /sdcard/emulated/0/audio.mp4, iOS: /var/mobile/Containers/Data/audio.mp4. Supported audio formats include MP3, AAC, M4A, MP4, WAV, and 3GP. See supported audio formats. + /// If you have preloaded an audio effect into memory by calling preloadEffect, ensure that this parameter is set to the same value as filePath in preloadEffect. + /// + /// + /// Param [loopCount] The number of times the audio effect loops: + /// ≥ 0: The number of playback times. For example, 1 means loop one time, which means play the audio effect two times in total. + /// -1: Play the music effect in an infinite loop. /// - /// To play multiple audio effect files simultaneously, call this method multiple times with different soundIds and filePaths. We recommend playing no more than three audio effect files at the same time. /// - /// After completing playing an audio effect file, the SDK triggers the [RtcEngineEventHandler.audioEffectFinished] callback. /// - /// **Note** - /// - Call this method joining a channel. + /// Param [pitch] The pitch of the audio effect. The value range is 0.5 to 2.0. The default value is 1.0, which means the original pitch. The lower the value, the lower the pitch. /// - /// **Parameter** [soundId] Audio effect ID. The ID of each audio effect file is unique. If you preloaded the audio effect into the memory through the [RtcEngine.preloadEffect] method, ensure that this parameter is set to the same value as in [RtcEngine.preloadEffect]. + /// Param [pan] The spatial position of the audio effect. The value range is 1 to10000. + /// -1.0: The audio effect displays to the left. + /// 0.0: The audio effect displays ahead. + /// 1.0: The audio effect displays to the right. /// - /// **Parameter** [filePath] The file path, including the filename extensions. - /// - Android: To access an online file, Agora supports using a URL address; to access a local file, Agora supports using a URI address, an absolute path, or a path that starts with /assets/. Supported audio formats: mp3, mp4, m4a, aac, 3gp, mkv and wav. For details, see [Supported Media Formats](https://developer.android.com/guide/topics/media/media-formats). - /// **Note**: You might encounter permission issues if you use an absolute path to access a local file, so Agora recommends using a URI address instead. For example: "content://com.android.providers.media.documents/document/audio%3A14441". - /// - iOS: To access an online file, Agora supports using a URL address; to access a local file, Agora supports using an absolute path. For example: /var/mobile/Containers/Data/audio.mp4. - /// Supported audio formats include MP3, AAC, M4A, MP4, WAV, and 3GP. For details, see [Best Practices for iOS Audio](https://developer.apple.com/library/archive/documentation/AudioVideo/Conceptual/MultimediaPG/UsingAudio/UsingAudio.html#//apple_ref/doc/uid/TP40009767-CH2-SW28). /// - /// **Parameter** [loopCount] The number of times the audio effect loops: - /// - ≥ 0: The number of loops. For example, `1` means loop one time, which means play the audio effect two times in total. - /// - -1: Play the audio effect in an indefinite loop. /// - /// **Parameter** [pitch] The pitch of the audio effect. The range is [0.5,2.0]. The default value is 1.0, which means the original pitch. The lower the value, the lower the pitch. + /// Param [gain] The volume of the audio effect. The value range is 1 to10000. The default value is 100.0, which means the original volume. The smaller the value, the lower the volume. /// - /// **Parameter** [pan] The spatial position of the audio effect. The range is [-1.0,1.0]. For example: - /// - -1.0: The audio effect occurs on the left. - /// - 0.0: The audio effect occurs in the front. - /// - 1.0: The audio effect occurs on the right. + /// Param [publish] Whether to publish the audio effect to the remote users. + /// true: Publish the audio effect to the remote users. Both the local user and remote users can hear the audio effect. + /// false: Do not publish the audio effect to the remote users. Only the local user can hear the audio effect. /// - /// **Parameter** [gain] The volume of the audio effect. The range is [0.0,100.0]. The default value is 100.0, which means the original volume. The smaller the value, the less the gain. /// - /// **Parameter** [publish] Whether to publish the audio effect to the remote users: - /// - `true`: Publish. Both the local user and remote users can hear the audio effect. - /// - `false`: Do not publish. Only the local user can hear the audio effect. /// - /// **Parameter** [startPos] The playback position (ms) of the audio effect file. + /// Param [startPos] The playback position (ms) of the audio effect file. + /// + /// Future playEffect(int soundId, String filePath, int loopCount, - double pitch, double pan, double gain, bool publish, + double pitch, double pan, int gain, bool publish, [int? startPos]); - /// Sets the playback position of an audio effect file. - /// - /// Since v3.4.2 /// + /// Sets the playback position of an audio effect file. /// After a successful setting, the local audio effect file starts playing at the specified position. + /// Call this method after playEffect. /// - /// **Note** - /// - Call this method after [RtcEngine.playEffect]. + /// Param [soundId] The ID of the audio effect. Each audio effect has a unique ID. /// - /// **Parameter** [soundId] Audio effect ID. Ensure that this parameter is set to the same value as in `playEffect`. + /// Param [pos] The playback position (ms) of the audio effect file. /// - /// **Parameter** [pos] The playback position (ms) of the audio effect file. Future setEffectPosition(int soundId, int pos); - /// Gets the duration of the audio effect file. /// - /// Since v3.4.2 + /// Retrieves the duration of the audio effect file. + /// Call this method after joining a channel. /// - /// **Note** - /// Call this method after [RtcEngine.playEffect]. + /// Param [filePath] The absolute path or URL address (including the suffixes of the filename) of the audio effect file. For example: Android: /sdcard/emulated/0/audio.mp4, iOS: /var/mobile/Containers/Data/audio.mp4. Supported audio formats include MP3, AAC, M4A, MP4, WAV, and 3GP. See supported audio formats. /// - /// **Parameter** [filePath] The file path, including the filename extensions. - /// - Android: Agora supports using a URI address, an absolute path, or a path that starts with /assets/. Supported audio formats: mp3, mp4, m4a, aac, 3gp, mkv and wav. For details, see [Supported Media Formats](https://developer.android.com/guide/topics/media/media-formats). - /// **Note**: You might encounter permission issues if you use an absolute path to access a local file, so Agora recommends using a URI address instead. For example: "content://com.android.providers.media.documents/document/audio%3A14441". - /// - iOS: Agora supports using an absolute path. For example: /var/mobile/Containers/Data/audio.mp4. - /// Supported audio formats include MP3, AAC, M4A, MP4, WAV, and 3GP. For details, see [Best Practices for iOS Audio](https://developer.apple.com/library/archive/documentation/AudioVideo/Conceptual/MultimediaPG/UsingAudio/UsingAudio.html#//apple_ref/doc/uid/TP40009767-CH2-SW28). /// - /// **Returns** - /// - The total duration (ms) of the specified audio file, if this method call succeeds. - /// - Error code, if this method call fails. - /// - -22(`ERR_RESOURCE_LIMITED`): Cannot find the audio effect file. Please set a valid `filePath`. + /// **return** ≥ 0: A successful method call. Returns the total duration (ms) of the specified audio effect file. + /// < 0: Failure. + /// Future getEffectDuration(String filePath); - /// Gets the playback postion of the audio effect file. /// - /// Since v3.4.2 + /// Retrieves the playback position of the audio effect file. + /// Call this method after playEffect. /// - /// **Note** - /// Call this method after [RtcEngine.playEffect]. + /// Param [soundId] The ID of the audio effect. Each audio effect has a unique ID. /// - /// **Parameter** [soundId] Audio effect ID. Ensure that this parameter is set to the same value as in `playEffect`. + /// **return** ≥ 0: A successful method call. Returns the playback position (ms) of the specified audio effect file. + /// < 0: Failure. /// - /// **Returns** - /// - The playback position (ms) of the specified audio effect file, if this method call succeeds. - /// - Error code, if this method call fails. - /// - -22(`ERR_RESOURCE_LIMITED`): Cannot find the audio effect file. Please set a valid `soundId`. Future getEffectCurrentPosition(int soundId); + /// /// Stops playing a specified audio effect. /// - /// **Note** - /// If you preloaded the audio effect into the memory through the [RtcEngine.preloadEffect] method, ensure that the `soundID` value is set to the same value as in the [RtcEngine.preloadEffect] method. /// - /// **Parameter** [soundId] ID of the specified audio effect. Each audio effect has a unique ID. + /// Param [soundId] The ID of the audio effect. Each audio effect has a unique ID. + /// Future stopEffect(int soundId); + /// /// Stops playing all audio effects. + /// + /// Future stopAllEffects(); + /// /// Preloads a specified audio effect file into the memory. + /// To ensure smooth communication, limit the size of the audio effect file. We recommend using this method to preload the audio effect before calling joinChannel. + /// + /// This method does not support online audio effect files. + /// For the supported audio formats, see What formats of audio files does the Agora RTC SDK support. /// - /// Supported audio formats: mp3, aac, m4a, 3gp, wav. + /// Param [soundId] The ID of the audio effect. Each audio effect has a unique ID. /// - /// **Note** - /// - This method does not support online audio effect files. - /// - To ensure smooth communication, limit the size of the audio effect file. We recommend using this method to preload the audio effect before calling the [RtcEngine.joinChannel] method. + /// Param [filePath] The absolute path or URL address (including the suffixes of the filename) of the audio effect file. For example: Android: /sdcard/emulated/0/audio.mp4, iOS: /var/mobile/Containers/Data/audio.mp4. Supported audio formats include MP3, AAC, M4A, MP4, WAV, and 3GP. See supported audio formats. /// - /// **Parameter** [soundId] ID of the audio effect. Each audio effect has a unique ID. /// - /// **Parameter** [filePath] The file path, including the filename extensions. - /// - Android: Agora supports using a URI address, an absolute path, or a path that starts with /assets/. Supported audio formats: mp3, mp4, m4a, aac, 3gp, mkv and wav. For details, see [Supported Media Formats](https://developer.android.com/guide/topics/media/media-formats). - /// **Note**: You might encounter permission issues if you use an absolute path to access a local file, so Agora recommends using a URI address instead. For example: "content://com.android.providers.media.documents/document/audio%3A14441". - /// - iOS: Agora supports using an absolute path. For example: /var/mobile/Containers/Data/audio.mp4. - /// Supported audio formats include MP3, AAC, M4A, MP4, WAV, and 3GP. For details, see [Best Practices for iOS Audio](https://developer.apple.com/library/archive/documentation/AudioVideo/Conceptual/MultimediaPG/UsingAudio/UsingAudio.html#//apple_ref/doc/uid/TP40009767-CH2-SW28). Future preloadEffect(int soundId, String filePath); + /// /// Releases a specified preloaded audio effect from the memory. /// - /// **Parameter** [soundId] ID of the audio effect. Each audio effect has a unique ID. + /// + /// Param [soundId] The ID of the audio effect. Each audio effect has a unique ID. + /// Future unloadEffect(int soundId); + /// /// Pauses a specified audio effect. /// - /// **Parameter** [soundId] ID of the audio effect. Each audio effect has a unique ID. + /// + /// Param [soundId] The ID of the audio effect. Each audio effect has a unique ID. + /// Future pauseEffect(int soundId); + /// /// Pauses all audio effects. + /// + /// Future pauseAllEffects(); + /// /// Resumes playing a specified audio effect. /// - /// **Parameter** [soundId] ID of the audio effect. Each audio effect has a unique ID. + /// + /// Param [soundId] The ID of the audio effect. Each audio effect has a unique ID. + /// Future resumeEffect(int soundId); + /// /// Resumes playing all audio effects. + /// + /// Future resumeAllEffects(); - /// Sets the operational permission of the SDK on the audio session. (iOS only) /// + /// Sets the operational permission of the SDK on the audio session. /// The SDK and the app can both configure the audio session by default. If you need to only use the app to configure the audio session, this method restricts the operational permission of the SDK on the audio session. - /// /// You can call this method either before or after joining a channel. Once you call this method to restrict the operational permission of the SDK on the audio session, the restriction takes effect when the SDK needs to change the audio session. /// - /// **Parameter** [restriction] The operational permission of the SDK on the audio session. See [AudioSessionOperationRestriction]. This parameter is in bit mask format, and each bit corresponds to a permission. - /// - /// **Note** + /// This method is for iOS only. /// This method does not restrict the operational permission of the app on the audio session. + /// + /// Param [restriction] The operational permission of the SDK on the audio session. See AudioSessionOperationRestriction. This parameter is in bit mask format, and each bit corresponds to a permission. + /// Future setAudioSessionOperationRestriction( AudioSessionOperationRestriction restriction); } /// @nodoc mixin RtcVoiceChangerInterface { + /// /// Sets the local voice changer option. + /// Deprecated: + /// Deprecated from v3.2.0. Use the following methods instead: + /// setAudioEffectPreset : Audio effects. + /// setVoiceBeautifierPreset : Voice beautifier effects. + /// setVoiceConversionPreset : Voice conversion effects. + /// + /// + /// + /// + /// This method can be used to set the local voice effect for users in a COMMUNICATION channel or hosts in a LIVE_BROADCASTING channel. After successfully calling this method, all users in the channel can hear the voice with reverberation. + /// VOICE_CHANGER_XXX: Changes the local voice to an old man, a little boy, or the Hulk. Applies to the voice talk scenario. + /// VOICE_BEAUTY_XXX: Beautifies the local voice by making it sound more vigorous, resounding, or adding spacial resonance. Applies to the voice talk and singing scenario. + /// GENERAL_VOICE_BEAUTY_XXX: Adds gender-based beautification effect to the local voice. Applies to the voice talk scenario. For a male voice: Adds magnetism to the voice. For a male voice: Adds magnetism to the voice. For a female voice: Adds freshness or vitality to the voice. + /// + /// + /// /// - /// **Deprecated** + /// To achieve better voice effect quality, Agora recommends setting the setAudioProfileprofile parameter in asMusicHighQuality (4) orMusicHighQualityStereo (5). + /// This method works best with the human voice, and Agora does not recommend using it for audio containing music and a human voice. + /// Do not use this method with setLocalVoiceReverbPreset, because the method called later overrides the one called earlier. For detailed considerations, see the advanced guide Set the Voice Effect. + /// You can call this method either before or after joining a channel. /// - /// This method is deprecated since v3.2.1. Use [RtcEngine.setAudioEffectPreset] or [RtcEngine.setVoiceBeautifierPreset] instead. + /// Param [voiceChanger] The local voice changer option. The default value is Off , which means the original voice. For more details, see AudioVoiceChanger. The gender-based beatification effect works best only when assigned a proper gender. Use GENERAL_BEAUTY_VOICE_MALE_MAGNETIC for male and use GENERAL_BEAUTY_VOICE_FEMALE_FRESH and GENERAL_BEAUTY_VOICE_FEMALE_VITALITY for female. Failure to do so can lead to voice distortion. /// - /// **Note** - /// - Do not use this method together with [RtcEngine.setLocalVoiceReverbPreset], or the method called earlier does not take effect. /// - /// **Parameter** [voiceChanger] The local voice changer option. See [AudioVoiceChanger]. @deprecated Future setLocalVoiceChanger(AudioVoiceChanger voiceChanger); - /// Sets the preset local voice reverberation effect. /// - /// **Deprecated** + /// Sets the local voice reverberation option, including the virtual stereo. + /// This method sets the local voice reverberation for users in a COMMUNICATION channel or hosts in a LIVE_BROADCASTING channel. After successfully calling this method, all users in the channel can hear the voice with reverberation. /// - /// This method is deprecated since v3.2.1. Use [RtcEngine.setAudioEffectPreset] or [RtcEngine.setVoiceBeautifierPreset] instead. /// - /// **Note** - /// - Do not use this method together with [RtcEngine.setLocalVoiceReverb]. - /// - Do not use this method together with [RtcEngine.setLocalVoiceChanger], or the method called eariler does not take effect. + /// When using the enumeration value prefixed with AUDIO_REVERB_FX, ensure that you set the profile parameter in setAudioProfile toMusicHighQuality(4) or MusicHighQualityStereo(5) before calling this method. Otherwise, the method setting is invalid. + /// When calling the VIRTUAL_STEREO method, Agora recommends setting the profile parameter in setAudioProfile as MusicHighQualityStereo(5). + /// This method works best with the human voice, and Agora does not recommend using it for audio containing music and a human voice. + /// Do not use this method with setLocalVoiceChanger, because the method called later overrides the one called earlier. For detailed considerations, see the advanced guide Set the Voice Effect. + /// You can call this method either before or after joining a channel. + /// + /// Param [reverbPreset] The local voice reverberation option. The default value is Off, which means the original voice. For more details, see AudioReverbPreset. To achieve better voice effects, Agora recommends the enumeration whose name begins with AUDIO_REVERB_FX. /// - /// **Parameter** [preset] The local voice reverberation preset. See [AudioReverbPreset]. @deprecated Future setLocalVoiceReverbPreset(AudioReverbPreset preset); + /// /// Changes the voice pitch of the local speaker. + /// You can call this method either before or after joining a channel. + /// + /// Param [pitch] The local voice pitch. The value range is [0.5,2.0]. The lower the value, the lower the pitch. The default value is 1 (no change to the pitch). /// - /// **Parameter** [pitch] Sets the voice pitch. The value ranges between 0.5 and 2.0. The lower the value, the lower the voice pitch. The default value is 1.0 (no change to the local voice pitch). Future setLocalVoicePitch(double pitch); + /// /// Sets the local voice equalization effect. + /// You can call this method either before or after joining a channel. + /// + /// Param [bandFrequency] The band frequency. The value ranges between 0 and 9; representing the respective 10-band center frequencies of the voice effects, including 31, 62, 125, 250, 500, 1k, 2k, 4k, 8k, and 16k Hz. For more details, see AudioEqualizationBandFrequency. /// - /// **Parameter** [bandFrequency] Sets the band frequency. The value ranges between 0 and 9; representing the respective 10-band center frequencies of the voice effects, including 31, 62, 125, 500, 1k, 2k, 4k, 8k, and 16k Hz. - /// See [AudioEqualizationBandFrequency]. + /// Param [bandGain] The gain of each band in dB. The value ranges between -15 and 15. The default value is 0. /// - /// **Parameter** [bandGain] Sets the gain of each band (dB). The value ranges between -15 and 15. The default value is 0. Future setLocalVoiceEqualization( AudioEqualizationBandFrequency bandFrequency, int bandGain); + /// /// Sets the local voice reverberation. + /// You can call this method either before or after joining a channel. /// - /// **Note** - /// - Adds the [RtcEngine.setLocalVoiceReverbPreset] method, a more user-friendly method for setting the local voice reverberation. You can use this method to set the local reverberation effect, such as Popular, R&B, Rock, Hip-hop, and more. + /// Param [reverbKey] The reverberation key. Agora provides 5 reverberation keys: AudioReverbType. /// - /// **Parameter** [reverbKey] Sets the reverberation key. This method contains five reverberation keys. For details, see the description of each value in [AudioReverbType]. + /// Param [value] The value of the reverberation key. /// - /// **Parameter** [value] Sets the local voice reverberation value. Future setLocalVoiceReverb(AudioReverbType reverbKey, int value); - /// Sets an SDK preset audio effect. - /// - /// Since v3.2.1 /// + /// Sets an SDK preset audio effect. /// Call this method to set an SDK preset audio effect for the local user who sends an audio stream. This audio effect does not change the gender characteristics of the original voice. After setting an audio effect, all users in the channel can hear the effect. + /// To get better audio effect quality, Agora recommends calling setAudioProfile and setting the scenario parameter as GameStreaming (3) before calling this method. /// - /// You can set different audio effects for different scenarios. See *Set the Voice Beautifier and Audio Effects*. /// - /// To achieve better audio effect quality, Agora recommends calling [RtcEngine.setAudioProfile] and setting the `scenario` parameter to `GameStreaming(3)` before calling this method. + /// You can call this method either before or after joining a channel. + /// Do not set the profile parameter in setAudioProfile to SpeechStandard (1), or the method does not take effect. + /// This method works best with the human voice. Agora does not recommend using this method for audio containing music. + /// If you call setAudioEffectPreset and set enumerators except for RoomAcoustics3DVoice or PitchCorrection, do not call setAudioEffectParameters; otherwise, setAudioEffectPreset is overridden. + /// After calling setAudioEffectPreset, Agora recommends not calling the following methods, because they can override setAudioEffectPreset: + /// setVoiceBeautifierPreset + /// setLocalVoiceReverbPreset + /// setLocalVoiceChanger + /// setLocalVoicePitch + /// setLocalVoiceEqualization + /// setLocalVoiceReverb + /// setVoiceBeautifierParameters + /// setVoiceConversionPreset /// - ///**Note** - /// - You can call this method either before or after joining a channel. - /// - Do not set the profile parameter of [RtcEngine.setAudioProfile] to `SpeechStandard(1)`; otherwise, this method call fails. - /// - This method works best with the human voice. Agora does not recommend using this method for audio containing music. - /// - If you call this method and set the preset parameter to enumerators except `RoomAcoustics3DVoice` or `PitchCorrection`, do not call [RtcEngine.setAudioEffectParameters]; otherwise, [RtcEngine.setAudioEffectParameters] overrides this method. - /// - After calling this method, Agora recommends not calling the following methods, because they can override `setAudioEffectPreset`: - /// - [RtcEngine.setVoiceBeautifierPreset] - /// - [RtcEngine.setLocalVoiceReverbPreset] - /// - [RtcEngine.setLocalVoiceChanger] - /// - [RtcEngine.setLocalVoicePitch] - /// - [RtcEngine.setLocalVoiceEqualization] - /// - [RtcEngine.setLocalVoiceReverb] + /// Param [preset] The options for SDK preset audio effects. See AudioEffectPreset. /// - /// **Parameter** [preset] The options for SDK preset audio effects. See [AudioEffectPreset]. Future setAudioEffectPreset(AudioEffectPreset preset); - /// Sets an SDK preset voice beautifier effect. /// - /// Since v3.2.1 + /// Sets a preset voice beautifier effect. + /// Call this method to set a preset voice beautifier effect for the local user who sends an audio stream. After setting a voice beautifier effect, all users in the channel can hear the effect. You can set different voice beautifier effects for different scenarios. + /// For better voice effects, Agora recommends that you call setAudioProfile and set scenario to GameStreaming (3) and profile to MusicHighQuality (4) or MusicHighQualityStereo (5) before calling this method. /// - /// Call this method to set an SDK preset voice beautifier effect for the local user who sends an audio stream. After setting a voice beautifier effect, all users in the channel can hear the effect. /// - /// You can set different voice beautifier effects for different scenarios. See *Set the Voice Beautifier and Audio Effects*. + /// You can call this method either before or after joining a channel. + /// Do not set the profile parameter in setAudioProfile to SpeechStandard(1), or the method does not take effect. + /// This method works best with the human voice. Agora does not recommend using this method for audio containing music. + /// After calling setVoiceBeautifierPreset, Agora recommends not calling the following methods, because they can override setVoiceBeautifierPreset: + /// setAudioEffectPreset + /// setAudioEffectParameters + /// setLocalVoiceReverbPreset + /// setLocalVoiceChanger + /// setLocalVoicePitch + /// setLocalVoiceEqualization + /// setLocalVoiceReverb + /// setVoiceBeautifierParameters + /// setVoiceConversionPreset /// - /// To achieve better audio effect quality, Agora recommends calling [RtcEngine.setAudioProfile] and setting the `scenario` parameter to `GameStreaming(3)` and the `profile` parameter to `MusicHighQuality(4)` or `MusicHighQualityStereo(5)` before calling this method. + /// Param [preset] The preset voice beautifier effect options: VoiceBeautifierPreset. /// - /// **Note** - /// - You can call this method either before or after joining a channel. - /// - Do not set the profile parameter of `setAudioProfile` to `SpeechStandard(1)`; otherwise, this method call fails. - /// - This method works best with the human voice. Agora does not recommend using this method for audio containing music. - /// - After calling this method, Agora recommends not calling the following methods, because they can override `setVoiceBeautifierPreset`: - /// - [RtcEngine.setAudioEffectPreset] - /// - [RtcEngine.setAudioEffectParameters] - /// - [RtcEngine.setLocalVoiceReverbPreset] - /// - [RtcEngine.setLocalVoiceChanger] - /// - [RtcEngine.setLocalVoicePitch] - /// - [RtcEngine.setLocalVoiceEqualization] - /// - [RtcEngine.setLocalVoiceReverb] /// - /// **Parameter** [preset] The options for SDK preset voice beautifier effects. See [VoiceBeautifierPreset]. Future setVoiceBeautifierPreset(VoiceBeautifierPreset preset); - /// Sets an SDK preset voice conversion effect. /// - /// Call this method to set an SDK preset voice conversion effect for the local user who sends an audio stream. After setting a voice conversion effect, all users in the channel can hear the effect. + /// Sets a preset voice beautifier effect. + /// Call this method to set a preset voice beautifier effect for the local user who sends an audio stream. After setting an audio effect, all users in the channel can hear the effect. You can set different audio effects for different scenarios. See Set the Voice Beautifier and Audio Effects. + /// To achieve better audio effect quality, Agora recommends that you call setAudioProfile and set the profile to MusicHighQuality(4) or MusicHighQualityStereo(5) and scenario to GameStreaming(3) before calling this method. /// - /// You can set different voice conversion effects for different scenarios. See *Set the Voice Effect*. /// - /// To achieve better voice effect quality, Agora recommends calling [RtcEngine.setAudioProfile] and setting the profile parameter to `MusicHighQuality(4)` or `MusicHighQualityStereo(5)` and the scenario parameter to `GameStreaming(3)` before calling this method. - /// - /// **Parameter** [preset] The options for SDK preset voice conversion effects: [VoiceConversionPreset]. + /// You can call this method either before or after joining a channel. + /// Do not setsetAudioProfile the profile parameter in to SpeechStandard(1) + /// This method works best with the human voice. Agora does not recommend using this method for audio containing music. + /// After calling setVoiceConversionPreset, Agora recommends not calling the following methods, or the settings in setVoiceConversionPreset are overridden : + /// setAudioEffectPreset + /// setAudioEffectParameters + /// setVoiceBeautifierPreset + /// setVoiceBeautifierParameters + /// setLocalVoiceReverbPreset + /// setLocalVoiceChanger + /// setLocalVoicePitch + /// setLocalVoiceEqualization + /// setLocalVoiceReverb + /// + /// Param [preset] The options for the preset voice beautifier effects: VoiceConversionPreset. /// - /// **Note** /// - /// - You can call this method either before or after joining a channel. - /// - Do not set the profile parameter of [RtcEngine.setAudioProfile] to `SpeechStandard(1)`; otherwise, this method call does not take effect. - /// - This method works best with the human voice. Agora does not recommend using this method for audio containing music. - /// - After calling this method, Agora recommends not calling the following methods, because they can override `setVoiceConversionPreset`: - /// - [RtcEngine.setAudioEffectPreset] - /// - [RtcEngine.setAudioEffectParameters] - /// - [RtcEngine.setVoiceBeautifierPreset] - /// - [RtcEngine.setVoiceBeautifierParameters] - /// - [RtcEngine.setLocalVoiceReverbPreset] - /// - [RtcEngine.setLocalVoiceChanger] - /// - [RtcEngine.setLocalVoicePitch] - /// - [RtcEngine.setLocalVoiceEqualization] - /// - [RtcEngine.setLocalVoiceReverb] Future setVoiceConversionPreset(VoiceConversionPreset preset); - /// Sets parameters for SDK preset audio effects. /// + /// Sets parameters for SDK preset audio effects. /// Call this method to set the following parameters for the local user who sends an audio stream: - /// - 3D voice effect: Sets the cycle period of the 3D voice effect. - /// - Pitch correction effect: Sets the basic mode and tonic pitch of the pitch correction effect. Different songs have different modes and tonic pitches. Agora recommends bounding this method with interface elements to enable users to adjust the pitch correction interactively. - /// - /// After setting parameters, all users in the channel can hear the relevant effect. - /// - /// **Note** - /// - You can call this method either before or after joining a channel. - /// - To achieve better audio effect quality, Agora recommends calling [RtcEngine.setAudioProfile] and setting the `scenario` parameter to `GameStreaming(3)` before calling this method. - /// - Do not set the profile parameter of `setAudioProfile` to `SpeechStandard(1)`; otherwise, this method call fails. - /// - This method works best with the human voice. Agora does not recommend using this method for audio containing music. - /// - After calling this method, Agora recommends not calling the following methods, because they can override `setAudioEffectParameters`: - /// - [RtcEngine.setAudioEffectPreset] - /// - [RtcEngine.setVoiceBeautifierPreset] - /// - [RtcEngine.setLocalVoiceReverbPreset] - /// - [RtcEngine.setLocalVoiceChanger] - /// - [RtcEngine.setLocalVoicePitch] - /// - [RtcEngine.setLocalVoiceEqualization] - /// - [RtcEngine.setLocalVoiceReverb] - /// - /// **Parameter** [preset] The options for SDK preset audio effects: - /// - 3D voice effect: `RoomAcoustics3DVoice` - /// - Call `setAudioProfile` and set the `profile` parameter to `MusicStandardStereo(3)` or `MusicHighQualityStereo(5)` before setting this enumerator; otherwise, the enumerator setting does not take effect. - /// - If the 3D voice effect is enabled, users need to use stereo audio playback devices to hear the anticipated voice effect. - /// - Pitch correction effect: `PitchCorrection`. To achieve better audio effect quality, Agora recommends calling `setAudioProfile` and setting the `profile` parameter to `MusicHighQuality(4)` or `MusicHighQualityStereo(5)` before setting this enumerator. - /// - /// **Parameter** [param1] - /// - If you set `preset` to `RoomAcoustics3DVoice`, the `param1` sets the cycle period of the 3D voice effect. The value range is [1, 60] and the unit is a second. The default value is 10 seconds, indicating that the voice moves around you every 10 seconds. - /// - If you set `preset` to `PitchCorrection`, `param1` sets the basic mode of the pitch correction effect: - /// - 1: (Default) Natural major scale. - /// - 2: Natural minor scale. - /// - 3: Japanese pentatonic scale. - /// - /// **Parameter** [param2] - /// - If you set `preset` to `RoomAcoustics3DVoice`, you need to set `param2` to 0. - /// - If you set `preset` to `PitchCorrection`, `param2` sets the tonic pitch of the pitch correction effect: - /// - 1: A - /// - 2: A# - /// - 3: B - /// - 4: (Default) C - /// - 5: C# - /// - 6: D - /// - 7: D# - /// - 8: E - /// - 9: F - /// - 10: F# - /// - 11: G - /// - 12: G# + /// 3D voice effect: Sets the cycle period of the 3D voice effect. + /// Pitch correction effect: Sets the basic mode and tonic pitch of the pitch correction effect. Different songs have different modes and tonic pitches. Agora recommends bounding this method with interface elements to enable users to adjust the pitch correction interactively. + /// + /// + /// After setting the audio parameters, all users in the channel can hear the effect. + /// + /// + /// You can call this method either before or after joining a channel. + /// To get better audio effect quality, Agora recommends calling and setting scenario in setAudioProfile as GameStreaming(3) before calling this method. + /// Do not set the profile parameter in setAudioProfile to SpeechStandard (1), or the method does not take effect. + /// This method works best with the human voice. Agora does not recommend using this method for audio containing music. + /// After calling setAudioEffectParameters, Agora recommends not calling the following methods, or the settings in setAudioEffectParameters are overridden : + /// setAudioEffectPreset + /// setVoiceBeautifierPreset + /// setLocalVoiceReverbPreset + /// setLocalVoiceChanger + /// setLocalVoicePitch + /// setLocalVoiceEqualization + /// setLocalVoiceReverb + /// setVoiceBeautifierParameters + /// setVoiceConversionPreset + /// + /// Param [preset] The options for SDK preset audio effects: + /// RoomAcoustics3DVoice, 3D voice effect: + /// Call and set the profile parameter in setAudioProfile to MusicStandardStereo (3) or MusicHighQualityStereo(5) before setting this enumerator; otherwise, the enumerator setting does not take effect. + /// If the 3D voice effect is enabled, users need to use stereo audio playback devices to hear the anticipated voice effect. + /// + /// + /// PitchCorrection, Pitch correction effect: To achieve better audio effect quality, Agora recommends calling setAudioProfile and setting the profile parameter to MusicHighQuality (4) or MusicHighQualityStereo(5) before setting this enumerator. + /// + /// + /// + /// Param [param1] + /// If you set preset to RoomAcoustics3DVoice , param1 sets the cycle period of the 3D voice effect. The value range is [1,60] and the unit is seconds. The default value is 10, indicating that the voice moves around you every 10 seconds. + /// If you set preset to PitchCorrection , param1 sets the basic mode of the pitch correction effect: + /// 1: (Default) Natural major scale. + /// 2: Natural minor scale. + /// 3: Japanese pentatonic scale. + /// + /// + /// + /// + /// + /// Param [param2] + /// If you set preset to RoomAcoustics3DVoice, you need to set param2 to 0. + /// If you set preset to PitchCorrection, param2 sets the tonic pitch of the pitch correction effect: + /// 1: A + /// 2: A# + /// 3: B + /// 4: (Default) C + /// 5: C# + /// 6: D + /// 7: D# + /// 8: E + /// 9: F + /// 10: F# + /// 11: G + /// 12: G# + /// + /// + /// + /// + /// Future setAudioEffectParameters( AudioEffectPreset preset, int param1, int param2); - /// Sets parameters for SDK preset voice beautifier effects. /// - /// Since v3.3.1 + /// Sets parameters for the preset voice beautifier effects. + /// Call this method to set a gender characteristic and a reverberation effect for the singing beautifier effect. This method sets parameters for the local user who sends an audio stream. After setting the audio parameters, all users in the channel can hear the effect. + /// For better voice effects, Agora recommends that you call setAudioProfile and setscenario to GameStreaming(3) and profile to MusicHighQuality(4) or MusicHighQualityStereo(5) before calling this method. + /// + /// + /// You can call this method either before or after joining a channel. + /// Do not set the profile parameter of setAudioProfile to SpeechStandard(1). Otherwise, the method does not take effect. + /// This method works best with the human voice. Agora does not recommend using this method for audio containing music. + /// After calling setVoiceBeautifierParameters, Agora recommends not calling the following methods, because they can override settings in setVoiceBeautifierParameters: + /// setAudioEffectPreset + /// setAudioEffectParameters + /// setVoiceBeautifierPreset + /// setLocalVoiceReverbPreset + /// setLocalVoiceChanger + /// setLocalVoicePitch + /// setLocalVoiceEqualization + /// setLocalVoiceReverb + /// setVoiceConversionPreset + /// + /// Param [preset] The option for the preset audio effect: + /// SINGING_BEAUTIFIER: The singing beautifier effect. /// - /// Call this method to set a gender characteristic and a reverberation effect for the singing beautifier effect. This method sets parameters for the local user who sends an audio stream. /// - /// After you call this method successfully, all users in the channel can hear the relevant effect. /// - /// To achieve better audio effect quality, before you call this method, Agora recommends calling [RtcEngine.setAudioProfile], and setting the scenario parameter to `GameStreaming(3)` and the profile parameter to `MusicHighQuality(4)` or `MusicHighQualityStereo(5)`. + /// Param [param1] The gender characteristics options for the singing voice: + /// 1: A male-sounding voice. + /// 2: A female-sounding voice. /// - /// **Parameter** [preset] The options for SDK preset voice beautifier effects. You can only set it as [VoiceBeautifierPreset.SingingBeautifier]. /// - /// **Parameter** [param1] The gender characteristics options for the singing voice: - /// - `1`: A male-sounding voice. - /// - `2`: A female-sounding voice. /// - /// **Parameter** [param2] The reverberation effects options: - /// - `1`: The reverberation effect sounds like singing in a small room. - /// - `2`: The reverberation effect sounds like singing in a large room. - /// - `3`: The reverberation effect sounds like singing in a hall. + /// Param [param2] The reverberation effect options for the singing voice: + /// 1: The reverberation effect sounds like singing in a small room. + /// 2: The reverberation effect sounds like singing in a large room. + /// 3: The reverberation effect sounds like singing in a hall. + /// /// - /// **Note** /// - /// - You can call this method either before or after joining a channel. - /// - Do not set the `profile` parameter of [RtcEngine.setAudioProfile] to `SpeechStandard(1)`; otherwise, this method call does not take effect. - /// - This method works best with the human voice. Agora does not recommend using this method for audio containing music. - /// - After calling this method, Agora recommends not calling the following methods, because they can override `setVoiceBeautifierParameters`: - /// - [RtcEngine.setAudioEffectPreset] - /// - [RtcEngine.setAudioEffectParameters] - /// - [RtcEngine.setVoiceBeautifierPreset] - /// - [RtcEngine.setVoiceConversionPreset] - /// - [RtcEngine.setLocalVoiceReverbPreset] - /// - [RtcEngine.setLocalVoiceChanger] - /// - [RtcEngine.setLocalVoicePitch] - /// - [RtcEngine.setLocalVoiceEqualization] - /// - [RtcEngine.setLocalVoiceReverb] Future setVoiceBeautifierParameters( VoiceBeautifierPreset preset, int param1, int param2); } /// @nodoc mixin RtcVoicePositionInterface { + /// /// Enables/Disables stereo panning for remote users. + /// Ensure that you call this method before joining a channel to enable stereo panning for remote users so that the local user can track the position of a remote user by calling setRemoteVoicePosition. + /// + /// Param [enabled] Whether to enable stereo panning for remote users: + /// true: Enable stereo panning. + /// false: Disable stereo panning. + /// /// - /// Ensure that you call this method before [RtcEngine.joinChannel] to enable stereo panning for remote users so that the local user can track the position of a remote user by calling [RtcEngine.setRemoteVoicePosition]. /// - /// **Parameter** [enabled] Sets whether or not to enable stereo panning for remote users: - /// - `true`: enables stereo panning. - /// - `false`: disables stereo panning. Future enableSoundPositionIndication(bool enabled); - /// Sets the sound position of a remote user. - /// When the local user calls this method to set the sound position of a remote user, the sound difference between the left and right channels allows the local user to track the real-time position of the remote user, creating a real sense of space. This method applies to massively multiplayer online games, such as Battle Royale games. /// - /// **Note** - /// - For this method to work, enable stereo panning for remote users by calling the [RtcEngine.enableSoundPositionIndication] method before joining a channel. - /// - This method requires hardware support. For the best sound positioning, we recommend using a wired headset. + /// Sets the 2D position (the position on the horizontal plane) of the remote user's voice. + /// This method sets the 2D position and volume of a remote user, so that the local user can easily hear and identify the remote user's position. + /// When the local user calls this method to set the voice position of a remote user, the voice difference between the left and right channels allows the local user to track the real-time position of the remote user, creating a sense of space. This method applies to massive multiplayer online games, such as Battle Royale games. + /// /// - /// **Parameter** [uid] The ID of the remote user. + /// For this method to work, enable stereo panning for remote users by calling the enableSoundPositionIndication method before joining a channel. + /// For the best voice positioning, Agora recommends using a wired headset. + /// Call this method after joining a channel. /// - /// **Parameter** [pan] The sound position of the remote user. The value ranges from -1.0 to 1.0: - /// - 0.0: The remote sound comes from the front. - /// - -1.0: The remote sound comes from the left. - /// - 1.0: The remote sound comes from the right. + /// Param [uid] The user ID of the remote user. + /// + /// Param [pan] The voice position of the remote user. The value ranges from -1.0 to 1.0: + /// 0.0: (Default) The remote voice comes from the front. + /// -1.0: The remote voice comes from the left. + /// 1.0: The remote voice comes from the right. + /// + /// + /// + /// Param [gain] The volume of the remote user. The value ranges from 0.0 to 100.0. The default value is 100.0 (the original volume of the remote user). The smaller the value, the lower the volume. /// - /// **Parameter** [gain] Gain of the remote user. The value ranges from 0.0 to 100.0. The default value is 100.0 (the original gain of the remote user). The smaller the value, the less the gain. Future setRemoteVoicePosition(int uid, double pan, double gain); } /// @nodoc mixin RtcPublishStreamInterface { - /// Sets the video layout and audio settings for CDN live. /// - /// The SDK triggers the [RtcEngineEventHandler.transcodingUpdated] callback when you call this method to update the [LiveTranscoding] class. If you call this method to set the [LiveTranscoding] class for the first time, the SDK does not trigger the [RtcEngineEventHandler.transcodingUpdated] callback. + /// Sets the transcoding configurations for CDN live streaming. + /// This method sets the video layout and audio settings for CDN live streaming. The SDK triggers the transcodingUpdated callback when you call this method to update the transcoding settings. + /// /// - /// **Note** - /// - Before calling the methods listed in this section: - /// - This method applies to [ChannelProfile.LiveBroadcasting] only. - /// - Ensure that you enable the RTMP Converter service before using this function. See Prerequisites in *Push Streams to CDN*. - /// - Ensure that you call the [RtcEngine.setClientRole] method and set the user role as the host. - /// - Ensure that you call the `setLiveTranscoding` method before calling the [RtcEngine.addPublishStreamUrl] method. - /// - Agora supports pushing media streams in RTMPS protocol to the CDN only when you enable transcoding. + /// This method takes effect only when you are a host in live interactive streaming. + /// Ensure that you enable the RTMP Converter service before using this function. See Prerequisites in the advanced guide Push Streams to CDN. + /// If you call this method to set the transcoding configuration for the first time, the SDK does not trigger the transcodingUpdated callback. + /// Call this method after joining a channel. + /// Agora supports pushing media streams in RTMPS protocol to the CDN only when you enable transcoding. + /// + /// Param [transcoding] The transcoding configurations for CDN live streaming. For details, see LiveTranscoding. /// - /// **Parameter** [transcoding] Sets the CDN live audio/video transcoding settings. See [LiveTranscoding]. Future setLiveTranscoding(LiveTranscoding transcoding); - /// Publishes the local stream to a specified **CDN streaming URL**. /// - /// After calling this method, you can push media streams in RTMP or RTMPS protocol to the CDN. The `addPublishStreamUrl` method call triggers the [RtcEngineEventHandler.rtmpStreamingStateChanged] callback on the local client to report the state of adding a local stream to the CDN. + /// Publishes the local stream to a specified CDN live streaming URL. + /// After calling this method, you can push media streams in RTMP or RTMPS protocol to the CDN. The SDK triggers the rtmpStreamingStateChanged callback on the local client to report the state of adding a local stream to the CDN. + /// + /// + /// Call this method after joining a channel. + /// Ensure that you enable the RTMP Converter service before using this function. + /// This method takes effect only when you are a host in live interactive streaming. + /// This method adds only one stream CDN streaming URL each time it is called. To push multiple URLs, call this method multiple times. + /// Agora supports pushing media streams in RTMPS protocol to the CDN only when you enable transcoding. /// - /// **Note** - /// - Ensure that you enable the RTMP Converter service before using this function. See Prerequisites in *Push Streams to CDN*. - /// - This method applies to LiveBroadcasting only. - /// - Ensure that the user joins a channel before calling this method. - /// - This method adds only one **CDN streaming URL **each time it is called. - /// - Agora supports pushing media streams in RTMPS protocol to the CDN only when you enable transcoding. + /// Param [url] The CDN streaming URL in the RTMP or RTMPS format. The maximum length of this parameter is 1024 bytes. The URL address must not contain special characters, such as Chinese language characters. /// - /// **Parameter** [url] The CDN streaming URL in the **RTMP or RTMPS** format. The maximum length of this parameter is 1024 bytes. The URL address must not contain special characters, such as Chinese language characters. + /// Param [transcodingEnabled] Whether to enable transcoding. Transcoding in a CDN live streaming converts the audio and video streams before pushing them to the CDN server. It applies to scenarios where a channel has multiple broadcasters and composite layout is needed + /// true: Enable transcoding. + /// false: Disable transcoding. + /// + /// If you set this parameter as true, ensure that you call the setLiveTranscoding method before this method. /// - /// **Parameter** [transcodingEnabled] Sets whether transcoding is enabled/disabled. If you set this parameter as true, ensure that you call the setLiveTranscoding method before this method. /// - /// See [RtcEngine.setLiveTranscoding] - /// - `true`: Enable transcoding. To transcode the audio or video streams when publishing them to CDN live, often used for combining the audio and video streams of multiple hosts in CDN live. - /// - `false`: Disable transcoding. Future addPublishStreamUrl(String url, bool transcodingEnabled); - /// Removes an **RTMP or RTMPS** stream from the CDN. /// - /// This method removes the CDN streaming URL (added by [RtcEngine.addPublishStreamUrl]) from a CDN live stream to report the state of removing an **RTMP or RTMPS** stream from the CDN. + /// Removes an RTMP or RTMPS stream from the CDN. + /// After a successful method call, the SDK triggers rtmpStreamingStateChanged on the local client to report the result of deleting the address. + /// /// - /// **Note** - /// - Ensure that you enable the RTMP Converter service before using this function. See Prerequisites in *Push Streams to CDN*. - /// - Ensure that the user joins a channel before calling this method. - /// - This method applies to LiveBroadcasting only. - /// - This method removes only one stream CDN streaming URL each time it is called. + /// Ensure that you enable the RTMP Converter service before using this function. + /// This method takes effect only when you are a host in live interactive streaming. + /// Call this method after joining a channel. + /// This method removes only one CDN streaming URL each time it is called. To remove multiple URLs, call this method multiple times. + /// + /// Param [url] The CDN streaming URL to be removed. The maximum length of this parameter is 1024 bytes. The CDN streaming URL must not contain special characters, such as Chinese characters. /// - /// **Parameter** [url] The CDN streaming URL to be removed. The maximum length of this parameter is 1024 bytes. The URL address must not contain special characters, such as Chinese language characters. Future removePublishStreamUrl(String url); } /// @nodoc mixin RtcMediaRelayInterface { - /// Starts to relay media streams across channels. /// - /// After a successful method call, the SDK triggers the [RtcEngineEventHandler.channelMediaRelayStateChanged] and [RtcEngineEventHandler.channelMediaRelayEvent] callbacks, and these callbacks return the state and events of the media stream relay. - /// - If the [RtcEngineEventHandler.channelMediaRelayStateChanged] callback returns [ChannelMediaRelayState.Running] and [ChannelMediaRelayError.None], and the [RtcEngineEventHandler.channelMediaRelayEvent] callback returns [ChannelMediaRelayEvent.SentToDestinationChannel], the SDK starts relaying media streams between the original and the destination channel. - /// - If the [RtcEngineEventHandler.channelMediaRelayStateChanged] callback returns [ChannelMediaRelayState.Failure], an exception occurs during the media stream relay. + /// Starts relaying media streams across channels. This method can be used to implement scenarios such as co-host across channels. + /// After a successful method call, the SDK triggers the channelMediaRelayStateChanged and channelMediaRelayEvent callbacks, and these callbacks return the state and events of the media stream relay. + /// If the channelMediaRelayStateChanged callback returns Running (2) and None (0), and the channelMediaRelayEvent callback returns SentToDestinationChannel (4), it means that the SDK starts relaying media streams between the source channel and the destination channel. + /// If the channelMediaRelayStateChanged callback returns Failure (3), an exception occurs during the media stream relay. + /// + /// + /// + /// + /// Call this method after joining the channel. + /// This method takes effect only when you are a host in a live streaming channel. + /// After a successful method call, if you want to call this method again, ensure that you call the stopChannelMediaRelay method to quit the current relay. + /// Contact support@agora.io (https://agora-ticket.agora.io/) before implementing this function. + /// We do not support string user accounts in this API. /// - /// **Note** - /// - Contact sales-us@agora.io before implementing this function. - /// - We do not support string user accounts in this API. - /// - Call this method after the [RtcEngine.joinChannel] method. - /// - This method takes effect only when you are a [ClientRole.Broadcaster] in a [ChannelProfile.LiveBroadcasting] channel. - /// - After a successful method call, if you want to call this method again, ensure that you call the [RtcEngine.stopChannelMediaRelay] method to quit the current relay. + /// Param [channelMediaRelayConfiguration] The configuration of the media stream relay. For details, see ChannelMediaRelayConfiguration. /// - /// **Parameter** [channelMediaRelayConfiguration] The configuration of the media stream relay. Future startChannelMediaRelay( ChannelMediaRelayConfiguration channelMediaRelayConfiguration); - /// Updates the channels for media relay. /// - /// After the channel media relay starts, if you want to relay the media stream to more channels, or leave the current relay channel, you can call the `updateChannelMediaRelay` method. + /// Updates the channels for media stream relay. + /// After the media relay starts, if you want to relay the media stream to more channels, or leave the current relay channel, you can call the updateChannelMediaRelay method. + /// After a successful method call, the SDK triggers the channelMediaRelayEvent callback with the UpdateDestinationChannel (7) state code. + /// Call this method after the startChannelMediaRelay method to update the destination channel. /// - /// After a successful method call, the SDK triggers the [RtcEngineEventHandler.channelMediaRelayEvent] callback with the [ChannelMediaRelayEvent.UpdateDestinationChannel] state code. + /// Param [channelMediaRelayConfiguration] The configuration of the media stream relay. For more details, see ChannelMediaRelayConfiguration. /// - /// **Note** - /// - Call this method after the [RtcEngine.startChannelMediaRelay] method to update the destination channel. - /// - This method supports adding at most four destination channels in the relay. If there are already four destination channels in the relay. - /// - /// **Parameter** [channelMediaRelayConfiguration] The media stream relay configuration. See [ChannelMediaRelayConfiguration]. Future updateChannelMediaRelay( ChannelMediaRelayConfiguration channelMediaRelayConfiguration); - /// Stops the media stream relay. - /// - /// Once the relay stops, the broadcaster quits all the destination channels. /// - /// After a successful method call, the SDK triggers the [RtcEngineEventHandler.channelMediaRelayStateChanged] callback. If the callback returns [ChannelMediaRelayState.Idle] and [ChannelMediaRelayError.None], the [ClientRole.Broadcaster] successfully stops the relay. + /// Stops the media stream relay. Once the relay stops, the host quits all the destination channels. + /// After a successful method call, the SDK triggers the channelMediaRelayStateChanged callback. If the callback reports Idle (0) and None (0), the host successfully stops the relay. + /// If the method call fails, the SDK triggers the channelMediaRelayStateChanged callback with the ServerNoResponse (2) or ServerConnectionLost (8) status code. You can call the leaveChannel method to leave the channel, and the media stream relay automatically stops. /// - /// **Note** - /// - If the method call fails, the SDK triggers the [RtcEngineEventHandler.channelMediaRelayStateChanged] callback with the [ChannelMediaRelayError.ServerNoResponse] or [ChannelMediaRelayError.ServerConnectionLost] error code. You can leave the channel by calling the [RtcEngine.leaveChannel] method, and the media stream relay automatically stops. Future stopChannelMediaRelay(); - /// Pauses the media stream relay to all destination channels. /// - /// After the cross-channel media stream relay starts, you can call this method - /// to pause relaying media streams to all destination channels; after the pause, - /// if you want to resume the relay, call [resumeAllChannelMediaRelay]. - /// - /// After a successful method call, the SDK triggers the [RtcEngineEventHandler.channelMediaRelayEvent] - /// callback to report whether the media stream relay is successfully paused. + /// Pauses the media stream relay to all destination channels. + /// After the cross-channel media stream relay starts, you can call this method to pause relaying media streams to all destination channels; after the pause, if you want to resume the relay, call resumeAllChannelMediaRelay. + /// After a successful method call, the SDK triggers the channelMediaRelayEvent callback to report whether the media stream relay is successfully paused. + /// Call this method after startChannelMediaRelay. /// - /// **Note**: Call this method after the [startChannelMediaRelay] method. Future pauseAllChannelMediaRelay(); - /// Resumes the media stream relay to all destination channels. - /// - /// After calling the [pauseAllChannelMediaRelay] method, you can call this - /// method to resume relaying media streams to all destination channels. /// - /// After a successful method call, the SDK triggers the [RtcEngineEventHandler.channelMediaRelayEvent] - /// callback to report whether the media stream relay is successfully resumed. + /// Resumes the media stream relay to all destination channels. + /// After calling the pauseAllChannelMediaRelay method, you can call this method to resume relaying media streams to all destination channels. + /// After a successful method call, the SDK triggers the channelMediaRelayEvent callback to report whether the media stream relay is successfully resumed. + /// Call this method after the pauseAllChannelMediaRelay method. /// - /// **Note**: Call this method after the [pauseAllChannelMediaRelay] method. Future resumeAllChannelMediaRelay(); } /// @nodoc mixin RtcAudioRouteInterface { - /// Sets the default audio route. /// - /// If the default audio route of the SDK (see *Set the Audio Route*) cannot meet your requirements, - /// you can call this method to switch the default audio route. After successfully switching the audio route, the SDK triggers the [audioRouteChanged] callback to indicate the changes. + /// Sets the default audio playback route. + /// This method sets whether the received audio is routed to the earpiece or speakerphone by default before joining a channel. If a user does not call this method, the audio is routed to the earpiece by default. + /// The default settings for each profile: + /// For the COMMUNICATION profile: + /// In a voice call, the default audio route is the earpiece. + /// In a video call, the default audio route is the speakerphone. If a user calls the disableVideo, muteLocalVideoStream, or muteAllRemoteVideoStreams method, the default audio route switches back to the earpiece automatically. + /// + /// For the live broadcasting profile: Speakerphone. + /// + /// + /// + /// + /// This method is for Android and iOS only. + /// This method needs to be set before joining a channel, otherwise, it will not take effect. + /// + /// Param [defaultToSpeaker] The default audio playback route. + /// true: The audio routing is speakerphone. If the device connects to the earpiece or Bluetooth, the audio cannot be routed to the speakerphone. + /// false: (Default) Route the audio to the earpiece. If a headset is plugged in, the audio is routed to the headset. + /// /// - /// **Note** - /// - Call this method before calling [joinChannel]. If you need to switch the audio route after joining a channel, call [setEnableSpeakerphone]. - /// - If the user uses an external audio playback device such as a Bluetooth or wired headset, this method does not take effect, and the SDK plays audio through the external device. When the user uses multiple external devices, the SDK plays audio through the last connected device. /// - /// **Parameter** [defaultToSpeaker] Sets the default audio route as follows: - /// - `true`: Set to the speakerphone. - /// - `false`: Set to the earpiece. Future setDefaultAudioRoutetoSpeakerphone(bool defaultToSpeaker); + /// /// Enables/Disables the audio playback route to the speakerphone. + /// This method sets whether the audio is routed to the speakerphone or earpiece. After a successful method call, the SDK triggers the audioRouteChanged callback. + /// + /// + /// Ensure that you have joined a channel before calling this method. /// - /// If the default audio route of the SDK (see *Set the Audio Route*) or the setting in [setDefaultAudioRoutetoSpeakerphone] cannot meet your requirements, you can call this method to switch the current audio route. - /// After successfully switching the audio route, the SDK triggers the [audioRouteChanged] callback to indicate the changes. + /// Param [speakerOn] Whether the audio is routed to the speakerphone or earpiece. + /// true: Route the audio to the speakerphone. If the device connects to the earpiece or Bluetooth, the audio cannot be routed to the speakerphone. + /// false: Route the audio to the earpiece. If a headset is plugged in, the audio is routed to the headset. /// - /// This method only sets the audio route in the current channel and does not influence the default audio route. If the user leaves the current channel and joins another channel, the default audio route is used. /// - /// **Note** - /// - Call this method after calling [joinChannel]. - /// - If the user uses an external audio playback device such as a Bluetooth or wired headset, this method does not take effect, and the SDK plays audio through the external device. When the user uses multiple external devices, the SDK plays audio through the last connected device. /// - /// **Parameter** [enabled] Sets whether to enable the speakerphone or earpiece: - /// - `true`: Enable the speakerphone. The audio route is the speakerphone. - /// - `false`: Disable the speakerphone. The audio route is the earpiece. - Future setEnableSpeakerphone(bool enabled); + Future setEnableSpeakerphone(bool speakerOn); + /// /// Checks whether the speakerphone is enabled. + /// This method is for Android and iOS only. /// - /// **Note** + /// **return** true: The speakerphone is enabled, and the audio plays from the speakerphone. + /// false: The speakerphone is not enabled, and the audio plays from devices other than the speakerphone. For example, the headset or earpiece. /// - /// You can call this method either before or after joining a channel. - /// - /// **Returns** - /// - `true`: The speakerphone is enabled, and the audio plays from the speakerphone. - /// - `false`: The speakerphone is not enabled, and the audio plays from devices other than the speakerphone. For example, the headset or earpiece. Future isSpeakerphoneEnabled(); } /// @nodoc mixin RtcEarMonitoringInterface { + /// /// Enables in-ear monitoring. + /// This method enables or disables in-ear monitoring. + /// + /// + /// + /// This method is for Android and iOS only. + /// Users must use wired earphones to hear their own voices. + /// You can call this method either before or after joining a channel. + /// + /// Param [enabled] Enables in-ear monitoring. + /// true: Enables in-ear monitoring. + /// false: (Default) Disables in-ear monitoring. + /// + /// /// - /// **Parameter** [enabled] Sets whether to enable/disable in-ear monitoring: - /// - `true`: Enable. - /// - `false`: (Default) Disable. Future enableInEarMonitoring(bool enabled); + /// /// Sets the volume of the in-ear monitor. + /// This method is for Android and iOS only. + /// Users must use wired earphones to hear their own voices. + /// You can call this method either before or after joining a channel. + /// + /// Param [volume] The volume of the in-ear monitor. The value ranges between 0 and 100. The default value is 100. /// - /// **Parameter** [volume] Sets the volume of the in-ear monitor. The value ranges between 0 and 100 (default). Future setInEarMonitoringVolume(int volume); } /// @nodoc mixin RtcDualStreamInterface { - /// Enables/Disables the dual video stream mode. /// - /// If dual-stream mode is enabled, the receiver can choose to receive the high stream (high-resolution high-bitrate video stream) or low stream (low-resolution low-bitrate video stream) video. + /// Enables/Disables dual-stream mode. + /// You can call this method to enable or disable the dual-stream mode on the publisher side. Dual streams are a hybrid of a high-quality video stream and a low-quality video stream: + /// High-quality video stream: High bitrate, high resolution. + /// Low-quality video stream: Low bitrate, low resolution. + /// After you enable the dual-stream mode, you can call + /// to choose to receive the high-quality video stream or low-quality video stream on the subscriber side. + /// + /// You can call this method either before or after joining a channel. + /// + /// Param [enabled] Enables dual-stream mode. + /// true: Enables dual-stream mode. + /// false: Disables dual-stream mode. + /// + /// + /// /// - /// **Parameter** [enabled] Sets the stream mode: - /// - `true`: Dual-stream mode. - /// - `false`: (Default) Single-stream mode. Future enableDualStreamMode(bool enabled); - /// Sets the stream type of the remote video. /// - /// Under limited network conditions, if the publisher has not disabled the dual-stream mode using [RtcEngine.enableDualStreamMode] (false), the receiver can choose to receive either the high-video stream (the high resolution, and high bitrate video stream) or the low-video stream (the low resolution, and low bitrate video stream). + /// Sets the stream type of the remote video. + /// Under limited network conditions, if the publisher has not disabled the dual-stream mode using enableDualStreamMode(false), the receiver can choose to receive either the high-quality video stream (the high resolution, and high bitrate video stream) or the low-quality video stream (the low resolution, and low bitrate video stream). The high-quality video stream has a higher resolution and bitrate, and the low-quality video stream has a lower resolution and bitrate. + /// By default, users receive the high-quality video stream. Call this method if you want to switch to the low-quality video stream. This method allows the app to adjust the corresponding video stream type based on the size of the video window to reduce the bandwidth and resources. The aspect ratio of the low-quality video stream is the same as the high-quality video stream. Once the resolution of the high-quality video stream is set, the system automatically sets the resolution, frame rate, and bitrate of the low-quality video stream. /// - /// By default, users receive the high-video stream. Call this method if you want to switch to the low-video stream. This method allows the app to adjust the corresponding video stream type based on the size of the video window to reduce the bandwidth and resources. + /// The method result returns in the apiCallExecuted callback. /// - /// The aspect ratio of the low-video stream is the same as the high-video stream. Once the resolution of the high-video stream is set, the system automatically sets the resolution, frame rate, and bitrate of the low-video stream. + /// You can call this method either before or after joining a channel. If you call both setRemoteVideoStreamType and setRemoteDefaultVideoStreamType, the setting of setRemoteVideoStreamType takes effect. /// - /// The SDK reports the result of calling this method in the [RtcEngineEventHandler.apiCallExecuted] callback. + /// Param [streamType] The video stream type: VideoStreamType. /// - /// **Parameter** [uid] ID of the remote user sending the video stream. /// - /// **Parameter** [streamType] Sets the video-stream type. See [VideoStreamType]. - Future setRemoteVideoStreamType(int uid, VideoStreamType streamType); + Future setRemoteVideoStreamType(int userId, VideoStreamType streamType); - /// Sets the default video-stream type of the remotely subscribed video stream when the remote user sends dual streams. /// - /// You can call this method either before or after joining a channel. - /// If you call both [setRemoteVideoStreamType] and [setRemoteDefaultVideoStreamType], the SDK applies the settings in the [setRemoteVideoStreamType] method. + /// Sets the default stream type of remote video streams. + /// Under limited network conditions, if the publisher has not disabled the dual-stream mode using (),the receiver can choose to receive either the high-quality video stream or the low-quality video stream. The high-quality video stream has a higher resolution and bitrate, and the low-quality video stream has a lower resolution and bitrate.enableDualStreamModefalse + /// By default, users receive the high-quality video stream. Call this method if you want to switch to the low-quality video stream. This method allows the app to adjust the corresponding video stream type based on the size of the video window to reduce the bandwidth and resources. The aspect ratio of the low-quality video stream is the same as the high-quality video stream. Once the resolution of the high-quality video stream is set, the system automatically sets the resolution, frame rate, and bitrate of the low-quality video stream. + /// The result of this method returns in the apiCallExecuted callback. + /// You can call this method either before or after joining a channel. If you call both setRemoteVideoStreamType and setRemoteDefaultVideoStreamType, the settings in setRemoteVideoStreamType take effect. + /// + /// Param [streamType] The default stream type of the remote video, see VideoStreamType. + /// /// - /// **Parameter** [streamType] Sets the default video-stream type. See [VideoStreamType]. Future setRemoteDefaultVideoStreamType(VideoStreamType streamType); } /// @nodoc mixin RtcFallbackInterface { - /// Sets the fallback option for the locally published video stream based on the network conditions. /// - /// If option is set as [StreamFallbackOptions.AudioOnly], the SDK will: - /// - Disable the upstream video but enable audio only when the network conditions deteriorate and cannot support both video and audio. - /// - Re-enable the video when the network conditions improve. + /// Sets the fallback option for the published video stream based on the network conditions. + /// An unstable network affects the audio and video quality in a video call or interactive live video streaming. If option is set as AudioOnly(2), the SDK disables the upstream video but enables audio only when the network conditions deteriorate and cannot support both video and audio. The SDK monitors the network quality and restores the video stream when the network conditions improve. When the published video stream falls back to audio-only or when the audio-only stream switches back to the video, the SDK triggers the localPublishFallbackToAudioOnly callback. /// - /// When the locally published video stream falls back to audio only or when the audio-only stream switches back to the video, the SDK triggers the [RtcEngineEventHandler.localPublishFallbackToAudioOnly]. /// - /// **Note** - /// - Agora does not recommend using this method for CDN live streaming, because the remote CDN live user will have a noticeable lag when the locally published video stream falls back to audio only. + /// Agora does not recommend using this method for CDN live streaming, because the remote CDN live user will have a noticeable lag when the published video stream falls back to AudioOnly(2). + /// Ensure that you call this method before joining a channel. /// - /// **Parameter** [option] Sets the fallback option for the locally published video stream. See [StreamFallbackOptions]. + /// Param [option] The stream fallback option. For details, see StreamFallbackOptions. /// Future setLocalPublishFallbackOption(StreamFallbackOptions option); - /// Sets the fallback option for the remotely subscribed video stream based on the network conditions. /// - /// If option is set as [StreamFallbackOptions.VideoStreamLow] or [StreamFallbackOptions.AudioOnly], the SDK automatically switches the video from a high-stream to a low-stream, or disables the video when the downlink network condition cannot support both audio and video to guarantee the quality of the audio. The SDK monitors the network quality and restores the video stream when the network conditions improve. When the remotely subscribed video stream falls back to audio only, or the audio-only stream switches back to the video, the SDK triggers the [RtcEngineEventHandler.remoteSubscribeFallbackToAudioOnly] callback. + /// Sets the fallback option for the remote video stream based on the network conditions. + /// Unreliable network conditions affect the overall quality of the interactive live streaming. If option is set as VideoStreamLow(1) or AudioOnly(2), the SDK automatically switches the video from a high stream to a low stream or disables the video when the downlink network conditions cannot support both audio and video to guarantee the quality of the audio. The SDK monitors the network quality and restores the video stream when the network conditions improve. When the remote video stream falls back to audio-only or when the audio-only stream switches back to the video, the SDK triggers the remoteSubscribeFallbackToAudioOnly callback. + /// Ensure that you call this method before joining a channel. + /// + /// Param [option] See StreamFallbackOptions. The default value is VideoStreamLow(1). /// - /// **Parameter** [option] Sets the fallback option for the remotely subscribed video stream. See [StreamFallbackOptions]. Future setRemoteSubscribeFallbackOption(StreamFallbackOptions option); - /// Sets the priority of a remote user's media stream. /// - /// Use this method with the [RtcEngine.setRemoteSubscribeFallbackOption] method. If the fallback function is enabled for a subscribed stream, the SDK ensures the high-priority user gets the best possible stream quality. + /// Prioritizes a remote user's stream. + /// Prioritizes a remote user's stream. The SDK ensures the high-priority user gets the best possible stream quality. The SDK ensures the high-priority user gets the best possible stream quality. /// - /// **Note** - /// The Agora SDK supports setting `userPriority` as `High` for one user only. /// - /// **Parameter** [uid] The ID of the remote user. + /// The SDK supports setting only one user as high priority. + /// Ensure that you call this method before joining a channel. + /// + /// Param [uid] The ID of the remote user. + /// + /// Param [userPriority] The priority of the remote user. See UserPriority. /// - /// **Parameter** [userPriority] The priority of the remote user. See [UserPriority]. Future setRemoteUserPriority(int uid, UserPriority userPriority); } /// @nodoc mixin RtcTestInterface { + /// /// Starts an audio call test. + /// This method starts an audio call test to determine whether the audio devices (for example, headset and speaker) and the network connection are working properly. To conduct the test, let the user speak for a while, and the recording is played back within the set interval. If the user can hear the recording within the interval, the audio devices and network connection are working properly. /// - /// In the audio call test, you record your voice. If the recording plays back within the set time interval, the audio devices and the network connection are working properly. /// - /// **Note** - /// - Call this method before joining a channel. - /// - After calling this method, call the [RtcEngine.stopEchoTest] method to end the test. Otherwise, the app cannot run the next echo test, or call the [RtcEngine.joinChannel] method. - /// - In the [ChannelProfile.LiveBroadcasting] profile, only a host can call this method. + /// Call this method before joining a channel. + /// After calling stopEchoTest, you must call startEchoTest to end the test. Otherwise, the app cannot perform the next echo test, and you cannot join the channel. + /// In the live streaming channels, only a host can call this method. + /// + /// Param [intervalInSeconds] The time interval (s) between when you speak and when the recording plays back. /// /// **Parameter** [intervalInSeconds] The time interval (s) between when you speak and when the recording plays back. /// @@ -3082,499 +3799,637 @@ mixin RtcTestInterface { Future startEchoTest( {int? intervalInSeconds, EchoTestConfiguration? config}); + /// /// Stops the audio call test. + /// + /// Future stopEchoTest(); + /// /// Enables the network connection quality test. + /// This method tests the quality of the users' network connections. By default, this function is disabled. This method applies to the following scenarios: + /// Before a user joins a channel, call this method to check the uplink network quality. + /// Before an audience switches to a host, call this method to check the uplink network quality. + /// + /// + /// Regardless of the scenario, enabling this method consumes extra network traffic and affects the call quality. After receiving the lastmileQuality callback, call disableLastmileTest to stop the test, and then join the channel or switch to the host. /// - /// This method tests the quality of the users' network connections and is disabled by default. /// - /// Before users join a channel or before an audience switches to a host, call this method to check the uplink network quality. This method consumes additional network traffic, which may affect the communication quality. Call the [RtcEngine.disableLastmileTest] method to disable this test after receiving the [RtcEngineEventHandler.lastmileQuality] callback, and before the user joins a channel or switches the user role. + /// Do not use this method together with startLastmileProbeTest. + /// Do not call any other methods before receiving the lastmileQuality callback. Otherwise, the callback may be interrupted by other methods, and hence may not be triggered. + /// A host should not call this method after joining a channel (when in a call). + /// If you call this method to test the last mile network quality, the SDK consumes the bandwidth of a video stream, whose bitrate corresponds to the bitrate you set in setVideoEncoderConfiguration. After joining a channel, whether you have called disableLastmileTest or not, the SDK automatically stops consuming the bandwidth. /// - /// **Note** - /// - Do not use this method with the [RtcEngine.startLastmileProbeTest] method. - /// - Do not call any other methods before receiving the [RtcEngineEventHandler.lastmileQuality] callback. Otherwise, the callback may be interrupted by other methods and may not execute. - /// - In the [ChannelProfile.LiveBroadcasting] profile, a host should not call this method after joining a channel. - /// - If you call this method to test the last-mile quality, the SDK consumes the bandwidth of a video stream, whose bitrate corresponds to the bitrate you set in the [RtcEngine.setVideoEncoderConfiguration] method. After you join the channel, whether you have called the [RtcEngine.disableLastmileTest] method or not, the SDK automatically stops consuming the bandwidth. Future enableLastmileTest(); + /// /// Disables the network connection quality test. + /// + /// Future disableLastmileTest(); - /// Starts the last-mile network probe test before joining a channel to get the uplink and downlink last-mile network statistics, including the bandwidth, packet loss, jitter, and round-trip time (RTT). /// + /// Starts the last mile network probe test. + /// This method starts the last-mile network probe test before joining a channel to get the uplink and downlink last mile network statistics, including the bandwidth, packet loss, jitter, and round-trip time (RTT). /// Once this method is enabled, the SDK returns the following callbacks: - /// - [RtcEngineEventHandler.lastmileQuality]: the SDK triggers this callback within two seconds depending on the network conditions. This callback rates the network conditions with a score and is more closely linked to the user experience. - /// - [RtcEngineEventHandler.lastmileProbeResult]: the SDK triggers this callback within 30 seconds depending on the network conditions. This callback returns the real-time statistics of the network conditions and is more objective. + /// lastmileQuality: The SDK triggers this callback within two seconds depending on the network conditions. This callback rates the network conditions and is more closely linked to the user experience. + /// lastmileProbeResult: The SDK triggers this callback within 30 seconds depending on the network conditions. This callback returns the real-time statistics of the network conditions and is more objective. + /// + /// + /// This method applies to the following scenarios: + /// Before a user joins a channel, call this method to check the uplink network quality. + /// In a live streaming channel, call this method to check the uplink network quality before an audience member switches to a host. /// - /// Call this method to check the uplink network quality before users join a channel or before an audience switches to a host. /// - /// **Note** - /// - This method consumes extra network traffic and may affect communication quality. We do not recommend calling this method together with [RtcEngine.enableLastmileTest]. - /// - Do not call other methods before receiving the [RtcEngineEventHandler.lastmileQuality] and [RtcEngineEventHandler.lastmileProbeResult] callbacks. Otherwise, the callbacks may be interrupted by other methods. - /// - In the [ChannelProfile.LiveBroadcasting] profile, a host should not call this method after joining a channel. /// - /// **Parameter** [config] The configurations of the last-mile network probe test. See [LastmileProbeConfig]. + /// + /// Do not call other methods before receiving the lastmileQuality and lastmileProbeResult callbacks. Otherwise, the callbacks may be interrupted. + /// A host should not call this method after joining a channel (when in a call). + /// + /// Param [config] The configurations of the last-mile network probe test. See LastmileProbeConfig. + /// Future startLastmileProbeTest(LastmileProbeConfig config); - /// Stops the last-mile network probe test. + /// + /// Stops the last mile network probe test. + /// + /// Future stopLastmileProbeTest(); } /// @nodoc mixin RtcMediaMetadataInterface { - /// Registers the metadata observer. /// - /// This method enables you to add synchronized metadata in the video stream for more diversified live broadcast interactions, such as sending shopping links, digital coupons, and online quizzes. + /// Registers the metadata observer. + /// Call this method before joinChannel. + /// This method applies only to interactive live streaming. /// - /// **Note** - /// Call this method before the [RtcEngine.joinChannel] method. Future registerMediaMetadataObserver(); - /// Unregisters the metadata observer. + /// + /// Unregisters the specified metadata observer. + /// + /// Future unregisterMediaMetadataObserver(); - /// Sets the maximum size of the metadata. /// - /// **Parameter** [size] The maximum size of the buffer of the metadata that you want to use. The highest value is 1024 bytes. + /// Sets the maximum size of the media metadata. + /// After calling registerMediaMetadataObserver, you can call this method to set the maximum size of the media metadata. + /// + /// Param [size] The maximum size of media metadata. + /// Future setMaxMetadataSize(int size); - /// Sends the metadata. /// - /// **Parameter** [metadata] The metadata to be sent in the form of String. + /// Sends media metadata. + /// If the metadata is sent successfully, the SDK triggers the metadataReceived callback on the receiver. /// - /// **Note** + /// Param [metadata] Media metadata See Metadata. /// - /// Ensure that the size of the metadata does not exceed the value set in the [setMaxMetadataSize] method. - Future sendMetadata(String metadata); + Future sendMetadata(Uint8List metadata); } /// @nodoc mixin RtcWatermarkInterface { + /// /// Adds a watermark image to the local video. + /// This method adds a PNG watermark image to the local video in the live streaming. Once the watermark image is added, all the audience in the channel (CDN audience included), and the capturing device can see and capture it. Agora supports adding only one watermark image onto the local video, and the newly watermark image replaces the previous one. + /// The watermark coordinates are dependent on the settings in the setVideoEncoderConfiguration method: + /// If the orientation mode of the encoding video (VideoOutputOrientationMode) is FIXED_LANDSCAPE, or the landscape mode in ADAPTIVE, the watermark uses the landscape orientation. + /// If the orientation mode of the encoding video (VideoOutputOrientationMode) is FIXED_PORTRAIT, or the portrait mode in ADAPTIVE, the watermark uses the portrait orientation. + /// When setting the watermark position, the region must be less than the dimensions set in the setVideoEncoderConfiguration method. Otherwise, the watermark image will be cropped. + /// /// - /// This method adds a PNG watermark image to the local video stream in a live broadcast. Once the watermark image is added, all the audience in the channel (CDN audience included), and the recording device can see and capture it. /// - /// Agora supports adding only one watermark image onto the local video, and the newly watermark image replaces the previous one. /// - /// The watermark position depends on the settings in the [RtcEngine.setVideoEncoderConfiguration] method: - /// - If the orientation mode of the encoding video is [VideoOutputOrientationMode.FixedLandscape], or the landscape mode in [VideoOutputOrientationMode.Adaptative], the watermark uses the landscape orientation. - /// - If the orientation mode of the encoding video is [VideoOutputOrientationMode.FixedPortrait], or the portrait mode in [VideoOutputOrientationMode.Adaptative], the watermark uses the portrait orientation. - /// - When setting the watermark position, the region must be less than the dimensions set in the setVideoEncoderConfiguration method. Otherwise, the watermark image will be cropped. + /// Ensure that you have called enableVideo before calling this method. + /// If you only want to add a watermark to the CDN live streaming, you can call this method or the setLiveTranscoding method. + /// This method supports adding a watermark image in the PNG file format only. Supported pixel formats of the PNG image are RGBA, RGB, Palette, Gray, and Alpha_gray. + /// If the dimensions of the PNG image differ from your settings in this method, the image will be cropped or zoomed to conform to your settings. + /// If you have enabled the local video preview by calling the startPreview method, you can use the visibleInPreview member to set whether or not the watermark is visible in the preview. + /// If you have enabled the mirror mode for the local video, the watermark on the local video is also mirrored. To avoid mirroring the watermark, Agora recommends that you do not use the mirror and watermark functions for the local video at the same time. You can implement the watermark function in your application layer. /// - /// **Note** - /// - Ensure that you have called the [RtcEngine.enableVideo] method to enable the video module before calling this method. - /// - If you only want to add a watermark image to the local video for the audience in the CDN LiveBroadcasting channel to see and capture, you can call this method or the [RtcEngine.setLiveTranscoding] method. - /// - This method supports adding a watermark image in the PNG file format only. Supported pixel formats of the PNG image are RGBA, RGB, Palette, Gray, and Alpha_gray. - /// - If the dimensions the PNG image differ from your settings in this method, the image will be cropped or zoomed to conform to your settings. - /// - If you have enabled the local video preview by calling the startPreview method, you can use the visibleInPreview member in the WatermarkOptions class to set whether or not the watermark is visible in preview. - /// - If you have enabled the mirror mode for the local video, the watermark on the local video is also mirrored. To avoid mirroring the watermark, Agora recommends that you do not use the mirror and watermark functions for the local video at the same time. You can implement the watermark function in your application layer. + /// Param [watermarkUrl] The local file path of the watermark image to be added. This method supports adding a watermark image from the local absolute or relative file path. /// - /// **Parameter** [watermarkUrl] The local file path of the watermark image to be added. This method supports adding a watermark image from either the local file path or the assets file path. If you use the assets file path, you need to start with `/assets/` when filling in this parameter. + /// Param [options] The options of the watermark image to be added. For details, see WatermarkOptions. /// - /// **Parameter** [options] The options of the watermark image to be added. See [WatermarkOptions]. Future addVideoWatermark(String watermarkUrl, WatermarkOptions options); - /// Removes the watermark image from the video stream added by [RtcEngine.addVideoWatermark]. + /// + /// Removes the watermark image from the video stream. + /// + /// Future clearVideoWatermarks(); } /// @nodoc mixin RtcEncryptionInterface { - /// Enables built-in encryption with an encryption password before joining a channel. /// - /// **Deprecated** + /// Enables built-in encryption with an encryption password before users join a channel. + /// Deprecated: + /// This method is deprecated from v3.2.0. Please use enableEncryption instead. + /// + /// + /// Before joining the channel, you need to call this method to set the secret parameter to enable the built-in encryption. All users in the same channel should use the same secret. The secret is automatically cleared once a user leaves the channel. If you do not specify the secret or secret is set as null, the built-in encryption is disabled. /// - /// This method is deprecated. Use [RtcEngine.enableEncryption] instead. /// - /// All users in a channel must set the same encryption password. The encryption password is automatically cleared once a user leaves the channel. If the encryption password is not specified or set to empty, the encryption functionality is disabled. + /// Do not use this method for CDN live streaming. + /// For optimal transmission, ensure that the encrypted data size does not exceed the original data size + 16 bytes. 16 bytes is the maximum padding size for AES encryption. /// - /// **Note** - /// - For optimal transmission, ensure that the encrypted data size does not exceed the original data size + 16 bytes. 16 bytes is the maximum padding size for AES encryption. - /// - Do not use this method for CDN live streaming. + /// Param [secret] The encryption password. /// - /// **Parameter** [secret] The encryption password. @deprecated Future setEncryptionSecret(String secret); + /// /// Sets the built-in encryption mode. + /// Deprecated: + /// This method is deprecated from v3.2.0. Please use enableEncryption instead. + /// /// - /// **Deprecated** + /// The Agora SDK supports built-in encryption. The default encryption is AES-128-XTS. Call this method to use other encryption modes. All users in the same channel must use the same encryption mode and secret. Refer to the information related to the AES encryption algorithm on the differences between the encryption modes. + /// Before calling this method, please call setEncryptionSecret to enable the built-in encryption function. /// - /// This method is deprecated since v3.1.2. Use [RtcEngine.enableEncryption] instead. + /// Param [encryptionMode] Encryption mode. + /// "aes-128-xts": (Default) 128-bit AES encryption, XTS mode. + /// "aes-128-ecb": 128-bit AES encryption, ECB mode. + /// "aes-256-xts": 256-bit AES encryption, XTS mode. + /// "": When setting as NULL, the encryption mode is set as "aes-128-xts" by default. /// - /// The Agora SDK supports built-in encryption, which is set to aes-128-xts mode by default. Call this method to set the encryption mode to use other encryption modes. All users in the same channel must use the same encryption mode and password. /// - /// Refer to the information related to the AES encryption algorithm on the differences between the encryption modes. /// - /// **Note** - /// - Call the [RtcEngine.setEncryptionSecret] method before calling this method. /// - /// **Parameter** [encryptionMode] Sets the encryption mode. See [EncryptionMode]. @deprecated Future setEncryptionMode(EncryptionMode encryptionMode); + /// /// Enables/Disables the built-in encryption. + /// In scenarios requiring high security, Agora recommends calling this method to enable the built-in encryption before joining a channel. + /// All users in the same channel must use the same encryption mode and encryption key. After the user leaves the channel, the SDK automatically disables the built-in encryption. To enable the built-in encryption, call this method before the user joins the channel again. + /// If you enable the built-in encryption, you cannot use the RTMP or RTMPS streaming function. /// - /// In scenarios requiring high security, Agora recommends calling `enableEncryption` to enable the built-in encryption before joining a channel. + /// Param [enabled] Whether to enable built-in encryption: + /// true: Enable the built-in encryption. + /// false: Disable the built-in encryption. /// - /// All users in the same channel must use the same encryption mode and encryption key. Once all users leave the channel, the encryption key of this channel is automatically cleared. /// - /// **Note** - /// - If you enable the built-in encryption, you cannot use the RTMP or RTMPS streaming function. - /// - Agora supports four encryption modes. If you choose an encryption mode (excepting `SM4128ECB` mode), you need to add an external encryption library when integrating the SDK. For details, see the advanced guide *Channel Encryption*. /// /// - /// **Parameter** [enabled] Whether to enable the built-in encryption. - /// - `true`: Enable the built-in encryption. - /// - `false`: Disable the built-in encryption. - /// **Parameter** [config] Configurations of built-in encryption schemas. See [EncryptionConfig]. + /// Param [config] Configurations of built-in encryption. For details, see EncryptionConfig. + /// Future enableEncryption(bool enabled, EncryptionConfig config); } /// @nodoc mixin RtcAudioRecorderInterface { - /// Starts an audio recording on the client. /// - /// The SDK allows recording during a call. After successfully calling this method, you can record the audio of all the users in the channel and get an audio recording file. + /// Starts audio recording on the client. + /// Deprecated: + /// This method is deprecated as of v3.4.0. Please use startAudioRecordingWithConfig instead. + /// + /// + /// The Agora SDK allows recording during a call. After successfully calling this method, you can record the audio of all the users in the channel and get an audio recording file. Supported formats of the recording file are as follows: + /// .wav: Large file size with high fidelity. + /// .aac: Small file size with low fidelity. + /// + /// + /// + /// + /// Ensure that the directory you use to save the recording file exists and is writable. + /// This method should be called after the joinChannel method. The recording automatically stops when you call the leaveChannel method. + /// For better recording effects, set quality to Medium or High when sampleRate is 44.1 kHz or 48 kHz. /// - /// Supported formats of the recording file are as follows: - /// - .wav: Large file size with high fidelity. - /// - .aac: Small file size with low fidelity. + /// Param [filePath] The absolute path (including the filename extensions) of the recording file. For example: C:\music\audio.aac. + /// Ensure that the directory for the log files exists and is writable. /// - /// **Note** - /// - Ensure that the directory to save the recording file exists and is writable. - /// - This method is usually called after calling the [RtcEngine.joinChannel] method. The recording automatically stops when you call the [RtcEngine.leaveChannel] method. - /// - For better recording effects, set quality as [AudioRecordingQuality.Medium] or [AudioRecordingQuality.High] when sampleRate is 44.1 kHz or 48 kHz. /// - /// **Parameter** [filePath] Absolute file path (including the suffixes of the filename) of the recording file. The string of the file name is in UTF-8. For example, `/sdcard/emulated/0/audio/aac`. + /// Param [sampleRate] The sample rate (kHz) of the recording file. Supported values are as follows: + /// 16000 + /// (Default) 32000 + /// 44100 + /// 48000 /// - /// **Parameter** [sampleRate] Sample rate (Hz) of the recording file. See [AudioSampleRateType] for supported values. /// - /// **Parameter** [quality] The audio recording quality. See [AudioRecordingQuality]. + /// + /// + /// Param [quality] Recording quality. For more details, see AudioRecordingQuality. + /// @deprecated Future startAudioRecording(String filePath, AudioSampleRateType sampleRate, AudioRecordingQuality quality); - /// Starts an audio recording on the client. /// - /// Since v3.4.2 - /// - /// The SDK allows recording audio during a call. After successfully calling this method, you can record the audio of users in the channel and get an audio recording file. Supported file formats are as follows: - /// - WAV: High-fidelity files with typically larger file sizes. For example, if the sample rate is 32,000 Hz, the file size for a 10-minute recording is approximately 73 MB. - /// - AAC: Low-fidelity files with typically smaller file sizes. For example, if the sample rate is 32,000 Hz and the recording quality is `[AudioRecordingQuality.Medium]`, the file size for a 10-minute recording is approximately 2 MB. + /// Starts audio recording on the client. + /// The Agora SDK allows recording during a call. After successfully calling this method, you can record the audio of users in the channel and get an audio recording file. Supported formats of the recording file are as follows: + /// WAV: Large file size with high fidelity. For example, if the sample rate is 32,000 Hz, the file size for a recording duration of 10 minutes is around 73 M. + /// AAC: Small file size with low fidelity. For example, if the sample rate is 32,000 Hz and the recording quality is Medium, the file size for a recording duration of 10 minutes is around 2 M. /// /// Once the user leaves the channel, the recording automatically stops. + /// Call this method after joining a channel. /// - /// **Note** - /// - Call this method after joining a channel. + /// Param [config] Recording configuration. See AudioRecordingConfiguration. /// - /// **Parameter** [config] Recording configuration. See [AudioRecordingConfiguration]. Future startAudioRecordingWithConfig( AudioRecordingConfiguration config); - /// Enables the virtual metronome. /// - /// Since v3.4.2 + /// Enables the virtual metronome. + /// In music education, physical education and other scenarios, teachers usually need to use a metronome so that students can practice with the correct beat. The meter is composed of a downbeat and upbeats. The first beat of each measure is called a downbeat, and the rest are called upbeats. + /// In this method, you need to set the paths of the upbeat and downbeat files, the number of beats per measure, the tempo, and whether to send the sound of the metronome to remote users. /// - /// In music education, physical education, and other scenarios, teachers often need to use a metronome so that students can practice - /// at the correct tempo. A meter is composed of a downbeat and some number of upbeats (including zero). The first beat of each - /// measure is called the downbeat, and the rest are called the upbeats. In this method, you need to set the paths of the upbeat and - /// downbeat files, the number of beats per measure, the tempo, and whether to send the sound of the metronome to remote users. + /// After enabling the virtual metronome, the SDK plays the specified audio effect file from the beginning, and controls the playback duration of each file according to beatsPerMinute you set in RhythmPlayerConfig. For example, if you set beatsPerMinute as 60, the SDK plays one beat every second. If the file duration exceeds the beat duration, the SDK only plays the audio within the beat duration. /// - /// **Note** - /// - After enabling the virtual metronome, the SDK plays the specified files from the beginning and controls the beat duration according to the value of `beatsPerMinute` in [RhythmPlayerConfig]. - /// If the file duration exceeds the beat duration, the SDK only plays the audio within the beat duration. + /// Param [sound1] The absolute path or URL address (including the filename extensions) of the file for the downbeat. For example: Android: /sdcard/emulated/0/audio.mp4, iOS: /var/mobile/Containers/Data/audio.mp4. For the audio file formats supported by this method, see What formats of audio files does the Agora RTC SDK support. /// - /// **Parameter** [sound1] The absolute path or URL address (including the filename extensions) of the file for the downbeat. For example: `/sdcard/emulated/0/audio.mp4` on Android and `/var/mobile/Containers/Data/audio.mp4` on iOS. Supported audio formats include MP3, AAC, M4A, MP4, WAV, and 3GP. + /// Param [sound2] The absolute path or URL address (including the filename extensions) of the file for the upbeats. For example: Android: /sdcard/emulated/0/audio.mp4, iOS: /var/mobile/Containers/Data/audio.mp4. For the audio file formats supported by this method, see What formats of audio files does the Agora RTC SDK support. /// - /// **Parameter** [sound2] The absolute path or URL address (including the filename extensions) of the file for the upbeats. For example: `/sdcard/emulated/0/audio.mp4` on Android and `/var/mobile/Containers/Data/audio.mp4` on iOS. Supported audio formats include MP3, AAC, M4A, MP4, WAV, and 3GP. + /// Param [config] The metronome configuration. See RhythmPlayerConfig. /// - /// **Parameter** [config] The metronome configuration. See [RhythmPlayerConfig]. Future startRhythmPlayer( String sound1, String sound2, RhythmPlayerConfig config); - /// Disables the virtual metronome. /// - /// Since v3.4.2 + /// Disables the virtual metronome. + /// After calling startRhythmPlayer, you can call this method to disable the virtual metronome. /// - /// After calling [RtcEngine.startRhythmPlayer], you can call this method to disable the virtual metronome. Future stopRhythmPlayer(); - /// Configures the virtual metronome. /// - /// Since v3.4.2 + /// Configures the virtual metronome. + /// After enabling the virtual metronome, the SDK plays the specified audio effect file from the beginning, and controls the playback duration of each file according to beatsPerMinute you set in RhythmPlayerConfig. For example, if you set beatsPerMinute as 60, the SDK plays one beat every second. If the file duration exceeds the beat duration, the SDK only plays the audio within the beat duration. /// - /// After calling [RtcEngine.startRhythmPlayer], you can call this method to reconfigure the virtual metronome. + /// After calling startRhythmPlayer, you can call this method to reconfigure the virtual metronome. /// - /// **Note** - /// - After reconfiguring the virtual metronome, the SDK plays the specified files from the beginning and controls the beat duration according to the value of `beatsPerMinute` in [RhythmPlayerConfig]. - /// If the file duration exceeds the beat duration, the SDK only plays the audio within the beat duration. + /// Param [config] The metronome configuration. See RhythmPlayerConfig. /// - /// **Parameter** [config] The metronome configuration. For details, see [RhythmPlayerConfig]. Future configRhythmPlayer(RhythmPlayerConfig config); + /// /// Stops the audio recording on the client. + /// If you call startAudioRecordingWithConfig to start recording, you can call this method to stop the recording. + /// Once the user leaves the channel, the recording automatically stops. /// - /// **Note** - /// You can call this method before calling the [RtcEngine.leaveChannel] method; else, the recording automatically stops when you call the [RtcEngine.leaveChannel] method. Future stopAudioRecording(); } /// @nodoc mixin RtcInjectStreamInterface { - /// Injects an online media stream to a live broadcast. /// - /// If this method call is successful, the server pulls the voice or video stream and injects it into a live channel. This is applicable to scenarios where all audience members in the channel can watch a live show and interact with each other. + /// Injects an online media stream to a live streaming channel. + /// Agora will soon stop the service for injecting online media streams on the client. If you have not implemented this service, Agora recommends that you do not use it. For details, see Service Sunset Plans. + /// + /// + /// Ensure that you enable the RTMP Converter service before using this function. See Prerequisites in Push Streams to CDN. + /// This method takes effect only when you are a host in a live streaming channel. + /// Only one online media stream can be injected into the same channel at the same time. + /// Call this method after joining a channel. + /// /// - /// **Warning** + /// This method injects the currently playing audio and video as audio and video sources into the + /// ongoing live broadcast. This applies to scenarios where all users in the channel can + /// watch a live show and interact with each other. After calling this method, the SDK + /// triggers the streamInjectedStatus callback on the local client to + /// report the state of injecting the online media stream; after successfully injecting + /// the media stream, the stream joins the channel, and all users in the channel receive + /// the userJoined callback, where uid is + /// 666. /// - /// Agora will soon stop the service for injecting online media streams on the client. If you have not implemented this service, Agora recommends that you do not use it. + /// Param [url] The URL address to be added to the ongoing streaming. Valid protocols are RTMP, HLS, and HTTP-FLV. + /// Supported audio codec type: AAC. + /// Supported video codec type: H264 (AVC). /// - /// **Note** - /// - This method applies to the LiveBroadcasting profile only. - /// - Ensure that you enable the RTMP Converter service before using this function. See Prerequisites in *Push Streams to CDN*. - /// - You can inject only one media stream into the channel at the same time. /// - /// This method call triggers the following callbacks: - /// - The local client: - /// - [RtcEngineEventHandler.streamInjectedStatus], with the state of the injecting the online stream. - /// - [RtcEngineEventHandler.userJoined](uid: 666), if the method call is successful and the online media stream is injected into the channel. - /// - The remote client: - /// - [RtcEngineEventHandler.userJoined](uid: 666), if the method call is successful and the online media stream is injected into the channel. /// - /// **Parameter** [url] The URL address to be added to the ongoing live broadcast. Valid protocols are RTMP, HLS, and HTTP-FLV. - /// - Supported audio codec type: AAC. - /// - Supported video codec type: H264(AVC). /// - /// **Parameter** [config] The [LiveInjectStreamConfig] object which contains the configuration information for the added voice or video stream. + /// Param [config] The configuration information for the added voice or video stream: LiveInjectStreamConfig. + /// Future addInjectStreamUrl(String url, LiveInjectStreamConfig config); - /// Removes the injected online media stream from a live broadcast. /// - /// This method removes the URL address (added by [RtcEngine.addInjectStreamUrl]) from a live broadcast. + /// Removes the voice or video stream URL address from the live streaming. + /// Agora will soon stop the service for injecting online media streams on the client. If you have not implemented this service, Agora recommends that you do not use it. For details, see Service Sunset Plans. + /// After a successful method, the SDK triggers the userOffline callback + /// with the uid of 666. /// - /// If this method call is successful, the SDK triggers the [RtcEngineEventHandler.userOffline] callback and returns a stream uid of 666. + /// Param [url] The URL address of the injected stream to be removed. /// - /// **Parameter** [url] HTTP/HTTPS URL address of the added stream to be removed. Future removeInjectStreamUrl(String url); } /// @nodoc mixin RtcCameraInterface { - /// Switches between front and rear cameras. /// - /// Ensure that you call this method after the camera starts, for example, by calling `startPreview` or `joinChannel`. - /// - /// **Returns** + /// Switches between front and rear cameras. + /// This method needs to be called after the camera is started (for example, by calling startPreview or joinChannel). /// - /// - `true`: Success. - /// - `false`: Failure. Future switchCamera(); - /// Checks whether the camera zoom function is supported. /// - /// Ensure that you call this method after the camera starts, for example, by calling `startPreview` or `joinChannel`. + /// Checks whether the device supports camera zoom. + /// Call this method before calling joinChannel, enableVideo, or enableLocalVideo, depending on which method you use to turn on your local camera. /// - /// **Returns** + /// **return** true: The device supports camera zoom. + /// false: The device does not support camera zoom. /// - /// - `true`: The device supports the camera zoom function. - /// - `false`: The device does not support the camera zoom function. Future isCameraZoomSupported(); - /// Checks whether the camera flash function is supported. /// - /// Ensure that you call this method after the camera starts, for example, by calling `startPreview` or `joinChannel`. + /// Checks whether the device supports camera flash. + /// This method needs to be called after the camera is started (for example, by calling startPreview or joinChannel). /// - /// **Returns** /// - /// - `true`: The device supports the camera flash function. - /// - `false`: The device does not the support camera flash function. - Future isCameraTorchSupported(); - - /// Checks whether the camera manual focus function is supported. + /// The app enables the front camera by default. If your front camera does not support flash, this method returns false. + /// If you want to check whether the rear camera supports flash, call switchCamera before this method. /// - /// Ensure that you call this method after the camera starts, for example, by calling `startPreview` or `joinChannel`. + /// **return** true: The device supports camera flash. + /// false: The device does not support camera flash. /// - /// **Note** + Future isCameraTorchSupported(); + /// - /// This method is not supported for iOS. + /// Check whether the device supports the manual focus function. + /// Call this method before calling joinChannel, enableVideo, or enableLocalVideo, depending on which method you use to turn on your local camera. /// - /// **Returns** + /// **return** true: The device supports the manual focus function. + /// false: The device does not support the manual focus function. /// - /// - `true`: The device supports the camera manual focus function. - /// - `false`: The device does not support the camera manual focus function. Future isCameraFocusSupported(); - /// Checks whether the camera exposure function is supported. /// - /// Ensure that you call this method after the camera starts, for example, by calling `startPreview` or `joinChannel`. + /// Checks whether the device supports manual exposure. + /// Call this method before calling joinChannel, enableVideo, or enableLocalVideo, depending on which method you use to turn on your local camera. /// - /// **Returns** + /// **return** true: The device supports manual exposure. + /// false: The device does not support manual exposure. /// - /// - `true`: The device supports the camera exposure function. - /// - `false`: The device does not support the camera exposure function. Future isCameraExposurePositionSupported(); - /// Checks whether the camera auto-face focus function is supported. /// - /// Ensure that you call this method after the camera starts, for example, by calling `startPreview` or `joinChannel`. + /// Checks whether the device supports the face auto-focus function. + /// This method needs to be called after the camera is started (for example, by calling startPreview or joinChannel). /// - /// **Returns** + /// **return** true: The device supports the face auto-focus function. + /// false: The device does not support the face auto-focus function. /// - /// - `true`: The device supports the camera auto-face focus function. - /// - `false`: The device does not support the camera auto-face focus function. Future isCameraAutoFocusFaceModeSupported(); + /// /// Sets the camera zoom ratio. + /// Call this method before calling joinChannel, enableVideo, or enableLocalVideo, depending on which method you use to turn on your local camera. + /// + /// Param [factor] The camera zoom ratio. The value ranges between 1.0 and the maximum zoom supported by the device. You can get the maximum zoom ratio supported by the device by calling the getCameraMaxZoomFactor method. /// - /// **Parameter** [factor] Sets the camera zoom factor. The value ranges between 1.0 and the maximum zoom supported by the device. Future setCameraZoomFactor(double factor); - /// Gets the maximum zoom ratio supported by the camera. - /// - /// **Note** /// - /// This method is only supported in iOS. - /// - /// Ensure that you call this method after the camera starts, for example, by calling `startPreview` or `joinChannel`. + /// Gets the maximum zoom ratio supported by the camera. + /// Call this method before calling joinChannel, enableVideo, or enableLocalVideo, depending on which method you use to turn on your local camera. /// - /// **Returns** + /// **return** The maximum zoom factor. /// - /// - The maximum camera zoom factor, if this method call succeeds. - /// - Error code, if this method call fails. Future getCameraMaxZoomFactor(); + /// /// Sets the camera manual focus position. - /// A successful method call triggers the [RtcEngineEventHandler.cameraFocusAreaChanged] callback on the local client. + /// This method needs to be called after the camera is started (for example, by calling startPreview or joinChannel). + /// After a successful method call, the SDK triggers the cameraFocusAreaChanged callback. + /// This method is for Android and iOS only. + /// + /// Param [positionX] The horizontal coordinate of the touchpoint in the view. /// - /// **Parameter** [positionX] The horizontal coordinate of the touch point in the view. + /// Param [positionY] The vertical coordinate of the touchpoint in the view. /// - /// **Parameter** [positionY] The vertical coordinate of the touch point in the view. Future setCameraFocusPositionInPreview( double positionX, double positionY); + /// /// Sets the camera exposure position. + /// This method needs to be called after the camera is started (for example, by calling startPreview or joinChannel). + /// After a successful method call, the SDK triggers the cameraExposureAreaChanged callback. + /// This method is for Android and iOS only. /// - /// A successful method call triggers the [RtcEngineEventHandler.cameraExposureAreaChanged] callback on the local client. - /// See [RtcEngineEventHandler.cameraExposureAreaChanged] + /// Param [positionXinView] The horizontal coordinate of the touchpoint in the view. /// - /// **Parameter** [positionXinView] The horizontal coordinate of the touch point in the view. + /// Param [positionYinView] The vertical coordinate of the touchpoint in the view. /// - /// **Parameter** [positionYinView] The vertical coordinate of the touch point in the view. Future setCameraExposurePosition( double positionXinView, double positionYinView); + /// /// Enables/Disables face detection for the local user. + /// You can call this method either before or after joining a channel. + /// This method is for Android and iOS only. + /// Once face detection is enabled, the SDK triggers the facePositionChanged callback to report the face information of the local user: + /// The width and height of the local video. + /// The position of the human face in the local video. + /// The distance between the human face and the screen. /// - /// Once face detection is enabled, the SDK triggers the [RtcEngineEventHandler.facePositionChanged] callback to report the face information of the local user, which includes the following aspects: - /// - The width and height of the local video. - /// - The position of the human face in the local video. - /// - The distance between the human face and the device screen. /// - /// **Note** + /// This method needs to be called after the camera is started (for example, by calling startPreview or joinChannel). + /// + /// Param [enable] Whether to enable face detection: + /// true: Enable face detection. + /// false: (Default) Disable face detection. + /// /// - /// You can call this method either before or after joining a channel. /// - /// **Parameter** [enabled] Determines whether to enable the face detection function for the local user: - /// - `true`: Enable face detection. - /// - `false`: (Default) Disable face detection. - Future enableFaceDetection(bool enabled); + Future enableFaceDetection(bool enable); - /// Enables the camera flash function. /// - /// **Parameter** [isOn] Sets whether to enable/disable the camera flash function: - /// - `true`: Enable the camera flash function. - /// - `false`: Disable the camera flash function. + /// Enables the camera flash. + /// Call this method before calling joinChannel, enableVideo, or enableLocalVideo, depending on which method you use to turn on your local camera. + /// + /// Param [isOn] Whether to turn on the camera flash: + /// true: Turn on the flash. + /// false: (Default) Turn off the flash. + /// + /// + /// **return** 0: Success. + /// < 0: Failure. + /// Future setCameraTorchOn(bool isOn); - /// Sets whether to enable face autofocus. /// - /// The SDK disables face autofocus by default. To set face autofocus, call this method. + /// Enables the camera auto-face focus function. + /// Call this method before calling joinChannel, enableVideo, or enableLocalVideo, depending on which method you use to turn on your local camera. /// - /// **Note** + /// Param [] /// - /// Call this method after the camera is started. + /// **return** 0: Success. + /// < 0: Failure. /// - /// **Parameter** [enabled] Sets whether to enable/disable the camera auto-face focus function: - /// - `true`: Enable face autofocus. - /// - `false`: Disable face autofocus. Future setCameraAutoFocusFaceModeEnabled(bool enabled); - /// Sets The camera capture configuration. /// - /// For a video call or live broadcast, generally the SDK controls the camera output parameters. When the default camera capture settings do not meet special requirements or cause performance problems, we recommend using this method to set the camera capturer configuration: - /// - If the resolution or frame rate of the captured raw video data are higher than those set by [RtcEngine.setVideoEncoderConfiguration], processing video frames requires extra CPU and RAM usage and degrades performance. We recommend setting config as [CameraCaptureOutputPreference.Performance] to avoid such problems. - /// - If you do not need local video preview or are willing to sacrifice preview quality, we recommend setting config as [CameraCaptureOutputPreference.Performance] to optimize CPU and RAM usage. - /// - If you want better quality for the local video preview, we recommend setting config as [CameraCaptureOutputPreference.Preview]. + /// Sets the camera capture configuration. + /// Call this method before calling joinChannel, enableVideo, or enableLocalVideo, depending on which method you use to turn on your local camera. /// - /// **Note** - /// - Call this method before enabling the local camera. That said, you can call this method before calling [RtcEngine.joinChannel], [RtcEngine.enableVideo], or [RtcEngine.enableLocalVideo], depending on which method you use to turn on your local camera. + /// Param [config] The camera capturer configuration. See CameraCapturerConfiguration. /// - /// **Parameter** [config] The camera capture configuration. See [CameraCapturerConfiguration]. Future setCameraCapturerConfiguration( CameraCapturerConfiguration config); } /// @nodoc mixin RtcStreamMessageInterface { + /// /// Creates a data stream. + /// Each user can create up to five data streams during the lifecycle of RtcEngine. /// - /// Each user can create up to five data streams during the lifecycle of the [RtcEngine]. /// - /// **Deprecated** + /// Call this method after joining a channel. + /// Agora does not support setting reliable as true and ordered as true. /// - /// This method is deprecated from v3.3.1. + /// Param [reliable] Whether or not the data stream is reliable: + /// true: The recipients receive the data from the sender within five seconds. If the recipient does not receive the data within five seconds, the SDK triggers the streamMessageError callback and returns an error code. + /// false: There is no guarantee that the recipients receive the data stream within five seconds and no error message is reported for any delay or missing data stream. /// - /// **Note** - /// - Set both the reliable and ordered parameters to true or false. Do not set one as true and the other as false. /// - /// **Parameter** [reliable] Sets whether or not the recipients are guaranteed to receive the data stream from the sender within five seconds: - /// - `true`: The recipients receive the data from the sender within five seconds. If the recipient does not receive the data within five seconds, the SDK triggers the [RtcEngineEventHandler.streamMessageError] callback and returns an error code. - /// - `false`: There is no guarantee that the recipients receive the data stream within five seconds and no error message is reported for any delay or missing data stream. + /// Param [ordered] Whether or not the recipients receive the data stream in the sent order: + /// true: The recipients receive the data in the sent order. + /// false: The recipients do not receive the data in the sent order. /// - /// **Parameter** [ordered] Sets whether or not the recipients receive the data stream in the sent order: - /// - `true`: The recipients receive the data in the sent order. - /// - `false`: The recipients do not receive the data in the sent order. /// + /// **return** ID of the created data stream, if the method call succeeds. + /// < 0: Failure. /// - /// **Returns** - /// - The stream ID, if this method call succeeds. - /// - Error code, if this method call fails. Future createDataStream(bool reliable, bool ordered); - /// Creates a data stream. - /// - /// Since v3.3.1. /// - /// Each user can create up to five data streams in a single channel. + /// Creates a data stream. + /// Creates a data stream. Each user can create up to five data streams in a single channel. + /// Compared with createDataStream[1/2], this method does not support data reliability. If a data packet is not received five seconds after it was sent, the SDK directly discards the data. /// - /// This method does not support data reliability. If the receiver receives a data packet five seconds or more after it was sent, the SDK directly discards the data. + /// Param [config] The configurations for the data stream. For details, see DataStreamConfig. /// - /// **Parameter** [config] The configurations for the data stream: [DataStreamConfig]. + /// **return** ID of the created data stream, if the method call succeeds. + /// < 0: Failure. /// - /// **Returns** - /// - The stream ID, if this method call succeeds. - /// - Error code, if this method call fails. Future createDataStreamWithConfig(DataStreamConfig config); + /// /// Sends data stream messages. + /// Sends data stream messages to all users in a channel. The SDK has the following restrictions on this method:Up to 30 packets can be sent per second in a channel with each packet having a maximum size of 1 KB.Each client can send up to 6 KB of data per second.Each user can have up to five data streams simultaneously. + /// A successful method call triggers the streamMessage callback on the remote client, from which the remote user gets the stream message. A failed method call triggers the streamMessageError callback on the remote client. + /// + /// Ensure that you call createDataStreamWithConfig to create a data channel before calling this method. + /// In live streaming scenarios, this method only applies to hosts. + /// + /// Param [streamId] The data stream ID. You can get the data stream ID by calling createDataStreamWithConfig. + /// + /// Param [message] The message to be sent. + /// + Future sendStreamMessage(int streamId, Uint8List message); +} + +/// @nodoc +mixin RtcScreenSharingInterface { + /// + /// Shares the screen by specifying the display ID. + /// This method shares a screen or part of the screen. You need to specify the ID of the screen to be shared in this method. + /// + /// + /// This method applies to macOS only. + /// Call this method after joining a channel. + /// + /// Param [displayId] The display ID of the screen to be shared. This parameter specifies which screen you want to share. + /// + /// Param [regionRect] (Optional) Sets the relative location of the region to the screen. If you do not set this parameter, the SDK shares the whole screen. For details, see Rectangle. If the specified region overruns the screen, the SDK shares only the region within it; if you set width or height as 0, the SDK shares the whole screen. + /// + /// Param [captureParams] Screen sharing configurations. The default video dimension is 1920 x 1080, that is, 2,073,600 pixels. Agora uses the value of this parameter to calculate the charges. For details, see ScreenCaptureParameters. + /// + Future startScreenCaptureByDisplayId(int displayId, + [Rectangle? regionRect, ScreenCaptureParameters? captureParams]); + + /// + /// Shares the whole or part of a screen by specifying the screen rect. + /// This method shares a screen or part of the screen. You need to specify the area of the screen to be shared. + /// Call this method after joining a channel. + /// + /// Param [screenRect] Sets the relative location of the screen to the virtual screen. + /// + /// Param [regionRect] (Optional) Sets the relative location of the region to the screen. If you do not set this parameter, the SDK shares the whole screen. See Rectangle. If the specified region overruns the screen, the SDK shares only the region within it; if you set width or height as 0, the SDK shares the whole screen. + /// + /// Param [captureParams] The screen sharing encoding parameters. The default video dimension is 1920 x 1080, that is, 2,073,600 pixels. Agora uses the value of this parameter to calculate the charges. See ScreenCaptureParameters. + /// + Future startScreenCaptureByScreenRect(Rectangle screenRect, + [Rectangle? regionRect, ScreenCaptureParameters? captureParams]); + + /// + /// Shares the whole or part of a window by specifying the window ID. + /// This method shares a window or part of the window. You need to specify the ID of the window to be shared. + /// + /// + /// Call this method after joining a channel. + /// This method applies to macOS and Windows only. + /// + /// Param [windowId] The ID of the window to be shared. + /// + /// Param [regionRect] (Optional) Sets the relative location of the region to the screen. If you do not set this parameter, the SDK shares the whole screen. For details, see Rectangle. If the specified region overruns the window, the SDK shares only the region within it; if you set width or height as 0, the SDK shares the whole window. + /// + /// Param [captureParams] Screen sharing configurations. The default video dimension is 1920 x 1080, that is, 2,073,600 pixels. Agora uses the value of this parameter to calculate the charges. For details, see ScreenCaptureParameters. + /// + Future startScreenCaptureByWindowId(int windowId, + [Rectangle? regionRect, ScreenCaptureParameters? captureParams]); + + /// + /// Sets the content hint for screen sharing. + /// A content hint suggests the type of the content being shared, so that the SDK applies different optimization algorithms to different types of content. If you don't call this method, the default content hint is None. + /// You can call this method either before or after you start screen sharing. + /// + /// Param [contentHint] The content hint for screen sharing. For details, see VideoContentHint. + /// + Future setScreenCaptureContentHint(VideoContentHint contentHint); + + /// + /// Updates the screen sharing parameters. + /// + /// + /// Param [captureParams] The screen sharing encoding parameters. The default video dimension is 1920 x 1080, that is, 2,073,600 pixels. Agora uses the value of this parameter to calculate the charges. For details, see ScreenCaptureParameters. + /// + Future updateScreenCaptureParameters( + ScreenCaptureParameters captureParams); + + /// + /// Updates the screen sharing region. + /// + /// + /// Param [regionRect] The relative location of the screen-shared area to the screen or window. If you do not set this parameter, the SDK shares the whole screen or window. See Rectangle. If the specified region overruns the screen or window, the SDK shares only the region within it; if you set width or height as 0, the SDK shares the whole screen or window. + /// + Future updateScreenCaptureRegion(Rectangle regionRect); + + /// + /// Stops screen sharing. + /// + /// + Future stopScreenCapture(); + + /// + /// Starts screen sharing. + /// Deprecated: + /// This method is deprecated as of v2.4.0. See the following methods instead: + /// startScreenCaptureByDisplayId + /// startScreenCaptureByWindowId + /// + /// + /// + /// This method shares the whole screen, a specified window, or the specified region: + /// Whole screen: Set windowId as 0 and rect as null. + /// A specified window: Set windowId as a value other than 0. Each window has a windowId that is not 0. + /// The specified region: Set windowId as 0 and rect as a value other than null. In this case, you can share the specified region, for example by dragging the mouse or implementing your own logic. The specified region is a region on the whole screen. Currently, sharing a specified region in a specific window is not supported. /// - /// The SDK has the following restrictions on this method: - /// - Up to 30 packets can be sent per second in a channel with each packet having a maximum size of 1 kB. - /// - Each client can send up to 6 kB of data per second. - /// - Each user can have up to five data channels simultaneously. + /// captureFreq is the captured frame rate once the screen-sharing function is enabled. The mandatory value ranges between 1 fps and 15 fps. No matter which of the above functions you enable, the SDK returns 0 when the execution succeeds, and an error code when the execution fails. /// - /// A successful method call triggers the [RtcEngineEventHandler.streamMessage] callback on the remote client, from which the remote user gets the stream message. + /// Param [windowId] The screen sharing area. /// - /// A failed method call triggers the [RtcEngineEventHandler.streamMessageError] callback on the remote client. + /// Param [captureFreq] (Mandatory) The captured frame rate. The value ranges between 1 fps and 15 fps. /// - /// **Note** - /// - Ensure that you have created the data stream using [RtcEngine.createDataStream] before calling this method. - /// - This method applies only to the [ChannelProfile.Communication] profile or to hosts in the [ChannelProfile.LiveBroadcasting] profile. + /// Param [rect] Specifies the screen-sharing region: Rect. This parameter is valid when windowsId is set as 0. When rect is set as null, the whole screen is shared. /// - /// **Parameter** [streamId] ID of the sent data stream returned by the [RtcEngine.createDataStream] method. + /// Param [bitrate] The bitrate of the screen share. /// - /// **Parameter** [message] Sent data. - Future sendStreamMessage(int streamId, String message); + // TODO(littlegnal): [MS-99459] Doc breack change captureFreq type int? -> int, bitrate type + // int? -> int + Future startScreenCapture(int windowId, + [int captureFreq, Rect? rect, int bitrate]); } diff --git a/lib/src/rtc_engine_extension.dart b/lib/src/rtc_engine_extension.dart index 32cba1c29..74f852fdb 100644 --- a/lib/src/rtc_engine_extension.dart +++ b/lib/src/rtc_engine_extension.dart @@ -1,13 +1,181 @@ +import 'dart:convert'; +import 'dart:ffi'; +import 'dart:io'; + +import 'classes.dart'; import 'rtc_engine.dart'; -/// Extension for RtcEngine +class _Rect extends Struct { + @Double() + external double x; + @Double() + external double y; + @Double() + external double width; + @Double() + external double height; + + Rectangle toRectangle() { + return Rectangle( + x: x.toInt(), + y: y.toInt(), + width: width.toInt(), + height: height.toInt(), + ); + } +} + +class _Display extends Struct { + @Uint32() + external int id; + @Float() + external double scale; + external _Rect bounds; + external _Rect work_area; + @Int32() + external int rotation; +} + +class Display { + int id; + double scale; + Rectangle bounds; + Rectangle workArea; + int rotation; + + Display._(this.id, this.scale, this.bounds, this.workArea, this.rotation); + + factory Display.from(_Display _display) => Display._( + _display.id, + _display.scale, + _display.bounds.toRectangle(), + _display.work_area.toRectangle(), + _display.rotation); +} + +class _DisplayCollection extends Struct { + external Pointer<_Display> displays; + @Uint32() + external int length; +} + +const _kBasicResultLength = 512; + +class _Window extends Struct { + @Uint32() + external int id; + @Array(_kBasicResultLength) + external Array name; + @Array(_kBasicResultLength) + external Array owner_name; + external _Rect bounds; + external _Rect work_area; +} + +class Window { + int id; + String name; + String ownerName; + Rectangle bounds; + Rectangle workArea; + + Window._(this.id, this.name, this.ownerName, this.bounds, this.workArea); + + factory Window.from(_Window _window) { + final name = + utf8.decode(Iterable.generate(_kBasicResultLength, (index) { + return _window.name[index]; + }).where((element) => element != 0).toList()); + final owner_name = + utf8.decode(Iterable.generate(_kBasicResultLength, (index) { + return _window.owner_name[index]; + }).where((element) => element != 0).toList()); + return Window._(_window.id, name, owner_name, _window.bounds.toRectangle(), + _window.work_area.toRectangle()); + } +} + +class _WindowCollection extends Struct { + external Pointer<_Window> windows; + @Uint32() + external int length; +} + +final DynamicLibrary _nativeLib = Platform.isMacOS + ? DynamicLibrary.process() + : DynamicLibrary.open('AgoraRtcWrapper.dll'); + +final Pointer<_DisplayCollection> Function() _EnumerateDisplays = _nativeLib + .lookup Function()>>( + 'EnumerateDisplays') + .asFunction(); + +final void Function(Pointer<_DisplayCollection>) _FreeDisplayCollection = + _nativeLib + .lookup)>>( + 'FreeIrisDisplayCollection') + .asFunction(); + +final Pointer<_WindowCollection> Function() _EnumerateWindows = _nativeLib + .lookup Function()>>( + 'EnumerateWindows') + .asFunction(); + +final void Function(Pointer<_WindowCollection>) _FreeWindowCollection = + _nativeLib + .lookup)>>( + 'FreeIrisWindowCollection') + .asFunction(); + +/// +/// The RtcEngineExtension class. +/// +/// extension RtcEngineExtension on RtcEngine { - /// Get the actual absolute path of the asset through the relative path of the asset /// - /// - [assetPath] The resource path configured in the `flutter` -> `assets` field of pubspec.yaml, for example: assets/Sound_Horizon.mp3 - /// - Returns the actual absolute path of the asset + /// Gets the actual absolute path of the asset through the relative path of the asset. + /// + /// + /// Param [assetPath] The resource path configured in the flutter -> assets field of pubspec.yaml, for example: assets/Sound_Horizon.mp3. + /// + /// **return** The actual path of the asset. + /// Future getAssetAbsolutePath(String assetPath) { return RtcEngine.methodChannel .invokeMethod('getAssetAbsolutePath', assetPath); } + + /// + /// Enumerates the information of all the screens in the system. + /// + /// + /// **return** The information of the screen for screen-sharing. + /// + List enumerateDisplays() { + final list = []; + final collection = _EnumerateDisplays(); + for (var i = 0; i < collection.ref.length; ++i) { + final display = collection.ref.displays.elementAt(i).ref; + list.add(Display.from(display)); + } + _FreeDisplayCollection(collection); + return list; + } + + /// + /// Enumerates the information of all the windows in the system. + /// + /// + /// **return** The information of the window for screen-sharing. + /// + List enumerateWindows() { + final list = []; + final collection = _EnumerateWindows(); + for (var i = 0; i < collection.ref.length; ++i) { + final window = collection.ref.windows.elementAt(i).ref; + list.add(Window.from(window)); + } + _FreeWindowCollection(collection); + return list; + } } diff --git a/lib/src/rtc_engine_extension_web.dart b/lib/src/rtc_engine_extension_web.dart new file mode 100644 index 000000000..80482b765 --- /dev/null +++ b/lib/src/rtc_engine_extension_web.dart @@ -0,0 +1,23 @@ +import 'package:flutter/services.dart'; + +import 'enums.dart'; +import 'rtc_engine.dart'; + +/// Extension for RtcEngine +extension RtcEngineExtension on RtcEngine { + /// Get the actual absolute path of the asset through the relative path of the asset + /// + /// - [assetPath] The resource path configured in the `flutter` -> `assets` field of pubspec.yaml, for example: assets/Sound_Horizon.mp3 + /// - Returns the actual absolute path of the asset + Future getAssetAbsolutePath(String assetPath) { + throw PlatformException(code: ErrorCode.NotSupported.toString()); + } + + List enumerateDisplays() { + throw PlatformException(code: ErrorCode.NotSupported.toString()); + } + + List enumerateWindows() { + throw PlatformException(code: ErrorCode.NotSupported.toString()); + } +} diff --git a/lib/src/rtc_render_view.dart b/lib/src/rtc_render_view.dart index 5515d4bb4..f7a1686b9 100644 --- a/lib/src/rtc_render_view.dart +++ b/lib/src/rtc_render_view.dart @@ -1,64 +1,95 @@ +import 'dart:convert'; +import 'dart:io'; + import 'package:flutter/foundation.dart'; import 'package:flutter/gestures.dart'; +import 'package:flutter/material.dart'; import 'package:flutter/rendering.dart'; import 'package:flutter/services.dart'; -import 'package:flutter/widgets.dart'; import 'enum_converter.dart'; import 'enums.dart'; +import 'rtc_engine.dart'; +import 'api_types.dart'; + +ApiTypeEngine _getSetRenderModeApiType(int uid) { + return uid == 0 + ? ApiTypeEngine.kEngineSetLocalRenderMode + : ApiTypeEngine.kEngineSetRemoteRenderMode; +} + +ApiTypeEngine _getSetupVideoApiType(int uid) { + return uid == 0 + ? ApiTypeEngine.kEngineSetupLocalVideo + : ApiTypeEngine.kEngineSetupRemoteVideo; +} final Map _channels = {}; -/// Use SurfaceView on Android. -/// Use UIView on iOS. +/// +/// The RtcSurfaceView class, which is used for rendering the local and remote video. +/// This class corresponds to different classes on different platforms: +/// +/// Android: SurfaceView (https://developer.android.com/reference/android/view/SurfaceView). +/// iOS: UIView (https://developer.apple.com/documentation/uikit/uiview). +/// Web: DivElement (https://api.dart.dev/stable/2.15.0/dart-html/DivElement-class.html). +/// Does not apply to macOS or Windows. +/// class RtcSurfaceView extends StatefulWidget { - /// User ID. + /// + /// The user ID. + /// final int uid; - /// The unique channel name for the AgoraRTC session in the string format. The string length must be less than 64 bytes. Supported character scopes are: - /// - All lowercase English letters: a to z. - /// - All uppercase English letters: A to Z. - /// - All numeric characters: 0 to 9. - /// - The space character. - /// - Punctuation characters and other symbols, including: "!", "#", "$", "%", "&", "(", ")", "+", "-", ":", ";", "<", "=", ".", ">", "?", "@", "\[", "\]", "^", "_", " {", "}", "|", "~", ",". /// - /// **Note** - /// - The default value is the empty string "". Use the default value if the user joins the channel using the [RtcEngine.joinChannel] method in the [RtcEngine] class. - /// - If the user joins the channel using the [RtcChannel.joinChannel] method in the [RtcChannel] class, set this parameter as the channelId of the [RtcChannel] object. + /// The channel name. This parameter signifies the channel in which users engage in real-time audio and video interaction. Under the premise of the same App ID, users who fill in the same channel ID enter the same channel for audio and video interaction. The string length must be less than 64 bytes. Supported characters: + /// The 26 lowercase English letters: a to z. + /// The 26 uppercase English letters: A to Z. + /// The 10 numeric characters: 0 to 9. + /// Space + /// "!", "#", "$", "%", "&", "(", ")", "+", "-", ":", ";", "<", "=", ".", ">", "?", "@", "[", "]", "^", "_", "{", "}", "|", "~", "," + /// + /// + /// final String? channelId; - /// The rendering mode of the video view. + /// + /// The video render mode. For details, see VideoRenderMode. + /// final VideoRenderMode renderMode; - /// The video mirror mode. + /// + /// The video mirror mode. For details, see VideoMirrorMode. + /// final VideoMirrorMode mirrorMode; - /// Control whether the surface view's surface is placed on top of its window. /// - /// Only support [TargetPlatform.android]. + /// Whether to place the surface on top of another surface view in the window, but still behind the window itsellf. + /// This parameter is for Android only. + /// final bool zOrderOnTop; - /// Control whether the surface view's surface is placed on top of another regular surface view in the window (but still behind the window itself). - /// - /// Only support [TargetPlatform.android]. final bool zOrderMediaOverlay; - /// Callback signature for when a platform view was created. /// - /// `id` is the platform view's unique identifier. + /// Occurs when a platform view is created. + /// final PlatformViewCreatedCallback? onPlatformViewCreated; - /// Which gestures should be consumed by the web view. /// - /// It is possible for other gesture recognizers to be competing with the web view on pointer - /// events, e.g if the web view is inside a [ListView] the [ListView] will want to handle - /// vertical drags. The web view will claim gestures that are recognized by any of the - /// recognizers on this list. + /// The gesture object that should be consumed by the Web view. It is possible for other gesture recognizers to be competing + /// with the web view on pointer events, e.g if the web view is inside a [ListView] the [ListView] will want to handle vertical + /// drags. The web view will claim gestures that are recognized by any of the recognizers on this list. + /// When this set is empty or null, the web view will only handle pointer events for gestures that were not claimed by any + /// other gesture recognizer. /// - /// When this set is empty or null, the web view will only handle pointer events for gestures that - /// were not claimed by any other gesture recognizer. final Set>? gestureRecognizers; + /// + /// Whether to create a sub process. + /// + final bool subProcess; + /// Constructs a [RtcSurfaceView] RtcSurfaceView({ Key? key, @@ -70,6 +101,7 @@ class RtcSurfaceView extends StatefulWidget { this.zOrderMediaOverlay = false, this.onPlatformViewCreated, this.gestureRecognizers, + this.subProcess = false, }) : super(key: key); @override @@ -83,6 +115,24 @@ class _RtcSurfaceViewState extends State { int? _renderMode; int? _mirrorMode; + ApiTypeEngine get _apiType => widget.uid == 0 + ? ApiTypeEngine.kEngineSetupLocalVideo + : ApiTypeEngine.kEngineSetupRemoteVideo; + + Map get _creationParams => { + 'callApi': { + 'apiType': _apiType.index, + 'params': jsonEncode({ + 'canvas': { + 'uid': widget.uid, + 'channelId': widget.channelId, + 'renderMode': _renderMode, + 'mirrorMode': _mirrorMode, + } + }), + }, + }; + @override Widget build(BuildContext context) { if (defaultTargetPlatform == TargetPlatform.android) { @@ -93,11 +143,13 @@ class _RtcSurfaceViewState extends State { onPlatformViewCreated: onPlatformViewCreated, hitTestBehavior: PlatformViewHitTestBehavior.transparent, creationParams: { - 'data': {'uid': widget.uid, 'channelId': widget.channelId}, - 'renderMode': _renderMode, - 'mirrorMode': _mirrorMode, - 'zOrderOnTop': widget.zOrderOnTop, - 'zOrderMediaOverlay': widget.zOrderMediaOverlay, + ..._creationParams, + 'setZOrderOnTop': { + 'onTop': widget.zOrderOnTop, + }, + 'setZOrderMediaOverlay': { + 'isMediaOverlay': widget.zOrderMediaOverlay, + }, }, creationParamsCodec: const StandardMessageCodec(), gestureRecognizers: widget.gestureRecognizers, @@ -110,15 +162,29 @@ class _RtcSurfaceViewState extends State { viewType: 'AgoraSurfaceView', onPlatformViewCreated: onPlatformViewCreated, hitTestBehavior: PlatformViewHitTestBehavior.transparent, - creationParams: { - 'data': {'uid': widget.uid, 'channelId': widget.channelId}, - 'renderMode': _renderMode, - 'mirrorMode': _mirrorMode, - }, + creationParams: _creationParams, creationParamsCodec: const StandardMessageCodec(), gestureRecognizers: widget.gestureRecognizers, ), ); + } else if (kIsWeb) { + return GestureDetector( + behavior: HitTestBehavior.opaque, + child: PlatformViewLink( + viewType: 'AgoraSurfaceView', + onCreatePlatformView: onCreatePlatformView, + surfaceFactory: + (BuildContext context, PlatformViewController controller) { + return PlatformViewSurface( + controller: controller, + hitTestBehavior: PlatformViewHitTestBehavior.transparent, + gestureRecognizers: widget.gestureRecognizers != null + ? widget.gestureRecognizers! + : const >{}, + ); + }, + ), + ); } return Text('$defaultTargetPlatform is not yet supported by the plugin'); } @@ -138,10 +204,18 @@ class _RtcSurfaceViewState extends State { setData(); } if (oldWidget.renderMode != widget.renderMode) { - setRenderMode(); + if (kIsWeb || (Platform.isWindows || Platform.isMacOS)) { + setData(); + } else { + setRenderMode(); + } } if (oldWidget.mirrorMode != widget.mirrorMode) { - setMirrorMode(); + if (kIsWeb || (Platform.isWindows || Platform.isMacOS)) { + setData(); + } else { + setMirrorMode(); + } } if (defaultTargetPlatform == TargetPlatform.android) { if (oldWidget.zOrderOnTop != widget.zOrderOnTop) { @@ -160,25 +234,51 @@ class _RtcSurfaceViewState extends State { } void setData() { - _channels[_id]?.invokeMethod('setData', { - 'data': { - 'uid': widget.uid, - 'channelId': widget.channelId, - }, - }); + var params = { + 'userId': widget.uid, + 'channelId': widget.channelId, + }; + if (kIsWeb || (Platform.isWindows || Platform.isMacOS)) { + params['subProcess'] = widget.subProcess; + } + _renderMode = VideoRenderModeConverter(widget.renderMode).value(); + params['renderMode'] = _renderMode; + + _mirrorMode = VideoMirrorModeConverter(widget.mirrorMode).value(); + params['mirrorMode'] = _mirrorMode; + + if (!kIsWeb && (Platform.isAndroid || Platform.isIOS)) { + RtcEngine.methodChannel.invokeMethod('callApi', { + 'apiType': _getSetRenderModeApiType(widget.uid).index, + 'params': jsonEncode(params), + }); + } else { + _channels[_id]?.invokeMethod('setData', params); + } } void setRenderMode() { _renderMode = VideoRenderModeConverter(widget.renderMode).value(); - _channels[_id]?.invokeMethod('setRenderMode', { - 'renderMode': _renderMode, + + RtcEngine.methodChannel.invokeMethod('callApi', { + 'apiType': _getSetRenderModeApiType(widget.uid).index, + 'params': jsonEncode({ + 'userId': widget.uid, + 'renderMode': _renderMode, + 'mirrorMode': _mirrorMode, + }), }); } void setMirrorMode() { _mirrorMode = VideoMirrorModeConverter(widget.mirrorMode).value(); - _channels[_id]?.invokeMethod('setMirrorMode', { - 'mirrorMode': _mirrorMode, + RtcEngine.methodChannel.invokeMethod('callApi', { + 'apiType': _getSetRenderModeApiType(widget.uid).index, + 'params': jsonEncode({ + 'userId': widget.uid, + 'renderMode': _renderMode, + 'mirrorMode': _mirrorMode, + }), }); } @@ -201,48 +301,120 @@ class _RtcSurfaceViewState extends State { } widget.onPlatformViewCreated?.call(id); } + + PlatformViewController onCreatePlatformView( + PlatformViewCreationParams params) { + final controller = _HtmlElementViewController(params.id, params.viewType); + controller._initialize().then((_) { + params.onPlatformViewCreated(params.id); + onPlatformViewCreated(params.id); + setData(); + }); + return controller; + } +} + +class _HtmlElementViewController extends PlatformViewController + with WidgetsBindingObserver { + _HtmlElementViewController( + this.viewId, + this.viewType, + ); + + @override + final int viewId; + + /// The unique identifier for the HTML view type to be embedded by this widget. + /// + /// A PlatformViewFactory for this type must have been registered. + final String viewType; + + bool _initialized = false; + + Future _initialize() async { + final args = { + 'id': viewId, + 'viewType': viewType, + }; + await SystemChannels.platform_views.invokeMethod('create', args); + _initialized = true; + } + + @override + Future clearFocus() async { + // Currently this does nothing on Flutter Web. + // TODO(het): Implement this. See https://github.com/flutter/flutter/issues/39496 + } + + @override + Future dispatchPointerEvent(PointerEvent event) async { + // We do not dispatch pointer events to HTML views because they may contain + // cross-origin iframes, which only accept user-generated events. + } + + @override + Future dispose() async { + if (_initialized) { + await SystemChannels.platform_views.invokeMethod('dispose', viewId); + } + } } -/// Use TextureView on Android. -/// Not support iOS. +/// +/// The RtcTextureView class, which is used for rendering +/// the local and remote video. +/// This class corresponds to different classes in on different platforms: +/// +/// Android: TextureView (https://developer.android.com/reference/android/view/TextureView) +/// or FlutterTexture (https://api.flutter.dev/objcdoc/Protocols/FlutterTexture.html). +/// iOS/macOS/Windows: FlutterTexture (https://api.flutter.dev/objcdoc/Protocols/FlutterTexture.html). +/// Does not apply to Web. +/// class RtcTextureView extends StatefulWidget { - /// User ID. + /// + /// The user ID. + /// final int uid; - /// The unique channel name for the AgoraRTC session in the string format. The string length must be less than 64 bytes. Supported character scopes are: - /// - All lowercase English letters: a to z. - /// - All uppercase English letters: A to Z. - /// - All numeric characters: 0 to 9. - /// - The space character. - /// - Punctuation characters and other symbols, including: "!", "#", "$", "%", "&", "(", ")", "+", "-", ":", ";", "<", "=", ".", ">", "?", "@", "\[", "\]", "^", "_", " {", "}", "|", "~", ",". /// - /// **Note** - /// - The default value is the empty string "". Use the default value if the user joins the channel using the [RtcEngine.joinChannel] method in the [RtcEngine] class. - /// - If the user joins the channel using the [RtcChannel.joinChannel] method in the [RtcChannel] class, set this parameter as the channelId of the [RtcChannel] object. + /// + /// final String? channelId; - /// The rendering mode of the video view. + /// + /// The video render mode. For details, see VideoRenderMode. + /// final VideoRenderMode renderMode; - /// The video mirror mode. + /// + /// The video mirror mode. For details, see VideoMirrorMode. + /// final VideoMirrorMode mirrorMode; - /// Callback signature for when a platform view was created. /// - /// `id` is the platform view's unique identifier. + /// Occurs when a platform view is created. + /// final PlatformViewCreatedCallback? onPlatformViewCreated; - /// Which gestures should be consumed by the web view. /// - /// It is possible for other gesture recognizers to be competing with the web view on pointer - /// events, e.g if the web view is inside a [ListView] the [ListView] will want to handle - /// vertical drags. The web view will claim gestures that are recognized by any of the - /// recognizers on this list. + /// The gesture object that should be consumed by the Web view. It is possible for other gesture recognizers to be competing + /// with the web view on pointer events, e.g if the web view is inside a [ListView] the [ListView] will want to handle vertical + /// drags. The web view will claim gestures that are recognized by any of the recognizers on this list. + /// When this set is empty or null, the web view will only handle pointer events for gestures that were not claimed by any + /// other gesture recognizer. /// - /// When this set is empty or null, the web view will only handle pointer events for gestures that - /// were not claimed by any other gesture recognizer. final Set>? gestureRecognizers; + /// + /// Whether to use FlutterTexture for rendering the view. + /// + final bool useFlutterTexture; + + /// + /// Whether to create a sub process. + /// + final bool subProcess; + /// Constructs a [RtcTextureView] RtcTextureView({ Key? key, @@ -252,6 +424,8 @@ class RtcTextureView extends StatefulWidget { this.mirrorMode = VideoMirrorMode.Auto, this.onPlatformViewCreated, this.gestureRecognizers, + this.useFlutterTexture = true, + this.subProcess = false, }) : super(key: key); @override @@ -267,24 +441,43 @@ class _RtcTextureViewState extends State { @override Widget build(BuildContext context) { - if (defaultTargetPlatform == TargetPlatform.android) { - return GestureDetector( - behavior: HitTestBehavior.opaque, - child: AndroidView( - viewType: 'AgoraTextureView', - onPlatformViewCreated: onPlatformViewCreated, - hitTestBehavior: PlatformViewHitTestBehavior.transparent, - creationParams: { - 'data': {'uid': widget.uid, 'channelId': widget.channelId}, - 'renderMode': _renderMode, - 'mirrorMode': _mirrorMode, - }, - creationParamsCodec: const StandardMessageCodec(), - gestureRecognizers: widget.gestureRecognizers, - ), - ); + if (kIsWeb) { + return Text('Web is not yet supported by the plugin'); + } + if (widget.useFlutterTexture && + defaultTargetPlatform != TargetPlatform.android) { + if (_id != null) { + return Texture(textureId: _id!); + } + return Container(); + } else { + if (defaultTargetPlatform == TargetPlatform.android) { + return GestureDetector( + behavior: HitTestBehavior.opaque, + child: AndroidView( + viewType: 'AgoraTextureView', + onPlatformViewCreated: onPlatformViewCreated, + hitTestBehavior: PlatformViewHitTestBehavior.transparent, + creationParams: { + 'callApi': { + 'apiType': _getSetupVideoApiType(widget.uid).index, + 'params': jsonEncode({ + 'canvas': { + 'uid': widget.uid, + 'channelId': widget.channelId, + 'renderMode': _renderMode, + 'mirrorMode': _mirrorMode, + } + }), + }, + }, + creationParamsCodec: const StandardMessageCodec(), + gestureRecognizers: widget.gestureRecognizers, + ), + ); + } + return Text('$defaultTargetPlatform is not yet supported by the plugin'); } - return Text('$defaultTargetPlatform is not yet supported by the plugin'); } @override @@ -292,6 +485,21 @@ class _RtcTextureViewState extends State { super.initState(); _renderMode = VideoRenderModeConverter(widget.renderMode).value(); _mirrorMode = VideoMirrorModeConverter(widget.mirrorMode).value(); + if (widget.useFlutterTexture && + defaultTargetPlatform != TargetPlatform.android) { + RtcEngine.methodChannel.invokeMethod('createTextureRender', { + 'subProcess': widget.subProcess, + }).then((value) { + setState(() { + _id = value; + }); + if (!_channels.containsKey(value)) { + _channels[value] = + MethodChannel('agora_rtc_engine/texture_render_$value'); + setData(); + } + }); + } } @override @@ -313,28 +521,69 @@ class _RtcTextureViewState extends State { void dispose() { super.dispose(); _channels.remove(_id); + if (widget.useFlutterTexture && + defaultTargetPlatform != TargetPlatform.android) { + RtcEngine.methodChannel.invokeMethod('destroyTextureRender', { + 'id': _id, + 'subProcess': widget.subProcess, + }); + } } void setData() { - _channels[_id]?.invokeMethod('setData', { + if (defaultTargetPlatform == TargetPlatform.android) { + var params = { + 'canvas': { + 'uid': widget.uid, + 'channelId': widget.channelId, + 'renderMode': _renderMode, + 'mirrorMode': _mirrorMode, + }, + }; + _channels[_id]?.invokeMethod('callApi', { + 'apiType': _getSetupVideoApiType(widget.uid).index, + 'params': jsonEncode(params), + }); + + return; + } + var params = { 'data': { 'uid': widget.uid, 'channelId': widget.channelId, }, - }); + }; + if (kIsWeb || (Platform.isWindows || Platform.isMacOS)) { + params['subProcess'] = widget.subProcess; + } + _channels[_id]?.invokeMethod('setData', params); } void setRenderMode() { _renderMode = VideoRenderModeConverter(widget.renderMode).value(); - _channels[_id]?.invokeMethod('setRenderMode', { - 'renderMode': _renderMode, + _mirrorMode = VideoMirrorModeConverter(widget.mirrorMode).value(); + + RtcEngine.methodChannel.invokeMethod('callApi', { + 'apiType': _getSetRenderModeApiType(widget.uid).index, + 'params': jsonEncode({ + 'userId': widget.uid, + 'renderMode': _renderMode, + 'mirrorMode': _mirrorMode, + }), }); } void setMirrorMode() { + _renderMode = VideoRenderModeConverter(widget.renderMode).value(); _mirrorMode = VideoMirrorModeConverter(widget.mirrorMode).value(); - _channels[_id]?.invokeMethod('setMirrorMode', { - 'mirrorMode': _mirrorMode, + + RtcEngine.methodChannel.invokeMethod('callApi', { + 'apiType': _getSetRenderModeApiType(widget.uid).index, + 'params': jsonEncode({ + 'userId': widget.uid, + 'renderMode': _renderMode, + 'mirrorMode': _mirrorMode, + }), }); } diff --git a/macos/Classes/AgoraRtcChannelPlugin.h b/macos/Classes/AgoraRtcChannelPlugin.h new file mode 100644 index 000000000..963be89f7 --- /dev/null +++ b/macos/Classes/AgoraRtcChannelPlugin.h @@ -0,0 +1,7 @@ +#import + +@interface AgoraRtcChannelPlugin + : NSObject ++ (void)registerWithRegistrar:(NSObject *)registrar + engine:(void *)engine; +@end diff --git a/macos/Classes/AgoraRtcChannelPlugin.mm b/macos/Classes/AgoraRtcChannelPlugin.mm new file mode 100644 index 000000000..cfd69ca31 --- /dev/null +++ b/macos/Classes/AgoraRtcChannelPlugin.mm @@ -0,0 +1,43 @@ +#import "AgoraRtcChannelPlugin.h" +#import +#import +#import "CallApiMethodCallHandler.h" +#import "FlutterIrisEventHandler.h" +#import + +using namespace agora::iris; +using namespace agora::iris::rtc; + +@interface AgoraRtcChannelPlugin () +@property(nonatomic) IrisRtcEngine *engine; +@property(nonatomic) FlutterEventSink events; +@property(nonatomic) CallApiMethodCallHandler *callApiMethodCallHandler; +@property(nonatomic) FlutterIrisEventHandler *eventHandler; +@end + +@implementation AgoraRtcChannelPlugin ++ (void)registerWithRegistrar:(NSObject *)registrar + engine:(void *)engine { + FlutterMethodChannel *methodChannel = + [FlutterMethodChannel methodChannelWithName:@"agora_rtc_channel" + binaryMessenger:[registrar messenger]]; + FlutterEventChannel *eventChannel = + [FlutterEventChannel eventChannelWithName:@"agora_rtc_channel/events" + binaryMessenger:[registrar messenger]]; + AgoraRtcChannelPlugin *instance = [[AgoraRtcChannelPlugin alloc] init]; + instance.engine = (IrisRtcEngine *)engine; + instance.eventHandler = [[RtcChannelFlutterIrisEventHandler alloc] initWith:engine]; + instance.callApiMethodCallHandler = [[RtcChannelCallApiMethodCallHandler alloc] initWith:engine]; + [registrar addMethodCallDelegate:instance channel:methodChannel]; + [eventChannel setStreamHandler:instance.eventHandler]; +} + +- (void)handleMethodCall:(FlutterMethodCall *)call + result:(FlutterResult)result { + [[self callApiMethodCallHandler] onMethodCall:call _:result]; +} + ++ (void)registerWithRegistrar:(nonnull id)registrar { +} + +@end diff --git a/macos/Classes/AgoraRtcDeviceManagerPlugin.h b/macos/Classes/AgoraRtcDeviceManagerPlugin.h new file mode 100644 index 000000000..61666e7d6 --- /dev/null +++ b/macos/Classes/AgoraRtcDeviceManagerPlugin.h @@ -0,0 +1,10 @@ +#import + +@interface AgoraRtcDeviceManagerPlugin : NSObject +@property(nonatomic, assign) BOOL audio; + ++ (void)registerWithRegistrar:(NSObject *)registrar + engine:(void *)engine; + +- (instancetype)initWithType:(BOOL)audio; +@end diff --git a/macos/Classes/AgoraRtcDeviceManagerPlugin.mm b/macos/Classes/AgoraRtcDeviceManagerPlugin.mm new file mode 100644 index 000000000..0c3535356 --- /dev/null +++ b/macos/Classes/AgoraRtcDeviceManagerPlugin.mm @@ -0,0 +1,54 @@ +#import "AgoraRtcDeviceManagerPlugin.h" +#import "CallApiMethodCallHandler.h" +#import +#import + +using namespace agora::iris; +using namespace agora::iris::rtc; + +@interface AgoraRtcDeviceManagerPlugin () +@property(nonatomic) IrisRtcEngine *engine; +@property(nonatomic) CallApiMethodCallHandler *callApiMethodCallHandler; +@end + +@implementation AgoraRtcDeviceManagerPlugin ++ (void)registerWithRegistrar:(NSObject *)registrar + engine:(void *)engine { + FlutterMethodChannel *audioMethodChannel = [FlutterMethodChannel + methodChannelWithName:@"agora_rtc_audio_device_manager" + binaryMessenger:[registrar messenger]]; + AgoraRtcDeviceManagerPlugin *audioInstance = + [[AgoraRtcDeviceManagerPlugin alloc] initWithType:YES]; + audioInstance.engine = (IrisRtcEngine *)engine; + audioInstance.callApiMethodCallHandler = + [[RtcADMCallApiMethodCallHandler alloc] initWith:engine maxResultLength:kMaxResultLength]; + [registrar addMethodCallDelegate:audioInstance channel:audioMethodChannel]; + + FlutterMethodChannel *videoMethodChannel = [FlutterMethodChannel + methodChannelWithName:@"agora_rtc_video_device_manager" + binaryMessenger:[registrar messenger]]; + AgoraRtcDeviceManagerPlugin *videoInstance = + [[AgoraRtcDeviceManagerPlugin alloc] initWithType:NO]; + videoInstance.engine = (IrisRtcEngine *)engine; + videoInstance.callApiMethodCallHandler = + [[RtcVDMCallApiMethodCallHandler alloc] initWith:engine maxResultLength:kMaxResultLength]; + [registrar addMethodCallDelegate:videoInstance channel:videoMethodChannel]; +} + +- (instancetype)initWithType:(BOOL)audio { + self = [super init]; + if (self) { + self.audio = audio; + } + return self; +} + +- (void)handleMethodCall:(FlutterMethodCall *)call + result:(FlutterResult)result { + [[self callApiMethodCallHandler] onMethodCall:call _:result]; +} + ++ (void)registerWithRegistrar:(nonnull id)registrar { +} + +@end diff --git a/macos/Classes/AgoraRtcEnginePlugin.h b/macos/Classes/AgoraRtcEnginePlugin.h new file mode 100644 index 000000000..7df41ef84 --- /dev/null +++ b/macos/Classes/AgoraRtcEnginePlugin.h @@ -0,0 +1,4 @@ +#import + +@interface AgoraRtcEnginePlugin : NSObject +@end diff --git a/macos/Classes/AgoraRtcEnginePlugin.mm b/macos/Classes/AgoraRtcEnginePlugin.mm new file mode 100644 index 000000000..ee927582d --- /dev/null +++ b/macos/Classes/AgoraRtcEnginePlugin.mm @@ -0,0 +1,152 @@ +#import "AgoraRtcEnginePlugin.h" +#import "AgoraRtcChannelPlugin.h" +#import "AgoraRtcDeviceManagerPlugin.h" +#import "AgoraTextureViewFactory.h" +#import "CallApiMethodCallHandler.h" +#import "FlutterIrisEventHandler.h" +#import +#import +#import + +using namespace agora::iris; +using namespace agora::iris::rtc; + +@interface AgoraRtcEnginePlugin () +@property(nonatomic) IrisRtcEngine *engine_main; +@property(nonatomic) IrisRtcEngine *engine_sub; +@property(nonatomic) CallApiMethodCallHandler *callApiMethodCallHandlerMain; +@property(nonatomic) CallApiMethodCallHandler *callApiMethodCallHandlerSub; +@property(nonatomic) FlutterIrisEventHandler *eventHandler; +@property(nonatomic) FlutterEventSink events; +@property(nonatomic, strong) AgoraTextureViewFactory *factory; +@property(nonatomic) NSObject *registrar; +@end + +@implementation AgoraRtcEnginePlugin ++ (void)registerWithRegistrar:(NSObject *)registrar { + FlutterMethodChannel *methodChannel = + [FlutterMethodChannel methodChannelWithName:@"agora_rtc_engine" + binaryMessenger:[registrar messenger]]; + FlutterEventChannel *eventChannel = + [FlutterEventChannel eventChannelWithName:@"agora_rtc_engine/events" + binaryMessenger:[registrar messenger]]; + AgoraRtcEnginePlugin *instance = [[AgoraRtcEnginePlugin alloc] init]; + [instance + setFactory:[[AgoraTextureViewFactory alloc] initWithRegistrar:registrar]]; + + instance.eventHandler = + [[FlutterIrisEventHandler alloc] initWith:instance.engine_main + subEngine:instance.engine_sub]; + instance.registrar = registrar; + [registrar addMethodCallDelegate:instance channel:methodChannel]; + [eventChannel setStreamHandler:instance.eventHandler]; + + [AgoraRtcChannelPlugin registerWithRegistrar:registrar + engine:instance.engine_main]; + [AgoraRtcDeviceManagerPlugin registerWithRegistrar:registrar + engine:instance.engine_main]; +} + +- (instancetype)init { + self = [super init]; + if (self) { + self.engine_main = new IrisRtcEngine(); + self.engine_main->raw_data()->Attach(new IrisVideoFrameBufferManager); + self.callApiMethodCallHandlerMain = + [[CallApiMethodCallHandler alloc] initWith:self.engine_main]; + + self.engine_sub = new IrisRtcEngine(nullptr, kEngineTypeSubProcess); + self.engine_sub->raw_data()->Attach(new IrisVideoFrameBufferManager); + self.callApiMethodCallHandlerSub = + [[CallApiMethodCallHandler alloc] initWith:self.engine_sub]; + } + return self; +} + +- (void)dealloc { + if (self.engine_main) { + delete self.engine_main; + self.engine_main = nil; + } + + if (self.engine_sub) { + delete self.engine_sub; + self.engine_sub = nil; + } +} + +- (IrisRtcEngine *)engine:(id)arguments { + if ([self isSubProcess:arguments]) { + return self.engine_sub; + } else { + return self.engine_main; + } +} + +- (BOOL)isSubProcess:(id)arguments { + NSNumber *subProcess = arguments[@"subProcess"]; + return [subProcess boolValue]; +} + +- (void)handleMethodCall:(FlutterMethodCall *)call + result:(FlutterResult)result { +#if DEBUG + if ([@"getIrisRtcEngineIntPtr" isEqualToString:call.method]) { + if ([self isSubProcess:call.arguments]) { + result(@((intptr_t)self.engine_sub)); + } else { + result(@((intptr_t)self.engine_main)); + } + + return; + } +#endif + + if ([@"createTextureRender" isEqualToString:call.method]) { + int64_t textureId = [self.factory + createTextureRenderer:[self engine:call.arguments]->raw_data() + -> buffer_manager()]; + result(@(textureId)); + } else if ([@"destroyTextureRender" isEqualToString:call.method]) { + NSNumber *textureId = call.arguments[@"id"]; + [self.factory destroyTextureRenderer:[textureId integerValue]]; + result(nil); + } + else if ([@"getAssetAbsolutePath" isEqualToString:call.method]) { + [self getAssetAbsolutePath:call result:result]; + } + else { + if ([self isSubProcess:call.arguments]) { + [[self callApiMethodCallHandlerSub] onMethodCall:call _:result]; + } else { + [[self callApiMethodCallHandlerMain] onMethodCall:call _:result]; + } + } +} + +- (void)getAssetAbsolutePath:(FlutterMethodCall *)call + result:(FlutterResult)result { + NSString *assetPath = (NSString *)[call arguments]; + if (assetPath) { + NSString *bundlePath = [[NSBundle mainBundle] bundlePath]; + // Temporary workaround for loop up flutter asset in macOS + // https://github.com/flutter/flutter/issues/47681#issuecomment-958111474 + NSString *realPath = [NSString stringWithFormat:@"%@%@%@", bundlePath, @"/Contents/Frameworks/App.framework/Resources/flutter_assets/", assetPath]; + + if (realPath) { + result(realPath); + return; + } + + result([FlutterError + errorWithCode:@"FileNotFoundException" + message:nil + details:nil]); + return; + } + result([FlutterError + errorWithCode:@"IllegalArgumentException" + message:nil + details:nil]); +} +@end diff --git a/macos/Classes/AgoraRtcEnginePlugin.swift b/macos/Classes/AgoraRtcEnginePlugin.swift deleted file mode 100644 index 2c690aeaa..000000000 --- a/macos/Classes/AgoraRtcEnginePlugin.swift +++ /dev/null @@ -1,19 +0,0 @@ -import Cocoa -import FlutterMacOS - -public class AgoraRtcEnginePlugin: NSObject, FlutterPlugin { - public static func register(with registrar: FlutterPluginRegistrar) { - let channel = FlutterMethodChannel(name: "agora_rtc_engine", binaryMessenger: registrar.messenger) - let instance = AgoraRtcEnginePlugin() - registrar.addMethodCallDelegate(instance, channel: channel) - } - - public func handle(_ call: FlutterMethodCall, result: @escaping FlutterResult) { - switch call.method { - case "getPlatformVersion": - result("macOS " + ProcessInfo.processInfo.operatingSystemVersionString) - default: - result(FlutterMethodNotImplemented) - } - } -} diff --git a/macos/Classes/AgoraTextureViewFactory.h b/macos/Classes/AgoraTextureViewFactory.h new file mode 100644 index 000000000..21cf67749 --- /dev/null +++ b/macos/Classes/AgoraTextureViewFactory.h @@ -0,0 +1,9 @@ +#import + +@interface AgoraTextureViewFactory : NSObject +- (instancetype)initWithRegistrar:(NSObject *)registrar; + +- (int64_t)createTextureRenderer:(void *)renderer; + +- (BOOL)destroyTextureRenderer:(int64_t)textureId; +@end diff --git a/macos/Classes/AgoraTextureViewFactory.mm b/macos/Classes/AgoraTextureViewFactory.mm new file mode 100644 index 000000000..cbc85914a --- /dev/null +++ b/macos/Classes/AgoraTextureViewFactory.mm @@ -0,0 +1,185 @@ +#import "AgoraTextureViewFactory.h" +#import +#import +#import + +using namespace agora::iris; + +@interface TextureRenderer : NSObject +@property(nonatomic, weak) NSObject *textureRegistry; +@property(nonatomic, assign) int64_t textureId; +@property(nonatomic, strong) FlutterMethodChannel *channel; +@property(nonatomic) CVPixelBufferRef buffer_cache; +@property(nonatomic) CVPixelBufferRef buffer_temp; +@property(nonatomic) IrisVideoFrameBufferManager *renderer; +@property(nonatomic, strong) dispatch_semaphore_t lock; + +- (instancetype) + initWithTextureRegistry:(NSObject *)textureRegistry + messenger:(NSObject *)messenger + renderer:(IrisVideoFrameBufferManager *)renderer; + +- (void)destroy; +@end + +namespace { +class RendererDelegate : public IrisVideoFrameBufferDelegate { +public: + RendererDelegate(void *renderer) : renderer_(renderer) {} + + void OnVideoFrameReceived(const IrisVideoFrame &video_frame, + const IrisVideoFrameBufferConfig *config, + bool resize) override { + @autoreleasepool { + TextureRenderer *renderer = (__bridge TextureRenderer *)renderer_; + CVPixelBufferRef buffer = NULL; + NSDictionary *dic = [NSDictionary + dictionaryWithObjectsAndKeys: + @(YES), kCVPixelBufferCGBitmapContextCompatibilityKey, @(YES), + kCVPixelBufferCGImageCompatibilityKey, @(YES), + kCVPixelBufferOpenGLCompatibilityKey, @(YES), + kCVPixelBufferMetalCompatibilityKey, @(YES), + kCVPixelBufferOpenGLTextureCacheCompatibilityKey, nil]; + CVPixelBufferCreate(kCFAllocatorDefault, video_frame.width, + video_frame.height, kCVPixelFormatType_32BGRA, + (__bridge CFDictionaryRef)dic, &buffer); + + CVPixelBufferLockBaseAddress(buffer, 0); + void *copyBaseAddress = CVPixelBufferGetBaseAddress(buffer); + memcpy(copyBaseAddress, video_frame.y_buffer, + video_frame.y_buffer_length); + CVPixelBufferUnlockBaseAddress(buffer, 0); + + dispatch_semaphore_wait(renderer.lock, DISPATCH_TIME_FOREVER); + if (renderer.buffer_cache) { + CVPixelBufferRelease(renderer.buffer_cache); + } + renderer.buffer_cache = buffer; + dispatch_semaphore_signal(renderer.lock); + + [renderer.textureRegistry textureFrameAvailable:renderer.textureId]; + } + } + +public: + void *renderer_; +}; +} + +@interface TextureRenderer () +@property(nonatomic) RendererDelegate *delegate; +@end + +@implementation TextureRenderer +- (instancetype) + initWithTextureRegistry:(NSObject *)textureRegistry + messenger:(NSObject *)messenger + renderer:(IrisVideoFrameBufferManager *)renderer { + self = [super init]; + if (self) { + self.textureRegistry = textureRegistry; + self.textureId = [self.textureRegistry registerTexture:self]; + self.channel = [FlutterMethodChannel + methodChannelWithName: + [NSString stringWithFormat:@"agora_rtc_engine/texture_render_%lld", + self.textureId] + binaryMessenger:messenger]; + self.renderer = renderer; + self.lock = dispatch_semaphore_create(1); + self.delegate = new ::RendererDelegate((__bridge void *)self); + __weak typeof(self) weakSelf = self; + [self.channel setMethodCallHandler:^(FlutterMethodCall *_Nonnull call, + FlutterResult _Nonnull result) { + if (!weakSelf) { + return; + } + if ([@"setData" isEqualToString:call.method]) { + NSDictionary *data = call.arguments[@"data"]; + NSNumber *uid = data[@"uid"]; + NSString *channelId = data[@"channelId"]; + + IrisVideoFrameBuffer buffer(kVideoFrameTypeBGRA, + weakSelf.delegate); + IrisVideoFrameBufferConfig config; + config.id = [uid unsignedIntValue]; + if (config.id == 0) { + config.type = IrisVideoSourceType::kVideoSourceTypeCameraPrimary; + } else { + config.type = IrisVideoSourceType::kVideoSourceTypeRemote; + } + if (channelId && (NSNull *)channelId != [NSNull null]) { + strcpy(config.key, [channelId UTF8String]); + } else { + strcpy(config.key, ""); + } + renderer->EnableVideoFrameBuffer(buffer, &config); + } + }]; + } + return self; +} + +- (void)dealloc { + [self destroy]; + if (self.buffer_cache) { + CVPixelBufferRelease(self.buffer_cache); + } +} + +- (void)destroy { + [self.channel setMethodCallHandler:nil]; + self.renderer->DisableVideoFrameBuffer(self.delegate); + [self.textureRegistry unregisterTexture:self.textureId]; +} + +- (CVPixelBufferRef)copyPixelBuffer { + dispatch_semaphore_wait(self.lock, DISPATCH_TIME_FOREVER); + self.buffer_temp = self.buffer_cache; + CVPixelBufferRetain(self.buffer_temp); + dispatch_semaphore_signal(self.lock); + return self.buffer_temp; +} + +- (void)onTextureUnregistered:(NSObject *)texture { +} +@end + +@interface AgoraTextureViewFactory () +@property(nonatomic, weak) NSObject *registrar; +@property(nonatomic, weak) NSObject *messenger; +@property(nonatomic, strong) + NSMutableDictionary *renderers; +@end + +@implementation AgoraTextureViewFactory +- (instancetype)initWithRegistrar: + (NSObject *)registrar { + self = [super init]; + if (self) { + self.registrar = [registrar textures]; + self.messenger = [registrar messenger]; + self.renderers = [NSMutableDictionary new]; + } + return self; +} + +- (int64_t)createTextureRenderer:(void *)renderer { + TextureRenderer *texture = [[TextureRenderer alloc] + initWithTextureRegistry:self.registrar + messenger:self.messenger + renderer:(IrisVideoFrameBufferManager *)renderer]; + int64_t textureId = [texture textureId]; + self.renderers[@(textureId)] = texture; + return textureId; +} + +- (BOOL)destroyTextureRenderer:(int64_t)textureId { + TextureRenderer *texture = [self.renderers objectForKey:@(textureId)]; + if (texture != nil) { + [texture destroy]; + [self.renderers removeObjectForKey:@(textureId)]; + return YES; + } + return NO; +} +@end diff --git a/macos/Classes/CallApiMethodCallHandler.h b/macos/Classes/CallApiMethodCallHandler.h new file mode 100644 index 000000000..551488a7a --- /dev/null +++ b/macos/Classes/CallApiMethodCallHandler.h @@ -0,0 +1,34 @@ +#ifndef CallApiMethodCallHandler_h +#define CallApiMethodCallHandler_h + +#if TARGET_OS_IPHONE +#import +#else +#import +#endif + +@interface CallApiMethodCallHandler : NSObject +//@property(nonatomic) agora::iris::rtc::IrisRtcEngine *irisRtcEngine; +- (instancetype)initWith:(void *)engine; +- (instancetype)initWith:(void *)engine maxResultLength:(int)maxResultLength; +- (void)onMethodCall:(FlutterMethodCall *)call _:(FlutterResult)result; +- (int)callApi:(NSNumber *)apiType _:(NSString *)params _:(char *)result; + +- (int)callApiWithBuffer:(NSNumber *)apiType + _:(NSString *)params + _:(void *)buffer + _:(char *)result; + +- (NSString *)callApiError:(int)ret; +@end + +#endif /* CallApiMethodCallHandler_h */ + +@interface RtcChannelCallApiMethodCallHandler : CallApiMethodCallHandler +@end + +@interface RtcADMCallApiMethodCallHandler : CallApiMethodCallHandler +@end + +@interface RtcVDMCallApiMethodCallHandler : CallApiMethodCallHandler +@end diff --git a/macos/Classes/CallApiMethodCallHandler.mm b/macos/Classes/CallApiMethodCallHandler.mm new file mode 100644 index 000000000..ee0a53e82 --- /dev/null +++ b/macos/Classes/CallApiMethodCallHandler.mm @@ -0,0 +1,133 @@ +#import "CallApiMethodCallHandler.h" +#import +#import +#import + +@interface CallApiMethodCallHandler () +@property(nonatomic) agora::iris::rtc::IrisRtcEngine *irisRtcEngine; +@property(nonatomic) int maxResultLength; +@end + +@implementation CallApiMethodCallHandler + +- (instancetype)initWith:(void *)engine { + return [self initWith:engine maxResultLength:kBasicResultLength]; +} + +- (instancetype)initWith:(void *)engine maxResultLength:(int)maxResultLength { + self = [super init]; + if (self) { + self.irisRtcEngine = (agora::iris::rtc::IrisRtcEngine *)engine; + self.maxResultLength = maxResultLength; + } + return self; + +} + +- (void)onMethodCall:(FlutterMethodCall *)call _:(FlutterResult)result { + if ([@"callApi" isEqualToString:call.method] || + [@"callApiWithBuffer" isEqualToString:call.method]) { + @try { + NSDictionary *arguments = call.arguments; + NSNumber *apiType = arguments[@"apiType"]; + NSString *params = arguments[@"params"]; + FlutterStandardTypedData *buffer = arguments[@"buffer"]; + const int length = [self maxResultLength]; + char res[length]; + res[length] = {'\0'}; + int ret; + if (buffer == nil || buffer == [NSNull null]) { + + ret = [self callApi:apiType + _:params + _:res]; // self.irisRtcEngine->CallApi( + } else { + ret = [self callApiWithBuffer:apiType + _:params + _:(void *)[[buffer data] bytes] + _:res]; + } + if (ret == 0) { + if (strlen(res) == 0) { + result(nil); + } else { + result([NSString stringWithUTF8String:res]); + } + } else if (ret > 0) { + result(@(ret)); + } else { + NSString *des = [self callApiError:ret]; + result([FlutterError errorWithCode:[@(ret) stringValue] + message:des + details:nil]); + } + } @catch (NSException *exception) { + result([FlutterError errorWithCode:exception.name + message:exception.reason + details:nil]); + } + } else { + result(FlutterMethodNotImplemented); + } +} +- (int)callApi:(NSNumber *)apiType _:(NSString *)params _:(char *)result { + return self.irisRtcEngine->CallApi((ApiTypeEngine)[apiType unsignedIntValue], + [params UTF8String], result); +} + +- (int)callApiWithBuffer:(NSNumber *)apiType + _:(NSString *)params + _:(void *)buffer + _:(char *)result { + return self.irisRtcEngine->CallApi((ApiTypeEngine)[apiType unsignedIntValue], + [params UTF8String], buffer, result); +} + +- (NSString *)callApiError:(int)ret { + char description[kBasicResultLength]; + self.irisRtcEngine->CallApi( + ApiTypeEngine::kEngineGetErrorDescription, + [[NSString stringWithFormat:@"{\"code\":%d}", abs(ret)] UTF8String], + description); + return [NSString stringWithUTF8String:description]; +} + +@end + +@implementation RtcChannelCallApiMethodCallHandler + +- (int)callApi:(NSNumber *)apiType _:(NSString *)params _:(char *)result { + return self.irisRtcEngine->channel()->CallApi( + (ApiTypeChannel)[apiType unsignedIntValue], [params UTF8String], result); +} + +- (int)callApiWithBuffer:(NSNumber *)apiType + _:(NSString *)params + _:(void *)buffer + _:(char *)result { + return self.irisRtcEngine->channel()->CallApi( + (ApiTypeChannel)[apiType unsignedIntValue], [params UTF8String], buffer, + result); +} + +@end + +@implementation RtcADMCallApiMethodCallHandler + +- (int)callApi:(NSNumber *)apiType _:(NSString *)params _:(char *)result { + agora::iris::rtc::IrisRtcDeviceManager * deviceManager = (agora::iris::rtc::IrisRtcDeviceManager *) self.irisRtcEngine->device_manager(); + return deviceManager->CallApi((ApiTypeAudioDeviceManager)[apiType unsignedIntValue], + [params UTF8String], result); +} + +@end + +@implementation RtcVDMCallApiMethodCallHandler + +- (int)callApi:(NSNumber *)apiType _:(NSString *)params _:(char *)result { + agora::iris::rtc::IrisRtcDeviceManager * deviceManager = (agora::iris::rtc::IrisRtcDeviceManager *) self.irisRtcEngine->device_manager(); + return deviceManager->CallApi((ApiTypeVideoDeviceManager)[apiType unsignedIntValue], + [params UTF8String], result); +} + +@end diff --git a/macos/Classes/File.swift b/macos/Classes/File.swift new file mode 100644 index 000000000..27d6e0ba0 --- /dev/null +++ b/macos/Classes/File.swift @@ -0,0 +1,2 @@ +/// This file is created to make macos project can be compiled. +import Foundation diff --git a/macos/Classes/FlutterIrisEventHandler.h b/macos/Classes/FlutterIrisEventHandler.h new file mode 100644 index 000000000..0e93c0f1b --- /dev/null +++ b/macos/Classes/FlutterIrisEventHandler.h @@ -0,0 +1,20 @@ +#ifndef FlutterIrisEventHandler_h +#define FlutterIrisEventHandler_h + +#if TARGET_OS_IPHONE +#import +#else +#import +#endif + +@interface FlutterIrisEventHandler : NSObject +- (instancetype)initWith:(void *)engine; +- (instancetype)initWith:(void *)mainEngine subEngine:(void *)subEngine; +- (void)setUpEventHandler:(void *)engine eventHandler:(void *)eventHandler; +- (void)resetEventHandler:(void *)engine; +@end + +@interface RtcChannelFlutterIrisEventHandler : FlutterIrisEventHandler +@end + +#endif /* FlutterIrisEventHandler_h */ diff --git a/macos/Classes/FlutterIrisEventHandler.mm b/macos/Classes/FlutterIrisEventHandler.mm new file mode 100644 index 000000000..715256f23 --- /dev/null +++ b/macos/Classes/FlutterIrisEventHandler.mm @@ -0,0 +1,147 @@ +#import "FlutterIrisEventHandler.h" +#import +#import + +class EventHandler : public agora::iris::IrisEventHandler { +public: + EventHandler(FlutterEventSink eventSink, bool shouldHandleSubProcess = false, + bool sub_process = false) + : eventSink_(eventSink), sub_process_(sub_process), + shouldHandleSubProcess_(shouldHandleSubProcess) {} + + void OnEvent(const char *event, const char *data) override { + @autoreleasepool { + if (eventSink_) { + NSMutableDictionary *dic = [NSMutableDictionary + dictionaryWithObjectsAndKeys:[NSString stringWithUTF8String:event], + @"methodName", + [NSString stringWithUTF8String:data], + @"data", nil]; + + if (shouldHandleSubProcess_) { + [dic setObject:@(sub_process_) forKey:@"subProcess"]; + } + + eventSink_(dic); + } + } + } + + void OnEvent(const char *event, const char *data, const void *buffer, + unsigned int length) override { + @autoreleasepool { + FlutterStandardTypedData *bufferApple = [FlutterStandardTypedData + typedDataWithBytes:[[NSData alloc] initWithBytes:buffer + length:length]]; + if (eventSink_) { + NSMutableDictionary *dic = [NSMutableDictionary + dictionaryWithObjectsAndKeys:[NSString stringWithUTF8String:event], + @"methodName", + [NSString stringWithUTF8String:data], + @"data", bufferApple, @"buffer", nil]; + + if (shouldHandleSubProcess_) { + [dic setObject:@(sub_process_) forKey:@"subProcess"]; + } + + eventSink_(dic); + } + } + } + +private: + FlutterEventSink eventSink_; + bool sub_process_; + bool shouldHandleSubProcess_; +}; + +@interface FlutterIrisEventHandler () +@property(nonatomic) FlutterEventSink eventSink; +@property(nonatomic) agora::iris::rtc::IrisRtcEngine *irisRtcEngine; +@property(nonatomic) agora::iris::rtc::IrisRtcEngine *irisRtcEngineSub; +@property(nonatomic) EventHandler *eventHandler; +@property(nonatomic) EventHandler *eventHandlerSub; +@end + +@implementation FlutterIrisEventHandler + +- (instancetype)initWith:(void *)engine { + self.irisRtcEngine = (agora::iris::rtc::IrisRtcEngine *)engine; + return self; +} + +- (instancetype)initWith:(void *)mainEngine subEngine:(void *)subEngine { + self = [super init]; + if (self) { + self.irisRtcEngine = (agora::iris::rtc::IrisRtcEngine *)mainEngine; + self.irisRtcEngineSub = (agora::iris::rtc::IrisRtcEngine *)subEngine; + } + return self; +} + +- (void)dealloc { + if (self.eventHandler) { + delete self.eventHandler; + } + if (self.eventHandlerSub) { + delete self.eventHandlerSub; + } +} + +- (FlutterError *_Nullable)onCancelWithArguments:(id _Nullable)arguments { + self.eventSink = nil; + // self.irisRtcEngine->SetEventHandler(nil); + + [self resetEventHandler:self.irisRtcEngine]; + if (self.irisRtcEngineSub) { + [self resetEventHandler:self.irisRtcEngineSub]; + } + + return nil; +} + +- (FlutterError *)onListenWithArguments:(id)arguments + eventSink:(FlutterEventSink)events { + self.eventSink = events; + if (!self.eventHandler) { + self.eventHandler = + new EventHandler(self.eventSink, self.irisRtcEngineSub != nil, false); + [self setUpEventHandler:self.irisRtcEngine eventHandler:self.eventHandler]; + if (self.irisRtcEngineSub != nil) { + self.eventHandlerSub = new EventHandler(self.eventSink, true, true); + [self setUpEventHandler:self.irisRtcEngineSub + eventHandler:self.eventHandlerSub]; + } + } + + return nil; +} + +- (void)setUpEventHandler:(void *)engine eventHandler:(void *)eventHandler { + agora::iris::rtc::IrisRtcEngine *e = + (agora::iris::rtc::IrisRtcEngine *)engine; + e->SetEventHandler((EventHandler *)eventHandler); +} + +- (void)resetEventHandler:(void *)engine { + agora::iris::rtc::IrisRtcEngine *e = + (agora::iris::rtc::IrisRtcEngine *)engine; + e->SetEventHandler(nil); +} + +@end + +@implementation RtcChannelFlutterIrisEventHandler +- (void)setUpEventHandler:(void *)engine eventHandler:(void *)eventHandler { + agora::iris::rtc::IrisRtcEngine *e = + (agora::iris::rtc::IrisRtcEngine *)engine; + e->channel()->SetEventHandler((EventHandler *)eventHandler); +} + +- (void)resetEventHandler:(void *)engine { + agora::iris::rtc::IrisRtcEngine *e = + (agora::iris::rtc::IrisRtcEngine *)engine; + e->channel()->SetEventHandler(nil); +} + +@end diff --git a/macos/agora_rtc_engine.podspec b/macos/agora_rtc_engine.podspec index 36054add6..903983ae5 100644 --- a/macos/agora_rtc_engine.podspec +++ b/macos/agora_rtc_engine.podspec @@ -1,22 +1,22 @@ # # To learn more about a Podspec see http://guides.cocoapods.org/syntax/podspec.html. -# Run `pod lib lint agora_rtc_engine.podspec' to validate before publishing. +# Run `pod lib lint agora_rtc_engine.podspec` to validate before publishing. # +require "yaml" +require "ostruct" +project = OpenStruct.new YAML.load_file("../pubspec.yaml") + Pod::Spec.new do |s| - s.name = 'agora_rtc_engine' - s.version = '0.0.1' + s.name = project.name + s.version = project.version s.summary = 'A new flutter plugin project.' - s.description = <<-DESC -A new flutter plugin project. - DESC - s.homepage = 'http://example.com' + s.description = project.description + s.homepage = 'https://github.com/AgoraIO/Flutter-SDK' s.license = { :file => '../LICENSE' } - s.author = { 'Your Company' => 'email@example.com' } + s.author = { 'Agora' => 'developer@agora.io' } s.source = { :path => '.' } - s.source_files = 'Classes/**/*' + s.source_files = 'Classes/**/*.{h,mm}', 'Classes/File.swift' s.dependency 'FlutterMacOS' - + s.dependency 'AgoraIrisRTC_macOS', '3.5.2' s.platform = :osx, '10.11' - s.pod_target_xcconfig = { 'DEFINES_MODULE' => 'YES' } - s.swift_version = '5.0' end diff --git a/pubspec.yaml b/pubspec.yaml index 9299e8c7b..33b1708b1 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,8 +1,6 @@ name: agora_rtc_engine -description: >- - Flutter plugin to simply integrate Agora Video Calling or Live Video Streaming - to your app with just a few lines of code. -version: 4.2.1 +description: Flutter plugin for Agora Video SDK. +version: 5.0.0 homepage: 'https://www.agora.io' repository: 'https://github.com/AgoraIO/Flutter-SDK' environment: @@ -13,7 +11,9 @@ dependencies: sdk: flutter flutter_web_plugins: sdk: flutter + js: ^0.6.3 json_annotation: ^4.4.0 + dev_dependencies: integration_test: sdk: flutter @@ -22,7 +22,7 @@ dev_dependencies: flutter_driver: sdk: flutter pedantic: ^1.11.0 - build_runner: ^1.11.5 + build_runner: ^2.1.7 json_serializable: ^6.1.1 flutter: plugin: @@ -32,4 +32,11 @@ flutter: pluginClass: AgoraRtcEnginePlugin ios: pluginClass: AgoraRtcEnginePlugin + macos: + pluginClass: AgoraRtcEnginePlugin + windows: + pluginClass: AgoraRtcEnginePlugin + web: + fileName: agora_rtc_engine_web.dart + pluginClass: AgoraRtcEngineWeb diff --git a/scripts/build-internal-testing-macos.sh b/scripts/build-internal-testing-macos.sh new file mode 100644 index 000000000..ff999138b --- /dev/null +++ b/scripts/build-internal-testing-macos.sh @@ -0,0 +1,17 @@ +#!/usr/bin/env bash + +set -e + +ROOT_PATH=$(pwd) +EXAMPLE_PATH=$ROOT_PATH/example + +cd $EXAMPLE_PATH + +flutter build macos --release --dart-define TEST_APP_ID="$TEST_APP_ID" --dart-define TEST_TOEKN="$TEST_TOEKN" --dart-define TEST_CHANNEL_ID="$TEST_CHANNEL_ID" +mkdir -p $EXAMPLE_PATH/build/internal_testing_artifacts/macos +mkdir -p $EXAMPLE_PATH/build/internal_testing_artifacts/macos/dSYMs + +# /Users/fenglang/codes/aw/Agora-Flutter/example/build/macos/Build/Products/Release +cp -r $EXAMPLE_PATH/build/macos/Build/Products/Release/agora_rtc_engine_example.app "$EXAMPLE_PATH/build/internal_testing_artifacts/macos" +cp -r $EXAMPLE_PATH/build/macos/Build/Products/Release/agora_rtc_engine "$EXAMPLE_PATH/build/internal_testing_artifacts/macos/dSYMs" +cp -r $EXAMPLE_PATH/build/macos/Build/Products/Release/agora_rtc_engine_example.app.dSYM "$EXAMPLE_PATH/build/internal_testing_artifacts/macos/dSYMs" \ No newline at end of file diff --git a/scripts/build-internal-testing.sh b/scripts/build-internal-testing.sh new file mode 100644 index 000000000..3a0c3235d --- /dev/null +++ b/scripts/build-internal-testing.sh @@ -0,0 +1,23 @@ +#!/usr/bin/env bash + +set -e + +ROOT_PATH=$(pwd) +EXAMPLE_PATH=$ROOT_PATH/example + +cd $EXAMPLE_PATH + +flutter clean +flutter packages get + +mkdir build/internal_testing_artifacts +mkdir build/internal_testing_artifacts/ios +mkdir build/internal_testing_artifacts/android + +flutter build ipa --dart-define TEST_APP_ID="$TEST_APP_ID" --dart-define TEST_TOEKN="$TEST_TOEKN" --dart-define TEST_CHANNEL_ID="$TEST_CHANNEL_ID" --export-options-plist $exportPList +cp -r $EXAMPLE_PATH/build/app/outputs/flutter-apk/app-release.apk $EXAMPLE_PATH/build/internal_testing_artifacts/android/agora_rtc_engine_example.apk + +bash $ROOT_PATH/scripts/build-internal-testing-ios.sh + +dt=$(date '+%d/%m/%Y %H:%M:%S') +zip -r -y "$EXAMPLE_PATH/build/internal_testing_artifacts_${dt}.zip" "$EXAMPLE_PATH/build/internal_testing_artifacts" diff --git a/scripts/build-iris-all.sh b/scripts/build-iris-all.sh new file mode 100644 index 000000000..74887c8f5 --- /dev/null +++ b/scripts/build-iris-all.sh @@ -0,0 +1,14 @@ +#!/usr/bin/env bash + +set -e +set -x + +BUILD_TYPE=$1 + +if [[ -z "$BUILD_TYPE" ]]; then + BUILD_TYPE="Debug" +fi + +bash scripts/build-iris-android.sh $BUILD_TYPE +bash scripts/build-iris-ios.sh $BUILD_TYPE +bash scripts/build-iris-macos.sh $BUILD_TYPE \ No newline at end of file diff --git a/scripts/build-iris-android.sh b/scripts/build-iris-android.sh new file mode 100644 index 000000000..6f70c9e9e --- /dev/null +++ b/scripts/build-iris-android.sh @@ -0,0 +1,21 @@ +#!/usr/bin/env bash + +set -e + +AGORA_FLUTTER_PROJECT_PATH=$(pwd) +IRIS_PROJECT_PATH="$AGORA_FLUTTER_PROJECT_PATH/../iris/" +BUILD_TYPE=$1 +ABIS="arm64-v8a armeabi-v7a x86_64" + +bash $IRIS_PROJECT_PATH/rtc/ci/build-android.sh + +echo "Copying $IRIS_PROJECT_PATH/build/android/arm64-v8a/output/rtc/AgoraRtcWrapper.jar to $AGORA_FLUTTER_PROJECT_PATH/android/libs/AgoraRtcWrapper.jar" +cp -r "$IRIS_PROJECT_PATH/build/android/arm64-v8a/output/rtc/AgoraRtcWrapper.jar" "$AGORA_FLUTTER_PROJECT_PATH/android/libs/AgoraRtcWrapper.jar" + +for ABI in ${ABIS}; +do + echo "Copying $IRIS_PROJECT_PATH/build/android/$ABI/output/rtc/$BUILD_TYPE/libAgoraRtcWrapper.so to $AGORA_FLUTTER_PROJECT_PATH/android/libs/$ABI/libAgoraRtcWrapper.so" + mkdir -p "$AGORA_FLUTTER_PROJECT_PATH/android/libs/$ABI/" && \ + cp -r "$IRIS_PROJECT_PATH/build/android/$ABI/output/rtc/$BUILD_TYPE/libAgoraRtcWrapper.so" \ + "$AGORA_FLUTTER_PROJECT_PATH/android/libs/$ABI/libAgoraRtcWrapper.so" +done; \ No newline at end of file diff --git a/scripts/build-iris-ios.sh b/scripts/build-iris-ios.sh new file mode 100644 index 000000000..fc78987bf --- /dev/null +++ b/scripts/build-iris-ios.sh @@ -0,0 +1,26 @@ +#!/usr/bin/env bash + +set -e + +AGORA_FLUTTER_PROJECT_PATH=$(pwd) +IRIS_PROJECT_PATH="$AGORA_FLUTTER_PROJECT_PATH/../iris" +ARCH_TYPE="SIMULATOR64" +BUILD_TYPE=$1 + +bash $IRIS_PROJECT_PATH/rtc/ci/build-ios.sh + +echo "Copying $IRIS_PROJECT_PATH/build/ios/$ARCH_TYPE/output/rtc/$BUILD_TYPE/AgoraRtcWrapper.framework $AGORA_FLUTTER_PROJECT_PATH/ios/AgoraRtcWrapper.framework" +cp -r "$IRIS_PROJECT_PATH/build/ios/$ARCH_TYPE/output/rtc/$BUILD_TYPE/AgoraRtcWrapper.framework" "$AGORA_FLUTTER_PROJECT_PATH/ios/" + +if [ ! -d "$AGORA_FLUTTER_PROJECT_PATH/integration_test_app/iris_integration_test/third_party/iris" ]; then + mkdir -p "$AGORA_FLUTTER_PROJECT_PATH/integration_test_app/iris_integration_test/third_party/iris" +fi +cp -r "$IRIS_PROJECT_PATH/build/ios/OS64COMBINED/output/rtc/Release/AgoraRtcWrapper.framework/Headers/" "$AGORA_FLUTTER_PROJECT_PATH/integration_test_app/iris_integration_test/third_party/iris" + +if [ ! -d "$AGORA_FLUTTER_PROJECT_PATH/integration_test_app/iris_integration_test/third_party/agora/rtc/include" ]; then + mkdir -p "$AGORA_FLUTTER_PROJECT_PATH/integration_test_app/iris_integration_test/third_party/agora/rtc/include" +fi +cp -r "$IRIS_PROJECT_PATH/third_party/agora/rtc/include/" "$AGORA_FLUTTER_PROJECT_PATH/integration_test_app/iris_integration_test/third_party/agora/rtc/include" + +echo "Generating framework" +lipo -create "$IRIS_PROJECT_PATH/build/ios/SIMULATOR64/output/rtc/$BUILD_TYPE/AgoraRtcWrapper.framework/AgoraRtcWrapper" "$IRIS_PROJECT_PATH/build/ios/OS64COMBINED/output/rtc/$BUILD_TYPE/AgoraRtcWrapper.framework/AgoraRtcWrapper" -output "$AGORA_FLUTTER_PROJECT_PATH/ios/AgoraRtcWrapper.framework/AgoraRtcWrapper" \ No newline at end of file diff --git a/scripts/build-iris-macos.sh b/scripts/build-iris-macos.sh new file mode 100644 index 000000000..9fe46bd78 --- /dev/null +++ b/scripts/build-iris-macos.sh @@ -0,0 +1,21 @@ +#!/usr/bin/env bash + +set -e +set -x + +AGORA_FLUTTER_PROJECT_PATH=$(pwd) +IRIS_PROJECT_PATH="$AGORA_FLUTTER_PROJECT_PATH/../iris" +BUILD_TYPE=$1 + +echo "Cleaning build cache..." +rm -rf $IRIS_PROJECT_PATH/build + +echo "Building iris for mac..." +bash $IRIS_PROJECT_PATH/rtc/ci/build-mac.sh + +if [[ -d "$AGORA_FLUTTER_PROJECT_PATH/macos/AgoraRtcWrapper.framework" ]]; then + rm -rf $AGORA_FLUTTER_PROJECT_PATH/macos/AgoraRtcWrapper.framework +fi + +echo "Copying $IRIS_PROJECT_PATH/build/mac/MAC/output/rtc/$BUILD_TYPE/AgoraRtcWrapper.framework $AGORA_FLUTTER_PROJECT_PATH/macos/AgoraRtcWrapper.framework" +cp -RP "$IRIS_PROJECT_PATH/build/mac/MAC/output/rtc/$BUILD_TYPE/AgoraRtcWrapper.framework" "$AGORA_FLUTTER_PROJECT_PATH/macos/" \ No newline at end of file diff --git a/scripts/build-iris-windows.sh b/scripts/build-iris-windows.sh new file mode 100644 index 000000000..66521e795 --- /dev/null +++ b/scripts/build-iris-windows.sh @@ -0,0 +1,29 @@ +#!/usr/bin/env bash + +set -e + +AGORA_FLUTTER_PROJECT_PATH=$(pwd) +WINDOWS_PATH=$AGORA_FLUTTER_PROJECT_PATH/windows + +DOWNLOAD_IRIS_URL=$1 + +cd $WINDOWS_PATH + +mkdir -p iris_windows + +curl -u "$ARTIFACTORY_USER":"$ARTIFACTORY_PWD" -o "iris_windows/iris_windows.zip" -L $DOWNLOAD_IRIS_URL + +unzip $WINDOWS_PATH/iris_windows/iris_windows.zip -d $WINDOWS_PATH/iris_windows + +files=($WINDOWS_PATH/iris_windows/*) +echo "${files[0]}" +IRIS_ZIP="${files[0]}" + +cp -r $IRIS_ZIP/x64/include third_party/iris + +cp -r $IRIS_ZIP/x64/Debug/AgoraRtcScreenSharing.exe third_party/iris/AgoraRtcScreenSharing.exe +cp -r $IRIS_ZIP/x64/Debug/AgoraRtcWrapper.dll third_party/iris/AgoraRtcWrapper.dll +cp -r $IRIS_ZIP/x64/Debug/AgoraRtcWrapper.lib third_party/iris/AgoraRtcWrapper.lib + +rm -rf $WINDOWS_PATH/iris_windows + diff --git a/web b/web new file mode 160000 index 000000000..2e7dd4637 --- /dev/null +++ b/web @@ -0,0 +1 @@ +Subproject commit 2e7dd4637146a58a61b61b05fb6ebabdc47a206c diff --git a/windows/.gitignore b/windows/.gitignore index b3eb2be16..b77df48ae 100644 --- a/windows/.gitignore +++ b/windows/.gitignore @@ -15,3 +15,6 @@ x86/ *.[Cc]ache # but keep track of directories ending in .cache !*.[Cc]ache/ + +third_party/rtc +third_party/iris diff --git a/windows/CMakeLists.txt b/windows/CMakeLists.txt index 086f005f3..a90ca6a2b 100644 --- a/windows/CMakeLists.txt +++ b/windows/CMakeLists.txt @@ -6,19 +6,50 @@ project(${PROJECT_NAME} LANGUAGES CXX) # not be changed set(PLUGIN_NAME "agora_rtc_engine_plugin") +# Add this project's cmake/ directory to the module path. +set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_CURRENT_SOURCE_DIR}/cmake") + +set(IRIS_DOWNLOAD_PATH "${CMAKE_CURRENT_SOURCE_DIR}/third_party/iris") +set(IRIS_SDK_PATH "${IRIS_DOWNLOAD_PATH}/Agora_Native_SDK_for_Windows_IRIS/x64") +set(IRIS_SDK_BIN_PATH "${IRIS_SDK_PATH}/Release") +set(RTC_SDK_PATH "${IRIS_DOWNLOAD_PATH}/Agora_Native_SDK_for_Windows_IRIS/RTC") +set(RTC_SDK_BIN_PATH "${RTC_SDK_PATH}/Agora_Native_SDK_for_Windows_FULL/libs/x86_64") + +# Download and extract the SDK binary distribution (executes DownloadSDK.cmake). +include(DownloadSDK) +DownloadSDK("Windows" "v3_5_2" "${IRIS_DOWNLOAD_PATH}") + add_library(${PLUGIN_NAME} SHARED - "agora_rtc_engine_plugin.cpp" + "agora_rtc_channel_plugin.cc" + "agora_rtc_device_manager_plugin.cc" + "agora_rtc_engine_plugin.cc" + "agora_texture_view_factory.cc" + "call_api_method_call_handler.cc" ) apply_standard_settings(${PLUGIN_NAME}) set_target_properties(${PLUGIN_NAME} PROPERTIES CXX_VISIBILITY_PRESET hidden) target_compile_definitions(${PLUGIN_NAME} PRIVATE FLUTTER_PLUGIN_IMPL) target_include_directories(${PLUGIN_NAME} INTERFACE - "${CMAKE_CURRENT_SOURCE_DIR}/include") -target_link_libraries(${PLUGIN_NAME} PRIVATE flutter flutter_wrapper_plugin) + "${CMAKE_CURRENT_SOURCE_DIR}/include" + PRIVATE + "${IRIS_SDK_PATH}/include" + ) +target_link_libraries(${PLUGIN_NAME} PRIVATE flutter flutter_wrapper_plugin ${IRIS_SDK_BIN_PATH}/AgoraRtcWrapper.lib) # List of absolute paths to libraries that should be bundled with the plugin set(agora_rtc_engine_bundled_libraries - "" + "${IRIS_SDK_BIN_PATH}/AgoraRtcScreenSharing.exe" + "${IRIS_SDK_BIN_PATH}/AgoraRtcWrapper.dll" + "${RTC_SDK_BIN_PATH}/agora_rtc_sdk.dll" + "${RTC_SDK_BIN_PATH}/av1.dll" + "${RTC_SDK_BIN_PATH}/libagora_ai_denoise_extension.dll" + "${RTC_SDK_BIN_PATH}/libagora_dav1d_extension.dll" + "${RTC_SDK_BIN_PATH}/libagora-core.dll" + "${RTC_SDK_BIN_PATH}/libagora-fdkaac.dll" + "${RTC_SDK_BIN_PATH}/libagora-ffmpeg.dll" + "${RTC_SDK_BIN_PATH}/libagora-mpg123.dll" + "${RTC_SDK_BIN_PATH}/libagora-soundtouch.dll" + "${RTC_SDK_BIN_PATH}/libhwcodec.dll" PARENT_SCOPE ) diff --git a/windows/PluginInfo.props b/windows/PluginInfo.props deleted file mode 100644 index 3d2f9157b..000000000 --- a/windows/PluginInfo.props +++ /dev/null @@ -1,14 +0,0 @@ - - - - - agora_rtc_engine - - - - - - $(FlutterPluginName) - - - diff --git a/windows/agora_rtc_channel_plugin.cc b/windows/agora_rtc_channel_plugin.cc new file mode 100644 index 000000000..3ab2f5bb4 --- /dev/null +++ b/windows/agora_rtc_channel_plugin.cc @@ -0,0 +1,164 @@ +#include "include/agora_rtc_engine/agora_rtc_channel_plugin.h" +#include "include/agora_rtc_engine/call_api_method_call_handler.h" + +// This must be included before many other Windows headers. +#include + +#include +#include +#include +#include +#include + +namespace +{ + using namespace flutter; + using namespace agora::iris; + using namespace agora::iris::rtc; + + class RtcChannelCallApiMethodCallHandler : public CallApiMethodCallHandler + { + public: + RtcChannelCallApiMethodCallHandler(agora::iris::rtc::IrisRtcEngine *engine); + int32_t CallApi(int32_t api_type, const char *params, char *result) override; + int32_t CallApi(int32_t api_type, + const char *params, + void *buffer, + char *result) override; + }; + + RtcChannelCallApiMethodCallHandler::RtcChannelCallApiMethodCallHandler( + agora::iris::rtc::IrisRtcEngine *engine) : CallApiMethodCallHandler(engine) {} + + int32_t RtcChannelCallApiMethodCallHandler::CallApi(int32_t api_type, const char *params, + char *result) + { + return irisRtcEngine_->channel()->CallApi( + static_cast(api_type), params, result); + } + + int32_t RtcChannelCallApiMethodCallHandler::CallApi(int32_t api_type, + const char *params, + void *buffer, + char *result) + { + return irisRtcEngine_->channel()->CallApi(static_cast(api_type), + params, buffer, result); + } + + class AgoraRtcChannelPlugin : public Plugin, public IrisEventHandler + { + public: + static void RegisterWithRegistrar(PluginRegistrarWindows *registrar, + IrisRtcEngine *engine); + + AgoraRtcChannelPlugin(PluginRegistrar *registrar, IrisRtcEngine *engine); + + virtual ~AgoraRtcChannelPlugin(); + + public: + virtual void OnEvent(const char *event, const char *data) override; + + virtual void OnEvent(const char *event, const char *data, const void *buffer, + unsigned int length) override; + + private: + // Called when a method is called on this plugin's channel from Dart. + void HandleMethodCall(const MethodCall &method_call, + std::unique_ptr> result); + + private: + std::unique_ptr> event_sink_; + std::unique_ptr callApiMethodCallHandler_; + IrisRtcEngine *engine_; + }; + + // static + void AgoraRtcChannelPlugin::RegisterWithRegistrar( + PluginRegistrarWindows *registrar, IrisRtcEngine *engine) + { + auto method_channel = std::make_unique>( + registrar->messenger(), "agora_rtc_channel", + &StandardMethodCodec::GetInstance()); + auto event_channel = std::make_unique>( + registrar->messenger(), "agora_rtc_channel/events", + &StandardMethodCodec::GetInstance()); + + auto plugin = std::make_unique(registrar, engine); + + method_channel->SetMethodCallHandler( + [plugin_pointer = plugin.get()](const auto &call, auto result) + { + plugin_pointer->HandleMethodCall(call, std::move(result)); + }); + + auto handler = std::make_unique>( + [plugin_pointer = + plugin.get()](const EncodableValue *arguments, + std::unique_ptr> &&events) + -> std::unique_ptr> + { + plugin_pointer->event_sink_ = std::move(events); + return nullptr; + }, + [plugin_pointer = plugin.get()](const EncodableValue *arguments) + -> std::unique_ptr> + { + plugin_pointer->event_sink_ = nullptr; + return nullptr; + }); + event_channel->SetStreamHandler(std::move(handler)); + + registrar->AddPlugin(std::move(plugin)); + } + + AgoraRtcChannelPlugin::AgoraRtcChannelPlugin(PluginRegistrar *registrar, + IrisRtcEngine *engine) + : engine_(engine) + { + engine_->channel()->SetEventHandler(this); + callApiMethodCallHandler_ = std::make_unique(engine_); + } + + AgoraRtcChannelPlugin::~AgoraRtcChannelPlugin() {} + + void AgoraRtcChannelPlugin::HandleMethodCall( + const MethodCall &method_call, + std::unique_ptr> result) + { + callApiMethodCallHandler_->HandleMethodCall(method_call, std::move(result)); + } + + void AgoraRtcChannelPlugin::OnEvent(const char *event, const char *data) + { + if (event_sink_) + { + EncodableMap ret = {{EncodableValue("methodName"), EncodableValue(event)}, + {EncodableValue("data"), EncodableValue(data)}}; + event_sink_->Success(ret); + } + } + + void AgoraRtcChannelPlugin::OnEvent(const char *event, const char *data, + const void *buffer, unsigned int length) + { + if (event_sink_) + { + std::vector vector(length); + if (buffer && length) + { + memcpy(&vector[0], buffer, length); + } + EncodableMap ret = {{EncodableValue("methodName"), EncodableValue(event)}, + {EncodableValue("data"), EncodableValue(data)}, + {EncodableValue("buffer"), EncodableValue(vector)}}; + event_sink_->Success(ret); + } + } +} // namespace + +void AgoraRtcChannelPluginRegisterWithRegistrar( + PluginRegistrarWindows *registrar, IrisRtcEngine *engine) +{ + AgoraRtcChannelPlugin::RegisterWithRegistrar(registrar, engine); +} diff --git a/windows/agora_rtc_device_manager_plugin.cc b/windows/agora_rtc_device_manager_plugin.cc new file mode 100644 index 000000000..9117c0470 --- /dev/null +++ b/windows/agora_rtc_device_manager_plugin.cc @@ -0,0 +1,134 @@ +#include "include/agora_rtc_engine/agora_rtc_device_manager_plugin.h" +#include "include/agora_rtc_engine/call_api_method_call_handler.h" + +// This must be included before many other Windows headers. +#include +#include +#include + +#include +#include +#include + +namespace +{ + using namespace flutter; + using namespace agora::iris; + using namespace agora::iris::rtc; + + class RtcDeviceManagerAudioCallApiMethodCallHandler : public CallApiMethodCallHandler + { + + public: + RtcDeviceManagerAudioCallApiMethodCallHandler( + agora::iris::rtc::IrisRtcEngine *engine) : CallApiMethodCallHandler(engine) {} + + int32_t CallApi(int32_t api_type, const char *params, + char *result) override + { + return reinterpret_cast(irisRtcEngine_->device_manager())->CallApi(static_cast(api_type), params, result); + } + }; + + class RtcDeviceManagerVideoCallApiMethodCallHandler : public CallApiMethodCallHandler + { + + public: + RtcDeviceManagerVideoCallApiMethodCallHandler( + agora::iris::rtc::IrisRtcEngine *engine) : CallApiMethodCallHandler(engine) {} + + int32_t CallApi(int32_t api_type, const char *params, + char *result) override + { + return reinterpret_cast(irisRtcEngine_->device_manager())->CallApi(static_cast(api_type), params, result); + } + }; + + class AgoraRtcDeviceManagerPlugin : public Plugin + { + public: + static void RegisterWithRegistrar(PluginRegistrarWindows *registrar, + IrisRtcEngine *engine); + + AgoraRtcDeviceManagerPlugin(PluginRegistrar *registrar, + IrisRtcEngine *engine); + + virtual ~AgoraRtcDeviceManagerPlugin(); + + private: + // Called when a method is called on this plugin's channel from Dart. + void HandleMethodCall(const MethodCall &method_call, + std::unique_ptr> result, + bool audio); + + private: + IrisRtcEngine *engine_; + std::unique_ptr audioCallApiMethodCallHandler_; + std::unique_ptr videoCallApiMethodCallHandler_; + }; + + // static + void AgoraRtcDeviceManagerPlugin::RegisterWithRegistrar( + PluginRegistrarWindows *registrar, IrisRtcEngine *engine) + { + auto audio_method_channel = std::make_unique>( + registrar->messenger(), "agora_rtc_audio_device_manager", + &StandardMethodCodec::GetInstance()); + auto video_method_channel = std::make_unique>( + registrar->messenger(), "agora_rtc_video_device_manager", + &StandardMethodCodec::GetInstance()); + + auto plugin = + std::make_unique(registrar, engine); + + audio_method_channel->SetMethodCallHandler( + [plugin_pointer = plugin.get()](const auto &call, auto result) + { + plugin_pointer->HandleMethodCall(call, std::move(result), true); + }); + video_method_channel->SetMethodCallHandler( + [plugin_pointer = plugin.get()](const auto &call, auto result) + { + plugin_pointer->HandleMethodCall(call, std::move(result), false); + }); + + registrar->AddPlugin(std::move(plugin)); + } + + AgoraRtcDeviceManagerPlugin::AgoraRtcDeviceManagerPlugin( + PluginRegistrar *registrar, IrisRtcEngine *engine) + : engine_(engine) + { + audioCallApiMethodCallHandler_ = std::make_unique(engine_); + videoCallApiMethodCallHandler_ = std::make_unique(engine_); + } + + AgoraRtcDeviceManagerPlugin::~AgoraRtcDeviceManagerPlugin() {} + + void AgoraRtcDeviceManagerPlugin::HandleMethodCall( + const MethodCall &method_call, + std::unique_ptr> result, bool audio) + { + auto method = method_call.method_name(); + if (!method_call.arguments()) + { + result->Error("Bad Arguments", "Null arguments received"); + return; + } + + if (audio) + { + audioCallApiMethodCallHandler_.get()->HandleMethodCall(method_call, std::move(result)); + } + else + { + videoCallApiMethodCallHandler_.get()->HandleMethodCall(method_call, std::move(result)); + } + } +} // namespace + +void AgoraRtcDeviceManagerPluginRegisterWithRegistrar( + PluginRegistrarWindows *registrar, IrisRtcEngine *engine) +{ + AgoraRtcDeviceManagerPlugin::RegisterWithRegistrar(registrar, engine); +} diff --git a/windows/agora_rtc_engine_plugin.cc b/windows/agora_rtc_engine_plugin.cc new file mode 100644 index 000000000..85f50ab65 --- /dev/null +++ b/windows/agora_rtc_engine_plugin.cc @@ -0,0 +1,257 @@ +#include "include/agora_rtc_engine/agora_rtc_engine_plugin.h" +#include "include/agora_rtc_engine/call_api_method_call_handler.h" + +// This must be included before many other Windows headers. +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include "include/agora_rtc_engine/agora_rtc_channel_plugin.h" +#include "include/agora_rtc_engine/agora_rtc_device_manager_plugin.h" +#include "include/agora_rtc_engine/agora_texture_view_factory.h" +#include "iris_rtc_engine.h" +#include "iris_rtc_raw_data.h" +#include "iris_video_processor.h" + +namespace +{ + using namespace flutter; + using namespace agora::iris; + using namespace agora::iris::rtc; + + class EventHandler; + + class AgoraRtcEnginePlugin : public Plugin + { + public: + static void RegisterWithRegistrar(PluginRegistrarWindows *registrar); + + AgoraRtcEnginePlugin(PluginRegistrar *registrar); + + virtual ~AgoraRtcEnginePlugin(); + + EventSink *event_sink(); + + private: + IrisRtcEngine *engine(EncodableMap &arguments); + + // Called when a method is called on this plugin's channel from Dart. + void HandleMethodCall(const MethodCall &method_call, + std::unique_ptr> result); + + private: + std::unique_ptr> event_sink_; + std::unique_ptr engine_main_; + std::unique_ptr engine_sub_; + std::unique_ptr handler_main_; + std::unique_ptr handler_sub_; + std::unique_ptr callApiMethodCallHandlerMain_; + std::unique_ptr callApiMethodCallHandlerSub_; + std::unique_ptr factory_; + std::unique_ptr videoFrameBufferManagerMain_; + std::unique_ptr videoFrameBufferManagerSub_; + }; + + class EventHandler : public IrisEventHandler + { + public: + EventHandler(AgoraRtcEnginePlugin *plugin, bool sub_process = false) + : plugin_(plugin), sub_process_(sub_process) {} + + void OnEvent(const char *event, const char *data) override + { + if (plugin_->event_sink()) + { + EncodableMap ret = { + {EncodableValue("methodName"), EncodableValue(event)}, + {EncodableValue("data"), EncodableValue(data)}, + {EncodableValue("subProcess"), EncodableValue(sub_process_)}}; + plugin_->event_sink()->Success(ret); + } + } + + void OnEvent(const char *event, const char *data, const void *buffer, + unsigned int length) override + { + if (plugin_->event_sink()) + { + std::vector vector(length); + if (buffer && length) + { + memcpy(&vector[0], buffer, length); + } + EncodableMap ret = { + {EncodableValue("methodName"), EncodableValue(event)}, + {EncodableValue("data"), EncodableValue(data)}, + {EncodableValue("buffer"), EncodableValue(vector)}, + {EncodableValue("subProcess"), EncodableValue(sub_process_)}}; + plugin_->event_sink()->Success(ret); + } + } + + private: + AgoraRtcEnginePlugin *plugin_; + bool sub_process_; + }; + + bool isSubProcess(EncodableMap &arguments) + { + if (arguments.find(EncodableValue("subProcess")) == arguments.end()) { + return false; + } + auto subProcess = std::get(arguments[EncodableValue("subProcess")]); + return subProcess; + } + + void AgoraRtcEnginePlugin::RegisterWithRegistrar( + PluginRegistrarWindows *registrar) + { + auto method_channel = std::make_unique>( + registrar->messenger(), "agora_rtc_engine", + &StandardMethodCodec::GetInstance()); + auto event_channel = std::make_unique>( + registrar->messenger(), "agora_rtc_engine/events", + &StandardMethodCodec::GetInstance()); + + auto plugin = std::make_unique(registrar); + + method_channel->SetMethodCallHandler( + [plugin_pointer = plugin.get()](const auto &call, auto result) + { + plugin_pointer->HandleMethodCall(call, std::move(result)); + }); + + auto handler = std::make_unique>( + [plugin_pointer = + plugin.get()](const EncodableValue *arguments, + std::unique_ptr> &&events) + -> std::unique_ptr> + { + plugin_pointer->event_sink_ = std::move(events); + return nullptr; + }, + [plugin_pointer = plugin.get()](const EncodableValue *arguments) + -> std::unique_ptr> + { + plugin_pointer->event_sink_ = nullptr; + return nullptr; + }); + event_channel->SetStreamHandler(std::move(handler)); + + AgoraRtcChannelPluginRegisterWithRegistrar(registrar, + plugin->engine_main_.get()); + AgoraRtcDeviceManagerPluginRegisterWithRegistrar(registrar, + plugin->engine_main_.get()); + + registrar->AddPlugin(std::move(plugin)); + } + + AgoraRtcEnginePlugin::AgoraRtcEnginePlugin(PluginRegistrar *registrar) + : engine_main_(new IrisRtcEngine), + engine_sub_(new IrisRtcEngine(nullptr, kEngineTypeSubProcess)), + handler_main_(new EventHandler(this)), + handler_sub_(new EventHandler(this, true)), + factory_(new AgoraTextureViewFactory(registrar)), + videoFrameBufferManagerMain_(new IrisVideoFrameBufferManager()), + videoFrameBufferManagerSub_(new IrisVideoFrameBufferManager()) + { + + engine_main_->SetEventHandler(handler_main_.get()); + engine_sub_->SetEventHandler(handler_sub_.get()); + engine_main_->raw_data()->Attach(videoFrameBufferManagerMain_.get()); + engine_sub_->raw_data()->Attach(videoFrameBufferManagerSub_.get()); + callApiMethodCallHandlerMain_ = std::make_unique(engine_main_.get()); + callApiMethodCallHandlerSub_ = std::make_unique(engine_sub_.get()); + } + + AgoraRtcEnginePlugin::~AgoraRtcEnginePlugin() {} + + EventSink *AgoraRtcEnginePlugin::event_sink() + { + return event_sink_.get(); + } + + IrisRtcEngine *AgoraRtcEnginePlugin::engine(EncodableMap &arguments) + { + if (isSubProcess(arguments)) + { + return engine_sub_.get(); + } + else + { + return engine_main_.get(); + } + } + + void AgoraRtcEnginePlugin::HandleMethodCall( + const MethodCall &method_call, + std::unique_ptr> result) + { + auto method = method_call.method_name(); + if (!method_call.arguments()) + { + result->Error("Bad Arguments", "Null arguments received"); + return; + } + + if (method.compare("createTextureRender") == 0) + { + auto arguments = std::get(*method_call.arguments()); + auto texture_id = factory_->CreateTextureRenderer( + engine(arguments)->raw_data()->buffer_manager()); + result->Success(EncodableValue(texture_id)); + } + else if (method.compare("destroyTextureRender") == 0) + { + auto arguments = std::get(*method_call.arguments()); + auto texture_id = std::get(arguments[EncodableValue("id")]); + factory_->DestoryTextureRenderer(texture_id); + result->Success(); + } + else if (method.compare("getAssetAbsolutePath") == 0) + { + auto asset_path = std::get(*method_call.arguments()); + char exe_path[MAX_PATH]; + GetModuleFileNameA(NULL, exe_path, MAX_PATH); + + if (exe_path) + { + // The real asset path: /data/flutter_assets/ + auto realPath = std::filesystem::path(exe_path).parent_path() / std::filesystem::path("data") / std::filesystem::path("flutter_assets") / std::filesystem::path(asset_path); + result->Success(EncodableValue(realPath.u8string())); + } + } + else + { + auto arguments = std::get(*method_call.arguments()); + if (isSubProcess(arguments)) + { + callApiMethodCallHandlerSub_->HandleMethodCall(method_call, std::move(result)); + } + else + { + callApiMethodCallHandlerMain_->HandleMethodCall(method_call, std::move(result)); + } + } + } +} // namespace + +void AgoraRtcEnginePluginRegisterWithRegistrar( + FlutterDesktopPluginRegistrarRef registrar) +{ + AgoraRtcEnginePlugin::RegisterWithRegistrar( + PluginRegistrarManager::GetInstance() + ->GetRegistrar(registrar)); +} diff --git a/windows/agora_rtc_engine_plugin.cpp b/windows/agora_rtc_engine_plugin.cpp deleted file mode 100644 index 027748d38..000000000 --- a/windows/agora_rtc_engine_plugin.cpp +++ /dev/null @@ -1,89 +0,0 @@ -#include "agora_rtc_engine_plugin.h" - -// This must be included before many other Windows headers. -#include - -// For getPlatformVersion; remove unless needed for your plugin implementation. -#include - -#include -#include -#include - -#include -#include -#include - -namespace { - -class AgoraRtcEnginePlugin : public flutter::Plugin { - public: - static void RegisterWithRegistrar(flutter::PluginRegistrarWindows *registrar); - - AgoraRtcEnginePlugin(); - - virtual ~AgoraRtcEnginePlugin(); - - private: - // Called when a method is called on this plugin's channel from Dart. - void HandleMethodCall( - const flutter::MethodCall &method_call, - std::unique_ptr> result); -}; - -// static -void AgoraRtcEnginePlugin::RegisterWithRegistrar( - flutter::PluginRegistrarWindows *registrar) { - auto channel = - std::make_unique>( - registrar->messenger(), "agora_rtc_engine", - &flutter::StandardMethodCodec::GetInstance()); - - auto plugin = std::make_unique(); - - channel->SetMethodCallHandler( - [plugin_pointer = plugin.get()](const auto &call, auto result) { - plugin_pointer->HandleMethodCall(call, std::move(result)); - }); - - registrar->AddPlugin(std::move(plugin)); -} - -AgoraRtcEnginePlugin::AgoraRtcEnginePlugin() {} - -AgoraRtcEnginePlugin::~AgoraRtcEnginePlugin() {} - -void AgoraRtcEnginePlugin::HandleMethodCall( - const flutter::MethodCall &method_call, - std::unique_ptr> result) { - // Replace "getPlatformVersion" check with your plugin's method. - // See: - // https://github.com/flutter/engine/tree/master/shell/platform/common/cpp/client_wrapper/include/flutter - // and - // https://github.com/flutter/engine/tree/master/shell/platform/glfw/client_wrapper/include/flutter - // for the relevant Flutter APIs. - if (method_call.method_name().compare("getPlatformVersion") == 0) { - std::ostringstream version_stream; - version_stream << "Windows "; - if (IsWindows10OrGreater()) { - version_stream << "10+"; - } else if (IsWindows8OrGreater()) { - version_stream << "8"; - } else if (IsWindows7OrGreater()) { - version_stream << "7"; - } - flutter::EncodableValue response(version_stream.str()); - result->Success(&response); - } else { - result->NotImplemented(); - } -} - -} // namespace - -void AgoraRtcEnginePluginRegisterWithRegistrar( - FlutterDesktopPluginRegistrarRef registrar) { - AgoraRtcEnginePlugin::RegisterWithRegistrar( - flutter::PluginRegistrarManager::GetInstance() - ->GetRegistrar(registrar)); -} diff --git a/windows/agora_rtc_engine_plugin.h b/windows/agora_rtc_engine_plugin.h deleted file mode 100644 index a044247f9..000000000 --- a/windows/agora_rtc_engine_plugin.h +++ /dev/null @@ -1,23 +0,0 @@ -#ifndef FLUTTER_PLUGIN_AGORA_RTC_ENGINE_PLUGIN_H_ -#define FLUTTER_PLUGIN_AGORA_RTC_ENGINE_PLUGIN_H_ - -#include - -#ifdef FLUTTER_PLUGIN_IMPL -#define FLUTTER_PLUGIN_EXPORT __declspec(dllexport) -#else -#define FLUTTER_PLUGIN_EXPORT __declspec(dllimport) -#endif - -#if defined(__cplusplus) -extern "C" { -#endif - -FLUTTER_PLUGIN_EXPORT void AgoraRtcEnginePluginRegisterWithRegistrar( - FlutterDesktopPluginRegistrarRef registrar); - -#if defined(__cplusplus) -} // extern "C" -#endif - -#endif // FLUTTER_PLUGIN_AGORA_RTC_ENGINE_PLUGIN_H_ diff --git a/windows/agora_texture_view_factory.cc b/windows/agora_texture_view_factory.cc new file mode 100644 index 000000000..3aa16136d --- /dev/null +++ b/windows/agora_texture_view_factory.cc @@ -0,0 +1,177 @@ +#include "include/agora_rtc_engine/agora_texture_view_factory.h" + +#include + +#include "iris_rtc_raw_data.h" +#include "iris_rtc_raw_data.h" +#include "iris_video_processor.h" + +using namespace flutter; +using namespace agora::iris; +using namespace agora::iris::rtc; + +TextureRenderer::TextureRenderer(flutter::BinaryMessenger *messenger, + flutter::TextureRegistrar *registrar, + agora::iris::IrisVideoFrameBufferManager *renderer) + : registrar_(registrar), renderer_(renderer), + texture_(PixelBufferTexture(std::bind(&TextureRenderer::CopyPixelBuffer, + this, std::placeholders::_1, + std::placeholders::_2))), + uid_(0), pixel_buffer_(new FlutterDesktopPixelBuffer{nullptr, 0, 0}) +{ + texture_id_ = registrar_->RegisterTexture(&texture_); + auto channel = std::make_unique>( + messenger, + "agora_rtc_engine/texture_render_" + std::to_string(texture_id_), + &flutter::StandardMethodCodec::GetInstance()); + channel->SetMethodCallHandler([this](const auto &call, auto result) + { this->HandleMethodCall(call, std::move(result)); }); +} + +TextureRenderer::~TextureRenderer() +{ + renderer_->DisableVideoFrameBuffer(this); + registrar_->UnregisterTexture(texture_id_); + if (pixel_buffer_) + { + if (pixel_buffer_->buffer) + { + delete[] pixel_buffer_->buffer; + } + delete pixel_buffer_; + pixel_buffer_ = nullptr; + } +} + +int64_t TextureRenderer::texture_id() { return texture_id_; } + +void TextureRenderer::HandleMethodCall( + const flutter::MethodCall &method_call, + std::unique_ptr> result) +{ + auto method = method_call.method_name(); + if (!method_call.arguments()) + { + result->Error("Bad Arguments", "Null arguments received"); + return; + } + if (method.compare("setData") == 0) + { + auto arguments = std::get(*method_call.arguments()); + auto data = std::get( + arguments[flutter::EncodableValue("data")]); + unsigned int uid = 0; + auto uid_int32 = + std::get_if(&data[flutter::EncodableValue("uid")]); + if (!uid_int32) + { + auto uid_int64 = + std::get_if(&data[flutter::EncodableValue("uid")]); + uid = (unsigned int)*uid_int64; + } + else + { + uid = (unsigned int)*uid_int32; + } + auto channel_id = + std::get_if(&data[flutter::EncodableValue("channelId")]); + if (uid_ != uid) + { + renderer_->DisableVideoFrameBuffer(this); + } + uid_ = uid; + if (channel_id) + { + channel_id_ = channel_id->c_str(); + } + else + { + channel_id_ = ""; + } + + IrisVideoFrameBuffer buffer(kVideoFrameTypeRGBA, this); + IrisVideoFrameBufferConfig config; + + config.id = uid_; + if (config.id == 0) + { + config.type = IrisVideoSourceType::kVideoSourceTypeCameraPrimary; + } + else + { + config.type = IrisVideoSourceType::kVideoSourceTypeRemote; + } + if (!channel_id_.empty()) + { + strcpy_s(config.key, channel_id_.c_str()); + } + else + { + strcpy_s(config.key, ""); + } + renderer_->EnableVideoFrameBuffer(buffer, &config); + + result->Success(); + } + else if (method.compare("setRenderMode") == 0) + { + } + else if (method.compare("setMirrorMode") == 0) + { + } +} + +void TextureRenderer::OnVideoFrameReceived(const IrisVideoFrame &video_frame, + const IrisVideoFrameBufferConfig *config, + bool resize) +{ + std::lock_guard lock_guard(mutex_); + if (pixel_buffer_->width != video_frame.width || + pixel_buffer_->height != video_frame.height) + { + if (pixel_buffer_->buffer) + { + delete[] pixel_buffer_->buffer; + } + pixel_buffer_->buffer = new uint8_t[video_frame.y_buffer_length]; + } + memcpy((void *)pixel_buffer_->buffer, video_frame.y_buffer, + video_frame.y_buffer_length); + pixel_buffer_->width = video_frame.width; + pixel_buffer_->height = video_frame.height; + registrar_->MarkTextureFrameAvailable(texture_id_); +} + +const FlutterDesktopPixelBuffer * +TextureRenderer::CopyPixelBuffer(size_t width, size_t height) +{ + std::lock_guard lock_guard(mutex_); + return pixel_buffer_; +} + +AgoraTextureViewFactory::AgoraTextureViewFactory(PluginRegistrar *registrar) + : messenger_(registrar->messenger()), + registrar_(registrar->texture_registrar()) {} + +AgoraTextureViewFactory::~AgoraTextureViewFactory() {} + +int64_t +AgoraTextureViewFactory::CreateTextureRenderer(IrisVideoFrameBufferManager *renderer) +{ + std::unique_ptr texture( + new TextureRenderer(messenger_, registrar_, renderer)); + int64_t texture_id = texture->texture_id(); + renderers_[texture_id] = std::move(texture); + return texture_id; +} + +bool AgoraTextureViewFactory::DestoryTextureRenderer(int64_t texture_id) +{ + auto it = renderers_.find(texture_id); + if (it != renderers_.end()) + { + renderers_.erase(it); + return true; + } + return false; +} diff --git a/windows/call_api_method_call_handler.cc b/windows/call_api_method_call_handler.cc new file mode 100644 index 000000000..983d82c9c --- /dev/null +++ b/windows/call_api_method_call_handler.cc @@ -0,0 +1,114 @@ +#include "include/agora_rtc_engine/call_api_method_call_handler.h" + +#include +#include + +using namespace flutter; + +CallApiMethodCallHandler::CallApiMethodCallHandler( + agora::iris::rtc::IrisRtcEngine *engine) : irisRtcEngine_(engine) {} + +CallApiMethodCallHandler::~CallApiMethodCallHandler() {} + +void CallApiMethodCallHandler::HandleMethodCall(const flutter::MethodCall &method_call, + std::unique_ptr> result) +{ + auto method = method_call.method_name(); + if (!method_call.arguments()) + { + result->Error("Bad Arguments", "Null arguments received"); + return; + } +// #if DEBUG + +// #endif +#ifdef NDEBUG + // nondebug +#else + if (method.compare("getIrisRtcEngineIntPtr") == 0) + { + result->Success((intptr_t)irisRtcEngine_); + return; + } +#endif + if (method.compare("callApi") == 0 || method.compare("callApiWithBuffer") == 0) + { + try + { + auto arguments = std::get(*method_call.arguments()); + auto api_type = std::get(arguments[EncodableValue("apiType")]); + auto ¶ms = std::get(arguments[EncodableValue("params")]); + char res[kMaxResultLength] = ""; + int32_t ret; + if (arguments.find(EncodableValue("buffer")) == arguments.end()) + { + ret = CallApi(static_cast(api_type), + params.c_str(), res); + } + else + { + auto &buffer = + std::get>(arguments[EncodableValue("buffer")]); + ret = CallApi(static_cast(api_type), + params.c_str(), buffer.data(), res); + } + + std::printf("api type: %s, param: %s, ret: %s, res: %s", std::to_string(api_type).c_str(), params.c_str(), std::to_string(ret).c_str(), std::string(res).c_str()); + + if (ret == 0) + { + std::string res_str(res); + if (res_str.empty()) + { + result->Success(); + } + else + { + result->Success(EncodableValue(res_str)); + } + } + else if (ret > 0) + { + result->Success(EncodableValue(ret)); + } + else + { + auto des = CallApiError(ret); + result->Error(std::to_string(ret), des); + } + } + catch (std::exception &e) + { + result->Error("-1", e.what()); + } + } + else + { + result->NotImplemented(); + } +} + +int32_t CallApiMethodCallHandler::CallApi(int32_t api_type, const char *params, + char *result) +{ + return irisRtcEngine_->CallApi(static_cast(api_type), + params, result); +} + +int32_t CallApiMethodCallHandler::CallApi(int32_t api_type, const char *params, void *buffer, + char *result) +{ +// TODO(littlegnal): Remove this after we migrate not deprecated CallApi +#pragma warning(disable : 4996) + return irisRtcEngine_->CallApi(static_cast(api_type), + params, buffer, result); +} + +std::string CallApiMethodCallHandler::CallApiError(int32_t ret) +{ + char res[kMaxResultLength] = ""; + irisRtcEngine_->CallApi(ApiTypeEngine::kEngineGetErrorDescription, + ("{\"code\":" + std::to_string(ret) + "}").c_str(), + res); + return std::string(res); +} \ No newline at end of file diff --git a/windows/cmake/DownloadSDK.cmake b/windows/cmake/DownloadSDK.cmake new file mode 100644 index 000000000..04b13dead --- /dev/null +++ b/windows/cmake/DownloadSDK.cmake @@ -0,0 +1,32 @@ +function(DownloadSDK platform version download_dir) + # Specify the binary distribution type and download directory. + set(SDK_DISTRIBUTION "Agora_Native_SDK_for_${platform}_${version}_IRIS") + set(SDK_DOWNLOAD_DIR "${download_dir}") + + # The location where we expect the extracted binary distribution. + set(SDK_ROOT "${SDK_DOWNLOAD_DIR}/Agora_Native_SDK_for_${platform}_IRIS" CACHE INTERNAL "SDK_ROOT") + + # Download and/or extract the binary distribution if necessary. + if(NOT IS_DIRECTORY "${SDK_ROOT}") + set(SDK_DOWNLOAD_FILENAME "${SDK_DISTRIBUTION}.zip") + set(SDK_DOWNLOAD_PATH "${SDK_DOWNLOAD_DIR}/${SDK_DOWNLOAD_FILENAME}") + if(NOT EXISTS "${SDK_DOWNLOAD_PATH}") + set(SDK_DOWNLOAD_URL "https://download.agora.io/sdk/release/${SDK_DOWNLOAD_FILENAME}") + string(REPLACE "+" "%2B" SDK_DOWNLOAD_URL_ESCAPED ${SDK_DOWNLOAD_URL}) + + # Download the binary distribution and verify the hash. + message(STATUS "Downloading ${SDK_DOWNLOAD_PATH}...") + file( + DOWNLOAD "${SDK_DOWNLOAD_URL_ESCAPED}" "${SDK_DOWNLOAD_PATH}" + SHOW_PROGRESS + ) + endif() + + # Extract the binary distribution. + message(STATUS "Extracting ${SDK_DOWNLOAD_PATH}...") + execute_process( + COMMAND ${CMAKE_COMMAND} -E tar xzf "${SDK_DOWNLOAD_DIR}/${SDK_DOWNLOAD_FILENAME}" + WORKING_DIRECTORY ${SDK_DOWNLOAD_DIR} + ) + endif() +endfunction() diff --git a/windows/include/agora_rtc_engine/agora_rtc_channel_plugin.h b/windows/include/agora_rtc_engine/agora_rtc_channel_plugin.h new file mode 100644 index 000000000..bedbbc1af --- /dev/null +++ b/windows/include/agora_rtc_engine/agora_rtc_channel_plugin.h @@ -0,0 +1,12 @@ +#ifndef FLUTTER_PLUGIN_AGORA_RTC_CHANNEL_PLUGIN_H_ +#define FLUTTER_PLUGIN_AGORA_RTC_CHANNEL_PLUGIN_H_ + +#include + +#include "iris_rtc_engine.h" + +void AgoraRtcChannelPluginRegisterWithRegistrar( + flutter::PluginRegistrarWindows *registrar, + agora::iris::rtc::IrisRtcEngine *engine); + +#endif // FLUTTER_PLUGIN_AGORA_RTC_CHANNEL_PLUGIN_H_ diff --git a/windows/include/agora_rtc_engine/agora_rtc_device_manager_plugin.h b/windows/include/agora_rtc_engine/agora_rtc_device_manager_plugin.h new file mode 100644 index 000000000..c50f7d8b9 --- /dev/null +++ b/windows/include/agora_rtc_engine/agora_rtc_device_manager_plugin.h @@ -0,0 +1,12 @@ +#ifndef FLUTTER_PLUGIN_AGORA_RTC_DEVICE_MANAGER_PLUGIN_H_ +#define FLUTTER_PLUGIN_AGORA_RTC_DEVICE_MANAGER_PLUGIN_H_ + +#include + +#include "iris_rtc_engine.h" + +void AgoraRtcDeviceManagerPluginRegisterWithRegistrar( + flutter::PluginRegistrarWindows *registrar, + agora::iris::rtc::IrisRtcEngine *engine); + +#endif // FLUTTER_PLUGIN_AGORA_RTC_DEVICE_MANAGER_PLUGIN_H_ diff --git a/windows/include/agora_rtc_engine/agora_texture_view_factory.h b/windows/include/agora_rtc_engine/agora_texture_view_factory.h new file mode 100644 index 000000000..08451eb41 --- /dev/null +++ b/windows/include/agora_rtc_engine/agora_texture_view_factory.h @@ -0,0 +1,67 @@ +#ifndef AGORA_TEXTURE_VIEW_FACTORY_H +#define AGORA_TEXTURE_VIEW_FACTORY_H + +#include +#include +#include +#include +#include +#include + +#include "iris_rtc_raw_data.h" +#include "iris_video_processor.h" + +class AgoraTextureViewFactory; + +class TextureRenderer : public agora::iris::IrisVideoFrameBufferDelegate { +public: + TextureRenderer(flutter::BinaryMessenger *messenger, + flutter::TextureRegistrar *registrar, + agora::iris::IrisVideoFrameBufferManager* renderer); + ~TextureRenderer(); + + int64_t texture_id(); + + virtual void OnVideoFrameReceived(const IrisVideoFrame &video_frame, + const IrisVideoFrameBufferConfig *config, + bool resize) override; + +private: + void HandleMethodCall( + const flutter::MethodCall &method_call, + std::unique_ptr> result); + + const FlutterDesktopPixelBuffer *CopyPixelBuffer(size_t width, size_t height); + +public: + flutter::TextureRegistrar *registrar_; + agora::iris::IrisVideoFrameBufferManager* renderer_; + flutter::TextureVariant texture_; + int64_t texture_id_; + std::unique_ptr> channel_; + unsigned int uid_; + std::string channel_id_; + std::mutex mutex_; + FlutterDesktopPixelBuffer *pixel_buffer_; +}; + +class AgoraTextureViewFactory { +public: + AgoraTextureViewFactory(flutter::PluginRegistrar *registrar); + ~AgoraTextureViewFactory(); + + flutter::BinaryMessenger *messenger(); + + flutter::TextureRegistrar *registrar(); + + int64_t CreateTextureRenderer(agora::iris::IrisVideoFrameBufferManager *renderer); + + bool DestoryTextureRenderer(int64_t texture_id); + +private: + flutter::BinaryMessenger *messenger_; + flutter::TextureRegistrar *registrar_; + std::map> renderers_; +}; + +#endif // AGORA_TEXTURE_VIEW_FACTORY_H diff --git a/windows/include/agora_rtc_engine/call_api_method_call_handler.h b/windows/include/agora_rtc_engine/call_api_method_call_handler.h new file mode 100644 index 000000000..05871af9c --- /dev/null +++ b/windows/include/agora_rtc_engine/call_api_method_call_handler.h @@ -0,0 +1,25 @@ +#include "iris_rtc_engine.h" +#include +#include + +class CallApiMethodCallHandler +{ +public: + CallApiMethodCallHandler(agora::iris::rtc::IrisRtcEngine *engine); + + ~CallApiMethodCallHandler(); + + virtual void HandleMethodCall(const flutter::MethodCall &method_call, + std::unique_ptr> result); + + virtual int32_t CallApi(int32_t api_type, const char *params, + char *result); + + virtual int32_t CallApi(int32_t api_type, const char *params, void *buffer, + char *result); + + virtual std::string CallApiError(int32_t ret); + +protected: + agora::iris::rtc::IrisRtcEngine *irisRtcEngine_; +}; diff --git a/windows/plugin.vcxproj b/windows/plugin.vcxproj deleted file mode 100644 index 36b8c5795..000000000 --- a/windows/plugin.vcxproj +++ /dev/null @@ -1,247 +0,0 @@ - - - - - Debug - x64 - - - Profile - x64 - - - Release - x64 - - - - 15.0 - A9C98CB1-C3E4-4CF8-93CF-2A0A220FD3BA - Win32Proj - agora_rtc_engine - 10.0 - agora_rtc_engine - - - - DynamicLibrary - true - v141 - v142 - Unicode - - - DynamicLibrary - false - v141 - v142 - true - Unicode - - - DynamicLibrary - false - v141 - v142 - true - Unicode - - - - - - - - - - - - - - - - - - - - - - - - true - $(SolutionDir)..\build\windows\$(Platform)\$(Configuration)\Plugins\ - $(SolutionDir)..\build\windows\intermediates\$(Platform)\$(Configuration)\$(ProjectName)\ - - - $(ProjectName)_plugin - - - false - $(SolutionDir)..\build\windows\$(Platform)\$(Configuration)\Plugins\ - $(SolutionDir)..\build\windows\intermediates\$(Platform)\$(Configuration)\$(ProjectName)\ - - - $(ProjectName)_plugin - - - false - $(SolutionDir)..\build\windows\$(Platform)\$(Configuration)\Plugins\ - $(SolutionDir)..\build\windows\intermediates\$(Platform)\$(Configuration)\$(ProjectName)\ - - $(ProjectName)_plugin - - - - NotUsing - Level4 - Disabled - true - _DEBUG;FLUTTER_PLUGIN_IMPL;_WINDOWS;_USRDLL;_HAS_EXCEPTIONS=0;%(PreprocessorDefinitions) - true - false - true - 4100 - $(FLUTTER_EPHEMERAL_DIR);$(FLUTTER_EPHEMERAL_DIR)\cpp_client_wrapper\include;%(AdditionalIncludeDirectories) - - - Windows - true - flutter_windows.dll.lib;%(AdditionalDependencies) - $(FLUTTER_EPHEMERAL_DIR);%(AdditionalLibraryDirectories) - - - - - - - - - - - - - - - - - - - - - - - - - - - - - NotUsing - Level4 - MaxSpeed - true - true - true - NDEBUG;FLUTTER_PLUGIN_IMPL;_WINDOWS;_USRDLL;_HAS_EXCEPTIONS=0;%(PreprocessorDefinitions) - true - false - true - 4100 - $(FLUTTER_EPHEMERAL_DIR);$(FLUTTER_EPHEMERAL_DIR)\cpp_client_wrapper\include;%(AdditionalIncludeDirectories) - - - Windows - true - true - true - flutter_windows.dll.lib;%(AdditionalDependencies) - $(FLUTTER_EPHEMERAL_DIR);%(AdditionalLibraryDirectories) - - - - - - - - - - - - - - - - - - - - - - - - - - - - - NotUsing - Level4 - MaxSpeed - true - true - true - NDEBUG;FLUTTER_PLUGIN_IMPL;_WINDOWS;_USRDLL;_HAS_EXCEPTIONS=0;%(PreprocessorDefinitions) - true - false - true - 4100 - $(FLUTTER_EPHEMERAL_DIR);$(FLUTTER_EPHEMERAL_DIR)\cpp_client_wrapper\include;%(AdditionalIncludeDirectories) - - - Windows - true - true - true - flutter_windows.dll.lib;%(AdditionalDependencies) - $(FLUTTER_EPHEMERAL_DIR);%(AdditionalLibraryDirectories) - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/windows/plugin.vcxproj.filters b/windows/plugin.vcxproj.filters deleted file mode 100644 index 0f8c708a8..000000000 --- a/windows/plugin.vcxproj.filters +++ /dev/null @@ -1,45 +0,0 @@ - - - - - {4FC737F1-C7A5-4376-A066-2A32D752A2FF} - cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx - - - {93995380-89BD-4b04-88EB-625FBE52EBFB} - h;hh;hpp;hxx;hm;inl;inc;ipp;xsd - - - {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} - rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms - - - {dbe2dac9-4a21-4849-bef5-2069d695609d} - - - - - Header Files - - - Header Files - - - Source Files - - - - - Source Files\cpp_client_wrapper - - - Source Files\cpp_client_wrapper - - - Source Files\cpp_client_wrapper - - - Source Files - - -

        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�Fe}epJrtE>1I% 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®+>d!wU)h%X@MhSOd-3MD`Ud-dBIZ}A%LTay zZ-KLNH*UfixeITJlX4JG!Ew0*Z-rxW8~zE7$gTLNI4rl|sW>DzI4S4w&NwcQ z;$3h|9>Ltoq#Tjcm|LQj!*U8w!y$PXPsgsDz^&LX4`FUmQufJ%_!rob`|)nrmizE8 zu_gCnZe>!gzNY+R{#3DCkbCe9oRzyVw_GV_@h`Hr*IWBkLJ#kEK!+YU~ z+=}(?bwx@a0m9wjrdpCCpTbj{Ze*hFP?>M*@J(LExES6@o#W7ul!?f z5l}A36}%75%0(Q+899&l#Ys7b_rq~{6z`8?@(4ZvN8~g<5QpUyJ_v{8Vfyc{&5%=-az8#3+j1X13tMt8J{wnGR{n7W7vvs% z4$jKmxDRLKE<6_}8aSRva3jPbu%0)bgGjbkZgp+a({}spOQG79u z$s_m@9Ff!bQXH03_%a-lhw zco_TTMtl?Y$qo2s?8shx3$|qsz7<(`#S5DwG_RB-~KJ1eR@%`A5`|$(VmizF7 z*phqkL%909@{cpPAot*haaQieBRC^>;e|LU2k|2~E_dKZaZGN*kKu^iiWlLq+=3s+ zA-NepfnB)?k7B>vh@ZqhxdA_g9odVY#x(%<5#gOCvYD7AJMh17Om4&P;fUOd z-^XFO1($G0ZpLNo%1yX}{c|VLyaY$&H2xBY7mwlUv&uiVRyHokJ$NOYmAkPAXXGxtGET}tyb6xX9e4tc z$!&O59Fbcwx8g5{aaTj~pFD_vfgQOY?}lx;5C0NdaxdN;SD#e=F^`5R z7vvs1183!K%&m^g8MzDZfs=9&&%|-L1M??+<(S-t_rejm74MD1atjXNklc*hu`4&> z4(yj3@vpE?Zor+`k-c~pwq+0gHMZp1PmF(qtE0+4<`E|4f?UD-;H+H4L7b8Ecwd~9 zbC^e$m*es%-XF*05qtoS$Z32a4$CRbqejXhc^Ll|yK(||VZS_t55_)u5FdgaxgT>& zkFqWIVIFy0w&Y%XIIcdS{NoTV$UXRXI4gJKZk&<3@DVsE2l0_OE_dLga7=E)Jff!@ zkz4WaaaeA_{6SecBsb$fVpnd$J=iZd;$yH+ZotQ4NA}|5uq}J=pRgs@wlY2*S07jY zaTpim3O)g62XXHFS2`A+oo{i)3D4v63@(4Z|N8~g<1&8Gn=2n#DkUWe}!>*jb zz1S}g;nT5C9>iy0NAAaGVq5ORXJJe3#b@K{BIO@Pa6#_D=isc|jr(v$?!t3%QV!yI zI4*bK`8X!G;d60BZpG)}u-t;r$04~HN3kn6;ePCw8}R`4$qo3=*pa<>0k&liz5rWt zZHn=QxcZp#k7KwXSMXnORxaW}oRRbRBAk?S_^&uFkK&7QOdi3P;E0^Ym*TLT!k6KY zJd7{LuAIO_*e?&^E3i)<#DBw%+>fusw%muW!j{~Nug29!m46(^1-S=bgR^osPT-8( zg|Ed)If$>rak&Hk9mnK0{0|(FTk-WcEVtkra7b>(H)2al?w%msw#FpHPAHvmz%0JHFg4}~2 z##y-=kKl~lg%{$a9K?^{xZHss#WA@JKZYZ6D_(@datnSOhva7b1a{>nJc|8tBYqP5 zyU%?@H7{7{LIf3)oFAw3@uumSuuVY8<$8TU;?!#|lOYX&Q;p)T6 zKQ7>c+=Ji7S-Be*aYpXK@8F~y#P8y`+=2gvV{#jQ4@cxy{5}rLEx3e3ax*StS8l=; z?3WwyV(gO}@CVqDz4$|H%O3m@w&dCt#vkKqM)}88T#zgH6P%Tc_*0yb^Y}BIlymrV z9G6G&7dR%5;3YUBr}39KET`~SI3y3_udyp9a1HzAA^Z*Y$%FV??8yE2J8a8+_x8l`sSZ=`+ zaY$~)t7BJg!d~o`8}S<0CpX|Vu_Jr&TG*C7cx`OSHOF`ou0A-%zyD(!7vu_F2WRCX zZonBikJrUXIfvK7ad{N4k7M!(-T+7BG~N)0E!zuH1y1v0rY)+hCvEfVaht?8Vz*TlV1Xu_f0wH{JnP?^ph@ z4;SPL-VtZzB5uJMIgfY3NjZmi#&LNR?}B6U2>uz4$Z7m@9F|jf8VPcqWd^ z9e7V1liToKI3l;=y>VD>!2ukSn{hjKyDF^Y9I4*bKqi{@a!$;$Y+=_pX!*UDe1~TQ4+>HN-UAYPOV87gmkHJ2<0UwJU z*^7_Ew(P-w!j@dy)cAN@y+`@SVO)?a_ynAli}*yGk@NT@oRo8THjc}qcn*%qBlu(- zk<<7T9F|k~R2-6r@oCtV6Sx=q;34dnhwv5HClBJkVMp%AS7KZ4!&hNT?!{N* z>Yd6zj^l#dgRj9^xf>^NM()Db;-nnJ*WtL_f&Y$UavS~!j>xU}dK{Kp@C`U5H{%va`?3WwyP1q+l;G3}{d+{yUmOc1ZY{|8ajc>!%JCuK%#09y6|B1755vOoQ&g0v0 zQqJK!a9ke6cjA~lg73l+IgRheVL65G!6A7V--}&2fz#M858?Z;PaeegV@K}C4`5sF z!w+Ih?!^z`>g~!u&ftRFgCE9Oxf_q*jNFA6;-nnJkKnl6fgi;&xeY&tBXTQVgu`+R zejJD7X8Z(pm@N3v758~Ic zBlqJsur2rDH?bx6;XLu|_){1LX~+D677<7!g*$5mXA zEBF(fm5caOoRRbRGn|xj_;VbWNAVXpCXe7HI3lO#vYuJyYR|5DF^W?I4*bK z2{jtYm<#9 z;p(l*Kell}uHbcWRxaWOoRRZ*U7VD2cs(4KNAdbNCXe6^a70ey4RKgb;mJ58595un zD<^Ox_RB+fW9*X$@g~@j`|+mOmizE#*phqk=D2!`@{b){kbCeJI4gH!9>HDC$X$3# zoRouj3XaPicq<%}+wf0tL~g}D#bLPxb4%lLNN&bkV^?m%&DbwD;%%@`Zou1ONA}|F zuq}J=_SlkZ8yfF`t2ZnEm`CZ93vvbTh_iALx8RJN$2;MqoWtBAw;Y#8F}J)f$K(eIHcf+>ahkuDJxfkz_t2ZhC z*pCZx51xUuayM?n8MzDZfs=9&&%|-L1Mi7ravRj-WNAAamVq5ORhhaT&%ln{ zkI%%m+=tJ?mfVZa#?|YUe;mODxd)$vvvN1?!x^~?&&5eOi09$B+=1ugnB0cX#Sys` zpNGS83qBu*ZQ9kK?!?_uy-AR_?|LoRPcmwKypU@pU*Zci_L{ znB0c{fg^G&z8;6=7JLH^$<6pi?8;4e82jZ$d=vJ`4ftm4$XhzmvBgK#%1ivO}K*nawA@heR2c-06Vf5 ze~4|_gFnKSTwBNZV_c0Z|G0_^as_{avvLuCiZgN^e}|K zcqN>byRipnN3XaPicmj^eZFp52kz4Ur?!sH*q#VRka9r-dTj7}8hJS)1ax4BR4$CcgDh|ob zcx&v+O}H8R>_Q?%+TkObQydAb>58fVIa&40F4!HU^aK9+g=3%R_iq?2`xaFR&x` z{c*PaKom@Lo6~ zx8l8VSZ=`q9Fm)HJ9gzJ+=2aaBmNck$ql#@JF*wg!nW+ezs8naTif_IxH_c#V;2|X z3f>22!QT#zgH1e}$N_(YtM^Y|p3lyi7Cj?1HX4vxtq_+%WB)A$q|mQ(mt9Fm9e zY1ow$xEK57A$&Ua$%FU|?8yE2Ol-@2_$+M6z4&Zgy;S+f5nPaa@HsducjG>sk-P9* zoRouj9*)Z$cs`EFZTMUqkz4V3I4rl|^KnRS#!>9bO}HQX`NuI_kSq8vI4c+NAkN5nd=XB{Is8`~mq+o%I3|zaOK?O^<4bW^ zPT|XNNFK(QV^>b#A?%lj@D;~TLnH{oIImmBd-*e5sO zo3SH%@h#YvJ@{5^$+b0%Z^PBUD*rf%3vvbj6KCZjPT`E4$G798oWpnExIBvQ#4&jU z--RP`8sCk>athyrL-H`b7rSx-r?Foi!uMgHJc#edj@*wQz_#3nAHp)>m^^}C!Vx)*U&diMg#IIvV?#FLnTkgYeVoUDD zZ{g}+lz&{n1-S>mjk9t$F5-;bh2OzRIf&oIak&Hk3&-R({2q?Tt@wQ$mRoQMhva5l z#;)9iE7&hL;>Fk}H{cJjBYW|O*p@x`BW%gF)r~*K)tK^+tGFOn@FzGc7xAY!Bj@pF zI4S4w=Qu8p;xDjyx}Led8o^6&L{8%`aac~_uW(2n#$RJsPT(5$%R~4Z?2`xax7d;U z@pssk`|$VJl6&zOu3o78V{0|zg4}~w!dbZ+dvHeX!YkvX9K@^OxZHs!;F#QoSH%&z z6|aWFatoe_Lvk}-9lLT9_F})>h}XbAxdE?<9odW5!nW+eYhz2UO*Ec_s~0H$*v199 zg4e-WxriHZM$Y4PaZ=9V^>ADs#p~mkJc2jC5jl-F#9=vwC*zPjj5orroWPCPFAw33 zu}>bvn_x%o$D3kX?!%j5OYX&+R2D~kHWG~(h+p-65k1e^jn(+>} z`e)@I`*1<7;2m*RF5(uPk@I*boRo8TXB?MD@h&(fkKmu-h@8eh$6+~zr{R!1jHhE) zPT*GTmxu7K*e4I-UtmY>$Gc%$?!&*tmfVYX$JGJlANz4Z?!hx~R_?}aI3suAJ#bPE z;+Z%uci=s7Om4$_;fUOd_r_tl1qX0QZpQ7{m78z}_REdv;7;twUOWrivIqYf zTXJnxX2{< z;B#2Va0KxweY&g}8dI@{ePjmcj@*y0#J1drufmqxi?7Dj z`N}_z;~TLn zH{oIImmBd-*e5sOo3SH%@h#YvJ@{5^$+eY@Z^PAj%0Euxf?UD>#96tBQ#d2%@$EP% z=kOgkE|20naZDb;cj1Vf#&_eeoWl3ukUWg<#jc#dY3!GW@O{`P590f=BlqJ6ur2rD z2eBph;)if`uJVsFxFGl7hjCW!#v?c*cj1LNDF^W*I4*bKM{!JU!;j&J+=>_Bu-t+l z$04~HKY?Aj36EmG+=!pVKDhxug&o<8pT@TA!Ovhzu6c}~#nnFLA7^nvuHffzRxaWk z&d7QEJWk3v`~r^4qxeM}lSlANI3lO<%Q!5j@GCeZ593#{D<^Os`{g108urP9_;u{a z{rC-R%YFDwY{|X&EnGcE`NsuZkbCgkI4gJKBF@NN_#K>-gZNz>mpkyka7=E)@8O8t zir>d!xdoSSNN&bu?8;5Jg8gzMUW|Qm1O5OzvKN1dZP|lA!j@cH$@pVjjVS-PiVJcD ze}c1e5r2v^avpz%lX4D!j^pwu{sPD35xfLPGfJcPf& zK6wy-iygTie}`?k4}Xs>xfhS&>eh_wq*}q8(VVCGMwe9m^^|vz!5o(H^gB%g(u^XJd8KO zuAIP)*e?&^jj>N2#G7D8?#G*ATkgY~VN34Co8#)4?Ei__!3DVoZ-KLNH*UfixeITJ zlX4JG!Ew0*Z-rxW8~zE7$gTLNI4rl|sW>DzA1=rhyd%!aMcjfjavtx5lX4F4jN|es-UY|x5&Sb8k<<9+ zI4q~|G#rwL@pSCU3EYbP@(|t?`{Y6V3+%}KcsFdzefXEyl6&#)xO%$skNvnH_uv^g zD|h2IoRPcm9ylon@k|_-JMf-3Cb!|ea71p!d*iU&f&(}tH{*8f%1yWf`{hRbE9{dS za3^+TFP?>M*@J(LExGo+@o#XoSNX>-F31(U56;R(9K;zpkN3q%IfwVdad{N)k7M!( zJ^)ALG(HfA$hvZ@WTkOgS+=cz}5Iz|DFRmUVJ#No~Hcc z5H83)_;)xfcjIoHk-P8_I4KA5kvJ}Q;G=L%Zo^08h}?>QkHc~c{sRul&G?Vlm78!6 z_REd<80?c9@UhsDz4$n6%O3nEY{|9njE~3FQS+%pFD`qz>eIH&&0OehtI;6 z+>6h~)l-yz9Ki*-2cLtpayRb78MzD3#Ys7c=i#{Af#>6x+=kD^5xEtghr@CUJ|BnV zW*o(?+=TnFUv9($*e5sOKVwJs;sw~2J@^7_$+d5dFT~Z8m46(=1-XL%g0pfF58{lR z#~0zGoWp;`ad{M9jAQZ$z63|)G`=IdRWk2w#DH@*w^jcI1A1 zCAQ^0d=<9jUVJsK&Qbnx92evsd=1XZ-8g|Wau>c9C*>f%4#(vV{C6Ca+webdL~g~` zgLLR{n7k7vu{5 zC(g=6oWdD7k8j6GIfw7Sad{NqiDU8zz6(d>G`<^$=FLvbwPGi43gzv*X zc@W=^9l0MrfNi-CKZq^47e9onCn^6pg9~yGei&!vZajiBau;5RlX4J0g5z=reiX;# zHvAZl$gOx04$Ce0aU7DH@e|mUoA4<1%Z>O+?2{YtQ`nKc_-Sm*9{dcphcj{>KaZ1g4!?lo@+f{0$K(OYX&ExO%+ukFC{>3vv%$31{VQ?7uZ=Ca_LcD@T>X>sk8NC#D|j88m5aCmXXHFy7boQ$UJu9RQM^8m$s>3J9Ffy_ zLmZY&EKCpaRv;-BKM+=8d#klc*7#;)9io3USR#M@w> z+<>>mj_k$TVO#d#?Xe}-zBJweSC3Wxu@4vI3f>WCu{Ja~zgacp47L!+1J&jol>^Z1V-iN|WZ_WLegd35(6utij#FV|6SPuBqc$ z;fy+76ArB7eSynuQ^04!T6K&GC3B%tP2^uLs_!2hJk!wgOxZnWCPn2WAm?T!D@1fk*3s zO$gkkK*^l2norzY4=gr1sC==BOxk>=WtsjEQj?AMhh6Ka_lFJYsP~6Yv~%<8{o$!P z>iyyRI_mwQua0_uIJAy>f0$NBy+5p5N4-CMq^i%a_lGCysP~8K>ZtdJv+G#aAMP<_ zl%D(}%{5QOE$t8I5lAVpZ#^*H9}XaJxdMC*U|MCoKWs%HqQEEG%DnOZ@VQax_X=d{ zf${#Zkif4MxUe1=?+;u*mv&L$uzFy;Km3lsCJJm<4~+K*AAyw>__m&_@%}JoRI2=e z9elDL81E0y5O_|3p?YAvKU_)R9tHkb4~+MRV+mZXz_fZ`yg%$}bWnM|iKsu!IACA* zKEHXIPv?SN!lqtrOJ?p=T4~M(lQy4c2DN1c<}NJFo?Kr#`_qnrGj{r_6fhrV`J7T< z?jsWqo^ja1qqkqW{twDC-Rb{Q-dDf>@8y~P8Z%$OuQYp2Gwv@n?@FU)?IjbAVBs83 zeV#Dy4=Sh3@}pyB{rIx=uV?)st$)%A>z}Ii`^<8)e+zcI_x(++^3Fz+HuqaA?26i_ zeBkjLTFZAY7MMRa+cWn5!lnBgh<b3 znsJ~hkcB(7N55>3eqS&4lJQ~(Cd@u>Gn2E79f+>n89jYs`@pK5(JuqhH^*Fiv1iBE z0#UX! zF}LJp`7Y*%+PhwUr)eU}pZ4$NzjoArDL-cdr8mrvrR9IPpDBNN`}udwEIfJz2YzH% z{$Ka+;2&<^oClBZUy$t|y2AF4WBWfW&;RfHv&Mfb&qH}@tx(>kl=olqe`LK|nf%ZH z|C@idKV!drUD|bed-Mg?7|E0eqOrUg&`LVRWJP=%#uciIZ{r7ww z{NKt8Qr@8}ly@BE?LXdNv{zeu^qCpam)oPC2bRtUZ*(tB+`_p(XtKcEN6i@i*o@qn z(Hir_mZs!oBUp`gs2Rl8()L<2Fn5vpz)PhysGk|bt22PhSDNw}!pqw0f2q%`W%b$h z-|92@2lct#toh&SGk1|$_oY&t!j@H~K~fZ- zm&OXQfb2K(9SZ`{(V5YQ#|q0ouXyy!F=x`|5gkui-#9eUba`_=wlp5HSMY#;@`~k; zg`8#MV|;s4O&Qvp*%tpTZ@=;K|HthO`0XE-Klumc|1aB%t++kY|Gp``PaD(Swhz%* zE5_^nZGSUm1m=G5hd}g7WQyO6iaF~q-ocDtQ<2hFhtYhC1M@$ey-8qTo4~;7rY3u6 zFQ~xl)6b?D7WP)imgwhR$f!%&mVoc*Y?!4rO*d)SRlBYAoKY zJ^I+c@5UPA#jmXBu~hEEIg=OfG~OShAD0eN{oY_GZyFdl)b!aiO$GN{R>9ZCOL+c2 zRd8eTVRH&nI(*iKmf7DQ_6IZ1wnv{fhmk<^3v(D*z9aOEhcad_OZOc*Hb%`%lRAOu zN2U7?9~;|qV9FF0OzboZhRuS&z#0J_2}7UioHEU{pc!Omm|a=4hZ*pUvOP@RXHE$O z2KF_H-EWFJaFS#C!9jufx!ElN(}e=&gw_rWn1Q_DKr?B*JbO}L`d25ewPP;ur5V`S z#VZH4$OfW2KTLOBXJtNNvfOEEV6r^T?BC32vE(x~nHBvx8Rn=pXWhly#mMhuvkU*% z{7xgk(^O~W_w_@}+3w6K6IbG-%=Ez0ll2A8_yS)kZ5AwVxTQVds~`7(lT04kql*Fq z$5Ocu=WMWeN6shBoL)NBln{viAM^Wz3eK@rw>j&Z7iXn8+bo_|+GbgW7uPG?xU|A^ z)?B=isex8C%}Zx4eRr_wm!{_}qKi}w%y~j-=U>rP>enC3`-|HieOcY)`-d#^4M8bk z);6co?a@b+6O*}t2^XBP{2;pE7^jm1=trd+O#9D@Za*t}^hA^8sWVIsrmi%{d-M#` z)Mg%9yluM~pwk|+toEg2tG>$Yb=yrPrtmI)j(#SE00X3948^7GD~G}RmmC#_?$F)(jRTq~JrsMAdRlLHIP9It8l zJsspro#yyHwe_O9~jtW zIxh>>?|pewt2E(2MK)utC(K&qt<1+tV+Wa~T*~e?fk1|jn;qP5um3c^aenlFYQK9= z`BD2N&4Lx$Z*{Yo|4;3=wkdjfK6R}55A8SE)TeZ<+4mLNZ%vk6O?wRNHqpE{?f3P` zYQNT(O#3~$zanp%MWv`&tKNPO(W+{{M+rpKoNtxZ+jDvQExo*&`@ytX(MQ^&&zkve zc@0f3@tHxqErZx$e09-F%pi8g2l1v)YY^;WUd$jqRxg}-n(?^pvO#>Al50*W%&ggM z2JyBGV#f^P&gj>(qJ=TnHQU)_={RPxn0%z!&aCxJF8tT2t^4-e2d-o!M?@^S2& zW3Cn-nZ`kiuYyVknU#Kcyw%yduQU4Op3z0^(WlJi>JQrVhZEy*<88WhVtnFBRp@Q= zV%l`FD)es?<4m(na~`QSJ!-{?u`~Mip3$$`nI5N_X8qyxcnX`+^!N@N`O%DaXMMwe zsBidcz5EZ;<7vwZyW~FWjd#SGkfpOfvvteX)~*R?j!c%)sBv}Pk(E6 zv-#GpGkR^|dz$RN5-;a0jPNqSqMuCvYW6Fo+k@sz>bdrT2Q#Lm#pcUDbIS7|rIs!? zk@f{=g-an*pY{cN`P&E13h|+}mY)VpU0grBJF^DPa;VcGvj&cyI&1p3bJjH_E#7n4 z_2I1P@0+h4%^B`jriN862|f%g%9vV=RRfbA-oxZGGsj#H@bw{ICYsr`ty47Oz{nQ^n6Ty@}KQ>2J*L3JmOOE}duW zx~F}%IdL^Z`y;+GE$G^0QRyhN{*1ZbdgdIn?7L0VE_|)ItErng&~!$>FZs<|oe$5x zx_;`rx%t%Mi)IY$^@|w;v+TKFuR43J=?|Z=di_gTbNF9gQ8Se~bM`O|Fm=UK#|66t zo}d?+I+vc`*R+97FwB|qO9u5Vjb9bq>6*h$)+{Xz&<{2+vt~W6^X$o`i%r~I!$cRB z?&IBNKaS5?7Qe#0BW<_sUO$mMxI&XJJAYGu9zWc#P=7O0%~{RiPN!+;PSemwv`4>f zkG^NVZynfG=b0wC3+?vlZ_N2<@!mR-UsPJhY-z^aG0&X+R%lamvGrK#eX|edWZ8US zSo*-cU9!rQ@v9xX^we+6K7MI_EWY&ztv7kjZl?8|Wv#c+oGz{LxM@6d&V89FBM^O$ z)9)*PRNR>qN4&HzxmurgVQXqOyL1>EQnStD-KIYZ@4hU2lzB(1o%YLmt8G=L`7zpgS!wbidIxC z7)h~;unV*bBy1uX)>Ue4ZEMfb)2pYpRZlG!FSwhK3m}j{g#Z--3e2)XLeN|YWWWFO z&g?ZI!Jcz^zVCeH_ai&=&dl@PpZ9tH&*j}-gao2-57nUv=N!ptlN_O$B;`A(!ouLhRFo5 z?1^s}5<~oh;YD|%tx?g3e4Vx)=d&P62chPOU4Bf$)}s?QA6kEG_za=-sWdi4YXz@7 zP4r&APULo2CqJ>;{)FgWm*!lPqd^-2C(4ocvw@9`9vcdc?B0L9@@#X=vnsj=gU7BQ zZyB%CX7V}+=)4ZgK0oljh5SHUK0h$eWR)IYEx7)Ln#bz;qteEH`z==YvoN zFLI5d>wca8=5XJ!@kNPN?uaPS&u3QS6~3eqax{jIp!W;ziGyseN76*&#T7c0>)`i( z9ZS?75RFHz{EVYEaPbdpt~p7fJ7u8g?8sO?LUe1#2u3gOdihiW1#w*20*<4LI9$ZhMLaIz=|YPOEnOtwB7rXY;Gz#*B;q0w*(C|aD#yFN zFR?7zq*@^4d5n%_k4ojtm4d4v)OqvUU0T8T#;f3*h=?1micHFTJ;A}-GQL7 z%n;ypmMI$a_7ojI(2}!>A85^agVHi64Vw*1&O4Omp)?bv{A5plA0Cp!qoACvs@>7PbL^zLh}POCN%N7lnEe_O(e4Md4_0g zcAT;qEBKNW)K7G$W?4Be^?|<1XGcmDD>ONHutFik3IYGEw9h} zpB@E(G7FQb8pBTHszqa~m7k7b8<2Bm6F-@wvz6}TOUAHW+7UFY=xop6*MH3hNNPX9 zSi54-YI@-JPVMitXU}%0Vm+v`a#fccHmNFHTInmheXcDEFNsxQeMD(K7co8xe_#TPfzBm!88AbUOxxNAq!g8S~)aJ5o zt3c1uQfQzCa!op0h-Jhz*iS!LEGFX}!bfpw!X@EoU)>qrA1VBn=(rL*^ogPyCbXvr z^i+Lv@t3p}hb}LA_f(QeJPi=b!l0yxas=|TeHU1A!YU9{cJhSCA%~|z3AeF?DUTyT zuDKiQ>jC_sJy4F-HDx|hMQ0)>xcbk-r683HV+IPvmrT=n4gUhmQ{qVM$&u65&rEb{ z0_&D6Cj0d7?Xv+-9mZ`*L@t-rd^x+&jv_9tt;Pp@%-P@aN zu9dovv#E&jQ;sY_3EY#0GJ4iblPJ~OqzeX*Y^ID{Q+|o(avrWDCYjPOj&(xu4r(~1 z8}V)dz5DOzSlam#D?-|OqVJmY5X)w;wHmwKLo?Zv9D4gTyzTQUua2jL@2a0~XK4wy z(|6U#gc^8Ce|lpHeeyaU%l|5X5ZfSMegY3($3&%paB-3%g}mONF0bJc9^Q{YZ+n>` zr-_0JUV@v;pAbc7Thj_iaMidNx?<1_w|1JjOq&UTpQ8opR{tHeypZ7R{Je?s8;bgf z=vyT0=0qty(?)t8AhU`PXO%9=sVLfvDs3(XU`WVkz-T`_h#3F*u%_6uJxwEDyi5{Q zguVdN0-AzOE5Cgz#CdEq&e=0A3jEeRg0r1lIn*Xy#_G3fh*fGM&>s7MzxtE?4`D41 z*hXE(;y2rs-az{mL2x?)q%bOCZ91ySYHV=aZpnF8$CpTK)DEZDMnPwgWW_G&6r+Dg zFv`n6Wt5=~z$f-SA7_AoJUowef#}M^R4ALF3uAkA|!piH=tZfo)CekI91@FM?U9e-Q- zDsY%HzV#@L;Jgygzw8m*Hs~<+@IUq@c`x#hcnkQu`g;0a=oSFC4v##x*1KxRhDC9h_0ugAjt#qN(e1zZe6&! z4*|y?RV}&(%ywzpu?-}X5-bM&{CU`OGO0t528q%my4ez*V~2=W#wi*XR$BWYYT|*x zCiW*9_WM(XQ8j|MAzq9J91b2jGmZNX4!hytAX3#^#Q$Q1WMw-`Xtn&a846qcY(mg} z0>kJ7$W&;qPR>3|AVH?Iidb{2{EJzvJ4xujh`lgIKnK6!w|G|(g;-Yt>FKd2(LImM zgvvJ9=$>E2H2OAbar{H0d#TYqN~3#4XCQug);weg#Eu1XToS8Slrv4IsY_O=Xdqoahl}Tl|V~hMlzEf7a*1 zNAy00WkBiJH#ZWE>RCyY;)Sf}mx43|>z3e3 zEvHA)K>F6D^$Jps-$^=0ltGlreRjys>Pq9D;@=7$xv%xA{2dEjT}D|JzpAN>rz_X~hDoYb{pE&Y>#?g5BRy1~It;%)Z5u>Cd*g3-IU*Fo84jI1^2e z8Myz1vr0EHMHJQ_(xyXHY?jAa0)gpO+S{YpJWaw(JRm$LjMspllTb3~F|2PYB<5ZP zoKCsJI-@&EXwJby0vK3d6TI75%rWj5}u(ZwfJIWOBvEw@b zcxv@SQ)zwu8!byCMOS(zsU_1$BdN>@Ot-`8ZXE#N$E?ED8|a7rDYNkvBH?vxDm)z#HHJYk&vjwc!QyO=T<|@Np5+Md@`SAWsHib4wnKF?l9y z0S3y=l%E+l6uq!6TTW+>A#=&NO_TfMmc5XV7ox`l@H_1HzYa@T5GYL8BTu!uS3-=# zHkrpFi#~&#VFPmPPr^pU3UnV`^R`l=%Yus)3Q(V;pZ{i}PuO11_y$>i=&;2#66Fk0 z`U4YsS(WTso67<6Pa@rTo-fIPiGfvW5S(%my$o{_EoQl=lWwx|4CgSMfAL6gIHQn$@-x!|$1)DItGPQBa{F+&od(-qP3(TNd7FHMDCP|g$^%NGUyp2=MMS;^oelUKG90iXI+I9|82>=SwysJAQjV zXZsZU&B9hH0PRvl$>VGv=g^~}rV_2q{oMD|Ixi)!`hmc2 zufyiOR&YOyyc+GR_|11p7o6T&XFC+l7!0d$DnSwDh&T6QtN$|o-^0Ez*4ssX^NKk3 zI&oQivhpw^@*d1j^bZ|43>9X@Se!OI%@&`Ia)lLS{Dz^oek7mW4|WQUZbQmutN zZa?V1E<7e6Z%|sfncu#{={fFfdywBihlvU9{wE;o3yZYH0#_4g_&5z&$WP@^t1Ln9 zFT+gl-})diD=&B|R!8Dzu9plY6|MG3*etV<&#XggSj?{TCGE(aKWAKH|s z!LE+F051^X3xd~|Q6LGa7Rn>EMu9x`08!+fwD+JlbofQjLwNIoYq58HZzD-5^ZR#3 zmHF;o%KT3Mm@@aJGQW#dh1}9;a@tkV*rW)mW(yjg-6a zo-%lS<3lCz-4RuxjSuwP3CB}nDrBS*G$2)}(9fgE&FF>PrdV=k?*h3WhREF=P44pi zo=azrCHESUn;s%}c~Vqm|I!P&=6*4iwGz3DNL4EP$7pg-^+N7fvE;6R9r%77BKJr% zxm$W6H!qglpNQOjA#!{)xrY0DZo7n7a*qCA(uI+-YAI{83p@qf#XYNB1C zEV^IJ>ByKUau+axeROb)Lhf795~y^wn-mfT-3=Y0!8KVN4dy#0f1zm_PYP+rHniDnHao8(D7C~E^&H;zy+X8E&F4fHb!d-8T`oiw z^Oqpyw<>h{MAJEB?WqM<+E ze4w0eSAWN-zl3^H`f&AkkowzC{f$?DJJ5CX9tEPHU%&eMx%zul{XL-m?pA**)ZY)( z-#@FrZ>hh(Qh#4le}AO@y3}8%^6OuVO#R=dKX&@_H2wK5{dt`JETlgV(VzSAhu{(> z!YhCk;Px!};>|Rz8)ZNHJuZ(QLV#6;|7Q9#ivFatFJmxi>xzG6fm~Po3#l{&uL=LUDXKz8X7*g6uJ{*~AOio2CikOW$aTfP zZUMOn{41KAwHI<-@h>75fq&f?RoR4I$aTfPh+G8z6-{n?Ue9gU75@TviNwF6$*t;z zTvz;y$VK2^(d4pwA=efEB61P<*Qltr^I3YXY*+k?$VK2^(d2&F3%RcN7nnyR{uNE` zp2sKs$o%d1izg^6$dGP?kviE1LRu zBdA{+{zc>>@UM}qA-dvUW-2u`$2Y>iK&==2Yuog2b97VSYsJ4oj$(#c_xk@(lNVELo*ueIL@ z|Duc|@UIb3O%%t*$5mm>^75 zfq$h(Rd!r2xzG2#zx{_(d7E|LarPfqT+=3VhGA{T*wfn0RWf66GTHDAhR z=QZPBcsmmRiZ1G`9*Y`_e}Pm8|B9xQ*dv{P0RBZq`}^=O%=j4mi+I344F5uA|494` zQ(nct*dY5S{#D`ohv8p?Xj%jRV!yz@;{QwVued1u3wJU2SJ)p0cHTp+t|yX2{a@in z8qbUm$x*}WgLV9uKpDvsbz4CB2Q%D9bb|f>IlFl;#S7%DL;nyps(ICD!P^n1TIIuL zmoH%`s&V&97|TtW;DX`ykX=;S-GV#!Gr)%$`QUYd06fbYtZr>RtiM$|`q@%S!yLD@ zA<5>NDw3tP)NIpV;!B$GiRdhEvq*=$jq&g_V?LOZh1TN+PqcZx3EwidZxMt$@nd;lq+i>56dt$%%dU_M?W!%f^ zy^Q+?+&8HA4Y;qzeZ6{LkNaBO*Q)omxUa!|je1{$dk^kC?A}@BK^`91NqXRZ$d^8i z7G-sRB#9y#bcoUrn=}XBE;DuH%$!Bu%_f*%1&yf5t?sRXu!#@3J23xd6ruf{&5RgC9(LjNx^j~q&#a{XW7H20l z6P{dQl?XN~`4JA%Fpy3nFKKuwkc%`%>viOlYn-3v7+^!-4fq_l@TD^JvJ@mmXM-*v z!v?dyY_c!Urfw0PFv!%{leb|GXbc{IDx9gd(={3?0HZz_ItrYKkSH*pv}R^kY2zOH z_(_;Y2rg}A{OVM)bgxP!i(c}lb}xf@Gi-QQz?hpt)2alJN&$LAlokXy_yuV*T}yP% zO3ry@(W=!Ze)DIA{yoUkd#<0`GEU>x7G+hKiYl|OnX0L5ELXJq+TVv0v;W(Id&JbT zG|hHcHK2Kp%L7mkxM`u9CUVliZx;Q@#vm9I8WL7Ag+vvZaU{iuGqIL~Uk)4{$?CZt zEH0+p)TXR8tkML+ei3#|?cx)EJHO8BBW$Sk+~a^f3fE z#Z?;udObEs{tO!5q#^E78bbR&-4FvxBO2luV_)4g#Fg>a+z`J9jc?u%aJc-R9T0s= zBHG~~f0Y68^=;SO4!;DAUfO};Qen17u#DS83SSrE^CdUI^uY!_O_q)86kYdq7f<3o zC7#56IvaP~hE-UNCvnlL?@;1NkXOgW74TBa!wS$y3>@#ekQx(4O$b9U^$pxxrolN3so9kJ4yAfns)?oMQ)(@xHn7x%EOi;BHX$Yf z!V6GXiHggPHz=&c9SAF7<#w@X67Gr9kg*a~0x>xdKf%(6;u*l-&k{%9#z8uPHxr9z zpvIH9+nt)o;z@jF)mQo)B>un^3EpmCQt)UH-VaAxLC9PLIaVc!PDm0}!u$JL@BREY zukFa7S6lHyP|ipsIiv7=+GUJ=?$hEcXX4?Kvf(f2Z+=UqSB@*Je>N2hx_{u(ipBa$ zwr;__iwOvhw5ai=CewhD96BsokOwMbmOfKfC0pLFnMBbZtb5n=Hi-`Yz7m|x&dXy{ zXck`6XOLqazV=r$NX$yo@Fl+`>!fSW;USvaNhHIS3}tgWH#0c3hm*WWlas}V3D4(? zkloTY%SU@9Me-O~f zCLI>t&p?EQ=RE=%^|Jnm`osV2>yK!>@J-jBU_7IU^#}Yv9M4EyekhG1=&*Q3>f%Fb z6hVi@Gg6lxN}~umES^!!!V`*Tq%J%V4aSETp74SU8ojPRYCI!!flcpa>kkbT>=pm3 z2do(^)&v%-!AkTES!@n=XWPePtjKru!FpEevAP#>Hr{fY94TLoXGwfXD)DZq+Qyxs zaU3(AZQS1wP?0ZD_-}_*|M`DTo=Wd3PwfcGQ;0S8zgM2hC21&EN7B%ykUW)}!BVp+ z^_`GBmCNL*+V^NR;#P2M#Pg-4*LL@*Ao5?sAPuJ)>_Y7tDS9&mlx7u9)kdzT^@Nu#PM1Mo1}8dBNTc@ zmiq4jTseAa(_-m>{vy9+;)4ZdX(Gj->MXv*-=fj1`V`l3&bH*0x8Ms`|38BezeQ`t zYnIGTdapF_{n7qml+j?kw(77p+gxVJ4B$}!kNTRca5IkXC`v_ums=5!+#feZPYxCA1v|`+fuWEL7zGhWLuX{cuElMKEb? zn1APN0#D9)1BsRh{;h^sWT|2PokRRPr-7x0`FAizAMJ+`W-+uMhP+1+9d(c`z`#Rc z7B?ZMUgIlbKdkWY?&B+Fu*k*C*?@)59@fDIe+ha{iKk~~@o|g4EW$kwdy0)Euo?jy z;v6_YVv9C&%Cl>*9WL3#wq%Qe8AI?f0eBaP7U8M+1f)JdLG>3}aka$eo`~3Xmqzk0 zy@@vvq=qjc%Xk{S*;eUu|L`#HX7NE`Gmc0_d6$>)ExKU zsy-!^7}GY$=P)*X{lni0Ts>Z-0G8axF=XDfqx1y`2un^JvbD8pwN>&lIeXq|d(_OBE=% zQoj7~6V=I?YJ)b?fq$oI3ebSV;JS z&7Jrf+8H!1JEMu!ZkK!`mE+_UoGw(-a;-U0eE+8?4&{g(`r-5HL#m?Bsb45RDr;jV1%sGq@Dk~t3Am|_XPiFwJQDz{>z#K$uZ4>z!)fDjzvBxlcm0+$) z6gDNkH;dQWqLlCT7NvYjyjHVPwp*35jZw?y!aHi&HsO-WW?^Mh)(;l1btwBXK|`M~ zi|6>5c&*MaGf;sr8$)}iNf%p>^44Qgy|aenKO&K+W(b`NlIs<@8_vVc^+<3i!_Q29C*OLh8oti35h0ixc73wTg1;L72waEn1ESU5zEMa;vF zcd>NIqThuXmYQE6K?e7B76;gd?XS3wb9RCS zc#sha;hNMrkY-ux{RPrJojwVvFn~%Got{3(c{ywhp3Ce5-4^6`By zv9!;kKZN{p!E)}RcZ=JD`IS?Cn9&!I*UK!glsN^`>`p(Hv2r|Gb;?v!m2E0p&gL|% zBoIftTz>OnCq@4XADE+a3`cXPRR~-im4AZ?3#;9y1x23?INbcZG>u{Z9AjoX|0)Co2!^8m5I7Gr z+i}fR*>(-FI%7Gp?HV6Bqhe74+n$remz3g;!k(6q&#maZjL!QmW8Ur53*y#_ud^1s zRQ`1qhC!(g4NvD&FnPHFS;UF04Tza6dcTYlm+n|Bpnvq`*rLoYV1czYN4|F5&7~0Rb|yFbJ31$OW9+PF0ff> zmVbMJEz(hpJ;QOQ!q`JQzbe=%L9}Eo?fePj?d_~(Hk`&ykfeW`+=@`(!FYf;r3P&) zvMH(^okgvM;TakclRo%08xbjUFe1hyf}0^Q+nBnO4F?ndYPD6`Dd^j=&p=a7gg$2( z=IzhfC|CwApN{}+2ceYZOP(jf&Px~qx3VEnBk0?(Y$8H;Rj0TuI1;R`!OsqeYF~;^ z%QUzc4<`ig**IZoIR?W%L0?T9)*lq$1XGX@)Hzm*8)%d-VKnTc99;=xKo2is?$7M> z{e;ro6LH+srNztP65Rl118c?V=pwZBr@^SqA5nr$C25c&^S5G2)_W;`2n!e@_`X=_ zUF2WQ@?Uv9@_w5LvAkz>A~GTDH7Q!->7w%NG92njU0W{i#$-hd$e6AjVFieU2m+Ym z7~rVR1_S0eeRzMse?Y#&A6%cK{G|nU^vFdq=6Ea;Q5VQ_MPuH+h@N4ufZof^3^P}zzcn5s(MV$**0y5aR#Kr0#`;jo zETOnV2QW+}y8N#9=}wViu~V4%iy<0krFPrv&m$^;@h}TJZ5`GQ5gOvf@?SeEulSRk zm7V^0XC?i9vaN(}YEp2pou5irBy*iUBbl?}`L0E&kC6$qA0LCdob=F>1e` zSe1xr03%c!Motp@TOp&V<3U`76yFZ9SdgWob zL!8p69y8G?w=#Mx>X?g{eCQ_jFJu53?k|W`5TmX@Z`YSb82Vtv0AUe?W5gUg>pP4# zMx#h6ndT3vxvbLHf^-1q@f2TCnzWw2SUy^9;6{`c4Se9|Lo}lCOV+T$u)}amz(>n> zBkE!%%z3jAP-w_MEdb%n1ADLRM9yp^2*c`^Z$UyFLP%%QX{w(ZJlhboOJg-&z_?jH zz>GyMugn4Hvy#p@awR+uQp5(A5iNkFl?dKUt(g>pKOR=k^9;A25}!BP(9~pB$91Sp z`Slbi!5lHL%^$N-3-A^p)d}Ci%Jpdo{}I*kEew-a+=Ii;)C$QfW~)P+g}Fe>PYn)j zoal-+dhlmMH0Ic`EewNgCZbV)y8KN%yW;PQzny+9{$hAj#x5Ypiz+F6vJN9!G(uco zK7^fIAjZS`!rs?{@w*L^9T6AY3-FS3oKk*=6kNjg1<h}GxwTc#(MwyeHhF+h)Vp1{G-gEh%FXk26a3f@y0{*>0E!bfOn z%{br!G;a{0Qbd4ueo>!?m6i&Rw)brk zx&duE%IxBS2IRTcY0d8WT=Fiy`h(zy z#yWmhot2-}>6-$hV-P@T3`!}SJF}%--jh@s-cn~tK4~~t+)ib|%2(+J^%pn%e$kiKNt{pKO`a_Lmerhg}h!+sM9rD-_r8S@$pMg9d?4#A7irlsLX)6!}b zAYu!imxwJmfDg6{Z*?WQ=4##daLMI-iHjAf1J-02${`F`Zvxg)mxSbI!Fw*pJ#h@= z!db~?Dxw*!2o#wweV8>Qj#IjTV&Y_mS?&C+CSNg%iN44)AY!bK!--BO@DcXv^?h(W zOA1h)&vR1pGZrfYG|NZX;{_R~@K1M+<%5%-qqHjmjVH##*&AN1S>-%I;zFmXA zyrtQae7d-bMiv6@N_)(%p=L;j$p;a+ne_(HVvBUf+nDB_$cH-0hZWNXmI^Tijd0G` z%+G2@JNSI(Fqn{m-DEEQ0xhX=4E0Z9`Wr>qM06a^?ENyyo)J~ohM;Y9Fx8KEy>loW zxL!2Qglt8}A}|RXCkSBf@FlO(eB!Wvc$huDbhzjQSF|&`EUC^b8G!@v_op)ilyv37bL6SB`6GpZ+-i;%#`&VJX?moK>l5W(S*Q zlz&>JfCl~GH}6jZw1VTS1er#SuN73H=<$`v#+Mgok|+br?|Tfh0IU=d=k;J#Gklor z9dT^3Q}8DpraR7^z*d-MJX><@z^fo%otH0v!RCChIycgRJ`ek!4X?+s^*I)t86xq9 zZstp5bC^Qy0l5yb?5hL4&o@%i=tMn^w+qj^CNMt@4muT#xN@D}M?EfOCHuf>$z-uB@;E%me4&pib+bQ5H5W*4lGh7c%6O^ z|6+eOjR8b=`n0$ND!@R*uYjPdAmUP>`n3S}gHsPI0~o1yWNdpKfkKPloT@7u==GCk zggDk&|2XW@*xbR$ROe0!IJ45eUB+Li!PcGxj9-TW8K8_{tzcJMfm(}>4ubDh!a@zC z&5bE2H8mHtR1TU(S&)==q1EU+phdvA(ituCa`m3t6_1AOesfKeoo^ZJ$()1 z-KK|E4_E*bLUHT_tuxD~MUM9gy^QxR{o$XA?juAz1Ko#T&q#H^EBvp^`=S2Zjx&YP z<`hPs1FJwlzVaxy?*Bq#euV%{hd(!Q0$Je87+=HCm)bRUY8C_jR_fv)@>B0EV!5`D&C#bRI!{N-`HxrQKxL@9h+}2az3MeE)WNgl3ZfJ3!P8c#6;pHTwa` zn}BpGu&X>9iYDUD+~QOX?C$NP&$eVPQMNZ(2^VuH^ou3)0UWE$nVrW2 z+rGlIHWvrJW^?`M@}bmO0?pg9V>Cv{Gyxt73$4a>=;Zb>y9ja7KEXW}YMe@(Bzz@~ zf58ow#hM=nh}#pact3|Wy?Nvq>%X1m9J+}V>KxQ7ZB{<720kB|rm{TLHm?SBaF$CW zeStG)F)P;2n9gr58Oy5cUK1#zV^OvnN?X?c4f3s2^Rw1Y9M`eVz842r?h@T*SXW>b zXes9$KNjlX331&2D#&eA`lu|C1PQIB?1^AyXoHF4eMxy|!OD?A`qeZVMZkgJ5YsNd z&ZZ0e0IBg%_I#xU$+c9jIM^BZGso&`XNN%N$nPL2V$v!@-jRy#FWx~@BVuzeFUBD& ze#|xK`(ueact#axC}QTlSvf=_&j(>8r!QF($}^EbPdDOeG~UASZ}og=EQKB6@}QcS zHP~g#^?w5#I^Tm6sBl=Gj#e2E$DxgY@TdXU`BX^2^No-i%VwncpP~H~4xQ?3;+eMXjRq%Vv(ANVMa<__u$v3SBlc;c-+pAYOu$v*4md|-&! z!@HgjToF7U_(+U7{f&lmL4LPcduy3ikC_JLKqL8cofSBrsQ3L(+0$R;eBg6*KJe4w z^MP}r$*Nw4YUs3MV0}DB2i`TFtk=fB0h6*ZWKKUOo6_E)G!LbjC@r7TYALOO(iT$M zGD>TL-7zfY&lQ2oUv|7neq2-07-4hzF?gW*afM|#vR~`fo}SLAh5k;pr>FCQ$x$8< zH=R;103(b>`g}5YfwH)F#sAFr-y5sTV!8-6lW93il!svg_!HzCX&$&HIa{!VvuQp` znHb7VCVLvMd?p5f}TXS@% zdS()irRrlYo0%3hKQkQtLaLcZD&(>QU1#Jgb;^va_Y5JfrxfZXRGg-11rpWqsoIB- zaR}hT?$1Nc0&C{`aY2zHT5n;nI z+V^uXKHBd?ZHs3(18P2CmQ}hkl8Y*E63-79V^l5CjId8T7;B&A-@#&a+(R$o9Fq94 znFOdoE2EoA~;7_}N{Am}!pLPNH(=LEN z?Sh~`ZBxjfsWyB*dnM3L_|sN$(s}3U(CO^pEROH{evb+X`maTII=F8IylD$Ik^S&g z{IO2efs0Pw1kO774YCQIn!!@DDfJyn^{`YEOUX%AD*oE(^kTM zm{?kbKdqI64zU^zYo`;;Nb}#J%n#-J@P0M;DkIR)g}`1jPA?W0%}K|A zO~H~hfXw$FrR~oEW#30eA$K&52;zCw(f0c?%t7>LyRim=y%nrMV7@<`%=ZU>)yVb@ z(`nz}?+=wYne3m^W|x^2b1SkC*5MdH@cpn|Mw%lTOBoqj;f(v2_dwaQ>Hm%PG`rTO z3yb!dH{Or_TLE2Et6+RKZTSd6dKO)`6g}LCG<*M&{f_zA$qhy0`0v9F4i_BPmu?Vq zW!%Xb*g`9v!V4U%O1uMLk5}zH1AJ%R6b%3#X8MY=$Q?df?|5p%PiooPNPy3je2pk#HvLhqhW0M>eoPh3XPz4CQj zZE^eUw?ih{kVU1GpmBZs@Vh2t%5UB&^1s^6JL!Qla0~xZA9j(*zc3sZ08?wuj?m2H z-%f3xIeA{Ymfvt1S@?8##ydMvEhi#Ty>J)OoTqVEs{t4Aj40JpLLl+E3`UZj*5K;D zR-rTzlcU@epgGnIPbfGoA+Xj;QLXM3E9|8XVvspQ?d z=aWx9foc-b+~k|wDH?Z*Wc2aQKY{$aw=fERMD(chI|HBbrDX8v{Jc}D_npIYrDeVH zAgrOp^|Z{M#4* z1I>Px-@ISoe|3;|-UWGp|FFi{o=8EPHT?8C>7ZdJpuV*aOVyhStM#zaoARq=Q~IvD z8!Mz#ZM^W@S^so{2N;(B(e6LYl&XXBMCAAV!r#Y9ZDv>@8|&5#Ev%)+Ftik3nt1!| zx10EvtN7{V$rldDW{8pAh78GLP4+O`<%cVbe&+$Gv;Ak#Y5tSWz?F3=X0o3CaF@ln zb8Vfoq0|3KH2$N^C&=ncL{wgC53d{$q8BpIj&vjQEv~7AdF5NAwxGTG;52yzu*A>xnT==Hj)H#-8o0GwqtR&`52Cd@IL89`ip+-=jgUbUV_v4E)WeqzLFbEH zg+*Tn!&#H^g`#9Fx)jHk+&o|6ehyYf)_B&vK0Z7!%aQju3$*}TkjU~w5{*MQQUYu6d}PhkO5UM~ms z6Yp$Wv=tK&&Kh&eQ9N@|8_W)mVmDF|Z#ZhzABLvoFodiif^_~gTVYj&3+Y;_f;y;u zgnPBr(9-HQBQ_)bwqw1uZf&*G8q08*$bFZytyHcDxN+6G8c z+kis~%AO3X77q9{LiPaB6xjBOt{@T6P9In3SBCVVx^(*h-2xm$htO3vU76@A$L#7u z^{XdMQbhd*^isbeG4-p$J?dwNAwP6zP$D(U7pr50$%TArKFSY)a)~oWrf1NDatZn>8w2c+^H^P0sp)H96}Gc&~Na(7*Yj=YjOcs_22V2Cd2l(vQI9 ze80dS`H~mnVR!l(wx7QW1Uf>=*9NzT17F&t$`AyK9eD@>JuTnHvad2zU^@Uv0Qmb4 zqA%0QT?BQfV1vC`wCK;^G;;(yS_@xMOXf0aH8@64(^30D%jmx;Tzu^3*TVnexG1f~ ze*QDjc_p4N>BO-4044((tKJWRd~!FCD&BU%Pgvg}8joUIf0Q8At#?D20vrjsr5Z(N zN5=9DZ0*NbxdzyG^UmLbAa?g7vAbuxeX^yEiRv&Md(zG6Tv<9m4iE6uYQj^!6n05p z8L^-DM3i5BA3Jjn`}sK9&vV$%$I*VC!+t)F_VXO}^KrDF=dhoTqy0RG{d^ql=Q-@> z;}Ve_;$u~Y_Ve}O{d~9brp`ckDql)In?8yFWz`>K=*et%dKO%DjUY(iDvMV&1|X+( z%p2HXXKlikJ?jnZxyQUiX;2whvfiOI52e*oS_7rkQd$G0(cXLvCDFbsBFPRH#);tlb5D%Wm^O|D_7t(*$6k?K z)|kH<8|{(kfZ4TDYlf8&%mHVnklSqn4AIzHC7)ph0zw3Lha>W~a<(Nj11Kmxw{E0= zN_e=y{#C^r2rppj?Wh8DgEyErK9w5vPA`RAi;5qUA4iFzw)Q$lKX78S7ksF&x&O;Y zWI=DyXcYMZ-0Py5uxw0n*Br36Wn5`s^;p4p0h{TovsDw7Ixb#(aMc9g{Hm_y~<3 z;GJ}An+P-Xy}mWHm@nFeGGg0;@~va#W3DhjtV)P1$`|9mwDcI^RY$IhSHYWTI`dqz zuwp5mOAo>1n7oPj4YRRO2R(|Yu%-7RVdH$RY^aZz@6baqDX0^jC*b+= zU;}Mvyk`N0LiK-;L7^QBSELyB6BN42_X{dL?5Fhy4ErPJC-~J+4*Y89KwdX*=qO&d zV5or~s2vK1I8?_EoHsOsAGly>HoZoe=g@n=)`ptsX+EVrMrqGb+CoZOCOFSRAyuJu z{EmRoTb2GCD6}36?k{-Vbg;+1{J`mr{J`0Wyj-3k1gade4YmoRZQO2~v`ggB{1*LQ z!%^^aGq9xL=CV|Da|H((eBF6$i7jPXo;+GZ^O^V`!fVHxL1Qi_y4cE2EYSEjg$0Hj z$_d8T#lrX^`85LhCx8?}02cN+I?z~@tU_gd2)}%Ugf6(2k=+WW*Wi^$d%!O{^nQNJ z*l!m|K+QwWZ187|gfAz70L&h)24BLS_L6)Lcoq!Xfa_ zOfl9>`LS(yZH_>g2zSo0$QFdHOyV34HZ zQ(7mlF=!GSCHmtOSCz%P)VZ=Bem>*X8YpA)pjE6r&^>8=qt^D)N(egD@ z*k*L6Pl%dL{`zk!P(+oar)4&q=3P+^;+oKgkSQQ~lv=tB(=^tcgZ;Pv9r6dw56t8FGV2&|Z1d0ShJ$6_EFJjfPV*ALPk2IR5b+mwt+69+>#}lD*3f2juYViG2o&v;x z*m{!^17gV_QXC{~8ACsVx6)5A1_U%+{%Jr*LLnd!j)L~4*u#NuN2U>6QJ$d&W{LLvFN{s!BBsc3*LdERA(vtjKEs6w_{Kq_xZciELm{x zIwZil)ID}MEW}_;1k2yU!U0&-H3_XJnd2mk6`SBkYjvj%C&LzJokn;+_xN1*t503$ zWZ`k~+Cjm4KDn@p!s2pXaZ#gj--;}OYr*ogxvo*)?(|M*@nTa+Q34CS^}ixCcL-cM zeW_aDSTHVxQYUZ+glz;o(myH^yh~YA zz$8R_2mTkquaS2W&i-y+Mh$_W;Z#`Hh?@MFFD1h!sIy_7*Xiqv;);M_sU3j6vNmws z%IZCn>b>p;wa!-8xYWPG0MWG|0Ym)lBjV%*2}vt&wBqCq+>y&C`i(pCj>(c$&u{hs zpT)kL^tA-V3;c&w&NkgPh9gb~UYo?fa0|8A`=bWEz$3NiUDvOcRG57x!!Ux49QQp>1c+51?@z*V2TrOp%Y z+3O3-H6#08a_9CbY-Cupr}&D}9^+6{$j$bFDvV7CHNT!XT-`aLu({|bKh^l3kq)|r zwgcyV@)BY$%V6yQ3z2AQAjqzJ8Z1kg(y=VJfHB;iOlxhEn zOqZ{#I|nn0!Y0a6;LbC+&G#bS!~r22@I&K_f2l~h>ib*{T+1-U5`I(1rdVp0b@IHd zq?Nb(AA=UcKA^Di)78G4i?2|9mM+`?wlbYA1X6LdP(rR3?)i2R4;W@GglzzwH6 z{kL}gY&JfF*HhsI`Vgan0e@x$;Fg*!*pfJ-oHw2A@l>B5uI;#M3d?k&_gp+OeFLto z{u{bHorI^Xy7Zi?iy5Zz|I*p6rLvDWy}O@U_8ihF7dDeitbb(J$9Li}DDv%Z*p#% z^Ed!J*!ki=&hp;PT>qGUgDEynlFpHqP(`uP0T~L4jhvzmQfwT(s$wID6dM&G#YR9; zY>baoY@~KkZ0M9PRK-R|SH*@7b1Pc0(cZ0M0~wQIqr&rfLecI#lpf*BU{;U+0yPVT zG0QJokU0;EjR*cK6dQy0_KZi5cqfEMqa=G}+q+n*x+pf-qX~Evqu5~0$Ojc0%raR~ z?sTiz0C2@3dtsMAS0)13(XR}Hw*&CUZ8qILKv(1GY9U=QTzSb=@b*c2damD;x1;N~ z2K7b#A{86g|LcPt-hrz?h$|V8;Sw3tfRa3zLT;(iL(fff!e4ax0Yw?gAKfmQ>VdLoL;22xnDF$$bw)4dk=hD=NraS??rZN2Wu-HOZhG{M_;6IbI-@mSpHqPe&N zHtzxGu_1|JSL^Cug8bo*4oGeumt@gHhWjyQT;V=uAmAHhF05cz@*uJysDKU7L-@ez zN~yL;XsMBc9(=!+LUc%nLNG$ZG47Zq zv}xGB?OO3__|{)LsJ<2h?3nx)lp<=9!30^|zc9Qy;dd%tjr|-J7<9%@8E{JQBz6ah z1Xxl~6n=dgNipt;IV7}224)#?vWE7jSarIKhXNq50wAUKAvGS0s7B|h1sN!VC>{&! zLC_iruYn9+Wbs%SehMbX@Y4!pY;~^!e)=Hr(+c3H9l%fNDSStPpSs!eROouBn6Fa0 z8U-pUlF(!-W(0l_QC@`U3C541@}d-v#sm{0{EZcNWy3@) z{7NtuhN@1%?Z#PLS)z~ZQLI?t@z$!3=#6^b8{s-59t3J)n{tV)(ga`lMgQxDc z<0Oy0dTG~6q{t@yyAJT)T<0rFJ^p|S|G=xf4L z1(!}(1V#5mm|!EYPl14tG0-~#9gQ3s<1&yzXrD;&rNZN(gN+Bv!=KSM)QMx-k$jZfv)~vv0)Q6Dq=y`Ctj!3xd`ioqE8M6>@EYw0{>xN4=FwROwE$a zA_AbWjWMZGE_OMDX)cuS`VEL>K?KFYA2eOO=Q8*$Pi8{qI~73uUS5waqQH*OTs=aP zoej$%0`gm6bvA_n4Bq0!jXAl}KfqkPho#K#f9A?i4WE_JL_hdk$ItWfdTl13)&Crl z~V81(mDD7gQSNsUY%)=N+y4b=xOzsnGNBVMr>4Hc#o2=&v*%MQNZe=ewO)N(ks zHgg$jqA5f3;|I=}77-zQEKsi`pQr7`LirPP_eJ`03GFZPSs>$l;L>*uAxkWD7YlE` zOMXuo7QWw7n`ia^&1Gs~ZKhm`W`l9*?@|d1pY&_|m|H7pQ;T5E7x3UG?7`q4(GQwYGmV;(^VHiBDK|uKxkAj@*y{rt7xhae@?d$`>s452HXX6I8I#rGYn2#+* zWpMI_vP+`j#A>0I+4BY)%Dz4*vsKE>M03MNQE8{u{mjx1v?KiI{0Lb_$Oin`1&v*% zM8`mLG4SQUI=-X@Pt0&yvPkDJAOo$4HqBa4P+JfocI4k-QGtv1pKoJzkJH%AwKsmvbl)mB}X)pCz>M&Bw(u z{60Wtj|+ed3(1wxtifW9_KvPx=ooym0i^)L4~`ldxC_Z4cL^Lt;qbiwXH4V{@_J=P zItCNFFWx~jH-h8KrLP5JM)&&{qFRa0{p)q;LxddIhS?9{;+G$x5-hrMo`(Du>DD#4 zgnpn1_yV?Th|GlI;N}e7454t5C>`2Fz8^i~Pw?YS=0B|#)2$3scJ!}&6N*cV+7o5u z0vr;M5!q{2GWKA;MCS>Pf?cJ08#ZRU@tLgjs#lu(3?t z1Y@JX$^JAdF^5NLoHgu%qT!&Wup!HOvPLO=ik=?byOj4*$tnNOmb*OyV$&aLY2&I^>D z`zQg!ju&MDJnq6cH;xwg_fJn;!56j1JNi=UWTf78Q|Y4Af&*p#R^_)m3+G+MD7q!RnuXu~RkC$OfYKp^Nco8$$L)<}PQ81-V@{@lOcGMsN zn<%U6SsVbcG|9%DvgsizHj?uz#+wm&4wHO*7HaVhC-25+@DC38R|S*bL$X<_D)p=$ zXMxk9@%XBVik~Wl+NV&7%w6g={}01m%kXfx^Q6J_E?_V6(dpInOm0^opxu*5~#*3tfI`*K*j@(FDVi_ETqTr zdB>pt5RE(Sw^1ld_ZqHXQ_<=`w%|4e>@DW))Oa?-d6BDvJ}(X+I(gOa2EQO{FSs1R zFRM~LnhCuq7-foM$reULQc~7NN)`C&vIs7&v*<7S$AlUl`m9jH12Rw=9*KCpUXUKv z8IFeM5F}TVV<5An5F**w_Mb3mKZ1V*w|9^>01Utg4zfr8GhdUSfYt0fOGpSCqpIA1pF+7(;dsm}Hiw)2K3{^a$jHwcuQ{0t{Um5ma?H+-7-t3l z+MA}kC*DY)el-L2A2RHOj)-$S0)Bamit2yM0(O@IgW59kM-aI~7G{8+q6-^$Vowk^?6(x_FMEPcmWn$``)J~7X1-`h5X!uL?{y1C%bgiHHYeH zqS{-~3<7|CTBP%VWkVc&u?Q3lJBu$VZVLnl#5*r7dY_FXer_F#skkj1hlE(o+!oqm z%=+)#+%qUU?WZA77UkJ1&;2>p*e>Wkdo&S`RCNC+|Dqp7QyZt0Do#y-B(*70kP>uT zs7BeC2|tz;!tb$Cg>im#Fa|E1^pJ^E^N z{nn8T5smKW;uY|Xu;IiKzVsI;KW4=;;v5VmFt;A15khe^g8=_w=DCn$mUibQ|BWws z7nR3=O5}VWTt_Nwt;UJm*vBt-}xioJ@W>FFU}eZQIEc=hXW{oft0 ze)rpvfYPS_biDd!K`*EuxyE?)0)6sd5wAY*r(oV!k5@nZhs0jKVZ8e1Ux3`G+E?Fy zFU+c?CT|;TA%=5JB%vj6?DRNiLxUbi1=L~r2!*rRfg2{wy`O=F!K`l<;i$SQ*|6Vm z&i5@mW3d%awiTH9r*`4ICxmO9-bUME7M-*Lk$meBv6w5c@Hvw_?C(x^u<#`g`cw~} zm&W~uondLKU=y&Lu`l6|{Usg#E_f*ee;2=$4Upps^4Q;wi@kKQ6BphB{w}^ch5lYj zL1ME^f0_#T&PM!iy2!61QtLnpFIUi4_~Plm(nTFE&eDf6``pVuug6#QM4|x~r|>1q zejT!h?4pCgdMDhgX^()d_8gQ;O9izu>h#(E!ytNsE>7U$OQP;))Q>Rg9->?W%BXec z9#E&x*D0U>6)z9@G+s2;*~dz9WP7;MUzI+yNOcF!Nf!=$&Q(b1uaXQc$#~as5^)-D z#xd0~UTxHQES1dNaj?d8X>1wdAwkfmDDKqar~zMk7pmfao{78R92I?0KBDT7n|n68 z$t<-n9lSDrq)NAC9AXB4z4mL^-6vIRXk(A7G>XoI?NH)&e1cJ-9Q2lEVBP&=uPDvc znX5OviD&fBdnL{>*jI@wGR>bZrAu{J_!8y_hU4aHusm8yzqb1k=SF9P4cAFB;?I+6 zXeeR)agKh576W|dJdWx9d1OMMucidj*SS*Pby?oUY2v9b!;()*eHS{W48fgV1cO6q z0Ul6%ZPJMvTOA0dp-?&*Iw1ML?kuAtiqVN{@L|nGIaAcnARcgsuZtVms`r6|9SGt|y*7h?S zJ&w6%_x%Ag_Ui@@&Pv_Q3-uP`#WmxYO}l`788)`z{>Gk6+T$AgwsGtx$4v;@X*{y- zOQgZg(YR~P4Zef%6j=Bi$gUgc+ld?VN5~0wryt?kA{~IG0)gN<{>3KLc&0n|c4jP( zbJA8!Q1`|JvykwK;09Ld(>$p%pv%MXmClNYcA!8XWJ*lH2tET0(PjfEh=k`5-K+Hg z4zuH5d>F(LZ8MLnw=Jp_7vV^b_C)@9W@mvzB^Lqv%?rSF@YVOpz6?g3{HAg;AKg%e z+Y1PEkZ3RGYyg8J!QSb?1w7Nw0-Y!ar>ipq!Xy8@2dw&C>Zf0^!lfhQil(4H z<6Cf;NqGyNgl_`;eiJvAw`$>b^Hu{qZr;Qn%bS2MDw{yG(@`t50_UmlL!VpWzmvQs zacC3FukF~f)>4$F)=vd)4@kWI1xUR86-aErAIpX>1n`m@5uq5Nqo^#w@#LEK(q##} z%ySt$EwHYs^r%fbyEZ+KJAx>2Kc?n0w8&?$ToB?5Csp)Bp6iuN8eeAY1|{W^Mx9OS z#K=H_9M}6!`HlGI$(B`HYyFLAU1 z(hLhE9|Ed|_nhImLglkaUt8P`KqW0}2e281Qx=`MWg7cwGXjO8YcPl}tr!v>`-Jnb z@vS^Ut6_*Y+i23@%mf6*S6UR4m(69@i>$%8oyHoz6gEbf$ZOeTmJkf~11cIXR9K8n zYsRw)BDfw&LWcbGv#S0IHZIaGSL%<9sc$=m(0s1Md`23~%6a$Wpy%(yZ+IBL(6oTv zz)vTn7G?4Qi`O~tUMv9cgNhD!w*q)K9X^Fv+^zOezERl7lZhh|?1RLQ!3OEyG^??b z-;jW3HsBz$-MNfk$O-EqwP4WT5LLcp3ylzW>I;Z~>n5#)h?5#bc*?VbU$NnaW%c@I z)YOVOI0!~2SiE4%RBbh$;5QsWx()FJFbhTZGE6`MnlS+peicWv;-WJRPIB0A?MJ*Y z#Yqm+daog<--FYe_Cx%!eh6%$5a^_TJv!zkVb$^PY3w^DfW(?8_^tW3pUt*i~a8XXh2Wv=*w? zV%0iET8pK1jA|XHTBl0uIBA^7;LZGHBlokeSip9^OH zQqO*h9yq`F=s4c>lem*g8XG);leyEzB?bek{S0Py)-$^Vy`9r^Zy2Gn3Cu zKC}4D;**>cU9$Pi;WLNNTt3P1mDyR1maslA49AP4rA{x^=aOr+&Q7sG-=$)jQdCQ+ z8p4Ci!5s15m`4WRcoJ)5zi(psjK%jw?W-r5dSkolQQ3HCoJt5QIU>-_jH3->OzWAy zjhbjIS4uafD^Z=peS~hX6X`<6bYRQ$HWa;!2RT07Lk~I9L(v*hen;~NA2-UY1kK59 zl2VduXip;T`oc6)$8=RJ_~>G0WnL=m?5A%k_#}fe@r@cz*8}K?1Y8@SJi3d zaya&R2TnjGQ*kpd@P@tzsoCtCimLrxRNw%~CpM4m9g<`4R(rg|lHlaeOM*66F#B<$ z1-1~28Jzt%u(LIVOf)CGq&=3eff|5vIYDZ>K&1Y4-VhE&=**9=Aih@kph%Y}J}%nn z0aL0AH*!ISn=?Gs1VG1H9Z877&dTL#Zs~{;-cfvJox^NLgDXY=tv4 zTuj)+Q;Op%yGfepN$GGNT#$0XcHsofEhQnH>?DHE=kg^>SwKh?S)w0}T#Y<>+ND?P zWtFm_pQsIWVt6Arv{N!i>bqTzk9DxX^Q;9o_Trs_-B)81J+aYcJL(<(?lU%jR~bUO z%P}F(?t6jke=+s+;-SH`Csbw?p{>EPCq5?#CAtT^Tb|2N&uJAtwO<0fq3l3(Kjr!1 z!MmSGD+#tE7KlVGL_}|;e9Ud1(`_m{y31=@X97tr>$$tc@xFg;IN#cPG{7fap;=-& znA^b}EQPr|6&Unrithk2Anz_dpVed2e+s>mTMK3NIMB&ytv`C8k(F2QgI4*N9J2W< z1c4+_FgHcI3f?Z-nXo>f`zOHmPh^38pPU4;esUHV`3bwU6>6O-o~)AoIz9a4u-xF7MBk z_vg-1PY@$b>XI6jBXT0KXmDQ(DAiB_6`ABI*mOfEtp{Wv*QKwjIg+X}z>~VO7epW- zd8d+hGM~^hf2sId$*<$sE%bm??uY4INP@N?o!-eT^0MIZqK07a0ebHt!Mg{f>30uF z<1?MlbUrir%;YnR&n!N(`OM}shtC{7bNPfG^d7*wm@xFt@wWd(-U8mFEY2x(o3HW5 zxMDU!5GYt}fAf2qb3b?&Q+U~A$-TSENY57Hkl;@o%@-(ju;MPno?m`Z52{k6ozn65 zWJwN+($HPtP((FYi5p zX}ScG|0n#7qa@ah7Y=_Ds+*9n*s1upFY5&_Ay-WmIcrE$lS;lCo8+rWC0~ur%2!i& z!TD<7C?)^*%y|Cqv`)}vGSI@=r415xaFCqv{);)`{ht=5Z;)ar2Ng=|3({JxT8q`a zW2AMXwC+)@<5cTZX*~*ui1YW6axek;XC>dS8tUaKV8a z*6Js)d`K!Ku?1b2a~LJU#GdON-ydg9ts)Of%WvvR=5v-rT*``kEsm`vpR%;6g4TSJ zQK{5{V(5@?Jo;%fof27+%kor7>q{*uOZYOmTeT-uwO&#xJQ&q5I;nh0k}A2EN}eQ4 zH)8SSDpm4IE$|C|Q})q|RUFE%Duse?&3sC!OoFA4=2NN_*X9CT1WvZq7L-BlkU>7z5D33P1->mDZz40Q!^wC=tFf0ELi|#y$$57Yd*GarlJb zBPx;;V{B&S&Us&rxZ_=%BH)Vq^^+sw^2=#R7KP6TBn8 z(NoR1I4*22U}e56nl2-UA$5;9<3mzR{udt)HH%|>3&$_sUtHe@&n)yWb^;~k$?%_l zQ4%PpO$2Xmu)lYFfvl@{yj@nKcp*pd^EgEe%>274VzJo;y_@+jE-Igi>8_n*cuHKK zxPGDudMfzY#i6GQ$7TX@vY;xL#WM<*iL1-`I%o<=IY9xW&XN9$FA{!ajiX3a^3BVR zdV__fwi6~&?Gfdt8sXFTOHt3n@u`({{_nx3UulX@Nj-1kQyi%NrSWMC^gf<%J^`I3 zdP(K)lFP zKUOXfF^2?nsFIIIl?_vFg_ILLX8a0HLp*JRC5l^cJN!AQ5KYfR<^5(hBQ(14JCw6^ zo?G#35E0Y5dzRpNC%V;iHwJ;=&3NZ+m3K^=EjPG>BoM(3)<*QIxE`8{Ec6wZ?RYfN zV62<@%_(Zo6-_4bOEu^YtI1zwrtT3ZQJKq@>1r-X9(s2Fosw4~AX!RcN>qZNGEIeq zyz8E%cZs}aNC?J4I&XA6aqAE@Ask> z{7kFZi)GHauq0*B1HM}a&GAq1jK^yayI;EfkU3KrO}HWXH=v3NBCGdxmCQt>}cKc zrJF$m{8R=Wo+GcGFTIt@0YVeY`v!9Xxrs&B33+e$jOB2WV|H_&0b$Jlf5?EtJ6_Vf4GkVgXpkc3&oM zFYiA`tGJIRaTL$^unSW12@ej|J@+wwblC8CzR6zZ**fw8g7LrcjvjboflP}QoGC~ovx#iF&t zn@d!8Yz=b!?uLz0WvdYFuRT1D-mIQ@37du?%y?AZbA9}ZB;VF|u?!+aq^_YFEb*S5D`Or$XFO!%HQESxy zP;f<=snF`L)=;82aAKpm7LAFqjbj~_1TJX#`tejbj(JYav%;nCoxhi#^XAvfU#)Tv z7q4V2^Kh-GCS%jWHC?c?-P?KzpNycj8o_04)Ch)cR2y1IRpajBAsS2BBu<(zlM;8& zeyW7RW7JsI8u!RR9+s1Af`wN38gDdfGwvgisi<*6{odTm+tAaL%iSW2S$ALPTD{6l z>0rCyKMTow~KTB-z3yYW@#K$%g1_oYW`*ihaL-}^j8BH?af{*Vbou_ zE4*3ywMJgiUk1kVU;YEeEnfNJMSse8_HJ$zaql7r9cRsz{UT}nYL`P!Q3yBQ=e5Q@ zUQCHWb9e$w(4*Wub}ubY1pyHY29U{m+xaKDDazQt%|j|~YWG3{QXQ^CG*~k$R~8Ix;8Yk31$GFEN2VE^opA zOd{B?agD-p-r&4^_jqceHq6QwwEl>fgI=>gRsWdMvQDY4QZaxQMH*WT15?&SdO95^ zup>xoaJmpp$V6rvS8#TlEb+0gXeU=fQ|v*9D>xbA;7NA|8Zc0j5;Wq6V3QOC z)6*rs&69CPk;a1!n}~8r4_62URK^FLNGVZIo3I3o6@#4I3SoH^!Ww1gB5gN-u;?2f z*kWaX5_rs)IJ`oM!0IpNB+Pl!?{=0C%A4c={=(EjUf-R1P5Iv4A{%Brlowk$nRZ};6CsK46RFHql0t6a=% zkjeXpra@ubYk_TaGx1e>3bm?cjEIzZ^uNjwD{tpyg~d#kc<;07-Yj+R6_LWkON-T| zLb)`vOW+i#&>o>>Svz`AB^u`QODsVIa!$(#?0-aCx+de}iTX&Y4OIiY4A)>_3)9Q% zd-|_JzNsD*gWP;iMtMr?_E)Xj3;q2PZ%>cjt}VSW<9My+Zx`5iG_W>p zqJCpWowI$R^}KJ6VwX6eteSBOkY)@%fOo~hltI@}Hq&ILP*fi`KC-TkG_QL7-4R#& z6QCJ5$@qRQ^p^(4=gvsMh`2()z}L;WFfDJ;92g<7QHepZ%9*ZKwiUtzXDLhA49@5s zU>AW9P=^T<6>p~oG}&a29%t|=%)WiwVWY|_rv`L`7W0I%az% z@B$RWI9qpmR|r)%O+FIYr`IOPvXq%N1nSV&|0MSX^`ynDEIn zZWxTTye8Mi3O(x`axV+iUpKSNP3TK;N?Us|!}`tI>0WJF-vrpMF$O3qNdFO4*ZQgomnbOXAN`R%AJ_^a97H$99>z1deuNSTr2lW;WQ3Od5=B<5cUvsTGpj zj?0>a`aKY9_|R;)dPlUQztSN5mC#>w_mo;Wxv)!U=*B@AGwtQ43bjgMfv_mrimGuX zb2~oKDuv?;i?KU2^r=CYPwP~E>P}x~dF@-}r@CqnNeqlPG#b*rJWeb{|LSmmzvu)kOxAc{!>QAOdii>1Xc+TbqD)q ze23pLdvBbdfaPZMgPO`xN@&{NA*NakB83;!tZZ-a-gJ06ynW`Rr}(qO!W&s_dsLh6 z9-PKM z?~*|MARlFeS3$}A`@`D+xrt8F7~(bUB;#PDH6Jz@jCxN29uktI-&ua@0j**kH{vBm z{iw|XrNKVR-S9rMwfl^(ctWGwyB+mf;9(xY^j(BjhlU#M!3Ss{0#rZdIk6d67*7G2 zvew{3(#m&vbbL#43!PPE*O9%6&|&Df{}74fTWJdR7Zx{DV${gyxW^s3V-NZU){gA%H7H`%I+g31%I}VE z_GbUQ@UOYORDZ`)urAp@9&=+l#+-DV);hU5w&$<6;}s|c)5W799j7%~d#Toe(kk8z z={T*?I!d*ES6aoBA$_W9ouXPFfNquJ?~&$L_MCjri5=1PXzqQC+U~)DZ68zAD*p&i zP*OEo<4nLTq-smu8G*e=$wsv?W9>wJOhyvy3+y9%-0@K+O$r5l-` zK2sX`9$t#3{OOgeNFynN7K8o5bCfi4P(A?pk=$p=A~*0=WRX^$ZP_|kDAS1p9th{C?*?~hI0)wsTWFL* zINKt{<)$ruJ5hkQO?|sL@c;D<{+^ME{t5EUcL#n;3Uyr#Qvq5W0bx+-4J^KydhS#)i07Z{h1Xw**c$`0o#k+b2Zj0j=^~Sx=Gs9H+Gk$vW!= zoi1#}+NKXe3%EeFoG?EBH^FG!5~QJgpmjwE5dBB4)heH+oxYJM_<|pvT2@N7StP+) z*EybGN8O1>@$ekfpflUOde$ktf6cVv@pXX6r~Aj7rgJlDT2>nn6sfa6!^bL&=`ku{=cltUOm#=z@Z;<#LE(xLK{y2#* zb$skAa%xM4+d{LR`css^&yq)=@HK-V@XOQJL40f~7`q0Djt5b~Mc;AAJ{rI&a^(>Y)d*nks(k*$fn3Prd3 zb4bt}N-NivQOFKhN^`n}sVVohalR&pgGn>=g>9_k_cg}i(zhDz7)X5W*u*S@ts@Mew|rwZr}a1#n(s9#<<2hg0b%4y!61ltQ74Li4s^f zB8%~Ws)l8uIV`3HA!|%Jlz3Jjr9mjC#qxh7OLkzNhH|dh_d|EEm^^Ch-8FmDh*D3N zyc&g(Jjb!Q-;Q5t9lR-B5~~--?ts33L$Xv9O46ZXGe1xPvHxEcRv_43w{=KvPYQC;}d7xW6|T_Jwp|D zXvTw_vgp=`UE(Kdi!PNNDpF<;K`&8DLVSnrB@QXeOxnrv+sqB>>DV~ume>XM#}?fm z^9J_ko6YUd0>&U%r}6$=q4r0jfMk-}*G2c}7)Zf*^QK1ntCr!>JswTDOzv4Vxo>A- zcp(ZaI&F7w8W4GWRxjo|@BY|a$?>V_$kV>N+`*A#|0g$9Y^FVMOvM>iH8(rYX5sLO zvh%^=r)#5g?8qFM^m-<3q{@8X{&u7JTKwq09zOgHXyktdKD>&7#7{Hdy`2UAM@RKV|4O-St(?Zy`ORF@42x6;csbNoX#qs-!oHYlKRW@KXI9anNeWEjPCe^78U6o;wm1aH)0GQ^V*VOFI3H7$k zU&$|$ad44G5z9h#Idp;#BxHOdm3kzUBY|s|$%=-)jy;8@f6pOlMTeH3w2#vyXwa zGY3KvV`q88EK=`Ot1)SBRtJveQbWP{W;z3P7OV`mV_?>}Ml&vt4l5n@)a%E>}Zejje_OZgOiQPHH1Ig|EQ0BQ~DOff=NjsS_QW?@EDJw3GW0oW#fU zV`B!`1h*0|n(G|u=T$Ce2+>iYI_`e2BhPH)nv}M#%&V!eVMwuvP zj~Ee@;it4my^K)SFx2;QVrba#5g7zaYitk->dNcXV&b*>F+)AdQ0ui3N5l6s)L<%+ zD(-+GO6xsL4aj)u9?@H4t^SarEw~<0DEN?8(UvX{tx0r+P0y$Uw;*$eKV>-4aliWP zAO7$MqEE$MafXU*85;>9mHv;^9LbTQeI{r~lvS2inWJoAn@Hp?@KLLcs0BXi!`+z^ z(VQbCwP8bw|ErPWIH^+nERG;}bk0y&E6LR8v*S6JWjZsHZfdV5NNKhc;!te1MmC7^ zB%Z=OJdWWx+5(k&O&`wnThd{6wTj2(q}VoMnKAig{ap&Ll&>kQO5YTbMrs9r6#knz zDwj2?#CmHNF`nU!CllY9(Try}ulMML`>XM=V*O|kIM*s4<)v(AcWD$Y^SI%Le|xAru=do(H4zocWozK1(+sk!(;iOwrbiibHI@+;*0pj$6M22C$I&l z^*VdtG?~Nw0*qqylk_}+Y8+fUv}KHzzDeJKs&evfv$AI7$|;&I z>a+7tXU>@2)%ys$l!m6-Cn?phVS#z6FDFdfarQfpTBVUE*0EEB)z0&Kndm$!ZhvL zMEL${BlvEz9})avOpHtiVCL%XvGaQF{rjam4&Wd)3kmEumYD5vwiB^(jQ@wGnr&=? zK@@l!_&Q9bsPj(8j4kNw(Xfzt1fAWm4Fpy~Kk#K6rR$;;NV8-hqCki_}tqO$_Xz zEJ%kCFLVWSZIKKQ<)B}`8oD4}G{QbV5NDq!$Y~38=>O*g_PL~D&3%26*=KSqIyKiS zSH|{6+%qL&NU6PC*dhRyRg9lU_a;MSB*cLCX|TO3I0aU^1Xg-SNWeV5{Ktw9s6eD`S;b@mmI2MdFlwc6Y`> z7xW$mk5cUVNf~O1zMI4_)_`*vFm4PGrK00b2k8?>eC&kL7K}DbSQ=rpABWL)V%cTQ zeP6RU?c?N}#lq&&cNy)6OAgS83RD+X`*Ln~>%H-gKm{DF&eh@OdNQUi?d=3U*YedH z%%g%a{Q40OMY_zvkG5rCh5Qv`r`wuCh%4FGYD-69>q2Ca)%}U$4e)ubV}W5xH!|F_ z+K7$e6~c+>M}n;qcx{;~_@`vN!gc9UZhN_K+fu!WUD;vWsla~~+y)NBic57<;}}>y zhabJGs;}ZVDvFRPc&i!k8oq*Gygmt*H25L*tCjNd5r0fq@PRY|fv*v!@9P1>I4_s& zR~-ARid|QLFuz6slgyE$L%s8`V0RC;kBV~=6BC2IJxQ=XaV z-q?6BGb9uXVm$ad>@LyYlPpIcM6X3w^PFJo0=Cud7{-WhP$ME|?@$Icl0glj!DK>z zA@CAxUG#4-p+A*z5Cger50`;zWIUJcU`fH5u-LvGhqXoh0XsReMvm=h!QpT(ezKbG zU~ZmoWOU?LM6S2^>kA$KE*U?k#++MZHS}Jw@E%n=T^M4{hdZ##WaY7{<-;4Cb-%Uz zv;4A0YCj`!!qr9Nx}_|}*dr%RN*tazAcn)5!>OJrbrWPA3TpAEx;b9*<+S4L-=?F~ z@DU&>`p!7^o4A-%%y~93!KdZ1UqG(4UtUIJuHH_bWc5C|lhxbGcPS&j-Bmzp;{n`b z<6s>N_c0eKzCf2pt_S4A-tl+B8)5MRZ;#0!V(|75zr40R0$mE;OoGf(kgvuBI3v73 zvEYY_j++eP$4sF=Q-Be|VnMhgtdPZmLzTqPEUmC99C1N&eVrzn(^p3K{OhnX{_ln7 za#-UF2>hA>G%@&v6HSQE0e(vaYcxGiG5CoE;1qK98(^lJdp;iD6M0*bd}Xnx)3Adzsh=TWib3IOG%g!!}p4~pZIfSQl4H<DpLWX|R-EHm)c#^#leBTvDZpw4PlX?MSlQ}0Fm#+i- z2@r1lo>z+Ta;r6nI%6B0N!ZSLRWf){!buiMJlvB85*cx{GQ`DiW;AVHoTn081P?2QG7suwUoJ7O8@6lNYIWXnd#qYDLVQIu^c@U+_VRN28l8O5)K72<7Bl@uQI&aYpCgrgTfipu8p0CD=l0h zz|a!DhzyPHWc)A)J(u%v&i&ju$XsUn7Jt-^=7BIiHJjs1FdY0;|BuW7w^_*?{C&?0 z2Okz;5PWiocoNO z-!#W({bqPZ-z&wPrvgMK^?6#ZXaA;f4?V9H@hX9TF!OOl^$+$aNmKP2_L}5cu$4vV z(D&Vg+4PWKCG;qU9>nu`kog4tL-bbF0r*nreL@H8QN`sDYiH+Va{4HTc2^6fkUD(_ z`uO+NKN=g&7Yk<4n$|-T9x^hZQG)OsKW^(Q2#+8esPV(=lsO>|L;nivJ3Plpl%0G0 z2Is(x8t2jzaR ze(5L8}RjZw$6=^VX938&A9 zMujE7MwV>V`GH{7P=`6cW7tuvjsv3lxEFPCi|U^dLjE3{Nq;4@1T5b6)8*W*%H@?&-PZQ!%o%D4%-t9hPug$1r(Ik)?Iko7&u2?GMbI_w0oj#EmM)4&sE8hsP#-`-O_olV9_*6BPUneu z+AGo}WpuFjo>Ir*QvE<<@$^TGsRi-0g2jasZYrK$))qTZGqUOLZ!&3Yl5DC~+$5WX z@(BpT7PMOq#Zs^c2tMrOk|ktD@ipt+RKA2YJ?{Ie$d}y&*b)RxwU>OLCXADi&ExuraR63vf2WX&Z6{Nt59yq%DT~_eEBmL zU5RP1#lCMv$J8@2B94kJdBmhYF@F7v%9~2qoF>DQpqse3DNL0qFcmWt_{`dGAutV; zVTrhTqXMJ^adQ|AB5uBFE`C(pe2$;8hiYr4MFq|X?$jo|zUcL}gg=<7vlxxG^BN%D z6L=2{Cb6NROkr)41#( zF6Q#~HTxS+f8lHS9+yX-;Fl?n{+MramXMUvm9{5Ar2s)oW-+2HiKXfBwTA&g%M%vc zo&?UMhaG|~VeUpn;p&P=aU=OH22WoQ-Yxm|59(b}eae&kI-h*|pH1c4v18&)e0n4K zmV8bk;O1BY?oQ*|eHwG|XsHhQ|4qeB#J8jgyzOXKKK)0_x9K9^<|N{TX~U!Vz&9u+ z-=eaQ4^^G-7UW%6bH6M66krjBItjkdYEl0oq=f*GgU08DCi^V%u8Pu+$-9@+naI0k z(ZF<;w^-y|F*}WEEbqQCI=VNOynB<9)DFb4x`EajyVfTL_t45QBY5ROJn zFqINt6c&ZA5`E=YREecTUny8>iN4xH4`P^#iN5zh>#}|$9GVhz;kT5aTi9g%j>QZJ zP2}A|h4Ui4EK#Wte19(aNG;&&*COwJ!mvzvmo}9W0by3HRieE6cxfYfcT6LBH*t-A zLchstwCNk>8dX%PMZiv{%v6G_8%ev@@}j7;nbv{ga_xjlR=ogcBIrUBU7kyAO`m)Hd=%ywx28M9$ku z`bTv_j89ZMI~M1&2U>h~rI0cSlTDY(l6+4Thq3;oN7ezXcq&kdDi8`qTsfZ8rX}GtKTytMUKep=s|?nuoPkH@^sze zd_$~VQuZsKj4XGihek=fr1sD_f!@$%t)3LALb-r@(M~q(t*E~5>Y5MI1M3R)cX81o z#f9ct=gQbyw0ZvNxPO)_l!qZ{1!J+1yOi@_Y z)JpY}CBb>vzHYT;klg3)TuZiak>0cBFxI5^S$8WwxAGw{pA=&&*v7dcVrj(3_zJP; z$HK=UN{rJSVPH+66yP*Ry2+KXujn|@A&jh8`*~f>{v3wdIXYBqUTUa|WqcHsI0!eg zk}lN%Bju-+pBdwH24|*)ZefgMJq8JS@FzQgS!y3o=Ui5{xwDw&#GULg z?qv8$g*QRW1(U8sEcks2iw(xM1PK<4lp(Bz@fe4m5bAbbz&bxXNJ$W|=+3vepSX~- z?Fis?2ezkB0}wvg`4;nrRr<`UM-o@tm6Gzxc&<<)L1h(icipZ9ZsCDf4#*NFwhpJ2 zqRd%emr-vwyS|RL*UT1C-I2~>`L@d_HoGeA)u$e$g03U1T-MxO-&JPXcc%TAYiGg@ zOpv9*_k`eSREc5M#2xH#m0PeYn;vn$6G63xevj~JuVj=UeEO6zlmp>GxmZBLKWr!} zALX;{w6Es368|?Yg(2tP0BSR2ZNaE3={vUa4NsVkl8H!wPLr> z)FU)n`|AYskkqQ4V|DSy3vb{P`1ZNUW1=irS40L|{8s$EdDyQ$N|$tn38Te-MMf*t zNwZ^DB5TciGRbl|5@SNW?4dp~%hPHob|ML(mee{}4ir7J^yQ`6bBAqJ>7Gq2V>LG8 zkG&aT|K4zsk~97$#x-+jc8qH=ad_h5iyNP)1y5}B1iuCO!3QsFjx!J&=eN>*_i+fc z${hkG!44CL!~AaHyVHR?mBg-d29zo5l(S%W_+Dvntk)Jvh93$LV-L2SuzjY?H_-iD zTvMRk<#ey;H~h9aTXfbk-IZb@_huOWec>ksP9<54db_aOyxl0_?N{+#?eA$8#%FgN z5!>e9UKMXd(-qMrN8a>Bbn1Wgh6eQp=ny>>it&9jhFK0LU>3<&k{JmB;v@DNm(Bnl66WDGV=cN`vsUdjr!0v>7(DI=2w z5PQOQkqwfR=^Zw@tdr)0B#OsPOk>YX5E+FHZx56j8@{HFoHZRm^M2*{jml3Q*5|6X!);HD+SX;@S=h|FcQ}89pT6MRdh($$a>Qctiz4NtmQY& zCKH4|Cnt;el@trlIY#mtjFk$T}cuGsk;U|}$&hiP&?&w0Tl}G`nP z8t0P{0jdEv{~Rf|G=GIK)QQZ0sKXC`Du;#CYnHw%#_zXyUVd%z{eiDU`Tk3#3;6yX zyd3Vk-Svv^Z!aJ4`BS*hsLPG<{qkG*{_gEmzO5vFU)*oJ`bt1BO6guCli5D#QVz0E|OwapAdXw7yVI=^9`U9uCW2G5hp3(8egWt`G#-?GXYDCyHNf`j$MkC^ma9--$B{**pFM?^G^$}XfdYKMp>NWZk#UR z9QC(_b6i0Zh4&TH=@X{#}s{+{fM2KB6Q}meAd0BO88kqTXdQocJGx-pHG(HsUNe z68_wn)tzXM;NTw(?#807%92crW4$mbvjn@3)AC!NxDW5MPGort%+5=rFvzZkWuLMI z&}`@YGoSHonkrf|R{X7lbSASHC$pI9MJK8a`%DnXB+q!>-J7AVBoo&PN^<;7TOzz9Rw%j~j1;|Y@13@1$L=75SNr;wrz zcF?g`4;$}(RgSLY_+}l&5;4w8f`!&bO_#F`f3m6B`r1jm+xUMp#SZ|7Sq^|d8-Zp1 z3OOtZXW95(R}?fHIkHnG^y}ADhkj1RZsXZDlnuX)KFybW6lurp=J!433kP#i?wrq^ ziXO(#=a?4j`;Hl?uzf6@u4MfN-78o7>^#fK_ONkdH<@=`DfNBFgX*}fRb0v>Ji**N zj}0m4maIq@`K!|B%g0WyBcfFtQJ{op|1K!?Ri(i@RPy|+xaa&Wq|T>NGUrF|i{4d= zp!GUMBoh+n6GB0vmKrVa0szGiNt{nPcrEZWzoCky`nyy^gv@WCP)}RmSEbfnIhV+n zl6F-UZf|mi97p^|-L``$NjwGUNzO*|=O2$F{Keegrz))o@ato%auoqSu0E-JA%DKB zPb`n2H-^&MP&+VX|^4t42Y*7t3xzHj;!5`88a5R%fY zH-cB<3HzfqiXR_NWMQxkvIDie0h5#3(%~7VsQyU*WB?{VLP9=h!RQhl@#y7pHkKZNjgrk2aLaR z`lXhc$>S~I7reW8$B<)B@VM~~O{_(xnLUO~1ciPw-mK`Kh(fwwW_nX3<(E|cDsX<1 z%s*){^Z&Q_tK7qKjAk`v6q4r>pNhWjAZ`@4v%(>ZPsMa-=`e_U9c{{|;x^cnpInC< z#aPp)V(^3V1D}e)cLd>O#PNlaBjB)x#kv8AaH!j&D0@4tDitlGx*!^ajMe@D`$%&t>|qa zT_Q12jMhEGbWFvlTOVX9Mz2XwjEePC8+t*S(f@XRXd9FR=tGN?#x|-CH3xWM3eo=o zedu0GAG+mS`p`;nOK@KSe`DJV5h0(Zx;mp%ZzasXkP+q>c5Vq9aY#hyJPd z0`#F8k2RwYz5E-NOxS`xv=7MV@6d@-pEl3}(a0rH{yBEuEI0qWaPM`Sp*`kM6sqW&P+^ddE)Wx%H#n7|fUY(TmWJzML67A&L6Y^=4}Vk9|J< zXz4sTEEl049iO2j0_1^D=F$cFQ5!Eu@HkkY^rI2^K+`gc`;7l;D>tjqU->Qi(S}bi zLjyy+011(!^`^&)wnYDnRzUDrQZCSnJTnoE7{Ji5=Ln*}q>LTWn9>1}LAy7TC+L5< zWM0w80^XHaMUt;f)aI@snQu3}Ca`y^7MMYEQLmaQ%NN+fwix_*1|MIl*- zLXwG!*#i~T-Ff|`z{vL*)hALPhAgM8w8}0FFFF|d=)!rCiT`@n<~N~mm1tXwyHWDVhct~wbkF6iU|YlXteESWS9Vg8n!ja zZ){5GsRjoH)-_Mf*n>12G?g~fxMi5zD6dVn&K+~_=0_v?}uF!)@_X!7)GSE z@v4j_*zfYMb0C0QyYY%@z{s?!;l>=Lk(Sn%XhjxgE}(d2r1Iw3`BIFzARmb6O)(mG z#>x_H8EWL4tPKep&$d$=qQJuh6t$x^$UB>+WA;3KThY>m_i>{Ziy-@G_fxaH9W>$0F>=a``bqesqp> zlAmhQ@6bi0wWYuncviy%*2a)vnz8=ICNJG>95{LzDFK?3|Iv4m3_w3~OjPm7NiR{~ ze2k*OUS4mT*&$TYPi%^b5Px4*1ivL4o~8b zDj+c^)z^OznBuoAi^uk!*+Xzx4r$1zHZ{Tv}tWdE5@ zl-SH9`F+|FJhiYosBE*xUgvcU?xNFPTSVXC4$ZU~y=5AhWt8;~|3W%HNjGE zwr=ngtaY!dJ0mYHSnpKT-AR6qLH2B`>1jpBBRAvFD(Sl^G8d@D4BTk^%dQReT@v#7 zQ~1!9-D`_~O^tuWMPpT3=w<&4*YcJ?ZJK|zr{G=Z@!D3tp3cArt%^3s?2Fp6-d)TN zH*zC6ncwk$qWQ_MX*7&X=W1A;5$2M_s`K$&|dvSyBxO15-UTM)` zkB#EBD^syliajaP<}5)9M`iuc`K=Vo3hEpUY?eri?M@x?5hlai8^0tp)= z_d^)w*0@7sAP8$Y?S1F(Z9rQ9_Y!*bZHlN@u5oLw+E>@}RV&#*mwWn(-7O#EoO)eK zN_xs-;=tUM8;SH!@qJ46)b_8fXVHP6@tfU~HxDh%DpkASwjC3PYklkdy6*yvHD|lm z9PZ`{_3h&{8`ztgQ>~nV{U_zYV7~`@2qx_I5FgrGW#1;2e!^DB`%2s^uJ_os*w#T^ zQkdsk4b0i8c|U)3oxJv4%aZ#JDsIslm4xm{cfNWPZ`8K~v}hQYYn zoQVL6Tr4dt#rb#;}(LXQsQ@i$PuoS=nIlD^F@s10Nc5O{j5^p4-)UR5iv^oF|mr*}y)H%}Vi z-<+^3&cI317K!DlsCv}+-T|*|m;OG93mZOsMaDwTxuZCJ_6((6M|SAQrLTOa%TgRD zRpZr@>%_=hu-vJCs&eWJ7n9+gyeBX!jezHmzV4j7B4zCp1H%>c?w!0}@{ZAbrE|)P z36beEyi@u;TwXr<8uuA2aO6(frmVel3T@ZXR{pccQzE0J)7Esl^0wLStWKZC;W5&O zV5rEoJP~;RieX&n!xP0rwUkI#+Vp|@Z>G&5BiQ>{YfGO~u$*KCvXo9?I^3b#s4U>? zOp&2=TIdgKoQp$99DJ=!!I8&yjOD#~~6+ z+_q}7dw{(>z^EERH>+1vWm6NjPJ3{u95UQ?9lPhPaq4GEL)l+pu%uP}c0;(B-q8@w zy$y)*gF!!lZ&esXGg(@EJO$yXHt@}MkA5dV=aFIu$RXupefJ(UC*CCmOQ!TF%OT90 zaSaTK^Tc~$i64(~!on%@uyD$%Pe|NU_-Ki_%JLq@DitI%D10GY#R-7z_*b&K}QrFzeOZy2k9u*&1R6qVty&8f5vVbh1OyV)9PSg?4=M9EL$GUJ%hTls;16w6OJ zk>H)m6}~r1mL5mF${tugJ4e#X|DFknyN~QM{nNFx=62-ZQ3I`wLrCj9i0=@`-2TqG zHbsrs*s&!(1FdorW2D2*sf@oCmgt@EOj;T}6MrE59l2kfoX&F01uB~C?DjZLY7g$0TMO!3 z`Vnox^DsDyk&`@ZoZbb$q@lQcWs$S$Dw9&Ou7@8fEJXMKV*SdQ4kzTH=MO+Pp3+(&$x@9?n;9r`^@do0l8OZgf?hJC}{Kq3^VS zW%^|?Kq=L?He{7jBPJRBsH4T9(JEH)-f#!TWL$IN9Q?}skKAB6%OMa)T6QviJaEPm z9Ec$O>#iV&Kn+~}!+DDZ{zDacFUTjiJkF<<-(kcp;ve*|@?Ke0ktZ2{zZ{3Q#A-8Vl!@SiC^GDa^{F1JpmQU`l;#0a_ z%qREfTlbUW)#nmih%TfW30SEX=K;5M&YHtr#0%-CHG_d2_>!Nma@sePNU7XCpi+;7 zeUzub^8A3yk&zU0o4cZvEV(s@`?^)tBshQ+PmdLJ07Eo?pKxP=Q#Pv~=luQBpjA96 zXqnO%o($eyC!8AfD>mSbMCC|W4pjCZ$UCcoa^I?I-j!fe)}J(UrlHo6J_NOW4S3mmfSQp9yc0dlKK&Xor!npd{u~W?BJW`3+tfXJGMz z4bWi9DPltRB%py0LU7P(s9E2q@U=hJ-R1%=T5 zvid$$@2v|1q`a_pvBpSJQY&T>Adyxm^Jl)E^s2P3(We=xk9Zu-5{)vfXl2ib2Ef4yu1!F=}I6*LcrEBI4|wt_FKZF2>Gt58!(Xi(o_q0Fl!T{H!|9`4_P z9kgwc2=qr*Wb)nd*Ao4m5^XdJ1#?jZopL(N%~r~k5`B~N#3ob#MLS*k85dQ<7nSoU z;hT;va|@lX$Py?QQm5n4>?`pmFA!J9ELSjXp^I9rmnJS}F`*IoMe1w3wi=h?!?~K% zab$Ko7&D%*2M4_dzmjpa^~$RR$SVLw#f) z6f%<26f8n$2Xf&so5e{&EQ}rXXBy;8x(Z<9t@Aq3>PbjK9CiEykQ7J>-HwbthL`{v z_3Iyin1ni&(_Lij3DnFc_!*~8%Bq<2cRQX_s8$P%MIS3;NW`@yu!v(?wQ|Ey@k5wd zg>YXUu&|pTE`0=hC@#hM*eu zEYe;S@p|t3QvK7#(P6qn)+zZe!?kdSbw*VD5T%jY1)o$yp;>6NZHLpbSvsEOAC0Re z%(#B6V29#{H1{^g+BqryHJgY?^0C`+9)g z@xHI4_Ee3wWQ{A7M$Y)^hLYg(&#;&hNhYm4TM#7^$R*2&E)3f*jb3kc_+ z?b9CqI(^HL>8L^u!#VsEdC|qHpe7ML4G@~;bi7UCNDlO_634rIkbTbNa^#jV@bvkNigWTyP zlnuGTz7f3XF&L9=E{8Gqa>w%7o#o;<>!RHq{9(E)=zEMYAM@Hy6&-RpRtpAL0S5R? z?wlIz{d@h8C&Ta*Y@F7MrIJV~vY0Y3p*J3VqxRt4a^$lqf)M__NFpb;cSS3$mP7!h zSj2bS>%4hmZ5u+9paJ3q9-6`EZpw4x1KEc}`2uBj?cpDDP>_ipS;(g>j8GS01}fGv z+bBA8>eWIcU{q}WY^VUFuG)WV$P#hQ)eb{Nyhu$v+ZxZ@&_aET|dQY(sy@~j9 zEqW2r%Y;A(OJouViV{})E{PF{+;8i-(1(Z}N8#&5ns!^XVLI7KOu7(-b2(rZ=8n!m z?zbo;he95Z1E;38!J3-jp~R_mjZUpBa(8_9l|K4^Y<_|b&G{wb5OaPq-q=K}`N^cr zL+{3|KR-pQNI`Bus6e*(RL%A%C`I%Ti8E~;hp4l!7WmL;(vOWetP{ z5HVzUDDT>#p|r2SWxE`Ew1=PK38(Fo62}MHBMaoa<1?pz44kk=^XHh;{>~Y z)Wij2um}h$*vt9fq%Ha;j~DH9d_4DSCb@qTFrvS8v#*eIHHI1>QIh`$m%cL6T8R81 z{gBtT(&Y%t5&sKEoGeU2@Ged&=q%lRdzNPR{r zl_Hu#<4sB>jC%Mr98QayszQB_kC0;`a-$W^;{lP=iTkG&ihGTJ010Zg(ZWUtb}yQ%L-5uzQ^_yow0#D9I5*4r zQcL4$McS|KoaN46`Nzf(mB0DFko}0jnNN)l!-#(NGFZs+P4h*0ZB^(+5kDDY& z#_r{?$FMX2|jfO zvtM@xeXpm9%1e8GEjoT8J+$ZFaq4NWlg!JmpvSgFOhtsmY0uZ`VbT9+&wt|7y{`jB zVe6L9+%{7AVn%b+`+qO=qi0Dl?e$Xa`Hh4F*tRw*@-JOrjL zwk`#351BiVVhjI*O$4bXNR*!OTdUIGe0VG}BjKR9)iFfL>#72;%GGg1FBRK-ommP$ z5AY*UP0z%L4XsLZU>KHAIw-(!QO>JJO7#uXQPNA997{=WUeiQLe+S(%Dpx`O=x_zr z%Nd~Xqzbeh8!*Oq-UpA)6-7xcZq*&C$QvVjpv?83?ltdFyTTo^dvZsLoF8?^X6p_m zb8?5G7~G-6Cw0dQ+!5Ef5&b0^H~%I0CWvA#Q6D|=1C$x zaCG$a|Fq0T^*=^N5WTJCsT3sM*7AH(6K`vIQaks^!t6G>Z~VvjHw6t;nA*MK5!IZ3 zlQM~3xQA2g=bXw7r^CzYbLVQTu^qEgsdzkrL=nN}^i zICWT1tX!OMfKe_^;(^u3#c4YaH+FI21U2z(8hh}}1^G4=ACRqE9u6v4Zar))&M%=3 z#e5|BHhn|2w=R?qe4AtiJC6CEb8forZ{{fLf%7ly+$1%JqU4qZTV15vRSXD`*t-#8)LvZEqOKd z-hIZZSN@VZnBvv+0P1>%X^aD_;ML@@iGn}o)pV8o3|`htK5%3T@>tBPX_5R$^lCaI zi0K?&O>e&^^Vn^4`io!#^he6w@g}K)m?L$n^iLZ{onsXme%yzt&u#2vr6PS^WeI?WJ&Vo!src+cFv#tlmltxLg-yp9 zVUK!@K;gB<0Tc1YEvQ+3DdLzTDA%fM`<0tzjSd*OPy*usD{k>uN&X(hACkGM$rK8M z&NQ(N>MIFDJXl%n)!YXI4p7XCf|~K>u=5Gj@I{Fbj2jza+O%(s3iZYncI6owyp9iN z^pwExEPljU!o@76m?XFCXI&k}w41hUeY(8`Q|(B&dYxlD}-#N zWL70V#2LXCG8lRmiNJ#1WL8pCH449*dJ9-%hBQ z!-K}XJe6dLZYJjNSs&KGaI7htsFjo}r(j5q!=-gvoIfqQPl z$WV4G6y(HwBRGV8v`DOMH|zWdv-3FX36aI&$3ZSF#v6ZITh>`yBK}sbyrI^mPjyMb z^p`Tv{f;qGTb5}%u~F1ph#;X3FLJGC_WYWCm*9Ul+=lW#u=o0!y_p%C_&pkbwzYwM z*VpW8ld+cHx3t1=fbZP(&Wv|>_Rl=KFmt~1oe0juRs28{9GJU+iuN^o+u*=Ae_zT; zu{_T|m9iZn{HM!nK4@EX$VsNUhAhedwzB5Kbf**x4eUAUtO>Vq)*NgzER^{t7H8-u+umzv z2%JjQ7W~}&UB0QIVg9KxGg5f{kL$Sm`aE|>$D&B zcOh@AxI{=I-@Sc#9AU=kO@4B~EXX&|FkxDmH#8v+YhLS~ zr*g#~U#}-9cJe8+zT=TAr)-;`uP@lDEzO=f(W#RHjT|2H>s1|?EqqT6G-S-^NurHl zhY#v`ercMM+gy2P<-SN4>H9KnnYpXDd=)h;X6K=ZCH)8Z6jVAp@3K;AURG$(E|naC zq{Qlrl^>zh_Fk#u^JspA)82v)&~{vU?)(Tlp*ZMRo8(6r6-vu(oFBpCSYhTz@ap@# z;gus$}cvJ7v8Qujp)Xf5RtlUu%4A7xSh*N42cXK0I3}&*EBBXZJXc`9CZr zKZU|qqXi z+`$>??$E9LL*Zq-1>!3W&V_Vh1-4J(%fnS}~6m4~#j&Bj}sg^N@H59!7GV;rm zNq(6!^2?M-ewi}z%aloenKJUrlu3S>GV;rmNq(6!^2?N&`DO6PYz}{7DmVoGTnYX> z*cgA#vhe2?PpB{Wv(ChyuE8k+nuD_dw;_uG!XZ!d+cns(S_`H11!=8Tt;MQ!jI?f) z);+3qoNApatw#Y^KvEFs%Fq2z2?Fg00`;o+1WMxdy_Pqd__JE!&o+WT+wf?rJemq# z2Y=QkP<|0-(YE2cn5GJ8$N8_PrDlkm7nSo*4 zVhOEEL522i+IR^VTxI-#&p7@He|JsG{NRQ-^+rf33kd{BG+UILKZfW^n-$bWBCV5Z6nMMiEMF(`hY12r0)Lnw&?d*gT1p5I)fnoxfZPDu(!RH#@H-)C0tTiX!#_9hJ}hcfKJU&;JyJ?gf8Y3q3_wZk zT^kR)(4Wr05yS3SZVa-9tnNIr-W>E#UJ~m|IiQ$ee-V8c6?@|c7?NNoylcX=ADTL` zSL3yk`?WqG+A-`m1O*X)gq4LD&%O9;r@E)qP7tF6K|V{<=A!+=0E+U9?72!ywn4OH zl$p$!@l}*;%l0cJ*_b9uGPz^s`{lJL$!=;^Np?A>SRLUj<7+Se2}$SqOMTgw`m(0_ zvVvMpXiQ%=usZp?O8ON=ZCcWojg6njN7gBQ+1Lbq*^DtUg;_Tf9uX|R)R+B3^|$}3 z`m(98;&Jra41e^SRQZ|?7%RA2;CIsR8o_V- zSH3X(ih%09J`TV6yrwDq4&{ws!ta;x+t7ghw;B1gPtAGZ_lBi0_)X((f!}9-+X#L~ z{rRHcxA)*U{7&LEP2qO|jP#fA`z8Fg1i#akofm!|c{v8ZF76iiHGb6yeuFQy2)|R6 z`{mX+l1GCvNl9z^fn_-;JB;^Xo;~9U00?zh*FO%>KbQB4MKD{m3i^st+egYg(^cvX zCg``(4}PdsNU>c~HN^CT7ipjQQa^|p?_WeeC{W-IO(T6>a&9K8l?W9HnXXIAvIAX0 z?r;BQ9J(Aptb(r2$;DXYdg1Wp49+Dd-C3hAKotutX#|y4#@%?v zFndXGV!9{r`S_VXI`=aqefZ1dci#q8)Hl#C`j+j%@ej<;vR_N2QwZ_2jg?(zbd^^@M`ufz#t>PCNI!wI%CZlRuX8 zOD?PS&d}%!Kfxuo<7Bp3lE1EeUF-zo=o=~H0H5j+-NU#4Nca-vu)WP3;qYIY*~Pbb zwE129F~z=VHF9V3x#KKk!WQdYkq( zEN4`djCU*U4Kcm_GTi@CjLm-{5-JKCVo}@6hRaaXja6KVKdThAaf{kPHaO zG*jE%-X7iV_n&3E$r#3Vb5}CPKD9PsyCvnbVC;?ETiWj5(ABv|6&(i{``Qx79KqiJ z{JEcjU~QNjRs`!%`%vkHFM;h)$ot0>XZ{9f`G(jExT*%36f1*im=x^kd;~gcdg8NXZiYsmFa7X+zu)@ z(k;3&wVVU0Q8y19yH+=|IDg{V=5fJ;>P#IlMnl(<4&FF_dvL)dg$r(9Zrt-<;AAV_ z8HCWC+vW5v|4GcA9iH;rM(0l1H$`?I-NtpHvoIZtVTRMHA+~^9A z1GTku`ev_cW`V!Oqs=eym2@R2^bqtfX@MvCGc07w@@oGncPU)ELJ>;zpFeISf4Bcl z()vn#fue8cUEuH0V@YrZ#~R>04|3yJum3xdn=`*D01GpE%@xt*wSlQ6O0wzE?q1i- z;(m5{ON+Z2sFcNB3`J|SxQUePMOMyQ-HD3!?KavyYB3No2i5Sizq-ivO{GuP7e4== zy1whXM%VXOKvVPU`__tP*7q?UY#w+gDX@h8L!i&GzBm3lw!UqIl!F-l@JN&O9rbk5 z`rdq@;4AdY862J-n)GSlWTrOSxL_Ln--0FX%84%X01#eFSmKuD%`9|p9&LW18x({d zFjhgU8ZC4JmI$+g799UlF=xAtp^I2&;B2h`}}3m}A45JZs|C7^<{EH6gwuhSwPSIxdl#6y2jNcGsc>2qp=V`oENy%ZPqf-!kk&h zcxAo)fhA0AP<70)zq__9&C zZQgB_D}wK6^8|%|tKEtTGlWd6uTpUZjc~OTOTIZ60)3?VimA0q+u_yYMFf0Lg^iCc zzv~W<%Qrb$dCwRg9_K!Yg^YoHjLkA-+%jHnpdwg3JuIoipQd@Oa%YoW|bk%IaChbJpInE&nuL0(pJn7!dG7pkAE@( zKe~dJ8GO0XY9y6l>L7t8fW2xy@}VCumMh`tme zFMl5dP}`vOov z-aK)daMM*6THJI;E$U=BYboM)AxxTRW;6BR_K?5s8pI3%eUGyE>&jE@A%ER-;jeo# z;GvksUssu3dsk|(lQ`KfoOU-`opzaf5^fN1)^?9_&|U0@&<($HNdBJi-#u~Oy*8Xt zBG0>zdkh>Kvj6=xoPVwUyKCW{9^$!h8=zS9uf>GqnU>HBH}|zj#F=CN*|GewU%q__ zXJSSg+6wsqX9ux?mxPbFm^1pstB-TxhT{Z_RwdjB+NK6>xpdoxP!|BMf#_x?rzYI5%p z#r9qy*3()EvEGe8R-|kp2)?n@>e% zlF-J2giI?yN0cUsEuAXYv*W$LguW6;U!|B|{u}7aXESg+3M>_!zNWts1-Dn?!|1p@ z8-R|7zV3w?`uAnB`(q3wT>DUcNSN|^6eQ%~!{|sz0ifeS!tZS>_SCl5cj2!F#YeXl zyI+ffg2DJOItoq$AoAEwXxR<&Slk@&SZJsD9h4`RU0WnA#-aVX!?Ww-H>s~99<1U$ z9I6Ye&;mni7d~-=0a``Wa+r^*m9G7hmA*4@N$b5mRNrN(%KP3q@}D#x!>2{Ht)(#& zCT83_7oTIpb%>K-T%MF1jLY>+N}+}XB^Vygg*F6jpL&*(^<9IviFOS-8!OU1=ioNP zfmgHLoGx#4-aFBv;qvPPf1Cmn~VO9!JFBY|tv(c7faEcj)9=zoh z^H`PEeIo3afvxw2@rPlrM<|a-wn)`x;7jic?@HL+X-xLDS@|;B9NQC~aJX&3Q%)m2 zqGB`h9E%G(mb$UbFMm986xHjmP^PXs>ZZ{8bE&wn4?@WRzy+X_Cgn&7wJ*jJW zdlg>}&^R!)T#uI!XcaX-&CCzZ3hS@1-x}w0LwMu{l5bQtE?lq|e}LtOkQFsEXC%P} zb!&qAJVbfO)MC(P?`F?xAY(NmaKHBwkWnNKp4oFdO>R2XO9_464g;sc#H zpFv806Z1?+fQwD*$oN3(?jf0p&DmlxE8+b6c%d+c^u;yP>e9Q6HxdHQoeD|qcSvei zya(jm0D?YQ@lDIrz7bVPisr5%E=?y*AH5$m?YoJ5p_Q?SVc)_QhOu*DiEhdBZ5H}I z5ijTXRizCa3kna>cW`PreH;Gx2SSiZ z-oD9DernwPg&z2`x7t+sHaufh`IaS!rjfMIM18(#n0#uqUZiZ%h|}seIkc;uZEfxW zF=16{kKam$G}~K_!yEW#z6ZKSv_G_;7~X*f`BTwyMcsAy^Ln%b{Hc&XJG00M{zQ=C z6Y<|0iT^H%Jq=5X5D`Y<&&#J+__G;GQ_p(&<}m&oQWVLb`NHsgOssUoU5R%_vnM|Y zZ#Ro8mPs=Op{*c}NEhg}dmYi+2dgJDA^hTk8heeMNV(?H4!D_EEBOwtW&GMcc2%Q>ea( zwok`!nVvxx=xyI{BilX`dN0mDO==?kFH24@+xdNQtEK$vL8i-tA8h zz%O3!{@+;-)K6cn?r4a<{B5RvFK7#qn7`Hfffj{^+ervDa|L?B-}A)%Mq&3G!AnkD zz()7~2zmDOZDI7Li15d213jVB(VsamEj(ZMm*#wmu&mbkbPOW1$_e$%&~gv<4~zZ# z#C&>UK8>Wmj$^~<&!8`Am@=~JefvTJ?=ldh5O^KK1zw7|zjVUhcEVp6{=)UkyVq}N zgx((96QZ|mx1ON46ZWIV?+bBSnM) z#0Q;#QzZyGHxcJXR*c&u0;(YbXk15s+{~QR6*J4>c&mpMZ7|pHheU^>yDnt;yZL2tbaf`{)0Ty?=I{rT2G? zsIT|FyPMqmOaN(e@5AGRetBKQzMdlDg63P|g6_Ts3Ps3Y(%^9~p5}y^vi%-UfY#KfhJrelryXGSkpS9Z4!|TWAyHgs)=P@0hHv>%5njyny zjzOF~#CtA+JYPOei^Re5MEW(A{l3{Qz9Lf!on81)L!uYLT zc@@q`zmH(LZ?y$eS3=O%hp7qfCS$52z(in*0hV;Z)aFWJ$LbH*F+U7nwEr{SWnBTE z>$_Wqtepa$tH>Q!O{QZQ=KlV;i-aVv$eFpa$$ZoklKi+N54bMlid7bbb%x}mmQa;HfcC7dcUe*knYF1ds?sS@|(fP?MD(M+|8)zAlz$o_{}d zJyLE#*NtG6=;)d`p~>j#4j>Jn>vTa(Ve-D~;4pm2`0cP1uKg9_Ju2h2G2WwM+c4{J zD72&f-Ev%?JWgZi#2!w&pMcjWKc7uhn#+UYep;!p7&(M2dO}IP@ zY*ixgiRsh3=6Iqr^0>3Wc#K@81S&E21v*A;e{^C9h5uu8NjTUtcH)POo#^uSv?;b#mNlkxHhm=Xhdck0dPP@5*= z-i*EDzND<=6-UCrnSFc)PTrZ(H1m?UQDcPSKkdE6`ozWq8D2;fU1h3c;(X~=%hbl% zFVez-prX1(;7WjLS~FHX=yU*{LUZ|VF)1MBPjYqvDH^Va}KlRIyQ zLOXkj5X_zVV-?Il4bTO%+<#gLH%WR$2J7BWXZ4T#(bZ)qq7a;y=WFQx!=TIF|I57D zTiuKDcq^E{b)xDyoHFsWA^x~dN>-WOGarmN*dO-?mu;1rwcPHRi+2&tU=x%akV%E& z`L>1o%=Epw{%>E<>AX3ex+u6LN6Fe>RIS){E4F~rMN>S-TG;Q)tF5g~uL;d4B`Dux zPN#HiqW7@P8JP}MX=IOPcxc9lSUkk?Ar235e2B+GJRh3lp*bH~;GqRVEhH#e)&If$ z-`x_?~EB?~HTNKX;R>OKHH3ln50%!nCw0o69pj{&et? zF!`+O2e6nZQR16r=lX7h5delt8cmkhRbq2em*>o^XtL3y4~!WF5lJn2RYe?~Wc8^+pq0mRTKn-a~;h&J{6t-O*Km^e77X*u<+yqb@06bFVy@+|-f zBb#gyE>AJT<^7$6g7^=8{{KcVd)_v2RjVxq?MJ7VEjKiZD}!Dh0FdLM7yUNF-;rmu zw=6hV*sneuY#h~O9C!facyMsZ?`^Eu`KF12gW5YF=IF+X4c9k{0)u5{0!V`_^T*!g z75)pY$EIb4@sCv>uDb`xp#NA+cO7Iz8M{I84Q^tTu_=f$HYJ%c#V%~xIKA05*fZBR zB?X_{^>M?WAi$WhP=B-goOU)5ZA_EV#`YrG*pFU~(Z-I(+g9X`-`U65F8zJB_x8*; z2Oj(n@l~(=b3~&N zSO~Jz!;aP6YuIpIlaVkJaKh+cDT>fECS>XiV4?qu!swsIC9N0cUucfrZ6gAG0Fyz! zhE?k4g@%Ne7y1eP0cAXg3x#cB9qxW`>2b8Cp-N%4I5XV&&y4?G$N%r>iTlAfsh;iI zRe$z&1YJVxws?jr%kh4nhc#b@)bhC;r^}+oo3~I_U5@uai9H( z^Svj|_ey)cj9VR{PjpRhfc|S{k{!izoA_9ex!O2=F~K|6*X7=18u=L;Wz=uZ5%XkIUQ=n z3h~v#UHBINW~f;eQ_gnTe#S;dKP79KV!yO9=YvxL442@YIuRETE^{cJuc}q=XCnUW zxnzVD2>0v;8|_yR?j2Ly7HtW5Nb%(YewXEHmoMC>Gt*Y3#PUjw*pVm%X7g^thKTkT z6otvFz565uoRXk<08;f%aHyV-ZF%1Fq0uFqONr~t;VPoti7yQP%uq}oRy-9cT86=y zBfC(1gye_L&+!rE<7IiRJBkaAjzjg*A7M}mA=Wa)K`!Ev1J#SwqqzUx!+>iFAxyfeod)8 zv4v7G$Uzh!Qc8l-^%8q=DPJI^%MOd+Ze>~@`|JfsgONi!4KP*jAb1kBP|CiJ1G%Z* z8{lJfGW;;Ga_fJjWc95`zQAlyG+msVRWvzDV(0B^NE40Ro@N6U0GkduXp*n-<{hD z6Xyy?uqFGiW_{s44{`5Y-q*KdBTw-y()cs0d?tV5V?dZ>qD|U`X94JX)i)y_9Urba z@k&(h0f7(!1#J8)F5f9-Kea&OIwcDi0Su!!bUPiBZxS(kV&g!azB>|JSwGr~H_?mAciId6DKyF* z!S{r2K(F{UnW z(ADKI_UBK@^Ibg^$Mq+jf|f%d!X2DGgecAQE}y7bTd+mHfxE^F^L&?$m0R>b%Psm- z#TNZP(F|7&+Wyra`j4M>U^e_ ziqve8n$OfqrfwIh1tPVOsnytH@1=P5%|siH6wRdwx=68ouW!%0Y{$4e57~>|d4a#E z`}0axIrrz6nfvoC#QuCG_vfbww&sQ8Sx_V<4{-TE7dzHA<&VOjClq^1>YZV4^e#G&(0?IL8!E|av$WO znzc>H7o{=zvf*^fmpt#3guweiJ7%<)U@Rm{p0_ALTYyZ=ULgDdF_^-|{Do+x@9Dw= z{14#(-n2j9=a7{hqUfkl-XC_A_!k3Jj$KTc(nhhB!chb27$haG4cXBGo|h^G*oCM9 zK{=r&fN@caZ6#`UU=DYm7wQt`EBdqU68e$O+d6(Qu@gVn>tSVeu}n>CzxFuf3KoOJ zp4O|4xK)HDwXS$>NM1r8Jz{q>w>vI#*d14=*d3$NICD4#=40l_$1f)p{C@+IuSu~d zUhZ)Dr+|s$AG^fRpfKc$cMt@_A;qK3qUS8sFpI_A&Up(8bwt_Fj82H!$)r zt`HqLi+%+90aO1HT{~N@S=W{tBD6mbZ z`|`9tL&^Hk?s*$92m4zmyKJk~taWzJi+Fc=54pTwD*hrMXut5~IVXK<2;uP0X`MW$ z^&cSF;m=b=f1XW>Z3~!E`t$TfbrJqNt<&bT?qOfxO0&&z^?*N*E3FwG;Lqbqi^T)% zAFi}GJis33N{hz>{CQky&G7(#9#>imJm~&BKf<5q3$!uMxX)18jumyC{feK={R)dc zjy}-kx<5}pa(h1qxV?7?WI*q^lmY!xL@GuuxA%Oeg1V8KEmHHDTFKPyBDFxI7BaOO z@}jrt&NG*S8S>%~gfA5T)E-M08Atk+(Qx0P1fnvmc#}FfkoOd*M zx{x1H;Mt4!Qeqf0POK!GCQy_6-TEkrg4s$*PerAqPU%}4qn{}LV81T?>;cOD@6wMk z-&l#{ZuFQ`05u3}rC10Y(pG-N0yK!_#Y(xfMQ(vgoki)58Oa^5txA?UW$T2bm@xej zAdiGLfcYKdUA|b>Nc|e}3}TRqbqmV$=b)YEA=dO%Id>F0=YUQyiR3z`=2R3rpTJv8 z%uKLnVzF~B9>oJa4w+kuU*<05gVqjhQn5n!XT&`!uf)pKQaVDc`-eF*A>-3)v>evv zeZ#p5)JhCnYR&Dy1`3EYbpYbOn1VJAM>zPmKjt{NoWmL4 zAs=fIF5LHGrd54^)vJ6+uWGeeN9JH1>CK0(GdxZ4Drsy%+sGEUugAzG=p&b`UDBQ{ zfCk=_=6(kf2~j7Gv=e(GL#p!6+IGsN_$J7H_j>RKZ}}p zaxgL2o{M};joJp0zh8Sj33?J1>PR&j)-SRbMcu>jI2;uP|6l-mPzQ9Q3CI|mrgXA3 z`2b^S5Ga57kKc-3P3z1ds?uTso&}SeIN0pJ>RT*WLiHCrw-YE4Hdd5K9ZHkYYwCn5Ty(Ooe~^TLP&>Bp*#z6l{VPr z>#F$1gP!(=5#InBe%x(EB_D}O%JEUKtVHpVx%LZ^*{}Tx^vE(rUj$#KMW~`hsP;!h zEeExeQqT$ry;Ln9rMca&2r7nQXi+ojp0Hz8nfnnTdpj<8c&@3O*&Gm6-`^w=++T+V zrko*Zpth|j)>IOhPm=N9za4#2eM@3UIQ0_15{|oCaldu=r423t4Ks$abMV5DE@`KI zhT}07&2o7UW81*p&gJWE8QIH_!;xJwS3>6x|B<-jwKUlsV|d#IM~L-+mMq|XO-qaF z@}1@KO-mzeQ@E)1vO#sm_v=J4zN!y1RV{{>#*}#=AkmsvgIjUK-&8E}r-rKkH@;B) z_vUMOjSy*6zAgna)j2jwH~8wHQV-`>Lz=2#KI=IYNl z{ZBXtfJyXXKm-+nxoMIbfHgz^6fxO=F!iNau6J6d>a9}YWRBda_CybHgda{j_<03C z6`qCc3MNz($;SWr_`g7@=wHaxrP&y5ZJt9c^X!S7$J(qHO=38o1f?Q7nZ=O0D4h*u zs*=JboTn@skEvMDjJ}f#n(Q>W$np8aIQ90G;JZm3lnTgo0m4fwBxVzlA8f-Z3+Clo zZJFpNG>}kH45Cg`VRGG3WRK8hv>!1xQYJ?NXsyd6U1YybT!8x_Wx7+We_`hk?j-G; z=JMTw9^R7-w94M1e%OLxUrq>afMt%@R4N2gMNb4#K1~4r@hQ6H`AV1X1$LaqXAJlL zV1|_evSVm}K7-oUAr%-oL^v=+A0mN&qgMs`?}z0&p=f;pJ*Q?sjIGEntj@UO1#)E4 zv36+av^4E>kqry9hSy}xj#p9ON)`}P6iN@kiz#pP{ex#OG|3Ib_ni3#$J1FAhe!)U zsa*LMRZ|L7c=*GA!j>%C2~Hjn_y82c6}0K^r^D}SLTmx}{mi!z`~!bz9KJRR;6*(d zCv!W4^1}xZo{D61KcgdZEcJ)+TdMan7||oyEu~_Rq(oo*%OS2){C(#=NQG;fV@Vu( zs@(^v0-nQ7y?vjO87WJ|HSgnO22OtUyMIV zzZ9<^Uu5s|va^fkn%R%YY{4J?zMsi#3Uc}NB$>Ss3HW-k%q}&vhso?!GW!LYU1?@# z$m~rr`$3t#-OO$;vo)E0r_8Q4vkwX~@Q_O!@UwGMh>=zHTG4IT6e3X)-%gX8$lpV2#pJW{;HFip<_Bv-8dDzA}5b z%w8t53(V}(W%gK^{i@6^G_z~T&tA_|nO!2YXPVjDW%eAIJw;}hF#9B6N-LAuPsr>W zW%gV%`|mRQ6`7qUv*(-H9+|xm2`=wjr7Y!(zxRSpF%QNR<1WtSASomiAptF1#cXIg z=To=!QDOFMLXw!KJcU>#VG=5kKl$<}TmGcUAKrnBA`bZzBY&z1Ak;s2g z+;Tieo4GSRM{Py$bYH}#X)B-*!Hak;exS#7Ld(8B-)QP^+0-o}A=o^>B6eE6KPrwgb-35Jse0H!##9phmdlW#y)2Wl%_4gz6*PJ+~%YU=e2Bos- z+~9@S`NXE$&T396<61&J@Gj>xh_sKf=;`KUz&y-y@cumJ^6u8gv^iSae`Q>^7$MXX z#^h80dN4!r2|>G3bXY@E_^(D_z~(+xm&RHbzz0IueEw5>s0Vu;4tpy1E)tugH)I`` z?{zXv^xoVDN!GO9Je|;JZ=Pta_eSx*eh96q@$j#$C}E6H&qcoyFnqFK99{m?ONo9l zSGxi=prII6ruD15MWg*HZ58SlNwY=}Xn4O! zxw2o$X1`cgju&&ayHFGQ#Z>-_)-N(G`t<~UqW9}7?4UKRU%}>$_Dee{)UQ;us>Z{= z;r+@)itJaK-fq2=7%%2(&!Z;vi{IAQueq{clrho!)wap~I;HV`IV}CkMyqN({2Sh{ ze5A;JDSEs0QlekX)mF!ge(~G-`b9BGI;^)}m*V55jaP5f)`+yo1j7qy0sa~ez%?HJ z4e!@jq{x01;EDhAQlekX)xL`p{o=R$7ljU|Ib6Q+$A9*sjijr3>?Sl#GR zA=*CHz`)X>Z z7;PBHi+6pd{=`lAzTMBpyynYz3|TOB9rSdBJ{Sx1`T9;{>47L6IC@AFy_*S1`saV; z=a>ku;>7N2GX{Bc;62gzDi(6^tBHDvNt6mGIbQ$0N&g+8{|?oEhv>ik@vEIo(!>SE zzP@n;xK6xQX{SER-{48XgkbYvT(DUXQ}PO~Am?x@_bu9l5d^>TM_?RTLUYJ$EsYmP4I8-bUrZ)>;4~P6SX6;EMNkuM)i-qmb z<$ISp1zW!xodii@W*d|W_le$TN%sjkqhbn9y=nFduZpQaBQ8?Y+hAwm*E9ZUa2+iDZdC0Dq-F9;s7Fa}J#*)%042YX2W688L+ z+9QVjsuS#2TzbQfl58*){FQ{s;8P9)T#it`krl7qj&Ez?oVtbEp^fA_XjV^1)rJV* z*bhe^EW-s%h)A~umVt^v({XP&?a-o;rv$r~uzd*vgs^v_eXw^nwS7f)Hm#_gXi(94 z!Cu-2$Mojz5fr8UlkaRU{NFmDZrOA@GgGw^WYX`cf<{kI=;fd`2IE5;&-;5pGhy}u zj{i_O?v|0RVb6Rm4Ew6i&vH>=F+o5)h&YD-rp11f6CXI2TIU5ThZAy{ioWB(rfw`*oykr^jB;} z18e%H*@`Z&=?{btuZgu4jUEBvFBa|EnSjX;-0P4shrM%%lmeR@Wu_HsHu0+1-0$Oc zxc2=KmQS;}|Bcsd?Q8K0x_bq$soJM}jkUR-!<%D7UWuDlqx9 z7*Si0FrwV_Kkr-j`|qjlNBv&6`2k@#ABu)p?Mp)5`1`(cSNj+(1ub~XM#KF{ycCyL z)Qu{~8vY0~W7#~;=tbacIp+5uom1Q))(k(-4?zbLkj4@EMo(LSv;sY?QcwFk(uV12 zi}kcWA#ISJ_KHli&z?+gJ%2`qo?c?4kCN$U>*-UC^no({6g|DbNIzeu+w^qBNN+FG z_f3^;PBYSvVapfwexau)8|k}b`f5Er#z zUudM?FVpYW)932xkCp}|ASZom;1>Ku;di(q!b-eB^&Sgx6_^xTgBQ8Llfo9?AJl7i z#BwE0QJx4^`U(R@X|J#z2tC;JqirE}1s`IsNcdr=Xor7_;N8?BCuk*22o5lcWkYa2 zd4S&*Ef0RA{r#|%6-Gsk?Uqh7zBX!}g_=oPD>RG!Rm!JKB|<)>JqV(|3|4WM6YKoT zU^9RVA|4#}YgXG6PgW`hI>6!ZCTS)Rl8DX?V*xjc!!h$*`a-6d77ISm*Bug0l*%~P zf$R%EHgB&v*b0HgAcf!Jvq3F!z69x)V+zZ4o-01WLyCCtRHP_yw$i9(E~Jv(9RI^6 znu+PI0FPo(m*|pka|TP?zEQv+7o^~f9(bTw2#{aEEt@AmHFG@hyrg}wyUBhOdF zd%EeQkm61`kY``GQiVxr@~IFUd07W1wui%8`X}l^l-L+-8N5{WPp)-!KBjV;*B1v5 z^inqzCLj#%5kdn-2#412@-MU5i)qH7M-+BAZ+AKZ&)`+@{D0V=xpH~{hpp_}>1F-Qa zEms+-2kgU3UH+RO9lt|fuD4odqqkG-2UPoc8xO!sEiVPz-e(d@CCYyyliZ01?ANZh zpTBGhXmWqxK0$=XV(pKVs{YGr)!A$9kCr8r9k7oo8)Lutq|%cP*d1-gUxn3FDu9e! z4`|(%Df9~EznMz>WHzm7oRLZ^@juPA$OLb zkh1}3;@JiebjRH}zzvBI@6rEPIg1NSR5|-2+dXm@V5OtqXTNBv*i8@)r94u|=F-;8SXIcThNPAe%NknsGY>29#)O(g*Tz zVun)mftQJTG2g&x9=uvQwT0vx9QO(FjYuNXfC)wo#Q7(Kv`emxAno@6kN-g0WhCuV zN!n#N&lNi{6}+`@o#Oe)Hsv$~$7nY33@~f0V*g;3=evG2n-_wRVw4TrgCO7v?E{K| ztaA7_Z$e8aVQ8@1zfCSu)?-B^wT^oBD}PRz0@y!0><!34N%~De2?sG`vX*I zsT?Tiz3Tl0M9{vPPV(x)bJN#6K62Gd<#4|~q{LpL_}k&!(6ZJF4to*Jv10pjaICBScEwgPI5xNaA;sS*0p;-JhXBx#d7yDP->%Gp`!GZ0 zmX+bVpW!M`e_#Z&d++k>k_&p@w&N+qK5xBZ)6j%c#a0Q%z$w-XAT*Fr$#8&PhT%m* zB?^`W4q@Pxg_FL2V#yyDJn}Y@q$1=Si8d@Xx`X8D?W>g~W)<)R?D8?Xl!TlEitQ*X z!imAMeWxo+Ig$u8w**;-m6ivU_piC-Z}}CUtE-iC_NAL*!x_FxCA~sP zrUPZ^htcgV3S6wq_M*>+mGmGJRPQ#mY~KZH`nEj#yzk)~-yXR73`kFP*$x2jU0r@> z7n~u;vwf83{Youc)=sr8S8cmh;2MQ7Odqo%xE&vrAFbg>=$Xp~H}}J8S$R8`ZJlZh zsp4H=~f8$Z4E~sK}KJdQe`}pvossnQa>=dRpNpaumSw4%Y5!jRt@%zyrj}) zt9IGeU*^lb1i$dvFN06qhXDH7Wj@y>8d~V`?oezP@}ua>XRg>`&g#LwVV7)j**;fr zA zFo!OS9eK%imu)MEG|#p}z)k`&F%aDzXD<5Qu8} z5#4E-=m;O>mP#t!xBjRD?-d&Zk!i{2y8iV0JQsFV8OT^ znCdsIQhas@CS{4y4Sb3-S?iRt{b(nu`bj2$CCOH+@U{}%RSr;b6Z`t?zT93%%67ym zw(nRvM7Q>NA4+$63FSL{hXf0hW#!63ljCsWub+K^UGaVot;@ck-Kq8k(=Vx2%Dzfa zT7KwnO>V1HmYA$&pNHBuDri3trKA&h89EuR?Ik!a_$=@YiJG5P#5oB^ zep(#_Ff48om=t&o{Om$+x-7F!$tq6gC>3#QSwuePt`+5t7oou!FVg1cDT~ATilXJz zWX`tE?$B>lUpvD4knqIhj=7^~H?>FyrgnR=lTrm#eWZIhug9iYmz zN$4Z0cSA5XuXDNTi*pY4w%(-ry1<3WUi>ZQ0T*zQ;*x3(7JI?dtPRM3K6^Pbk(8$Trli0YYw8bj!WV_yRe`^uR47lJuk>Se zi|AIgP-e54(9rHlDauqlu>HljXX1>F2}_=jbHyiK+`4(u)l|vVtQAFj1H&OlLj1|^ z?8UiM*0>7Mo;rYO8Bf@pKrdZfms2at#FXGnX1_Y1sOf*D`kJd=Tn+&2`rtxC%h0BW_-vaJ68tv2gEoNu?R?`G}cmQIeh21lVo>L|SNx&Pw3Av5>Ee>{Ql z%Q|pxt6cAPCl*|fAw%&MJ5#75_!c{p#cxJtOT(H0F`#(gcFx6TivMkADSz?)3VyL6 zRH<-7s8~7{`+6w8D-&{jsc^3Ip%loIGh#jov_SDrcNQvW%1lD=FBTBFNs#?sr*5rd z2BfdnJir&oI4;-wwF0N*7&HY-!&?)ul83DcN1T)Me78D+E%N+-Y^ko_V|NtGW^}>& zRl5kN0eb+YxG7OMaUvNba=SB|yH`psm>5F_BR{tGvRY$n?*{Cy%*+I#(X@cXZcH4E zM8%hyizpm$XT056Al8*Q>S0d>IB~8*EW6g>Ni+_b5Q_CXh#w7wp760;86;W-ZsE0M|F=+6+Fy zc`90|3(Zn2Prke3Q=+g!>o7xXeiWm{VfK_+d*%S2;vBs7)DDOo$=YAodhbpki|01p z!8%QaNK6C8%_Wz4gFHi&&9i3tE`OhFwd`9Qe8e_de~?*UoP9*5c+BRJX`HVE{qexG zI4_Nik$uzfcUa#P{B`wph@vq=eAD}m9pdkH0gtw#v4{{3db;+TBej?NTVHUwzug6@ zXW3W|^H>VPLMYTucsl;oDGOJ+JF4DhL%goOQ#qN8rNwe8z{CV@MUPbPc_K@kP`?@p zw3BoxQ*4`+S!Du%=cg3=eI1Z91T`tMmN9X#zh_Scr^E56;1qTT7yLze7`V$y#kPx! zn=Aw&*@;}$yGkBf&fkt@nQ;iw`=e(k4lVyIjv&&lczWO^g6gtQucI1o>6ZH_fvrqn zE0f%MaS3p9@m%0C6L@oFf>m=bp3k&Wre!lNpJ|m$+s?ECrWG=+8fOVFHqRlx!UGNG z>vfXbm4jaj`$1TJ`ZuuZ)~+bpsb;Nmr@L&W7?1>gKq66={t3>DJLZhUu?5dE7$(*i z?H}UH?K>5wl1b;f7&~Rn5PzQwVCN{no)2(W>%fUcyq8WDQ`=_MyBlR)_DicT_qzKQ zs=j7Je6GF-n^J~Zki(U)VvI4XgPb_wrhlRw{7%K-W~;q%u&d})QLnesOwUw3xlRSs zd3=vpV@nDreK@_tSr)X-z6&wc>?=-P-wOT>O*g$!1Qbxz7UGKRVG&o_{IAIp722w4 zuy=Fg?py7jIWiUw-0z@bRAye&q{k)ZMeDopn9`tLgW{k9Nd-!`;e;_512RzlMI_N$U46Z2u4R z`>U%kb2L@Izcz;Y@7Lk_y^D#rA@MiV@8?tH!%W+Ve!qIlaq9PD0oS76&#HyDi5s_sUH1)s9B2T#oBunQCOj6O~N|b z5P;>vog!qjNG}yBrVV2u?k}t@59J?kdEsA!EdpQsGIF6`89PR?Prxz1QU@Pajj`Xp z>VSQQT?7YHyptTk4og#@b7_+{i47w*I29HV7qU#39O(pgCrYqi?^MWs{S&`N{JX0f zuFN;XK@*+~_J)1a{ti?bWAQIaYUumR44nef zAw~aKKyUM?`2GrktYxtC31qF-k)_w~A1;phS%HiKkZ}JPv{ZBz)-~o zcyo!Pm@q~P?)jrFBkryCDbJpW{lJu*g`79Os3 zPz!vPg?R>}0UOs`Q3#$lyrv|Xjyo_-9nAIaQoMmYuSSz%s&;IDm}q8*gX_?xv6fW~ zB<`UfA#puu1+9-GiBVtQJxrT{G(2l~hI9L7{`iyra20Z1`c&jBVX1K_6*wE8Y0qsW z$I{*WC1w=xb9C^BaxRAI*c+OPziRM$hnuLx}cQA-wmG`_`8J}Df}GxdwW?3em3VPi49iE>=DM^p(J~8O=GiH?VbI_x+G(?Xei$j6W zVXijr^J^78KSk;j_D1q8HmCrmPPt(|(Qhfnom#75sAhzZj^d+W#plZumTW zeb9}GgOT_ft`AD6@HW0acy(X7$lV0;DDvuC zA6$z9y8WL|^{fvrG)u8O+4hdbQjhL%Ykl^A?#KKJ`)#ZCHjUp3y8jydrmx3OS^ppK z+sbu7QB&9BtE)kP`!|I1+hQheLE>-7Zz){pHO_BYYmSrOHesP<;kWPhqbqiHMey4e zzQ*v?%5QIfM53zDKDzn1`0d#b`PqK$CHywPZ<9%~7JlP<6jr$$P_(=8$KbbDVFNeU z^6KNaz-oiv>?m3vzm=P%Sf2cLbfM(8S8w`_`EB^_rtw>KmtTY5 z^!e=tVC)yqZ&#Cgn#yn2LY!zbD#Q8B#l+i?_#5)ue5&J(^V{l*!3B0W7Fko&X=y&zAlfG@OaoOfYz^Wr0eGG@hY2eICM;26eyBu}*gTvB zODT^T`Qq;w#tpkeweD_Qf+3l96uB6~LLS~YE*9`7ec7CgG@MY-zTOc=MOfGuVa=r< z7#s+k^LVy6eQ_qlhy>BMdTm)^zgIu6*QRcHtKDhWax9y4 ze|TvbtJmHHB*o!~P(ry;eh?l*>n)=-`uC0~_9|g{llCfHog)_z=6cOs|B9m@mc>w= z_3zlo^>1&n{=F7c1ngId*b9hezk*dC_AAkZrr570vJzpx`ikHq>{oBgDtG0GD*uMJ z2A95W6WF6sfZZyAJt=`*VFHu(D{Lq4AIB+2>)u{v0 zOKZ35_S9iRX_AI_$N)xN{|LtnLanaD*s~%SJJ3ro_RLEJmt|%~W$eF-wdy^Bv2U>$ zw%~-aV}SRNO7nCostPwx(>YkOcPzk0viE1Q;uf;vrFd(Qy+x>dAuAT}!w6Y1M*@4l zujs`@6PRG{U0b8FH*eF0d0O~cUSF=I2%?t4OUlpeI`Y$yzcOEGBtO5A{DQjq{`kXa zyXl{vFGd^Wga2@~3?m&3$MokwH{n<}JkSR{tH&Pq>)C&*K)6lVAFe$8SJaO^;DukT zA73O!vZ?kT%BmYygzLxMm^c`TzoC9yLaniJ{rJ_zVM3@0_8-8t=*OceOJ*#mvLoz2 zd@bawRX=tvp{#-Z=j!9qkK3Sa!v2Hb2K3`ygl|Z{K~1 zuGrZXY5(DC3}3DM_V)WED%gLnJT88F7XAjp{)68J_-!&t*1~UmkHT-41B!Mx{uuoB zDlGUWzokb2;d>MyClScm$g7Xv0`D69W=GNb_^sS5#q#90qc2N-d-V$IdNdTj2Ft|1 zeL+qU%QT+8zy_|?N*EpDA7YMQQKEWNw1P(iH>tVnR+PLn4Nuxxs1-+HFeY%T)jq@S z1CETR>QO7WaIDo*j3%<4a_-=wmDiw^mi3wL&%xH9ea#zc1p?R1NaaRh8*SwR0Mpw9 z;805tF#z$KP>0wK3a$S_{vxkYO4Qdw;R1mbHzI!X=%Z)lA?-%gfdJd0-)Oi|$6;)h z)Z6}n4b@?3fAjG6YcI>4E~Acb-!b>MLhawZrP21g{F8(WM;q-WK(I7k8-NNdh`Jxy z#(G)el&TVxCVhDv!k>Y2slO#)ts=|IcL(*c601HHx&H zByCzPAH=`5;B68cu4Jmv4r7lH&O5YKaLnPqA&eAnqXfz8&mKQzFhiL^-e+Hs96MsU-ug^Zwbo)UMbkw?keqUG0mZaf5go3^vZ&B--WE*i})0ohyMoA%P{Dz{CRMDzv*1 z`@u5e_!s%VY=~U{BEh=;1>oOk{re|uqlH$I_3f7*`UEqa2d%KKf0;G|X)&5sKe!gK!t4k6NU-4VRn+<$ z;cpc7#Tv)o!u9BEf3(7azc-lHkNAN93!Z_$C;0>amo((uGGFA}%TirXO5*Q^Hx2yV z!i*Gt4*b3STnK-^hyTE#N;JF)>&Ftuuc6QC`z!rHJimDTSVKfMRiFI{?5LgbZn!?X zhlwX4@i)|G^SStHT%R5HuP`EPeEpaJxE6i3GrQ7n0p}sEA5Y?I8egsY>^JjBYZcm& zLC2-fe*8~6fMSBf@41IR<*%p0vbOaE-M*(s%fn0^W z`t;cjC?MC5{rFVR`tiUUMk$sj8+Lz2PUV{i{>JOaIUhHT-%{HA8vLfOA2$GFznI_d zC-pRy-@Fhf+Pt^I`E5EApF-kq$Zy-B{565!etPXV`Rxh7weZ`&*P$!x-Zc2_DZZBS z)yi*fkQe#wq1@x*x9ib1^4l%=ZGhh{BFS3#jqg!d#SSRi#rR|J+qg3={PrE2XaU0a zC_p}Z6+m{9Tk1Kl`zi`Zep|<+?^80@y6}r*Fr$FOJ}27Z|&} z9NtfmEMa>VJ7?m1g!F353J{p{9FieUS8E@LZ{gZIfbl!T{l-Yg_bat4LANSym6F@X zFN%UIRR5^7uyB^${(&B6eJLXe=3rv11>dZ||3|yqA9w+k!fUtFU)skEzNz&qIAvSA zgW#|egZK`B7^FXX+U25H#v5WXN;-famp`7ya+kl&$ti3qj^qlbe66qO6ut6;LrqAT zO!O`f_M*rCNC_-fbTR2=3Csgv!i}FBD5(-uTN9K-1>Zx1gLAnY9Q*9FmN791|A6DU z96hUJyU`H@r>zZ4=NK9(-!kPkk&;m;dPQ7cfmE)^f!mFEGy(yn1+rzyfo92bLnYs^ zl*|n10arVjC68hYQHOb-rDS%1=Lj*<-#d+w-ViD|+)@%@^l-c$)*Ci!#!E+P2c&-! z2#Sy8IN|1QtrtEBJS8E{H6hLt+n2loGs$ev9U_e@blw`hpKpw$2eZ+(+AD?!u9h%H znlSpBF!q~iUBY0z9uA`*&{o1oHp~AcwgK6WH_f!2BF$*Wt>G}n2G$~^oH<(KkQ-QR zO=0=KYu1!onDT@*ra?zyYZ3bZ~hogu; z<5M$vyG+K-F><)F%}Tx7zGp;*1pIC7tbKScD}M^SjnC(bDU9?y3zdtY=Nb2#AnyPO z*|WRMH16NZt5OTiw5wQ^xD9}}XIHQr2y*GIKyP!syS;(hzr4aa&yjU@GwW<)cK8Al zRu{k$Mj;|@x&W16UvL1>Y9F3YDBBNLpw*_Kj58784zXF}<1Lb=|Aa*Y+rYvE8<5z5IDN;?zEkK8X8 zJv!Bdl4yl;b2yYrLRs~*z{^@8VmYGoOem@e`DuJ8M|7E)M*Nw$I!Qv7gGW-`MA)}W z*b`0ILrvJjO*s8b*rUy~5mwm$5^ey%;06i4_TlXWZkNE5OyD)xoRQs6HUYJ@0=mTj zB*{V}l-0cX!k@A341+A@n^4{{AwPo;W%rkuX$z5NcE6PY*=%C9=)VL$(F8u!1U}pZ z)XxNdhnd!!@J#6c(FfFOw6lgT~7)9!_C(*Gb?7 zCh!~+_|qn!?jp@-^gIa(W6$~HVIF7;oMLVDDAXIUSyM(bW&c4jvOk_?jO<44zX|-L znN=+lX+~AK;ZH~R`sA+)p&r_XXI+J>&NM@_Tk|Kc#SN4 zy;=B@P~mb*;Q|&uPZmxy3nzvOKV~UBmW7Yjh#tq9g};F+rZ;1prEnn&SIWX0I~nMC zmxdC7p2a4B7x0xN{ORV1Ek&9+%xxuD3vW&(@JRr!)%*>*9c~!r6$A)YGOS{9^=sjtppX*WI2xdov-gt zi;?ya((wEvo?)`w#UFptxt);n=F=i)4NFZ%sXz~Wro9220gw3PO=jG|&!ODgd^*0w zeuG$owGe^RD+VP430NCkp27=i@PDS_y+)}RlrNGi1`QX#a6`Qr$NQGDu%@79?zU9m z#TFyA)u?^#cNg2F}RU<)`RTbOac}5Y@$h(=zvBc9PO5wkDZjnX_T?5$$V{uf2P@S4R~hEC+B z6-~fC6QU5~>Rd!1_Gdf*7Xq%h_?ecCu~_OrqqLXtB=)Di)hmBzbWBY4I|!4%iygg2 z0FPIe%0)Cn>ZR|+XlL`?mz0Aambw!_w2z(^;~VToW)YX2WEbx(Ivsq2D>lwyt?j*7 zrh|VRTIrKVYLV;ay#rc*d@V}35rLHf$N!F8mftl88?NSlTljuJllVz}KZ2jKkznDc zC(-0zkDq#DqrY)}dgnb5e>N(%@YAbI>qGqEJTRVt;m7#nPx?F=IX6Bba;CA=IVdIh zX(UKY^3#pXIE|kJY5#s8n*4zQp;`ui*GYuo@<0{OoC>OdacPF!6VLPCf|6eY4i`~> z07!&t0%2%>6g&0hxQsDP#G)2gKsdBRk8_z-qhtl$=Y(}V#Xg%852A>I3bD7Y$Hc!L zfi{I_p}qK@pg!!}a#k%ViN`bXv4M$R6e>alW<23SdC)6EsgcqjWREe;BkVXDwOiW) zYZ~WoANJPw+GoFsk44a3EeFlwEC7o+3;+Ytcz+}AIZP2_jYHvFU86AUYy&dIFABos zGXOOrLb~??88(tla$nB)sH(45kO5CGMVElIH`uZU(q9222iEFj9 zQr&+*#8QW`-;BV`m%^ep*r8-OimKJD3yN^1Q45A0%fwbNCQ&YXGC*lH15!lPQ{d^b zN7+=|5076f4(`Q!7{w(QIV82Egxox{1RV%zB(Dx}XafbjD(%5yaXW>@A0kY?C?dFD z_$4aY$_E@qA(Qd7(gj!6BBfP#2`1ilJTT!=}T5{!j4gER*!<3%n21GH?@9%nUYjZg5! zA}~EB2u;btc?fq;01DV;1Ajmf3I241phiX|GcbXO8penkZbuExkvjm=-Jj83Z`f_< z8t4Js(#M8>x};1QgM{-L>Xha+f6|^)WVbrUEDg57x}MwKdoKUF}sVA#z1TiEMEbxnhwV+W1Ear$SqIpS1Q?;J3c<%ZxI9 zm^CxrXe*KOXKee)Q9BFGcllv+#Qh3vJjb(v$=4xjcHz!b>G%u9qqG}aDH4Z~)dz^3(10`0WFN^H)WC9!!Iek1MK)ljT}v?+;1T7`BU zxANuGP$hQt(YlHewWHI7zB?2`N0uL?mp?C5ex9{_W<>c@_3}S++fKrtVJ)96%F~}n zL@U*6*&zgOg|R6jsW@hmX{zml}>YQXXAJT@14eR=a>mH~NsU1YKv$ z(&67s_!u0qbwE1C%($It5SbVZ;-L15eD4ZedzB)G2pZry!hbtim?ZTs?J40m975zv zmz*?I8m9+Q!IV_g61U!XmM4#Zhx)yb5Em8NW9Ny8iIE?Y!YXFSk(-1fkiXJj$9sUL zc7H~>&iyZAzfBN&#>JvPRoY+0{w-IFoKxHDJ@Ki-Q5{H4XpFTxaQ`6v?<5-m-XtB~ z)h4_I9bRr2yp?B%J9{n`r>AX3JQD)wt-0E!hM1~sJx=6|96W9NW&MO?s?>r|)|Fv^USwF9Go1lC4m<>2#}r55%m$ zPdkmx_F^04dL?Wd4NdY_5L*GZ%Oy%<&SBOXmVP+BU!V9F3(D<#vvu5A-kZ z2TCZ4!y9;OzqXO%hh+y^P{oof*+Z~Rs%XX*jr1aPI9?1?bcfX6W(nX}Dq?`J(+2$w z=*PC3RNy!i96B@u8eD%ppRO)cYiQZDsE`5d1czFhnQQXwVrOo z_iIpJJJw1H-W{(Ky_lpKi#FHgzXz8Mad}2jRP<-I8UNL253*xe{qmZhtd;H=D(^jm zc6OSOpH}_sLR}->jUM5m7u=wg<~{>=|2RU+trEo-uCL`~^%DA;f@^PpntL!|)@Toa z&T?u7Qe9Jh_oivz`ULfBRrs~4YwPe%70gE)?b@tlcLi4CLLY_R<;#I2zZS^}Mb*K7 zg(L+0+oI`eUHu_9+eiiow%zgRVQexU;2N80nQ0BPa|HnGx5*8cP$(mdq~b|@LF?VikBVE;Yt zrN;|PK^R@~5>0s^mWzL_hoCzB5=|Z6C4`55-FFxICFn!yzXm4bcNV= zr&Xc1-lNN9AHkLmY{EfmBz?xRQcUjCQrIIyeQ{`=@v6(n$HXo?W>TRxao42w;Sxab zt_a~%jFw%@jTYs8Bt}L=%g2%Aq6;BTw7b0~*nT=#u@6)G@EieAy9)(^|G-X<_D4|^ zcd1U5g7$*5;He}2h1(k#?q8o#?@VCltF&R*5SPQbPfxiNl?j_;4}qU5Er+$6Q`lSh zKun3=Cx{wvg?FEKi>`}cd@$FB@UQD6dX>jo$SQYWYg$%0O|NntV2Ua~(i65JL2Qgs zby=h*t~L_sFVERN)ojXKqbXv0%z?iy&?1!&VKJ)R5jt;ZAfQlh%}}#7!}WS{02bTU zs5wth>Bovh0|)9U-9?Hqtv|=jc3*dpLags%DppPqX~!if)4L~6W%L2ycezT4kBBQ-NJ_94b|aYWWpP+ z!y9IW_YV_ZX~Xbhb$Gk5ku8TlL5CM-g?Eh!Z&kza-inv_d(4ElP_N-_fH3jb!h}~D z2~X-cs1`_I-BI$Nu7n^jad*#5}zDT|f(dhrDVU$5#dcmxmyzRL83hgpS* zuvoLgL#Qyy07-cjj<2D5Z5Nrf-K+!e83z1i^bEqY^0$C+jI!BE`h+OK3YRmRJ;g zYG1I1s&G5D;?V@r3T@+kunfb2=}y?00)_Y^rZ{aWl3CY=JLP;eqf?#visK>gr_pDR zQk%rq3(p$_a8$?N!y<+9dcU4B53Mqr*i1ALYdCKT8YQ>IXjc#{BaTqlT^|nBE4#?7 ztV9RxL`sObUgjIuhhFZ1qUV++XZZZ9_eYtvM-e3>D5BU&12ej?IYxGK@mzLuIc}%v z@pTebZ^cfEu$9Hm?fBuPHC>sED_g$dD_#AHoj>pqzj5p*e#MGs;mk!bF=@!*Wi7-& zMX{5O#ebquHx>r?QoN5r9&faYMN4FgdBcl8=_TUCzu3vCL-9Z4oXcOV3nvQv8tHF~ zc8WVd#chc>EFP01o^Ok}Ek-+qRO?wTt~y1v0t%{~&tmw;rj+29P2nv~anOX{*6Wlx zjH!YJaZ+c|9^S`;1sMeEW^I*diAa%GwrDFwie8KFA$ds+@E}A1?))eV#EvWb_@j?L zLYlyy498lip!S)lo&Q4hCoSdRfHB8vrvb2TLCh!PjsnVzcEXz&YD>~1df^mdNz{f2 zQlUK+%`GJ2ve-E9Gh&zwSX>GgMASM|2c&5K01UmPVYf7E#hN~asL3X3^e@m1*dDb? z&=U1kyb4Th)0PM-eg=D4z_{!)whLhgXVoE7fff1Cg$W+IZPF*TxaR|CKvht)v@7(U z;gzeQiQ<*5VJKP>P#S9C4J&1Vc<)2bOuPvRwoAKJY`OxZq#7Z=SQu+1G#Bf`S}Yh~ zm`&BLzn5LmFXllq?);Qj4r%?7W07)_k%|&=(fh3BWHns}E7yLWfo+Jtpnris;SaQs zz_a@Aqw*J;w|zD*o~C)=$UUeKR6q>zpVkWX1S+wMfiHt&_-8c#jKm+R?8Ep`h5iv4 zPkgiy34s*-qjZ+<#y{txr`pEbrSMyeUnEBMcsyZ6?eP`JVQr7%Lrh-9qAEkac=jk! zjKvt5j2TBTYS8#^d`3tXq%1xvQ}RVh1%%43ZIm?_J3Q~!pVM>#iDo^jCQMKQ)_uaT zJ4OtsX+4_qoIY9Y(x#&hN=m=5)Wghzl@TccL#G=mg_*oHM1wGsW23iR8^lous$L&2 zQS}0Tb$u#)zJB4b?8*Ju<0CHp8Qb;Vy2VDKp*_{`O~`8@Zkr^prAl8%Ue5*EQBN1W z=GLO-;pTNVNjKH3$siO&1Zl+$AO5 zNNflZLAI_dA}+o=LJ-Ua6kQN-3{64s-8ASt`N7LbSyzmcl%?VqghNiwBX1qO3)NaC z0j)Kl2fpK;Ccf&Ze|3uf+e&^N$-=Jy2!ZVx+fLZCq0eCcZ37+a;B|0$fC zPEYF368Rx|`c&XA3Oxluu=UcDU5BG+^fxgmpk8{~{*$a$r>6qF&d_}GCqVgy^z@Jp z8wAA3<{KThPEP{}SQu7~$)*u{`hlCM5%iQFm7aD_X(By6k6||G$#$!xr=P}z)6+iz zER3EOBf+GnH7HHGD%XD($*&{nX*j+iJw1c$(EijvYDh5^+JkZ*omN!)s=3XGs$-YZS(G_ zAnF`@B6hB1(DMStHwYI|;M(paoUZ|~4srxtAp&^nTeW08V_``sr0pwCspKy;PRwO70ThN2XRux4UJ`O4z7oX2AB|b zO65Yab9y^w2sqajQcB~gO6!JX0T!424aac{vQ>`f$eC{EB6*hNNMg|xmSzWWJ+8I} zG#9+-|55iP@KF`n`e{fYtR01D1cabbgCHhK#zaxmkic#2XcQMzz_=lzC_)-g6oLst z)3nBQaK{;E2AvrPm0=Nqga858fT#!#ASzbVAUsr7CI9cMs=GA_i!<-N|Kq3Wd(S;} zs_N9Ks#E8js#?e>kr;-boRpu`n2;>~>nYZr7L<$F$W#}^sc2@ktjw}tU&@l8VS)XF zxSVf@g`v$8-hth`Na7i4V;K1*i31>OvjJAsalsR%)<^!BmbV(wbPRLXX;#Rh!2W$( zy#3puKS{SN=6mO5h*Gc4>HVXUz%C#IAvMQEYi7huypt#>AKXP7#a`5somhqrq-U=Y zbJ6a+h!@rRo)*kUQ8>SxED>#g1F_xq`k|xo9U4&}@0(J@5RK1OvncyhLzeRVpj&@x z4w;IbYSKKJMM)7Sf+kz|x?9^PNS_X0{CIKs%T4=*$qd>AF5a!GpAK&><|aUfYld6_ zhR7DaRRh`pAeYIg?p868?q6viWdou~LqDh%HJb?r(l~pyI!e;+fQXcoT@1a0?W_I6 z<=fK_x2%A_&_=F-QW~DfHAJwdx_M^*{VWp{?WCK3uL1y#5Nip$L-LCv6VNCJgDJ6r%6`Pk=It~6JHY%aIS{^F zx~xv5|L5QI@9;_z_zR?7d@h$esw^B;cxRpQIrn1k*34#1fJjFEI;mBR!+7K(#a;rtH%6mjE71C%OH8o z%ZJQ8fbZaBqU?!E{kcc?%B)(}Q68kHJ>40pKV2z02e`kS>xk z_MhW-Tg7i3>Q^HcO6hTV(^lR`fr9_@W~JW^;QSIAo5mfBVgsDhPDwf3ALx{qG%+6d z|CYQ!M&*iGUw(vBXVTeGl*nNI>YwI3k5%<=Eil85DgJcT<8kq)RRB2RPfr1d^pJS0 z_t_jFo_itqVasu2M|k9*2%-wY;)p-(M%a6RA^!9XJR|<}B>qHFum7P#g4i-bemVFU zu>K4z6@U7bY)i&-Z{dfRm>f-;Jy^$|I{R0aKlD@lu!9&d9LOVsO~q^^mb2JKkpxF5 z_E^d7nFxzCz*T5Q2WIKh1?oZvi`9}^n1 zUJO|bCtx_JjwV1%2Nr!PYR!w_7%p5r8((+lnU_^L~a!)@I)C8Rig9 znu-z1$-FYYhf^ovhs=8mL_}*THb-LKbpuW2CEVp;UO7^`n73t^V&0j+xAif#emj=_ zyA;6*N93QY|0Yg9mi{|6>R_J_RaNZ!3!Yr;n|rR4eFIsNaFRdbW}lDm;nY6(A^S#w zi1-LB!5DS~**p1qlYP~9I@ni$)Gqe@5nm~L-(U9|`|l%DkHSAhU)$r~T8M}Yg5U^f zyZ#RAz5RrPgY~Gb;@}K?e@i z`tax!QB5)6VGzk69B)6Lw4Ezmf9MN;XpegdsH||DHPT%R=-qIkGI|^fVQE6el9;89 z0X!6o=bnkd_QqnYit!JVGKPjsqwB61gX4F6%Qk?cLv)^kBH2i%k4)Z!TitOi+%C1& z9Rg-@oha8O$>KhuV}^x0#tNyr=nkNiFGKK~xm1)Ftz!pPeKA%t%w;8ta!e>KqU`hZ#Y9c{^8~YRM?+jRQSawe>Y-{GZe(6$=Zoln8x- z-GNY+&=z*Su3JBEvyjNB>D%Xl50=KwT9Fp@Ezv@I~^@(%zXg^{np7pkiG+2kWL zGL^kCGG6oXtVdY^cWBy=w*iKjJBFs6#LzTYexREnt{=DH6^3?k509+E8Z86 zTB-Zu@xYa>)QAwVR)(f&h@n%Fm5ZTgfg~Ba@M?|~{Aa~)@hHaL>JUo0B8>3w#D11O zJR0oUD|X;{PhYjqWPFzB$x7H~Wp=@9+A%ce(y7uSxfpFW+1`*gLOp z+t(AI;s#rVTlw-n4t^WM`r5mAK$`{3quXl2>c|*lfz|E0ek_xqNB!u}+go}n6l@x; znqjg-r28LYt+RJ9(cGxz zVd60`+}(aQzl#x`4=W_X)0V?Hu)$kFn;in63%qmB^zB)O4qX(!Gr0(B$XIj#>h1pW zT7>rY$N=NyhMm}1a(v6KD$4uG`y~Eu_4Zkwy$b7}8Px%=KW2nGeLw>z$n{O1g5qsVUBjdas zrI#bXqfk=AIvmt6G#IO6U{D~m#qjp|l+;dRW>~Lh#ghGzAc(C1v3l`GNvt$+Tywzl zz8Z~9QeZWA1|&QBNF}55%eN17j}&zDhx?~X;h^v#q8)+LluhZYhB*VjxnLg_JFw94 z0l$Wd+2m*$S}(pqp9=K_(+3Phov=7gx_>g}4LrAqU5H&2SO=YtbvG<)zFk;OJauwMxlhynKzg=@vEfnsmoEM)y`X-M*m95n##{F8xCK zN97z=U)vu_Bw5s7u`1lwSeS68iU6_ZQ}0|4tl#NlTN~a#){KVOS9@YHf2gf5+&>Gv z>R*VMj(2`O@T`U_ZPdE+1c--V@C8ht@(nNi;(6G2Dn*q))zqJ21L^X_W8x zPQdj*4DE;XO1W-ob_bgG3~&StX^IMCyLfKwn<7lVS#&0N1KsuoA|pNM$$rm@SXV#v zi}Zw`x>Hr0GMEyC-oZbaMezC>fo|CGgpBf51iXEAq4|n1jkIJN4gy1B%|$9a?AcXJ zkY#vk{0Lpi1?3``Q1hcVVDvn4{YM3Fu^*=AJ{zGf~wrvS*P7MnG z4j0-DIu0&ehrR?Zcpq+@3j@Ffy&p-&qdD9Emf%pk{`W{`==L8inSsWKFeF;cNNQLZ z8e&F^{|Gah-EpYx_75t(qHOx0X)?B_GC$EI9HuVSEkMoRNUTSuRdk2bXEZ6S6{R3wW&V z0A}Jnj zR;|8)c%fD=!fB4#7dzB3?qJtAYZVARj9TrCzKr}Q9jxDg!cF-W#g&a$mOIEh`E$OR zZN~xFJGq7+v(iOW)a`mtL0-P{39Pn2B}3JdzD|Jma?<{UuRwe9R3xqbrsbrXgoK&D zBqe0j*SA=g#Cb7PqmEj$B$ba&&*1(G3Tu-=7BST4F+JZ}KR40ZNb{5>U*Fs-U5|M|TX~K6HyL zT5)4N4Zc^bD(xg;tqJSkNV{x2*tt}GYsJzaZ_G7F&0S_N`#LCIm~0M-eGu_V~JXRktMkAUB@QI=!Q+;;kz@7y6u$}&sz@lPeA|R zUM|Gy{UDmMK+Of?8`!>>eAuvHoo6|AsHI0gMB~chwv@%aCnGl+fB;Jnj`Twf2+9LU z7!WIUDh-@=jw*>43J+T!sqyFHJWg9=J<31&{i=<{&!5`qErhjChqUi2WIDrD?~$A1?JYx|i=zI$J2GW}$` zMQ=sRa_pLnMSlWzyOTxoJQUUB4@3M_R*R4l^UIOTGovi`Lht00m8i2sM=rm2^6lWC zm8IA@&guu3;{$R$T6**aly8{_I#v1p9>L2sBOGh8Bk|8W`CGJdSuTd|MCPX%lL%JC z0_9-rMVcNDaKui3Q!6w=pQDrbLt}G|z3Yrf??#OtG2O(`J*bFD4L2x4So-Bg z$008hi0+#Zi-Mnx%0mrERN!!qE@Y-lCakqK*PBOfk2A}12M5n?KspdH+mLiX0AeRQ zn8))aw5V;co5?_*Q9`i-C3B+NwhEha*8CFblIc6lSji859hGroPbbvi&{1lczBqwxWaoh114*e32n_ zWd~b&%TEHlVohoD>@`s;4uut~io69|veyLIl|@eQHecDHyorPT3sG|X>yofY)&b2V zAuysz{)P61)?Xg!^qS$>Q0QH})#ursUGMjNmG6C~)>8}HMK;KsJK-d*LyPjh8rvdr zV?7B^z<${3`k{XBy~~DrZ%w-H?Nq3YgOY~G--oJv??CPQq$u>mv=$LxUGEkF=y2)Y zDa%n~7{%N4uO|BSYs%|WCY<49XFlb~!#1+vHum$`iHP zua#`R8c!LT@5|UjXuDui+5VgfYphzAyrpVAO#Y(QQlgOm*z;M-TdGnMDpBw{6nr&k zmsjgTSEJBNVad7D!|EU#X7Tyk9&inE82yE(m};rm5RJ*V8Yv?i{GmVv_6EfS?bnF5!MbCw`-pG2pEXc36- z#KD;?6#Ik=DSJ;8H;tndvMB>l-c!o<-{GBnKdAX56FpM?3fH1mHH8%$d<)TV2?gH5 zb-`1}uB8-`?AeN4dGeR+k_>24w*MTzw*abhcbp~+au|>EZ> zC$`p9T8`QhyUI7Mc_IjojiKcIWqaVY<>;?sI~Vmr=G{JXiYL}vD4Z(7*poErNbkOq z?u2in(3BH=p?$u+>rh(Mz80(q=7BY(cR<^0eh&4;H1Fgxp!xTH#YlsHAy$LK{LcVU zw@R+fS9;5fB;~2|P1^SXrqziTqCr;Sg-7gqr%%Sm-QFQd%@?O8%%>t((5=dt5i7Ja z33l7NQB;C>?A5}_RpZX^-v<4+jdxT>q`M)pI(8;AFXQ(~B7~plSd0-Ux5E4We&P*D ztcLWiMAu6C^P<#*F(;Y@qH9_4t4rW11BYxKL~qGs#-PObvae)DAqvf_&*a1 zH6uL2fY~I_EhYdd~Tv(*RGFn*iZE1U$ zO7X%?{spj~f6nrBMW5wyV_f20VsbhuG0+05*}~+4P%vROY>O^)ue6>59cv;iEr(&L zyaS8dSPxhMV)u1Sh%GS6$AeL6h*nd)y7)3$IdNJI*I#`z1L3<3quZ}6nLlqi7R~}} z=c@S!QO@|2=At+JuyXwYyA~H7Fl*t2u)Fi4J;4@JKOA6$+ZK2iV{#i-=Uc#eYCiwu zm;Ksu)M)@NnZHWCHXGFrudmF1UA-oGr>v$>MDBtv-V+qA0*T>uGF=9qmiQJ}3ESiS z72g6oeR%NT zcNeBqTB>4gV0BEE!hU^jc9jeq8*Ii~+V&pE3!taKiU%Zdq zh!G5J1LpLFiR2CprOT6}*#H)VzVpHG2*q)%uX;zb{IZW=(H#uqPyEvQ@#QRsip};` z+|Jp>Y5I%?IbMSjR##(NRPSgFN}FT()jLka!>)!&K6U^FuvY6+&-IlTCVNmInfkj+ zk+7_hge*&g2~mL~CY;?sLSNapm-@;+L|!9M!8q&EgiFXO+q!f*3Yie!dB80!*Xv6k za9M++k03J`U--#e@eW^H99s;C>b$KpXuPNx!A9ziL&hzGax_Sg?BE(_^5HmpNylLr z_+vlIFhEaJK=w*leGaoYZ-XNU9h318$}pfhCJa9-a3X1X^aBi~E~}DXQZ}thL6D{~ zyCKq#E7FE0?XW3o7p@SU^;*wLxa+=!piu7&XWeQGU3D|Uy)*pXppRq1R`s*Y z>1|XARtz;Or>!1l<@U(R+2)iH$3poO8tUIcY(@-v@I^3Kak7lwf%e zWF$QTmocN}qG@B4tI^wRrNl8FK#%jm*Ae92M&2CeW zxp`_Kc5TLDw+6yF&4zd6Zh|&rHp}m=3qp7BGKc!AU?M^hvwet|EMJbZ6u;Z&58n)J zv#Aj-PQEPC`fTH(YR>r%-fwV^#?RA? zU+PyRcBj$H>2X9DWFSxYz5Osd;7m+j=V6*N>-y42+aL2~U#wtz;~0JjW^J0cqJ*qp zgD?nq4ZRgt<1G-%vC18E zI_G<7yOTU@N_R+8$Fxa@$T50>+R4Jh_D6C@^8#Im9)mXbqDqZ>}m2J>R8(!<%JWt5VyD&hIaa^zfTH;?}w`o&MyNk*FMj3v~8XSd|ZsreTz{=Z)W~-(1 zD;ZrDVIslPq?RDf4C2H-Xdn0m;ERA>EA=}ndW`%>uBAB$s1d+&~EW#8RVt zsnvdPXu^bp#%PwkN|K4vWR_hYWpm?jWKxdyW4rR7WivYd_D%e4?R&oOI9xho5Wj); zJ@?k*XkX0ld;Ckxmc?OE)!!us!uO#ULTsU#hHlPo6tJAI8|9Ck%8^ zfBD1co*i{7CuWFq^2vol)y4)3pquwRL|cnSz+8c)X)D5Ti(;XPeb);*5+AEr3fKt z>z{_UH)Ms(Cr&pI^}zTOT==&+z!cyM4VcpB%)BceFsB5hEwU`{ODOI9M=a@ zo{w06Xra3PwSB2IVrh0hqEaUB@jizNH*a&2uCQi9uoEgAsxDuZKQwf?#f9eOD@(|N zw#yMwGBgk!x@nlw&S~aLlr-uK%`Wm}?RySIysp znl7O4(Cc40G*qN3gE4z>4RkfM-eI2mQ`P!Lw_eG`5LatuGa9X@S2l;~P=AJCqb@fO zVO@~KUffWJ%8w3YT^#<|YX&r0pWnsThqidsC%dW;dxhA9Np0wE8yYG+?g~BL`&cXV z8RQTZdTekb6}n!EBkUgy#J}AI=e8ODHW<&&_%~UAO=`*?677Q5xcIjQ=(TXr`}IZ_ zy^R;KLKeMG@ES+Y)`zggdnNeBQ8eTT5JcEx6~I_uPkUtsWF_zC2`xkGcvAKRfQ@iP zMjBT+;haYXF|2h3CM?V}Mo67x!u{`6NX7SAl(fvG4lk+$V7SOI!si*`tCM|UXe0DC z!uDPqz*7mQ#F0is9h|{qit`tA`j8H(RboBH444ZNjmY0J5|B0A;CCjQ0ciK7AqWit zXho6xS|A9`n^K{&?FKiTs6^j8=35V+x*6MP7W8r7diW@TuK|c1p85vCdooI-?o*I4 zOdpV0kTH%Xnsgo^GF8@@K0usnQ;CxbvZ)AuMxGji(;SZqexb<-1 z5LD$$AF6`6CVcU0e0`s<&RY*BNcq9}x1U1X6Xc#sd7k@G%64ZS#crp#55Gsa^)R2( z4gr~o0)iES?+sj7cnYY90{k&=Jsb`Du_+tkAdBcA!uJMjCrj+i!7`aqt`G9%W0p2-AtYj`-@&*)b^)03Ld)7 zXmJEruZB*tQ@nt70M_mlk18O8DX)n1>h3Q;v}^Qu8BJM!=%lfQk;IO^ zsZjnAitJ&`Bs4!-wiq_J9aUUWa4H%4y%Fw(HNZBpZxD@8o8uP}=&Sznt%$DLE1tc8 zm4O+Kmc{aqJw>5j2;3Y58N~jrKg8YyG4Tg7I#lCR+a2Z3NHIaC+a#8rDMQ+5?^Wkt zsSOq|&c(%0vl~VSqJ{FkiKYGIVrQ#Z2Y@5y^>hPqi^XmCE@iMRB41Y`obPt%O4bq0 z)}{az_>GA4zVG4OeNz|4A5aw|}SKuSjp9H#dzBAV+j6FL%q!~l%7h*JuV7!ZI1^*yKJYNIa zqZQE{Xz?|N(Bu$xS}aYvLiTzVguBDO=&g87cCalvrg@z1~q&8uJc3X z^7j3Oq0TY2f3|!%w6mTvgt>&vRTaXV7A{K2`ylvrth2q8kn^{9@wH|=Grm_F;b6nz z%s(@n*$XC7XfME!j$qBFT&VIZyl$c1JJ-9X+7rZ*{R8x{ z#V4Wa&{M+~$gWks6&GNxK%TpeZtDYiyGLhWiFdxyZMQ7Qm;TT?b>dgC?>e#O1~9yQ zSxW3;T1#?Cv{_N)PERb6Q;a{-8`q~od)X}>K+6O?Kl=7G_XLw=*K8h3^oMRv_N_?l z1R2_Ac08_z9rG>DJ!eFGZPgEGQUf6@d3D}Lk}-G(aQ8+C7ZmOF?P-Qg{gHmi6p><( z1568?A5;9b%Xc!>{H>G+=;a7k8hb{-a{#WnOO3pxh;FI#Ejk&MH_8v3JPHTVE``}) z%P#C|fH_+H`Fzw3F=ZG#KvZ1{z=n8}{TXKWVp!U^i=Z?E+H&viM(BOgkh$q-}7Nn zXlQbu6$NLotgb~fdrA)wa<;e4zvBPzSNRAE_<>;eJ+ey@mN*5=IGSFO{H7Ziy~D7A!cA@N})WmDuo+y@)_4?6hIk;pcFuk z!xvXw3ms=`u3M#hhrrbU{x_<0Cricis487n)^VzIpI`yzQ0c@qs7f1O`L zq0(i>5#f6SL_8$Y3Evu1={EN?Rk~(CZA_(m*TNz`Rl1)}B@1iC%$2As^%*@q!)mhD zfA}p2$xHGv&Wfv%+7D|EwwRP-&rdiA8k@u*u$zV^*k!TCf!+ac<$Cex08ANSo^DZk z>Yk?Z*!GE8A`29#He}*Adkx}bW3b({&cIxc6MvdxHvt42hp=N02QT<3g%JslS+S;2 z{jdW*S&Y0Ad6oA|@x1ME&7{e}6Vxn}Vl4}5#2>*DYBR_k>k;Js_BrGhKrF(a@WSCY z+DSz$TJ}Q6_`);S!}rl93N>*@X(#X8mY5_}lr7hQrBItML)7KfDKVTobV;-$$CuS` z&MpO#JWdZguwrLA6^MNFLOM?1IfkLSj?)*Ggy`MN5n6Lcx?JV8VWcj$HmUv4;1c4M z1CbHw{=82x=VOo1CQfS?U@wn{_yO$f@p}tlQb&O0dhsEK8qPs!^u4FUl-hRO^jIgm z41v7;-bd)KAd&NAVgy`~P?5I~r@z3J3q@nSsEDW2Y+Q@jxkD>aiqV-y1lMbY3&9qI zDqKinm@}c+XEFp<^auSy&C!sGf^$0-?O8_NA@9@u(t@W&Zvy*;pWA_y)We;En{A6xQk*Ds5u^sSzTxbLf_pq`Dallhmti-OX zqz?xLKR1(~Up4Zwy%leh@8PRZh4T>ji_d#XQTQuhNyS0_p+54L*Nr73>S=`$YQKy2 z@X%F&_eqJ32Z_=oBlK~sml3`W=}sVd{NlnXnI38kezVsgz4w`=MyOXEXyg0+fcHyT z(J#$|i~o>6470fVAf$?ysPd(Mg83AuF#jeh|JFET$rHN>O3I2pW@4m8`9p{UUsHOt zv_2pjDcmxH^~-=j_#~)@MM&30h5$lD&azonNwX}bHcab32Vl7XUa%FS&kD2G#IOq6 zO&0jUA|I^6Vb<6KtqyzHLRTfn+6BOiyaT*-#+MvRqM`MRf@znf8F{-)^Nle03myf+ zLsGIg`18*9J_ALn{g?3cTihj=(4o-vQKhR=rd^RXm8tg{-hu-Nn(JSF8#8dD9|u#dGe!m@ZRr5IMMm2#vSuqEZoTk$?Xs(JGvn)}qbrO`hDs{1pF)88%* z(kl5uQOHdeWu*GeYYRpq2quQV;3y;o0uzFO>e7Vj3`jqkQRn=qo z?N~MrT_lw(qIi0|Pou39S4UT3)yOj4RI{Q#|I(@Fpv-ErODa;wDRz*j=(8-ES<+G; zMc<}(>|KCT401GLVBO_QnKm$O>J4dfy!&rePSelkTyu=d>FJk4Tl4pHE2k$B*bBh_M&JH_U?+xgcuY-zMi$A7v+VmxdavF{!!uJM<+)g4B@vSlCv@Z~pz40zSWi)JWJk`P? zJ{8LA+bQL=>EbwhBTR0Y|M&E<-cU6E6Z+UsJ>uy6H|b-?VBc&}0Ex(Nn_r640X8vi zbRR++!f>oKb7|#=TQMK~qr-}MI{KTkVutV}7Z#=!b4Ju*#k>f_Va4px-)+Ur;Cndr z4E#`^zZNva?9-*n-?$a?U@$r0_kQdIEmP6CY@Z z7f(A1Prmn>Jb5DB=1D5jx_DBGkL1aGp#NXBSIzGBAGBB9CW#%@UUdxevml@HT;A0l{3>JJZm7eN_cW*n>*YB{b5D5+ydKRjE3-R=<61qPx&5BU5g(I zPaTZRDHXc;`lnATw~e%Zye%y6N4bX^;bfb{OcU(_py~7+4|$?YiaoT^=|dX~9KiAjrP{;{ zSy{v=!UYrByBOA!pB~AA?yl2;u&EpI5RvYp>!C|3@59;mFJzocP)?U zYC;Dp90Mi%GmNnoC3I^ago8;DMOI;Wnh_F!6vm{b?|+!eRjn=!*KQ(xaD3gh3f4=B32hd&I1C z6RSCVXZ4kpXcHVVPUB%aiH@San}FagTuOv@bWNkS8oAYr2`tG@w7)KyeE*8pzevt) zGgKLd(|4`Pz#`;F-?QYeou{mwvF$dyQ}`Hl4#gYa4{2%R|$UA30A=r>a1i| zl=~LlO{NBbw=YBArKM&b@J11^I&h8Ox$8fkw z%h-2l?3clOV&2IVeGGr!i-(YkV^2y_{C+C<3+E?-k)cmroo+T^itjv-k9PTYL0nE) zop5Xf&fk#TO!l#t;f|A`35fIHts9plLJqJ)8evW;xWgWa9~*$g*uBf>t=V`qA}`9w z8g#Yio<&>e4R1+_MvH1X_0sSm%n#}n-ft{VVuP*mg1SYn9m-&IT^%X*z`Kxz11zvl zDAWtPay^NhIN%iYBo~Gb1*EY(E_-f1FT{~#72IU3yCzQe6KziYrQXp~4|SptvO?H% z&W&$4+`l*t1Md zv5FTk0XVrv^a2#BB_e}Nmhb?FYJUs7v+FYm#NTy=zqT3Aqo5-J!36!1<>?vl7U7)p zkig~Z@?Y}=qidaO>!;KiQW#wSuJRx$UXLZc;Y2JEoc^|-INekID2-ZfZ0RocEni*YJ z7}Z-6Lth%zUnh!8ze0HLp0GD(j+>6NKWq?fqHl(bJi{Nm~b{;W2 zJ%e3D9-zqnW4YLHfa0a?F&4Cp!A2cRR0o2{`yBGc9_fVLB&K<^!f*N4Fn{i%eiX@h z<|z(MwPHANspMb|3Hu>iD{hjP)mDIUJkJQ~!ldmfD6I_7`_@2}E9#Vkp6K<`&ZcR`o}T;ep#yU&%OB+#Jsd@6bfc%hhU~**lSOr#=w+fbX|u}Nl?3zWp|0BE_nj2$~|rP$3YIht80?c zZFv@YL2?QXeM<587pd=vXrEV*(Ybtc^YVR(r6bDsHN{?Nj88@wN6p9@VpB=zHM>I8 zXZ{MA!%%Zrg|>;+m|4(cQqVEmvtz!ATx7M-F-s%EJ*#(kKFixS>fR{#iXSnL{*C4_ zA}$X(&60J<<6%3GvC)^2$0D-HSZ_kn&r(^LX z2X?ZwsT}ztZEmRqOZ8AkmafLU(bQyVQ^nHQ<*v-+;DQV>xO{*KvGL4sW)mi%6g8Qs zR!VHju|`S>bjTF(JP2T{AwV8#J12wUiNyzGiMR5}PQ~Ta{cRnHa*QFOxDa3|!D2IP zp{|a`juK2QfMa;lGWI3s*z%3H!LcP%JWq=%X84}JwsYN|G~h8cp4^D&0((5kSHp=l z{;1VQCVH)15-dQ{wF*Ert5ZEza5We*E<$%e5Zw3TFPQdaSSU{A1WRxnDbPGt#mBYL zpXIIRDZ;?JO&!NOr3VpGjwJ=0-#AgS1!`u^@Ai23SVWb78tZ3`hb2(Ioa5m!l)p=T z@i1Bb-rl*T8C_U`t?*SGp#t+-yDKmS??Su@Gk^0U0+5YKhfQIz57(e{)=w~A^>o{h&A$a{Q`q>zWTx0s# z^O%1R*Uz42T+jcSezpP<)>wJBVfy=@)z7AK!aXkiY$#GRs-L~pfPR+K!cO4O&kiM< z?Ts->>1Quw9=m?_O3Mbv(0p+nh;R(uwijcl%N}d@=buArJbGVRCQbb;Gp;`$uYUGo z3P%SVV5s%8nV2GuqMtp00o^egHKL!r0}lRs`k4nsYd}BShQ1T0pUpy{8`sYsIMW)0 zj;^15)v952X1!>_dF;sg*-lIq$ElxnnTl5Z@6^v)HBzB%A{(Xs&**1=fm}DN1AYWI zsWXq?q@T?Ik;YY~!}PQ2N5RtHteO=>kt)D#)u+q=+;q-HL zv?J+feVa8nwq%L}@WOIzdF)5Ge)dj<8c*IuF1CJ9e2n@TRvn$t>!424+90(-hSTU`bS)yFW%baHK_|cMA8;(|Q4q_kO>w$T?LCfYVyf<)|@ zKkaOXrl~*;UFSs~(LTy*9o;@U0Y>cKtbac+3A}Dd|Gt|a{&)269nD?(_eQ+_7X5n< z`fg+TYzL?dhwI<%0sY_8zxy4byu%r;^FL}IO-7E#r+;t79Mh=&O(Sf)ee|Ed9<&lT z^zR7(oA%L6rGIyX#r#<9qh0C`Hf$gL9Cmj0#Npc;*S~`kIP}zt%ZMuv;-Y=@-_^f6 zVN!$s9XCofZXEpuqrGdOY0xoG;?`N*~pU{@W^H#<~5A-T=ilZWC!XL){+?`(LFeN+3j350$`?7sxJ_CW`9+r>etwb9JFlO4fDzpfyp_=h`ywK-H;G%&x-y3qiSS*N z$DLwyZXj<5j>FmEI>D&zLCBLn!3dKT55DnM+zfdX?a3t?H?G1P_cw(aKfQ>jNgO_Y z!)WyZPcecgy$G8-aEGOwMCFB9<+V7p>3eL{tZ8nPe*@?I`arh>-bZf-MiGpyI4TCa zQn(`_(knU8jeAJb0(pB%`*8b>A&LEtv$IalD=gFzLWmQOwC=#epKc}d0+C+W_qYOQ zihpW^PKhQljpuz3!4`lq7vLP4Q}E!O@)YKsKm=z1VLPPZ`M?Mb#6AP~^I_h_*-$)g zs2Su5XU0csfXOWqQL5KP^!?{;3V8b+RA&qY+o?kc=kF(1(d29*_^uRNIlqZTbO&II z!-Iz(2<7KSh+^z!Xodr!`hcbWaE}b!E`@V#Vs82aZTi^rqMEHVQ{19yV~1#_dCHU@ z`-T}3j`K_saE#4KAX}J?Dsi8$^OUPfv;APtL&Nb(wC6jk2pC?QR;w;mUXsf?e7Wx+ zx@?+yKr{vyAR#-+)bHEL zQLGHV?)aEDPPOZ+E`&xz2bBzlwWLeJ;qjS_)3Cvr8k}W=(}B&Rq8Q_o6H4{bEz6;Z z;6t*;m!UQ`8QSF`?<&s529r+-d-~>Lo3m;zMAU@G8~QnV|6ax1@*3=P+ayLI3)b|; zC!Fyi+$4=H!qB3lKHzixa8O*&(lB18CqVJ`7M^fc+622UAO+~V1qLrO3gdiK?u@~1 zI{4JHl2}}V!4R@2OTVSN-T;MxI^m}J&En_I%&~7WB2V1;QQqV!;1D_7hWsz$fe}2> z?g= zsr+*~pk7+#pM_`a3YXgt!3K<16Tp|z^6oJm=Ta|y@EzdMGD0tE573L!8$n-0B^nQ% zU$n$`l?PS;B?x#a0A=42YR;2><$&UyavmU1l_PBy^X7DOAyA0J#L^_LTmhVnM=I~| zH18EZW7d!EJB6-&ES5EJ7lB&=gbIJfSWtqWE=9b7{JC8bO9h5nq(!SGhEDS#)BM8; zd7qG%oRF1-gaJ`x(B8$-ha^JIhEg+|^Wme?*-%EV8W_Dnp?o;TL`eY(RsTrNTr1fx z(t<2Y2mdIx)6`!zEZW7H`;E-KjROLgq_~#Aedr)&< z<0MmzNFZaR_=N?6Ll7_}l2U)u>@Z>Vm31H(opmzU!kQ+O(aVeeK^aDNGw`z+UFDcc zk=Q^f#vE3PwTNOntQ6~zPxLgF0+}*z{?qv*dp>R^2>*y7)FZ*W^y7+(44zDVY$d%@ zOQDlrA3`2o{6cI|uN*qoVJpI=TV*6`cfr3&lI`^>^#1T0n9tF4sR+bIxGvcsHh!s{? z<1DOEaahBMb%(;rv9NjoOR?h;3zq9lDF?)nOxsPR-G8si%3bifskCjav|j<{YWHzW z`ooEm9p76?|LH(u5Fn9ODWpjjZ>xX=w+Z+-#)AC~FvNgGa)w)=kVUJDckar9(4o+_ z`lqIn;#f&h&!ndz=r4K)AgXwX#-2r-0ZyE@#PKI+X$HKDD5rK2LP!Oor^03_Il@jib~W!vyU|Aogmrv`UsQbZ(7LI6`n}I zG!T7KAyrsNAvY2i;L#C4vg*wsrRYs6S&^0OYIic8Vi*0LGg&$z8BRzhAtyQ^S%f4g z(!DLA*o*i8Qz%gETq12qk#*~6A+2#E5^D~VLDkj}zkulWM!ann>;Pc6i2~*XRN)H?{0+dk{X(~QXrsK$J-NP8 zknlzvIR@;`R!#nCaSG$oE~4;MGN5#{P#&@JPPJe!TglAHpGnJ9(!CZ7`ddkNSg_mT zlR{yI{HvrNT4=2uXlTJ?BBd*&ITq6QGVH)y!aR{eq=UHP4&{H*LR#uZN+Z(e3Tdo` z^pYDXok(vfq^m8Yac-ncB28CF=U7Msh$JVEbPIMLU~=+kZ-E9`w7STdBUD}g6tBaH zUZeij@|{2P}%yO^U@9#RnRqIExgoR}?R@QeR|iCoP{Nj>E|*z&duSDx zW7Yu+cA}NdxsW8>b{G267pkg%W;S!$fh!R~VYS8BZ$UwEW41-1PQsYeW(#k+l~bjK zHw!Q&IPRS0GpBNu)14ND2Z1e%dZk6+PK$sZHmaD?uToxghuJ#$4m9-rl|;%=NGDlH z9oxi^oA&sz*s%<1GMw^K>M`8WJs?G~>Sb|uODXbSQ ztZQv7PQSZ|beBRJYawO1k@gX(KqBd0awSxv=y@vHRaUZ7>}0Z>DTqXkwpLiZEvz5m z64Op%C?n-o3hQwTYiS(TRAPNc%WNcPoQ3tFhrJU#s6-{fVQCq`*~m2M z@QmbH_@xD7K7RR+rl>OfHg09g(6pUalV{n^E-TY(R=t~h=l*C!o|Xl`UOSfZQdvqZ zIn$sSMbA;?zS=7Hw{T{u5wMR1OF&&Lk+0)+iYFMM8{LIJsC24@_!lI$L<|h9BG&s7 zOJ{lpGnL`Jrt$Q2LjDXKOQtq6)zi*YUgA9BgtQ@qEpOT(MJqyvI3X4iE@M{UPDwWSY+s3_=O4x)_99 zrpnaeX0zlcSWUd%f}Lv7^=flRG1KDG5Y}h*5Hsy(EGLZG{_q&MYrRzA2NLl+=%+v| zwF>&8^qAXAgc4#ckyxhuL7`Ij5=L^av@$5w8Gv~99*g{=iu^ei+QSMh4dc>j=#SAm z6v7Kug?iX@*#BoT`+R5i9hrSkmF!}xRnKrItKw?Cg+l6VAtktx))9&KU|W3OOvoDi z0ZVpRMS9L=35z6%^mm0+W+C1Fi(9Pfka={9!g|@NKI0LTmQiWJhD#X5s@#HI2bk0m z9<)Gxtx~v^j2YxmXPJ?1pcYX7qODcdZ&{W9(Jr8z|3)(1R*YO$?Z*LvV+{92KLr#s zhMv3LhaMHJ0th91+Ny7<^n}wE)OL_5WFwJ<68vFSu>-`D-V_QxcO*jM%aBuS1kxs0 zX|F+A*7!X+?!C+6!v)&&TTqOoeti?OFsB(*Q~V5W95(S}SsI^v44sPXB-hy!JEB0g zPYb)nW+E$V6APZ5n^-#k3jrV}#oEVCjHSfd##%S9SuRDaI>2gg5`*7wmr!{vH^&b& zuwyXf+*DS8Q(o!Z8=DO0pL7dw&kBMfv%uH{{N{3MBOspuwbKxVfmfj*!|-;)<|6J_ z?Mx>IHyVW!Gr*VWntgC;f6Y6>FJ%K@TEWT}H`K!t-xJE9^hJUSe2wGb)RLi>=?Ddr z;ceZH(Jfi;*zeE#&Vw!Be=Emr=h#`de*^1ZD+aGpuHtL;ZxMbgUH(et{LDo`l;e|6 zbb8Wf9LZUMR;I7c4}L-nMKz``(+7-OIkeXj?(y;io?vHU{^QGoxH?G80HUbDbF2>qje9c^(+u;C`J!6e<+^T|@^c)-XN?BNMmlSo@7+{0iF?fiFKJe8m)5Nfw6HC(sxOM#02foEchflLm)V zf^8&+aY>WfBmLBR)DIrkTGk$Cy4Q=h)|p+aIVm8(P%H*0HV;T*4xWg#vQ{ynbQE2@ z&ig4WMM*dZyOlHmBhe_ckZTno1{ZPCtG{zv(9Z@)!V92My4e#bmYWWzE7RQfGinlA=3r)$nK_wR%oa3< zqeSr*$Y^HL*Q%K*H|xc*v8~NUd4$LBzi{xd8*~2WXBI8hCiTVn;Mrn;V{emtbMQpO zmCLmJ->2js@eUjW>r0ANyqX>FmM<$+E1v&}rRGq{@c=`)Yd^C(|3n>h63I!|LNyd= zl)Bhjv*sE?R1^WI3_~H|tCxKlql@Fb71^Hp{O0rqS~Lw3`sZs@i>8Q=!SExrXo~C| zV~LKccirP`(OV>uYdCjo63>E;JZHe{i|^_l_0o^52$hk(no3wg*kM}h4%5{v4%_%1 zWWqMaP*|GLT6_e;R);|ntHa1}c~>*11yf`*r&|+ljd&BSW_1=GPbWV7)FxB8Ytt&W@%Jbj20iCnF-0HncP0X#;Z5^TM88h$&^&KEN zP%B>8eXw3H|Ck;Q@~8Q0N`zjRNdsXS;M@b?oy@!#>5}D&bjboKbFSy?-IKF7CT4SW z$MKo^wj5yP7qJ8556(JD_LR!4s%dJgY74!d$DFpt{4V!Eq=^>+VEQc42e~;Ij3p~7 z7W9J0la{geQuu1b`%Mwlb9>*dwvcg?O50H}($LvF{wu1=IPR1~Tynf$L^ie2|tkzEC5 z{5|$ZlyA?H-S-!pC}z`4NR~(Utx3p{*V1rgAwOtRh@15@(O%T6ve+loy#E3k7=nw@ z1t*7kypx}&s6lYvsY6L1RIqc=`T&i=pjj2?|giCV^sf1ZIAzW)$S@4)$P1mjSGc4a*kIBEY>Cz}QD9R186zwW1$hg%5w2 z;Mygs8+wLg|BX4`&ZObQwIAh|tCRp;xQoTp<84FxQRH|%lLi;0x9C-=clUTaRnpuf zw&LD)K$K%jSCZ1adyRbPVo8tu=vN&FMHxOuaTQ=j4phn~QPW_w(w&#PC z3ZFp}G@zrOaV4rLB{uZ6cv;rf65pMe5mnW-Rxaa;AV7L_x+sug1e-w~if^hBPlCPd zaC;Uh_Wpq1p@>f`-<}^|UVU|985h75LKHKLYg;`SHB`(AS2&8f7tFFI?o2VzUChk- z%5|u-tC+d6nE5DX>=RYYD|IpZvzWF%&He9_wo~*GIOx_rmCcPZok^au&?qy1$MKz3 zw=zE9A0DTwrvz-w>UE@wz3t?GXII6rK#Fks!b$o#5Pncbrlp;fW}uRrk%Oa>)8)!E z*b2ibix0u65r;ljmA&;n)h0LM_po@)|JnL3bv9(rADj(|`o2U3qLKQFqt~~suJ5RY zs=mYV>#ncWKX-u|`m4KtZn>O&ev|08-Rz%d1QetfAy)s~hs1RMSsIhI9<%5tP@Wy* zL9%+c^|{w%UbW&tj65*MmlUFzM>1giw&X+YW{oM3M=+r|kdgC;t)J4ybrD}NmHP08iM5e427b2zIe#LS1vFks_&$`r#mM;8( zjpA?A`0Jxi`X!Cxzp3%xaN!S&!*}yzuuQW_T!%DDeuint?SxqT9Vw|a#1A*UHac}P zi(ZC?{3M+8#)00^Z{-E9zX2;LYUZc8(0u!ae_$0_<#ukvoWZ0hR95K z7=TFXy#A;ZX4@3;sca^_Fi8{FKnYU(mQ!sSv>w*fZFI>Bo*>n)Tx&@J^HzsdN(01V z7%L-Qj_nB!>ol)3qt$r zpP3;GBAS4lrG70FKdzuQ^}T35w;dKP%PvCp!EFS*ix0XcpivMy0HsV(sKS@nyjV5R z#T-7r%l`0SiF1F0HQvoa8jPPdzwI`DLrTUbQTd%&{y7@*=2o^kmxq7VkQXI{wSHAY zo(Dv-;aLp`0iX)Z2!gfv|0665VeydOkNGTnja&&jH`qYqrop5aXN#4~O#;o`1nMhi z%hX~8Fk%b27JLs+Oj9>U%}@{BjM_W&53BwwRsF5^y14gU>OEfmH&DPp|26PN*78#g zcnSd3Ay#V0BtTTXy^#NXpqKBR`!j0r1tJRLx_~vm+2dK?Le)Pn0~x!2CP1fi_D>tX zoyPCr!lyCPiEq_61s~AtMnGV%((Zgc>0U_Df$n(=;y}K zx6AW{#=p#kpC5;ByZ>Rl!%i^x4IZL}AZLbb&Yj|NBv)Nd zHSkWc|7#RR4l567oUP06@;QPqAm@8aUhv5w66ZM z&~iDN;?%4`zQJla8wmYMyHh%sCCTjI{p31Bd{<2dOVgaDiPI|^pjkPL87~)~0YCPt zq#{<~Sy9&aJ^VN8Bz*XLLtd^ty+4!ZGD*X3d_?zSKl|F{^uPvcy zE7M^=A=0UCIYdK70%Ap?7HQy30NQb=Mz~BM2k2@l9u?DqI=32nk+d(_<(uSFOaI)b%Fw`i%dLO*(y1S{==IQ$ z*Ie`x5Pxtq{d1pgp9_)Fmd9kIboNKP{-0_5mM;91M)BX)`0L@rwdtodivNhlf5U~J z-YEXn8vj8Ter6ngy#CNhrrIP5kV;9*2^w-MAhMG**MO^tqM8W$Lly{=rHH?b(;cWl zTjNW7et*+qxArSDzgIP6Hy|><-)q3vM6vSAJ+}Pp_9?wY$>)u92V43>KFB!72OIw^ znJw0L$kxUm7{@;w|B$ACz(v0#4xhudytvqXJ|s?-*QQcEK+=8;)8{ZI=UI`M+h~@< zZsjwjLpsegxufvn`h_f_{;tl3&$7+D((|Vdh@`i+Mu_)-4$V8^S~##Vx5lNU`k4KO znyLPEjZ{w?Xg@leF$bS^5xKfkv}dj5Jl#=4ngF7kOKp-G$GWH~7n-!R9z()7$!5|l z`^dW{KHbHYBPF(&4rmPL4%Eu;#C!I2RkS`VTBXuYVBePBZxm?Sg{na1@JA~Fo~R-B z1EPvJPD5@cj#}wSWw$KDNtRuz0)(`WpF(oCy0&V7KW0HDztCjy97=g@4F z0qx3I>?mTfO%d?9&Wq-SwvPOJYTA9R{JolXww1q6&C4GUD=c`YO-?y(AC0vpbBJ6#o^Cf1?Y3SEJ>*Pvf8M!rvE%uk`U< z@OWS>>Z_CNh1*zHfsVE0L^Tj{eTJLrWxUXtj0l?ePZJNGtOSWA!hpr#iC7^f;fYw! zyrxDL-<7WO<2K8lS1aDIGeg^_fJ(#ss@C`qy6_ox-Z1`8y;OT#=E6^J6#w)bg@3jS zpE0pcc|zEk3V4t)>E5|jH^>tutnp<&&sA{Tzxx0C`*F_ixn##t=l8MiP%e&neoy`< z&@p4C7d1M+U-btiL%#+ZoZqRUG+^80y8LO`EjNjF((g;-VMs%Ka7A+zN}Wi6aw%>U z3mN=iUrf+&kWY~&(H72sJILn(Ne6~S&Q9f|gGGLFtV#ANHMZd%3GUsk%m))4jxa3m z;RVClKU&EU`@p`2*B`Y~M&a*)+g&LOH5$^35NrKmAP0Adj73kLck;QG;_MBMtq!Fp zI(4*n-a62txQ|+k|IC5N!s#z6QSa0i)8qZ8JR?7at0`M+L~t6MzC60` zLCGjHmTxB3FFsYZPAwi2B4XEJ)AOy*#gk3sP$ALJY7yWk3M zJ;c4DM}-3L%Q3`_12&I$Y42pg?AZv1tcoQ`Y0x@F{P{8Vcz$n|8b98k!`2%A%Sc!b zAo1(ZLXH2R3x8@Hz8s&+x0f^^-2)-ZUP)w=xC72?8HJZ=?XiHnm%$79RQ`~4tR`Yz=TN!@{XKp3R>5}1r!4_aqiJT+E?;t$v(a*oE zy6uzrRrOc;S7ZH^{(iY3equ17Dh=&OL4DV78b5G3)2!C-BB2X-|h$|B0{ls z+)5%Y?(+pSsulM+kP7;OH&NI~PL9lRljwl%)GH{Pi8Bg zL;A@(N-JWIO1dJ1chY_7B~^L9ficVKe=;7(R0g;7WGy#|F&~-zd98*#4bQOMpXVbd z#8;q8%Q3>C-`Vo_tV~%e&IT=8{;H7DDSyiTFll=+%;z{!)aDgVTQO*&&rG_@t4@Te zgUldYYqOM{%%och#*UqDDM}2CsmS<=kN8bwLj0!S*O*_nFd-oeUwD8E{YeNe$ixr+ zlSn=Az+FC7cpr*yALCb@B|``k&E#(+^{aCzm+#4~K}KY{1dG3cFGkn|&dFdQ-^Kq4 z3-|{YX7R6l9-c5fK@_ob!3HEFH8f@9Ih$zsXC8dRa`1+VMEI}g=nQrE1PrUiD9lZ= zFc0yZ8(jQ@dw@g}*>5Fejw)M%gy>wt)79Q4)Q8@8qg%C69c_A7^+z9m_#t4Db>Jc* zU`9G4G3@+P_xDi!a+tUtmDaH)#q1(Oz%R3$h_k>nm-?YbhN&C#iI^;fKw7>BAp`X4 z(PSKsiDDa>v^X@Bpl~*|NNPkAGQ`)Qp)u2$E5q%~ToE*%PHS;KS))^+7=es@(NbrP zSIMc3Vjm&MI?c{Homo>z9HWwx`Is-HF&gAsYx2knv#AJc@_0q)pZJ@6WoaR;EA)OWqTx^dEWyGs*DAAe;9D>{Mj-*+55mWHR z?kU*gz@DN*0ojpcr>qhAf5XtygoD5eYCn?pU5a)gD8vTG2F9+_`tw!Pj4x%55Ir)6 z|HKslM8D)kNj+mdVrOeyM5pf+?KCdiPvV|N-1CTQW~pv;au@x>*Od~U@|+rslJ#!_ ze(m^m8E*%v<{H(mDB9OB1;A=Av`ER>*jPZPFh{wCACPO>FPtt~e`tzXLmP39B{?09I`z z)}Ch7vN)n#!f_wt05Q|iX6?JHx*^Jw-Z57`#tK&p#Z{+agf)P<$F&^%z$NRPko)M^5cT75qegJBI)|0k!Ag#(e=l#+8>}} z7!PYu1GP_=wcjM>ET?GJV*0!+*$!;HLO+{Zlp1Q#YtD2x==8PvH4!>GIHs}ADsCWGQKLao+c`7gv15+g+{3oX=w%7#K zVv6@@u`*rwVQjHt(N>oouX8fWkT82q_Nv0{DscvCp@q7bB2j{GXs1#hRG#YBL=15+ z(rYw(%8^Kp`KE(L*YnNuD-^%%`DP_cf%&Ekd6?9!@yi}6INxa6DduFe;tbUoda~)P z>!T-|iSpGs*-T|M%&GmaZ@lpaCLl7+G3Brnu#RBQ+~HGB&)4E67B+zyV~$7Np5OoJ z@QFoFTHF7q#`mnJl+0>jekF~&a>KWo20HPZ)eNg6iKdDl0)4yBrtMv8% zu)Gv!DE?}B*|Qq0F~b;FVAY) zT3&w8w6(lkNy0dLIo(oDj#*xk8l2+{qlKNG!tZTcomsu z`WLvJ+_`>H{u6HS!3fV08DsDdlm|?zSxBj@BAYa%vxG3d>T?ZgEg=l;cwa*fEMe;t zGMkMFI+@kxkc&X0=kiekEWDh1%#|&`48ri$e`EVgton1$IqeUw_1;VADu-vSlHM$9 zjrb=*Ec*>Noi`RwZ(1@=m$YymI#McrjpkN##?v4*T+fWbaKvkDmbF7XC+lnRw*R|qnhf~K^+J|+=p!y}g07D&9+CZpcf$;6@76=jtSSGR`NV~?{Bb|BX3Fr|I_%dQ@Q=^i&#@@_dp>y|a*^_i+SXxE`r z<$n{Y+2Xq+ru^FSSkqa_<2Dq^<`;R(4f&G01PI8wyzCS1S8y&}5`p~(L{yN`A`KZJ$v%w3qxBWwSkbg6|8N_} zmc`H?)HUFx>C(h!EB)}kCI`=#EM(-wV5Gn?;IMCeVc<}7>QOkt5Bi?GY=$8DoDy3k ze6Nt1wc-X|q{*DjZ{%?0bT!WO#z&`r-R4J?=Eob0ocykWHtFPtjsL91f6#@$E)L)7 zkDKwq)gK1w^etWKMO=D2zi)N>zAv5E=J-^HNDpWKQR9=t-}YapsxJR2oY>0W_nn4R zO9%(2^&0XIK;%gDsRq0ZfF2bB;m{1oMkDS%%m1Lp8#A89v1)~~Oo4e^Q*KYnGAgZm zCsn{EGA}qc90HRn+c8dJx;7*+S(e1$j(FZm&lBuFH}3}76Iw6#rJ8p~q{OPki7zQ} zIXg#+i}i`pa_clDEp745-G8#H-2Rs1eYe|lt8UM;UG2$Z9Gw0n+ut)zeu?+@XnVKw z4sC82!@&f!UQU1l(9i`;QfRQAeO`ao7ch0fyQ?Rr1(W4YeHy#BynwN!GTxu0$7_2s z^yvmZeE}Po{*Fbbs0Qx(E+Le+Q*@Kp&v%H|q%u?x6CJ$C^0EbWK0nqIj48L|OWSWJ zZKp}^FoQvbH25Khu{zI>P>RrUb!a)ypui}fy+{0o$_36pB9iHM87-RuR%aAJ%&jpC zX4#xm>MN(BfQ}{HbeUPOEmmv*Ix8%8@je!uZ7)D&kYz*`nK*ny%_6L2W} z;s#8TML6OfEw2`hhb^82@`+xGa>>k8fmtkbd5WyMoUCMNB(f4`LF$;xNP8J7z5$FG zu!hJ0al9%su^u0yTL48$h$r|b^_A!+0IBx?RG76;VWRK3uvQcFIzcE(8GiW>kN;U7 z_F*HVlh{0bo$?jO!&E4BN9N&X6b^F>(LDNz2$Hs5t5HVlm?P z(4AcOnS(&4^w(|@?^U!@`yI544eB_pb-$)kPB)3KfhK3OpEY160IF>nz)u0?{oWK; zrBE}(N^fAX#vA3I&Xq1ax9!QYsc>nZj&g%dscFoLLy9)HS3%U-sAt)YYsKf~7)Pw~*y|6d$T-a4Gk*g|)95~tMO#C< zG&rDW-jmFtO`WS6&??&RunF3dB=2!RbjMZsq2>N?GrZsoo7n4O{4=WBPo0Cq z&O&Q3h2XY0Ptc%#{`gb)7Rh#NCc1jHZiDP3ebhmG~u;^sF|ilnjM zgPNV!)#PpuWTW>-Z&CZB&ju!tWDChsZcokgRv&cTa^%n zL!i;>&h&*#G)qD?c6F-7rBABLUw^h%Y0Yj0S5mFueU^$PsB76o<$p24{nMe*TH_1e zGvnT~T<@WMd-~%>9yr^pa`8X!*2y<&EdMgnC*vj>EOjc#BV~WURbQ5|WINor;v_Uj zs42SgR@s&JiW~y^CIa%6hMX=TU}w%&Fc|_WPLL4z+;eI*PW?Za3IhoT)SM+6x`3Ko zs4oOAXMqNNE)lVDh3080^j3YfK8d}FFgL`$9@4*fFDVa>ngkY;1pqil}xjK>uJ}~pt>+0+C|LKt` z!d@{C)xix_v)<`|Tb8PDxmC059Y#23Cf~!Uui}UNS`BidMi@ z7GY?mM*5l6(oNc;rF*=oTbf>d(!HDj+0uhGBu_%v(kJPbK1)K_(ycWlRYFn#X`&%b zC8T{IbT=+bx-A_tkcqF`Pf)ph_jl&<|JZvM@F{Z3VNSM^NKB;B3&{r3NSf1ZcwOi$H0RlmBOI_K0Ww8+4}h&O*Gnasc~Sq%gK zEMBc(iAt?Ci~243>xdc{-I4ZTq>W#RgmilozF*#%GZ@42Qh{y~)T-E+{~e|;9S z@DF6nq7ED2!E~UCDXvcHu&1E@R)_ue7PG^Sy)~)BPCQTTupOu@v7B8?>>c)7`X0;Q zjt6y(LJ*11Z6K^Ob=Z}2%no}^OzE)SqcFA(dk%i34tqD!Tk{i_pO}IXYg!X^m+NT3^d`a#tGFb?DTLVR6D;}tZ=vNyv65d)z$8wNfmUQgq%saq`Q#8Y0x zUv&${rlB9?*Rhl=j>{VSf?$5R;a(e+I9{EKqQ@co#e(ATu<3ITzkIwM&fa2w+!Uw& z56xK6m{tJN=uY`3NzyYjkv>q6CjOH24vbc4=7{v;Xe~~<2S}q=<~Ok)S*Z`tM0y!Z zhdISY`j3)y#3Ee?(nTPBizK~*Tny3yQYlCie_86$lJxgLikBK!LQcbEkl#domB-Av z0;I#eD@5?QaP~&MB*1}Q&Jw{N9w{Wb%|*ICQtChyQ1;>g4$c+vcUjN}ZW-AbQv9C%1{ne27WyRMTL>|QQ4cQa7hE_$+vIed%IV~coU#O`1{)aNm& zK=;%XKhw@>S~gg%gO%k8>a^hfzhHPH6|5yY%YP?KDjsmgxfsdJ! z34JA`c0WpQhLiO3Bc>aA^%Z}WYtH`G{AKD_3mvQ@w9c%i`Dz)HoV&2!;_oY@ik}$AUsGxy3KN2|Wd(?8{NEpIt7V z|G<;m|7iUd_bDRG|A7GG4I;aUChraSO5i@n-V8^u$blb=SJjL+Yl8LS)#dz^+5}~g zXU+3yJClV)s_@zX7?!Y%#Bg*DXLzWjez%|=5Y%yVa~`ehK(+%iTLb-B{GMU;=5aGW zXwT^%05Ex%r6`>*(OYvA&LcW70h1f}3QSn`xUYFk-%vn1jCi{nS$}2rLg?=url;Jp z*ie*nT}R@|7K1LCN{N;1cogR`mK-{Dq~(Pqx$1WImQApIF(61|Uv3PwHGM8?dNKk* zXpdLaV{d83w_xixhCoUq6v!Dg)(>SpgV<32r+H=qyd9k8nY<{H4(uk%xg4o@IjM90 z0uLGj69k&#zX8s4J#WzHhb0DMCO^)87WA_+(tnYXg2;Fq{l`@L`vDQBKP>PL^M1yP${-`qe56}}3<$(dFl>A#%2JDR?NR&BbBVjgDQ_F0i%W0 zQN)9U(wNGlZ$=&y1dm!9kF!)By2=AFHkMT$4IYD39xKUqowm(82_8q;&kts*$K`^@ z1vVaGl}8Vi$Fal%Ye@d7Dv$dz^3Vj2ACOAcV~Sj1Th(XCEN z%Ys&l7saxBo5g}wipNwI1HnQ}Q^ns0wY=ej&A<`)hRWz|GD17H`(Ti~R4_WmWW<9? zL@^8oo~g3y0Cw!Ryygx(4VZQXQ(|3eu|7;?eQrk9-?ro3;Yp-oFeF(z1MUuW8_igcvsiD>COkwPe}b7jeT%N7q!?vm9a#T`krCs0fHUiHfOP_3 zy;Ehm2rN@JHC(8fEckteBz!awrejr3%K^8*bb?L(Dqy==h~DOIcH>+~(yDx21Um6K zuy=FiNH4)`5_`jh=^ocL;p*5L^8>XZA3 z;c%*m$#ExtMM^a@)ffC#Azqnk#YaM3<<*P5%KC9{)+HgCQAPae?@pL{F#$q#a|I# zwIX9Je?@p*FJ3*wUlCq&#H$AWitwruujcSqgx59V)s_4eZm#D*DEf9=|2Z4!c;|~(NAOpK_rc=Tf&3NWeXV%43#MYxJtvD-U-DPfJ*SFSYxpardtyIp z>62T~N3q@1Bf!(zp&pEKI8Ai9Y&SKBl47Epf>d(inaBtT1yK+k8WT@$(ArInRO$Z% z#Z8&jIPuw@F36TB@ zL^-4+mG@+%aDs?_`V4@OWK#&i-`wEU(3nT57_UpnXzL(v6tYIUKuizIkV-aMkP#3Z zZUzV7S_r+fxxst%M}@(@yD~ADOG#1A^KA^SU<3q%<0J!fgZK76g~9JLGWZiE1%n@v zO4i_JMnEul1MrC&bVGAsnC8z?8JwDy0d2p+g27!D18Rg*R0bDP#}$oG01mXl`?bp9 zW3o{@HUe?j`xCFiNj45&(p$(}teJNKK9fTaaG=ij!S@PCGr=Kc?C@UnB&7pF?<0xq zMfb4Wg8aP-`9j;^>BB^VVkr{5eJ!d2grD$<;KyFoUo$g|DBdoQ&=07mH`Q*H;R?_ zaio%+X*wey7+enq=uFTESsI&jRR&vOMRl$LF*rsr7-3`3Rb|jaGB5}9k)ov;L^o$- zutPw!8L4CqK2srj0qBVum;?G%_Pda0kITs5KEa^g#-LVZFkUh+2lSX7N*laE7HY>v zCW!h{QZ#arjlm&|fM|m~Ku^@58Ufy-*_%hEC$3`T#Tq+s*{QZcBM z4bKgXj9_;^*g0$p$O=c}@FJDvHdr)M#vzx?PZs<}n*7*q=LnTkp{$sF7^X<(!>6Or zO#b2Pm$-mNmxC9E&C;^i8SskM>fR*3OT_=O?404=SLTKqzYbIe5e~Ua`{;v?nzTi4h-8OeVurTL$`0X@@3fmbP#ybj*Bf`YM~atWU(lDI zbTa$bUN3oXR(Cyng#-!f)6 zUGhr&QM8{9Zy$0X0;iBM6&8`LA)_22s;|$}>vw8(ceA5%yW(?En8YG{!O_MQEWWgC zWEi1Js}F@d%nqMeAzHtUZwCE%uW7_&b-ex}K389lr;G=eM&&OBlQ5f~mwZFRgem{K zlBGUn;0mq(B9;#F9}@AIhqV4x>@Cy!e{nNS%|%5KHZ#*;J(LLtjPz3c=t!DO`CjmLhB5h8SLnP@(Vkr}euwNf4=(e}f&6adO1xy@`ZnmD1Vyw=d^3#4-{h<;Y zq5RoDSREn@g>-B++N+Fa>6+pfA(8A5r?R)K)z-pR&O1b99_+UTrv0|JWU!c$*sZrf zf$hqLRP!@ZaO#JFXPmud)Sm@B3x^ajqQOPe>|QP@Q0%-KWcYs4I*&G3qKApAxGZ)| zr2b2-?pZNwFb6*7G}8Mwm`uNftdVmzdUU0(O{LQ!?OaT_ zgPNxc|DH%(lVz(u4e0_!Acic~1dHed zeP|^kFSIU@cXO$-yd`y;Zb~PgH-S%!H97Hw#032z%pR%T8LtK@k09K+GzFa{j@s2uXsa-eSTvsja_u{cmS_?q6DwJHM# z(GA9c!8kDZfc-A2@N8{5*oeVj1cNR%26w6qz5t@cpbWiv65X6S0ee(3A6yJpvs6|g zuu580;Rec7PG<`~k0OZzmC9$b*#SWQVsx_!7&(({i%Vg(hQ$TW*Ya4;Jr$s*>{m>G z%oKl)T)B8~{lL4;)ObviyS>HGe0HDK(MqC`c23N&1H^RA*M|&KBw1;OgOY zq7hvxefw#Iysr7^u7m$H;i@eh$qGI&TbcmOTU%WjWjmm(s)e;M<~vFY0< zflhqB;jh`;B2ZI1}Z^1m!zzly8@muQn-L0>iCL%wVK9EXYvkD}^{h{AHof zVQ*QXHH)+!zm`mOnC0HHm@BZ4&X=cH*6-zrIO15$htSDMZ`H%Qvk)6u4( zcA=pCCKAbF50kY21lk-CQxG^=lFmmi+c2~IiMt58*V^dr-fRuwvn;xHPsfxIHsez4 z$4q}uM}IsyIqIuBFs(#G{`ZU%Yqsgvr@@w%kT+Pmrudsk#OqIM)U&djXR_RZBJMcY z0gj5fg2m?b)*$SRM5#Cs{YI9kDL&ao|F7&V>v5mYqtco5vAJm&c&Es-iww=lzKV8t zz%iH5^pkY|c^^~5^>@<#IBB@_mncXQ{WEo4<%v2Z#$v?JE0J7L2z?g|-6hmq*a%z# zwahlD={kq9aAlcRUxqI@g&8uor6{{Bt=2yYC!~p83a!>~(rQ)T9Y%nPa9^A}V;ZfH z_BUK>9?901^YT4$pkA^@yJ;sd2kUU(6{N~SA{?RpNMAl?Ec=%ORTkTRIq9?hOpAj- z!RRbqR%yJ)cq+)YFsh03+THMDr>U%2Eq&IxralWWjDZ4+>HVY@t3YV6iWq6*+b|td zVoIz{XcDHx8dAi_6Jka`sx`K*A!B}C1XnB9EraSR3@y|%7ebHqn5oCACJmomNFbNs zei#CzvRbQimDL+~GBuxdeoMzG9b;5(8F~w|x4W}vevXdJ40hOxo;k;9w2*5(b>}&h z6hh+zNF|5ML`Fc^GiRVfL(Wp{nIlyCpI?`Weh)!^h>d;+m3~)?zO}M+`&6mG4H+3E zKH(Kuk5sY(@6%hzq|9S~35Ff7z%+Axd7k|){PYWvHEFP;7cqEl7u2t}QJ zixx>1**O=YfL8muYR}yNC~#EG&V=^{G1a_ed;XdIEYLVOBmLQe z{uCSi%T@Y8i@w#K=co++4%2k1fMa&ZqXmP5Yz*>L1{={BN$t5s?J%RkAWeI|OzF_w zpF$D|&yy^-=q)vpddBvA;sVF^M0lqZX}?sSdKmo?=j#dlcV(QpxefFgl6WrW8|8|Mekb zb8u%_k1l!D$26D8_0NEq-iYZs!nKVhP0?d`vgnb)SfGb)1d2kj2sDb3ysEW0(ogmI z2qH~0MYjxC2M2SjyI?+NN1>P<;+6QH#_~#aK;e_dw^@O~LE{~MRyaA8ENmaT&&1pE6@IfS(Mnq5NA^ zW?zz_JUxrc1&h;dEW#>_gB2E?7S7E>EG%|DEV4nV)Ai}ukRq=arA2YqA(&ZA|BrZTgD@3K&WiEl)Bt2 z?6>VjXR)Vr@^ltgs~;a5^2<GS znI&VznxPhJJHRm!7>$#-&~9Bi0gPT(8BHcey-6&?UV}QSo*n0h{z#wtpy09+sbpI& zQn~zA;bM1?&10Ptr>CT1>&4NagMXI%BI0Awg#!)?o^s%mtG5=b^45}TsD5-nIQg(A z6+J3Mt^;jFzf={u-ev7Ju_zZxt{=!1Jb>fq&T-iFK~U`iqZ6C#A{xEiy_w){$60M@g}2AML>U0Y*j$ zBR@hIabTUxSa-5m&sJHV1J(}W5Ahu>_&$v!$yFYp@+EoKfp4-vMAkLdPuNkmdq>gU zmG3u|{*e;Rj5OTVfneT0X1rw$aGd9yN@Hj^^^YK8>d0k_&r{_{OPi5^DJd(>{n{GfHM-N+yB@y81OSi&C<@yBiav5-B6O~;Hg0slwie<}W} zvk(RQ>rTOUUW}kSG216iKG%#)lC$yDra1BEq)8ur zKYPnae~jkgnylPV1v~V2qa;0&_@>y@N&9x0p!*l3kVPIT=}re-iq1*CpmKqQIXOj@ z_2@{DNY?i|`qwG~nbAE=0cjiZf6IE4@JIVSO!FKHHEIIP&}?n~4JE~d@gq{nJ|7a@ z5fWol{A&C}-7$}1H$-CdN!&j~0R#qqLT^nD>(C@vkIC(@zkkQgZofsuCL|>nEkQ zAEMWk2*v$vEM-%C0Lm*n^Bne;b>{Uzh4neo$~-JmFTIi}3|Tl1Xd zIZW{YH*M4#&e^Er=B~zVIeP7?Y-4-vM)*ALop5cZ{yRajdS>DQ%4oc-_x-;APIEoi z@&bc!WBMS-#$_ktBYbipqUsF7M|coctg@5w5k9$;-r*xWXf(aUNBHCk^bQ~4LDT6S zK5jmlmOj09+d{qe^YX!UVuSrfbP5$`#i zhBQKU5xiJ4Sy1+Z_%UVl8oK(E`ADz8Q;j!d?$2RN=1xzCF_rhOkhPBr_r8WXJ@wxj zHqhO|1_|6d%T9oHp?~5V)WXE4bkWHWG_pg+Z=hdTnHMVgMyq=Zzw^Xe-3t0!TN*t9 zK{DY-6&t~H<*!F#gTj5`{P~H#zfoKC1QLb&Za3G8{R{Nvs2%+~gM2#=mcE@7Zx*Os zfjv&p_%Ysd7`Ex8mR=dj{wBC6dPLS)4T0m(iL%Kt6S^5vX9#un!6OKik0Zv3A!9^t z#JCdr>z%x}v#n6w5b$I2)tS&_pNKEz{l6^lzqR>cQ^c?wF!#r=0I}rtuLYA1moK)x zYE5B(gwfnl2%yD!6-(C?-$#~p=G#K@#S-?G&0^Q$2O(d;3P&@+Dk-`Q&qVq`A-WKM zNqUhKT_#<@NzHZcCZT923AYBrjVM^CUz2m#nUFV>;3V#rhX19pa%Pk%VF;d&{6$1n{{S7k~#3b&WktjAEre zE*)v=b!&vUMf_#gc!9lTq<@}3bw0ib-a*tgNY;8-(ta1erZyiDULXjcU?Y5$B)o%K zp1E&Sw$OgZ2G#as`>k~P(i2IOaWzHOQPhIJ!T#!tP~%r{Z`|CBfaF3ydbaS!T)90u zSX(x-%dSS;-j;=kCu}pj5nuB#cWdRa?~%szY-mi+&Z}Ah@sHNLuOPrRzhslYQZ=U2 zO937Pun$h4=~(O+)$_M&R>0q4Im~V$7M$#SA)3ZvHG}yS1vHOedg;G>{(1OitCRKm zO@{tEkELsh&qE^F6DrwT))R)ICB^&$FGL=H3ccZ}*Dd;uWb8{(1wbw=Mu(_p>6+p_ zEc)c&dkuTb=)aG?q&WEIf=Nfy)p3kua&aam#|tLQkcd};m~@v+rrDWv#BiZ5{o%i? zO6(&es8c1VS3kwlHN`Km=+hwo9ec|v@ea$)hD#o3)5c-@3l{B%@T>E1d6Ok-ivNNX z68(R&w~TPLB;11Q^G~OPgzPWscqwJNRAtuyk!rA%0d%HI-9aKbmtcR1Z@ZWz*bx{( zP^D^$hJuTjuOTh%+DBN$CJFW*i~oEqMLDG7{XXtk;_EH5Tp`F zDBGh0dAjNoh+Q!#p{NiKeu;+!mjWH~e__>&kS*x-nRwldVDF~nszYo&kDWiM-JShB z1SZ@LNuObD#0p5W?PngP;|E-`HA@E8^Spg)~rb2pK%-;54 zZwJ#`l4+Ypv$r~XJC5FxRNFM2y`99~&PEA<@~S}fVz7?(K?AkdcYR86WAg$>BK47s zUr)xbC#3vWAkn^D{W%k76C}>=Bysla)6h9EK|a%m=i1g#1W-rvqL#zbXraj+Lycsz6&)T~{ANE)bS}*_C~K`g442qQIZU&%KaFmXmgw zcE#nC6xcn9RD4FEUGa&GfY7<#a1m2NDEIB4_}qSQ_-fqd@ahV1n)ho|T9npj2$+Iakf-U1mE zvMIiowHtVlOeLnoWb^fJS%xI@^>>UjH(wVZAU(mVk!xBmgGCPn;a=2gRaFxPA2Zzz%P_J?roRPzL!Ql=YhccDJ z0SbrF5JbkAg2=Hdn>Ax;fF!8^OSvP1;L*?G!5kSN?ol^jIDG*KVW%w>jttYr*=7%& zDf33lgW5%>pj|M1Eb7g-_zT5zws=m*)AFaI5a=zKtKfIVw+i<@ONC;J#?Ruvj4@k3 z*ESR_t~ibPNhCnQn&9)l6;)*8Gr&NpD#nq`H-?VFz2ATd|t?Aua&^$TI}p#r!1GnFGyW&5z?Rx|)Y6 zWO1)teA%8~_CJ%&?;nXX`+6*AFIkD>zj53xrqyv(-hd*#f1) zcxk*1X9m6T>zw$8VtNHhV?YrOOy}s0U%{TdLCfo)<&DZa6T;DH^cgrUl--0g(SDjsK1HpG(k_r$WJo;yB~6h-ljJfT|6E{DA;Dkj9c-9{S(Mqtj!+WBXUB zcs$w91s;n};{BrqJZ2Nkw0P_Vk^k#>?0W=wZ2U46j|Wb0fyb?w7ihe+fX5`FnHG;N zAObzP(4TPmP$+=4ewIB@qpUh z0dbJOTT%23Z0NN5%do$TRGdV5V&kij7D~k0$Ic6syru->>^y9CMwK=DD=G#rV77>g+XJvp+1^qSf4uuZeZ|2(lX^ z^w_o7WN#}o_UMhDV_Mpj6TcjOQek*_%gP9+?~%Fsa%99m_+0l|qjzl7jgjyGm>Y<- z*JC3=Ct<+b9G)_(1KH4NVF}4Uk0FR@HnIRU*RE=?MfjXifXJ5M*JWEa%7&u*@K z5gIQ{_pBr+M!-m*Ac6QN=ejD0F33wrrSyKRSe=elbJ6 zDgfA%0i+$RfPJI|9w5IF?;{nCS$?px@KwRerq$empAzrmL#-%PQXszl9M2V%fFA(* z0Q~Kz(*jN?WCVPY_j0%a9J9Gwz@4)A0DJ+wtz2|*wP#7dyKulKKII+oU1xhPha12< zxd+@Six0rNc(14goU|e6;o4ul1AZess5~~j8^B2*aXF~ z^Wp4p!2GzUAYi8;Aam?H%}bJDe)J}>yS^uLtyAoiEo zfBy`Zv(Ud$bo|Q+gbx}D{q*eP$gKgfq~e98+FdIfzv^(q+q@^yo^rvg4%)J|Imvsn^o}1&{c;e_^TF6yh=^6=(7C#nHCztS@S9-v z2W2InSLHSj3;v5_s!$B~H1ztc%-G0fjg2`trUK~`_W?G>=fF)1yXZhrTNWWF&|>N;OBcUha141gx?kbcgo@e@TqXt^4POd0Kd&g5B~~IM;^=J2Jmj~ zHz-b7d;q==K1v=dngaMS4|?z6QSaq&19-7}z@4)A06ca^8vri0;4eMk9q{(v%h3Yh zwjJS?-=m00JHo-X9pM(|#l+kZBJqF0j_^ZxRe2mHHndvU5tg=gN0^k*^N#T6Aua9D z_$XI*ghltGNreX5?T)aaMSh-kgdGlrjX?3w7W!Dq%kZ_@PS0mK^+OicLU#oqsv`kwT zhtq1YsT&9->n;W>d+yE3p8GiXRE6Qx#LK|#0ejSKK7X~z)-7qPF(o_Kv=G23?R5n~^jOqMW&n91a9yUApD;x0m_g5`|B zDNhUiBI>EtJgJ^ZnAep7w&}#mIuZbV=A#El~NQqvnRO?9*xmyV>5UOL9J{g)# zDdrP>IVq9Y;c`Uk>9s~Ka|ePoBqmy|Xk<_`F#84L}b<<2VOG@JRt;AYgJ^r@Zq-sH8 z8NRC(R@6-o4TkwIE%HvCQerK3DO>JN!kYRi(>YzDGFAJ(Yo<;k!Bil2Z>JzSm?3&D z5T#?u!Ga&O@hhx;`v(i7=m?2VFhO`ZB;Rf&*Xr)U-&Pi_hHUkT_wb?CP{PWB;}^t- z4H9AO3%o)sOoO-FB_Sr-**N_ZIH~u45BC*P z@6#D0q21^18WrRwVVPWvc{y3Ix|quS98&J*&^b(IVWF^mb_W?pe;7Svyhld_j3GtR zhJwvksUmhL0x$E!Fju;D*~}pZewDqo$j(N7a=&MdgWIN6s{`n5fP)xy@%u*)H6R$+b+X zgB!}Zsp4Qb`iG zvf54xpt_K=cA8@Q1f{Mv)8h!|u@j#{zH+UrWm>85c)p~XEh}YsVfxDnkPKhSTA8kS ziBzy1cEtG6CL%sbn8>C&TTVEk#BKO3QZWgl|JDeOK&S%z9$Pl8j{1R>RjauLUlSkV zLj^$2SMkYkjx$}Ju)A~*g30pEs)$j!EuOJnrhLv_LhM#J zE=jo}qX?@CcM@tbx38*Ep=J_|(AbPiBhlo8bF2B;dUUGA;xq;;JFL@?b3ck=*>`9V zhGL_ORf!o6N=@c&% zA|V^0E1DDoq2YR;jWD#etlc%jNH!A2%8}4sZG@NDT=H4!oJ5@$BjJ3j16Pf1hEFq1 zY4cl0;RQxPtD}WfQkkFlGrqGS5W%rmc0g&fG71LwbZ&r%v763kbJ#sPiZpu=k&>j;2gH8cPy30hY zk5-`dJhrmff)Eehy_cQ!e&DNvv9_*`-zA3o zLokhsg>fBhzNX<**uqWa3ty#%vQ9Avogx@JmQ)ryBARacu4^^4SO`^i$_Y7|BFke( zmDhg>Wf5}86LNX1k8wx#$J9pGYRI6L*p3fXBdDH`ix{iI2K1Hj!97U0!C$g25o5co zqO3>Cg5`K-PMjz@WDZ0daZ--7hEQHi*0rzhyBC_|m13-HsK68QLOzXI0A=A@p@ z&`dhe!KJUx=guN5zZ1te=Fu^ZC_l!bt8FX0b^POkbkp5rb-IJpOb0lkIf!+{qh$+G z+1XwLd3iA8Fr3a$5txf*e@U5?%oDxP4O>1cq|WAg{BdXm=opJ|K;>)Ng@h}hw)hf9 zc}?qsRzs^4kNU$+5TnZ)svtsd3udn?EBU@^MDvU^8Q*5@vw$7CAtJVXT1^dJCCEi3 z_);D|MN5^DpN}|SdK^%fuS!{L>OtQMz zL$AvYYx;Jp7txkU7#By$UZgiq#|=O&=O!6Me z2+K__X5aA{=qtjeoPBNLrGpXuldW95JbgVEF9+fY=Sh;ev$AaZ48&J(@}DeB)n`~I z?r19J8)=dhX*mlnEMdEc?nJ&aD0dH#3+R>Aau4E5@<#f%c;|}9Cya+0N=5hEUEmQaeWut^ROenv8X@N_v(>kvd?AdePxS2P-B z&}*c)1!80wz(Zym#xfl+$1~|jZ_|+0dbyt z)LKpxTFoP;NMvK~w7PVs-DzcOT?mrRiW4onnUcmzd|emmm4NvcLxCxi zQ-m40ol*u#K5vr~rgqCR9aV8M*Ai>g5G2!;IaYCMmIaBlsvwFCV0ZrzM=E78losGp z{C*B4qDcl_^olD8DGLW||Af))7lBD={IDUQK*L?l>`2)Uw{3xDV z#q%pX)2=6^A7^2Ad1*dau6&%!u5HbHR4e_ zs|raCt{z8L#txSn@=u*ejm|aZ&tOJRS!-3bInWq-NYPsQKm{w&*hQ|Vq4n2?ToMJ+GSU& z_`;S+HX!C+I-cPxIZBA*!(DK+VL1f;e~8Etip|UuQ@@Uwbr)8$xr8*1bZH5c!lSW4 zqp*k9W4*C}4FPZkCbMVd1hhI@HY~uj8k#^7MM%yGQxmZ% zwQl&D7{;juwEAA{Qi{0_Q@mBohGcRPJ2|41Af6~3$gQR1=?iDj&n!qXQ{*%%w*Se zWEKW9X%N8KDH5x@D;9y^>aqae>q=8Z>YTeI$GNIWW&yK0fk5+xDridou52A8Y8SJt zriFouiha9WUY%p8e9*)f@xgENMZ8!%`-o>Do>n|rGalmyh{%i(E2PrsdVr3ApItWY zrAVZ~+Wnnp6;uXSmv_nOv7~cZpWVSl<((tOHwoGo^7oy}jq9_@jGqv?T&p9MCW3+= zpx1t}J46>@;c8X%veAfF-03j=wA@+U^aedQ+yKonREc`_`?~R~=E@LhoJu~{wc-3y zhFa+PvZ@dHH~K?Xy!{3$3JqQZ7s29Y350dmYgZRUkB{fVQct(Y92GVSDcC4QXJ1`P zz7*g&HcK}!+Kuw8{%e~X5SJ2hSjyq4y|FmlabpOyP-Ye(ekbmgiNA;n2Ui7pP>6Ol zzNfRiqlD^5$@1!7*KVOTNH^YRK<<~yP2=t63(Z(DGbs`vb%rurKTHAm#PS%OsxG=j17DS*whTsx=LMPUZA1+vjO+falFW*SEKjA(; z;|F=dGI}1HZ%3fv!YtgPsmp_$aw=sax#rZ6D`LR;PO4YDp$5V?CVZ%Kqq3l!m8FW->^!He8@ZgAn5R2IDMdWtPW36R zH7|i9{!v3I!7(jiFP*>gzxHF=u>^e&rLl=8Vt-0gP!QJnD7AuT z)Fy1xXi1aLZ#%qvmXw zk@t3Za-YxAxN3(^9^1hwpWk-)$4@?MF2{qgR$VmSdpi{QEsd*o$n)3^PWk+{!?AnY zx*ax-^WF{*?D1I|SMAWvV>>wI^V<%8f)`U8tq)>6TycT-cIf7}G_KmAz+*c&<@4JP zhwWFZ6SyrVwUZ)x12ezZH(Wpcl$pTDiGQNJ$Y9rf4X zK;=uab%%N%cc{zceo^1}jn8_@zApT74hefl{anALafkY`?ogM>{i1$#bDN<~W=2{~ z&+?A?f42B6jXTtjcZa%6?ickP37_?peO;hFJmekqO24IP33Yy$XExU=7t?N43%zGy zPv(AguN1M=^Hn2Q>_(`RQ!>#}9wn1j_c*9n8MPX6?@Tn~!&$E%F+Pf46W^WPnjp&iEXeN&ZMCTWMIGOdTVlixC>v*k1QK z?On(FElm>o%mE}7^Yc08r55H7Wx~9cV=hzgv!~YTsJkn@pZt*%AK`=bG&oG9y3x$| zYA@Vqe({C3SZBX0YZ-6uIVMXYyM6rYFTIw;32ReSTAHPzUe0dA%OalLL zuJD(s+W`NM;q-zfu#NB+?%;Dvec@l$24!jqf9_@}A}CLwX+{;2$e}ykFldfqVoJ%e z#-1ZJmNI#ysKZ`*J&+`F4qUdV8N`8Y=SU`8{2?zCayEn)O5Zbpv*LxqLwO1>lrh{3 zH(8jc5 zB*pogj!Z-Cr946Il+Q2Zjh}j|u7sS=Q2EcD>K*day_LZYdIa&CYJ2M-XXuhTN&Iyj&QP`Aa}~= z7xGE#d_pd)h!33N9r7c^49y8uB-s>>cu7)_N*~8^|gCO0tOE8X?gspI^u|Z`GB(yeo(N zx|6&^9$WK24mrZbdV<_3pI^uyc+XRHCFCMzWI=!LkQaC>gPUHCNU@$Ecgp7%^1ko- zgk1FU=T7tv`6KUmDuWxykM{_+kfz; zr!v^krBKT7n^a;>*wiTlJa%ZOe10MS>J3lTl^t3@ep?#I)ewH^AivC88ElZJYOuIc zw=WqrDy|!hpx`#66FCB_-P(3`ewtH`RrVZO-9o&OgJDjBY)xsDRtsK-p*4d#cd`|` zv@9n}=yT6L7M(arpPPeIg=!$bQ7S*F&y8y>^0R4j(}(kOx_^nszc%BGidx~cp%TS| zoi8-Q_K6FJaLOKml5pz~4`?}&W}4Ws6jVYBC9LU2iK>F=H)_1T;R%ZE72qzdo+T(5pLl(lptkPX7cD87h6WQ*p?RqBpeCE%vYd_bP%qo%T#3uWU6M|p>QR^$H;$VWZj z7LW@s)XKxWPb@2+^Ii})kV9GP7ILR7J|JJe%zI5!digH}-XTBNM?qSEoQJ;6XF9Pt z#at)W!UYzQisXb^&A+S-XLNzJ*{r%QLE0B}ORczVUB5K5222fr%V&ztZyX8?lN4YS zR%@PeGkHX1rzpU>w8+k;02>k@KgncQ#`O1(bLH0_(`66JFS^hO|Lm@e{NC;7_)q+D zoims>{4CZ2M?nu9Ha6($r4@7sScu1|O>4MfGB2m$`H+im!hbj__7B!nm#tm%5k%x8Rg0+!J?ZX9#GU>e-mzU5)w) zZLk&4R`q*V{29&Sggq8V(Z#gnSPGdInqlQX{FlZyDWxjvOW2SgeK6)4 zsKn^@&d)4`@ME$KbgNreoymeaJEhN78h{RtSb4M>b~I;Gh6Z>mjB9El#%J+&|4z=( zKkz}YsTG638GPa0`)F4cd}f5YIQ2N1Z46i?Dfd$n8}MY5y4YrvI-UW~t~1h>Rdo`O zSK%U~>*)5DK^AmX{c(|zl0>T^t-nY%PbQn0_@jxgb==6-!(WY8FCk<%;`me2G{O)} zx=MrFmO6i+nNeHG{t?Z=?QP;BBX0kYyp$E76BuRSVw?V>Iax%K=6_qP&$Ra$rSWHP z!2&}5?A#E@jURov@gr{a^}hl=)hLCNP^txFq_BXbK&lT&EBsiq{}r}ks1}g(JQl;&*)thG_<=NT{J2UQ zKQcChY60QR5UIFIT0rE1G*5>LY-W)2o^sI)juwyus5>;|UyOv?}UrWXh)e3%7lj)@xYx9(DF2D5=Pi1fexwK@sgWM^fU&tSN*i&`o#3FRV*X4MhSbBIX zgB!@DCBq%$PWk*oe!`#I2J%x8#NJfx$djk7n^^wxCr@Q?1G%(hxP#m&pI^wA|It%* zWiJ=%_>bCohx`<8WpD$zv}Cx0+$o=5$VWWn6LK-JT$Ak`@>dpnDuWxyr6t21}(p}vEf4s#ICR39g_a; z>7$oOfr^~1d5c`bTIA43{o05@Axt(|THmLDu<-a*FS1VDjrWlX$`Lkxv^mM=f|lv< zOGc)oOPnZU;!Auu8=B~n)x0pd;>W+fmxh6Z=ere)#7Rp}T4CHpB?p7)|N8^l&$?7+ zOg5N^*d^8c$}1iUjTt(`l~+nxE^=FzGNU38YcC388x`Gf`QH?qse>E7$Cor}A} zdxAwe`nHar?x@FYw)>>|&@EoL{H-r~3f(5wvpp2bQ98geq=+5jh)>0urJne3Fm(@r zd5P=^xmrD40A}@fGQ;WYl5J*Y8Y+Pt+&tGxwbhnNt0UvLl~Sv@1z!`d<3s7=sz$f- zJ(zydSTDH7+UnvVV>>G*?@7vm4za8@?K%XP2J$;uwLU-u7Zhf5ShBKkPhoSqfQH81 zZpt9oD;-%d3uLnK!BQKp(Uf>e+_r6M z*==41?LbvFoO9&E&p=-FG_aXAX5W<_5D_3LwN|r z_{t7DsWn%oqMdj6ueqG}g%{=PJCYi}(vPKUfNR>I7;YLsXw%&`fKxV~4N!f1TQ-2O z^u68ewgI-?=D!$j8bIjQ-8O(zHlGc!<5vGQmm@$d5g%Z|HkSyy?kwF1nA!%#aMJ)n z)9$tboU-|BfNO7Q%LWkIhD*1*ZGdkY{1?Mb0|>pl+XisT=Cc95zuAAy

    2__<34z6Gb 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