From dd41beee7a45fbcfe296557a871d1ac9e28227b4 Mon Sep 17 00:00:00 2001 From: fcancela Date: Sun, 1 May 2022 18:02:22 -0300 Subject: [PATCH 1/5] h264-support: Temporal fix in example --- example/android/app/build.gradle | 5 +- .../flutter/example/MainActivity.java | 54 ++++++++++++++++++ .../com/example/example/MainActivity.kt | 6 -- .../src/main/res/mipmap-xhdpi/ic_launcher.png | Bin 0 -> 721 bytes example/android/build.gradle | 3 + example/lib/main.dart | 1 + .../lib/millicast_publisher_user_media.dart | 2 + example/lib/publisher_settings_widget.dart | 12 +++- example/lib/publisher_widget.dart | 26 +++++++-- 9 files changed, 93 insertions(+), 16 deletions(-) create mode 100644 example/android/app/src/main/java/com/millicast/flutter/example/MainActivity.java delete mode 100644 example/android/app/src/main/kotlin/com/example/example/MainActivity.kt create mode 100644 example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png diff --git a/example/android/app/build.gradle b/example/android/app/build.gradle index d0eff5c..7364dc2 100644 --- a/example/android/app/build.gradle +++ b/example/android/app/build.gradle @@ -40,9 +40,8 @@ android { 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 "com.millicast.flutter.example" minSdkVersion 21 targetSdkVersion flutter.targetSdkVersion @@ -64,5 +63,7 @@ flutter { } dependencies { + implementation 'com.github.webrtc-sdk:android:97.4692.01' + implementation 'androidx.annotation:annotation:1.1.0' implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" } diff --git a/example/android/app/src/main/java/com/millicast/flutter/example/MainActivity.java b/example/android/app/src/main/java/com/millicast/flutter/example/MainActivity.java new file mode 100644 index 0000000..f522212 --- /dev/null +++ b/example/android/app/src/main/java/com/millicast/flutter/example/MainActivity.java @@ -0,0 +1,54 @@ +package com.millicast.flutter.example; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + +import android.content.ContextWrapper; +import android.content.Intent; +import android.content.IntentFilter; + +import android.os.BatteryManager; +import android.os.Build.VERSION; +import android.os.Build.VERSION_CODES; +import android.os.Bundle; + +import org.webrtc.DefaultVideoEncoderFactory; +import org.webrtc.VideoCodecInfo; +import org.webrtc.DtmfSender; +import org.webrtc.EglBase; + +import com.cloudwebrtc.webrtc.utils.EglUtils; + +import io.flutter.embedding.android.FlutterActivity; +import io.flutter.embedding.engine.FlutterEngine; +import io.flutter.plugin.common.MethodChannel; + +import java.util.ArrayList; + +public class MainActivity extends FlutterActivity { + private static final String CHANNEL = "sample.millicast.app/fluttersdk"; + + @Override + public void configureFlutterEngine(@NonNull FlutterEngine flutterEngine) { + super.configureFlutterEngine(flutterEngine); + new MethodChannel(flutterEngine.getDartExecutor().getBinaryMessenger(), CHANNEL) + .setMethodCallHandler( + (call, result) -> { + switch (call.method) { + case "getSupportedCodecs": + EglBase.Context eglContext = EglUtils.getRootEglBaseContext(); + DefaultVideoEncoderFactory dummyEncoderFactory = new DefaultVideoEncoderFactory( + eglContext, true, true); + ArrayList codecs = new ArrayList(); + for (VideoCodecInfo codec : dummyEncoderFactory.getSupportedCodecs()) { + codecs.add(codec.name); + } + result.success(codecs); + break; + default: + result.notImplemented(); + break; + } + }); + } +} diff --git a/example/android/app/src/main/kotlin/com/example/example/MainActivity.kt b/example/android/app/src/main/kotlin/com/example/example/MainActivity.kt deleted file mode 100644 index 807f535..0000000 --- a/example/android/app/src/main/kotlin/com/example/example/MainActivity.kt +++ /dev/null @@ -1,6 +0,0 @@ -package com.millicast.flutter.example - -import io.flutter.embedding.android.FlutterActivity - -class MainActivity: FlutterActivity() { -} diff --git a/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png b/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..09d4391482be68e9e4a07fab769b5de337d16eb1 GIT binary patch literal 721 zcmeAS@N?(olHy`uVBq!ia0vp^2_VeD3?#3*wSy!iOI#yLg7ec#$`gxH85~pclTsBt za}(23gHjVyDhp4h+5i=O3-AeX1=1l$e`s#|#^}+&7(N@w0CIr{$Oe+Uk^K-ZP~83C zcc@hG6rikF&NPT(23>y!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/example/android/build.gradle b/example/android/build.gradle index 9e8dea7..e44c8e1 100644 --- a/example/android/build.gradle +++ b/example/android/build.gradle @@ -3,6 +3,7 @@ buildscript { repositories { google() mavenCentral() + jcenter() } dependencies { @@ -15,6 +16,8 @@ allprojects { repositories { google() mavenCentral() + jcenter() + maven { url 'https://jitpack.io' } } } diff --git a/example/lib/main.dart b/example/lib/main.dart index f613b4d..5c0d149 100644 --- a/example/lib/main.dart +++ b/example/lib/main.dart @@ -65,6 +65,7 @@ class MyApp extends StatelessWidget { '/subscriber': (context) => const SubscriberWidget(), '/settings': (context) => const PublisherSettingsWidget( isConnected: false, + supportedCodecs: [], ) }, home: HomeScreen(), diff --git a/example/lib/millicast_publisher_user_media.dart b/example/lib/millicast_publisher_user_media.dart index 52e603c..9948673 100644 --- a/example/lib/millicast_publisher_user_media.dart +++ b/example/lib/millicast_publisher_user_media.dart @@ -15,6 +15,7 @@ const String? sourceId = String.fromEnvironment('sourceId'); class MillicastPublishUserMedia extends Publish { MillicastMedia? mediaManager; + List? supportedCodecs; MillicastPublishUserMedia(options, tokenGenerator, autoReconnect) : super( @@ -29,6 +30,7 @@ class MillicastPublishUserMedia extends Publish { MillicastPublishUserMedia(options, tokenGenerator, autoReconnect); await instance.getMediaStream(); + await instance.webRTCPeer.getRTCLocalSDP(options: options); return instance; } diff --git a/example/lib/publisher_settings_widget.dart b/example/lib/publisher_settings_widget.dart index cec69ba..ce500c5 100644 --- a/example/lib/publisher_settings_widget.dart +++ b/example/lib/publisher_settings_widget.dart @@ -12,14 +12,20 @@ class PublisherSettingsWidget extends StatefulWidget { final MillicastPublishUserMedia? publisherMedia; final Map? options; final bool isConnected; + final List supportedCodecs; const PublisherSettingsWidget( - {this.publisherMedia, this.options, required this.isConnected, Key? key}) + {this.publisherMedia, + required this.supportedCodecs, + this.options, + required this.isConnected, + Key? key}) : super(key: key); @override _PublisherSettingsWidgetState createState() => // ignore: no_logic_in_create_state _PublisherSettingsWidgetState( publisherMedia: publisherMedia, + supportedCodecs: supportedCodecs, options: options, isConnected: isConnected); } @@ -30,9 +36,11 @@ class _PublisherSettingsWidgetState extends State { final _formKey = GlobalKey(); MillicastPublishUserMedia? publisherMedia; bool isSimulcastEnabled = true; + List supportedCodecs = ['h264', 'vp8', 'vp9', 'av1']; _PublisherSettingsWidgetState( {required this.publisherMedia, + required this.supportedCodecs, required this.options, required this.isConnected}); @@ -254,7 +262,7 @@ class _PublisherSettingsWidgetState extends State { style: TextStyle(color: Colors.white, fontSize: 15)), dropdownColor: Colors.purple, value: options?['codec'], - items: ['h264', 'vp8', 'vp9', 'av1'].map((String value) { + items: supportedCodecs.map((String value) { return DropdownMenuItem( value: value, child: Text( diff --git a/example/lib/publisher_widget.dart b/example/lib/publisher_widget.dart index 577c1aa..ac3bf78 100644 --- a/example/lib/publisher_widget.dart +++ b/example/lib/publisher_widget.dart @@ -1,4 +1,7 @@ +import 'dart:io'; + import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; import 'package:logger/logger.dart'; import 'dart:convert'; @@ -23,6 +26,7 @@ class PublisherWidget extends StatefulWidget { class _PublisherWidgetState extends State with WidgetsBindingObserver { + static const platform = MethodChannel('sample.millicast.app/fluttersdk'); Map options = {}; _PublisherWidgetState(); @@ -38,6 +42,7 @@ class _PublisherWidgetState extends State bool isLoading = false; bool isAudioMuted = false; bool _isMirrored = true; + List _supportedCodecs = ['h264', 'vp8', 'vp9', 'av1']; PeerConnection? webRtcPeer; @override @@ -72,6 +77,9 @@ class _PublisherWidgetState extends State @override void initState() { initRenderers(); + if (Platform.isAndroid) { + _setSupportedCodecs(); + } initPublish(); super.initState(); WidgetsBinding.instance?.addObserver(this); @@ -109,12 +117,6 @@ class _PublisherWidgetState extends State stopWatchTimer.onExecute.add(StopWatchExecute.start); }); - Map onUserCountOptions = { - 'accountId': Constants.accountId, - 'streamName': Constants.streamName, - 'callback': (countChange) => {refresh(countChange)}, - }; - setUserCount(); } @@ -123,6 +125,17 @@ class _PublisherWidgetState extends State setState(() {}); } + _setSupportedCodecs() async { + var codecObjects = await platform.invokeMethod('getSupportedCodecs'); + List codecs = []; + for (var codec in codecObjects) { + codecs.add((codec as String).toLowerCase()); + } + setState(() { + _supportedCodecs = codecs; + }); + } + void setUserCount() { // Add listener of broacastEvent to get UserCount _publisherMedia.on('broadcastEvent', this, (event, context) { @@ -248,6 +261,7 @@ class _PublisherWidgetState extends State builder: (BuildContext context) => PublisherSettingsWidget( publisherMedia: _publisherMedia, + supportedCodecs: _supportedCodecs, options: options, isConnected: isConnected), )); From e92a9a28833ec93c47647cc7cb6975290c6b38dc Mon Sep 17 00:00:00 2001 From: fcancela Date: Tue, 3 May 2022 00:37:44 -0300 Subject: [PATCH 2/5] h264-support: Implements getCapabilities, Fallback to other codecs if selected one is valid but not supported. --- .gitignore | 6 ++ android/.gitignore | 8 +++ android/build.gradle | 47 +++++++++++++++ android/gradle.properties | 16 +++++ android/proguard-rules.pro | 3 + android/settings.gradle | 1 + android/src/main/AndroidManifest.xml | 3 + .../MillicastFlutterSdkPlugin.java | 60 +++++++++++++++++++ example/android/.gitignore | 1 + example/android/app/build.gradle | 1 - .../flutter/example/MainActivity.java | 39 ------------ example/android/build.gradle | 3 - .../lib/millicast_publisher_user_media.dart | 8 ++- example/lib/publisher_widget.dart | 10 +--- ios/.gitignore | 38 ++++++++++++ ios/Assets/.gitkeep | 0 ios/Classes/MillicastFlutterSdkPlugin.h | 4 ++ ios/Classes/MillicastFlutterSdkPlugin.m | 15 +++++ .../SwiftMillicastFlutterSdkPlugin.swift | 14 +++++ ios/millicast_flutter_sdk.podspec | 21 +++++++ lib/millicast_flutter_sdk.dart | 1 + lib/src/peer_connection.dart | 10 +++- lib/src/signaling.dart | 7 +++ lib/src/utils/channel.dart | 29 +++++++++ pubspec.yaml | 9 ++- 25 files changed, 299 insertions(+), 55 deletions(-) create mode 100644 android/.gitignore create mode 100644 android/build.gradle create mode 100644 android/gradle.properties create mode 100644 android/proguard-rules.pro create mode 100644 android/settings.gradle create mode 100644 android/src/main/AndroidManifest.xml create mode 100644 android/src/main/java/com/millicast_flutter_sdk/MillicastFlutterSdkPlugin.java create mode 100644 ios/.gitignore create mode 100644 ios/Assets/.gitkeep create mode 100644 ios/Classes/MillicastFlutterSdkPlugin.h create mode 100644 ios/Classes/MillicastFlutterSdkPlugin.m create mode 100644 ios/Classes/SwiftMillicastFlutterSdkPlugin.swift create mode 100644 ios/millicast_flutter_sdk.podspec create mode 100644 lib/src/utils/channel.dart diff --git a/.gitignore b/.gitignore index 7346743..428e569 100644 --- a/.gitignore +++ b/.gitignore @@ -28,3 +28,9 @@ example/web # Env files *.env + +# IntelliJ related +*.iml +*.ipr +*.iws +.idea/ \ No newline at end of file diff --git a/android/.gitignore b/android/.gitignore new file mode 100644 index 0000000..c6cbe56 --- /dev/null +++ b/android/.gitignore @@ -0,0 +1,8 @@ +*.iml +.gradle +/local.properties +/.idea/workspace.xml +/.idea/libraries +.DS_Store +/build +/captures diff --git a/android/build.gradle b/android/build.gradle new file mode 100644 index 0000000..fda987c --- /dev/null +++ b/android/build.gradle @@ -0,0 +1,47 @@ +group 'com.millicast_flutter_sdk' +version '1.0' + +buildscript { + repositories { + google() + mavenCentral() + jcenter() + } + + dependencies { + classpath 'com.android.tools.build:gradle:4.1.3' + } +} + +rootProject.allprojects { + repositories { + google() + mavenCentral() + jcenter() + maven { url 'https://jitpack.io' } + } +} + +apply plugin: 'com.android.library' + +android { + compileSdkVersion 31 + + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } + + defaultConfig { + minSdkVersion 21 + multiDexEnabled true + testInstrumentationRunner 'androidx.test.runner.AndroidJUnitRunner' + consumerProguardFiles 'proguard-rules.pro' + } +} + +dependencies { + implementation 'com.github.webrtc-sdk:android:97.4692.01' + implementation 'androidx.annotation:annotation:1.1.0' + implementation 'com.android.support:multidex:2.0.1' +} diff --git a/android/gradle.properties b/android/gradle.properties new file mode 100644 index 0000000..433f971 --- /dev/null +++ b/android/gradle.properties @@ -0,0 +1,16 @@ +## For more details on how to configure your build environment visit +# http://www.gradle.org/docs/current/userguide/build_environment.html +# +# Specifies the JVM arguments used for the daemon process. +# The setting is particularly useful for tweaking memory settings. +# Default value: -Xmx1024m -XX:MaxPermSize=256m +# org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8 +# +# When configured, Gradle will run in incubating parallel mode. +# This option should only be used with decoupled projects. More details, visit +# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects +# org.gradle.parallel=true +#Mon May 02 10:37:31 UYT 2022 +org.gradle.jvmargs=-Xmx1536M +android.useAndroidX=true +android.enableJetifier=true diff --git a/android/proguard-rules.pro b/android/proguard-rules.pro new file mode 100644 index 0000000..54f34ec --- /dev/null +++ b/android/proguard-rules.pro @@ -0,0 +1,3 @@ +# Flutter WebRTC +-keep class com.cloudwebrtc.webrtc.** { *; } +-keep class org.webrtc.** { *; } \ No newline at end of file diff --git a/android/settings.gradle b/android/settings.gradle new file mode 100644 index 0000000..7c43c21 --- /dev/null +++ b/android/settings.gradle @@ -0,0 +1 @@ +rootProject.name = 'millicast_flutter_sdk' diff --git a/android/src/main/AndroidManifest.xml b/android/src/main/AndroidManifest.xml new file mode 100644 index 0000000..da9b4f0 --- /dev/null +++ b/android/src/main/AndroidManifest.xml @@ -0,0 +1,3 @@ + + diff --git a/android/src/main/java/com/millicast_flutter_sdk/MillicastFlutterSdkPlugin.java b/android/src/main/java/com/millicast_flutter_sdk/MillicastFlutterSdkPlugin.java new file mode 100644 index 0000000..f97ef21 --- /dev/null +++ b/android/src/main/java/com/millicast_flutter_sdk/MillicastFlutterSdkPlugin.java @@ -0,0 +1,60 @@ +package com.millicast_flutter_sdk; + +import androidx.annotation.NonNull; + +// import com.cloudwebrtc.webrtc.utils.EglUtils; + +import org.webrtc.DefaultVideoEncoderFactory; +import org.webrtc.EglBase; +import org.webrtc.VideoCodecInfo; + +import java.util.ArrayList; +import java.util.Map; + +import io.flutter.embedding.engine.plugins.FlutterPlugin; +import io.flutter.plugin.common.MethodCall; +import io.flutter.plugin.common.MethodChannel; +import io.flutter.plugin.common.MethodChannel.MethodCallHandler; +import io.flutter.plugin.common.MethodChannel.Result; + +/** MillicastFlutterSdkPlugin */ +public class MillicastFlutterSdkPlugin implements FlutterPlugin, MethodCallHandler { + /// 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 + /// when the Flutter Engine is detached from the Activity + private MethodChannel channel; + + @Override + public void onAttachedToEngine(@NonNull FlutterPluginBinding flutterPluginBinding) { + channel = new MethodChannel(flutterPluginBinding.getBinaryMessenger(), "millicast_flutter_sdk"); + channel.setMethodCallHandler(this); + } + + @Override + public void onMethodCall(@NonNull MethodCall call, @NonNull Result result) { + switch (call.method) { + case "getSupportedCodecs": + EglBase eglBase = EglBase.createEgl10(EglBase.CONFIG_PLAIN); + EglBase.Context eglContext = eglBase == null ? null : eglBase.getEglBaseContext(); + DefaultVideoEncoderFactory dummyEncoderFactory = new DefaultVideoEncoderFactory( + eglContext, true, true); + ArrayList codecs = new ArrayList(); + for (VideoCodecInfo codec : dummyEncoderFactory.getSupportedCodecs()) { + codecs.add(codec.name); + } + result.success(codecs); + break; + case "getPlatformVersion": + result.success("Android " + android.os.Build.VERSION.RELEASE); + default: + result.notImplemented(); + break; + } + } + + @Override + public void onDetachedFromEngine(@NonNull FlutterPluginBinding binding) { + channel.setMethodCallHandler(null); + } +} diff --git a/example/android/.gitignore b/example/android/.gitignore index 6f56801..4d1915e 100644 --- a/example/android/.gitignore +++ b/example/android/.gitignore @@ -5,6 +5,7 @@ gradle-wrapper.jar /gradlew.bat /local.properties GeneratedPluginRegistrant.java +/app/local.properties # Remember to never publicly share your keystore. # See https://flutter.dev/docs/deployment/android#reference-the-keystore-from-the-app diff --git a/example/android/app/build.gradle b/example/android/app/build.gradle index 7364dc2..482525f 100644 --- a/example/android/app/build.gradle +++ b/example/android/app/build.gradle @@ -63,7 +63,6 @@ flutter { } dependencies { - implementation 'com.github.webrtc-sdk:android:97.4692.01' implementation 'androidx.annotation:annotation:1.1.0' implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" } diff --git a/example/android/app/src/main/java/com/millicast/flutter/example/MainActivity.java b/example/android/app/src/main/java/com/millicast/flutter/example/MainActivity.java index f522212..de62870 100644 --- a/example/android/app/src/main/java/com/millicast/flutter/example/MainActivity.java +++ b/example/android/app/src/main/java/com/millicast/flutter/example/MainActivity.java @@ -7,48 +7,9 @@ import android.content.Intent; import android.content.IntentFilter; -import android.os.BatteryManager; -import android.os.Build.VERSION; -import android.os.Build.VERSION_CODES; -import android.os.Bundle; - -import org.webrtc.DefaultVideoEncoderFactory; -import org.webrtc.VideoCodecInfo; -import org.webrtc.DtmfSender; -import org.webrtc.EglBase; - -import com.cloudwebrtc.webrtc.utils.EglUtils; - import io.flutter.embedding.android.FlutterActivity; import io.flutter.embedding.engine.FlutterEngine; import io.flutter.plugin.common.MethodChannel; -import java.util.ArrayList; - public class MainActivity extends FlutterActivity { - private static final String CHANNEL = "sample.millicast.app/fluttersdk"; - - @Override - public void configureFlutterEngine(@NonNull FlutterEngine flutterEngine) { - super.configureFlutterEngine(flutterEngine); - new MethodChannel(flutterEngine.getDartExecutor().getBinaryMessenger(), CHANNEL) - .setMethodCallHandler( - (call, result) -> { - switch (call.method) { - case "getSupportedCodecs": - EglBase.Context eglContext = EglUtils.getRootEglBaseContext(); - DefaultVideoEncoderFactory dummyEncoderFactory = new DefaultVideoEncoderFactory( - eglContext, true, true); - ArrayList codecs = new ArrayList(); - for (VideoCodecInfo codec : dummyEncoderFactory.getSupportedCodecs()) { - codecs.add(codec.name); - } - result.success(codecs); - break; - default: - result.notImplemented(); - break; - } - }); - } } diff --git a/example/android/build.gradle b/example/android/build.gradle index e44c8e1..9e8dea7 100644 --- a/example/android/build.gradle +++ b/example/android/build.gradle @@ -3,7 +3,6 @@ buildscript { repositories { google() mavenCentral() - jcenter() } dependencies { @@ -16,8 +15,6 @@ allprojects { repositories { google() mavenCentral() - jcenter() - maven { url 'https://jitpack.io' } } } diff --git a/example/lib/millicast_publisher_user_media.dart b/example/lib/millicast_publisher_user_media.dart index 9948673..2439af3 100644 --- a/example/lib/millicast_publisher_user_media.dart +++ b/example/lib/millicast_publisher_user_media.dart @@ -2,6 +2,7 @@ import 'dart:io'; import 'package:flutter_webrtc/flutter_webrtc.dart'; import 'package:millicast_flutter_sdk/millicast_flutter_sdk.dart'; +import 'package:flutter/foundation.dart'; var _logger = getLogger('MillicastPublishUserMedia'); @@ -104,8 +105,11 @@ class MillicastMedia { try { mediaStream = await navigator.mediaDevices.getUserMedia(constraints); - if (Platform.isIOS) { - mediaStream?.getAudioTracks()[0].enableSpeakerphone(true); + // Adding this check check so we don't lose web support + if (!kIsWeb) { + if (Platform.isIOS) { + mediaStream?.getAudioTracks()[0].enableSpeakerphone(true); + } } return mediaStream; diff --git a/example/lib/publisher_widget.dart b/example/lib/publisher_widget.dart index ac3bf78..bad75ec 100644 --- a/example/lib/publisher_widget.dart +++ b/example/lib/publisher_widget.dart @@ -1,7 +1,4 @@ -import 'dart:io'; - import 'package:flutter/material.dart'; -import 'package:flutter/services.dart'; import 'package:logger/logger.dart'; import 'dart:convert'; @@ -26,7 +23,6 @@ class PublisherWidget extends StatefulWidget { class _PublisherWidgetState extends State with WidgetsBindingObserver { - static const platform = MethodChannel('sample.millicast.app/fluttersdk'); Map options = {}; _PublisherWidgetState(); @@ -77,9 +73,7 @@ class _PublisherWidgetState extends State @override void initState() { initRenderers(); - if (Platform.isAndroid) { - _setSupportedCodecs(); - } + _setSupportedCodecs(); initPublish(); super.initState(); WidgetsBinding.instance?.addObserver(this); @@ -126,7 +120,7 @@ class _PublisherWidgetState extends State } _setSupportedCodecs() async { - var codecObjects = await platform.invokeMethod('getSupportedCodecs'); + var codecObjects = (await PeerConnection.getCapabilities('video'))['codec']; List codecs = []; for (var codec in codecObjects) { codecs.add((codec as String).toLowerCase()); diff --git a/ios/.gitignore b/ios/.gitignore new file mode 100644 index 0000000..0c88507 --- /dev/null +++ b/ios/.gitignore @@ -0,0 +1,38 @@ +.idea/ +.vagrant/ +.sconsign.dblite +.svn/ + +.DS_Store +*.swp +profile + +DerivedData/ +build/ +GeneratedPluginRegistrant.h +GeneratedPluginRegistrant.m + +.generated/ + +*.pbxuser +*.mode1v3 +*.mode2v3 +*.perspectivev3 + +!default.pbxuser +!default.mode1v3 +!default.mode2v3 +!default.perspectivev3 + +xcuserdata + +*.moved-aside + +*.pyc +*sync/ +Icon? +.tags* + +/Flutter/Generated.xcconfig +/Flutter/ephemeral/ +/Flutter/flutter_export_environment.sh \ No newline at end of file diff --git a/ios/Assets/.gitkeep b/ios/Assets/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/ios/Classes/MillicastFlutterSdkPlugin.h b/ios/Classes/MillicastFlutterSdkPlugin.h new file mode 100644 index 0000000..11abdb5 --- /dev/null +++ b/ios/Classes/MillicastFlutterSdkPlugin.h @@ -0,0 +1,4 @@ +#import + +@interface MillicastFlutterSdkPlugin : NSObject +@end diff --git a/ios/Classes/MillicastFlutterSdkPlugin.m b/ios/Classes/MillicastFlutterSdkPlugin.m new file mode 100644 index 0000000..cd04d16 --- /dev/null +++ b/ios/Classes/MillicastFlutterSdkPlugin.m @@ -0,0 +1,15 @@ +#import "MillicastFlutterSdkPlugin.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 "millicast_flutter_sdk-Swift.h" +#endif + +@implementation MillicastFlutterSdkPlugin ++ (void)registerWithRegistrar:(NSObject*)registrar { + [SwiftMillicastFlutterSdkPlugin registerWithRegistrar:registrar]; +} +@end diff --git a/ios/Classes/SwiftMillicastFlutterSdkPlugin.swift b/ios/Classes/SwiftMillicastFlutterSdkPlugin.swift new file mode 100644 index 0000000..f3f0e9e --- /dev/null +++ b/ios/Classes/SwiftMillicastFlutterSdkPlugin.swift @@ -0,0 +1,14 @@ +import Flutter +import UIKit + +public class SwiftMillicastFlutterSdkPlugin: NSObject, FlutterPlugin { + public static func register(with registrar: FlutterPluginRegistrar) { + let channel = FlutterMethodChannel(name: "millicast_flutter_sdk", binaryMessenger: registrar.messenger()) + let instance = SwiftMillicastFlutterSdkPlugin() + registrar.addMethodCallDelegate(instance, channel: channel) + } + + public func handle(_ call: FlutterMethodCall, result: @escaping FlutterResult) { + result("iOS " + UIDevice.current.systemVersion) + } +} diff --git a/ios/millicast_flutter_sdk.podspec b/ios/millicast_flutter_sdk.podspec new file mode 100644 index 0000000..8a5616b --- /dev/null +++ b/ios/millicast_flutter_sdk.podspec @@ -0,0 +1,21 @@ +# +# To learn more about a Podspec see http://guides.cocoapods.org/syntax/podspec.html. +# Run `pod lib lint millicast_flutter_sdk.podspec` to validate before publishing. +# +Pod::Spec.new do |s| + s.name = 'millicast_flutter_sdk' + s.version = '0.2.0' + s.summary = 'A Flutter SDK that allows developers to simplify Millicast services integration into their own Android and iOS apps.' + s.homepage = 'https://github.com/millicast/flutter-sdk/ios' + s.license = { :file => '../LICENSE' } + s.author = { 'Millicast' => 'fabian.cancela@dolby.com' } + s.source = { :path => '.' } + s.source_files = 'Classes/**/*' + s.dependency 'Flutter' + s.dependency 'WebRTC-SDK', '97.4692.02' + s.platform = :ios, '9.0' + + # 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/millicast_flutter_sdk.dart b/lib/millicast_flutter_sdk.dart index bf5b5a2..027e84c 100644 --- a/lib/millicast_flutter_sdk.dart +++ b/lib/millicast_flutter_sdk.dart @@ -4,3 +4,4 @@ export 'src/view.dart'; export 'src/signaling.dart'; export 'src/peer_connection.dart'; export 'src/logger.dart'; +export 'src/utils/channel.dart'; diff --git a/lib/src/peer_connection.dart b/lib/src/peer_connection.dart index 3c4a043..4af514b 100644 --- a/lib/src/peer_connection.dart +++ b/lib/src/peer_connection.dart @@ -4,6 +4,7 @@ import 'dart:convert'; import 'package:eventify/eventify.dart'; import 'package:millicast_flutter_sdk/src/peer_connection_stats.dart'; import 'package:millicast_flutter_sdk/src/utils/sdp_parser.dart'; +import 'utils/channel.dart'; import 'utils/reemit.dart'; import 'config.dart'; @@ -315,7 +316,14 @@ class PeerConnection extends EventEmitter { /// Millicast Media Server. /// Bug: This ticket is related to the implementation of /// jsTrack.getCapabilities(), https://github.com/dart-lang/sdk/issues/44319 - static getCapabilities(String kind) {} + static Future getCapabilities(String kind) async { + if (kind == 'video') { + return {'codec': await NativeChannel.supportedCodecs}; + } else { + // kind is audio + return {'codec': []}; + } + } /// Get sender tracks /// Returns [List] of [MediaStreamTrack] with all tracks in sender peer. diff --git a/lib/src/signaling.dart b/lib/src/signaling.dart index e6cde5a..3f67de0 100644 --- a/lib/src/signaling.dart +++ b/lib/src/signaling.dart @@ -1,4 +1,5 @@ import 'package:eventify/eventify.dart'; +import 'package:millicast_flutter_sdk/src/utils/channel.dart'; import 'package:millicast_flutter_sdk/src/utils/sdp_parser.dart'; import 'utils/transaction_manager.dart'; import 'package:web_socket_channel/web_socket_channel.dart'; @@ -152,6 +153,12 @@ class Signaling extends EventEmitter { _logger.e('Invalid codec. Possible values are: $videoCodec'); throw Exception('Invalid codec. Possible values are: $videoCodec'); } + List codecs = (await NativeChannel.supportedCodecs); + if (!codecs.contains(options['codec'])) { + options['codec'] = codecs[0]; + _logger + .w('Codec not supported by this device. Fallback to: ${codecs[0]}'); + } if (options['codec'] == videoCodec['AV1']) { sdp = SdpParser.adaptCodecName(sdp, 'AV1X', videoCodec['AV1']!); } diff --git a/lib/src/utils/channel.dart b/lib/src/utils/channel.dart new file mode 100644 index 0000000..e43b3af --- /dev/null +++ b/lib/src/utils/channel.dart @@ -0,0 +1,29 @@ +import 'dart:async'; +import 'dart:io'; + +import 'package:flutter/foundation.dart'; +import 'package:flutter/services.dart'; + +class NativeChannel { + static const MethodChannel _channel = MethodChannel('millicast_flutter_sdk'); + + static Future get platformVersion async { + final String? version = await _channel.invokeMethod('getPlatformVersion'); + return version; + } + + static Future> get supportedCodecs async { + List codecs = [ + 'vp8', + 'vp9', + 'h264', + 'av1', + ]; + if (!kIsWeb) { + if (Platform.isAndroid) { + codecs = await _channel.invokeMethod('getSupportedCodecs'); + } + } + return codecs; + } +} diff --git a/pubspec.yaml b/pubspec.yaml index 226ca40..9050fa0 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -9,7 +9,7 @@ environment: dependencies: eventify: ^1.0.0 - dotenv: ^3.0.0 + dotenv: ^4.0.0 flutter: sdk: flutter logger: ^1.1.0 @@ -33,6 +33,13 @@ dev_dependencies: # The following section is specific to Flutter. flutter: + plugin: + platforms: + android: + package: com.millicast_flutter_sdk + pluginClass: MillicastFlutterSdkPlugin + ios: + pluginClass: MillicastFlutterSdkPlugin # To add assets to your package, add an assets section, like this: # assets: From b81e27aa4e0f002acc150e9d48bf41989c60a6f8 Mon Sep 17 00:00:00 2001 From: fcancela Date: Tue, 3 May 2022 17:09:07 -0300 Subject: [PATCH 3/5] h264-support: Code review corrections --- example/lib/millicast_publisher_user_media.dart | 1 - example/lib/publisher_widget.dart | 4 ++-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/example/lib/millicast_publisher_user_media.dart b/example/lib/millicast_publisher_user_media.dart index 2439af3..95128ed 100644 --- a/example/lib/millicast_publisher_user_media.dart +++ b/example/lib/millicast_publisher_user_media.dart @@ -31,7 +31,6 @@ class MillicastPublishUserMedia extends Publish { MillicastPublishUserMedia(options, tokenGenerator, autoReconnect); await instance.getMediaStream(); - await instance.webRTCPeer.getRTCLocalSDP(options: options); return instance; } diff --git a/example/lib/publisher_widget.dart b/example/lib/publisher_widget.dart index bad75ec..62364e7 100644 --- a/example/lib/publisher_widget.dart +++ b/example/lib/publisher_widget.dart @@ -31,14 +31,14 @@ class _PublisherWidgetState extends State mode: StopWatchMode.countUp, ); final RTCVideoRenderer _localRenderer = RTCVideoRenderer(); - late String _viewers = '0'; + String _viewers = '0'; late MillicastPublishUserMedia _publisherMedia; + late List _supportedCodecs; bool isVideoMuted = false; bool isConnected = false; bool isLoading = false; bool isAudioMuted = false; bool _isMirrored = true; - List _supportedCodecs = ['h264', 'vp8', 'vp9', 'av1']; PeerConnection? webRtcPeer; @override From 6f27a76c92753f6c0852c6b50fddccc2f26a70f9 Mon Sep 17 00:00:00 2001 From: fcancela Date: Tue, 3 May 2022 17:20:45 -0300 Subject: [PATCH 4/5] h264-support: Remove pubspec.lock from gitignore --- .gitignore | 3 --- 1 file changed, 3 deletions(-) diff --git a/.gitignore b/.gitignore index 428e569..482e492 100644 --- a/.gitignore +++ b/.gitignore @@ -7,9 +7,6 @@ build/ .idea/ -# If you're building an application, you may want to check-in your pubspec.lock -pubspec.lock - # Directory created by dartdoc # If you don't generate documentation locally you can remove this line. doc/api/ From 3b6f49435fc61c11e44ce948a9a8d8879ebc94e2 Mon Sep 17 00:00:00 2001 From: fcancela Date: Tue, 3 May 2022 17:21:03 -0300 Subject: [PATCH 5/5] mend --- example/pubspec.lock | 691 +++++++++++++++++++++++++++++++++++++++++ pubspec.lock | 714 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 1405 insertions(+) create mode 100644 example/pubspec.lock create mode 100644 pubspec.lock diff --git a/example/pubspec.lock b/example/pubspec.lock new file mode 100644 index 0000000..3aa4e89 --- /dev/null +++ b/example/pubspec.lock @@ -0,0 +1,691 @@ +# Generated by pub +# See https://dart.dev/tools/pub/glossary#lockfile +packages: + _fe_analyzer_shared: + dependency: transitive + description: + name: _fe_analyzer_shared + url: "https://pub.dartlang.org" + source: hosted + version: "38.0.0" + analyzer: + dependency: transitive + description: + name: analyzer + url: "https://pub.dartlang.org" + source: hosted + version: "3.4.1" + archive: + dependency: transitive + description: + name: archive + url: "https://pub.dartlang.org" + source: hosted + version: "3.3.0" + args: + dependency: transitive + description: + name: args + url: "https://pub.dartlang.org" + source: hosted + version: "2.3.0" + async: + dependency: transitive + description: + name: async + url: "https://pub.dartlang.org" + source: hosted + version: "2.8.2" + boolean_selector: + dependency: transitive + description: + name: boolean_selector + url: "https://pub.dartlang.org" + source: hosted + version: "2.1.0" + build: + dependency: transitive + description: + name: build + url: "https://pub.dartlang.org" + source: hosted + version: "2.2.1" + built_collection: + dependency: transitive + description: + name: built_collection + url: "https://pub.dartlang.org" + source: hosted + version: "5.1.1" + built_value: + dependency: transitive + description: + name: built_value + url: "https://pub.dartlang.org" + source: hosted + version: "8.1.4" + characters: + dependency: transitive + description: + name: characters + url: "https://pub.dartlang.org" + source: hosted + version: "1.2.0" + charcode: + dependency: transitive + description: + name: charcode + url: "https://pub.dartlang.org" + source: hosted + version: "1.3.1" + clock: + dependency: transitive + description: + name: clock + url: "https://pub.dartlang.org" + source: hosted + version: "1.1.0" + code_builder: + dependency: transitive + description: + name: code_builder + url: "https://pub.dartlang.org" + source: hosted + version: "4.1.0" + collection: + dependency: transitive + description: + name: collection + url: "https://pub.dartlang.org" + source: hosted + version: "1.15.0" + convert: + dependency: transitive + description: + name: convert + url: "https://pub.dartlang.org" + source: hosted + version: "3.0.1" + crypto: + dependency: transitive + description: + name: crypto + url: "https://pub.dartlang.org" + source: hosted + version: "3.0.1" + cupertino_icons: + dependency: "direct main" + description: + name: cupertino_icons + url: "https://pub.dartlang.org" + source: hosted + version: "1.0.4" + dart_style: + dependency: transitive + description: + name: dart_style + url: "https://pub.dartlang.org" + source: hosted + version: "2.2.2" + dart_webrtc: + dependency: transitive + description: + name: dart_webrtc + url: "https://pub.dartlang.org" + source: hosted + version: "1.0.5" + dotenv: + dependency: transitive + description: + name: dotenv + url: "https://pub.dartlang.org" + source: hosted + version: "4.0.1" + eventify: + dependency: transitive + description: + name: eventify + url: "https://pub.dartlang.org" + source: hosted + version: "1.0.0" + fake_async: + dependency: transitive + description: + name: fake_async + url: "https://pub.dartlang.org" + source: hosted + version: "1.2.0" + ffi: + dependency: transitive + description: + name: ffi + url: "https://pub.dartlang.org" + source: hosted + version: "1.1.2" + file: + dependency: transitive + description: + name: file + url: "https://pub.dartlang.org" + source: hosted + version: "6.1.2" + fixnum: + dependency: transitive + description: + name: fixnum + url: "https://pub.dartlang.org" + source: hosted + version: "1.0.0" + flutter: + dependency: "direct main" + description: flutter + source: sdk + version: "0.0.0" + flutter_dotenv: + dependency: "direct main" + description: + name: flutter_dotenv + url: "https://pub.dartlang.org" + source: hosted + version: "5.0.2" + flutter_launcher_icons: + dependency: "direct dev" + description: + name: flutter_launcher_icons + url: "https://pub.dartlang.org" + source: hosted + version: "0.9.2" + flutter_lints: + dependency: "direct dev" + description: + name: flutter_lints + url: "https://pub.dartlang.org" + source: hosted + version: "1.0.4" + flutter_settings_ui: + dependency: "direct main" + description: + name: flutter_settings_ui + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.1" + flutter_test: + dependency: "direct dev" + description: flutter + source: sdk + version: "0.0.0" + flutter_web_plugins: + dependency: transitive + description: flutter + source: sdk + version: "0.0.0" + flutter_webrtc: + dependency: "direct main" + description: + name: flutter_webrtc + url: "https://pub.dartlang.org" + source: hosted + version: "0.8.5" + glob: + dependency: transitive + description: + name: glob + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.2" + http: + dependency: "direct main" + description: + name: http + url: "https://pub.dartlang.org" + source: hosted + version: "0.13.4" + http_parser: + dependency: transitive + description: + name: http_parser + url: "https://pub.dartlang.org" + source: hosted + version: "4.0.0" + image: + dependency: transitive + description: + name: image + url: "https://pub.dartlang.org" + source: hosted + version: "3.1.3" + js: + dependency: transitive + description: + name: js + url: "https://pub.dartlang.org" + source: hosted + version: "0.6.3" + jwt_decode: + dependency: transitive + description: + name: jwt_decode + url: "https://pub.dartlang.org" + source: hosted + version: "0.3.1" + lints: + dependency: transitive + description: + name: lints + url: "https://pub.dartlang.org" + source: hosted + version: "1.0.1" + logger: + dependency: "direct main" + description: + name: logger + url: "https://pub.dartlang.org" + source: hosted + version: "1.1.0" + logging: + dependency: transitive + description: + name: logging + url: "https://pub.dartlang.org" + source: hosted + version: "1.0.2" + matcher: + dependency: transitive + description: + name: matcher + url: "https://pub.dartlang.org" + source: hosted + version: "0.12.11" + material_color_utilities: + dependency: transitive + description: + name: material_color_utilities + url: "https://pub.dartlang.org" + source: hosted + version: "0.1.3" + meta: + dependency: transitive + description: + name: meta + url: "https://pub.dartlang.org" + source: hosted + version: "1.7.0" + millicast_flutter_sdk: + dependency: "direct main" + description: + path: ".." + relative: true + source: path + version: "0.0.1" + mime: + dependency: transitive + description: + name: mime + url: "https://pub.dartlang.org" + source: hosted + version: "1.0.1" + mockito: + dependency: transitive + description: + name: mockito + url: "https://pub.dartlang.org" + source: hosted + version: "5.1.0" + package_config: + dependency: transitive + description: + name: package_config + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.2" + path: + dependency: transitive + description: + name: path + url: "https://pub.dartlang.org" + source: hosted + version: "1.8.0" + path_provider: + dependency: transitive + description: + name: path_provider + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.9" + path_provider_android: + dependency: transitive + description: + name: path_provider_android + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.12" + path_provider_ios: + dependency: transitive + description: + name: path_provider_ios + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.8" + path_provider_linux: + dependency: transitive + description: + name: path_provider_linux + url: "https://pub.dartlang.org" + source: hosted + version: "2.1.5" + path_provider_macos: + dependency: transitive + description: + name: path_provider_macos + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.5" + path_provider_platform_interface: + dependency: transitive + description: + name: path_provider_platform_interface + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.3" + path_provider_windows: + dependency: transitive + description: + name: path_provider_windows + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.5" + petitparser: + dependency: transitive + description: + name: petitparser + url: "https://pub.dartlang.org" + source: hosted + version: "4.4.0" + platform: + dependency: transitive + description: + name: platform + url: "https://pub.dartlang.org" + source: hosted + version: "3.1.0" + plugin_platform_interface: + dependency: transitive + description: + name: plugin_platform_interface + url: "https://pub.dartlang.org" + source: hosted + version: "2.1.2" + process: + dependency: transitive + description: + name: process + url: "https://pub.dartlang.org" + source: hosted + version: "4.2.4" + pub_semver: + dependency: transitive + description: + name: pub_semver + url: "https://pub.dartlang.org" + source: hosted + version: "2.1.1" + rxdart: + dependency: transitive + description: + name: rxdart + url: "https://pub.dartlang.org" + source: hosted + version: "0.27.3" + sdp_transform: + dependency: transitive + description: + name: sdp_transform + url: "https://pub.dartlang.org" + source: hosted + version: "0.3.2" + share_plus: + dependency: "direct main" + description: + name: share_plus + url: "https://pub.dartlang.org" + source: hosted + version: "3.1.0" + share_plus_linux: + dependency: transitive + description: + name: share_plus_linux + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.4" + share_plus_macos: + dependency: transitive + description: + name: share_plus_macos + url: "https://pub.dartlang.org" + source: hosted + version: "2.1.0" + share_plus_platform_interface: + dependency: transitive + description: + name: share_plus_platform_interface + url: "https://pub.dartlang.org" + source: hosted + version: "2.1.0" + share_plus_web: + dependency: transitive + description: + name: share_plus_web + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.4" + share_plus_windows: + dependency: transitive + description: + name: share_plus_windows + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.3" + sky_engine: + dependency: transitive + description: flutter + source: sdk + version: "0.0.99" + source_gen: + dependency: transitive + description: + name: source_gen + url: "https://pub.dartlang.org" + source: hosted + version: "1.2.1" + source_span: + dependency: transitive + description: + name: source_span + url: "https://pub.dartlang.org" + source: hosted + version: "1.8.1" + stack_trace: + dependency: transitive + description: + name: stack_trace + url: "https://pub.dartlang.org" + source: hosted + version: "1.10.0" + stop_watch_timer: + dependency: "direct main" + description: + name: stop_watch_timer + url: "https://pub.dartlang.org" + source: hosted + version: "1.3.1" + stream_channel: + dependency: transitive + description: + name: stream_channel + url: "https://pub.dartlang.org" + source: hosted + version: "2.1.0" + string_scanner: + dependency: transitive + description: + name: string_scanner + url: "https://pub.dartlang.org" + source: hosted + version: "1.1.0" + term_glyph: + dependency: transitive + description: + name: term_glyph + url: "https://pub.dartlang.org" + source: hosted + version: "1.2.0" + test_api: + dependency: transitive + description: + name: test_api + url: "https://pub.dartlang.org" + source: hosted + version: "0.4.8" + typed_data: + dependency: transitive + description: + name: typed_data + url: "https://pub.dartlang.org" + source: hosted + version: "1.3.0" + uni_links: + dependency: "direct main" + description: + name: uni_links + url: "https://pub.dartlang.org" + source: hosted + version: "0.5.1" + uni_links_platform_interface: + dependency: transitive + description: + name: uni_links_platform_interface + url: "https://pub.dartlang.org" + source: hosted + version: "1.0.0" + uni_links_web: + dependency: transitive + description: + name: uni_links_web + url: "https://pub.dartlang.org" + source: hosted + version: "0.1.0" + url_launcher: + dependency: transitive + description: + name: url_launcher + url: "https://pub.dartlang.org" + source: hosted + version: "6.0.20" + url_launcher_android: + dependency: transitive + description: + name: url_launcher_android + url: "https://pub.dartlang.org" + source: hosted + version: "6.0.15" + url_launcher_ios: + dependency: transitive + description: + name: url_launcher_ios + url: "https://pub.dartlang.org" + source: hosted + version: "6.0.15" + url_launcher_linux: + dependency: transitive + description: + name: url_launcher_linux + url: "https://pub.dartlang.org" + source: hosted + version: "3.0.0" + url_launcher_macos: + dependency: transitive + description: + name: url_launcher_macos + url: "https://pub.dartlang.org" + source: hosted + version: "3.0.0" + url_launcher_platform_interface: + dependency: transitive + description: + name: url_launcher_platform_interface + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.5" + url_launcher_web: + dependency: transitive + description: + name: url_launcher_web + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.9" + url_launcher_windows: + dependency: transitive + description: + name: url_launcher_windows + url: "https://pub.dartlang.org" + source: hosted + version: "3.0.0" + vector_math: + dependency: transitive + description: + name: vector_math + url: "https://pub.dartlang.org" + source: hosted + version: "2.1.1" + watcher: + dependency: transitive + description: + name: watcher + url: "https://pub.dartlang.org" + source: hosted + version: "1.0.1" + web_socket_channel: + dependency: "direct main" + description: + name: web_socket_channel + url: "https://pub.dartlang.org" + source: hosted + version: "2.1.0" + webrtc_interface: + dependency: transitive + description: + name: webrtc_interface + url: "https://pub.dartlang.org" + source: hosted + version: "1.0.3" + win32: + dependency: transitive + description: + name: win32 + url: "https://pub.dartlang.org" + source: hosted + version: "2.5.1" + xdg_directories: + dependency: transitive + description: + name: xdg_directories + url: "https://pub.dartlang.org" + source: hosted + version: "0.2.0+1" + xml: + dependency: transitive + description: + name: xml + url: "https://pub.dartlang.org" + source: hosted + version: "5.3.1" + yaml: + dependency: transitive + description: + name: yaml + url: "https://pub.dartlang.org" + source: hosted + version: "3.1.0" +sdks: + dart: ">=2.16.0 <3.0.0" + flutter: ">=2.10.0" diff --git a/pubspec.lock b/pubspec.lock new file mode 100644 index 0000000..06b7627 --- /dev/null +++ b/pubspec.lock @@ -0,0 +1,714 @@ +# Generated by pub +# See https://dart.dev/tools/pub/glossary#lockfile +packages: + _fe_analyzer_shared: + dependency: transitive + description: + name: _fe_analyzer_shared + url: "https://pub.dartlang.org" + source: hosted + version: "31.0.0" + analyzer: + dependency: transitive + description: + name: analyzer + url: "https://pub.dartlang.org" + source: hosted + version: "2.8.0" + args: + dependency: transitive + description: + name: args + url: "https://pub.dartlang.org" + source: hosted + version: "2.3.0" + async: + dependency: transitive + description: + name: async + url: "https://pub.dartlang.org" + source: hosted + version: "2.8.2" + boolean_selector: + dependency: transitive + description: + name: boolean_selector + url: "https://pub.dartlang.org" + source: hosted + version: "2.1.0" + build: + dependency: transitive + description: + name: build + url: "https://pub.dartlang.org" + source: hosted + version: "2.3.0" + build_config: + dependency: transitive + description: + name: build_config + url: "https://pub.dartlang.org" + source: hosted + version: "1.0.0" + build_daemon: + dependency: transitive + description: + name: build_daemon + url: "https://pub.dartlang.org" + source: hosted + version: "3.1.0" + build_resolvers: + dependency: transitive + description: + name: build_resolvers + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.6" + build_runner: + dependency: "direct dev" + description: + name: build_runner + url: "https://pub.dartlang.org" + source: hosted + version: "2.1.10" + build_runner_core: + dependency: transitive + description: + name: build_runner_core + url: "https://pub.dartlang.org" + source: hosted + version: "7.2.3" + built_collection: + dependency: transitive + description: + name: built_collection + url: "https://pub.dartlang.org" + source: hosted + version: "5.1.1" + built_value: + dependency: transitive + description: + name: built_value + url: "https://pub.dartlang.org" + source: hosted + version: "8.2.3" + characters: + dependency: transitive + description: + name: characters + url: "https://pub.dartlang.org" + source: hosted + version: "1.2.0" + charcode: + dependency: transitive + description: + name: charcode + url: "https://pub.dartlang.org" + source: hosted + version: "1.3.1" + checked_yaml: + dependency: transitive + description: + name: checked_yaml + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.1" + cli_util: + dependency: transitive + description: + name: cli_util + url: "https://pub.dartlang.org" + source: hosted + version: "0.3.5" + clock: + dependency: transitive + description: + name: clock + url: "https://pub.dartlang.org" + source: hosted + version: "1.1.0" + code_builder: + dependency: transitive + description: + name: code_builder + url: "https://pub.dartlang.org" + source: hosted + version: "4.1.0" + collection: + dependency: transitive + description: + name: collection + url: "https://pub.dartlang.org" + source: hosted + version: "1.15.0" + convert: + dependency: transitive + description: + name: convert + url: "https://pub.dartlang.org" + source: hosted + version: "3.0.1" + coverage: + dependency: transitive + description: + name: coverage + url: "https://pub.dartlang.org" + source: hosted + version: "1.0.3" + crypto: + dependency: transitive + description: + name: crypto + url: "https://pub.dartlang.org" + source: hosted + version: "3.0.2" + csslib: + dependency: transitive + description: + name: csslib + url: "https://pub.dartlang.org" + source: hosted + version: "0.17.1" + dart_style: + dependency: transitive + description: + name: dart_style + url: "https://pub.dartlang.org" + source: hosted + version: "2.2.1" + dart_webrtc: + dependency: transitive + description: + name: dart_webrtc + url: "https://pub.dartlang.org" + source: hosted + version: "1.0.5" + dartdoc: + dependency: "direct dev" + description: + name: dartdoc + url: "https://pub.dartlang.org" + source: hosted + version: "4.1.0" + dotenv: + dependency: "direct main" + description: + name: dotenv + url: "https://pub.dartlang.org" + source: hosted + version: "4.0.1" + eventify: + dependency: "direct main" + description: + name: eventify + url: "https://pub.dartlang.org" + source: hosted + version: "1.0.0" + fake_async: + dependency: transitive + description: + name: fake_async + url: "https://pub.dartlang.org" + source: hosted + version: "1.2.0" + ffi: + dependency: transitive + description: + name: ffi + url: "https://pub.dartlang.org" + source: hosted + version: "1.1.2" + file: + dependency: transitive + description: + name: file + url: "https://pub.dartlang.org" + source: hosted + version: "6.1.2" + fixnum: + dependency: transitive + description: + name: fixnum + url: "https://pub.dartlang.org" + source: hosted + version: "1.0.0" + flutter: + dependency: "direct main" + description: flutter + source: sdk + version: "0.0.0" + flutter_lints: + dependency: "direct dev" + description: + name: flutter_lints + url: "https://pub.dartlang.org" + source: hosted + version: "1.0.4" + flutter_test: + dependency: "direct dev" + description: flutter + source: sdk + version: "0.0.0" + flutter_webrtc: + dependency: "direct main" + description: + name: flutter_webrtc + url: "https://pub.dartlang.org" + source: hosted + version: "0.8.5" + frontend_server_client: + dependency: transitive + description: + name: frontend_server_client + url: "https://pub.dartlang.org" + source: hosted + version: "2.1.2" + glob: + dependency: transitive + description: + name: glob + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.2" + graphs: + dependency: transitive + description: + name: graphs + url: "https://pub.dartlang.org" + source: hosted + version: "2.1.0" + html: + dependency: transitive + description: + name: html + url: "https://pub.dartlang.org" + source: hosted + version: "0.15.0" + http: + dependency: "direct main" + description: + name: http + url: "https://pub.dartlang.org" + source: hosted + version: "0.13.4" + http_multi_server: + dependency: transitive + description: + name: http_multi_server + url: "https://pub.dartlang.org" + source: hosted + version: "3.2.0" + http_parser: + dependency: transitive + description: + name: http_parser + url: "https://pub.dartlang.org" + source: hosted + version: "4.0.0" + io: + dependency: transitive + description: + name: io + url: "https://pub.dartlang.org" + source: hosted + version: "1.0.3" + js: + dependency: transitive + description: + name: js + url: "https://pub.dartlang.org" + source: hosted + version: "0.6.4" + json_annotation: + dependency: transitive + description: + name: json_annotation + url: "https://pub.dartlang.org" + source: hosted + version: "4.5.0" + jwt_decode: + dependency: "direct main" + description: + name: jwt_decode + url: "https://pub.dartlang.org" + source: hosted + version: "0.3.1" + lints: + dependency: transitive + description: + name: lints + url: "https://pub.dartlang.org" + source: hosted + version: "1.0.1" + logger: + dependency: "direct main" + description: + name: logger + url: "https://pub.dartlang.org" + source: hosted + version: "1.1.0" + logging: + dependency: transitive + description: + name: logging + url: "https://pub.dartlang.org" + source: hosted + version: "1.0.2" + markdown: + dependency: transitive + description: + name: markdown + url: "https://pub.dartlang.org" + source: hosted + version: "4.0.1" + matcher: + dependency: transitive + description: + name: matcher + url: "https://pub.dartlang.org" + source: hosted + version: "0.12.11" + material_color_utilities: + dependency: transitive + description: + name: material_color_utilities + url: "https://pub.dartlang.org" + source: hosted + version: "0.1.3" + meta: + dependency: transitive + description: + name: meta + url: "https://pub.dartlang.org" + source: hosted + version: "1.7.0" + mime: + dependency: transitive + description: + name: mime + url: "https://pub.dartlang.org" + source: hosted + version: "1.0.2" + mockito: + dependency: "direct main" + description: + name: mockito + url: "https://pub.dartlang.org" + source: hosted + version: "5.1.0" + node_preamble: + dependency: transitive + description: + name: node_preamble + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.1" + package_config: + dependency: transitive + description: + name: package_config + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.2" + path: + dependency: transitive + description: + name: path + url: "https://pub.dartlang.org" + source: hosted + version: "1.8.0" + path_provider: + dependency: transitive + description: + name: path_provider + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.9" + path_provider_android: + dependency: transitive + description: + name: path_provider_android + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.13" + path_provider_ios: + dependency: transitive + description: + name: path_provider_ios + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.8" + path_provider_linux: + dependency: transitive + description: + name: path_provider_linux + url: "https://pub.dartlang.org" + source: hosted + version: "2.1.5" + path_provider_macos: + dependency: transitive + description: + name: path_provider_macos + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.5" + path_provider_platform_interface: + dependency: transitive + description: + name: path_provider_platform_interface + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.3" + path_provider_windows: + dependency: transitive + description: + name: path_provider_windows + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.5" + platform: + dependency: transitive + description: + name: platform + url: "https://pub.dartlang.org" + source: hosted + version: "3.1.0" + plugin_platform_interface: + dependency: transitive + description: + name: plugin_platform_interface + url: "https://pub.dartlang.org" + source: hosted + version: "2.1.2" + pool: + dependency: transitive + description: + name: pool + url: "https://pub.dartlang.org" + source: hosted + version: "1.5.0" + process: + dependency: transitive + description: + name: process + url: "https://pub.dartlang.org" + source: hosted + version: "4.2.4" + pub_semver: + dependency: transitive + description: + name: pub_semver + url: "https://pub.dartlang.org" + source: hosted + version: "2.1.1" + pubspec_parse: + dependency: transitive + description: + name: pubspec_parse + url: "https://pub.dartlang.org" + source: hosted + version: "1.2.0" + sdp_transform: + dependency: "direct main" + description: + name: sdp_transform + url: "https://pub.dartlang.org" + source: hosted + version: "0.3.2" + shelf: + dependency: transitive + description: + name: shelf + url: "https://pub.dartlang.org" + source: hosted + version: "1.3.0" + shelf_packages_handler: + dependency: transitive + description: + name: shelf_packages_handler + url: "https://pub.dartlang.org" + source: hosted + version: "3.0.0" + shelf_static: + dependency: transitive + description: + name: shelf_static + url: "https://pub.dartlang.org" + source: hosted + version: "1.1.0" + shelf_web_socket: + dependency: transitive + description: + name: shelf_web_socket + url: "https://pub.dartlang.org" + source: hosted + version: "1.0.1" + sky_engine: + dependency: transitive + description: flutter + source: sdk + version: "0.0.99" + source_gen: + dependency: transitive + description: + name: source_gen + url: "https://pub.dartlang.org" + source: hosted + version: "1.2.2" + source_map_stack_trace: + dependency: transitive + description: + name: source_map_stack_trace + url: "https://pub.dartlang.org" + source: hosted + version: "2.1.0" + source_maps: + dependency: transitive + description: + name: source_maps + url: "https://pub.dartlang.org" + source: hosted + version: "0.10.10" + source_span: + dependency: transitive + description: + name: source_span + url: "https://pub.dartlang.org" + source: hosted + version: "1.8.1" + stack_trace: + dependency: transitive + description: + name: stack_trace + url: "https://pub.dartlang.org" + source: hosted + version: "1.10.0" + stream_channel: + dependency: transitive + description: + name: stream_channel + url: "https://pub.dartlang.org" + source: hosted + version: "2.1.0" + stream_transform: + dependency: transitive + description: + name: stream_transform + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.0" + string_scanner: + dependency: transitive + description: + name: string_scanner + url: "https://pub.dartlang.org" + source: hosted + version: "1.1.0" + term_glyph: + dependency: transitive + description: + name: term_glyph + url: "https://pub.dartlang.org" + source: hosted + version: "1.2.0" + test: + dependency: "direct dev" + description: + name: test + url: "https://pub.dartlang.org" + source: hosted + version: "1.19.5" + test_api: + dependency: transitive + description: + name: test_api + url: "https://pub.dartlang.org" + source: hosted + version: "0.4.8" + test_core: + dependency: transitive + description: + name: test_core + url: "https://pub.dartlang.org" + source: hosted + version: "0.4.9" + timing: + dependency: transitive + description: + name: timing + url: "https://pub.dartlang.org" + source: hosted + version: "1.0.0" + typed_data: + dependency: transitive + description: + name: typed_data + url: "https://pub.dartlang.org" + source: hosted + version: "1.3.0" + vector_math: + dependency: transitive + description: + name: vector_math + url: "https://pub.dartlang.org" + source: hosted + version: "2.1.1" + vm_service: + dependency: transitive + description: + name: vm_service + url: "https://pub.dartlang.org" + source: hosted + version: "7.5.0" + watcher: + dependency: transitive + description: + name: watcher + url: "https://pub.dartlang.org" + source: hosted + version: "1.0.1" + web_socket_channel: + dependency: "direct main" + description: + name: web_socket_channel + url: "https://pub.dartlang.org" + source: hosted + version: "2.2.0" + webkit_inspection_protocol: + dependency: transitive + description: + name: webkit_inspection_protocol + url: "https://pub.dartlang.org" + source: hosted + version: "1.0.0" + webrtc_interface: + dependency: transitive + description: + name: webrtc_interface + url: "https://pub.dartlang.org" + source: hosted + version: "1.0.3" + win32: + dependency: transitive + description: + name: win32 + url: "https://pub.dartlang.org" + source: hosted + version: "2.5.2" + xdg_directories: + dependency: transitive + description: + name: xdg_directories + url: "https://pub.dartlang.org" + source: hosted + version: "0.2.0+1" + yaml: + dependency: transitive + description: + name: yaml + url: "https://pub.dartlang.org" + source: hosted + version: "3.1.0" +sdks: + dart: ">=2.16.0 <3.0.0" + flutter: ">=2.8.1"