From 9df13a02ea8c1a7cca9c61c701592b38185b8613 Mon Sep 17 00:00:00 2001 From: Karthikeyan S Date: Mon, 13 Oct 2025 07:43:54 +0530 Subject: [PATCH] refactor: merge onGroupCallState and onGroupCallEvent into matrixRTCEventStream with proper types --- lib/fake_matrix_api.dart | 8 ++ lib/src/voip/backend/mesh_backend.dart | 50 +++++++++++ lib/src/voip/group_call_session.dart | 6 ++ lib/src/voip/models/matrixrtc_call_event.dart | 89 +++++++++++++++++++ lib/src/voip/utils/types.dart | 10 +-- 5 files changed, 154 insertions(+), 9 deletions(-) diff --git a/lib/fake_matrix_api.dart b/lib/fake_matrix_api.dart index c2651629..5dffda6d 100644 --- a/lib/fake_matrix_api.dart +++ b/lib/fake_matrix_api.dart @@ -2753,6 +2753,14 @@ class FakeMatrixApi extends BaseClient { (var reqI) => { 'event_id': '42', }, + '/client/v3/rooms/!calls%3Aexample.com/state/com.famedly.call.member/%40test%3AfakeServer.notExisting': + (var reqI) => { + 'event_id': 'call_member_42', + }, + '/client/v3/rooms/!calls%3Aexample.com/state/com.famedly.call.member/%40remoteuser%3Aexample.com': + (var reqI) => { + 'event_id': 'call_member_remote_42', + }, '/client/v3/directory/list/room/!localpart%3Aexample.com': (var req) => {}, '/client/v3/room_keys/version/5': (var req) => {}, diff --git a/lib/src/voip/backend/mesh_backend.dart b/lib/src/voip/backend/mesh_backend.dart index e6ca667b..ba1795df 100644 --- a/lib/src/voip/backend/mesh_backend.dart +++ b/lib/src/voip/backend/mesh_backend.dart @@ -133,7 +133,9 @@ class MeshBackend extends CallBackend { Future _addCall(GroupCallSession groupCall, CallSession call) async { _callSessions.add(call); _initCall(groupCall, call); + // ignore: deprecated_member_use_from_same_package groupCall.onGroupCallEvent.add(GroupCallStateChange.callsChanged); + groupCall.matrixRTCEventStream.add(CallAddedEvent(call)); } /// init a peer call from group calls. @@ -183,7 +185,10 @@ class MeshBackend extends CallBackend { _registerListenersBeforeCallAdd(replacementCall); _initCall(groupCall, replacementCall); + // ignore: deprecated_member_use_from_same_package groupCall.onGroupCallEvent.add(GroupCallStateChange.callsChanged); + groupCall.matrixRTCEventStream + .add(CallReplacedEvent(existingCall, replacementCall)); } /// Removes a peer call from group calls. @@ -196,7 +201,9 @@ class MeshBackend extends CallBackend { _callSessions.removeWhere((element) => call.callId == element.callId); + // ignore: deprecated_member_use_from_same_package groupCall.onGroupCallEvent.add(GroupCallStateChange.callsChanged); + groupCall.matrixRTCEventStream.add(CallRemovedEvent(call)); } Future _disposeCall( @@ -375,7 +382,10 @@ class MeshBackend extends CallBackend { if (nextActiveSpeaker != null && _activeSpeaker != nextActiveSpeaker) { _activeSpeaker = nextActiveSpeaker; + // ignore: deprecated_member_use_from_same_package groupCall.onGroupCallEvent.add(GroupCallStateChange.activeSpeakerChanged); + groupCall.matrixRTCEventStream + .add(GroupCallActiveSpeakerChanged(_activeSpeaker!)); } _activeSpeakerLoopTimeout?.cancel(); _activeSpeakerLoopTimeout = Timer( @@ -401,8 +411,12 @@ class MeshBackend extends CallBackend { ) { _screenshareStreams.add(stream); onStreamAdd.add(stream); + // ignore: deprecated_member_use_from_same_package groupCall.onGroupCallEvent + // ignore: deprecated_member_use_from_same_package .add(GroupCallStateChange.screenshareStreamsChanged); + groupCall.matrixRTCEventStream + .add(GroupCallStreamAdded(GroupCallStreamType.screenshare)); } Future _replaceScreenshareStream( @@ -423,8 +437,12 @@ class MeshBackend extends CallBackend { _screenshareStreams.replaceRange(streamIndex, 1, [replacementStream]); await existingStream.dispose(); + // ignore: deprecated_member_use_from_same_package groupCall.onGroupCallEvent + // ignore: deprecated_member_use_from_same_package .add(GroupCallStateChange.screenshareStreamsChanged); + groupCall.matrixRTCEventStream + .add(GroupCallStreamReplaced(GroupCallStreamType.screenshare)); } Future _removeScreenshareStream( @@ -450,8 +468,12 @@ class MeshBackend extends CallBackend { await stopMediaStream(stream.stream); } + // ignore: deprecated_member_use_from_same_package groupCall.onGroupCallEvent + // ignore: deprecated_member_use_from_same_package .add(GroupCallStateChange.screenshareStreamsChanged); + groupCall.matrixRTCEventStream + .add(GroupCallStreamRemoved(GroupCallStreamType.screenshare)); } Future _onCallStateChanged(CallSession call, CallState state) async { @@ -486,8 +508,12 @@ class MeshBackend extends CallBackend { ) async { _userMediaStreams.add(stream); onStreamAdd.add(stream); + // ignore: deprecated_member_use_from_same_package groupCall.onGroupCallEvent + // ignore: deprecated_member_use_from_same_package .add(GroupCallStateChange.userMediaStreamsChanged); + groupCall.matrixRTCEventStream + .add(GroupCallStreamAdded(GroupCallStreamType.userMedia)); } Future _replaceUserMediaStream( @@ -508,8 +534,12 @@ class MeshBackend extends CallBackend { _userMediaStreams.replaceRange(streamIndex, 1, [replacementStream]); await existingStream.dispose(); + // ignore: deprecated_member_use_from_same_package groupCall.onGroupCallEvent + // ignore: deprecated_member_use_from_same_package .add(GroupCallStateChange.userMediaStreamsChanged); + groupCall.matrixRTCEventStream + .add(GroupCallStreamReplaced(GroupCallStreamType.userMedia)); } Future _removeUserMediaStream( @@ -536,12 +566,19 @@ class MeshBackend extends CallBackend { await stopMediaStream(stream.stream); } + // ignore: deprecated_member_use_from_same_package groupCall.onGroupCallEvent + // ignore: deprecated_member_use_from_same_package .add(GroupCallStateChange.userMediaStreamsChanged); + groupCall.matrixRTCEventStream + .add(GroupCallStreamRemoved(GroupCallStreamType.userMedia)); if (_activeSpeaker == stream.participant && _userMediaStreams.isNotEmpty) { _activeSpeaker = _userMediaStreams[0].participant; + // ignore: deprecated_member_use_from_same_package groupCall.onGroupCallEvent.add(GroupCallStateChange.activeSpeakerChanged); + groupCall.matrixRTCEventStream + .add(GroupCallActiveSpeakerChanged(_activeSpeaker!)); } } @@ -663,7 +700,9 @@ class MeshBackend extends CallBackend { } } + // ignore: deprecated_member_use_from_same_package groupCall.onGroupCallEvent.add(GroupCallStateChange.localMuteStateChanged); + groupCall.matrixRTCEventStream.add(GroupCallLocalMutedChanged(muted, kind)); return; } @@ -799,8 +838,12 @@ class MeshBackend extends CallBackend { _addScreenshareStream(groupCall, localScreenshareStream!); + // ignore: deprecated_member_use_from_same_package groupCall.onGroupCallEvent + // ignore: deprecated_member_use_from_same_package .add(GroupCallStateChange.localScreenshareStateChanged); + groupCall.matrixRTCEventStream + .add(GroupCallLocalScreenshareStateChanged(true)); for (final call in _callSessions) { await call.addLocalStream( await localScreenshareStream!.stream!.clone(), @@ -813,7 +856,10 @@ class MeshBackend extends CallBackend { return; } catch (e, s) { Logs().e('[VOIP] Enabling screensharing error', e, s); + // ignore: deprecated_member_use_from_same_package groupCall.onGroupCallEvent.add(GroupCallStateChange.error); + groupCall.matrixRTCEventStream + .add(GroupCallStateError(e.toString(), s)); return; } } else { @@ -826,8 +872,12 @@ class MeshBackend extends CallBackend { await groupCall.sendMemberStateEvent(); + // ignore: deprecated_member_use_from_same_package groupCall.onGroupCallEvent + // ignore: deprecated_member_use_from_same_package .add(GroupCallStateChange.localMuteStateChanged); + groupCall.matrixRTCEventStream + .add(GroupCallLocalScreenshareStateChanged(false)); return; } } diff --git a/lib/src/voip/group_call_session.dart b/lib/src/voip/group_call_session.dart index 9058f76e..27dfaa90 100644 --- a/lib/src/voip/group_call_session.dart +++ b/lib/src/voip/group_call_session.dart @@ -54,9 +54,11 @@ class GroupCallSession { String groupCallId; + @Deprecated('Use matrixRTCEventStream instead') final CachedStreamController onGroupCallState = CachedStreamController(); + @Deprecated('Use matrixRTCEventStream instead') final CachedStreamController onGroupCallEvent = CachedStreamController(); @@ -105,8 +107,11 @@ class GroupCallSession { void setState(GroupCallState newState) { state = newState; + // ignore: deprecated_member_use_from_same_package onGroupCallState.add(newState); + // ignore: deprecated_member_use_from_same_package onGroupCallEvent.add(GroupCallStateChange.groupCallStateChanged); + matrixRTCEventStream.add(GroupCallStateChanged(newState)); } bool hasLocalParticipant() { @@ -313,6 +318,7 @@ class GroupCallSession { .add(ParticipantsLeftEvent(participants: anyLeft.toList())); } + // ignore: deprecated_member_use_from_same_package onGroupCallEvent.add(GroupCallStateChange.participantsChanged); } } diff --git a/lib/src/voip/models/matrixrtc_call_event.dart b/lib/src/voip/models/matrixrtc_call_event.dart index 82086974..57259f8e 100644 --- a/lib/src/voip/models/matrixrtc_call_event.dart +++ b/lib/src/voip/models/matrixrtc_call_event.dart @@ -5,15 +5,18 @@ import 'package:matrix/matrix.dart'; /// often. sealed class MatrixRTCCallEvent {} +/// Event type for participants change sealed class ParticipantsChangeEvent implements MatrixRTCCallEvent {} final class ParticipantsJoinEvent implements ParticipantsChangeEvent { + /// The participants who joined the call final List participants; ParticipantsJoinEvent({required this.participants}); } final class ParticipantsLeftEvent implements ParticipantsChangeEvent { + /// The participants who left the call final List participants; ParticipantsLeftEvent({required this.participants}); @@ -46,3 +49,89 @@ final class CallReactionRemovedEvent implements CallReactionEvent { required this.redactedEventId, }); } + +/// Group call active speaker changed event +final class GroupCallActiveSpeakerChanged implements MatrixRTCCallEvent { + final CallParticipant participant; + GroupCallActiveSpeakerChanged(this.participant); +} + +/// Group calls changed event type +sealed class GroupCallChanged implements MatrixRTCCallEvent {} + +/// Group call, call added event +final class CallAddedEvent implements GroupCallChanged { + final CallSession call; + CallAddedEvent(this.call); +} + +/// Group call, call removed event +final class CallRemovedEvent implements GroupCallChanged { + final CallSession call; + CallRemovedEvent(this.call); +} + +/// Group call, call replaced event +final class CallReplacedEvent extends GroupCallChanged { + final CallSession existingCall, replacementCall; + CallReplacedEvent(this.existingCall, this.replacementCall); +} + +enum GroupCallStreamType { + userMedia, + screenshare, +} + +/// Group call stream added event +final class GroupCallStreamAdded implements MatrixRTCCallEvent { + final GroupCallStreamType type; + GroupCallStreamAdded(this.type); +} + +/// Group call stream removed event +final class GroupCallStreamRemoved implements MatrixRTCCallEvent { + final GroupCallStreamType type; + GroupCallStreamRemoved(this.type); +} + +/// Group call stream replaced event +final class GroupCallStreamReplaced implements MatrixRTCCallEvent { + final GroupCallStreamType type; + GroupCallStreamReplaced(this.type); +} + +/// Group call local screenshare state changed event +final class GroupCallLocalScreenshareStateChanged + implements MatrixRTCCallEvent { + final bool screensharing; + GroupCallLocalScreenshareStateChanged(this.screensharing); +} + +/// Group call local muted changed event +final class GroupCallLocalMutedChanged implements MatrixRTCCallEvent { + final bool muted; + final MediaInputKind kind; + GroupCallLocalMutedChanged(this.muted, this.kind); +} + +enum GroupCallState { + localCallFeedUninitialized, + initializingLocalCallFeed, + localCallFeedInitialized, + entering, + entered, + ended +} + +/// Group call state changed event +final class GroupCallStateChanged implements MatrixRTCCallEvent { + final GroupCallState state; + GroupCallStateChanged(this.state); +} + +/// Group call error event +final class GroupCallStateError implements MatrixRTCCallEvent { + final String msg; + final dynamic err; + GroupCallStateError(this.msg, this.err); +} diff --git a/lib/src/voip/utils/types.dart b/lib/src/voip/utils/types.dart index 09455726..29531fdd 100644 --- a/lib/src/voip/utils/types.dart +++ b/lib/src/voip/utils/types.dart @@ -165,6 +165,7 @@ class GroupCallError extends Error { } } +@Deprecated('Use the events implementing MatrixRTCCallEvent instead') enum GroupCallStateChange { groupCallStateChanged, activeSpeakerChanged, @@ -176,12 +177,3 @@ enum GroupCallStateChange { participantsChanged, error } - -enum GroupCallState { - localCallFeedUninitialized, - initializingLocalCallFeed, - localCallFeedInitialized, - entering, - entered, - ended -}