Skip to content
Draft
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
1 change: 1 addition & 0 deletions lib/livekit_client.dart
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ export 'src/publication/local.dart';
export 'src/publication/remote.dart';
export 'src/publication/track_publication.dart';
export 'src/support/platform.dart';
export 'src/support/value_or_absent.dart';
export 'src/track/audio_visualizer.dart';
export 'src/track/local/audio.dart';
export 'src/track/local/local.dart';
Expand Down
7 changes: 4 additions & 3 deletions lib/src/core/engine.dart
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ import '../publication/local.dart';
import '../support/disposable.dart';
import '../support/platform.dart' show lkPlatformIsTest, lkPlatformIs, PlatformType;
import '../support/region_url_provider.dart';
import '../support/value_or_absent.dart';
import '../support/websocket.dart';
import '../track/local/local.dart';
import '../track/local/video.dart';
Expand Down Expand Up @@ -562,18 +563,18 @@ class Engine extends Disposable with EventsEmittable<EngineEvent> {
// The server provided iceServers are only used if
// the client's iceServers are not set.
if (rtcConfiguration.iceServers == null && serverProvidedIceServers.isNotEmpty) {
rtcConfiguration = connectOptions.rtcConfiguration.copyWith(iceServers: serverProvidedIceServers);
rtcConfiguration = connectOptions.rtcConfiguration.copyWith(iceServers: Value(serverProvidedIceServers));
}

// set forceRelay if server response is enabled
if (serverResponseForceRelay == lk_models.ClientConfigSetting.ENABLED) {
rtcConfiguration = rtcConfiguration.copyWith(
iceTransportPolicy: RTCIceTransportPolicy.relay,
iceTransportPolicy: Value(RTCIceTransportPolicy.relay),
);
}

if (kIsWeb && (roomOptions.e2eeOptions != null || roomOptions.encryption != null)) {
rtcConfiguration = rtcConfiguration.copyWith(encodedInsertableStreams: true);
rtcConfiguration = rtcConfiguration.copyWith(encodedInsertableStreams: Value(true));
}

return rtcConfiguration;
Expand Down
33 changes: 18 additions & 15 deletions lib/src/core/room.dart
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ import '../proto/livekit_rtc.pb.dart' as lk_rtc;
import '../support/disposable.dart';
import '../support/platform.dart';
import '../support/region_url_provider.dart';
import '../support/value_or_absent.dart';
import '../support/websocket.dart' show WebSocketException;
import '../track/audio_management.dart';
import '../track/local/audio.dart';
Expand Down Expand Up @@ -262,9 +263,9 @@ class Room extends DisposableChangeNotifier with EventsEmittable<RoomEvent> {
if (_e2eeManager != null) {
// Disable backup codec when e2ee is enabled
roomOptions = roomOptions.copyWith(
defaultVideoPublishOptions: roomOptions.defaultVideoPublishOptions.copyWith(
backupVideoCodec: const BackupVideoCodec(enabled: false),
),
defaultVideoPublishOptions: Value(roomOptions.defaultVideoPublishOptions.copyWith(
backupVideoCodec: Value(const BackupVideoCodec(enabled: false)),
)),
);
}

Expand Down Expand Up @@ -449,7 +450,7 @@ class Room extends DisposableChangeNotifier with EventsEmittable<RoomEvent> {
logger.info('Publishing preconnect audio track');
await _localParticipant!.publishAudioTrack(
preConnectAudioBuffer.localTrack!,
publishOptions: roomOptions.defaultAudioPublishOptions.copyWith(preConnect: true),
publishOptions: roomOptions.defaultAudioPublishOptions.copyWith(preConnect: Value(true)),
);
}

Expand Down Expand Up @@ -1095,9 +1096,9 @@ extension RoomHardwareManagementMethods on Room {
await Hardware.instance.selectAudioOutput(device);
}
engine.roomOptions = engine.roomOptions.copyWith(
defaultAudioOutputOptions: roomOptions.defaultAudioOutputOptions.copyWith(
deviceId: device.deviceId,
),
defaultAudioOutputOptions: Value(roomOptions.defaultAudioOutputOptions.copyWith(
deviceId: Value(device.deviceId),
)),
);
}

Expand All @@ -1112,9 +1113,9 @@ extension RoomHardwareManagementMethods on Room {
await Hardware.instance.selectAudioInput(device);
}
engine.roomOptions = engine.roomOptions.copyWith(
defaultAudioCaptureOptions: roomOptions.defaultAudioCaptureOptions.copyWith(
deviceId: device.deviceId,
),
defaultAudioCaptureOptions: Value(roomOptions.defaultAudioCaptureOptions.copyWith(
deviceId: Value(device.deviceId),
)),
);
}

