matrix-js-sdk 41.6.0 → 41.7.0-rc.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (171) hide show
  1. package/lib/ReEmitter.js +1 -1
  2. package/lib/ReEmitter.js.map +1 -1
  3. package/lib/ToDeviceMessageQueue.js +2 -2
  4. package/lib/ToDeviceMessageQueue.js.map +1 -1
  5. package/lib/autodiscovery.js +1 -0
  6. package/lib/autodiscovery.js.map +1 -1
  7. package/lib/client.d.ts.map +1 -1
  8. package/lib/client.js +77 -3
  9. package/lib/client.js.map +1 -1
  10. package/lib/common-crypto/CryptoBackend.js +2 -0
  11. package/lib/common-crypto/CryptoBackend.js.map +1 -1
  12. package/lib/crypto/store/indexeddb-crypto-store-backend.js +1 -1
  13. package/lib/crypto/store/indexeddb-crypto-store-backend.js.map +1 -1
  14. package/lib/crypto/store/indexeddb-crypto-store.js +2 -0
  15. package/lib/crypto/store/indexeddb-crypto-store.js.map +1 -1
  16. package/lib/crypto-api/index.js +58 -58
  17. package/lib/crypto-api/index.js.map +1 -1
  18. package/lib/embedded.js +13 -9
  19. package/lib/embedded.js.map +1 -1
  20. package/lib/extensible_events_v1/MessageEvent.js +15 -15
  21. package/lib/extensible_events_v1/MessageEvent.js.map +1 -1
  22. package/lib/extensible_events_v1/PollEndEvent.js +8 -8
  23. package/lib/extensible_events_v1/PollEndEvent.js.map +1 -1
  24. package/lib/extensible_events_v1/PollResponseEvent.js +1 -0
  25. package/lib/extensible_events_v1/PollResponseEvent.js.map +1 -1
  26. package/lib/extensible_events_v1/PollStartEvent.js +28 -28
  27. package/lib/extensible_events_v1/PollStartEvent.js.map +1 -1
  28. package/lib/filter.js +3 -1
  29. package/lib/filter.js.map +1 -1
  30. package/lib/http-api/errors.js +16 -16
  31. package/lib/http-api/errors.js.map +1 -1
  32. package/lib/http-api/fetch.js +2 -1
  33. package/lib/http-api/fetch.js.map +1 -1
  34. package/lib/http-api/refresh.js +7 -6
  35. package/lib/http-api/refresh.js.map +1 -1
  36. package/lib/http-api/utils.d.ts.map +1 -1
  37. package/lib/http-api/utils.js +1 -5
  38. package/lib/http-api/utils.js.map +1 -1
  39. package/lib/interactive-auth.js +11 -1
  40. package/lib/interactive-auth.js.map +1 -1
  41. package/lib/logger.js +2 -0
  42. package/lib/logger.js.map +1 -1
  43. package/lib/matrixrtc/CallMembership.js +6 -5
  44. package/lib/matrixrtc/CallMembership.js.map +1 -1
  45. package/lib/matrixrtc/MatrixRTCSession.d.ts.map +1 -1
  46. package/lib/matrixrtc/MatrixRTCSession.js +15 -5
  47. package/lib/matrixrtc/MatrixRTCSession.js.map +1 -1
  48. package/lib/matrixrtc/MatrixRTCSessionManager.js +3 -2
  49. package/lib/matrixrtc/MatrixRTCSessionManager.js.map +1 -1
  50. package/lib/matrixrtc/MembershipManager.js +24 -17
  51. package/lib/matrixrtc/MembershipManager.js.map +1 -1
  52. package/lib/matrixrtc/MembershipManagerActionScheduler.js +2 -1
  53. package/lib/matrixrtc/MembershipManagerActionScheduler.js.map +1 -1
  54. package/lib/matrixrtc/RTCEncryptionManager.js +6 -4
  55. package/lib/matrixrtc/RTCEncryptionManager.js.map +1 -1
  56. package/lib/matrixrtc/ToDeviceKeyTransport.js +4 -4
  57. package/lib/matrixrtc/ToDeviceKeyTransport.js.map +1 -1
  58. package/lib/models/MSC3089TreeSpace.js +2 -1
  59. package/lib/models/MSC3089TreeSpace.js.map +1 -1
  60. package/lib/models/beacon.js +8 -4
  61. package/lib/models/beacon.js.map +1 -1
  62. package/lib/models/device.js +7 -0
  63. package/lib/models/device.js.map +1 -1
  64. package/lib/models/event-context.js +2 -1
  65. package/lib/models/event-context.js.map +1 -1
  66. package/lib/models/event-timeline-set.js +7 -1
  67. package/lib/models/event-timeline-set.js.map +1 -1
  68. package/lib/models/event-timeline.js +5 -1
  69. package/lib/models/event-timeline.js.map +1 -1
  70. package/lib/models/event.js +35 -11
  71. package/lib/models/event.js.map +1 -1
  72. package/lib/models/poll.js +7 -3
  73. package/lib/models/poll.js.map +1 -1
  74. package/lib/models/related-relations.js +2 -0
  75. package/lib/models/related-relations.js.map +1 -1
  76. package/lib/models/relations-container.js +2 -2
  77. package/lib/models/relations-container.js.map +1 -1
  78. package/lib/models/relations.js +4 -3
  79. package/lib/models/relations.js.map +1 -1
  80. package/lib/models/room-member.js +24 -2
  81. package/lib/models/room-member.js.map +1 -1
  82. package/lib/models/room-receipts.js +19 -12
  83. package/lib/models/room-receipts.js.map +1 -1
  84. package/lib/models/room-state.js +2 -2
  85. package/lib/models/room-state.js.map +1 -1
  86. package/lib/models/room-sticky-events.js +1 -0
  87. package/lib/models/room-sticky-events.js.map +1 -1
  88. package/lib/models/room.js +35 -4
  89. package/lib/models/room.js.map +1 -1
  90. package/lib/models/thread.js +46 -2
  91. package/lib/models/thread.js.map +1 -1
  92. package/lib/models/user.js +20 -1
  93. package/lib/models/user.js.map +1 -1
  94. package/lib/oidc/tokenRefresher.js +11 -8
  95. package/lib/oidc/tokenRefresher.js.map +1 -1
  96. package/lib/pushprocessor.js +1 -1
  97. package/lib/pushprocessor.js.map +1 -1
  98. package/lib/rendezvous/MSC4108SignInWithQR.js +6 -1
  99. package/lib/rendezvous/MSC4108SignInWithQR.js.map +1 -1
  100. package/lib/rendezvous/channels/MSC4108SecureChannel.js +3 -1
  101. package/lib/rendezvous/channels/MSC4108SecureChannel.js.map +1 -1
  102. package/lib/rendezvous/transports/MSC4108RendezvousSession.js +8 -0
  103. package/lib/rendezvous/transports/MSC4108RendezvousSession.js.map +1 -1
  104. package/lib/room-hierarchy.js +8 -4
  105. package/lib/room-hierarchy.js.map +1 -1
  106. package/lib/rust-crypto/DehydratedDeviceManager.js +3 -2
  107. package/lib/rust-crypto/DehydratedDeviceManager.js.map +1 -1
  108. package/lib/rust-crypto/KeyClaimManager.js +2 -1
  109. package/lib/rust-crypto/KeyClaimManager.js.map +1 -1
  110. package/lib/rust-crypto/OutgoingRequestsManager.js +12 -12
  111. package/lib/rust-crypto/OutgoingRequestsManager.js.map +1 -1
  112. package/lib/rust-crypto/PerSessionKeyBackupDownloader.js +5 -3
  113. package/lib/rust-crypto/PerSessionKeyBackupDownloader.js.map +1 -1
  114. package/lib/rust-crypto/RoomEncryptor.js +6 -6
  115. package/lib/rust-crypto/RoomEncryptor.js.map +1 -1
  116. package/lib/rust-crypto/backup.js +6 -4
  117. package/lib/rust-crypto/backup.js.map +1 -1
  118. package/lib/rust-crypto/rust-crypto.js +18 -10
  119. package/lib/rust-crypto/rust-crypto.js.map +1 -1
  120. package/lib/rust-crypto/verification.js +9 -7
  121. package/lib/rust-crypto/verification.js.map +1 -1
  122. package/lib/scheduler.js +2 -2
  123. package/lib/scheduler.js.map +1 -1
  124. package/lib/serverCapabilities.js +5 -2
  125. package/lib/serverCapabilities.js.map +1 -1
  126. package/lib/sliding-sync-sdk.js +6 -3
  127. package/lib/sliding-sync-sdk.js.map +1 -1
  128. package/lib/sliding-sync.js +9 -4
  129. package/lib/sliding-sync.js.map +1 -1
  130. package/lib/store/indexeddb-local-backend.js +5 -1
  131. package/lib/store/indexeddb-local-backend.js.map +1 -1
  132. package/lib/store/indexeddb-remote-backend.js +7 -6
  133. package/lib/store/indexeddb-remote-backend.js.map +1 -1
  134. package/lib/store/indexeddb-store-worker.js +2 -1
  135. package/lib/store/indexeddb-store-worker.js.map +1 -1
  136. package/lib/store/indexeddb.js +1 -0
  137. package/lib/store/indexeddb.js.map +1 -1
  138. package/lib/store/memory.js +4 -0
  139. package/lib/store/memory.js.map +1 -1
  140. package/lib/sync-accumulator.js +1 -1
  141. package/lib/sync-accumulator.js.map +1 -1
  142. package/lib/sync.d.ts.map +1 -1
  143. package/lib/sync.js +32 -16
  144. package/lib/sync.js.map +1 -1
  145. package/lib/timeline-window.js +6 -2
  146. package/lib/timeline-window.js.map +1 -1
  147. package/lib/webrtc/call.js +42 -6
  148. package/lib/webrtc/call.js.map +1 -1
  149. package/lib/webrtc/callEventHandler.js +5 -0
  150. package/lib/webrtc/callEventHandler.js.map +1 -1
  151. package/lib/webrtc/callFeed.js +15 -0
  152. package/lib/webrtc/callFeed.js.map +1 -1
  153. package/lib/webrtc/groupCall.js +24 -8
  154. package/lib/webrtc/groupCall.js.map +1 -1
  155. package/lib/webrtc/groupCallEventHandler.js +1 -1
  156. package/lib/webrtc/groupCallEventHandler.js.map +1 -1
  157. package/lib/webrtc/mediaHandler.js +7 -3
  158. package/lib/webrtc/mediaHandler.js.map +1 -1
  159. package/lib/webrtc/stats/callStatsReportGatherer.js +5 -2
  160. package/lib/webrtc/stats/callStatsReportGatherer.js.map +1 -1
  161. package/lib/webrtc/stats/groupCallStats.js +4 -3
  162. package/lib/webrtc/stats/groupCallStats.js.map +1 -1
  163. package/lib/webrtc/stats/media/mediaTrackStats.js +3 -3
  164. package/lib/webrtc/stats/media/mediaTrackStats.js.map +1 -1
  165. package/lib/webrtc/stats/media/mediaTrackStatsHandler.js +1 -1
  166. package/lib/webrtc/stats/media/mediaTrackStatsHandler.js.map +1 -1
  167. package/package.json +125 -138
  168. package/src/client.ts +4 -1
  169. package/src/http-api/utils.ts +4 -9
  170. package/src/matrixrtc/MatrixRTCSession.ts +4 -3
  171. package/src/sync.ts +5 -1
@@ -31,6 +31,7 @@ export var GroupCallEventHandlerEvent = /*#__PURE__*/function (GroupCallEventHan
31
31
  }({});
32
32
  export class GroupCallEventHandler {
33
33
  constructor(client) {
34
+ this.client = client;
34
35
  _defineProperty(this, "groupCalls", new Map());
35
36
  // roomId -> GroupCall
36
37
  // All rooms we know about and whether we've seen a 'Room' event
@@ -62,7 +63,6 @@ export class GroupCallEventHandler {
62
63
  }
63
64
  }
64
65
  });
65
- this.client = client;
66
66
  }
