feat: web/native device consistency management (#243)

* fix: Force audio settings to be consistent.

* chore: applyAudioSettings for onUnpublish.

* revert audio output select for web.

* add RoomHardwareManagementMethods to Room.

* update.

* fix analyze.

* update.

* update.

* chore: Reset sinkId for web when remoteTrack replays.

* rename setAudioOutput to setSinkId for flutter web.

* chore: Make sure AudioElement has `setSinkId` method.
This commit is contained in:
CloudWebRTC
2023-03-07 17:54:06 +08:00
committed by GitHub
parent 70e6589981
commit db2e25d424
12 changed files with 275 additions and 136 deletions
+50 -60
View File
@@ -33,7 +33,6 @@ class _ControlsWidgetState extends State<ControlsWidget> {
List<MediaDevice>? _audioInputs;
List<MediaDevice>? _audioOutputs;
List<MediaDevice>? _videoInputs;
MediaDevice? _selectedVideoInput;
StreamSubscription? _subscription;
@@ -61,7 +60,6 @@ class _ControlsWidgetState extends State<ControlsWidget> {
_audioInputs = devices.where((d) => d.kind == 'audioinput').toList();
_audioOutputs = devices.where((d) => d.kind == 'audiooutput').toList();
_videoInputs = devices.where((d) => d.kind == 'videoinput').toList();
_selectedVideoInput = _videoInputs?.first;
setState(() {});
}
@@ -94,23 +92,18 @@ class _ControlsWidgetState extends State<ControlsWidget> {
}
void _selectAudioOutput(MediaDevice device) async {
await Hardware.instance.selectAudioOutput(device);
await widget.room.setAudioOutputDevice(device);
setState(() {});
}
void _selectAudioInput(MediaDevice device) async {
await Hardware.instance.selectAudioInput(device);
await widget.room.setAudioInputDevice(device);
setState(() {});
}
void _selectVideoInput(MediaDevice device) async {
final track = participant.videoTracks.firstOrNull?.track;
if (track == null) return;
if (_selectedVideoInput?.deviceId != device.deviceId) {
await track.switchCamera(device.deviceId);
_selectedVideoInput = device;
setState(() {});
}
await widget.room.setVideoInputDevice(device);
setState(() {});
}
void _toggleCamera() async {
@@ -293,8 +286,7 @@ class _ControlsWidgetState extends State<ControlsWidget> {
value: device,
child: ListTile(
leading: (device.deviceId ==
Hardware
.instance.selectedAudioInput?.deviceId)
widget.room.selectedAudioInputDeviceId)
? const Icon(
EvaIcons.checkmarkSquare,
color: Colors.white,
@@ -317,45 +309,43 @@ class _ControlsWidgetState extends State<ControlsWidget> {
icon: const Icon(EvaIcons.micOff),
tooltip: 'un-mute audio',
),
if (!lkPlatformIs(PlatformType.web))
PopupMenuButton<MediaDevice>(
icon: const Icon(Icons.volume_up),
itemBuilder: (BuildContext context) {
return [
const PopupMenuItem<MediaDevice>(
value: null,
child: ListTile(
leading: Icon(
EvaIcons.speaker,
color: Colors.white,
),
title: Text('Select Audio Output'),
PopupMenuButton<MediaDevice>(
icon: const Icon(Icons.volume_up),
itemBuilder: (BuildContext context) {
return [
const PopupMenuItem<MediaDevice>(
value: null,
child: ListTile(
leading: Icon(
EvaIcons.speaker,
color: Colors.white,
),
title: Text('Select Audio Output'),
),
if (_audioOutputs != null)
..._audioOutputs!.map((device) {
return PopupMenuItem<MediaDevice>(
value: device,
child: ListTile(
leading: (device.deviceId ==
Hardware
.instance.selectedAudioOutput?.deviceId)
? const Icon(
EvaIcons.checkmarkSquare,
color: Colors.white,
)
: const Icon(
EvaIcons.square,
color: Colors.white,
),
title: Text(device.label),
),
onTap: () => _selectAudioOutput(device),
);
}).toList()
];
},
),
),
if (_audioOutputs != null)
..._audioOutputs!.map((device) {
return PopupMenuItem<MediaDevice>(
value: device,
child: ListTile(
leading: (device.deviceId ==
widget.room.selectedAudioOutputDeviceId)
? const Icon(
EvaIcons.checkmarkSquare,
color: Colors.white,
)
: const Icon(
EvaIcons.square,
color: Colors.white,
),
title: Text(device.label),
),
onTap: () => _selectAudioOutput(device),
);
}).toList()
];
},
),
if (participant.isCameraEnabled())
PopupMenuButton<MediaDevice>(
icon: const Icon(EvaIcons.video),
@@ -377,16 +367,16 @@ class _ControlsWidgetState extends State<ControlsWidget> {
return PopupMenuItem<MediaDevice>(
value: device,
child: ListTile(
leading:
(device.deviceId == _selectedVideoInput?.deviceId)
? const Icon(
EvaIcons.checkmarkSquare,
color: Colors.white,
)
: const Icon(
EvaIcons.square,
color: Colors.white,
),
leading: (device.deviceId ==
widget.room.selectedVideoInputDeviceId)
? const Icon(
EvaIcons.checkmarkSquare,
color: Colors.white,
)
: const Icon(
EvaIcons.square,
color: Colors.white,
),
title: Text(device.label),
),
onTap: () => _selectVideoInput(device),