➕ Add livekit
This commit is contained in:
parent
ed32a31819
commit
66f41179ba
@ -12,7 +12,7 @@ plugins {
|
|||||||
android {
|
android {
|
||||||
namespace = "dev.solsynth.solian"
|
namespace = "dev.solsynth.solian"
|
||||||
compileSdk = flutter.compileSdkVersion
|
compileSdk = flutter.compileSdkVersion
|
||||||
ndkVersion = flutter.ndkVersion
|
ndkVersion = "27.0.12077973"
|
||||||
|
|
||||||
compileOptions {
|
compileOptions {
|
||||||
sourceCompatibility JavaVersion.VERSION_17
|
sourceCompatibility JavaVersion.VERSION_17
|
||||||
|
@ -2,4 +2,4 @@ distributionBase=GRADLE_USER_HOME
|
|||||||
distributionPath=wrapper/dists
|
distributionPath=wrapper/dists
|
||||||
zipStoreBase=GRADLE_USER_HOME
|
zipStoreBase=GRADLE_USER_HOME
|
||||||
zipStorePath=wrapper/dists
|
zipStorePath=wrapper/dists
|
||||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.3-all.zip
|
distributionUrl=https\://services.gradle.org/distributions/gradle-8.9-all.zip
|
||||||
|
@ -18,7 +18,7 @@ pluginManagement {
|
|||||||
|
|
||||||
plugins {
|
plugins {
|
||||||
id "dev.flutter.flutter-plugin-loader" version "1.0.0"
|
id "dev.flutter.flutter-plugin-loader" version "1.0.0"
|
||||||
id "com.android.application" version "8.1.0" apply false
|
id "com.android.application" version '8.7.2' apply false
|
||||||
// START: FlutterFire Configuration
|
// START: FlutterFire Configuration
|
||||||
id "com.google.gms.google-services" version "4.3.15" apply false
|
id "com.google.gms.google-services" version "4.3.15" apply false
|
||||||
id "com.google.firebase.crashlytics" version "2.8.1" apply false
|
id "com.google.firebase.crashlytics" version "2.8.1" apply false
|
||||||
|
@ -1,12 +0,0 @@
|
|||||||
import 'dart:io';
|
|
||||||
|
|
||||||
import 'package:dio/dio.dart';
|
|
||||||
import 'package:native_dio_adapter/native_dio_adapter.dart';
|
|
||||||
|
|
||||||
Dio addClientAdapter(Dio client) {
|
|
||||||
if (Platform.isAndroid || Platform.isIOS || Platform.isMacOS) {
|
|
||||||
// Switch to native implementation if possible
|
|
||||||
client.httpClientAdapter = NativeAdapter();
|
|
||||||
}
|
|
||||||
return client;
|
|
||||||
}
|
|
@ -1,2 +0,0 @@
|
|||||||
export 'package:surface/providers/adapters/sn_network_web.dart'
|
|
||||||
if (dart.library.io) 'package:surface/providers/adapters/sn_network_native.dart';
|
|
@ -1,5 +0,0 @@
|
|||||||
import 'package:dio/dio.dart';
|
|
||||||
|
|
||||||
Dio addClientAdapter(Dio client) {
|
|
||||||
return client;
|
|
||||||
}
|
|
@ -5,7 +5,6 @@ import 'dart:developer';
|
|||||||
import 'package:dio/dio.dart';
|
import 'package:dio/dio.dart';
|
||||||
import 'package:dio_smart_retry/dio_smart_retry.dart';
|
import 'package:dio_smart_retry/dio_smart_retry.dart';
|
||||||
import 'package:shared_preferences/shared_preferences.dart';
|
import 'package:shared_preferences/shared_preferences.dart';
|
||||||
import 'package:surface/providers/adapters/sn_network_universal.dart';
|
|
||||||
import 'package:synchronized/synchronized.dart';
|
import 'package:synchronized/synchronized.dart';
|
||||||
|
|
||||||
const kAtkStoreKey = 'nex_user_atk';
|
const kAtkStoreKey = 'nex_user_atk';
|
||||||
@ -21,7 +20,7 @@ const kNetworkServerDirectory = [
|
|||||||
];
|
];
|
||||||
|
|
||||||
class SnNetworkProvider {
|
class SnNetworkProvider {
|
||||||
late Dio client;
|
late final Dio client;
|
||||||
|
|
||||||
late final SharedPreferences _prefs;
|
late final SharedPreferences _prefs;
|
||||||
|
|
||||||
@ -53,8 +52,6 @@ class SnNetworkProvider {
|
|||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
client = addClientAdapter(client);
|
|
||||||
|
|
||||||
SharedPreferences.getInstance().then((prefs) {
|
SharedPreferences.getInstance().then((prefs) {
|
||||||
_prefs = prefs;
|
_prefs = prefs;
|
||||||
client.options.baseUrl =
|
client.options.baseUrl =
|
||||||
|
@ -14,114 +14,7 @@ class CallRoomScreen extends StatefulWidget {
|
|||||||
State<CallRoomScreen> createState() => _CallRoomScreenState();
|
State<CallRoomScreen> createState() => _CallRoomScreenState();
|
||||||
}
|
}
|
||||||
|
|
||||||
const _kLocalWebRtcBaseUrl = 'http://localhost:8001';
|
|
||||||
|
|
||||||
class _CallRoomScreenState extends State<CallRoomScreen> {
|
class _CallRoomScreenState extends State<CallRoomScreen> {
|
||||||
RTCPeerConnection? _peerConnection;
|
|
||||||
MediaStream? _localStream;
|
|
||||||
WebSocketChannel? _wsChannel;
|
|
||||||
|
|
||||||
@override
|
|
||||||
void initState() {
|
|
||||||
super.initState();
|
|
||||||
_initWebRtc();
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<void> _initWebRtc() async {
|
|
||||||
final client = Dio();
|
|
||||||
client.options.baseUrl = _kLocalWebRtcBaseUrl;
|
|
||||||
|
|
||||||
final configResp = await client.get('/.well-known/webrtc');
|
|
||||||
|
|
||||||
// Get user media (audio only)
|
|
||||||
_localStream = await navigator.mediaDevices.getUserMedia({
|
|
||||||
'audio': true,
|
|
||||||
'video': false,
|
|
||||||
});
|
|
||||||
|
|
||||||
// Configure Peer Connection
|
|
||||||
Map<String, dynamic> config = {
|
|
||||||
'iceServers': configResp.data['ice_servers']
|
|
||||||
};
|
|
||||||
|
|
||||||
_peerConnection = await createPeerConnection(config);
|
|
||||||
|
|
||||||
// Add local stream to peer connection
|
|
||||||
_peerConnection?.addStream(_localStream!);
|
|
||||||
|
|
||||||
// Listen for ICE candidates
|
|
||||||
_peerConnection?.onIceCandidate = (RTCIceCandidate candidate) {
|
|
||||||
print('New ICE candidate: ${candidate.candidate}');
|
|
||||||
// Send the candidate to the signaling server
|
|
||||||
};
|
|
||||||
|
|
||||||
// Handle remote stream
|
|
||||||
_peerConnection?.onAddStream = (MediaStream stream) {
|
|
||||||
print('Remote stream added');
|
|
||||||
// Play the remote stream
|
|
||||||
};
|
|
||||||
|
|
||||||
_wsChannel = WebSocketChannel.connect(
|
|
||||||
Uri.parse('$_kLocalWebRtcBaseUrl/webrtc'),
|
|
||||||
);
|
|
||||||
await _wsChannel!.ready;
|
|
||||||
|
|
||||||
_wsChannel!.stream.listen((event) {
|
|
||||||
final Map<String, dynamic> data = jsonDecode(event);
|
|
||||||
|
|
||||||
switch (data['type']) {
|
|
||||||
case 'offer':
|
|
||||||
_handleOffer(data);
|
|
||||||
break;
|
|
||||||
case 'answer':
|
|
||||||
_handleAnswer(data);
|
|
||||||
break;
|
|
||||||
case 'candidate':
|
|
||||||
_handleCandidate(data);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<void> _handleOffer(Map<String, dynamic> data) async {
|
|
||||||
// Set remote description
|
|
||||||
final offer = RTCSessionDescription(data['sdp'], data['type']);
|
|
||||||
await _peerConnection?.setRemoteDescription(offer);
|
|
||||||
|
|
||||||
// Create and send answer
|
|
||||||
final answer = await _peerConnection?.createAnswer();
|
|
||||||
await _peerConnection?.setLocalDescription(answer!);
|
|
||||||
|
|
||||||
_wsChannel?.sink.add({
|
|
||||||
'type': 'answer',
|
|
||||||
'sdp': answer?.sdp,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<void> _handleAnswer(Map<String, dynamic> data) async {
|
|
||||||
// Set remote description
|
|
||||||
final answer = RTCSessionDescription(data['sdp'], data['type']);
|
|
||||||
await _peerConnection?.setRemoteDescription(answer);
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<void> _handleCandidate(Map<String, dynamic> data) async {
|
|
||||||
// Add ICE candidate
|
|
||||||
final candidate = RTCIceCandidate(
|
|
||||||
data['candidate'],
|
|
||||||
data['sdpMid'],
|
|
||||||
data['sdpMLineIndex'],
|
|
||||||
);
|
|
||||||
await _peerConnection?.addCandidate(candidate);
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
void dispose() {
|
|
||||||
_wsChannel?.sink.close();
|
|
||||||
_localStream?.dispose();
|
|
||||||
_peerConnection?.close();
|
|
||||||
super.dispose();
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
|
@ -6,12 +6,14 @@ import FlutterMacOS
|
|||||||
import Foundation
|
import Foundation
|
||||||
|
|
||||||
import connectivity_plus
|
import connectivity_plus
|
||||||
|
import device_info_plus
|
||||||
import file_selector_macos
|
import file_selector_macos
|
||||||
import firebase_analytics
|
import firebase_analytics
|
||||||
import firebase_core
|
import firebase_core
|
||||||
import firebase_messaging
|
import firebase_messaging
|
||||||
import flutter_udid
|
import flutter_udid
|
||||||
import flutter_webrtc
|
import flutter_webrtc
|
||||||
|
import livekit_client
|
||||||
import media_kit_libs_macos_video
|
import media_kit_libs_macos_video
|
||||||
import media_kit_video
|
import media_kit_video
|
||||||
import package_info_plus
|
import package_info_plus
|
||||||
@ -26,12 +28,14 @@ import wakelock_plus
|
|||||||
|
|
||||||
func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
|
func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
|
||||||
ConnectivityPlusPlugin.register(with: registry.registrar(forPlugin: "ConnectivityPlusPlugin"))
|
ConnectivityPlusPlugin.register(with: registry.registrar(forPlugin: "ConnectivityPlusPlugin"))
|
||||||
|
DeviceInfoPlusMacosPlugin.register(with: registry.registrar(forPlugin: "DeviceInfoPlusMacosPlugin"))
|
||||||
FileSelectorPlugin.register(with: registry.registrar(forPlugin: "FileSelectorPlugin"))
|
FileSelectorPlugin.register(with: registry.registrar(forPlugin: "FileSelectorPlugin"))
|
||||||
FLTFirebaseAnalyticsPlugin.register(with: registry.registrar(forPlugin: "FLTFirebaseAnalyticsPlugin"))
|
FLTFirebaseAnalyticsPlugin.register(with: registry.registrar(forPlugin: "FLTFirebaseAnalyticsPlugin"))
|
||||||
FLTFirebaseCorePlugin.register(with: registry.registrar(forPlugin: "FLTFirebaseCorePlugin"))
|
FLTFirebaseCorePlugin.register(with: registry.registrar(forPlugin: "FLTFirebaseCorePlugin"))
|
||||||
FLTFirebaseMessagingPlugin.register(with: registry.registrar(forPlugin: "FLTFirebaseMessagingPlugin"))
|
FLTFirebaseMessagingPlugin.register(with: registry.registrar(forPlugin: "FLTFirebaseMessagingPlugin"))
|
||||||
FlutterUdidPlugin.register(with: registry.registrar(forPlugin: "FlutterUdidPlugin"))
|
FlutterUdidPlugin.register(with: registry.registrar(forPlugin: "FlutterUdidPlugin"))
|
||||||
FlutterWebRTCPlugin.register(with: registry.registrar(forPlugin: "FlutterWebRTCPlugin"))
|
FlutterWebRTCPlugin.register(with: registry.registrar(forPlugin: "FlutterWebRTCPlugin"))
|
||||||
|
LiveKitPlugin.register(with: registry.registrar(forPlugin: "LiveKitPlugin"))
|
||||||
MediaKitLibsMacosVideoPlugin.register(with: registry.registrar(forPlugin: "MediaKitLibsMacosVideoPlugin"))
|
MediaKitLibsMacosVideoPlugin.register(with: registry.registrar(forPlugin: "MediaKitLibsMacosVideoPlugin"))
|
||||||
MediaKitVideoPlugin.register(with: registry.registrar(forPlugin: "MediaKitVideoPlugin"))
|
MediaKitVideoPlugin.register(with: registry.registrar(forPlugin: "MediaKitVideoPlugin"))
|
||||||
FPPPackageInfoPlusPlugin.register(with: registry.registrar(forPlugin: "FPPPackageInfoPlusPlugin"))
|
FPPPackageInfoPlusPlugin.register(with: registry.registrar(forPlugin: "FPPPackageInfoPlusPlugin"))
|
||||||
|
50
pubspec.lock
50
pubspec.lock
@ -326,6 +326,22 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.7.10"
|
version: "0.7.10"
|
||||||
|
device_info_plus:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: device_info_plus
|
||||||
|
sha256: f545ffbadee826f26f2e1a0f0cbd667ae9a6011cc0f77c0f8f00a969655e6e95
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "11.1.1"
|
||||||
|
device_info_plus_platform_interface:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: device_info_plus_platform_interface
|
||||||
|
sha256: "282d3cf731045a2feb66abfe61bbc40870ae50a3ed10a4d3d217556c35c8c2ba"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "7.0.1"
|
||||||
dio:
|
dio:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
@ -643,7 +659,7 @@ packages:
|
|||||||
source: sdk
|
source: sdk
|
||||||
version: "0.0.0"
|
version: "0.0.0"
|
||||||
flutter_webrtc:
|
flutter_webrtc:
|
||||||
dependency: "direct main"
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: flutter_webrtc
|
name: flutter_webrtc
|
||||||
sha256: "0b69ecab98211504c10d40c1c4cb48eb387e03ea8e732079bd0d2665d8c20d3f"
|
sha256: "0b69ecab98211504c10d40c1c4cb48eb387e03ea8e732079bd0d2665d8c20d3f"
|
||||||
@ -946,6 +962,14 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "5.0.0"
|
version: "5.0.0"
|
||||||
|
livekit_client:
|
||||||
|
dependency: "direct main"
|
||||||
|
description:
|
||||||
|
name: livekit_client
|
||||||
|
sha256: ad55045435fbf1a106e2da4c9a8d523755ce834db47f6d967beaa58228b21a05
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "2.3.0"
|
||||||
logging:
|
logging:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -1250,6 +1274,14 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.5.1"
|
version: "1.5.1"
|
||||||
|
protobuf:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: protobuf
|
||||||
|
sha256: "68645b24e0716782e58948f8467fd42a880f255096a821f9e7d0ec625b00c84d"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "3.1.0"
|
||||||
provider:
|
provider:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
@ -1354,6 +1386,14 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.1.3"
|
version: "0.1.3"
|
||||||
|
sdp_transform:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: sdp_transform
|
||||||
|
sha256: "73e412a5279a5c2de74001535208e20fff88f225c9a4571af0f7146202755e45"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "0.3.2"
|
||||||
sentry:
|
sentry:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -1815,6 +1855,14 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "5.8.0"
|
version: "5.8.0"
|
||||||
|
win32_registry:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: win32_registry
|
||||||
|
sha256: "21ec76dfc731550fd3e2ce7a33a9ea90b828fdf19a5c3bcf556fa992cfa99852"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "1.1.5"
|
||||||
xdg_directories:
|
xdg_directories:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
@ -88,7 +88,7 @@ dependencies:
|
|||||||
pasteboard: ^0.3.0
|
pasteboard: ^0.3.0
|
||||||
sentry_flutter: ^8.10.1
|
sentry_flutter: ^8.10.1
|
||||||
synchronized: ^3.3.0+3
|
synchronized: ^3.3.0+3
|
||||||
flutter_webrtc: ^0.12.1+hotfix.1
|
livekit_client: ^2.3.0
|
||||||
|
|
||||||
dev_dependencies:
|
dev_dependencies:
|
||||||
flutter_test:
|
flutter_test:
|
||||||
|
@ -11,6 +11,7 @@
|
|||||||
#include <firebase_core/firebase_core_plugin_c_api.h>
|
#include <firebase_core/firebase_core_plugin_c_api.h>
|
||||||
#include <flutter_udid/flutter_udid_plugin_c_api.h>
|
#include <flutter_udid/flutter_udid_plugin_c_api.h>
|
||||||
#include <flutter_webrtc/flutter_web_r_t_c_plugin.h>
|
#include <flutter_webrtc/flutter_web_r_t_c_plugin.h>
|
||||||
|
#include <livekit_client/live_kit_plugin.h>
|
||||||
#include <media_kit_libs_windows_video/media_kit_libs_windows_video_plugin_c_api.h>
|
#include <media_kit_libs_windows_video/media_kit_libs_windows_video_plugin_c_api.h>
|
||||||
#include <media_kit_video/media_kit_video_plugin_c_api.h>
|
#include <media_kit_video/media_kit_video_plugin_c_api.h>
|
||||||
#include <pasteboard/pasteboard_plugin.h>
|
#include <pasteboard/pasteboard_plugin.h>
|
||||||
@ -29,6 +30,8 @@ void RegisterPlugins(flutter::PluginRegistry* registry) {
|
|||||||
registry->GetRegistrarForPlugin("FlutterUdidPluginCApi"));
|
registry->GetRegistrarForPlugin("FlutterUdidPluginCApi"));
|
||||||
FlutterWebRTCPluginRegisterWithRegistrar(
|
FlutterWebRTCPluginRegisterWithRegistrar(
|
||||||
registry->GetRegistrarForPlugin("FlutterWebRTCPlugin"));
|
registry->GetRegistrarForPlugin("FlutterWebRTCPlugin"));
|
||||||
|
LiveKitPluginRegisterWithRegistrar(
|
||||||
|
registry->GetRegistrarForPlugin("LiveKitPlugin"));
|
||||||
MediaKitLibsWindowsVideoPluginCApiRegisterWithRegistrar(
|
MediaKitLibsWindowsVideoPluginCApiRegisterWithRegistrar(
|
||||||
registry->GetRegistrarForPlugin("MediaKitLibsWindowsVideoPluginCApi"));
|
registry->GetRegistrarForPlugin("MediaKitLibsWindowsVideoPluginCApi"));
|
||||||
MediaKitVideoPluginCApiRegisterWithRegistrar(
|
MediaKitVideoPluginCApiRegisterWithRegistrar(
|
||||||
|
@ -8,6 +8,7 @@ list(APPEND FLUTTER_PLUGIN_LIST
|
|||||||
firebase_core
|
firebase_core
|
||||||
flutter_udid
|
flutter_udid
|
||||||
flutter_webrtc
|
flutter_webrtc
|
||||||
|
livekit_client
|
||||||
media_kit_libs_windows_video
|
media_kit_libs_windows_video
|
||||||
media_kit_video
|
media_kit_video
|
||||||
pasteboard
|
pasteboard
|
||||||
|
Loading…
Reference in New Issue
Block a user