Simulcast, Screen sharing & Various improvements (#4)
* Respect `RTCIceTransportPolicy` enum and organize * Simplify syntax where possible etc. * Combine `VideoPreset` and `VideoPresets` * Default values for `ConnectOptions` * Build URI instead of String manipulation * Slight modifications to Exception * `LiveKitTheme` for example * `VideoEncoding` class * Organize imports * First simulcast implementation * Remove unnecessary try-catches * Update Android settings * Remember uri and token * example improvements * `fit` parameter for VideoTrackRenderer * Simulcast option for example * Pass `defaultPublishOptions` * Show only `VideoQuality` * Pass tests * Better buildUri logic * Named parameter to positional * Explicit imports * `VideoParameter` instead of `VideoPreset` * Use `mediaTrack.getSettings` when possible * Safer dispose logic * Safer `PCTransport` Update transport.dart * Synchronized events for `SignalClient` * Use logger instead of print * Make example compile for iOS * First screen share implementation * Make example work with screen share * Example improvement * Code optimization * Don't depend on web_socket_channel * Fix: Unpublish track bug * Show participant mute state & identity * Update protos * Remote mute/unmute * iOS Background mode * Separate `createCameraTrack` and `createScreenTrack` * Clean up * PB fix * format * Fix analyzer warning * Android clean up * Update README.md * Clean up
This commit is contained in:
@@ -0,0 +1,91 @@
|
||||
import 'package:collection/collection.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_webrtc/flutter_webrtc.dart';
|
||||
import 'package:livekit_client/livekit_client.dart';
|
||||
|
||||
import 'no_video.dart';
|
||||
import 'participant_info.dart';
|
||||
|
||||
class ParticipantWidget extends StatefulWidget {
|
||||
//
|
||||
final Participant participant;
|
||||
final VideoQuality quality;
|
||||
|
||||
const ParticipantWidget(
|
||||
this.participant, {
|
||||
this.quality = VideoQuality.MEDIUM,
|
||||
Key? key,
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
State<StatefulWidget> createState() => _ParticipantWidgetState();
|
||||
}
|
||||
|
||||
class _ParticipantWidgetState extends State<ParticipantWidget> with ParticipantDelegate {
|
||||
//
|
||||
TrackPublication? videoPub;
|
||||
TrackPublication? audioPub;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
widget.participant.addListener(_onParticipantChanged);
|
||||
_onParticipantChanged();
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
widget.participant.removeListener(_onParticipantChanged);
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
void didUpdateWidget(covariant ParticipantWidget oldWidget) {
|
||||
oldWidget.participant.removeListener(_onParticipantChanged);
|
||||
widget.participant.addListener(_onParticipantChanged);
|
||||
_onParticipantChanged();
|
||||
super.didUpdateWidget(oldWidget);
|
||||
}
|
||||
|
||||
// register for change so Flutter will re-build the widget upon change
|
||||
void _onParticipantChanged() {
|
||||
//
|
||||
final firstAudio = widget.participant.audioTracks.firstWhereOrNull((pub) => pub.subscribed);
|
||||
final firstVideo = widget.participant.videoTracks
|
||||
.firstWhereOrNull((pub) => !pub.isScreenShare && pub.subscribed);
|
||||
|
||||
if (firstVideo is RemoteTrackPublication) {
|
||||
firstVideo.videoQuality = widget.quality;
|
||||
}
|
||||
|
||||
setState(() {
|
||||
audioPub = !(firstAudio?.muted ?? true) ? firstAudio : null;
|
||||
videoPub = !(firstVideo?.muted ?? true) ? firstVideo : null;
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext ctx) => Container(
|
||||
color: Theme.of(ctx).cardColor,
|
||||
child: Stack(
|
||||
children: [
|
||||
// Video
|
||||
if (videoPub != null)
|
||||
VideoTrackRenderer(
|
||||
videoPub!.track as VideoTrack,
|
||||
fit: RTCVideoViewObjectFit.RTCVideoViewObjectFitCover,
|
||||
)
|
||||
else
|
||||
const NoVideoWidget(),
|
||||
|
||||
Align(
|
||||
alignment: Alignment.bottomCenter,
|
||||
child: ParticipantInfoWidget(
|
||||
title: widget.participant.identity,
|
||||
muted: audioPub == null,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user