67
67
  start() {
68
68
  var _this = this;
@@ -1 +1 @@
1
- {"version":3,"file":"groupCallEventHandler.js","names":["ClientEvent","GroupCall","GroupCallIntent","GroupCallType","RoomStateEvent","logger","EventType","SyncState","GroupCallEventHandlerEvent","GroupCallEventHandler","constructor","client","_defineProperty","Map","room","createGroupCallForRoom","event","state","eventType","getType","GroupCallPrefix","groupCallId","getStateKey","content","getContent","currentGroupCall","groupCalls","get","roomId","isRedacted","createGroupCallFromRoomStateEvent","terminate","type","warn","concat","start","_this","_asyncToGenerator","getSyncState","Syncing","debug","Promise","resolve","onSync","off","Sync","on","rooms","getRooms","Room","onRoomsChanged","Events","onRoomStateChanged","stop","removeListener","getRoomDeferred","deferred","roomDeferreds","undefined","resolveFunc","prom","set","waitUntilRoomReadyForGroupCalls","getGroupCallById","values","find","groupCall","callEvents","currentState","getStateEvents","sortedCallEvents","sort","a","b","getTs","callEvent","length","getRoomId","getRoom","callType","Object","includes","callIntent","isPtt","Boolean","dataChannelOptions","dataChannelsEnabled","_content$dataChannelO","ordered","maxPacketLifeTime","maxRetransmits","protocol","isVoipWithNoMediaAllowed","useLivekitForGroupCalls","emit","Incoming"],"sources":["../../src/webrtc/groupCallEventHandler.ts"],"sourcesContent":["/*\nCopyright 2021 Šimon Brandner <simon.bra.ag@gmail.com>\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n*/\n\nimport { type MatrixEvent } from \"../models/event.ts\";\nimport { type MatrixClient, ClientEvent } from \"../client.ts\";\nimport { GroupCall, GroupCallIntent, GroupCallType, type IGroupCallDataChannelOptions } from \"./groupCall.ts\";\nimport { type Room } from \"../models/room.ts\";\nimport { type RoomState, RoomStateEvent } from \"../models/room-state.ts\";\nimport { type RoomMember } from \"../models/room-member.ts\";\nimport { logger } from \"../logger.ts\";\nimport { EventType } from \"../@types/event.ts\";\nimport { SyncState } from \"../sync.ts\";\n\nexport enum GroupCallEventHandlerEvent {\n Incoming = \"GroupCall.incoming\",\n Outgoing = \"GroupCall.outgoing\",\n Ended = \"GroupCall.ended\",\n Participants = \"GroupCall.participants\",\n}\n\nexport type GroupCallEventHandlerEventHandlerMap = {\n [GroupCallEventHandlerEvent.Incoming]: (call: GroupCall) => void;\n [GroupCallEventHandlerEvent.Outgoing]: (call: GroupCall) => void;\n [GroupCallEventHandlerEvent.Ended]: (call: GroupCall) => void;\n [GroupCallEventHandlerEvent.Participants]: (participants: RoomMember[], call: GroupCall) => void;\n};\n\ninterface RoomDeferred {\n prom: Promise<void>;\n resolve?: () => void;\n}\n\nexport class GroupCallEventHandler {\n public groupCalls = new Map<string, GroupCall>(); // roomId -> GroupCall\n\n // All rooms we know about and whether we've seen a 'Room' event\n // for them. The promise will be fulfilled once we've processed that\n // event which means we're \"up to date\" on what calls are in a room\n // and get\n private roomDeferreds = new Map<string, RoomDeferred>();\n\n public constructor(private client: MatrixClient) {}\n\n public async start(): Promise<void> {\n // We wait until the client has started syncing for real.\n // This is because we only support one call at a time, and want\n // the latest. We therefore want the latest state of the room before\n // we create a group call for the room so we can be fairly sure that\n // the group call we create is really the latest one.\n if (this.client.getSyncState() !== SyncState.Syncing) {\n logger.debug(\"GroupCallEventHandler start() waiting for client to start syncing\");\n await new Promise<void>((resolve) => {\n const onSync = (): void => {\n if (this.client.getSyncState() === SyncState.Syncing) {\n this.client.off(ClientEvent.Sync, onSync);\n return resolve();\n }\n };\n this.client.on(ClientEvent.Sync, onSync);\n });\n }\n\n const rooms = this.client.getRooms();\n\n for (const room of rooms) {\n this.createGroupCallForRoom(room);\n }\n\n this.client.on(ClientEvent.Room, this.onRoomsChanged);\n this.client.on(RoomStateEvent.Events, this.onRoomStateChanged);\n }\n\n public stop(): void {\n this.client.removeListener(ClientEvent.Room, this.onRoomsChanged);\n this.client.removeListener(RoomStateEvent.Events, this.onRoomStateChanged);\n }\n\n private getRoomDeferred(roomId: string): RoomDeferred {\n let deferred = this.roomDeferreds.get(roomId);\n if (deferred === undefined) {\n let resolveFunc: () => void;\n deferred = {\n prom: new Promise<void>((resolve) => {\n resolveFunc = resolve;\n }),\n };\n deferred.resolve = resolveFunc!;\n this.roomDeferreds.set(roomId, deferred);\n }\n\n return deferred;\n }\n\n public waitUntilRoomReadyForGroupCalls(roomId: string): Promise<void> {\n return this.getRoomDeferred(roomId).prom;\n }\n\n public getGroupCallById(groupCallId: string): GroupCall | undefined {\n return [...this.groupCalls.values()].find((groupCall) => groupCall.groupCallId === groupCallId);\n }\n\n private createGroupCallForRoom(room: Room): void {\n const callEvents = room.currentState.getStateEvents(EventType.GroupCallPrefix);\n const sortedCallEvents = callEvents.sort((a, b) => b.getTs() - a.getTs());\n\n for (const callEvent of sortedCallEvents) {\n const content = callEvent.getContent();\n\n if (content[\"m.terminated\"] || callEvent.isRedacted()) {\n continue;\n }\n\n logger.debug(\n `GroupCallEventHandler createGroupCallForRoom() choosing group call from possible calls (stateKey=${callEvent.getStateKey()}, ts=${callEvent.getTs()}, roomId=${\n room.roomId\n }, numOfPossibleCalls=${callEvents.length})`,\n );\n\n this.createGroupCallFromRoomStateEvent(callEvent);\n break;\n }\n\n this.getRoomDeferred(room.roomId).resolve!();\n }\n\n private createGroupCallFromRoomStateEvent(event: MatrixEvent): GroupCall | undefined {\n const roomId = event.getRoomId();\n const content = event.getContent();\n\n const room = this.client.getRoom(roomId);\n\n if (!room) {\n logger.warn(\n `GroupCallEventHandler createGroupCallFromRoomStateEvent() couldn't find room for call (roomId=${roomId})`,\n );\n return;\n }\n\n const groupCallId = event.getStateKey();\n\n const callType = content[\"m.type\"];\n\n if (!Object.values(GroupCallType).includes(callType)) {\n logger.warn(\n `GroupCallEventHandler createGroupCallFromRoomStateEvent() received invalid call type (type=${callType}, roomId=${roomId})`,\n );\n return;\n }\n\n const callIntent = content[\"m.intent\"];\n\n if (!Object.values(GroupCallIntent).includes(callIntent)) {\n logger.warn(`Received invalid group call intent (type=${callType}, roomId=${roomId})`);\n return;\n }\n\n const isPtt = Boolean(content[\"io.element.ptt\"]);\n\n let dataChannelOptions: IGroupCallDataChannelOptions | undefined;\n\n if (content?.dataChannelsEnabled && content?.dataChannelOptions) {\n // Pull out just the dataChannelOptions we want to support.\n const { ordered, maxPacketLifeTime, maxRetransmits, protocol } = content.dataChannelOptions;\n dataChannelOptions = { ordered, maxPacketLifeTime, maxRetransmits, protocol };\n }\n\n const groupCall = new GroupCall(\n this.client,\n room,\n callType,\n isPtt,\n callIntent,\n groupCallId,\n // Because without Media section a WebRTC connection is not possible, so need a RTCDataChannel to set up a\n // no media WebRTC connection anyway.\n content?.dataChannelsEnabled || this.client.isVoipWithNoMediaAllowed,\n dataChannelOptions,\n this.client.isVoipWithNoMediaAllowed,\n this.client.useLivekitForGroupCalls,\n content[\"io.element.livekit_service_url\"],\n );\n\n this.groupCalls.set(room.roomId, groupCall);\n this.client.emit(GroupCallEventHandlerEvent.Incoming, groupCall);\n\n return groupCall;\n }\n\n private onRoomsChanged = (room: Room): void => {\n this.createGroupCallForRoom(room);\n };\n\n private onRoomStateChanged = (event: MatrixEvent, state: RoomState): void => {\n const eventType = event.getType();\n\n if (eventType === EventType.GroupCallPrefix) {\n const groupCallId = event.getStateKey();\n const content = event.getContent();\n\n const currentGroupCall = this.groupCalls.get(state.roomId);\n\n if (!currentGroupCall && !content[\"m.terminated\"] && !event.isRedacted()) {\n this.createGroupCallFromRoomStateEvent(event);\n } else if (currentGroupCall && currentGroupCall.groupCallId === groupCallId) {\n if (content[\"m.terminated\"] || event.isRedacted()) {\n currentGroupCall.terminate(false);\n } else if (content[\"m.type\"] !== currentGroupCall.type) {\n // TODO: Handle the callType changing when the room state changes\n logger.warn(\n `GroupCallEventHandler onRoomStateChanged() currently does not support changing type (roomId=${state.roomId})`,\n );\n }\n } else if (currentGroupCall && currentGroupCall.groupCallId !== groupCallId) {\n // TODO: Handle new group calls and multiple group calls\n logger.warn(\n `GroupCallEventHandler onRoomStateChanged() currently does not support multiple calls (roomId=${state.roomId})`,\n );\n }\n }\n };\n}\n"],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"file":"groupCallEventHandler.js","names":["ClientEvent","GroupCall","GroupCallIntent","GroupCallType","RoomStateEvent","logger","EventType","SyncState","GroupCallEventHandlerEvent","GroupCallEventHandler","constructor","client","_defineProperty","Map","room","createGroupCallForRoom","event","state","eventType","getType","GroupCallPrefix","groupCallId","getStateKey","content","getContent","currentGroupCall","groupCalls","get","roomId","isRedacted","createGroupCallFromRoomStateEvent","terminate","type","warn","concat","start","_this","_asyncToGenerator","getSyncState","Syncing","debug","Promise","resolve","onSync","off","Sync","on","rooms","getRooms","Room","onRoomsChanged","Events","onRoomStateChanged","stop","removeListener","getRoomDeferred","deferred","roomDeferreds","undefined","resolveFunc","prom","set","waitUntilRoomReadyForGroupCalls","getGroupCallById","values","find","groupCall","callEvents","currentState","getStateEvents","sortedCallEvents","sort","a","b","getTs","callEvent","length","getRoomId","getRoom","callType","Object","includes","callIntent","isPtt","Boolean","dataChannelOptions","dataChannelsEnabled","_content$dataChannelO","ordered","maxPacketLifeTime","maxRetransmits","protocol","isVoipWithNoMediaAllowed","useLivekitForGroupCalls","emit","Incoming"],"sources":["../../src/webrtc/groupCallEventHandler.ts"],"sourcesContent":["/*\nCopyright 2021 Šimon Brandner <simon.bra.ag@gmail.com>\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n*/\n\nimport { type MatrixEvent } from \"../models/event.ts\";\nimport { type MatrixClient, ClientEvent } from \"../client.ts\";\nimport { GroupCall, GroupCallIntent, GroupCallType, type IGroupCallDataChannelOptions } from \"./groupCall.ts\";\nimport { type Room } from \"../models/room.ts\";\nimport { type RoomState, RoomStateEvent } from \"../models/room-state.ts\";\nimport { type RoomMember } from \"../models/room-member.ts\";\nimport { logger } from \"../logger.ts\";\nimport { EventType } from \"../@types/event.ts\";\nimport { SyncState } from \"../sync.ts\";\n\nexport enum GroupCallEventHandlerEvent {\n Incoming = \"GroupCall.incoming\",\n Outgoing = \"GroupCall.outgoing\",\n Ended = \"GroupCall.ended\",\n Participants = \"GroupCall.participants\",\n}\n\nexport type GroupCallEventHandlerEventHandlerMap = {\n [GroupCallEventHandlerEvent.Incoming]: (call: GroupCall) => void;\n [GroupCallEventHandlerEvent.Outgoing]: (call: GroupCall) => void;\n [GroupCallEventHandlerEvent.Ended]: (call: GroupCall) => void;\n [GroupCallEventHandlerEvent.Participants]: (participants: RoomMember[], call: GroupCall) => void;\n};\n\ninterface RoomDeferred {\n prom: Promise<void>;\n resolve?: () => void;\n}\n\nexport class GroupCallEventHandler {\n public groupCalls = new Map<string, GroupCall>(); // roomId -> GroupCall\n\n // All rooms we know about and whether we've seen a 'Room' event\n // for them. The promise will be fulfilled once we've processed that\n // event which means we're \"up to date\" on what calls are in a room\n // and get\n private roomDeferreds = new Map<string, RoomDeferred>();\n\n public constructor(private client: MatrixClient) {}\n\n public async start(): Promise<void> {\n // We wait until the client has started syncing for real.\n // This is because we only support one call at a time, and want\n // the latest. We therefore want the latest state of the room before\n // we create a group call for the room so we can be fairly sure that\n // the group call we create is really the latest one.\n if (this.client.getSyncState() !== SyncState.Syncing) {\n logger.debug(\"GroupCallEventHandler start() waiting for client to start syncing\");\n await new Promise<void>((resolve) => {\n const onSync = (): void => {\n if (this.client.getSyncState() === SyncState.Syncing) {\n this.client.off(ClientEvent.Sync, onSync);\n return resolve();\n }\n };\n this.client.on(ClientEvent.Sync, onSync);\n });\n }\n\n const rooms = this.client.getRooms();\n\n for (const room of rooms) {\n this.createGroupCallForRoom(room);\n }\n\n this.client.on(ClientEvent.Room, this.onRoomsChanged);\n this.client.on(RoomStateEvent.Events, this.onRoomStateChanged);\n }\n\n public stop(): void {\n this.client.removeListener(ClientEvent.Room, this.onRoomsChanged);\n this.client.removeListener(RoomStateEvent.Events, this.onRoomStateChanged);\n }\n\n private getRoomDeferred(roomId: string): RoomDeferred {\n let deferred = this.roomDeferreds.get(roomId);\n if (deferred === undefined) {\n let resolveFunc: () => void;\n deferred = {\n prom: new Promise<void>((resolve) => {\n resolveFunc = resolve;\n }),\n };\n deferred.resolve = resolveFunc!;\n this.roomDeferreds.set(roomId, deferred);\n }\n\n return deferred;\n }\n\n public waitUntilRoomReadyForGroupCalls(roomId: string): Promise<void> {\n return this.getRoomDeferred(roomId).prom;\n }\n\n public getGroupCallById(groupCallId: string): GroupCall | undefined {\n return [...this.groupCalls.values()].find((groupCall) => groupCall.groupCallId === groupCallId);\n }\n\n private createGroupCallForRoom(room: Room): void {\n const callEvents = room.currentState.getStateEvents(EventType.GroupCallPrefix);\n const sortedCallEvents = callEvents.sort((a, b) => b.getTs() - a.getTs());\n\n for (const callEvent of sortedCallEvents) {\n const content = callEvent.getContent();\n\n if (content[\"m.terminated\"] || callEvent.isRedacted()) {\n continue;\n }\n\n logger.debug(\n `GroupCallEventHandler createGroupCallForRoom() choosing group call from possible calls (stateKey=${callEvent.getStateKey()}, ts=${callEvent.getTs()}, roomId=${\n room.roomId\n }, numOfPossibleCalls=${callEvents.length})`,\n );\n\n this.createGroupCallFromRoomStateEvent(callEvent);\n break;\n }\n\n this.getRoomDeferred(room.roomId).resolve!();\n }\n\n private createGroupCallFromRoomStateEvent(event: MatrixEvent): GroupCall | undefined {\n const roomId = event.getRoomId();\n const content = event.getContent();\n\n const room = this.client.getRoom(roomId);\n\n if (!room) {\n logger.warn(\n `GroupCallEventHandler createGroupCallFromRoomStateEvent() couldn't find room for call (roomId=${roomId})`,\n );\n return;\n }\n\n const groupCallId = event.getStateKey();\n\n const callType = content[\"m.type\"];\n\n if (!Object.values(GroupCallType).includes(callType)) {\n logger.warn(\n `GroupCallEventHandler createGroupCallFromRoomStateEvent() received invalid call type (type=${callType}, roomId=${roomId})`,\n );\n return;\n }\n\n const callIntent = content[\"m.intent\"];\n\n if (!Object.values(GroupCallIntent).includes(callIntent)) {\n logger.warn(`Received invalid group call intent (type=${callType}, roomId=${roomId})`);\n return;\n }\n\n const isPtt = Boolean(content[\"io.element.ptt\"]);\n\n let dataChannelOptions: IGroupCallDataChannelOptions | undefined;\n\n if (content?.dataChannelsEnabled && content?.dataChannelOptions) {\n // Pull out just the dataChannelOptions we want to support.\n const { ordered, maxPacketLifeTime, maxRetransmits, protocol } = content.dataChannelOptions;\n dataChannelOptions = { ordered, maxPacketLifeTime, maxRetransmits, protocol };\n }\n\n const groupCall = new GroupCall(\n this.client,\n room,\n callType,\n isPtt,\n callIntent,\n groupCallId,\n // Because without Media section a WebRTC connection is not possible, so need a RTCDataChannel to set up a\n // no media WebRTC connection anyway.\n content?.dataChannelsEnabled || this.client.isVoipWithNoMediaAllowed,\n dataChannelOptions,\n this.client.isVoipWithNoMediaAllowed,\n this.client.useLivekitForGroupCalls,\n content[\"io.element.livekit_service_url\"],\n );\n\n this.groupCalls.set(room.roomId, groupCall);\n this.client.emit(GroupCallEventHandlerEvent.Incoming, groupCall);\n\n return groupCall;\n }\n\n private onRoomsChanged = (room: Room): void => {\n this.createGroupCallForRoom(room);\n };\n\n private onRoomStateChanged = (event: MatrixEvent, state: RoomState): void => {\n const eventType = event.getType();\n\n if (eventType === EventType.GroupCallPrefix) {\n const groupCallId = event.getStateKey();\n const content = event.getContent();\n\n const currentGroupCall = this.groupCalls.get(state.roomId);\n\n if (!currentGroupCall && !content[\"m.terminated\"] && !event.isRedacted()) {\n this.createGroupCallFromRoomStateEvent(event);\n } else if (currentGroupCall && currentGroupCall.groupCallId === groupCallId) {\n if (content[\"m.terminated\"] || event.isRedacted()) {\n currentGroupCall.terminate(false);\n } else if (content[\"m.type\"] !== currentGroupCall.type) {\n // TODO: Handle the callType changing when the room state changes\n logger.warn(\n `GroupCallEventHandler onRoomStateChanged() currently does not support changing type (roomId=${state.roomId})`,\n );\n }\n } else if (currentGroupCall && currentGroupCall.groupCallId !== groupCallId) {\n // TODO: Handle new group calls and multiple group calls\n logger.warn(\n `GroupCallEventHandler onRoomStateChanged() currently does not support multiple calls (roomId=${state.roomId})`,\n );\n }\n }\n };\n}\n"],"mappings":"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","ignoreList":[]}
@@ -27,13 +27,17 @@ export var MediaHandlerEvent = /*#__PURE__*/function (MediaHandlerEvent) {
27
27
  return MediaHandlerEvent;
28
28
  }({});
29
29
  export class MediaHandler extends TypedEventEmitter {
30
- // Promise chain to serialise calls to getMediaStream
31
-
32
30
  constructor(client) {
33
31
  super();
32
+ this.client = client;
33
+ _defineProperty(this, "audioInput", void 0);
34
+ _defineProperty(this, "audioSettings", void 0);
35
+ _defineProperty(this, "videoInput", void 0);
36
+ _defineProperty(this, "localUserMediaStream", void 0);
34
37
  _defineProperty(this, "userMediaStreams", []);
35
38
  _defineProperty(this, "screensharingStreams", []);
36
- this.client = client;
39
+ // Promise chain to serialise calls to getMediaStream
40
+ _defineProperty(this, "getMediaStreamPromise", void 0);
37
41
  }
38
42
  restoreMediaSettings(audioInput, videoInput) {
39
43
  this.audioInput = audioInput;
@@ -1 +1 @@
1
- {"version":3,"file":"mediaHandler.js","names":["TypedEventEmitter","GroupCallType","GroupCallState","logger","MediaHandlerEvent","MediaHandler","constructor","client","_defineProperty","restoreMediaSettings","audioInput","videoInput","setAudioInput","deviceId","_this","_asyncToGenerator","info","concat","updateLocalUsermediaStreams","setAudioSettings","opts","_this2","JSON","stringify","audioSettings","Object","assign","setVideoInput","_this3","setMediaInputs","_this4","log","_this5","userMediaStreams","length","callMediaStreamParams","Map","call","callEventHandler","calls","values","set","callId","audio","hasLocalUserMediaAudioTrack","video","hasLocalUserMediaVideoTrack","stream","id","track","getTracks","stop","localUserMediaStream","undefined","callHasEnded","has","_ref","get","getUserMediaStream","updateLocalUsermediaStream","groupCall","groupCallEventHandler","groupCalls","localCallFeed","groupCallId","type","Video","state","Ended","emit","LocalStreamsChanged","hasAudioDevice","devices","navigator","mediaDevices","enumerateDevices","filter","device","kind","err","hasVideoDevice","_arguments","arguments","_this6","reusable","getMediaStreamPromise","then","getUserMediaStreamInternal","_this7","shouldRequestAudio","shouldRequestVideo","canReuseStream","_this7$localUserMedia","_this7$localUserMedia2","getAudioTracks","getVideoTracks","getSettings","constraints","getUserMediaContraints","getUserMedia","e","warn","settings","_this7$localUserMedia3","clone","removeTrack","push","stopUserMediaStream","mediaStream","index","indexOf","debug","splice","_this$localUserMediaS","getTrackById","getScreensharingStream","_arguments2","_this8","screensharingStreams","screenshareConstraints","getScreenshareContraints","desktopCapturerSourceId","getDisplayMedia","matchingStream","stopScreensharingStream","stopAllStreams","exactDeviceId","isWebkit","webkitGetUserMedia","deviceIdKey","audioConstraints","autoGainControl","ideal","echoCancellation","noiseSuppression","videoConstraints","width","exact","height","mandatory","chromeMediaSource","chromeMediaSourceId"],"sources":["../../src/webrtc/mediaHandler.ts"],"sourcesContent":["/*\nCopyright 2015, 2016 OpenMarket Ltd\nCopyright 2017 New Vector Ltd\nCopyright 2019, 2020 The Matrix.org Foundation C.I.C.\nCopyright 2021 - 2022 Šimon Brandner <simon.bra.ag@gmail.com>\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n*/\n\nimport { TypedEventEmitter } from \"../models/typed-event-emitter.ts\";\nimport { GroupCallType, GroupCallState } from \"../webrtc/groupCall.ts\";\nimport { logger } from \"../logger.ts\";\nimport { type MatrixClient } from \"../client.ts\";\n\nexport enum MediaHandlerEvent {\n LocalStreamsChanged = \"local_streams_changed\",\n}\n\nexport type MediaHandlerEventHandlerMap = {\n [MediaHandlerEvent.LocalStreamsChanged]: () => void;\n};\n\nexport interface IScreensharingOpts {\n /**\n * sourceId for Electron DesktopCapturer\n */\n desktopCapturerSourceId?: string;\n audio?: boolean;\n // For electron screen capture, there are very few options for detecting electron\n // apart from inspecting the user agent or just trying getDisplayMedia() and\n // catching the failure, so we do the latter - this flag tells the function to just\n // throw an error so we can catch it in this case, rather than logging and emitting.\n throwOnFail?: boolean;\n}\n\nexport interface AudioSettings {\n autoGainControl: boolean;\n echoCancellation: boolean;\n noiseSuppression: boolean;\n}\n\nexport class MediaHandler extends TypedEventEmitter<\n MediaHandlerEvent.LocalStreamsChanged,\n MediaHandlerEventHandlerMap\n> {\n private audioInput?: string;\n private audioSettings?: AudioSettings;\n private videoInput?: string;\n private localUserMediaStream?: MediaStream;\n public userMediaStreams: MediaStream[] = [];\n public screensharingStreams: MediaStream[] = [];\n\n // Promise chain to serialise calls to getMediaStream\n private getMediaStreamPromise?: Promise<MediaStream>;\n\n public constructor(private client: MatrixClient) {\n super();\n }\n\n public restoreMediaSettings(audioInput: string, videoInput: string): void {\n this.audioInput = audioInput;\n this.videoInput = videoInput;\n }\n\n /**\n * Set an audio input device to use for MatrixCalls\n * @param deviceId - the identifier for the device\n * undefined treated as unset\n */\n public async setAudioInput(deviceId: string): Promise<void> {\n logger.info(`MediaHandler setAudioInput() running (deviceId=${deviceId})`);\n\n if (this.audioInput === deviceId) return;\n\n this.audioInput = deviceId;\n await this.updateLocalUsermediaStreams();\n }\n\n /**\n * Set audio settings for MatrixCalls\n * @param opts - audio options to set\n */\n public async setAudioSettings(opts: AudioSettings): Promise<void> {\n logger.info(`MediaHandler setAudioSettings() running (opts=${JSON.stringify(opts)})`);\n\n this.audioSettings = Object.assign({}, opts) as AudioSettings;\n await this.updateLocalUsermediaStreams();\n }\n\n /**\n * Set a video input device to use for MatrixCalls\n * @param deviceId - the identifier for the device\n * undefined treated as unset\n */\n public async setVideoInput(deviceId: string): Promise<void> {\n logger.info(`MediaHandler setVideoInput() running (deviceId=${deviceId})`);\n\n if (this.videoInput === deviceId) return;\n\n this.videoInput = deviceId;\n await this.updateLocalUsermediaStreams();\n }\n\n /**\n * Set media input devices to use for MatrixCalls\n * @param audioInput - the identifier for the audio device\n * @param videoInput - the identifier for the video device\n * undefined treated as unset\n */\n public async setMediaInputs(audioInput: string, videoInput: string): Promise<void> {\n logger.log(`MediaHandler setMediaInputs() running (audioInput: ${audioInput} videoInput: ${videoInput})`);\n this.audioInput = audioInput;\n this.videoInput = videoInput;\n await this.updateLocalUsermediaStreams();\n }\n\n /*\n * Requests new usermedia streams and replace the old ones\n */\n public async updateLocalUsermediaStreams(): Promise<void> {\n if (this.userMediaStreams.length === 0) return;\n\n const callMediaStreamParams: Map<string, { audio: boolean; video: boolean }> = new Map();\n for (const call of this.client.callEventHandler!.calls.values()) {\n callMediaStreamParams.set(call.callId, {\n audio: call.hasLocalUserMediaAudioTrack,\n video: call.hasLocalUserMediaVideoTrack,\n });\n }\n\n for (const stream of this.userMediaStreams) {\n logger.log(`MediaHandler updateLocalUsermediaStreams() stopping all tracks (streamId=${stream.id})`);\n for (const track of stream.getTracks()) {\n track.stop();\n }\n }\n\n this.userMediaStreams = [];\n this.localUserMediaStream = undefined;\n\n for (const call of this.client.callEventHandler!.calls.values()) {\n if (call.callHasEnded() || !callMediaStreamParams.has(call.callId)) {\n continue;\n }\n\n const { audio, video } = callMediaStreamParams.get(call.callId)!;\n\n logger.log(\n `MediaHandler updateLocalUsermediaStreams() calling getUserMediaStream() (callId=${call.callId})`,\n );\n const stream = await this.getUserMediaStream(audio, video);\n\n if (call.callHasEnded()) {\n continue;\n }\n\n await call.updateLocalUsermediaStream(stream);\n }\n\n for (const groupCall of this.client.groupCallEventHandler!.groupCalls.values()) {\n if (!groupCall.localCallFeed) {\n continue;\n }\n\n logger.log(\n `MediaHandler updateLocalUsermediaStreams() calling getUserMediaStream() (groupCallId=${groupCall.groupCallId})`,\n );\n const stream = await this.getUserMediaStream(true, groupCall.type === GroupCallType.Video);\n\n if (groupCall.state === GroupCallState.Ended) {\n continue;\n }\n\n await groupCall.updateLocalUsermediaStream(stream);\n }\n\n this.emit(MediaHandlerEvent.LocalStreamsChanged);\n }\n\n public async hasAudioDevice(): Promise<boolean> {\n try {\n const devices = await navigator.mediaDevices.enumerateDevices();\n return devices.filter((device) => device.kind === \"audioinput\").length > 0;\n } catch (err) {\n logger.log(`MediaHandler hasAudioDevice() calling navigator.mediaDevices.enumerateDevices with error`, err);\n return false;\n }\n }\n\n public async hasVideoDevice(): Promise<boolean> {\n try {\n const devices = await navigator.mediaDevices.enumerateDevices();\n return devices.filter((device) => device.kind === \"videoinput\").length > 0;\n } catch (err) {\n logger.log(`MediaHandler hasVideoDevice() calling navigator.mediaDevices.enumerateDevices with error`, err);\n return false;\n }\n }\n\n /**\n * @param audio - should have an audio track\n * @param video - should have a video track\n * @param reusable - is allowed to be reused by the MediaHandler\n * @returns based on passed parameters\n */\n public async getUserMediaStream(audio: boolean, video: boolean, reusable = true): Promise<MediaStream> {\n // Serialise calls, othertwise we can't sensibly re-use the stream\n if (this.getMediaStreamPromise) {\n this.getMediaStreamPromise = this.getMediaStreamPromise.then(() => {\n return this.getUserMediaStreamInternal(audio, video, reusable);\n });\n } else {\n this.getMediaStreamPromise = this.getUserMediaStreamInternal(audio, video, reusable);\n }\n\n return this.getMediaStreamPromise;\n }\n\n private async getUserMediaStreamInternal(audio: boolean, video: boolean, reusable: boolean): Promise<MediaStream> {\n const shouldRequestAudio = audio && (await this.hasAudioDevice());\n const shouldRequestVideo = video && (await this.hasVideoDevice());\n\n let stream: MediaStream;\n\n let canReuseStream = true;\n if (this.localUserMediaStream) {\n // This figures out if we can reuse the current localUsermediaStream\n // based on whether or not the \"mute state\" (presence of tracks of a\n // given kind) matches what is being requested\n if (shouldRequestAudio !== this.localUserMediaStream.getAudioTracks().length > 0) {\n canReuseStream = false;\n }\n if (shouldRequestVideo !== this.localUserMediaStream.getVideoTracks().length > 0) {\n canReuseStream = false;\n }\n\n // This code checks that the device ID is the same as the localUserMediaStream stream, but we update\n // the localUserMediaStream whenever the device ID changes (apart from when restoring) so it's not\n // clear why this would ever be different, unless there's a race.\n if (\n shouldRequestAudio &&\n this.localUserMediaStream.getAudioTracks()[0]?.getSettings()?.deviceId !== this.audioInput\n ) {\n canReuseStream = false;\n }\n if (\n shouldRequestVideo &&\n this.localUserMediaStream.getVideoTracks()[0]?.getSettings()?.deviceId !== this.videoInput\n ) {\n canReuseStream = false;\n }\n } else {\n canReuseStream = false;\n }\n\n if (!canReuseStream) {\n let constraints: MediaStreamConstraints;\n try {\n // Not specifying exact for deviceId means switching devices does not always work,\n // try with exact and fallback to ideal if it fails\n constraints = this.getUserMediaContraints(shouldRequestAudio, shouldRequestVideo, true);\n stream = await navigator.mediaDevices.getUserMedia(constraints);\n } catch (e) {\n logger.warn(\n `MediaHandler getUserMediaStreamInternal() error (e=${e}), retrying without exact deviceId`,\n );\n constraints = this.getUserMediaContraints(shouldRequestAudio, shouldRequestVideo, false);\n stream = await navigator.mediaDevices.getUserMedia(constraints);\n }\n logger.log(\n `MediaHandler getUserMediaStreamInternal() calling getUserMediaStream (streamId=${\n stream.id\n }, shouldRequestAudio=${shouldRequestAudio}, shouldRequestVideo=${shouldRequestVideo}, constraints=${JSON.stringify(\n constraints,\n )})`,\n );\n\n for (const track of stream.getTracks()) {\n const settings = track.getSettings();\n\n if (track.kind === \"audio\") {\n this.audioInput = settings.deviceId!;\n } else if (track.kind === \"video\") {\n this.videoInput = settings.deviceId!;\n }\n }\n\n if (reusable) {\n this.localUserMediaStream = stream;\n }\n } else {\n stream = this.localUserMediaStream!.clone();\n logger.log(\n `MediaHandler getUserMediaStreamInternal() cloning (oldStreamId=${this.localUserMediaStream?.id} newStreamId=${stream.id} shouldRequestAudio=${shouldRequestAudio} shouldRequestVideo=${shouldRequestVideo})`,\n );\n\n if (!shouldRequestAudio) {\n for (const track of stream.getAudioTracks()) {\n stream.removeTrack(track);\n }\n }\n\n if (!shouldRequestVideo) {\n for (const track of stream.getVideoTracks()) {\n stream.removeTrack(track);\n }\n }\n }\n\n if (reusable) {\n this.userMediaStreams.push(stream);\n }\n\n this.emit(MediaHandlerEvent.LocalStreamsChanged);\n\n return stream;\n }\n\n /**\n * Stops all tracks on the provided usermedia stream\n */\n public stopUserMediaStream(mediaStream: MediaStream): void {\n logger.log(`MediaHandler stopUserMediaStream() stopping (streamId=${mediaStream.id})`);\n for (const track of mediaStream.getTracks()) {\n track.stop();\n }\n\n const index = this.userMediaStreams.indexOf(mediaStream);\n\n if (index !== -1) {\n logger.debug(\n `MediaHandler stopUserMediaStream() splicing usermedia stream out stream array (streamId=${mediaStream.id})`,\n mediaStream.id,\n );\n this.userMediaStreams.splice(index, 1);\n }\n\n this.emit(MediaHandlerEvent.LocalStreamsChanged);\n\n if (this.localUserMediaStream === mediaStream) {\n // if we have this stream cahced, remove it, because we've stopped it\n this.localUserMediaStream = undefined;\n } else {\n // If it's not the same stream. remove any tracks from the cached stream that\n // we have just stopped, and if we do stop any, call the same method on the\n // cached stream too in order to stop all its tracks (in case they are different)\n // and un-cache it.\n for (const track of mediaStream.getTracks()) {\n if (this.localUserMediaStream?.getTrackById(track.id)) {\n this.stopUserMediaStream(this.localUserMediaStream);\n break;\n }\n }\n }\n }\n\n /**\n * @param opts - screensharing stream options\n * @param reusable - is allowed to be reused by the MediaHandler\n * @returns based on passed parameters\n */\n public async getScreensharingStream(opts: IScreensharingOpts = {}, reusable = true): Promise<MediaStream> {\n let stream: MediaStream;\n\n if (this.screensharingStreams.length === 0) {\n const screenshareConstraints = this.getScreenshareContraints(opts);\n\n if (opts.desktopCapturerSourceId) {\n // We are using Electron\n logger.debug(\n `MediaHandler getScreensharingStream() calling getUserMedia() (opts=${JSON.stringify(opts)})`,\n );\n stream = await navigator.mediaDevices.getUserMedia(screenshareConstraints);\n } else {\n // We are not using Electron\n logger.debug(\n `MediaHandler getScreensharingStream() calling getDisplayMedia() (opts=${JSON.stringify(opts)})`,\n );\n stream = await navigator.mediaDevices.getDisplayMedia(screenshareConstraints);\n }\n } else {\n const matchingStream = this.screensharingStreams[this.screensharingStreams.length - 1];\n logger.log(`MediaHandler getScreensharingStream() cloning (streamId=${matchingStream.id})`);\n stream = matchingStream.clone();\n }\n\n if (reusable) {\n this.screensharingStreams.push(stream);\n }\n\n this.emit(MediaHandlerEvent.LocalStreamsChanged);\n\n return stream;\n }\n\n /**\n * Stops all tracks on the provided screensharing stream\n */\n public stopScreensharingStream(mediaStream: MediaStream): void {\n logger.debug(`MediaHandler stopScreensharingStream() stopping stream (streamId=${mediaStream.id})`);\n for (const track of mediaStream.getTracks()) {\n track.stop();\n }\n\n const index = this.screensharingStreams.indexOf(mediaStream);\n\n if (index !== -1) {\n logger.debug(`MediaHandler stopScreensharingStream() splicing stream out (streamId=${mediaStream.id})`);\n this.screensharingStreams.splice(index, 1);\n }\n\n this.emit(MediaHandlerEvent.LocalStreamsChanged);\n }\n\n /**\n * Stops all local media tracks\n */\n public stopAllStreams(): void {\n for (const stream of this.userMediaStreams) {\n logger.log(`MediaHandler stopAllStreams() stopping (streamId=${stream.id})`);\n for (const track of stream.getTracks()) {\n track.stop();\n }\n }\n\n for (const stream of this.screensharingStreams) {\n for (const track of stream.getTracks()) {\n track.stop();\n }\n }\n\n this.userMediaStreams = [];\n this.screensharingStreams = [];\n this.localUserMediaStream = undefined;\n\n this.emit(MediaHandlerEvent.LocalStreamsChanged);\n }\n\n private getUserMediaContraints(audio: boolean, video: boolean, exactDeviceId?: boolean): MediaStreamConstraints {\n const isWebkit = !!navigator.webkitGetUserMedia;\n const deviceIdKey = exactDeviceId ? \"exact\" : \"ideal\";\n\n const audioConstraints: MediaTrackConstraints = {};\n if (this.audioInput) {\n audioConstraints.deviceId = { [deviceIdKey]: this.audioInput };\n }\n if (this.audioSettings) {\n audioConstraints.autoGainControl = { ideal: this.audioSettings.autoGainControl };\n audioConstraints.echoCancellation = { ideal: this.audioSettings.echoCancellation };\n audioConstraints.noiseSuppression = { ideal: this.audioSettings.noiseSuppression };\n }\n\n const videoConstraints: MediaTrackConstraints = {\n /* We want 640x360. Chrome will give it only if we ask exactly,\n FF refuses entirely if we ask exactly, so have to ask for ideal\n instead\n XXX: Is this still true?\n */\n width: isWebkit ? { exact: 640 } : { ideal: 640 },\n height: isWebkit ? { exact: 360 } : { ideal: 360 },\n };\n if (this.videoInput) {\n videoConstraints.deviceId = { [deviceIdKey]: this.videoInput };\n }\n\n return {\n audio: audio ? audioConstraints : false,\n video: video ? videoConstraints : false,\n };\n }\n\n private getScreenshareContraints(opts: IScreensharingOpts): MediaStreamConstraints {\n const { desktopCapturerSourceId, audio } = opts;\n if (desktopCapturerSourceId) {\n return {\n audio: audio ?? false,\n video: {\n mandatory: {\n chromeMediaSource: \"desktop\",\n chromeMediaSourceId: desktopCapturerSourceId,\n },\n },\n };\n } else {\n return {\n audio: audio ?? false,\n video: true,\n };\n }\n }\n}\n"],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"file":"mediaHandler.js","names":["TypedEventEmitter","GroupCallType","GroupCallState","logger","MediaHandlerEvent","MediaHandler","constructor","client","_defineProperty","restoreMediaSettings","audioInput","videoInput","setAudioInput","deviceId","_this","_asyncToGenerator","info","concat","updateLocalUsermediaStreams","setAudioSettings","opts","_this2","JSON","stringify","audioSettings","Object","assign","setVideoInput","_this3","setMediaInputs","_this4","log","_this5","userMediaStreams","length","callMediaStreamParams","Map","call","callEventHandler","calls","values","set","callId","audio","hasLocalUserMediaAudioTrack","video","hasLocalUserMediaVideoTrack","stream","id","track","getTracks","stop","localUserMediaStream","undefined","callHasEnded","has","_ref","get","getUserMediaStream","updateLocalUsermediaStream","groupCall","groupCallEventHandler","groupCalls","localCallFeed","groupCallId","type","Video","state","Ended","emit","LocalStreamsChanged","hasAudioDevice","devices","navigator","mediaDevices","enumerateDevices","filter","device","kind","err","hasVideoDevice","_arguments","arguments","_this6","reusable","getMediaStreamPromise","then","getUserMediaStreamInternal","_this7","shouldRequestAudio","shouldRequestVideo","canReuseStream","_this7$localUserMedia","_this7$localUserMedia2","getAudioTracks","getVideoTracks","getSettings","constraints","getUserMediaContraints","getUserMedia","e","warn","settings","_this7$localUserMedia3","clone","removeTrack","push","stopUserMediaStream","mediaStream","index","indexOf","debug","splice","_this$localUserMediaS","getTrackById","getScreensharingStream","_arguments2","_this8","screensharingStreams","screenshareConstraints","getScreenshareContraints","desktopCapturerSourceId","getDisplayMedia","matchingStream","stopScreensharingStream","stopAllStreams","exactDeviceId","isWebkit","webkitGetUserMedia","deviceIdKey","audioConstraints","autoGainControl","ideal","echoCancellation","noiseSuppression","videoConstraints","width","exact","height","mandatory","chromeMediaSource","chromeMediaSourceId"],"sources":["../../src/webrtc/mediaHandler.ts"],"sourcesContent":["/*\nCopyright 2015, 2016 OpenMarket Ltd\nCopyright 2017 New Vector Ltd\nCopyright 2019, 2020 The Matrix.org Foundation C.I.C.\nCopyright 2021 - 2022 Šimon Brandner <simon.bra.ag@gmail.com>\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n*/\n\nimport { TypedEventEmitter } from \"../models/typed-event-emitter.ts\";\nimport { GroupCallType, GroupCallState } from \"../webrtc/groupCall.ts\";\nimport { logger } from \"../logger.ts\";\nimport { type MatrixClient } from \"../client.ts\";\n\nexport enum MediaHandlerEvent {\n LocalStreamsChanged = \"local_streams_changed\",\n}\n\nexport type MediaHandlerEventHandlerMap = {\n [MediaHandlerEvent.LocalStreamsChanged]: () => void;\n};\n\nexport interface IScreensharingOpts {\n /**\n * sourceId for Electron DesktopCapturer\n */\n desktopCapturerSourceId?: string;\n audio?: boolean;\n // For electron screen capture, there are very few options for detecting electron\n // apart from inspecting the user agent or just trying getDisplayMedia() and\n // catching the failure, so we do the latter - this flag tells the function to just\n // throw an error so we can catch it in this case, rather than logging and emitting.\n throwOnFail?: boolean;\n}\n\nexport interface AudioSettings {\n autoGainControl: boolean;\n echoCancellation: boolean;\n noiseSuppression: boolean;\n}\n\nexport class MediaHandler extends TypedEventEmitter<\n MediaHandlerEvent.LocalStreamsChanged,\n MediaHandlerEventHandlerMap\n> {\n private audioInput?: string;\n private audioSettings?: AudioSettings;\n private videoInput?: string;\n private localUserMediaStream?: MediaStream;\n public userMediaStreams: MediaStream[] = [];\n public screensharingStreams: MediaStream[] = [];\n\n // Promise chain to serialise calls to getMediaStream\n private getMediaStreamPromise?: Promise<MediaStream>;\n\n public constructor(private client: MatrixClient) {\n super();\n }\n\n public restoreMediaSettings(audioInput: string, videoInput: string): void {\n this.audioInput = audioInput;\n this.videoInput = videoInput;\n }\n\n /**\n * Set an audio input device to use for MatrixCalls\n * @param deviceId - the identifier for the device\n * undefined treated as unset\n */\n public async setAudioInput(deviceId: string): Promise<void> {\n logger.info(`MediaHandler setAudioInput() running (deviceId=${deviceId})`);\n\n if (this.audioInput === deviceId) return;\n\n this.audioInput = deviceId;\n await this.updateLocalUsermediaStreams();\n }\n\n /**\n * Set audio settings for MatrixCalls\n * @param opts - audio options to set\n */\n public async setAudioSettings(opts: AudioSettings): Promise<void> {\n logger.info(`MediaHandler setAudioSettings() running (opts=${JSON.stringify(opts)})`);\n\n this.audioSettings = Object.assign({}, opts) as AudioSettings;\n await this.updateLocalUsermediaStreams();\n }\n\n /**\n * Set a video input device to use for MatrixCalls\n * @param deviceId - the identifier for the device\n * undefined treated as unset\n */\n public async setVideoInput(deviceId: string): Promise<void> {\n logger.info(`MediaHandler setVideoInput() running (deviceId=${deviceId})`);\n\n if (this.videoInput === deviceId) return;\n\n this.videoInput = deviceId;\n await this.updateLocalUsermediaStreams();\n }\n\n /**\n * Set media input devices to use for MatrixCalls\n * @param audioInput - the identifier for the audio device\n * @param videoInput - the identifier for the video device\n * undefined treated as unset\n */\n public async setMediaInputs(audioInput: string, videoInput: string): Promise<void> {\n logger.log(`MediaHandler setMediaInputs() running (audioInput: ${audioInput} videoInput: ${videoInput})`);\n this.audioInput = audioInput;\n this.videoInput = videoInput;\n await this.updateLocalUsermediaStreams();\n }\n\n /*\n * Requests new usermedia streams and replace the old ones\n */\n public async updateLocalUsermediaStreams(): Promise<void> {\n if (this.userMediaStreams.length === 0) return;\n\n const callMediaStreamParams: Map<string, { audio: boolean; video: boolean }> = new Map();\n for (const call of this.client.callEventHandler!.calls.values()) {\n callMediaStreamParams.set(call.callId, {\n audio: call.hasLocalUserMediaAudioTrack,\n video: call.hasLocalUserMediaVideoTrack,\n });\n }\n\n for (const stream of this.userMediaStreams) {\n logger.log(`MediaHandler updateLocalUsermediaStreams() stopping all tracks (streamId=${stream.id})`);\n for (const track of stream.getTracks()) {\n track.stop();\n }\n }\n\n this.userMediaStreams = [];\n this.localUserMediaStream = undefined;\n\n for (const call of this.client.callEventHandler!.calls.values()) {\n if (call.callHasEnded() || !callMediaStreamParams.has(call.callId)) {\n continue;\n }\n\n const { audio, video } = callMediaStreamParams.get(call.callId)!;\n\n logger.log(\n `MediaHandler updateLocalUsermediaStreams() calling getUserMediaStream() (callId=${call.callId})`,\n );\n const stream = await this.getUserMediaStream(audio, video);\n\n if (call.callHasEnded()) {\n continue;\n }\n\n await call.updateLocalUsermediaStream(stream);\n }\n\n for (const groupCall of this.client.groupCallEventHandler!.groupCalls.values()) {\n if (!groupCall.localCallFeed) {\n continue;\n }\n\n logger.log(\n `MediaHandler updateLocalUsermediaStreams() calling getUserMediaStream() (groupCallId=${groupCall.groupCallId})`,\n );\n const stream = await this.getUserMediaStream(true, groupCall.type === GroupCallType.Video);\n\n if (groupCall.state === GroupCallState.Ended) {\n continue;\n }\n\n await groupCall.updateLocalUsermediaStream(stream);\n }\n\n this.emit(MediaHandlerEvent.LocalStreamsChanged);\n }\n\n public async hasAudioDevice(): Promise<boolean> {\n try {\n const devices = await navigator.mediaDevices.enumerateDevices();\n return devices.filter((device) => device.kind === \"audioinput\").length > 0;\n } catch (err) {\n logger.log(`MediaHandler hasAudioDevice() calling navigator.mediaDevices.enumerateDevices with error`, err);\n return false;\n }\n }\n\n public async hasVideoDevice(): Promise<boolean> {\n try {\n const devices = await navigator.mediaDevices.enumerateDevices();\n return devices.filter((device) => device.kind === \"videoinput\").length > 0;\n } catch (err) {\n logger.log(`MediaHandler hasVideoDevice() calling navigator.mediaDevices.enumerateDevices with error`, err);\n return false;\n }\n }\n\n /**\n * @param audio - should have an audio track\n * @param video - should have a video track\n * @param reusable - is allowed to be reused by the MediaHandler\n * @returns based on passed parameters\n */\n public async getUserMediaStream(audio: boolean, video: boolean, reusable = true): Promise<MediaStream> {\n // Serialise calls, othertwise we can't sensibly re-use the stream\n if (this.getMediaStreamPromise) {\n this.getMediaStreamPromise = this.getMediaStreamPromise.then(() => {\n return this.getUserMediaStreamInternal(audio, video, reusable);\n });\n } else {\n this.getMediaStreamPromise = this.getUserMediaStreamInternal(audio, video, reusable);\n }\n\n return this.getMediaStreamPromise;\n }\n\n private async getUserMediaStreamInternal(audio: boolean, video: boolean, reusable: boolean): Promise<MediaStream> {\n const shouldRequestAudio = audio && (await this.hasAudioDevice());\n const shouldRequestVideo = video && (await this.hasVideoDevice());\n\n let stream: MediaStream;\n\n let canReuseStream = true;\n if (this.localUserMediaStream) {\n // This figures out if we can reuse the current localUsermediaStream\n // based on whether or not the \"mute state\" (presence of tracks of a\n // given kind) matches what is being requested\n if (shouldRequestAudio !== this.localUserMediaStream.getAudioTracks().length > 0) {\n canReuseStream = false;\n }\n if (shouldRequestVideo !== this.localUserMediaStream.getVideoTracks().length > 0) {\n canReuseStream = false;\n }\n\n // This code checks that the device ID is the same as the localUserMediaStream stream, but we update\n // the localUserMediaStream whenever the device ID changes (apart from when restoring) so it's not\n // clear why this would ever be different, unless there's a race.\n if (\n shouldRequestAudio &&\n this.localUserMediaStream.getAudioTracks()[0]?.getSettings()?.deviceId !== this.audioInput\n ) {\n canReuseStream = false;\n }\n if (\n shouldRequestVideo &&\n this.localUserMediaStream.getVideoTracks()[0]?.getSettings()?.deviceId !== this.videoInput\n ) {\n canReuseStream = false;\n }\n } else {\n canReuseStream = false;\n }\n\n if (!canReuseStream) {\n let constraints: MediaStreamConstraints;\n try {\n // Not specifying exact for deviceId means switching devices does not always work,\n // try with exact and fallback to ideal if it fails\n constraints = this.getUserMediaContraints(shouldRequestAudio, shouldRequestVideo, true);\n stream = await navigator.mediaDevices.getUserMedia(constraints);\n } catch (e) {\n logger.warn(\n `MediaHandler getUserMediaStreamInternal() error (e=${e}), retrying without exact deviceId`,\n );\n constraints = this.getUserMediaContraints(shouldRequestAudio, shouldRequestVideo, false);\n stream = await navigator.mediaDevices.getUserMedia(constraints);\n }\n logger.log(\n `MediaHandler getUserMediaStreamInternal() calling getUserMediaStream (streamId=${\n stream.id\n }, shouldRequestAudio=${shouldRequestAudio}, shouldRequestVideo=${shouldRequestVideo}, constraints=${JSON.stringify(\n constraints,\n )})`,\n );\n\n for (const track of stream.getTracks()) {\n const settings = track.getSettings();\n\n if (track.kind === \"audio\") {\n this.audioInput = settings.deviceId!;\n } else if (track.kind === \"video\") {\n this.videoInput = settings.deviceId!;\n }\n }\n\n if (reusable) {\n this.localUserMediaStream = stream;\n }\n } else {\n stream = this.localUserMediaStream!.clone();\n logger.log(\n `MediaHandler getUserMediaStreamInternal() cloning (oldStreamId=${this.localUserMediaStream?.id} newStreamId=${stream.id} shouldRequestAudio=${shouldRequestAudio} shouldRequestVideo=${shouldRequestVideo})`,\n );\n\n if (!shouldRequestAudio) {\n for (const track of stream.getAudioTracks()) {\n stream.removeTrack(track);\n }\n }\n\n if (!shouldRequestVideo) {\n for (const track of stream.getVideoTracks()) {\n stream.removeTrack(track);\n }\n }\n }\n\n if (reusable) {\n this.userMediaStreams.push(stream);\n }\n\n this.emit(MediaHandlerEvent.LocalStreamsChanged);\n\n return stream;\n }\n\n /**\n * Stops all tracks on the provided usermedia stream\n */\n public stopUserMediaStream(mediaStream: MediaStream): void {\n logger.log(`MediaHandler stopUserMediaStream() stopping (streamId=${mediaStream.id})`);\n for (const track of mediaStream.getTracks()) {\n track.stop();\n }\n\n const index = this.userMediaStreams.indexOf(mediaStream);\n\n if (index !== -1) {\n logger.debug(\n `MediaHandler stopUserMediaStream() splicing usermedia stream out stream array (streamId=${mediaStream.id})`,\n mediaStream.id,\n );\n this.userMediaStreams.splice(index, 1);\n }\n\n this.emit(MediaHandlerEvent.LocalStreamsChanged);\n\n if (this.localUserMediaStream === mediaStream) {\n // if we have this stream cahced, remove it, because we've stopped it\n this.localUserMediaStream = undefined;\n } else {\n // If it's not the same stream. remove any tracks from the cached stream that\n // we have just stopped, and if we do stop any, call the same method on the\n // cached stream too in order to stop all its tracks (in case they are different)\n // and un-cache it.\n for (const track of mediaStream.getTracks()) {\n if (this.localUserMediaStream?.getTrackById(track.id)) {\n this.stopUserMediaStream(this.localUserMediaStream);\n break;\n }\n }\n }\n }\n\n /**\n * @param opts - screensharing stream options\n * @param reusable - is allowed to be reused by the MediaHandler\n * @returns based on passed parameters\n */\n public async getScreensharingStream(opts: IScreensharingOpts = {}, reusable = true): Promise<MediaStream> {\n let stream: MediaStream;\n\n if (this.screensharingStreams.length === 0) {\n const screenshareConstraints = this.getScreenshareContraints(opts);\n\n if (opts.desktopCapturerSourceId) {\n // We are using Electron\n logger.debug(\n `MediaHandler getScreensharingStream() calling getUserMedia() (opts=${JSON.stringify(opts)})`,\n );\n stream = await navigator.mediaDevices.getUserMedia(screenshareConstraints);\n } else {\n // We are not using Electron\n logger.debug(\n `MediaHandler getScreensharingStream() calling getDisplayMedia() (opts=${JSON.stringify(opts)})`,\n );\n stream = await navigator.mediaDevices.getDisplayMedia(screenshareConstraints);\n }\n } else {\n const matchingStream = this.screensharingStreams[this.screensharingStreams.length - 1];\n logger.log(`MediaHandler getScreensharingStream() cloning (streamId=${matchingStream.id})`);\n stream = matchingStream.clone();\n }\n\n if (reusable) {\n this.screensharingStreams.push(stream);\n }\n\n this.emit(MediaHandlerEvent.LocalStreamsChanged);\n\n return stream;\n }\n\n /**\n * Stops all tracks on the provided screensharing stream\n */\n public stopScreensharingStream(mediaStream: MediaStream): void {\n logger.debug(`MediaHandler stopScreensharingStream() stopping stream (streamId=${mediaStream.id})`);\n for (const track of mediaStream.getTracks()) {\n track.stop();\n }\n\n const index = this.screensharingStreams.indexOf(mediaStream);\n\n if (index !== -1) {\n logger.debug(`MediaHandler stopScreensharingStream() splicing stream out (streamId=${mediaStream.id})`);\n this.screensharingStreams.splice(index, 1);\n }\n\n this.emit(MediaHandlerEvent.LocalStreamsChanged);\n }\n\n /**\n * Stops all local media tracks\n */\n public stopAllStreams(): void {\n for (const stream of this.userMediaStreams) {\n logger.log(`MediaHandler stopAllStreams() stopping (streamId=${stream.id})`);\n for (const track of stream.getTracks()) {\n track.stop();\n }\n }\n\n for (const stream of this.screensharingStreams) {\n for (const track of stream.getTracks()) {\n track.stop();\n }\n }\n\n this.userMediaStreams = [];\n this.screensharingStreams = [];\n this.localUserMediaStream = undefined;\n\n this.emit(MediaHandlerEvent.LocalStreamsChanged);\n }\n\n private getUserMediaContraints(audio: boolean, video: boolean, exactDeviceId?: boolean): MediaStreamConstraints {\n const isWebkit = !!navigator.webkitGetUserMedia;\n const deviceIdKey = exactDeviceId ? \"exact\" : \"ideal\";\n\n const audioConstraints: MediaTrackConstraints = {};\n if (this.audioInput) {\n audioConstraints.deviceId = { [deviceIdKey]: this.audioInput };\n }\n if (this.audioSettings) {\n audioConstraints.autoGainControl = { ideal: this.audioSettings.autoGainControl };\n audioConstraints.echoCancellation = { ideal: this.audioSettings.echoCancellation };\n audioConstraints.noiseSuppression = { ideal: this.audioSettings.noiseSuppression };\n }\n\n const videoConstraints: MediaTrackConstraints = {\n /* We want 640x360. Chrome will give it only if we ask exactly,\n FF refuses entirely if we ask exactly, so have to ask for ideal\n instead\n XXX: Is this still true?\n */\n width: isWebkit ? { exact: 640 } : { ideal: 640 },\n height: isWebkit ? { exact: 360 } : { ideal: 360 },\n };\n if (this.videoInput) {\n videoConstraints.deviceId = { [deviceIdKey]: this.videoInput };\n }\n\n return {\n audio: audio ? audioConstraints : false,\n video: video ? videoConstraints : false,\n };\n }\n\n private getScreenshareContraints(opts: IScreensharingOpts): MediaStreamConstraints {\n const { desktopCapturerSourceId, audio } = opts;\n if (desktopCapturerSourceId) {\n return {\n audio: audio ?? false,\n video: {\n mandatory: {\n chromeMediaSource: \"desktop\",\n chromeMediaSourceId: desktopCapturerSourceId,\n },\n },\n };\n } else {\n return {\n audio: audio ?? false,\n video: true,\n };\n }\n }\n}\n"],"mappings":"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","ignoreList":[]}
@@ -32,13 +32,16 @@ import { CallFeedStatsReporter } from "./callFeedStatsReporter.js";
32
32
  export class CallStatsReportGatherer {
33
33
  constructor(callId, opponentMemberId, pc, emitter) {
34
34
  var isFocus = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : true;
35
- _defineProperty(this, "isActive", true);
36
- _defineProperty(this, "connectionStats", new ConnectionStats());
37
35
  this.callId = callId;
38
36
  this.opponentMemberId = opponentMemberId;
39
37
  this.pc = pc;
40
38
  this.emitter = emitter;
41
39
  this.isFocus = isFocus;
40
+ _defineProperty(this, "isActive", true);
41
+ _defineProperty(this, "previousStatsReport", void 0);
42
+ _defineProperty(this, "currentStatsReport", void 0);
43
+ _defineProperty(this, "connectionStats", new ConnectionStats());
44
+ _defineProperty(this, "trackStats", void 0);
42
45
  pc.addEventListener("signalingstatechange", this.onSignalStateChange.bind(this));
43
46
  this.trackStats = new MediaTrackStatsHandler(new MediaSsrcHandler(), new MediaTrackHandler(pc));
44
47
  }
@@ -1 +1 @@
1
- {"version":3,"file":"callStatsReportGatherer.js","names":["ConnectionStats","ConnectionStatsBuilder","TransportStatsBuilder","MediaSsrcHandler","MediaTrackHandler","MediaTrackStatsHandler","TrackStatsBuilder","ConnectionStatsReportBuilder","ValueFormatter","logger","CallFeedStatsReporter","CallStatsReportGatherer","constructor","callId","opponentMemberId","pc","emitter","isFocus","arguments","length","undefined","_defineProperty","addEventListener","onSignalStateChange","bind","trackStats","processStats","groupCallId","localUserId","_this","_asyncToGenerator","summary","isFirstCollection","previousStatsReport","receivedMedia","receivedAudioMedia","receivedVideoMedia","audioTrackSummary","count","muted","maxPacketLoss","maxJitter","concealedAudio","totalAudio","videoTrackSummary","isActive","statsPromise","getStats","then","report","_this$connectionStats","_this$connectionStats2","currentStatsReport","result","processStatsReport","error","handleError","connectionStats","bitrate","download","audio","video","trackSummary","buildTrackSummary","Array","from","getTrack2stats","values","_objectSpread","catch","Promise","resolve","_this$currentStatsRep","byteSentStatsReport","Map","forEach","now","before","get","id","type","nominated","state","bandwidth","buildBandwidthReport","transport","buildReport","findTrack2Stats","buildPacketsLost","buildFramerateResolution","buildBitrateReceived","ts","findTransceiverByTrackId","trackId","setTrackStatsState","buildJitter","buildAudioConcealment","set","getNonNegativeValue","bytesSent","buildBitrateSend","buildCodec","kind","remoteSource","findLocalVideoTrackStats","calculateSimulcastFramerate","mediaTrackHandler","getActiveSimulcastStreams","emitByteSendReport","emitCallFeedReport","buildCallFeedReport","processAndEmitConnectionStatsReport","setActive","getActive","warn","concat","build","packetLoss","emitConnectionStatsReport","stopProcessingStats","signalingState","currentRemoteDescription","mediaSsrcHandler","parse","sdp","currentLocalDescription","setOpponentMemberId"],"sources":["../../../src/webrtc/stats/callStatsReportGatherer.ts"],"sourcesContent":["/*\nCopyright 2023 The Matrix.org Foundation C.I.C.\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n*/\n\nimport { ConnectionStats } from \"./connectionStats.ts\";\nimport { type StatsReportEmitter } from \"./statsReportEmitter.ts\";\nimport { type ByteSend, type ByteSentStatsReport, type TrackID } from \"./statsReport.ts\";\nimport { ConnectionStatsBuilder } from \"./connectionStatsBuilder.ts\";\nimport { TransportStatsBuilder } from \"./transportStatsBuilder.ts\";\nimport { MediaSsrcHandler } from \"./media/mediaSsrcHandler.ts\";\nimport { MediaTrackHandler } from \"./media/mediaTrackHandler.ts\";\nimport { MediaTrackStatsHandler } from \"./media/mediaTrackStatsHandler.ts\";\nimport { TrackStatsBuilder } from \"./trackStatsBuilder.ts\";\nimport { ConnectionStatsReportBuilder } from \"./connectionStatsReportBuilder.ts\";\nimport { ValueFormatter } from \"./valueFormatter.ts\";\nimport { type CallStatsReportSummary } from \"./callStatsReportSummary.ts\";\nimport { logger } from \"../../logger.ts\";\nimport { CallFeedStatsReporter } from \"./callFeedStatsReporter.ts\";\n\nexport class CallStatsReportGatherer {\n private isActive = true;\n private previousStatsReport: RTCStatsReport | undefined;\n private currentStatsReport: RTCStatsReport | undefined;\n private readonly connectionStats = new ConnectionStats();\n\n private readonly trackStats: MediaTrackStatsHandler;\n\n public constructor(\n public readonly callId: string,\n private opponentMemberId: string,\n private readonly pc: RTCPeerConnection,\n private readonly emitter: StatsReportEmitter,\n private readonly isFocus = true,\n ) {\n pc.addEventListener(\"signalingstatechange\", this.onSignalStateChange.bind(this));\n this.trackStats = new MediaTrackStatsHandler(new MediaSsrcHandler(), new MediaTrackHandler(pc));\n }\n\n public async processStats(groupCallId: string, localUserId: string): Promise<CallStatsReportSummary> {\n const summary = {\n isFirstCollection: this.previousStatsReport === undefined,\n receivedMedia: 0,\n receivedAudioMedia: 0,\n receivedVideoMedia: 0,\n audioTrackSummary: { count: 0, muted: 0, maxPacketLoss: 0, maxJitter: 0, concealedAudio: 0, totalAudio: 0 },\n videoTrackSummary: { count: 0, muted: 0, maxPacketLoss: 0, maxJitter: 0, concealedAudio: 0, totalAudio: 0 },\n } as CallStatsReportSummary;\n if (this.isActive) {\n const statsPromise = this.pc.getStats();\n if (typeof statsPromise?.then === \"function\") {\n return statsPromise\n .then((report) => {\n // @ts-ignore\n this.currentStatsReport = typeof report?.result === \"function\" ? report.result() : report;\n\n try {\n this.processStatsReport(groupCallId, localUserId);\n } catch (error) {\n this.handleError(error);\n return summary;\n }\n\n this.previousStatsReport = this.currentStatsReport;\n summary.receivedMedia = this.connectionStats.bitrate.download;\n summary.receivedAudioMedia = this.connectionStats.bitrate.audio?.download || 0;\n summary.receivedVideoMedia = this.connectionStats.bitrate.video?.download || 0;\n const trackSummary = TrackStatsBuilder.buildTrackSummary(\n Array.from(this.trackStats.getTrack2stats().values()),\n );\n return {\n ...summary,\n audioTrackSummary: trackSummary.audioTrackSummary,\n videoTrackSummary: trackSummary.videoTrackSummary,\n };\n })\n .catch((error) => {\n this.handleError(error);\n return summary;\n });\n }\n this.isActive = false;\n }\n return Promise.resolve(summary);\n }\n\n private processStatsReport(groupCallId: string, localUserId: string): void {\n const byteSentStatsReport: ByteSentStatsReport = new Map<TrackID, ByteSend>() as ByteSentStatsReport;\n byteSentStatsReport.callId = this.callId;\n byteSentStatsReport.opponentMemberId = this.opponentMemberId;\n\n this.currentStatsReport?.forEach((now) => {\n const before = this.previousStatsReport ? this.previousStatsReport.get(now.id) : null;\n // RTCIceCandidatePairStats - https://w3c.github.io/webrtc-stats/#candidatepair-dict*\n if (now.type === \"candidate-pair\" && now.nominated && now.state === \"succeeded\") {\n this.connectionStats.bandwidth = ConnectionStatsBuilder.buildBandwidthReport(now);\n this.connectionStats.transport = TransportStatsBuilder.buildReport(\n this.currentStatsReport,\n now,\n this.connectionStats.transport,\n this.isFocus,\n );\n\n // RTCReceivedRtpStreamStats\n // https://w3c.github.io/webrtc-stats/#receivedrtpstats-dict*\n // RTCSentRtpStreamStats\n // https://w3c.github.io/webrtc-stats/#sentrtpstats-dict*\n } else if (now.type === \"inbound-rtp\" || now.type === \"outbound-rtp\") {\n const trackStats = this.trackStats.findTrack2Stats(\n now,\n now.type === \"inbound-rtp\" ? \"remote\" : \"local\",\n );\n if (!trackStats) {\n return;\n }\n\n if (before) {\n TrackStatsBuilder.buildPacketsLost(trackStats, now, before);\n }\n\n // Get the resolution and framerate for only remote video sources here. For the local video sources,\n // 'track' stats will be used since they have the updated resolution based on the simulcast streams\n // currently being sent. Promise based getStats reports three 'outbound-rtp' streams and there will be\n // more calculations needed to determine what is the highest resolution stream sent by the client if the\n // 'outbound-rtp' stats are used.\n if (now.type === \"inbound-rtp\") {\n TrackStatsBuilder.buildFramerateResolution(trackStats, now);\n if (before) {\n TrackStatsBuilder.buildBitrateReceived(trackStats, now, before);\n }\n const ts = this.trackStats.findTransceiverByTrackId(trackStats.trackId);\n TrackStatsBuilder.setTrackStatsState(trackStats, ts);\n TrackStatsBuilder.buildJitter(trackStats, now);\n TrackStatsBuilder.buildAudioConcealment(trackStats, now);\n } else if (before) {\n byteSentStatsReport.set(trackStats.trackId, ValueFormatter.getNonNegativeValue(now.bytesSent));\n TrackStatsBuilder.buildBitrateSend(trackStats, now, before);\n }\n TrackStatsBuilder.buildCodec(this.currentStatsReport, trackStats, now);\n } else if (now.type === \"track\" && now.kind === \"video\" && !now.remoteSource) {\n const trackStats = this.trackStats.findLocalVideoTrackStats(now);\n if (!trackStats) {\n return;\n }\n TrackStatsBuilder.buildFramerateResolution(trackStats, now);\n TrackStatsBuilder.calculateSimulcastFramerate(\n trackStats,\n now,\n before,\n this.trackStats.mediaTrackHandler.getActiveSimulcastStreams(),\n );\n }\n });\n\n this.emitter.emitByteSendReport(byteSentStatsReport);\n this.emitter.emitCallFeedReport(\n CallFeedStatsReporter.buildCallFeedReport(this.callId, this.opponentMemberId, this.pc),\n );\n this.processAndEmitConnectionStatsReport();\n }\n\n public setActive(isActive: boolean): void {\n this.isActive = isActive;\n }\n\n public getActive(): boolean {\n return this.isActive;\n }\n\n private handleError(error: any): void {\n this.isActive = false;\n logger.warn(`CallStatsReportGatherer ${this.callId} processStatsReport fails and set to inactive ${error}`);\n }\n\n private processAndEmitConnectionStatsReport(): void {\n const report = ConnectionStatsReportBuilder.build(this.trackStats.getTrack2stats());\n report.callId = this.callId;\n report.opponentMemberId = this.opponentMemberId;\n\n this.connectionStats.bandwidth = report.bandwidth;\n this.connectionStats.bitrate = report.bitrate;\n this.connectionStats.packetLoss = report.packetLoss;\n\n this.emitter.emitConnectionStatsReport({\n ...report,\n transport: this.connectionStats.transport,\n });\n\n this.connectionStats.transport = [];\n }\n\n public stopProcessingStats(): void {}\n\n private onSignalStateChange(): void {\n if (this.pc.signalingState === \"stable\") {\n if (this.pc.currentRemoteDescription) {\n this.trackStats.mediaSsrcHandler.parse(this.pc.currentRemoteDescription.sdp, \"remote\");\n }\n if (this.pc.currentLocalDescription) {\n this.trackStats.mediaSsrcHandler.parse(this.pc.currentLocalDescription.sdp, \"local\");\n }\n }\n }\n\n public setOpponentMemberId(id: string): void {\n this.opponentMemberId = id;\n }\n}\n"],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"file":"callStatsReportGatherer.js","names":["ConnectionStats","ConnectionStatsBuilder","TransportStatsBuilder","MediaSsrcHandler","MediaTrackHandler","MediaTrackStatsHandler","TrackStatsBuilder","ConnectionStatsReportBuilder","ValueFormatter","logger","CallFeedStatsReporter","CallStatsReportGatherer","constructor","callId","opponentMemberId","pc","emitter","isFocus","arguments","length","undefined","_defineProperty","addEventListener","onSignalStateChange","bind","trackStats","processStats","groupCallId","localUserId","_this","_asyncToGenerator","summary","isFirstCollection","previousStatsReport","receivedMedia","receivedAudioMedia","receivedVideoMedia","audioTrackSummary","count","muted","maxPacketLoss","maxJitter","concealedAudio","totalAudio","videoTrackSummary","isActive","statsPromise","getStats","then","report","_this$connectionStats","_this$connectionStats2","currentStatsReport","result","processStatsReport","error","handleError","connectionStats","bitrate","download","audio","video","trackSummary","buildTrackSummary","Array","from","getTrack2stats","values","_objectSpread","catch","Promise","resolve","_this$currentStatsRep","byteSentStatsReport","Map","forEach","now","before","get","id","type","nominated","state","bandwidth","buildBandwidthReport","transport","buildReport","findTrack2Stats","buildPacketsLost","buildFramerateResolution","buildBitrateReceived","ts","findTransceiverByTrackId","trackId","setTrackStatsState","buildJitter","buildAudioConcealment","set","getNonNegativeValue","bytesSent","buildBitrateSend","buildCodec","kind","remoteSource","findLocalVideoTrackStats","calculateSimulcastFramerate","mediaTrackHandler","getActiveSimulcastStreams","emitByteSendReport","emitCallFeedReport","buildCallFeedReport","processAndEmitConnectionStatsReport","setActive","getActive","warn","concat","build","packetLoss","emitConnectionStatsReport","stopProcessingStats","signalingState","currentRemoteDescription","mediaSsrcHandler","parse","sdp","currentLocalDescription","setOpponentMemberId"],"sources":["../../../src/webrtc/stats/callStatsReportGatherer.ts"],"sourcesContent":["/*\nCopyright 2023 The Matrix.org Foundation C.I.C.\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n*/\n\nimport { ConnectionStats } from \"./connectionStats.ts\";\nimport { type StatsReportEmitter } from \"./statsReportEmitter.ts\";\nimport { type ByteSend, type ByteSentStatsReport, type TrackID } from \"./statsReport.ts\";\nimport { ConnectionStatsBuilder } from \"./connectionStatsBuilder.ts\";\nimport { TransportStatsBuilder } from \"./transportStatsBuilder.ts\";\nimport { MediaSsrcHandler } from \"./media/mediaSsrcHandler.ts\";\nimport { MediaTrackHandler } from \"./media/mediaTrackHandler.ts\";\nimport { MediaTrackStatsHandler } from \"./media/mediaTrackStatsHandler.ts\";\nimport { TrackStatsBuilder } from \"./trackStatsBuilder.ts\";\nimport { ConnectionStatsReportBuilder } from \"./connectionStatsReportBuilder.ts\";\nimport { ValueFormatter } from \"./valueFormatter.ts\";\nimport { type CallStatsReportSummary } from \"./callStatsReportSummary.ts\";\nimport { logger } from \"../../logger.ts\";\nimport { CallFeedStatsReporter } from \"./callFeedStatsReporter.ts\";\n\nexport class CallStatsReportGatherer {\n private isActive = true;\n private previousStatsReport: RTCStatsReport | undefined;\n private currentStatsReport: RTCStatsReport | undefined;\n private readonly connectionStats = new ConnectionStats();\n\n private readonly trackStats: MediaTrackStatsHandler;\n\n public constructor(\n public readonly callId: string,\n private opponentMemberId: string,\n private readonly pc: RTCPeerConnection,\n private readonly emitter: StatsReportEmitter,\n private readonly isFocus = true,\n ) {\n pc.addEventListener(\"signalingstatechange\", this.onSignalStateChange.bind(this));\n this.trackStats = new MediaTrackStatsHandler(new MediaSsrcHandler(), new MediaTrackHandler(pc));\n }\n\n public async processStats(groupCallId: string, localUserId: string): Promise<CallStatsReportSummary> {\n const summary = {\n isFirstCollection: this.previousStatsReport === undefined,\n receivedMedia: 0,\n receivedAudioMedia: 0,\n receivedVideoMedia: 0,\n audioTrackSummary: { count: 0, muted: 0, maxPacketLoss: 0, maxJitter: 0, concealedAudio: 0, totalAudio: 0 },\n videoTrackSummary: { count: 0, muted: 0, maxPacketLoss: 0, maxJitter: 0, concealedAudio: 0, totalAudio: 0 },\n } as CallStatsReportSummary;\n if (this.isActive) {\n const statsPromise = this.pc.getStats();\n if (typeof statsPromise?.then === \"function\") {\n return statsPromise\n .then((report) => {\n // @ts-ignore\n this.currentStatsReport = typeof report?.result === \"function\" ? report.result() : report;\n\n try {\n this.processStatsReport(groupCallId, localUserId);\n } catch (error) {\n this.handleError(error);\n return summary;\n }\n\n this.previousStatsReport = this.currentStatsReport;\n summary.receivedMedia = this.connectionStats.bitrate.download;\n summary.receivedAudioMedia = this.connectionStats.bitrate.audio?.download || 0;\n summary.receivedVideoMedia = this.connectionStats.bitrate.video?.download || 0;\n const trackSummary = TrackStatsBuilder.buildTrackSummary(\n Array.from(this.trackStats.getTrack2stats().values()),\n );\n return {\n ...summary,\n audioTrackSummary: trackSummary.audioTrackSummary,\n videoTrackSummary: trackSummary.videoTrackSummary,\n };\n })\n .catch((error) => {\n this.handleError(error);\n return summary;\n });\n }\n this.isActive = false;\n }\n return Promise.resolve(summary);\n }\n\n private processStatsReport(groupCallId: string, localUserId: string): void {\n const byteSentStatsReport: ByteSentStatsReport = new Map<TrackID, ByteSend>() as ByteSentStatsReport;\n byteSentStatsReport.callId = this.callId;\n byteSentStatsReport.opponentMemberId = this.opponentMemberId;\n\n this.currentStatsReport?.forEach((now) => {\n const before = this.previousStatsReport ? this.previousStatsReport.get(now.id) : null;\n // RTCIceCandidatePairStats - https://w3c.github.io/webrtc-stats/#candidatepair-dict*\n if (now.type === \"candidate-pair\" && now.nominated && now.state === \"succeeded\") {\n this.connectionStats.bandwidth = ConnectionStatsBuilder.buildBandwidthReport(now);\n this.connectionStats.transport = TransportStatsBuilder.buildReport(\n this.currentStatsReport,\n now,\n this.connectionStats.transport,\n this.isFocus,\n );\n\n // RTCReceivedRtpStreamStats\n // https://w3c.github.io/webrtc-stats/#receivedrtpstats-dict*\n // RTCSentRtpStreamStats\n // https://w3c.github.io/webrtc-stats/#sentrtpstats-dict*\n } else if (now.type === \"inbound-rtp\" || now.type === \"outbound-rtp\") {\n const trackStats = this.trackStats.findTrack2Stats(\n now,\n now.type === \"inbound-rtp\" ? \"remote\" : \"local\",\n );\n if (!trackStats) {\n return;\n }\n\n if (before) {\n TrackStatsBuilder.buildPacketsLost(trackStats, now, before);\n }\n\n // Get the resolution and framerate for only remote video sources here. For the local video sources,\n // 'track' stats will be used since they have the updated resolution based on the simulcast streams\n // currently being sent. Promise based getStats reports three 'outbound-rtp' streams and there will be\n // more calculations needed to determine what is the highest resolution stream sent by the client if the\n // 'outbound-rtp' stats are used.\n if (now.type === \"inbound-rtp\") {\n TrackStatsBuilder.buildFramerateResolution(trackStats, now);\n if (before) {\n TrackStatsBuilder.buildBitrateReceived(trackStats, now, before);\n }\n const ts = this.trackStats.findTransceiverByTrackId(trackStats.trackId);\n TrackStatsBuilder.setTrackStatsState(trackStats, ts);\n TrackStatsBuilder.buildJitter(trackStats, now);\n TrackStatsBuilder.buildAudioConcealment(trackStats, now);\n } else if (before) {\n byteSentStatsReport.set(trackStats.trackId, ValueFormatter.getNonNegativeValue(now.bytesSent));\n TrackStatsBuilder.buildBitrateSend(trackStats, now, before);\n }\n TrackStatsBuilder.buildCodec(this.currentStatsReport, trackStats, now);\n } else if (now.type === \"track\" && now.kind === \"video\" && !now.remoteSource) {\n const trackStats = this.trackStats.findLocalVideoTrackStats(now);\n if (!trackStats) {\n return;\n }\n TrackStatsBuilder.buildFramerateResolution(trackStats, now);\n TrackStatsBuilder.calculateSimulcastFramerate(\n trackStats,\n now,\n before,\n this.trackStats.mediaTrackHandler.getActiveSimulcastStreams(),\n );\n }\n });\n\n this.emitter.emitByteSendReport(byteSentStatsReport);\n this.emitter.emitCallFeedReport(\n CallFeedStatsReporter.buildCallFeedReport(this.callId, this.opponentMemberId, this.pc),\n );\n this.processAndEmitConnectionStatsReport();\n }\n\n public setActive(isActive: boolean): void {\n this.isActive = isActive;\n }\n\n public getActive(): boolean {\n return this.isActive;\n }\n\n private handleError(error: any): void {\n this.isActive = false;\n logger.warn(`CallStatsReportGatherer ${this.callId} processStatsReport fails and set to inactive ${error}`);\n }\n\n private processAndEmitConnectionStatsReport(): void {\n const report = ConnectionStatsReportBuilder.build(this.trackStats.getTrack2stats());\n report.callId = this.callId;\n report.opponentMemberId = this.opponentMemberId;\n\n this.connectionStats.bandwidth = report.bandwidth;\n this.connectionStats.bitrate = report.bitrate;\n this.connectionStats.packetLoss = report.packetLoss;\n\n this.emitter.emitConnectionStatsReport({\n ...report,\n transport: this.connectionStats.transport,\n });\n\n this.connectionStats.transport = [];\n }\n\n public stopProcessingStats(): void {}\n\n private onSignalStateChange(): void {\n if (this.pc.signalingState === \"stable\") {\n if (this.pc.currentRemoteDescription) {\n this.trackStats.mediaSsrcHandler.parse(this.pc.currentRemoteDescription.sdp, \"remote\");\n }\n if (this.pc.currentLocalDescription) {\n this.trackStats.mediaSsrcHandler.parse(this.pc.currentLocalDescription.sdp, \"local\");\n }\n }\n }\n\n public setOpponentMemberId(id: string): void {\n this.opponentMemberId = id;\n }\n}\n"],"mappings":"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","ignoreList":[]}
@@ -21,12 +21,13 @@ import { logger } from "../../logger.js";
21
21
  export class GroupCallStats {
22
22
  constructor(groupCallId, userId) {
23
23
  var interval = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 10000;
24
- _defineProperty(this, "gatherers", new Map());
25
- _defineProperty(this, "reports", new StatsReportEmitter());
26
- _defineProperty(this, "summaryStatsReportGatherer", new SummaryStatsReportGatherer(this.reports));
27
24
  this.groupCallId = groupCallId;
28
25
  this.userId = userId;
29
26
  this.interval = interval;
27
+ _defineProperty(this, "timer", void 0);
28
+ _defineProperty(this, "gatherers", new Map());
29
+ _defineProperty(this, "reports", new StatsReportEmitter());
30
+ _defineProperty(this, "summaryStatsReportGatherer", new SummaryStatsReportGatherer(this.reports));
30
31
  }
31
32
  start() {
32
33
  if (this.timer === undefined && this.interval > 0) {
@@ -1 +1 @@
1
- {"version":3,"file":"groupCallStats.js","names":["CallStatsReportGatherer","StatsReportEmitter","SummaryStatsReportGatherer","logger","GroupCallStats","constructor","groupCallId","userId","interval","arguments","length","undefined","_defineProperty","Map","reports","start","timer","setInterval","processStats","stop","clearInterval","gatherers","forEach","c","stopProcessingStats","hasStatsReportGatherer","callId","has","addStatsReportGatherer","opponentMemberId","peerConnection","set","removeStatsReportGatherer","delete","getStatsReportGatherer","get","updateOpponentMember","opponentMember","_this$getStatsReportG","setOpponentMemberId","summary","push","Promise","all","then","s","summaryStatsReportGatherer","build","catch","err","error"],"sources":["../../../src/webrtc/stats/groupCallStats.ts"],"sourcesContent":["/*\nCopyright 2023 The Matrix.org Foundation C.I.C.\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n*/\nimport { CallStatsReportGatherer } from \"./callStatsReportGatherer.ts\";\nimport { StatsReportEmitter } from \"./statsReportEmitter.ts\";\nimport { type CallStatsReportSummary } from \"./callStatsReportSummary.ts\";\nimport { SummaryStatsReportGatherer } from \"./summaryStatsReportGatherer.ts\";\nimport { logger } from \"../../logger.ts\";\n\nexport class GroupCallStats {\n private timer: undefined | ReturnType<typeof setTimeout>;\n private readonly gatherers: Map<string, CallStatsReportGatherer> = new Map<string, CallStatsReportGatherer>();\n public readonly reports = new StatsReportEmitter();\n private readonly summaryStatsReportGatherer = new SummaryStatsReportGatherer(this.reports);\n\n public constructor(\n private groupCallId: string,\n private userId: string,\n private interval: number = 10000,\n ) {}\n\n public start(): void {\n if (this.timer === undefined && this.interval > 0) {\n this.timer = setInterval(() => {\n this.processStats();\n }, this.interval);\n }\n }\n\n public stop(): void {\n if (this.timer !== undefined) {\n clearInterval(this.timer);\n this.gatherers.forEach((c) => c.stopProcessingStats());\n }\n }\n\n public hasStatsReportGatherer(callId: string): boolean {\n return this.gatherers.has(callId);\n }\n\n public addStatsReportGatherer(\n callId: string,\n opponentMemberId: string,\n peerConnection: RTCPeerConnection,\n ): boolean {\n if (this.hasStatsReportGatherer(callId)) {\n return false;\n }\n this.gatherers.set(callId, new CallStatsReportGatherer(callId, opponentMemberId, peerConnection, this.reports));\n return true;\n }\n\n public removeStatsReportGatherer(callId: string): boolean {\n return this.gatherers.delete(callId);\n }\n\n public getStatsReportGatherer(callId: string): CallStatsReportGatherer | undefined {\n return this.hasStatsReportGatherer(callId) ? this.gatherers.get(callId) : undefined;\n }\n\n public updateOpponentMember(callId: string, opponentMember: string): void {\n this.getStatsReportGatherer(callId)?.setOpponentMemberId(opponentMember);\n }\n\n private processStats(): void {\n const summary: Promise<CallStatsReportSummary>[] = [];\n this.gatherers.forEach((c) => {\n summary.push(c.processStats(this.groupCallId, this.userId));\n });\n\n Promise.all(summary)\n .then((s: Awaited<CallStatsReportSummary>[]) => this.summaryStatsReportGatherer.build(s))\n .catch((err) => {\n logger.error(\"Could not build summary stats report\", err);\n });\n }\n\n public setInterval(interval: number): void {\n this.interval = interval;\n }\n}\n"],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"file":"groupCallStats.js","names":["CallStatsReportGatherer","StatsReportEmitter","SummaryStatsReportGatherer","logger","GroupCallStats","constructor","groupCallId","userId","interval","arguments","length","undefined","_defineProperty","Map","reports","start","timer","setInterval","processStats","stop","clearInterval","gatherers","forEach","c","stopProcessingStats","hasStatsReportGatherer","callId","has","addStatsReportGatherer","opponentMemberId","peerConnection","set","removeStatsReportGatherer","delete","getStatsReportGatherer","get","updateOpponentMember","opponentMember","_this$getStatsReportG","setOpponentMemberId","summary","push","Promise","all","then","s","summaryStatsReportGatherer","build","catch","err","error"],"sources":["../../../src/webrtc/stats/groupCallStats.ts"],"sourcesContent":["/*\nCopyright 2023 The Matrix.org Foundation C.I.C.\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n*/\nimport { CallStatsReportGatherer } from \"./callStatsReportGatherer.ts\";\nimport { StatsReportEmitter } from \"./statsReportEmitter.ts\";\nimport { type CallStatsReportSummary } from \"./callStatsReportSummary.ts\";\nimport { SummaryStatsReportGatherer } from \"./summaryStatsReportGatherer.ts\";\nimport { logger } from \"../../logger.ts\";\n\nexport class GroupCallStats {\n private timer: undefined | ReturnType<typeof setTimeout>;\n private readonly gatherers: Map<string, CallStatsReportGatherer> = new Map<string, CallStatsReportGatherer>();\n public readonly reports = new StatsReportEmitter();\n private readonly summaryStatsReportGatherer = new SummaryStatsReportGatherer(this.reports);\n\n public constructor(\n private groupCallId: string,\n private userId: string,\n private interval: number = 10000,\n ) {}\n\n public start(): void {\n if (this.timer === undefined && this.interval > 0) {\n this.timer = setInterval(() => {\n this.processStats();\n }, this.interval);\n }\n }\n\n public stop(): void {\n if (this.timer !== undefined) {\n clearInterval(this.timer);\n this.gatherers.forEach((c) => c.stopProcessingStats());\n }\n }\n\n public hasStatsReportGatherer(callId: string): boolean {\n return this.gatherers.has(callId);\n }\n\n public addStatsReportGatherer(\n callId: string,\n opponentMemberId: string,\n peerConnection: RTCPeerConnection,\n ): boolean {\n if (this.hasStatsReportGatherer(callId)) {\n return false;\n }\n this.gatherers.set(callId, new CallStatsReportGatherer(callId, opponentMemberId, peerConnection, this.reports));\n return true;\n }\n\n public removeStatsReportGatherer(callId: string): boolean {\n return this.gatherers.delete(callId);\n }\n\n public getStatsReportGatherer(callId: string): CallStatsReportGatherer | undefined {\n return this.hasStatsReportGatherer(callId) ? this.gatherers.get(callId) : undefined;\n }\n\n public updateOpponentMember(callId: string, opponentMember: string): void {\n this.getStatsReportGatherer(callId)?.setOpponentMemberId(opponentMember);\n }\n\n private processStats(): void {\n const summary: Promise<CallStatsReportSummary>[] = [];\n this.gatherers.forEach((c) => {\n summary.push(c.processStats(this.groupCallId, this.userId));\n });\n\n Promise.all(summary)\n .then((s: Awaited<CallStatsReportSummary>[]) => this.summaryStatsReportGatherer.build(s))\n .catch((err) => {\n logger.error(\"Could not build summary stats report\", err);\n });\n }\n\n public setInterval(interval: number): void {\n this.interval = interval;\n }\n}\n"],"mappings":"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","ignoreList":[]}
@@ -17,6 +17,9 @@ limitations under the License.
17
17
 
18
18
  export class MediaTrackStats {
19
19
  constructor(trackId, type, kind) {
20
+ this.trackId = trackId;
21
+ this.type = type;
22
+ this.kind = kind;
20
23
  _defineProperty(this, "loss", {
21
24
  packetsTotal: 0,
22
25
  packetsLost: 0,
@@ -40,9 +43,6 @@ export class MediaTrackStats {
40
43
  _defineProperty(this, "isAlive", true);
41
44
  _defineProperty(this, "isMuted", false);
42
45
  _defineProperty(this, "isEnabled", true);
43
- this.trackId = trackId;
44
- this.type = type;
45
- this.kind = kind;
46
46
  }
47
47
  getType() {
48
48
  return this.type;
@@ -1 +1 @@
1
- {"version":3,"file":"mediaTrackStats.js","names":["MediaTrackStats","constructor","trackId","type","kind","_defineProperty","packetsTotal","packetsLost","isDownloadStream","download","upload","width","height","concealedAudio","totalAudioDuration","getType","setLoss","loss","getLoss","setResolution","resolution","getResolution","setFramerate","framerate","getFramerate","setBitrate","bitrate","getBitrate","setCodec","codecShortType","codec","getCodec","resetBitrate","alive","isAlive","muted","isMuted","enabled","isEnabled","setJitter","jitter","getJitter","setAudioConcealment","concealedAudioDuration","audioConcealment","getAudioConcealment"],"sources":["../../../../src/webrtc/stats/media/mediaTrackStats.ts"],"sourcesContent":["/*\nCopyright 2023 The Matrix.org Foundation C.I.C.\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n*/\n\nimport { type AudioConcealment } from \"../statsReport.ts\";\nimport { type TrackId } from \"./mediaTrackHandler.ts\";\n\nexport interface PacketLoss {\n packetsTotal: number;\n packetsLost: number;\n isDownloadStream: boolean;\n}\n\nexport interface Bitrate {\n /**\n * bytes per second\n */\n download: number;\n /**\n * bytes per second\n */\n upload: number;\n}\nexport interface ConcealedAudio {\n /**\n * duration in ms\n */\n duration: number;\n\n ratio: number;\n}\nexport interface Resolution {\n width: number;\n height: number;\n}\n\nexport type TrackStatsType = \"local\" | \"remote\";\n\nexport class MediaTrackStats {\n private loss: PacketLoss = { packetsTotal: 0, packetsLost: 0, isDownloadStream: false };\n private bitrate: Bitrate = { download: 0, upload: 0 };\n private resolution: Resolution = { width: -1, height: -1 };\n private audioConcealment: AudioConcealment = { concealedAudio: 0, totalAudioDuration: 0 };\n private framerate = 0;\n private jitter = 0;\n private codec = \"\";\n private isAlive = true;\n private isMuted = false;\n private isEnabled = true;\n\n public constructor(\n public readonly trackId: TrackId,\n public readonly type: TrackStatsType,\n public readonly kind: \"audio\" | \"video\",\n ) {}\n\n public getType(): TrackStatsType {\n return this.type;\n }\n\n public setLoss(loss: PacketLoss): void {\n this.loss = loss;\n }\n\n public getLoss(): PacketLoss {\n return this.loss;\n }\n\n public setResolution(resolution: Resolution): void {\n this.resolution = resolution;\n }\n\n public getResolution(): Resolution {\n return this.resolution;\n }\n\n public setFramerate(framerate: number): void {\n this.framerate = framerate;\n }\n\n public getFramerate(): number {\n return this.framerate;\n }\n\n public setBitrate(bitrate: Bitrate): void {\n this.bitrate = bitrate;\n }\n\n public getBitrate(): Bitrate {\n return this.bitrate;\n }\n\n public setCodec(codecShortType: string): boolean {\n this.codec = codecShortType;\n return true;\n }\n\n public getCodec(): string {\n return this.codec;\n }\n\n public resetBitrate(): void {\n this.bitrate = { download: 0, upload: 0 };\n }\n\n public set alive(isAlive: boolean) {\n this.isAlive = isAlive;\n }\n\n /**\n * A MediaTrackState is alive if the corresponding MediaStreamTrack track bound to a transceiver and the\n * MediaStreamTrack is in state MediaStreamTrack.readyState === live\n */\n public get alive(): boolean {\n return this.isAlive;\n }\n\n public set muted(isMuted: boolean) {\n this.isMuted = isMuted;\n }\n\n /**\n * A MediaTrackState.isMuted corresponding to MediaStreamTrack.muted.\n * But these values only match if MediaTrackState.isAlive.\n */\n public get muted(): boolean {\n return this.isMuted;\n }\n\n public set enabled(isEnabled: boolean) {\n this.isEnabled = isEnabled;\n }\n\n /**\n * A MediaTrackState.isEnabled corresponding to MediaStreamTrack.enabled.\n * But these values only match if MediaTrackState.isAlive.\n */\n public get enabled(): boolean {\n return this.isEnabled;\n }\n\n public setJitter(jitter: number): void {\n this.jitter = jitter;\n }\n\n /**\n * Jitter in milliseconds\n */\n public getJitter(): number {\n return this.jitter;\n }\n\n /**\n * Audio concealment ration (conceled duration / total duration)\n */\n public setAudioConcealment(concealedAudioDuration: number, totalAudioDuration: number): void {\n this.audioConcealment.concealedAudio = concealedAudioDuration;\n this.audioConcealment.totalAudioDuration = totalAudioDuration;\n }\n\n public getAudioConcealment(): AudioConcealment {\n return this.audioConcealment;\n }\n}\n"],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"file":"mediaTrackStats.js","names":["MediaTrackStats","constructor","trackId","type","kind","_defineProperty","packetsTotal","packetsLost","isDownloadStream","download","upload","width","height","concealedAudio","totalAudioDuration","getType","setLoss","loss","getLoss","setResolution","resolution","getResolution","setFramerate","framerate","getFramerate","setBitrate","bitrate","getBitrate","setCodec","codecShortType","codec","getCodec","resetBitrate","alive","isAlive","muted","isMuted","enabled","isEnabled","setJitter","jitter","getJitter","setAudioConcealment","concealedAudioDuration","audioConcealment","getAudioConcealment"],"sources":["../../../../src/webrtc/stats/media/mediaTrackStats.ts"],"sourcesContent":["/*\nCopyright 2023 The Matrix.org Foundation C.I.C.\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n*/\n\nimport { type AudioConcealment } from \"../statsReport.ts\";\nimport { type TrackId } from \"./mediaTrackHandler.ts\";\n\nexport interface PacketLoss {\n packetsTotal: number;\n packetsLost: number;\n isDownloadStream: boolean;\n}\n\nexport interface Bitrate {\n /**\n * bytes per second\n */\n download: number;\n /**\n * bytes per second\n */\n upload: number;\n}\nexport interface ConcealedAudio {\n /**\n * duration in ms\n */\n duration: number;\n\n ratio: number;\n}\nexport interface Resolution {\n width: number;\n height: number;\n}\n\nexport type TrackStatsType = \"local\" | \"remote\";\n\nexport class MediaTrackStats {\n private loss: PacketLoss = { packetsTotal: 0, packetsLost: 0, isDownloadStream: false };\n private bitrate: Bitrate = { download: 0, upload: 0 };\n private resolution: Resolution = { width: -1, height: -1 };\n private audioConcealment: AudioConcealment = { concealedAudio: 0, totalAudioDuration: 0 };\n private framerate = 0;\n private jitter = 0;\n private codec = \"\";\n private isAlive = true;\n private isMuted = false;\n private isEnabled = true;\n\n public constructor(\n public readonly trackId: TrackId,\n public readonly type: TrackStatsType,\n public readonly kind: \"audio\" | \"video\",\n ) {}\n\n public getType(): TrackStatsType {\n return this.type;\n }\n\n public setLoss(loss: PacketLoss): void {\n this.loss = loss;\n }\n\n public getLoss(): PacketLoss {\n return this.loss;\n }\n\n public setResolution(resolution: Resolution): void {\n this.resolution = resolution;\n }\n\n public getResolution(): Resolution {\n return this.resolution;\n }\n\n public setFramerate(framerate: number): void {\n this.framerate = framerate;\n }\n\n public getFramerate(): number {\n return this.framerate;\n }\n\n public setBitrate(bitrate: Bitrate): void {\n this.bitrate = bitrate;\n }\n\n public getBitrate(): Bitrate {\n return this.bitrate;\n }\n\n public setCodec(codecShortType: string): boolean {\n this.codec = codecShortType;\n return true;\n }\n\n public getCodec(): string {\n return this.codec;\n }\n\n public resetBitrate(): void {\n this.bitrate = { download: 0, upload: 0 };\n }\n\n public set alive(isAlive: boolean) {\n this.isAlive = isAlive;\n }\n\n /**\n * A MediaTrackState is alive if the corresponding MediaStreamTrack track bound to a transceiver and the\n * MediaStreamTrack is in state MediaStreamTrack.readyState === live\n */\n public get alive(): boolean {\n return this.isAlive;\n }\n\n public set muted(isMuted: boolean) {\n this.isMuted = isMuted;\n }\n\n /**\n * A MediaTrackState.isMuted corresponding to MediaStreamTrack.muted.\n * But these values only match if MediaTrackState.isAlive.\n */\n public get muted(): boolean {\n return this.isMuted;\n }\n\n public set enabled(isEnabled: boolean) {\n this.isEnabled = isEnabled;\n }\n\n /**\n * A MediaTrackState.isEnabled corresponding to MediaStreamTrack.enabled.\n * But these values only match if MediaTrackState.isAlive.\n */\n public get enabled(): boolean {\n return this.isEnabled;\n }\n\n public setJitter(jitter: number): void {\n this.jitter = jitter;\n }\n\n /**\n * Jitter in milliseconds\n */\n public getJitter(): number {\n return this.jitter;\n }\n\n /**\n * Audio concealment ration (conceled duration / total duration)\n */\n public setAudioConcealment(concealedAudioDuration: number, totalAudioDuration: number): void {\n this.audioConcealment.concealedAudio = concealedAudioDuration;\n this.audioConcealment.totalAudioDuration = totalAudioDuration;\n }\n\n public getAudioConcealment(): AudioConcealment {\n return this.audioConcealment;\n }\n}\n"],"mappings":"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","ignoreList":[]}
@@ -18,9 +18,9 @@ limitations under the License.
18
18
  import { MediaTrackStats } from "./mediaTrackStats.js";
19
19
  export class MediaTrackStatsHandler {
20
20
  constructor(mediaSsrcHandler, mediaTrackHandler) {
21
- _defineProperty(this, "track2stats", new Map());
22
21
  this.mediaSsrcHandler = mediaSsrcHandler;
23
22
  this.mediaTrackHandler = mediaTrackHandler;
23
+ _defineProperty(this, "track2stats", new Map());
24
24
  }
25
25
 
26
26
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"mediaTrackStatsHandler.js","names":["MediaTrackStats","MediaTrackStatsHandler","constructor","mediaSsrcHandler","mediaTrackHandler","_defineProperty","Map","findTrack2Stats","report","type","trackID","trackIdentifier","mid","getRemoteTrackIdByMid","getLocalTrackIdByMid","ssrc","findMidBySsrc","undefined","trackStats","track2stats","get","track","getTackById","kind","set","findLocalVideoTrackStats","localVideoTracks","getLocalTracks","length","getTrack2stats","findTransceiverByTrackId","getTransceiverByTrackId"],"sources":["../../../../src/webrtc/stats/media/mediaTrackStatsHandler.ts"],"sourcesContent":["/*\nCopyright 2023 The Matrix.org Foundation C.I.C.\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n*/\nimport { type TrackID } from \"../statsReport.ts\";\nimport { MediaTrackStats } from \"./mediaTrackStats.ts\";\nimport { type MediaTrackHandler, type TrackId } from \"./mediaTrackHandler.ts\";\nimport { type MediaSsrcHandler } from \"./mediaSsrcHandler.ts\";\n\nexport class MediaTrackStatsHandler {\n private readonly track2stats = new Map<TrackID, MediaTrackStats>();\n\n public constructor(\n public readonly mediaSsrcHandler: MediaSsrcHandler,\n public readonly mediaTrackHandler: MediaTrackHandler,\n ) {}\n\n /**\n * Find tracks by rtc stats\n * Argument report is any because the stats api is not consistent:\n * For example `trackIdentifier`, `mid` not existing in every implementations\n * https://www.w3.org/TR/webrtc-stats/#dom-rtcinboundrtpstreamstats\n * https://developer.mozilla.org/en-US/docs/Web/API/RTCInboundRtpStreamStats\n */\n public findTrack2Stats(report: any, type: \"remote\" | \"local\"): MediaTrackStats | undefined {\n let trackID;\n if (report.trackIdentifier) {\n trackID = report.trackIdentifier;\n } else if (report.mid) {\n trackID =\n type === \"remote\"\n ? this.mediaTrackHandler.getRemoteTrackIdByMid(report.mid)\n : this.mediaTrackHandler.getLocalTrackIdByMid(report.mid);\n } else if (report.ssrc) {\n const mid = this.mediaSsrcHandler.findMidBySsrc(report.ssrc, type);\n if (!mid) {\n return undefined;\n }\n trackID =\n type === \"remote\"\n ? this.mediaTrackHandler.getRemoteTrackIdByMid(report.mid)\n : this.mediaTrackHandler.getLocalTrackIdByMid(report.mid);\n }\n\n if (!trackID) {\n return undefined;\n }\n\n let trackStats = this.track2stats.get(trackID);\n\n if (!trackStats) {\n const track = this.mediaTrackHandler.getTackById(trackID);\n if (track !== undefined) {\n const kind: \"audio\" | \"video\" = track.kind === \"audio\" ? track.kind : \"video\";\n trackStats = new MediaTrackStats(trackID, type, kind);\n this.track2stats.set(trackID, trackStats);\n } else {\n return undefined;\n }\n }\n return trackStats;\n }\n\n public findLocalVideoTrackStats(report: any): MediaTrackStats | undefined {\n const localVideoTracks = this.mediaTrackHandler.getLocalTracks(\"video\");\n if (localVideoTracks.length === 0) {\n return undefined;\n }\n return this.findTrack2Stats(report, \"local\");\n }\n\n public getTrack2stats(): Map<TrackID, MediaTrackStats> {\n return this.track2stats;\n }\n\n public findTransceiverByTrackId(trackID: TrackId): undefined | RTCRtpTransceiver {\n return this.mediaTrackHandler.getTransceiverByTrackId(trackID);\n }\n}\n"],"mappings":";AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA,SAASA,eAAe,QAAQ,sBAAsB;AAItD,OAAO,MAAMC,sBAAsB,CAAC;EAGzBC,WAAWA,CACEC,gBAAkC,EAClCC,iBAAoC,EACtD;IAAAC,eAAA,sBAL6B,IAAIC,GAAG,CAA2B,CAAC;IAAA,KAG9CH,gBAAkC,GAAlCA,gBAAkC;IAAA,KAClCC,iBAAoC,GAApCA,iBAAoC;EACrD;;EAEH;AACJ;AACA;AACA;AACA;AACA;AACA;EACWG,eAAeA,CAACC,MAAW,EAAEC,IAAwB,EAA+B;IACvF,IAAIC,OAAO;IACX,IAAIF,MAAM,CAACG,eAAe,EAAE;MACxBD,OAAO,GAAGF,MAAM,CAACG,eAAe;IACpC,CAAC,MAAM,IAAIH,MAAM,CAACI,GAAG,EAAE;MACnBF,OAAO,GACHD,IAAI,KAAK,QAAQ,GACX,IAAI,CAACL,iBAAiB,CAACS,qBAAqB,CAACL,MAAM,CAACI,GAAG,CAAC,GACxD,IAAI,CAACR,iBAAiB,CAACU,oBAAoB,CAACN,MAAM,CAACI,GAAG,CAAC;IACrE,CAAC,MAAM,IAAIJ,MAAM,CAACO,IAAI,EAAE;MACpB,IAAMH,GAAG,GAAG,IAAI,CAACT,gBAAgB,CAACa,aAAa,CAACR,MAAM,CAACO,IAAI,EAAEN,IAAI,CAAC;MAClE,IAAI,CAACG,GAAG,EAAE;QACN,OAAOK,SAAS;MACpB;MACAP,OAAO,GACHD,IAAI,KAAK,QAAQ,GACX,IAAI,CAACL,iBAAiB,CAACS,qBAAqB,CAACL,MAAM,CAACI,GAAG,CAAC,GACxD,IAAI,CAACR,iBAAiB,CAACU,oBAAoB,CAACN,MAAM,CAACI,GAAG,CAAC;IACrE;IAEA,IAAI,CAACF,OAAO,EAAE;MACV,OAAOO,SAAS;IACpB;IAEA,IAAIC,UAAU,GAAG,IAAI,CAACC,WAAW,CAACC,GAAG,CAACV,OAAO,CAAC;IAE9C,IAAI,CAACQ,UAAU,EAAE;MACb,IAAMG,KAAK,GAAG,IAAI,CAACjB,iBAAiB,CAACkB,WAAW,CAACZ,OAAO,CAAC;MACzD,IAAIW,KAAK,KAAKJ,SAAS,EAAE;QACrB,IAAMM,IAAuB,GAAGF,KAAK,CAACE,IAAI,KAAK,OAAO,GAAGF,KAAK,CAACE,IAAI,GAAG,OAAO;QAC7EL,UAAU,GAAG,IAAIlB,eAAe,CAACU,OAAO,EAAED,IAAI,EAAEc,IAAI,CAAC;QACrD,IAAI,CAACJ,WAAW,CAACK,GAAG,CAACd,OAAO,EAAEQ,UAAU,CAAC;MAC7C,CAAC,MAAM;QACH,OAAOD,SAAS;MACpB;IACJ;IACA,OAAOC,UAAU;EACrB;EAEOO,wBAAwBA,CAACjB,MAAW,EAA+B;IACtE,IAAMkB,gBAAgB,GAAG,IAAI,CAACtB,iBAAiB,CAACuB,cAAc,CAAC,OAAO,CAAC;IACvE,IAAID,gBAAgB,CAACE,MAAM,KAAK,CAAC,EAAE;MAC/B,OAAOX,SAAS;IACpB;IACA,OAAO,IAAI,CAACV,eAAe,CAACC,MAAM,EAAE,OAAO,CAAC;EAChD;EAEOqB,cAAcA,CAAA,EAAkC;IACnD,OAAO,IAAI,CAACV,WAAW;EAC3B;EAEOW,wBAAwBA,CAACpB,OAAgB,EAAiC;IAC7E,OAAO,IAAI,CAACN,iBAAiB,CAAC2B,uBAAuB,CAACrB,OAAO,CAAC;EAClE;AACJ","ignoreList":[]}
1
+ {"version":3,"file":"mediaTrackStatsHandler.js","names":["MediaTrackStats","MediaTrackStatsHandler","constructor","mediaSsrcHandler","mediaTrackHandler","_defineProperty","Map","findTrack2Stats","report","type","trackID","trackIdentifier","mid","getRemoteTrackIdByMid","getLocalTrackIdByMid","ssrc","findMidBySsrc","undefined","trackStats","track2stats","get","track","getTackById","kind","set","findLocalVideoTrackStats","localVideoTracks","getLocalTracks","length","getTrack2stats","findTransceiverByTrackId","getTransceiverByTrackId"],"sources":["../../../../src/webrtc/stats/media/mediaTrackStatsHandler.ts"],"sourcesContent":["/*\nCopyright 2023 The Matrix.org Foundation C.I.C.\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n*/\nimport { type TrackID } from \"../statsReport.ts\";\nimport { MediaTrackStats } from \"./mediaTrackStats.ts\";\nimport { type MediaTrackHandler, type TrackId } from \"./mediaTrackHandler.ts\";\nimport { type MediaSsrcHandler } from \"./mediaSsrcHandler.ts\";\n\nexport class MediaTrackStatsHandler {\n private readonly track2stats = new Map<TrackID, MediaTrackStats>();\n\n public constructor(\n public readonly mediaSsrcHandler: MediaSsrcHandler,\n public readonly mediaTrackHandler: MediaTrackHandler,\n ) {}\n\n /**\n * Find tracks by rtc stats\n * Argument report is any because the stats api is not consistent:\n * For example `trackIdentifier`, `mid` not existing in every implementations\n * https://www.w3.org/TR/webrtc-stats/#dom-rtcinboundrtpstreamstats\n * https://developer.mozilla.org/en-US/docs/Web/API/RTCInboundRtpStreamStats\n */\n public findTrack2Stats(report: any, type: \"remote\" | \"local\"): MediaTrackStats | undefined {\n let trackID;\n if (report.trackIdentifier) {\n trackID = report.trackIdentifier;\n } else if (report.mid) {\n trackID =\n type === \"remote\"\n ? this.mediaTrackHandler.getRemoteTrackIdByMid(report.mid)\n : this.mediaTrackHandler.getLocalTrackIdByMid(report.mid);\n } else if (report.ssrc) {\n const mid = this.mediaSsrcHandler.findMidBySsrc(report.ssrc, type);\n if (!mid) {\n return undefined;\n }\n trackID =\n type === \"remote\"\n ? this.mediaTrackHandler.getRemoteTrackIdByMid(report.mid)\n : this.mediaTrackHandler.getLocalTrackIdByMid(report.mid);\n }\n\n if (!trackID) {\n return undefined;\n }\n\n let trackStats = this.track2stats.get(trackID);\n\n if (!trackStats) {\n const track = this.mediaTrackHandler.getTackById(trackID);\n if (track !== undefined) {\n const kind: \"audio\" | \"video\" = track.kind === \"audio\" ? track.kind : \"video\";\n trackStats = new MediaTrackStats(trackID, type, kind);\n this.track2stats.set(trackID, trackStats);\n } else {\n return undefined;\n }\n }\n return trackStats;\n }\n\n public findLocalVideoTrackStats(report: any): MediaTrackStats | undefined {\n const localVideoTracks = this.mediaTrackHandler.getLocalTracks(\"video\");\n if (localVideoTracks.length === 0) {\n return undefined;\n }\n return this.findTrack2Stats(report, \"local\");\n }\n\n public getTrack2stats(): Map<TrackID, MediaTrackStats> {\n return this.track2stats;\n }\n\n public findTransceiverByTrackId(trackID: TrackId): undefined | RTCRtpTransceiver {\n return this.mediaTrackHandler.getTransceiverByTrackId(trackID);\n }\n}\n"],"mappings":";AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA,SAASA,eAAe,QAAQ,sBAAsB;AAItD,OAAO,MAAMC,sBAAsB,CAAC;EAGzBC,WAAWA,CACEC,gBAAkC,EAClCC,iBAAoC,EACtD;IAAA,KAFkBD,gBAAkC,GAAlCA,gBAAkC;IAAA,KAClCC,iBAAoC,GAApCA,iBAAoC;IAAAC,eAAA,sBAJzB,IAAIC,GAAG,CAA2B,CAAC;EAK/D;;EAEH;AACJ;AACA;AACA;AACA;AACA;AACA;EACWC,eAAeA,CAACC,MAAW,EAAEC,IAAwB,EAA+B;IACvF,IAAIC,OAAO;IACX,IAAIF,MAAM,CAACG,eAAe,EAAE;MACxBD,OAAO,GAAGF,MAAM,CAACG,eAAe;IACpC,CAAC,MAAM,IAAIH,MAAM,CAACI,GAAG,EAAE;MACnBF,OAAO,GACHD,IAAI,KAAK,QAAQ,GACX,IAAI,CAACL,iBAAiB,CAACS,qBAAqB,CAACL,MAAM,CAACI,GAAG,CAAC,GACxD,IAAI,CAACR,iBAAiB,CAACU,oBAAoB,CAACN,MAAM,CAACI,GAAG,CAAC;IACrE,CAAC,MAAM,IAAIJ,MAAM,CAACO,IAAI,EAAE;MACpB,IAAMH,GAAG,GAAG,IAAI,CAACT,gBAAgB,CAACa,aAAa,CAACR,MAAM,CAACO,IAAI,EAAEN,IAAI,CAAC;MAClE,IAAI,CAACG,GAAG,EAAE;QACN,OAAOK,SAAS;MACpB;MACAP,OAAO,GACHD,IAAI,KAAK,QAAQ,GACX,IAAI,CAACL,iBAAiB,CAACS,qBAAqB,CAACL,MAAM,CAACI,GAAG,CAAC,GACxD,IAAI,CAACR,iBAAiB,CAACU,oBAAoB,CAACN,MAAM,CAACI,GAAG,CAAC;IACrE;IAEA,IAAI,CAACF,OAAO,EAAE;MACV,OAAOO,SAAS;IACpB;IAEA,IAAIC,UAAU,GAAG,IAAI,CAACC,WAAW,CAACC,GAAG,CAACV,OAAO,CAAC;IAE9C,IAAI,CAACQ,UAAU,EAAE;MACb,IAAMG,KAAK,GAAG,IAAI,CAACjB,iBAAiB,CAACkB,WAAW,CAACZ,OAAO,CAAC;MACzD,IAAIW,KAAK,KAAKJ,SAAS,EAAE;QACrB,IAAMM,IAAuB,GAAGF,KAAK,CAACE,IAAI,KAAK,OAAO,GAAGF,KAAK,CAACE,IAAI,GAAG,OAAO;QAC7EL,UAAU,GAAG,IAAIlB,eAAe,CAACU,OAAO,EAAED,IAAI,EAAEc,IAAI,CAAC;QACrD,IAAI,CAACJ,WAAW,CAACK,GAAG,CAACd,OAAO,EAAEQ,UAAU,CAAC;MAC7C,CAAC,MAAM;QACH,OAAOD,SAAS;MACpB;IACJ;IACA,OAAOC,UAAU;EACrB;EAEOO,wBAAwBA,CAACjB,MAAW,EAA+B;IACtE,IAAMkB,gBAAgB,GAAG,IAAI,CAACtB,iBAAiB,CAACuB,cAAc,CAAC,OAAO,CAAC;IACvE,IAAID,gBAAgB,CAACE,MAAM,KAAK,CAAC,EAAE;MAC/B,OAAOX,SAAS;IACpB;IACA,OAAO,IAAI,CAACV,eAAe,CAACC,MAAM,EAAE,OAAO,CAAC;EAChD;EAEOqB,cAAcA,CAAA,EAAkC;IACnD,OAAO,IAAI,CAACV,WAAW;EAC3B;EAEOW,wBAAwBA,CAACpB,OAAgB,EAAiC;IAC7E,OAAO,IAAI,CAACN,iBAAiB,CAAC2B,uBAAuB,CAACrB,OAAO,CAAC;EAClE;AACJ","ignoreList":[]}