diff --git a/packages/hms_room_kit/example/pubspec.lock b/packages/hms_room_kit/example/pubspec.lock index 345ac4899..63011adf5 100644 --- a/packages/hms_room_kit/example/pubspec.lock +++ b/packages/hms_room_kit/example/pubspec.lock @@ -137,6 +137,38 @@ packages: url: "https://pub.dev" source: hosted version: "7.0.0" + file_selector_linux: + dependency: transitive + description: + name: file_selector_linux + sha256: "045d372bf19b02aeb69cacf8b4009555fb5f6f0b7ad8016e5f46dd1387ddd492" + url: "https://pub.dev" + source: hosted + version: "0.9.2+1" + file_selector_macos: + dependency: transitive + description: + name: file_selector_macos + sha256: f42eacb83b318e183b1ae24eead1373ab1334084404c8c16e0354f9a3e55d385 + url: "https://pub.dev" + source: hosted + version: "0.9.4" + file_selector_platform_interface: + dependency: transitive + description: + name: file_selector_platform_interface + sha256: a3994c26f10378a039faa11de174d7b78eb8f79e4dd0af2a451410c1a5c3f66b + url: "https://pub.dev" + source: hosted + version: "2.6.2" + file_selector_windows: + dependency: transitive + description: + name: file_selector_windows + sha256: d3547240c20cabf205c7c7f01a50ecdbc413755814d6677f3cb366f04abcead0 + url: "https://pub.dev" + source: hosted + version: "0.9.3+1" flutter: dependency: "direct main" description: flutter @@ -158,6 +190,14 @@ packages: url: "https://pub.dev" source: hosted version: "2.0.3" + flutter_plugin_android_lifecycle: + dependency: transitive + description: + name: flutter_plugin_android_lifecycle + sha256: "592dc01a18961a51c24ae5d963b724b2b7fa4a95c100fe8eb6ca8a5a4732cadf" + url: "https://pub.dev" + source: hosted + version: "2.0.18" flutter_svg: dependency: "direct main" description: @@ -199,14 +239,24 @@ packages: relative: true source: path version: "1.1.3" + hms_video_plugin: + dependency: transitive + description: + path: "." + ref: main + resolved-ref: cd724255af2436783ff3b3ec8ea3bab87f4aa08b + url: "https://github.com/100mslive/hms_video_plugin.git" + source: git + version: "0.0.1" hmssdk_flutter: dependency: transitive description: - name: hmssdk_flutter - sha256: b3f1438c5146afe0399935d78820357bf548b0e3ea36f9355878670ccc2aca6e - url: "https://pub.dev" - source: hosted - version: "1.10.2" + path: "packages/hmssdk_flutter" + ref: FLUT-318 + resolved-ref: "75b35ed3b2da17b0c0c8ece19ccb3b7fa0321f67" + url: "https://github.com/100mslive/100ms-flutter.git" + source: git + version: "1.10.3" http: dependency: transitive description: @@ -223,6 +273,70 @@ packages: url: "https://pub.dev" source: hosted version: "4.0.2" + image_picker: + dependency: transitive + description: + name: image_picker + sha256: "1f498d086203360cca099d20ffea2963f48c39ce91bdd8a3b6d4a045786b02c8" + url: "https://pub.dev" + source: hosted + version: "1.0.8" + image_picker_android: + dependency: transitive + description: + name: image_picker_android + sha256: "42c098e7fb6334746be37cdc30369ade356ed4f14d48b7a0313f95a9159f4321" + url: "https://pub.dev" + source: hosted + version: "0.8.9+5" + image_picker_for_web: + dependency: transitive + description: + name: image_picker_for_web + sha256: e2423c53a68b579a7c37a1eda967b8ae536c3d98518e5db95ca1fe5719a730a3 + url: "https://pub.dev" + source: hosted + version: "3.0.2" + image_picker_ios: + dependency: transitive + description: + name: image_picker_ios + sha256: fadafce49e8569257a0cad56d24438a6fa1f0cbd7ee0af9b631f7492818a4ca3 + url: "https://pub.dev" + source: hosted + version: "0.8.9+1" + image_picker_linux: + dependency: transitive + description: + name: image_picker_linux + sha256: "4ed1d9bb36f7cd60aa6e6cd479779cc56a4cb4e4de8f49d487b1aaad831300fa" + url: "https://pub.dev" + source: hosted + version: "0.2.1+1" + image_picker_macos: + dependency: transitive + description: + name: image_picker_macos + sha256: "3f5ad1e8112a9a6111c46d0b57a7be2286a9a07fc6e1976fdf5be2bd31d4ff62" + url: "https://pub.dev" + source: hosted + version: "0.2.1+1" + image_picker_platform_interface: + dependency: transitive + description: + name: image_picker_platform_interface + sha256: fa4e815e6fcada50e35718727d83ba1c92f1edf95c0b4436554cec301b56233b + url: "https://pub.dev" + source: hosted + version: "2.9.3" + image_picker_windows: + dependency: transitive + description: + name: image_picker_windows + sha256: "6ad07afc4eb1bc25f3a01084d28520496c4a3bb0cb13685435838167c9dcedeb" + url: "https://pub.dev" + source: hosted + version: "0.2.1+1" intl: dependency: transitive description: diff --git a/packages/hms_room_kit/lib/src/assets/icons/max_blur.svg b/packages/hms_room_kit/lib/src/assets/icons/max_blur.svg new file mode 100644 index 000000000..c0455f9b7 --- /dev/null +++ b/packages/hms_room_kit/lib/src/assets/icons/max_blur.svg @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + + + + diff --git a/packages/hms_room_kit/lib/src/assets/icons/min_blur.svg b/packages/hms_room_kit/lib/src/assets/icons/min_blur.svg new file mode 100644 index 000000000..15811eea5 --- /dev/null +++ b/packages/hms_room_kit/lib/src/assets/icons/min_blur.svg @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + + + + diff --git a/packages/hms_room_kit/lib/src/assets/icons/remove_effects.svg b/packages/hms_room_kit/lib/src/assets/icons/remove_effects.svg new file mode 100644 index 000000000..1cdce30c9 --- /dev/null +++ b/packages/hms_room_kit/lib/src/assets/icons/remove_effects.svg @@ -0,0 +1,3 @@ + + + diff --git a/packages/hms_room_kit/lib/src/assets/icons/video_effects.svg b/packages/hms_room_kit/lib/src/assets/icons/video_effects.svg new file mode 100644 index 000000000..42274b1b6 --- /dev/null +++ b/packages/hms_room_kit/lib/src/assets/icons/video_effects.svg @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + diff --git a/packages/hms_room_kit/lib/src/common/utility_functions.dart b/packages/hms_room_kit/lib/src/common/utility_functions.dart index 92fdfe8cc..5fe8a4657 100644 --- a/packages/hms_room_kit/lib/src/common/utility_functions.dart +++ b/packages/hms_room_kit/lib/src/common/utility_functions.dart @@ -416,11 +416,12 @@ class Utilities { audioMode: audioMode, enableNoiseCancellation: isNoiseCancellationEnabled), videoTrackSetting: HMSVideoTrackSetting( - trackInitialState: joinWithMutedVideo - ? HMSTrackInitState.MUTED - : HMSTrackInitState.UNMUTED, - forceSoftwareDecoder: isSoftwareDecoderDisabled, - )); + trackInitialState: joinWithMutedVideo + ? HMSTrackInitState.MUTED + : HMSTrackInitState.UNMUTED, + forceSoftwareDecoder: isSoftwareDecoderDisabled, + isVirtualBackgroundEnabled: + AppDebugConfig.isVirtualBackgroundEnabled)); } static String getTimedMetadataEmojiFromId(String emojiId) { diff --git a/packages/hms_room_kit/lib/src/service/app_debug_config.dart b/packages/hms_room_kit/lib/src/service/app_debug_config.dart index 39573c59a..efcb776a5 100644 --- a/packages/hms_room_kit/lib/src/service/app_debug_config.dart +++ b/packages/hms_room_kit/lib/src/service/app_debug_config.dart @@ -16,6 +16,9 @@ class AppDebugConfig { static bool isDebugMode = false; static bool isProdRoom = true; + static bool isVirtualBackgroundEnabled = false; + static bool isVBEnabled = false; + static bool isBlurEnabled = false; /// The [iOSScreenshareConfig] contains the configuration for the iOS screenshare static HMSIOSScreenshareConfig? iOSScreenshareConfig; @@ -30,5 +33,8 @@ class AppDebugConfig { isAutoSimulcast = true; isProdRoom = true; nameChangeOnPreview = true; + isVirtualBackgroundEnabled = false; + isBlurEnabled = false; + isVBEnabled = false; } } diff --git a/packages/hms_room_kit/lib/src/widgets/bottom_sheets/app_utilities_bottom_sheet.dart b/packages/hms_room_kit/lib/src/widgets/bottom_sheets/app_utilities_bottom_sheet.dart index bb33d6760..fdc355b71 100644 --- a/packages/hms_room_kit/lib/src/widgets/bottom_sheets/app_utilities_bottom_sheet.dart +++ b/packages/hms_room_kit/lib/src/widgets/bottom_sheets/app_utilities_bottom_sheet.dart @@ -4,7 +4,6 @@ library; import 'package:badges/badges.dart' as badge; import 'package:flutter/material.dart'; import 'package:flutter_svg/flutter_svg.dart'; -import 'package:hms_room_kit/src/widgets/bottom_sheets/poll_and_quiz_bottom_sheet.dart'; import 'package:hmssdk_flutter/hmssdk_flutter.dart'; import 'package:provider/provider.dart'; @@ -18,6 +17,8 @@ import 'package:hms_room_kit/src/widgets/bottom_sheets/overlay_participants_bott import 'package:hms_room_kit/src/widgets/common_widgets/hms_cross_button.dart'; import 'package:hms_room_kit/src/widgets/common_widgets/hms_subheading_text.dart'; import 'package:hms_room_kit/src/widgets/tab_widgets/chat_participants_tab_bar.dart'; +import 'package:hms_room_kit/src/widgets/bottom_sheets/poll_and_quiz_bottom_sheet.dart'; +import 'package:hms_room_kit/src/widgets/bottom_sheets/video_effects_bottom_sheet.dart'; ///This renders the app utilities bottom sheet for webRTC or broadcaster ///It contains the participants, screen share, brb, raise hand and recording @@ -213,7 +214,6 @@ class _AppUtilitiesBottomSheetState extends State { meetingStore.isBRB ? "I'm Back" : "Be Right Back"), ///This renders the raise hand option - MoreOptionItem( onTap: () async { context.read().toggleLocalPeerHandRaise(); @@ -420,6 +420,38 @@ class _AppUtilitiesBottomSheetState extends State { optionText: meetingStore.isWhiteboardEnabled ? "Close Whiteboard" : "Open Whiteboard"), + if (AppDebugConfig.isVirtualBackgroundEnabled) + MoreOptionItem( + onTap: () async { + Navigator.pop(context); + showModalBottomSheet( + isScrollControlled: true, + backgroundColor: HMSThemeColors.surfaceDim, + shape: const RoundedRectangleBorder( + borderRadius: BorderRadius.only( + topLeft: Radius.circular(16), + topRight: Radius.circular(16)), + ), + context: context, + builder: (ctx) => ChangeNotifierProvider.value( + value: meetingStore, + child: Padding( + padding: EdgeInsets.only( + bottom: + MediaQuery.of(ctx).viewInsets.bottom), + child: VideoEffectsBottomSheet())), + ); + }, + isActive: false, + optionIcon: SvgPicture.asset( + "packages/hms_room_kit/lib/src/assets/icons/video_effects.svg", + height: 20, + width: 20, + colorFilter: ColorFilter.mode( + HMSThemeColors.onSurfaceHighEmphasis, + BlendMode.srcIn), + ), + optionText: "Virtual Background"), ], ), ], diff --git a/packages/hms_room_kit/lib/src/widgets/bottom_sheets/video_effects_bottom_sheet.dart b/packages/hms_room_kit/lib/src/widgets/bottom_sheets/video_effects_bottom_sheet.dart new file mode 100644 index 000000000..f2321bf4f --- /dev/null +++ b/packages/hms_room_kit/lib/src/widgets/bottom_sheets/video_effects_bottom_sheet.dart @@ -0,0 +1,250 @@ +library; + +///Package imports +import 'package:flutter/material.dart'; +import 'package:flutter_svg/flutter_svg.dart'; +import 'package:hms_video_plugin/hms_video_plugin.dart'; +import 'package:image_picker/image_picker.dart'; + +///Project imports +import 'package:hms_room_kit/hms_room_kit.dart'; +import 'package:hms_room_kit/src/widgets/common_widgets/hms_cross_button.dart'; +import 'package:hms_room_kit/src/widgets/common_widgets/hms_subheading_text.dart'; +import 'package:hms_room_kit/src/widgets/common_widgets/more_option_item.dart'; + +///[VideoEffectsBottomSheet] is a bottom sheet that is used to change the video effects +class VideoEffectsBottomSheet extends StatefulWidget { + @override + State createState() => + _VideoEffectsBottomSheetState(); +} + +class _VideoEffectsBottomSheetState extends State { + int blurValue = 0; + String selectedEffect = ""; + + @override + void initState() { + super.initState(); + if (AppDebugConfig.isBlurEnabled) { + setEffect("blur"); + } else if (AppDebugConfig.isVBEnabled) { + setEffect("background"); + } + } + + void changeBlur(int blurRadius) { + setState(() { + blurValue = blurRadius; + }); + HMSVideoPlugin.enableBlur(blurRadius: blurValue); + AppDebugConfig.isBlurEnabled = true; + } + + void setEffect(String effect) { + setState(() { + selectedEffect = effect; + }); + } + + @override + Widget build(BuildContext context) { + return SingleChildScrollView( + child: Padding( + padding: const EdgeInsets.only(top: 8.0, left: 16, right: 16), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisSize: MainAxisSize.min, + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Row( + children: [ + IconButton( + icon: Icon( + Icons.arrow_back_ios_new, + size: 24, + color: HMSThemeColors.onSurfaceHighEmphasis, + ), + onPressed: () { + Navigator.pop(context); + }, + ), + const SizedBox( + width: 4, + ), + HMSTitleText( + text: "Virtual Background", + textColor: HMSThemeColors.onSurfaceHighEmphasis, + letterSpacing: 0.15, + ) + ], + ), + Row( + children: [HMSCrossButton()], + ) + ], + ), + Padding( + padding: const EdgeInsets.only(top: 16, bottom: 16), + child: Divider( + color: HMSThemeColors.borderDefault, + height: 5, + ), + ), + const SizedBox( + height: 16, + ), + HMSSubheadingText( + text: "Effects", + textColor: HMSThemeColors.onSurfaceHighEmphasis, + fontWeight: FontWeight.w600, + ), + const SizedBox( + height: 8, + ), + Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Expanded( + child: MoreOptionItem( + onTap: () { + Navigator.pop(context); + if (AppDebugConfig.isBlurEnabled) { + HMSVideoPlugin.disableBlur(); + AppDebugConfig.isBlurEnabled = false; + } else if (AppDebugConfig.isVirtualBackgroundEnabled) { + HMSVideoPlugin.disable(); + AppDebugConfig.isVBEnabled = false; + } + setEffect(""); + }, + optionIcon: SvgPicture.asset( + "packages/hms_room_kit/lib/src/assets/icons/remove_effects.svg", + height: 20, + width: 20, + colorFilter: ColorFilter.mode( + HMSThemeColors.onSurfaceHighEmphasis, + BlendMode.srcIn), + ), + optionText: "No Effect", + isActive: true), + ), + const SizedBox( + width: 8, + ), + Expanded( + child: MoreOptionItem( + onTap: () { + Navigator.pop(context); + if (AppDebugConfig.isVBEnabled) { + HMSVideoPlugin.disable(); + AppDebugConfig.isVBEnabled = false; + } + changeBlur(100); + }, + optionIcon: SvgPicture.asset( + "packages/hms_room_kit/lib/src/assets/icons/max_blur.svg", + height: 20, + width: 20, + colorFilter: ColorFilter.mode( + HMSThemeColors.onSurfaceHighEmphasis, + BlendMode.srcIn), + ), + optionText: " Blur", + isActive: true), + ), + const SizedBox( + width: 8, + ), + Expanded( + child: MoreOptionItem( + onTap: () async { + Navigator.pop(context); + if (AppDebugConfig.isBlurEnabled) { + HMSVideoPlugin.disableBlur(); + AppDebugConfig.isBlurEnabled = false; + } + setEffect("background"); + XFile? result = await ImagePicker() + .pickImage(source: ImageSource.gallery); + if (result != null) { + final bytes = await result.readAsBytes(); + if (AppDebugConfig.isVBEnabled) { + HMSVideoPlugin.changeVirtualBackground( + image: bytes); + } else { + HMSVideoPlugin.enable(image: bytes); + AppDebugConfig.isVBEnabled = + !AppDebugConfig.isVBEnabled; + } + } + }, + optionIcon: SvgPicture.asset( + "packages/hms_room_kit/lib/src/assets/icons/video_effects.svg", + height: 20, + width: 20, + colorFilter: ColorFilter.mode( + HMSThemeColors.onSurfaceHighEmphasis, + BlendMode.srcIn), + ), + optionText: "Backgrounds", + isActive: true), + ), + ], + ), + const SizedBox( + height: 24, + ), + // if (selectedEffect == "blur") + // Row( + // mainAxisAlignment: MainAxisAlignment.spaceBetween, + // children: [ + // SvgPicture.asset( + // "packages/hms_room_kit/lib/src/assets/icons/min_blur.svg", + // height: 18, + // width: 18, + // colorFilter: ColorFilter.mode( + // HMSThemeColors.onSurfaceHighEmphasis, BlendMode.srcIn), + // ), + // Expanded( + // child: SliderTheme( + // data: SliderThemeData( + // trackHeight: 2, + // trackShape: RoundedRectSliderTrackShape(), + // inactiveTrackColor: HMSThemeColors.secondaryDefault, + // activeTrackColor: HMSThemeColors.primaryDefault, + // thumbColor: HMSThemeColors.primaryDefault, + // thumbShape: + // RoundSliderThumbShape(enabledThumbRadius: 6), + // overlayShape: + // RoundSliderOverlayShape(overlayRadius: 0)), + // child: Slider( + // value: blurValue.toDouble(), + // onChanged: (value) {}, + // onChangeEnd: (value) { + // changeBlur(value.toInt()); + // }, + // min: 0, + // max: 100, + // ), + // )), + // SvgPicture.asset( + // "packages/hms_room_kit/lib/src/assets/icons/max_blur.svg", + // height: 18, + // width: 18, + // colorFilter: ColorFilter.mode( + // HMSThemeColors.onSurfaceHighEmphasis, BlendMode.srcIn), + // ) + // ], + // ), + // const SizedBox( + // height: 16, + // ), + ], + ), + ), + ); + } +} diff --git a/packages/hms_room_kit/pubspec.lock b/packages/hms_room_kit/pubspec.lock index 5fe398031..0ac6750a4 100644 --- a/packages/hms_room_kit/pubspec.lock +++ b/packages/hms_room_kit/pubspec.lock @@ -129,6 +129,38 @@ packages: url: "https://pub.dev" source: hosted version: "7.0.0" + file_selector_linux: + dependency: transitive + description: + name: file_selector_linux + sha256: "045d372bf19b02aeb69cacf8b4009555fb5f6f0b7ad8016e5f46dd1387ddd492" + url: "https://pub.dev" + source: hosted + version: "0.9.2+1" + file_selector_macos: + dependency: transitive + description: + name: file_selector_macos + sha256: f42eacb83b318e183b1ae24eead1373ab1334084404c8c16e0354f9a3e55d385 + url: "https://pub.dev" + source: hosted + version: "0.9.4" + file_selector_platform_interface: + dependency: transitive + description: + name: file_selector_platform_interface + sha256: a3994c26f10378a039faa11de174d7b78eb8f79e4dd0af2a451410c1a5c3f66b + url: "https://pub.dev" + source: hosted + version: "2.6.2" + file_selector_windows: + dependency: transitive + description: + name: file_selector_windows + sha256: d3547240c20cabf205c7c7f01a50ecdbc413755814d6677f3cb366f04abcead0 + url: "https://pub.dev" + source: hosted + version: "0.9.3+1" flutter: dependency: "direct main" description: flutter @@ -142,6 +174,14 @@ packages: url: "https://pub.dev" source: hosted version: "6.0.0" + flutter_plugin_android_lifecycle: + dependency: transitive + description: + name: flutter_plugin_android_lifecycle + sha256: "592dc01a18961a51c24ae5d963b724b2b7fa4a95c100fe8eb6ca8a5a4732cadf" + url: "https://pub.dev" + source: hosted + version: "2.0.18" flutter_svg: dependency: "direct main" description: @@ -176,14 +216,24 @@ packages: url: "https://pub.dev" source: hosted version: "6.1.0" + hms_video_plugin: + dependency: "direct main" + description: + path: "." + ref: main + resolved-ref: cd724255af2436783ff3b3ec8ea3bab87f4aa08b + url: "https://github.com/100mslive/hms_video_plugin.git" + source: git + version: "0.0.1" hmssdk_flutter: dependency: "direct main" description: - name: hmssdk_flutter - sha256: b3f1438c5146afe0399935d78820357bf548b0e3ea36f9355878670ccc2aca6e - url: "https://pub.dev" - source: hosted - version: "1.10.2" + path: "packages/hmssdk_flutter" + ref: FLUT-318 + resolved-ref: "75b35ed3b2da17b0c0c8ece19ccb3b7fa0321f67" + url: "https://github.com/100mslive/100ms-flutter.git" + source: git + version: "1.10.3" http: dependency: transitive description: @@ -200,6 +250,70 @@ packages: url: "https://pub.dev" source: hosted version: "4.0.2" + image_picker: + dependency: "direct main" + description: + name: image_picker + sha256: "1f498d086203360cca099d20ffea2963f48c39ce91bdd8a3b6d4a045786b02c8" + url: "https://pub.dev" + source: hosted + version: "1.0.8" + image_picker_android: + dependency: transitive + description: + name: image_picker_android + sha256: "42c098e7fb6334746be37cdc30369ade356ed4f14d48b7a0313f95a9159f4321" + url: "https://pub.dev" + source: hosted + version: "0.8.9+5" + image_picker_for_web: + dependency: transitive + description: + name: image_picker_for_web + sha256: e2423c53a68b579a7c37a1eda967b8ae536c3d98518e5db95ca1fe5719a730a3 + url: "https://pub.dev" + source: hosted + version: "3.0.2" + image_picker_ios: + dependency: transitive + description: + name: image_picker_ios + sha256: fadafce49e8569257a0cad56d24438a6fa1f0cbd7ee0af9b631f7492818a4ca3 + url: "https://pub.dev" + source: hosted + version: "0.8.9+1" + image_picker_linux: + dependency: transitive + description: + name: image_picker_linux + sha256: "4ed1d9bb36f7cd60aa6e6cd479779cc56a4cb4e4de8f49d487b1aaad831300fa" + url: "https://pub.dev" + source: hosted + version: "0.2.1+1" + image_picker_macos: + dependency: transitive + description: + name: image_picker_macos + sha256: "3f5ad1e8112a9a6111c46d0b57a7be2286a9a07fc6e1976fdf5be2bd31d4ff62" + url: "https://pub.dev" + source: hosted + version: "0.2.1+1" + image_picker_platform_interface: + dependency: transitive + description: + name: image_picker_platform_interface + sha256: fa4e815e6fcada50e35718727d83ba1c92f1edf95c0b4436554cec301b56233b + url: "https://pub.dev" + source: hosted + version: "2.9.3" + image_picker_windows: + dependency: transitive + description: + name: image_picker_windows + sha256: "6ad07afc4eb1bc25f3a01084d28520496c4a3bb0cb13685435838167c9dcedeb" + url: "https://pub.dev" + source: hosted + version: "0.2.1+1" intl: dependency: "direct main" description: diff --git a/packages/hms_room_kit/pubspec.yaml b/packages/hms_room_kit/pubspec.yaml index 1d2a7a455..6c133d8ad 100644 --- a/packages/hms_room_kit/pubspec.yaml +++ b/packages/hms_room_kit/pubspec.yaml @@ -14,7 +14,15 @@ dependencies: flutter: sdk: flutter - hmssdk_flutter: 1.10.2 + hmssdk_flutter: + git: + url: https://github.com/100mslive/100ms-flutter.git + ref: FLUT-318 + path: packages/hmssdk_flutter + hms_video_plugin: + git: + url: https://github.com/100mslive/hms_video_plugin.git + ref: main intl: ^0.18.0 permission_handler: ^11.0.0 provider: ^6.0.5 @@ -35,6 +43,7 @@ dependencies: dots_indicator: ^3.0.0 webview_flutter: ^4.5.0 pointer_interceptor: ^0.10.1 + image_picker: ^1.0.8 dev_dependencies: flutter_test: diff --git a/packages/hmssdk_flutter/android/src/main/kotlin/live/hms/hmssdk_flutter/HmssdkFlutterPlugin.kt b/packages/hmssdk_flutter/android/src/main/kotlin/live/hms/hmssdk_flutter/HmssdkFlutterPlugin.kt index 2edbe1470..73b8f7db8 100644 --- a/packages/hmssdk_flutter/android/src/main/kotlin/live/hms/hmssdk_flutter/HmssdkFlutterPlugin.kt +++ b/packages/hmssdk_flutter/android/src/main/kotlin/live/hms/hmssdk_flutter/HmssdkFlutterPlugin.kt @@ -1204,7 +1204,7 @@ class HmssdkFlutterPlugin : isRoomAudioUnmutedLocally = isRoomAudioUnmuted } - fun build( + private fun build( activity: Activity, call: MethodCall, result: Result, diff --git a/packages/hmssdk_flutter/example/ExampleAppChangelog.txt b/packages/hmssdk_flutter/example/ExampleAppChangelog.txt index 53badfa06..2b33ea163 100644 --- a/packages/hmssdk_flutter/example/ExampleAppChangelog.txt +++ b/packages/hmssdk_flutter/example/ExampleAppChangelog.txt @@ -1,15 +1,15 @@ Board: https://100ms.atlassian.net/jira/software/projects/FLUT/boards/34/ -- Add Quality Selector sheet in HLS Player -https://100ms.atlassian.net/browse/FLUT-297 +- Implement Background Blur effects +https://100ms.atlassian.net/browse/FLUT-318 -- Whiteboard Support in flutter -https://100ms.atlassian.net/browse/FLUT-298 +- Expose SDK APIs for Virtual Backgrounds +https://100ms.atlassian.net/browse/FLUT-319 -- Add `peerListUpdated` callback shows the peers in the room -https://100ms.atlassian.net/browse/FLUT-284 +- Create separate package on pub for Virtual Background +https://100ms.atlassian.net/browse/FLUT-317 -Room Kit: 1.1.2 -Core SDK: 1.10.2 -Android SDK: 2.9.56 -iOS SDK: 1.10.0 \ No newline at end of file +Room Kit: 1.1.3 +Core SDK: 1.10.3 +Android SDK: 2.9.57 +iOS SDK: 1.11.0 \ No newline at end of file diff --git a/packages/hmssdk_flutter/example/android/app/build.gradle b/packages/hmssdk_flutter/example/android/app/build.gradle index d9b49e55c..0048156b7 100644 --- a/packages/hmssdk_flutter/example/android/app/build.gradle +++ b/packages/hmssdk_flutter/example/android/app/build.gradle @@ -36,8 +36,8 @@ android { applicationId "live.hms.flutter" minSdkVersion 21 targetSdkVersion 34 - versionCode 493 - versionName "1.5.193" + versionCode 495 + versionName "1.5.195" } signingConfigs { diff --git a/packages/hmssdk_flutter/example/android/app/src/main/java/io/flutter/plugins/GeneratedPluginRegistrant.java b/packages/hmssdk_flutter/example/android/app/src/main/java/io/flutter/plugins/GeneratedPluginRegistrant.java index e757d644b..cf4dd3942 100644 --- a/packages/hmssdk_flutter/example/android/app/src/main/java/io/flutter/plugins/GeneratedPluginRegistrant.java +++ b/packages/hmssdk_flutter/example/android/app/src/main/java/io/flutter/plugins/GeneratedPluginRegistrant.java @@ -45,11 +45,26 @@ public static void registerWith(@NonNull FlutterEngine flutterEngine) { } catch (Exception e) { Log.e(TAG, "Error registering plugin flutter_foreground_task, com.pravera.flutter_foreground_task.FlutterForegroundTaskPlugin", e); } + try { + flutterEngine.getPlugins().add(new io.flutter.plugins.flutter_plugin_android_lifecycle.FlutterAndroidLifecyclePlugin()); + } catch (Exception e) { + Log.e(TAG, "Error registering plugin flutter_plugin_android_lifecycle, io.flutter.plugins.flutter_plugin_android_lifecycle.FlutterAndroidLifecyclePlugin", e); + } + try { + flutterEngine.getPlugins().add(new live.hms.hms_video_plugin.HmsVideoFilterPlugin()); + } catch (Exception e) { + Log.e(TAG, "Error registering plugin hms_video_plugin, live.hms.hms_video_plugin.HmsVideoFilterPlugin", e); + } try { flutterEngine.getPlugins().add(new live.hms.hmssdk_flutter.HmssdkFlutterPlugin()); } catch (Exception e) { Log.e(TAG, "Error registering plugin hmssdk_flutter, live.hms.hmssdk_flutter.HmssdkFlutterPlugin", e); } + try { + flutterEngine.getPlugins().add(new io.flutter.plugins.imagepicker.ImagePickerPlugin()); + } catch (Exception e) { + Log.e(TAG, "Error registering plugin image_picker_android, io.flutter.plugins.imagepicker.ImagePickerPlugin", e); + } try { flutterEngine.getPlugins().add(new dev.steenbakker.mobile_scanner.MobileScannerPlugin()); } catch (Exception e) { diff --git a/packages/hmssdk_flutter/example/ios/Podfile.lock b/packages/hmssdk_flutter/example/ios/Podfile.lock index cd8639566..62d26f3d9 100644 --- a/packages/hmssdk_flutter/example/ios/Podfile.lock +++ b/packages/hmssdk_flutter/example/ios/Podfile.lock @@ -125,12 +125,14 @@ PODS: - GoogleUtilitiesComponents (1.1.0): - GoogleUtilities/Logger - GTMSessionFetcher/Core (2.3.0) + - hms_video_plugin (0.0.1): + - Flutter - HMSAnalyticsSDK (0.0.2) - HMSBroadcastExtensionSDK (0.0.9) - HMSHLSPlayerSDK (0.0.2): - HMSAnalyticsSDK (= 0.0.2) - HMSNoiseCancellationModels (1.0.0) - - HMSSDK (1.10.0): + - HMSSDK (1.11.0): - HMSAnalyticsSDK (= 0.0.2) - HMSWebRTC (= 1.0.6169) - hmssdk_flutter (1.10.2): @@ -138,8 +140,10 @@ PODS: - HMSBroadcastExtensionSDK (= 0.0.9) - HMSHLSPlayerSDK (= 0.0.2) - HMSNoiseCancellationModels (= 1.0.0) - - HMSSDK (= 1.10.0) + - HMSSDK (= 1.11.0) - HMSWebRTC (1.0.6169) + - image_picker_ios (0.0.1): + - Flutter - MLImage (1.0.0-beta4) - MLKitBarcodeScanning (3.0.0): - MLKitCommon (~> 9.0) @@ -196,8 +200,10 @@ DEPENDENCIES: - firebase_performance (from `.symlinks/plugins/firebase_performance/ios`) - Flutter (from `Flutter`) - flutter_foreground_task (from `.symlinks/plugins/flutter_foreground_task/ios`) + - hms_video_plugin (from `.symlinks/plugins/hms_video_plugin/ios`) - HMSBroadcastExtensionSDK - hmssdk_flutter (from `.symlinks/plugins/hmssdk_flutter/ios`) + - image_picker_ios (from `.symlinks/plugins/image_picker_ios/ios`) - mobile_scanner (from `.symlinks/plugins/mobile_scanner/ios`) - package_info_plus (from `.symlinks/plugins/package_info_plus/ios`) - path_provider_foundation (from `.symlinks/plugins/path_provider_foundation/darwin`) @@ -258,8 +264,12 @@ EXTERNAL SOURCES: :path: Flutter flutter_foreground_task: :path: ".symlinks/plugins/flutter_foreground_task/ios" + hms_video_plugin: + :path: ".symlinks/plugins/hms_video_plugin/ios" hmssdk_flutter: :path: ".symlinks/plugins/hmssdk_flutter/ios" + image_picker_ios: + :path: ".symlinks/plugins/image_picker_ios/ios" mobile_scanner: :path: ".symlinks/plugins/mobile_scanner/ios" package_info_plus: @@ -306,13 +316,15 @@ SPEC CHECKSUMS: GoogleUtilities: ea963c370a38a8069cc5f7ba4ca849a60b6d7d15 GoogleUtilitiesComponents: 679b2c881db3b615a2777504623df6122dd20afe GTMSessionFetcher: 3a63d75eecd6aa32c2fc79f578064e1214dfdec2 + hms_video_plugin: 051960514fa3ea646c740b3a34ff1f3b5c3fe573 HMSAnalyticsSDK: 4d2a88a729b1eb42f3d25f217c28937ec318a5b7 HMSBroadcastExtensionSDK: d80fe325f6c928bd8e5176290b5a4b7ae15d6fbb HMSHLSPlayerSDK: 6a54ad4d12f3dc2270d1ecd24019d71282a4f6a3 HMSNoiseCancellationModels: a3bda1405a16015632f4bcabd46ce48f35103b02 - HMSSDK: fbbdebf673baba7f98f3fa13241b4249929ad681 - hmssdk_flutter: 9be13b77e2a55dba665e154cae026d2b5cdfa053 + HMSSDK: cdba5b12c080832d135af7bbc4ca6282b0e171ac + hmssdk_flutter: 3813b9229fdd6437041d970a449a64575fb1cbd1 HMSWebRTC: 8f51ba33a0e505e17ebf3d7b37bcdca266751a13 + image_picker_ios: 99dfe1854b4fa34d0364e74a78448a0151025425 MLImage: 7bb7c4264164ade9bf64f679b40fb29c8f33ee9b MLKitBarcodeScanning: 04e264482c5f3810cb89ebc134ef6b61e67db505 MLKitCommon: c1b791c3e667091918d91bda4bba69a91011e390 @@ -332,4 +344,4 @@ SPEC CHECKSUMS: PODFILE CHECKSUM: 9fb9f6e431a2c6c79942252e94b241ac7972ac90 -COCOAPODS: 1.15.2 +COCOAPODS: 1.14.3 diff --git a/packages/hmssdk_flutter/example/ios/Runner/Info.plist b/packages/hmssdk_flutter/example/ios/Runner/Info.plist index 061bf3fc8..d7328afa0 100644 --- a/packages/hmssdk_flutter/example/ios/Runner/Info.plist +++ b/packages/hmssdk_flutter/example/ios/Runner/Info.plist @@ -21,7 +21,7 @@ CFBundlePackageType APPL CFBundleShortVersionString - 1.5.193 + 1.5.195 CFBundleSignature ???? CFBundleURLTypes @@ -48,7 +48,7 @@ CFBundleVersion - 493 + 495 ITSAppUsesNonExemptEncryption LSApplicationCategoryType diff --git a/packages/hmssdk_flutter/example/lib/app_settings_bottom_sheet.dart b/packages/hmssdk_flutter/example/lib/app_settings_bottom_sheet.dart index 7186aecb3..dd0b897be 100644 --- a/packages/hmssdk_flutter/example/lib/app_settings_bottom_sheet.dart +++ b/packages/hmssdk_flutter/example/lib/app_settings_bottom_sheet.dart @@ -27,6 +27,7 @@ class _AppSettingsBottomSheetState extends State { HMSAudioMode currentAudioMode = HMSAudioMode.VOICE; bool isStreamingFlow = true; bool nameChangeOnPreview = true; + bool isVirtualBackgroundEnabled = false; var versions = {}; @@ -70,6 +71,10 @@ class _AppSettingsBottomSheetState extends State { nameChangeOnPreview = await Utilities.getBoolData(key: 'name-change-on-preview') ?? true; + isVirtualBackgroundEnabled = + await Utilities.getBoolData(key: 'is_virtual_background_enabled') ?? + false; + WidgetsBinding.instance.addPostFrameCallback((_) { setState(() {}); }); @@ -86,6 +91,7 @@ class _AppSettingsBottomSheetState extends State { AppDebugConfig.skipPreview = skipPreview; AppDebugConfig.isDebugMode = isDebugMode; AppDebugConfig.nameChangeOnPreview = true; + AppDebugConfig.isVirtualBackgroundEnabled = isVirtualBackgroundEnabled; } Future _launchUrl() async { @@ -423,6 +429,36 @@ class _AppSettingsBottomSheetState extends State { setState(() {}) }), ), + ListTile( + horizontalTitleGap: 2, + enabled: true, + contentPadding: EdgeInsets.zero, + leading: SvgPicture.asset( + 'packages/hms_room_kit/lib/src/assets/icons/local_capture.svg', + colorFilter: + ColorFilter.mode(themeDefaultColor, BlendMode.srcIn), + ), + title: Text( + "Enable Virtual Background", + semanticsLabel: "fl_virtual_background", + style: HMSTextStyle.setTextStyle( + fontSize: 14, + color: themeDefaultColor, + letterSpacing: 0.25, + fontWeight: FontWeight.w600), + ), + trailing: CupertinoSwitch( + activeColor: hmsdefaultColor, + value: isVirtualBackgroundEnabled, + onChanged: (value) => { + isVirtualBackgroundEnabled = value, + Utilities.saveBoolData( + key: 'is_virtual_background_enabled', + value: value), + AppDebugConfig.isVirtualBackgroundEnabled = value, + setState(() {}) + }), + ), GestureDetector( onTap: () { showDialog( diff --git a/packages/hmssdk_flutter/example/pubspec.lock b/packages/hmssdk_flutter/example/pubspec.lock index 9c49b333a..95ac91989 100644 --- a/packages/hmssdk_flutter/example/pubspec.lock +++ b/packages/hmssdk_flutter/example/pubspec.lock @@ -145,6 +145,38 @@ packages: url: "https://pub.dev" source: hosted version: "7.0.0" + file_selector_linux: + dependency: transitive + description: + name: file_selector_linux + sha256: "045d372bf19b02aeb69cacf8b4009555fb5f6f0b7ad8016e5f46dd1387ddd492" + url: "https://pub.dev" + source: hosted + version: "0.9.2+1" + file_selector_macos: + dependency: transitive + description: + name: file_selector_macos + sha256: f42eacb83b318e183b1ae24eead1373ab1334084404c8c16e0354f9a3e55d385 + url: "https://pub.dev" + source: hosted + version: "0.9.4" + file_selector_platform_interface: + dependency: transitive + description: + name: file_selector_platform_interface + sha256: a3994c26f10378a039faa11de174d7b78eb8f79e4dd0af2a451410c1a5c3f66b + url: "https://pub.dev" + source: hosted + version: "2.6.2" + file_selector_windows: + dependency: transitive + description: + name: file_selector_windows + sha256: d3547240c20cabf205c7c7f01a50ecdbc413755814d6677f3cb366f04abcead0 + url: "https://pub.dev" + source: hosted + version: "0.9.3+1" firebase_core: dependency: "direct main" description: @@ -234,10 +266,10 @@ packages: dependency: "direct main" description: name: flutter_foreground_task - sha256: d40a1ddd5f275450d2e32055e7f884796c028a02ac26c751c20916576f79e132 + sha256: "9bcfcb43bba4a5446a056e723d21118ff6e184926b5557365c32c13caca157c2" url: "https://pub.dev" source: hosted - version: "6.2.0" + version: "6.1.3" flutter_linkify: dependency: transitive description: @@ -246,6 +278,14 @@ packages: url: "https://pub.dev" source: hosted version: "6.0.0" + flutter_plugin_android_lifecycle: + dependency: transitive + description: + name: flutter_plugin_android_lifecycle + sha256: "592dc01a18961a51c24ae5d963b724b2b7fa4a95c100fe8eb6ca8a5a4732cadf" + url: "https://pub.dev" + source: hosted + version: "2.0.18" flutter_svg: dependency: "direct main" description: @@ -295,14 +335,20 @@ packages: relative: true source: path version: "1.1.3" + hms_video_plugin: + dependency: transitive + description: + path: "../../hms_video_plugin" + relative: true + source: path + version: "0.0.1" hmssdk_flutter: dependency: transitive description: - name: hmssdk_flutter - sha256: b3f1438c5146afe0399935d78820357bf548b0e3ea36f9355878670ccc2aca6e - url: "https://pub.dev" - source: hosted - version: "1.10.2" + path: ".." + relative: true + source: path + version: "1.10.3" http: dependency: transitive description: @@ -319,6 +365,70 @@ packages: url: "https://pub.dev" source: hosted version: "4.0.2" + image_picker: + dependency: transitive + description: + name: image_picker + sha256: "1f498d086203360cca099d20ffea2963f48c39ce91bdd8a3b6d4a045786b02c8" + url: "https://pub.dev" + source: hosted + version: "1.0.8" + image_picker_android: + dependency: transitive + description: + name: image_picker_android + sha256: "42c098e7fb6334746be37cdc30369ade356ed4f14d48b7a0313f95a9159f4321" + url: "https://pub.dev" + source: hosted + version: "0.8.9+5" + image_picker_for_web: + dependency: transitive + description: + name: image_picker_for_web + sha256: e2423c53a68b579a7c37a1eda967b8ae536c3d98518e5db95ca1fe5719a730a3 + url: "https://pub.dev" + source: hosted + version: "3.0.2" + image_picker_ios: + dependency: transitive + description: + name: image_picker_ios + sha256: fadafce49e8569257a0cad56d24438a6fa1f0cbd7ee0af9b631f7492818a4ca3 + url: "https://pub.dev" + source: hosted + version: "0.8.9+1" + image_picker_linux: + dependency: transitive + description: + name: image_picker_linux + sha256: "4ed1d9bb36f7cd60aa6e6cd479779cc56a4cb4e4de8f49d487b1aaad831300fa" + url: "https://pub.dev" + source: hosted + version: "0.2.1+1" + image_picker_macos: + dependency: transitive + description: + name: image_picker_macos + sha256: "3f5ad1e8112a9a6111c46d0b57a7be2286a9a07fc6e1976fdf5be2bd31d4ff62" + url: "https://pub.dev" + source: hosted + version: "0.2.1+1" + image_picker_platform_interface: + dependency: transitive + description: + name: image_picker_platform_interface + sha256: fa4e815e6fcada50e35718727d83ba1c92f1edf95c0b4436554cec301b56233b + url: "https://pub.dev" + source: hosted + version: "2.9.3" + image_picker_windows: + dependency: transitive + description: + name: image_picker_windows + sha256: "6ad07afc4eb1bc25f3a01084d28520496c4a3bb0cb13685435838167c9dcedeb" + url: "https://pub.dev" + source: hosted + version: "0.2.1+1" intl: dependency: transitive description: diff --git a/packages/hmssdk_flutter/example/pubspec.yaml b/packages/hmssdk_flutter/example/pubspec.yaml index 4df1cfdf5..171abf091 100644 --- a/packages/hmssdk_flutter/example/pubspec.yaml +++ b/packages/hmssdk_flutter/example/pubspec.yaml @@ -26,7 +26,7 @@ dependencies: mobile_scanner: app_links: uuid: - flutter_foreground_task: ^6.1.3 + flutter_foreground_task: 6.1.3 flutter_svg: any provider: any diff --git a/packages/hmssdk_flutter/ios/Classes/Actions/HMSVirtualBackgroundAction.swift b/packages/hmssdk_flutter/ios/Classes/Actions/HMSVirtualBackgroundAction.swift new file mode 100644 index 000000000..c8ca1d258 --- /dev/null +++ b/packages/hmssdk_flutter/ios/Classes/Actions/HMSVirtualBackgroundAction.swift @@ -0,0 +1,130 @@ +// +// HMSVirtualBackgroundAction.swift +// hmssdk_flutter +// +// Created by Pushpam on 17/05/24. +// + +import Foundation +import HMSSDK + +internal protocol HMSVirtualBackgroundActionPluginProtocol { + @available(iOS 15.0, *) + var plugin: HMSVirtualBackgroundPlugin? { get } +} + +class HMSVirtualBackgroundAction: HMSVirtualBackgroundActionPluginProtocol { + + internal var _plugin: Any? + + @available(iOS 15.0, *) + internal var plugin: HMSVirtualBackgroundPlugin? { + if _plugin == nil { + _plugin = HMSVirtualBackgroundPlugin(backgroundImage: nil, blurRadius: 100) + } + return _plugin as? HMSVirtualBackgroundPlugin + } + + internal func performActions(_ call: FlutterMethodCall, _ result: @escaping FlutterResult) { + switch call.method { + case "enable_virtual_background": + enable(call, result) + case "disable_virtual_background": + disable(result) + case "enable_blur_background": + enableBlur(call, result) + case "disable_blur_background": + disableBlur(result) + case "change_virtual_background": + changeBackground(call, result) + case "is_virtual_background_supported": + isSupported(result) + default: + result(FlutterMethodNotImplemented) + } + } + + func enable(_ call: FlutterMethodCall, _ result: @escaping FlutterResult) { + + let arguments = call.arguments as! [AnyHashable: Any] + + guard let image = arguments["image"] as? FlutterStandardTypedData + else { + HMSErrorLogger.returnArgumentsError("Image can't be null") + return + } + + if #available(iOS 15.0, *) { + plugin?.backgroundImage = UIImage(data: image.data) + plugin?.activate() + } else { + HMSErrorLogger.logError("\(#function)", "Virtual Background is not supported below iOS 15", "Plugin not supported error") + } + result(nil) + } + + func disable(_ result: @escaping FlutterResult ) { + if #available(iOS 15.0, *) { + plugin?.deactivate() + } else { + HMSErrorLogger.logError("\(#function)", "Virtual Background is not supported below iOS 15", "Plugin not supported error") + } + result(nil) + } + + func enableBlur(_ call: FlutterMethodCall, _ result: @escaping FlutterResult) { + + let arguments = call.arguments as! [AnyHashable: Any] + + guard let blurRadius = arguments["blur_radius"] as? Int + else { + HMSErrorLogger.returnArgumentsError("blur radius not found") + return + } + + if #available(iOS 15.0, *) { + plugin?.backgroundImage = nil + plugin?.activate() + } else { + HMSErrorLogger.logError("\(#function)", "Virtual Background is not supported below iOS 15", "Plugin not supported error") + } + result(nil) + } + + func disableBlur(_ result: @escaping FlutterResult) { + + if #available(iOS 15.0, *) { + plugin?.deactivate() + } else { + HMSErrorLogger.logError("\(#function)", "Virtual Background is not supported below iOS 15", "Plugin not supported error") + } + result(nil) + + } + + func changeBackground(_ call: FlutterMethodCall, _ result: @escaping FlutterResult) { + + let arguments = call.arguments as! [AnyHashable: Any] + + guard let image = arguments["image"] as? FlutterStandardTypedData + else { + HMSErrorLogger.returnArgumentsError("Image can't be null") + return + } + + if #available(iOS 15.0, *) { + plugin?.backgroundImage = UIImage(data: image.data) + } else { + HMSErrorLogger.logError("\(#function)", "Virtual Background is not supported below iOS 15", "Plugin not supported error") + } + result(nil) + } + + func isSupported(_ result: @escaping FlutterResult) { + if #available(iOS 15.0, *) { + result(HMSResultExtension.toDictionary(true, true)) + } else { + result(HMSResultExtension.toDictionary(true, false)) + } + } +} diff --git a/packages/hmssdk_flutter/ios/Classes/Models/HMSTrackSettingsExtension.swift b/packages/hmssdk_flutter/ios/Classes/Models/HMSTrackSettingsExtension.swift index 0ba43524d..d0ea26d0b 100644 --- a/packages/hmssdk_flutter/ios/Classes/Models/HMSTrackSettingsExtension.swift +++ b/packages/hmssdk_flutter/ios/Classes/Models/HMSTrackSettingsExtension.swift @@ -9,6 +9,9 @@ import Foundation import HMSSDK class HMSTrackSettingsExtension { + + static var videoSettings: HMSVideoTrackSettings? + static func toDictionary(_ hmssdk: HMSSDK, _ audioMixerSourceMap: [String: HMSAudioNode]?) -> [String: Any] { let hmsTrackSettings = hmssdk.trackSettings @@ -57,7 +60,10 @@ class HMSTrackSettingsExtension { return dict } - static func setTrackSetting(_ settingsDict: [AnyHashable: Any], _ audioMixerSourceMap: [String: HMSAudioNode], _ result: @escaping FlutterResult) -> HMSTrackSettings? { + static func setTrackSetting(_ settingsDict: [AnyHashable: Any], + _ audioMixerSourceMap: [String: HMSAudioNode], + _ vbConformer: HMSVirtualBackgroundActionPluginProtocol, + _ result: @escaping FlutterResult) -> HMSTrackSettings? { var audioSettings: HMSAudioTrackSettings? @@ -130,10 +136,22 @@ class HMSTrackSettingsExtension { } } - var videoSettings: HMSVideoTrackSettings? if let videoSettingsDict = settingsDict["video_track_setting"] as? [AnyHashable: Any] { if let cameraFacing = videoSettingsDict["camera_facing"] as? String, + let isVirtualBackgroundEnabled = videoSettingsDict["is_virtual_background_enabled"] as? Bool, let initialMuteState = videoSettingsDict["track_initial_state"] as? String { + + var videoPlugins: [HMSVideoPlugin]? + if isVirtualBackgroundEnabled { + if #available(iOS 15.0, *) { + if let virtualbackground = vbConformer.plugin { + videoPlugins = [] + videoPlugins?.append(virtualbackground) + } + } else { + HMSErrorLogger.logError("\(#function)", "Virtual Background is not supported below iOS 15", "Plugin not supported error") + } + } videoSettings = HMSVideoTrackSettings(codec: HMSCodec.VP8, resolution: .init(width: 320, height: 180), maxBitrate: 32, @@ -142,8 +160,7 @@ class HMSTrackSettingsExtension { simulcastSettings: nil, trackDescription: "track_description", initialMuteState: getinitialMuteState(from: initialMuteState), - videoPlugins: nil) - + videoPlugins: videoPlugins) } } diff --git a/packages/hmssdk_flutter/ios/Classes/SwiftHmssdkFlutterPlugin.swift b/packages/hmssdk_flutter/ios/Classes/SwiftHmssdkFlutterPlugin.swift index aa2b04c5d..fd98f14f5 100644 --- a/packages/hmssdk_flutter/ios/Classes/SwiftHmssdkFlutterPlugin.swift +++ b/packages/hmssdk_flutter/ios/Classes/SwiftHmssdkFlutterPlugin.swift @@ -45,6 +45,7 @@ public class SwiftHmssdkFlutterPlugin: NSObject, FlutterPlugin, HMSUpdateListene var hlsStreamUrl: String? private var isRoomAudioUnmutedLocally = true + // MARK: - Flutter Setup @@ -341,11 +342,18 @@ public class SwiftHmssdkFlutterPlugin: NSObject, FlutterPlugin, HMSUpdateListene case "start_whiteboard", "stop_whiteboard", "add_whiteboard_update_listener", "remove_whiteboard_update_listener": whiteboardActions(call, result) + case "enable_virtual_background", "disable_virtual_background", "enable_blur_background", "disable_blur_background", "change_virtual_background", "is_virtual_background_supported": + vbAction.performActions(call, result) + default: result(FlutterMethodNotImplemented) } } + private lazy var vbAction: HMSVirtualBackgroundAction = { + HMSVirtualBackgroundAction() + }() + // MARK: - Build Actions private func buildActions(_ call: FlutterMethodCall, _ result: @escaping FlutterResult) { switch call.method { @@ -845,7 +853,7 @@ public class SwiftHmssdkFlutterPlugin: NSObject, FlutterPlugin, HMSUpdateListene var trackSettings: HMSTrackSettings? if let settingsDict = arguments?["hms_track_setting"] as? [AnyHashable: Any] { self.audioMixerSourceInit(settingsDict, sdk, result) - trackSettings = HMSTrackSettingsExtension.setTrackSetting(settingsDict, self.audioMixerSourceMap, result) + trackSettings = HMSTrackSettingsExtension.setTrackSetting(settingsDict, self.audioMixerSourceMap, vbAction, result) } if let settings = trackSettings { diff --git a/packages/hmssdk_flutter/lib/assets/sdk-versions.json b/packages/hmssdk_flutter/lib/assets/sdk-versions.json index b84919fd8..c473abe8c 100644 --- a/packages/hmssdk_flutter/lib/assets/sdk-versions.json +++ b/packages/hmssdk_flutter/lib/assets/sdk-versions.json @@ -1,8 +1,8 @@ { "flutter": "1.10.2", - "ios": "1.10.0", + "ios": "1.11.0", "iOSBroadcastExtension": "0.0.9", "iOSHLSPlayerSDK": "0.0.2", "iOSNoiseCancellationModels": "1.0.0", - "android": "2.9.56" + "android": "2.9.57" } diff --git a/packages/hmssdk_flutter/lib/hmssdk_flutter.dart b/packages/hmssdk_flutter/lib/hmssdk_flutter.dart index 11fac1b6f..67780008a 100644 --- a/packages/hmssdk_flutter/lib/hmssdk_flutter.dart +++ b/packages/hmssdk_flutter/lib/hmssdk_flutter.dart @@ -122,6 +122,7 @@ export 'src/model/whiteboard/hms_whiteboard_model.dart'; export 'src/model/whiteboard/hms_whiteboard_permission.dart'; export 'src/model/whiteboard/hms_whiteboard_update_listener.dart'; export 'src/model/hls_player/hms_hls_layer.dart'; +export 'src/model/hms_video_filter.dart'; //Views export 'src/ui/meeting/hms_texture_view.dart'; diff --git a/packages/hmssdk_flutter/lib/src/common/platform_methods.dart b/packages/hmssdk_flutter/lib/src/common/platform_methods.dart index 178f82cee..d49355bc6 100644 --- a/packages/hmssdk_flutter/lib/src/common/platform_methods.dart +++ b/packages/hmssdk_flutter/lib/src/common/platform_methods.dart @@ -239,6 +239,14 @@ enum PlatformMethod { stopWhiteboard, addWhiteboardUpdateListener, removeWhiteboardUpdateListener, + + ///Virtual background methods + enableVirtualBackground, + disableVirtualBackground, + changeVirtualBackground, + enableBlurBackground, + disableBlurBackground, + isVirtualBackgroundSupported } extension PlatformMethodValues on PlatformMethod { @@ -604,6 +612,20 @@ extension PlatformMethodValues on PlatformMethod { case PlatformMethod.removeWhiteboardUpdateListener: return "remove_whiteboard_update_listener"; + ///Virtual background methods + case PlatformMethod.enableVirtualBackground: + return "enable_virtual_background"; + case PlatformMethod.disableVirtualBackground: + return "disable_virtual_background"; + case PlatformMethod.changeVirtualBackground: + return "change_virtual_background"; + case PlatformMethod.enableBlurBackground: + return "enable_blur_background"; + case PlatformMethod.disableBlurBackground: + return "disable_blur_background"; + case PlatformMethod.isVirtualBackgroundSupported: + return "is_virtual_background_supported"; + default: return 'unknown'; } @@ -969,6 +991,20 @@ extension PlatformMethodValues on PlatformMethod { case "remove_whiteboard_update_listener": return PlatformMethod.removeWhiteboardUpdateListener; + ///Virtual Background Methods + case "enable_virtual_background": + return PlatformMethod.enableVirtualBackground; + case "disable_virtual_background": + return PlatformMethod.disableVirtualBackground; + case "change_virtual_background": + return PlatformMethod.changeVirtualBackground; + case "enable_blur_background": + return PlatformMethod.enableBlurBackground; + case "disable_blur_background": + return PlatformMethod.disableBlurBackground; + case "is_virtual_background_supported": + return PlatformMethod.isVirtualBackgroundSupported; + default: return PlatformMethod.unknown; } diff --git a/packages/hmssdk_flutter/lib/src/model/hms_video_filter.dart b/packages/hmssdk_flutter/lib/src/model/hms_video_filter.dart new file mode 100644 index 000000000..2e173b0af --- /dev/null +++ b/packages/hmssdk_flutter/lib/src/model/hms_video_filter.dart @@ -0,0 +1,72 @@ +///Package imports +import 'package:flutter/foundation.dart'; +import 'package:hmssdk_flutter/hmssdk_flutter.dart'; + +///Project imports +import 'package:hmssdk_flutter/src/service/platform_service.dart'; + +///[HMSVideoFilter] is used to apply video effects like virtual background and blur +abstract class HMSVideoFilter { + static Future enable({required Uint8List? image}) async { + var result = await PlatformService.invokeMethod( + PlatformMethod.enableVirtualBackground, + arguments: {"image": image}); + + if (result != null) { + return HMSException.fromMap(result["error"]); + } else { + return null; + } + } + + static Future changeVirtualBackground( + {required Uint8List? image}) async { + PlatformService.invokeMethod(PlatformMethod.changeVirtualBackground, + arguments: {"image": image}); + return null; + } + + static Future isSupported() async { + var result = await PlatformService.invokeMethod( + PlatformMethod.isVirtualBackgroundSupported); + if (result["success"]) { + return result["data"]; + } else { + return false; + } + } + + static Future disable() async { + var result = await PlatformService.invokeMethod( + PlatformMethod.disableVirtualBackground); + + if (result != null) { + return HMSException.fromMap(result["error"]); + } else { + return null; + } + } + + static Future enableBlur({required int blurRadius}) async { + assert(blurRadius >= 0 && blurRadius <= 100, + "blurRadius should be between 0 and 100, current value is $blurRadius"); + var result = await PlatformService.invokeMethod( + PlatformMethod.enableBlurBackground, + arguments: {"blur_radius": blurRadius}); + if (result != null) { + return HMSException.fromMap(result["error"]); + } else { + return null; + } + } + + static Future disableBlur() async { + var result = await PlatformService.invokeMethod( + PlatformMethod.disableBlurBackground); + if (result != null) { + return HMSException.fromMap(result["error"]); + } else { + return null; + } + } +} diff --git a/packages/hmssdk_flutter/lib/src/model/hms_video_track_setting.dart b/packages/hmssdk_flutter/lib/src/model/hms_video_track_setting.dart index 9fd0fc676..7de121d54 100644 --- a/packages/hmssdk_flutter/lib/src/model/hms_video_track_setting.dart +++ b/packages/hmssdk_flutter/lib/src/model/hms_video_track_setting.dart @@ -19,11 +19,14 @@ class HMSVideoTrackSetting { /// [forceSoftwareDecoder] property to use software decoder. By default it's set to false. This property is available only on Android. final bool? forceSoftwareDecoder; + final bool? isVirtualBackgroundEnabled; + HMSVideoTrackSetting( {this.cameraFacing = HMSCameraFacing.FRONT, this.disableAutoResize = false, this.trackInitialState = HMSTrackInitState.UNMUTED, - this.forceSoftwareDecoder = false}); + this.forceSoftwareDecoder = false, + this.isVirtualBackgroundEnabled = false}); factory HMSVideoTrackSetting.fromMap(Map map) { return HMSVideoTrackSetting( @@ -36,7 +39,9 @@ class HMSVideoTrackSetting { : HMSTrackInitState.UNMUTED, forceSoftwareDecoder: map.containsKey('force_software_decoder') ? map['force_software_decoder'] - : false); + : false, + isVirtualBackgroundEnabled: + map["is_virtual_background_enabled"] ?? false); } Map toMap() { @@ -48,7 +53,8 @@ class HMSVideoTrackSetting { 'track_initial_state': HMSTrackInitStateValue.getValuefromHMSTrackInitState( trackInitialState), - 'force_software_decoder': forceSoftwareDecoder ?? false + 'force_software_decoder': forceSoftwareDecoder ?? false, + 'is_virtual_background_enabled': isVirtualBackgroundEnabled ?? false, }; } }