@@ -20,8 +20,9 @@ import { TypedEventEmitter } from "../models/typed-event-emitter.ts";
2020import { type Room } from "../models/room.ts" ;
2121import { RoomStateEvent } from "../models/room-state.ts" ;
2222import { type MatrixEvent } from "../models/event.ts" ;
23- import { MatrixRTCSession , type SlotDescription } from "./MatrixRTCSession.ts" ;
23+ import { MatrixRTCSession , MatrixRTCSessionEvent , type SlotDescription } from "./MatrixRTCSession.ts" ;
2424import { EventType } from "../@types/event.ts" ;
25+ import { type CallMembership } from "./CallMembership.ts" ;
2526
2627export enum MatrixRTCSessionManagerEvents {
2728 // A member has joined the MatrixRTC session, creating an active session in a room where there wasn't previously
@@ -66,10 +67,7 @@ export class MatrixRTCSessionManager extends TypedEventEmitter<MatrixRTCSessionM
6667 // We shouldn't need to null-check here, but matrix-client.spec.ts mocks getRooms
6768 // returning nothing, and breaks tests if you change it to return an empty array :'(
6869 for ( const room of this . client . getRooms ( ) ?? [ ] ) {
69- const session = MatrixRTCSession . sessionForRoom ( this . client , room , this . slotDescription ) ;
70- if ( session . memberships . length > 0 ) {
71- this . roomSessions . set ( room . roomId , session ) ;
72- }
70+ this . createSessionIfNeeded ( room ) ;
7371 }
7472
7573 this . client . on ( ClientEvent . Room , this . onRoom ) ;
@@ -79,10 +77,10 @@ export class MatrixRTCSessionManager extends TypedEventEmitter<MatrixRTCSessionM
7977
8078 public stop ( ) : void {
8179 for ( const sess of this . roomSessions . values ( ) ) {
80+ sess . off ( MatrixRTCSessionEvent . MembershipsChanged , this . onRtcMembershipChange ) ;
8281 void sess . stop ( ) ;
8382 }
8483 this . roomSessions . clear ( ) ;
85-
8684 this . client . off ( ClientEvent . Room , this . onRoom ) ;
8785 this . client . off ( ClientEvent . Event , this . onEvent ) ;
8886 this . client . off ( RoomStateEvent . Events , this . onRoomState ) ;
@@ -98,67 +96,59 @@ export class MatrixRTCSessionManager extends TypedEventEmitter<MatrixRTCSessionM
9896
9997 /**
10098 * Gets the main MatrixRTC session for a room, returning an empty session
101- * if no members are currently participating
99+ * if no members are currently participating.
100+ * Getting the session will create it if needed (and setup listeners and emit a SessionStarted event if it has members)
102101 */
103102 public getRoomSession ( room : Room ) : MatrixRTCSession {
104- if ( ! this . roomSessions . has ( room . roomId ) ) {
105- this . roomSessions . set (
106- room . roomId ,
107- MatrixRTCSession . sessionForRoom ( this . client , room , this . slotDescription ) ,
108- ) ;
109- }
110-
103+ this . createSessionIfNeeded ( room ) ;
111104 return this . roomSessions . get ( room . roomId ) ! ;
112105 }
113106
114- private onRoom = ( room : Room ) : void => {
115- this . refreshRoom ( room ) ;
107+ private createRoomSession ( room : Room ) : MatrixRTCSession {
108+ const sess = MatrixRTCSession . sessionForSlot ( this . client , room , this . slotDescription ) ;
109+ this . roomSessions . set ( room . roomId , sess ) ;
110+
111+ sess . on ( MatrixRTCSessionEvent . MembershipsChanged , this . onRtcMembershipChange ) ;
112+ this . logger . trace ( `Session started for ${ room . roomId } (${ sess . memberships . length } members)` ) ;
113+ if ( sess . memberships . length > 0 ) this . emit ( MatrixRTCSessionManagerEvents . SessionStarted , room . roomId , sess ) ;
114+ return sess ;
115+ }
116+
117+ private readonly onRtcMembershipChange = (
118+ oldM : CallMembership [ ] ,
119+ newM : CallMembership [ ] ,
120+ session : MatrixRTCSession ,
121+ ) : void => {
122+ if ( oldM . length > 0 && newM . length === 0 ) {
123+ this . logger . trace ( `Session ended for ${ session . roomId } ` ) ;
124+ this . emit ( MatrixRTCSessionManagerEvents . SessionEnded , session . roomId , session ) ;
125+ } else if ( oldM . length === 0 && newM . length > 0 ) {
126+ this . logger . trace ( `Session started for ${ session . roomId } ` ) ;
127+ this . emit ( MatrixRTCSessionManagerEvents . SessionStarted , session . roomId , session ) ;
128+ }
116129 } ;
117130
131+ // Possible cases in which we need to create a session if one doesn't already exist:
132+ private createSessionIfNeeded ( room : Room ) : void {
133+ if ( ! this . roomSessions . has ( room . roomId ) ) this . createRoomSession ( room ) ;
134+ }
135+ private onRoom = ( room : Room ) : void => {
136+ this . createSessionIfNeeded ( room ) ;
137+ } ;
118138 private readonly onEvent = ( event : MatrixEvent ) : void => {
119- if ( ! event . unstableStickyExpiresAt ) return ; // Not sticky, not interested.
120-
121139 if ( event . getType ( ) !== EventType . GroupCallMemberPrefix ) return ;
140+ if ( ! event . unstableStickyExpiresAt ) return ; // Not sticky, not interested.
122141
123142 const room = this . client . getRoom ( event . getRoomId ( ) ) ;
124143 if ( ! room ) return ;
125144
126- this . refreshRoom ( room ) ;
145+ this . createSessionIfNeeded ( room ) ;
127146 } ;
128-
129147 private readonly onRoomState = ( event : MatrixEvent ) : void => {
130- if ( event . getType ( ) !== EventType . GroupCallMemberPrefix ) {
131- return ;
132- }
133- const room = this . client . getRoom ( event . getRoomId ( ) ) ;
134- if ( ! room ) {
135- this . logger . error ( `Got room state event for unknown room ${ event . getRoomId ( ) } !` ) ;
136- return ;
137- }
148+ if ( event . getType ( ) !== EventType . GroupCallMemberPrefix ) return ;
138149
139- this . refreshRoom ( room ) ;
150+ const room = this . client . getRoom ( event . getRoomId ( ) ) ;
151+ if ( ! room ) return ;
152+ this . createSessionIfNeeded ( room ) ;
140153 } ;
141-
142- private refreshRoom ( room : Room ) : void {
143- const isNewSession = ! this . roomSessions . has ( room . roomId ) ;
144- const session = this . getRoomSession ( room ) ;
145-
146- const wasActiveAndKnown = session . memberships . length > 0 && ! isNewSession ;
147- // This needs to be here and the event listener cannot be setup in the MatrixRTCSession,
148- // because we need the update to happen between:
149- // wasActiveAndKnown = session.memberships.length > 0 and
150- // nowActive = session.memberships.length
151- // Alternatively we would need to setup some event emission when the RTC session ended.
152- session . onRTCSessionMemberUpdate ( ) ;
153-
154- const nowActive = session . memberships . length > 0 ;
155-
156- if ( wasActiveAndKnown && ! nowActive ) {
157- this . logger . trace ( `Session ended for ${ room . roomId } (${ session . memberships . length } members)` ) ;
158- this . emit ( MatrixRTCSessionManagerEvents . SessionEnded , room . roomId , this . roomSessions . get ( room . roomId ) ! ) ;
159- } else if ( ! wasActiveAndKnown && nowActive ) {
160- this . logger . trace ( `Session started for ${ room . roomId } (${ session . memberships . length } members)` ) ;
161- this . emit ( MatrixRTCSessionManagerEvents . SessionStarted , room . roomId , this . roomSessions . get ( room . roomId ) ! ) ;
162- }
163- }
164154}
0 commit comments