Expand All @@ -1126,7 +1127,8 @@ extension RoomHardwareManagementMethods on Room {

// Always update roomOptions so future tracks use the correct device
engine.roomOptions = engine.roomOptions.copyWith(
defaultCameraCaptureOptions: roomOptions.defaultCameraCaptureOptions.copyWith(deviceId: device.deviceId),
defaultCameraCaptureOptions:
Value(roomOptions.defaultCameraCaptureOptions.copyWith(deviceId: Value(device.deviceId))),
);

try {
Expand All @@ -1137,7 +1139,8 @@ extension RoomHardwareManagementMethods on Room {
} catch (e) {
// if the switching actually fails, reset it to the previous deviceId
engine.roomOptions = engine.roomOptions.copyWith(
defaultCameraCaptureOptions: roomOptions.defaultCameraCaptureOptions.copyWith(deviceId: currentDeviceId),
defaultCameraCaptureOptions:
Value(roomOptions.defaultCameraCaptureOptions.copyWith(deviceId: Value(currentDeviceId))),
);
}
}
Expand All @@ -1150,9 +1153,9 @@ extension RoomHardwareManagementMethods on Room {
if (lkPlatformIsMobile()) {
await Hardware.instance.setSpeakerphoneOn(speakerOn, forceSpeakerOutput: forceSpeakerOutput);
engine.roomOptions = engine.roomOptions.copyWith(
defaultAudioOutputOptions: roomOptions.defaultAudioOutputOptions.copyWith(
speakerOn: speakerOn,
),
defaultAudioOutputOptions: Value(roomOptions.defaultAudioOutputOptions.copyWith(
speakerOn: Value(speakerOn),
)),
);
}
}
Expand Down
5 changes: 3 additions & 2 deletions lib/src/hardware/hardware.dart
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import '../logger.dart';
import '../support/native.dart';
import '../support/native_audio.dart';
import '../support/platform.dart';
import '../support/value_or_absent.dart';
import '../track/audio_management.dart';

class MediaDevice {
Expand Down Expand Up @@ -151,9 +152,9 @@ class Hardware {
config = await onConfigureNativeAudio.call(audioTrackState);
if (_preferSpeakerOutput && _forceSpeakerOutput) {
config = config.copyWith(
appleAudioCategoryOptions: {
appleAudioCategoryOptions: Value({
AppleAudioCategoryOption.defaultToSpeaker,
},
}),
);
}
logger.fine('configuring for ${audioTrackState} using ${config}...');
Expand Down
133 changes: 67 additions & 66 deletions lib/src/options.dart
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@

import 'constants.dart';
import 'e2ee/options.dart';
import 'support/value_or_absent.dart';
import 'track/local/audio.dart';
import 'track/local/video.dart';
import 'track/options.dart';
Expand Down Expand Up @@ -143,33 +144,33 @@ class RoomOptions {
});

RoomOptions copyWith({
CameraCaptureOptions? defaultCameraCaptureOptions,
ScreenShareCaptureOptions? defaultScreenShareCaptureOptions,
AudioCaptureOptions? defaultAudioCaptureOptions,
VideoPublishOptions? defaultVideoPublishOptions,
AudioPublishOptions? defaultAudioPublishOptions,
AudioOutputOptions? defaultAudioOutputOptions,
bool? adaptiveStream,
bool? dynacast,
bool? stopLocalTrackOnUnpublish,
E2EEOptions? e2eeOptions,
E2EEOptions? encryption,
bool? fastPublish,
ValueOrAbsent<CameraCaptureOptions> defaultCameraCaptureOptions = const Absent(),
ValueOrAbsent<ScreenShareCaptureOptions> defaultScreenShareCaptureOptions = const Absent(),
ValueOrAbsent<AudioCaptureOptions> defaultAudioCaptureOptions = const Absent(),
ValueOrAbsent<VideoPublishOptions> defaultVideoPublishOptions = const Absent(),
ValueOrAbsent<AudioPublishOptions> defaultAudioPublishOptions = const Absent(),
ValueOrAbsent<AudioOutputOptions> defaultAudioOutputOptions = const Absent(),
ValueOrAbsent<bool> adaptiveStream = const Absent(),
ValueOrAbsent<bool> dynacast = const Absent(),
ValueOrAbsent<bool> stopLocalTrackOnUnpublish = const Absent(),
ValueOrAbsent<E2EEOptions?> e2eeOptions = const Absent(),
ValueOrAbsent<E2EEOptions?> encryption = const Absent(),
ValueOrAbsent<bool> fastPublish = const Absent(),
}) {
return RoomOptions(
defaultCameraCaptureOptions: defaultCameraCaptureOptions ?? this.defaultCameraCaptureOptions,
defaultScreenShareCaptureOptions: defaultScreenShareCaptureOptions ?? this.defaultScreenShareCaptureOptions,
defaultAudioCaptureOptions: defaultAudioCaptureOptions ?? this.defaultAudioCaptureOptions,
defaultVideoPublishOptions: defaultVideoPublishOptions ?? this.defaultVideoPublishOptions,
defaultAudioPublishOptions: defaultAudioPublishOptions ?? this.defaultAudioPublishOptions,
defaultAudioOutputOptions: defaultAudioOutputOptions ?? this.defaultAudioOutputOptions,
adaptiveStream: adaptiveStream ?? this.adaptiveStream,
dynacast: dynacast ?? this.dynacast,
stopLocalTrackOnUnpublish: stopLocalTrackOnUnpublish ?? this.stopLocalTrackOnUnpublish,
defaultCameraCaptureOptions: defaultCameraCaptureOptions.valueOr(this.defaultCameraCaptureOptions),
defaultScreenShareCaptureOptions: defaultScreenShareCaptureOptions.valueOr(this.defaultScreenShareCaptureOptions),
defaultAudioCaptureOptions: defaultAudioCaptureOptions.valueOr(this.defaultAudioCaptureOptions),
defaultVideoPublishOptions: defaultVideoPublishOptions.valueOr(this.defaultVideoPublishOptions),
defaultAudioPublishOptions: defaultAudioPublishOptions.valueOr(this.defaultAudioPublishOptions),
defaultAudioOutputOptions: defaultAudioOutputOptions.valueOr(this.defaultAudioOutputOptions),
adaptiveStream: adaptiveStream.valueOr(this.adaptiveStream),
dynacast: dynacast.valueOr(this.dynacast),
stopLocalTrackOnUnpublish: stopLocalTrackOnUnpublish.valueOr(this.stopLocalTrackOnUnpublish),
// ignore: deprecated_member_use_from_same_package
e2eeOptions: e2eeOptions ?? this.e2eeOptions,
encryption: encryption ?? this.encryption,
fastPublish: fastPublish ?? this.fastPublish,
e2eeOptions: e2eeOptions.valueOr(this.e2eeOptions),
encryption: encryption.valueOr(this.encryption),
fastPublish: fastPublish.valueOr(this.fastPublish),
);
}
}
Expand All @@ -194,16 +195,16 @@ class BackupVideoCodec {
final VideoEncoding? encoding;
final bool simulcast;
BackupVideoCodec copyWith({
bool? enabled,
String? codec,
VideoEncoding? encoding,
bool? simulcast,
ValueOrAbsent<bool> enabled = const Absent(),
ValueOrAbsent<String> codec = const Absent(),
ValueOrAbsent<VideoEncoding?> encoding = const Absent(),
ValueOrAbsent<bool> simulcast = const Absent(),
}) {
return BackupVideoCodec(
enabled: enabled ?? this.enabled,
codec: codec ?? this.codec,
encoding: encoding ?? this.encoding,
simulcast: simulcast ?? this.simulcast,
enabled: enabled.valueOr(this.enabled),
codec: codec.valueOr(this.codec),
encoding: encoding.valueOr(this.encoding),
simulcast: simulcast.valueOr(this.simulcast),
);
}
}
Expand Down Expand Up @@ -272,30 +273,30 @@ class VideoPublishOptions extends PublishOptions {
this.degradationPreference});

