Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .version
Original file line number Diff line number Diff line change
@@ -1 +1 @@
2.5.2
2.5.3
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
# CHANGELOG

## 2.5.3

feat: Data Packet Cryptor (#873)
feat: Add E2EE support for H265 (#864)
fix: fix async call for update participant info (#897)

## 2.5.2

* Fix missing properties for TextStreamInfo (#881)
Expand Down
2 changes: 1 addition & 1 deletion ios/livekit_client.podspec
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
Pod::Spec.new do |s|
s.name = 'livekit_client'
s.version = '2.5.2'
s.version = '2.5.3'
s.summary = 'Open source platform for real-time audio and video.'
s.description = 'Open source platform for real-time audio and video.'
s.homepage = 'https://livekit.io/'
Expand Down
2 changes: 1 addition & 1 deletion lib/src/livekit.dart
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ import 'support/platform.dart' show lkPlatformIsMobile;
/// Main entry point to connect to a room.
/// {@category Room}
class LiveKitClient {
static const version = '2.5.2';
static const version = '2.5.3';

/// Initialize the WebRTC plugin. If this is not manually called, will be
/// initialized with default settings.
Expand Down
3 changes: 1 addition & 2 deletions lib/src/participant/local.dart
Original file line number Diff line number Diff line change
Expand Up @@ -53,9 +53,8 @@ import '../types/other.dart';
import '../types/participant_permissions.dart';
import '../types/rpc.dart';
import '../types/video_dimensions.dart';
import 'participant.dart';

import '../utils.dart' show buildStreamId, mimeTypeToVideoCodecString, Utils, compareVersions, isSVCCodec;
import 'participant.dart';

/// Represents the current participant in the room. Instance of [LocalParticipant] is automatically
/// created after successfully connecting to a [Room] and will be accessible from [Room.localParticipant].
Expand Down
3 changes: 1 addition & 2 deletions lib/src/publication/track_publication.dart
Original file line number Diff line number Diff line change
Expand Up @@ -119,8 +119,7 @@ abstract class TrackPublication<T extends Track> extends Disposable {
void _attachTrackListener(T track) {
// listen for Track's muted events
final listener = track.createListener()
..on<InternalTrackMuteUpdatedEvent>(
(event) => _onTrackMuteUpdatedEvent(event));
..on<InternalTrackMuteUpdatedEvent>((event) => _onTrackMuteUpdatedEvent(event));
// dispose listener when the track is disposed
track.onDispose(() => listener.dispose());
}
Expand Down
3 changes: 1 addition & 2 deletions lib/src/track/local/audio.dart
Original file line number Diff line number Diff line change
Expand Up @@ -62,8 +62,7 @@ class LocalAudioTrack extends LocalTrack with AudioTrack, LocalAudioManagementMi
if (stats != null && prevStats != null && sender != null) {
final bitrate = computeBitrateForSenderStats(stats, prevStats);
_currentBitrate = bitrate;
events
.emit(AudioSenderStatsEvent(stats: stats, currentBitrate: bitrate));
events.emit(AudioSenderStatsEvent(stats: stats, currentBitrate: bitrate));
}

prevStats = stats;
Expand Down
3 changes: 1 addition & 2 deletions lib/src/track/remote/audio.dart
Original file line number Diff line number Diff line change
Expand Up @@ -89,8 +89,7 @@ class RemoteAudioTrack extends RemoteTrack with AudioTrack, RemoteAudioManagemen
if (stats != null && prevStats != null && receiver != null) {
final bitrate = computeBitrateForReceiverStats(stats, prevStats);
_currentBitrate = bitrate;
events.emit(
AudioReceiverStatsEvent(stats: stats, currentBitrate: bitrate));
events.emit(AudioReceiverStatsEvent(stats: stats, currentBitrate: bitrate));
}

prevStats = stats;
Expand Down
3 changes: 1 addition & 2 deletions lib/src/track/remote/video.dart
Original file line number Diff line number Diff line change
Expand Up @@ -55,8 +55,7 @@ class RemoteVideoTrack extends RemoteTrack with VideoTrack {
if (stats != null && prevStats != null && receiver != null) {
final bitrate = computeBitrateForReceiverStats(stats, prevStats);
_currentBitrate = bitrate;
events.emit(
VideoReceiverStatsEvent(stats: stats, currentBitrate: bitrate));
events.emit(VideoReceiverStatsEvent(stats: stats, currentBitrate: bitrate));
}

prevStats = stats;
Expand Down
3 changes: 1 addition & 2 deletions lib/src/widgets/screen_select_dialog.dart
Original file line number Diff line number Diff line change
Expand Up @@ -138,8 +138,7 @@ class ScreenSelectDialog extends Dialog {

Future<void> _getSources() async {
try {
final sources =
await rtc.desktopCapturer.getSources(types: [_sourceType]);
final sources = await rtc.desktopCapturer.getSources(types: [_sourceType]);
for (var element in sources) {
if (kDebugMode) {
print('name: ${element.name}, id: ${element.id}, type: ${element.type}');
Expand Down
2 changes: 1 addition & 1 deletion macos/livekit_client.podspec
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
Pod::Spec.new do |s|
s.name = 'livekit_client'
s.version = '2.5.2'
s.version = '2.5.3'
s.summary = 'Open source platform for real-time audio and video.'
s.description = 'Open source platform for real-time audio and video.'
s.homepage = 'https://livekit.io/'
Expand Down
2 changes: 1 addition & 1 deletion pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
name: livekit_client
description: Flutter Client SDK for LiveKit.
Build real-time video and audio into your apps. Supports iOS, Android, and Web.
version: 2.5.2
version: 2.5.3
homepage: https://github.com/livekit/client-sdk-flutter

environment:
Expand Down
92 changes: 32 additions & 60 deletions test/core/data_stream_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -42,11 +42,9 @@ void main() {

group('Stream Handler Registration', () {
test('Register And Unregister Text And Byte Stream Handlers', () async {
room.registerTextStreamHandler(
'chat', (TextStreamReader reader, String participantIdentity) {});
room.registerTextStreamHandler('chat', (TextStreamReader reader, String participantIdentity) {});

room.registerByteStreamHandler(
'file', (ByteStreamReader reader, String participantIdentity) {});
room.registerByteStreamHandler('file', (ByteStreamReader reader, String participantIdentity) {});

expect(room.textStreamHandlers.keys.first, 'chat');

Expand All @@ -62,8 +60,7 @@ void main() {

group('Text Streaming', () {
test('Send Basic Text Message', () async {
room.registerTextStreamHandler('chat',
(TextStreamReader reader, String participantIdentity) async {
room.registerTextStreamHandler('chat', (TextStreamReader reader, String participantIdentity) async {
final text = await reader.readAll();
print('received chat message from $participantIdentity: $text');
expect('some text !!!', text);
Expand All @@ -78,11 +75,9 @@ void main() {
test('Send Large Text Message With Progress Tracking', () async {
final longText = 'a' * 100000;

room.registerTextStreamHandler('chat-long-text',
(TextStreamReader reader, String participantIdentity) async {
room.registerTextStreamHandler('chat-long-text', (TextStreamReader reader, String participantIdentity) async {
final text = await reader.readAll();
print(
'received chat message from $participantIdentity: long text length: ${text.length}');
print('received chat message from $participantIdentity: long text length: ${text.length}');
expect(longText, text);
});

Expand All @@ -99,8 +94,7 @@ void main() {
});

test('Stream Text With Multiple Chunks', () async {
room.registerTextStreamHandler('chat-stream',
(TextStreamReader reader, String participantIdentity) async {
room.registerTextStreamHandler('chat-stream', (TextStreamReader reader, String participantIdentity) async {
reader.listen((chunk) {
print(
'received chunk: ${chunk.content.length}, total: ${reader.info?.size}, progress: ${utf8.decode(chunk.content)}');
Expand Down Expand Up @@ -130,16 +124,14 @@ void main() {
for (var file in files) {
final randomFile = File(file);
final random = Random();
final bytes =
List<int>.generate(100000, (index) => random.nextInt(256));
final bytes = List<int>.generate(100000, (index) => random.nextInt(256));
randomFile.writeAsBytesSync(bytes);
}

room.registerTextStreamHandler('chat-stream-with-files',
(TextStreamReader reader, String participantIdentity) async {
final receivedText = await reader.readAll();
print(
'received chat message from $participantIdentity: long text length: ${receivedText.length}');
print('received chat message from $participantIdentity: long text length: ${receivedText.length}');
expect(longText, receivedText);
});

Expand Down Expand Up @@ -178,22 +170,19 @@ void main() {
final receivedMessages = <String>[];

for (var operationType in operationTypes) {
room.registerTextStreamHandler('chat-operations',
(TextStreamReader reader, String participantIdentity) async {
room.registerTextStreamHandler('chat-operations', (TextStreamReader reader, String participantIdentity) async {
final text = await reader.readAll();
receivedMessages.add('${operationType}: ${text}');
print('received ${operationType} message: ${text}');
});

final info =
await room.localParticipant?.sendText('Test ${operationType}',
options: SendTextOptions(
topic: 'chat-operations',
));
final info = await room.localParticipant?.sendText('Test ${operationType}',
options: SendTextOptions(
topic: 'chat-operations',
));

// Test with streamText and different operation types
final stream =
await room.localParticipant?.streamText(StreamTextOptions(
final stream = await room.localParticipant?.streamText(StreamTextOptions(
topic: 'chat-operations',
type: operationType,
version: operationType == TextStreamOperationType.update ? 2 : null,
Expand All @@ -207,14 +196,9 @@ void main() {
});

test('Text Stream With Attributes And Metadata', () async {
final testAttributes = {
'userId': '12345',
'sessionId': 'abc123',
'priority': 'high'
};
final testAttributes = {'userId': '12345', 'sessionId': 'abc123', 'priority': 'high'};

room.registerTextStreamHandler('chat-metadata',
(TextStreamReader reader, String participantIdentity) async {
room.registerTextStreamHandler('chat-metadata', (TextStreamReader reader, String participantIdentity) async {
final text = await reader.readAll();
print('received message with text: ${text}');
print('received message attributes: ${reader.info?.attributes}');
Expand All @@ -228,21 +212,19 @@ void main() {
expect(reader.info!.attributes['priority'], 'high');
});

final info =
await room.localParticipant?.sendText('Test message with metadata',
options: SendTextOptions(
topic: 'chat-metadata',
attributes: testAttributes,
));
final info = await room.localParticipant?.sendText('Test message with metadata',
options: SendTextOptions(
topic: 'chat-metadata',
attributes: testAttributes,
));
expect(info, isNotNull);
});

test('Text Stream With Reply Functionality', () async {
const originalStreamId = 'original-stream-123';
const replyStreamId = 'reply-stream-456';

room.registerTextStreamHandler('chat-replies',
(TextStreamReader reader, String participantIdentity) async {
room.registerTextStreamHandler('chat-replies', (TextStreamReader reader, String participantIdentity) async {
final text = await reader.readAll();
print('received reply message: ${text}');
expect(text, 'This is a reply to the original message');
Expand All @@ -266,8 +248,7 @@ void main() {
});

test('Text Stream With AI Generated Flag', () async {
room.registerTextStreamHandler('chat-ai-generated',
(TextStreamReader reader, String participantIdentity) async {
room.registerTextStreamHandler('chat-ai-generated', (TextStreamReader reader, String participantIdentity) async {
final text = await reader.readAll();
print('received AI-generated message: ${text}');
expect(text, 'This message was generated by AI');
Expand Down Expand Up @@ -313,8 +294,7 @@ void main() {
final bytes = List<int>.generate(100000, (index) => random.nextInt(256));
randomFile.writeAsBytesSync(bytes);

room.registerByteStreamHandler('file',
(ByteStreamReader reader, String participantIdentity) async {
room.registerByteStreamHandler('file', (ByteStreamReader reader, String participantIdentity) async {
final file = await reader.readAll();
final fileName = 'testfiles/copy-${reader.info!.name}';
print('received file from $participantIdentity: ${file.length}');
Expand All @@ -341,16 +321,13 @@ void main() {
});

test('Stream Raw Bytes With UTF8 Content', () async {
room.registerByteStreamHandler('bytes-stream',
(ByteStreamReader reader, String participantIdentity) async {
room.registerByteStreamHandler('bytes-stream', (ByteStreamReader reader, String participantIdentity) async {
final chunks = await reader.readAll();
final content = chunks.expand((element) => element).toList();
print(
'bytes content = ${content}, \n string content = ${utf8.decode(content)}');
print('bytes content = ${content}, \n string content = ${utf8.decode(content)}');
});

final stream =
await room.localParticipant?.streamBytes(StreamBytesOptions(
final stream = await room.localParticipant?.streamBytes(StreamBytesOptions(
topic: 'bytes-stream',
totalSize: 30,
));
Expand Down Expand Up @@ -389,8 +366,7 @@ void main() {
expect(content, expectedContent);
});

final stream =
await room.localParticipant?.streamBytes(StreamBytesOptions(
final stream = await room.localParticipant?.streamBytes(StreamBytesOptions(
topic: 'files-with-metadata',
name: testFileName,
mimeType: testMimeType,
Expand All @@ -410,8 +386,7 @@ void main() {
var receivedCount = 0;
const expectedCount = 3;

room.registerTextStreamHandler('concurrent-streams',
(TextStreamReader reader, String participantIdentity) async {
room.registerTextStreamHandler('concurrent-streams', (TextStreamReader reader, String participantIdentity) async {
final text = await reader.readAll();
receivedCount++;
print('received concurrent message ${receivedCount}: ${text}');
Expand All @@ -421,8 +396,7 @@ void main() {
final futures = <Future>[];
for (int i = 0; i < expectedCount; i++) {
futures.add(() async {
final stream =
await room.localParticipant?.streamText(StreamTextOptions(
final stream = await room.localParticipant?.streamText(StreamTextOptions(
topic: 'concurrent-streams',
streamId: 'stream-${i}',
type: TextStreamOperationType.create,
Expand All @@ -443,8 +417,7 @@ void main() {
const chunkSize = 50000; // Larger than normal chunk size
final largeData = 'x' * chunkSize;

room.registerTextStreamHandler('large-chunks',
(TextStreamReader reader, String participantIdentity) async {
room.registerTextStreamHandler('large-chunks', (TextStreamReader reader, String participantIdentity) async {
final text = await reader.readAll();
print('received large text, length: ${text.length}');
expect(text.length, chunkSize);
Expand All @@ -465,8 +438,7 @@ void main() {
// Test comprehensive header data transmission
final testCompleter = Completer<bool>();

room.registerTextStreamHandler('header-validation',
(TextStreamReader reader, String participantIdentity) async {
room.registerTextStreamHandler('header-validation', (TextStreamReader reader, String participantIdentity) async {
final text = await reader.readAll();
print('=== Header Validation Test ===');
print('Received text: ${text}');
Expand Down
Loading
Loading