VideoPublishOptions copyWith({
VideoEncoding? videoEncoding,
VideoEncoding? screenShareEncoding,
bool? simulcast,
List<VideoParameters>? videoSimulcastLayers,
List<VideoParameters>? screenShareSimulcastLayers,
String? videoCodec,
BackupVideoCodec? backupVideoCodec,
DegradationPreference? degradationPreference,
String? scalabilityMode,
String? name,
String? stream,
ValueOrAbsent<VideoEncoding?> videoEncoding = const Absent(),
ValueOrAbsent<VideoEncoding?> screenShareEncoding = const Absent(),
ValueOrAbsent<bool> simulcast = const Absent(),
ValueOrAbsent<List<VideoParameters>> videoSimulcastLayers = const Absent(),
ValueOrAbsent<List<VideoParameters>> screenShareSimulcastLayers = const Absent(),
ValueOrAbsent<String> videoCodec = const Absent(),
ValueOrAbsent<BackupVideoCodec> backupVideoCodec = const Absent(),
ValueOrAbsent<DegradationPreference?> degradationPreference = const Absent(),
ValueOrAbsent<String?> scalabilityMode = const Absent(),
ValueOrAbsent<String?> name = const Absent(),
ValueOrAbsent<String?> stream = const Absent(),
}) =>
VideoPublishOptions(
videoEncoding: videoEncoding ?? this.videoEncoding,
screenShareEncoding: screenShareEncoding ?? this.screenShareEncoding,
simulcast: simulcast ?? this.simulcast,
videoSimulcastLayers: videoSimulcastLayers ?? this.videoSimulcastLayers,
screenShareSimulcastLayers: screenShareSimulcastLayers ?? this.screenShareSimulcastLayers,
videoCodec: videoCodec ?? this.videoCodec,
backupVideoCodec: backupVideoCodec ?? this.backupVideoCodec,
degradationPreference: degradationPreference ?? this.degradationPreference,
scalabilityMode: scalabilityMode ?? this.scalabilityMode,
name: name ?? this.name,
stream: stream ?? this.stream,
videoEncoding: videoEncoding.valueOr(this.videoEncoding),
screenShareEncoding: screenShareEncoding.valueOr(this.screenShareEncoding),
simulcast: simulcast.valueOr(this.simulcast),
videoSimulcastLayers: videoSimulcastLayers.valueOr(this.videoSimulcastLayers),
screenShareSimulcastLayers: screenShareSimulcastLayers.valueOr(this.screenShareSimulcastLayers),
videoCodec: videoCodec.valueOr(this.videoCodec),
backupVideoCodec: backupVideoCodec.valueOr(this.backupVideoCodec),
degradationPreference: degradationPreference.valueOr(this.degradationPreference),
scalabilityMode: scalabilityMode.valueOr(this.scalabilityMode),
name: name.valueOr(this.name),
stream: stream.valueOr(this.stream),
);

@override
Expand Down Expand Up @@ -332,20 +333,20 @@ class AudioPublishOptions extends PublishOptions {
});

AudioPublishOptions copyWith({
AudioEncoding? encoding,
bool? dtx,
String? name,
String? stream,
bool? red,
bool? preConnect,
ValueOrAbsent<AudioEncoding?> encoding = const Absent(),
ValueOrAbsent<bool> dtx = const Absent(),
ValueOrAbsent<String?> name = const Absent(),
ValueOrAbsent<String?> stream = const Absent(),
ValueOrAbsent<bool?> red = const Absent(),
ValueOrAbsent<bool> preConnect = const Absent(),
}) =>
AudioPublishOptions(
encoding: encoding ?? this.encoding,
dtx: dtx ?? this.dtx,
name: name ?? this.name,
stream: stream ?? this.stream,
red: red ?? this.red,
preConnect: preConnect ?? this.preConnect,
encoding: encoding.valueOr(this.encoding),
dtx: dtx.valueOr(this.dtx),
name: name.valueOr(this.name),
stream: stream.valueOr(this.stream),
red: red.valueOr(this.red),
preConnect: preConnect.valueOr(this.preConnect),
);

@override
Expand Down
Loading