{"version":3,"sources":["jsdelivr-header.js","/npm/@100mslive/hms-video@0.9.28/package.json","/npm/@100mslive/hms-video@0.9.28/src/index.ts","/npm/@100mslive/hms-video@0.9.28/src/sdk/models/HMSMessage.ts","/npm/@100mslive/hms-video@0.9.28/src/sdk/models/HMSRoom.ts","/npm/@100mslive/hms-video@0.9.28/src/utils/constants.ts","/npm/@100mslive/hms-video@0.9.28/src/sdk/models/peer/HMSPeer.ts","/npm/@100mslive/hms-video@0.9.28/src/utils/id-factory.ts","/npm/@100mslive/hms-video@0.9.28/src/sdk/models/peer/HMSLocalPeer.ts","/npm/@100mslive/hms-video@0.9.28/src/utils/support.ts","/npm/@100mslive/hms-video@0.9.28/src/sdk/models/peer/HMSRemotePeer.ts","/npm/@100mslive/hms-video@0.9.28/src/notification-manager/managers/utils.ts","/npm/@100mslive/hms-video@0.9.28/src/sdk/HMSPeerListIterator.ts","/npm/@100mslive/hms-video@0.9.28/src/sdk/LocalTrackManager.ts","/npm/@100mslive/hms-video@0.9.28/src/analytics/AnalyticsEvent.ts","/npm/@100mslive/hms-video@0.9.28/src/analytics/domain-analytics.ts","/npm/@100mslive/hms-video@0.9.28/src/utils/analytics-deviceId.ts","/npm/@100mslive/hms-video@0.9.28/src/utils/logger.ts","/npm/@100mslive/hms-video@0.9.28/src/error/ErrorCodes.ts","/npm/@100mslive/hms-video@0.9.28/src/error/HMSException.ts","/npm/@100mslive/hms-video@0.9.28/src/signal/jsonrpc/models.ts","/npm/@100mslive/hms-video@0.9.28/src/error/ErrorFactory.ts","/npm/@100mslive/hms-video@0.9.28/src/utils/local-storage-polyfill.ts","/npm/@100mslive/hms-video@0.9.28/src/utils/local-storage.ts","/npm/@100mslive/hms-video@0.9.28/src/utils/validations.ts","/npm/@100mslive/hms-video@0.9.28/src/utils/user-agent.ts","/npm/@100mslive/hms-video@0.9.28/src/analytics/AnalyticsEventFactory.ts","/npm/@100mslive/hms-video@0.9.28/src/analytics/AnalyticsTimer.ts","/npm/@100mslive/hms-video@0.9.28/src/error/utils.ts","/npm/@100mslive/hms-video@0.9.28/src/internal.ts","/npm/@100mslive/hms-video@0.9.28/src/media/streams/HMSMediaStream.ts","/npm/@100mslive/hms-video@0.9.28/src/utils/json.ts","/npm/@100mslive/hms-video@0.9.28/src/media/tracks/HMSTrack.ts","/npm/@100mslive/hms-video@0.9.28/src/media/tracks/HMSTrackType.ts","/npm/@100mslive/hms-video@0.9.28/src/media/tracks/HMSAudioTrack.ts","/npm/@100mslive/hms-video@0.9.28/src/device-manager/DeviceStorage.ts","/npm/@100mslive/hms-video@0.9.28/src/plugins/audio/HMSAudioPlugin.ts","/npm/@100mslive/hms-video@0.9.28/src/analytics/MediaPluginsAnalyticsFactory.ts","/npm/@100mslive/hms-video@0.9.28/src/plugins/audio/AudioPluginsAnalytics.ts","/npm/@100mslive/hms-video@0.9.28/src/plugins/audio/HMSAudioPluginsManager.ts","/npm/@100mslive/hms-video@0.9.28/src/utils/track.ts","/npm/@100mslive/hms-video@0.9.28/src/utils/media.ts","/npm/@100mslive/hms-video@0.9.28/src/utils/queue.ts","/npm/@100mslive/hms-video@0.9.28/src/utils/timer-utils.ts","/npm/@100mslive/hms-video@0.9.28/src/utils/track-audio-level-monitor.ts","/npm/@100mslive/hms-video@0.9.28/src/interfaces/update-listener.ts","/npm/@100mslive/hms-video@0.9.28/src/interfaces/room.ts","/npm/@100mslive/hms-video@0.9.28/src/interfaces/simulcast-layers.ts","/npm/@100mslive/hms-video@0.9.28/src/interfaces/track-settings.ts","/npm/@100mslive/hms-video@0.9.28/src/interfaces/devices.ts","/npm/@100mslive/hms-video@0.9.28/src/interfaces/playlist.ts","/npm/@100mslive/hms-video@0.9.28/src/interfaces/session-store/polls.ts","/npm/@100mslive/hms-video@0.9.28/src/media/settings/HMSAudioTrackSettings.ts","/npm/@100mslive/hms-video@0.9.28/src/media/settings/HMSVideoTrackSettings.ts","/npm/@100mslive/hms-video@0.9.28/src/media/settings/HMSTrackSettings.ts","/npm/@100mslive/hms-video@0.9.28/src/media/tracks/HMSLocalAudioTrack.ts","/npm/@100mslive/hms-video@0.9.28/src/media/tracks/HMSRemoteAudioTrack.ts","/npm/@100mslive/hms-video@0.9.28/src/media/tracks/HMSVideoTrack.ts","/npm/@100mslive/hms-video@0.9.28/src/media/tracks/VideoElementManager.ts","/npm/@100mslive/hms-video@0.9.28/src/media/tracks/trackUtils.ts","/npm/@100mslive/hms-video@0.9.28/src/utils/intersection-observer.ts","/npm/@100mslive/hms-video@0.9.28/src/utils/resize-observer.ts","/npm/@100mslive/hms-video@0.9.28/src/plugins/video/HMSVideoPlugin.ts","/npm/@100mslive/hms-video@0.9.28/src/utils/math.ts","/npm/@100mslive/hms-video@0.9.28/src/plugins/video/VideoPluginsAnalytics.ts","/npm/@100mslive/hms-video@0.9.28/src/plugins/video/HMSVideoPluginsManager.ts","/npm/@100mslive/hms-video@0.9.28/src/plugins/video/HMSMediaStreamPluginsManager.ts","/npm/@100mslive/hms-video@0.9.28/src/media/tracks/HMSLocalVideoTrack.ts","/npm/@100mslive/hms-video@0.9.28/src/media/tracks/HMSRemoteVideoTrack.ts","/npm/@100mslive/hms-video@0.9.28/src/media/streams/HMSLocalStream.ts","/npm/@100mslive/hms-video@0.9.28/src/media/streams/HMSRemoteStream.ts","/npm/@100mslive/hms-video@0.9.28/src/utils/device-error.ts","/npm/@100mslive/hms-video@0.9.28/src/rtc-stats/utils.ts","/npm/@100mslive/hms-video@0.9.28/src/rtc-stats/HMSWebrtcStats.ts","/npm/@100mslive/hms-video@0.9.28/src/rtc-stats/HMSWebrtcInternals.ts","/npm/@100mslive/hms-video@0.9.28/src/sdk/NetworkTestManager.ts","/npm/@100mslive/hms-video@0.9.28/src/sdk/RoleChangeManager.ts","/npm/@100mslive/hms-video@0.9.28/src/analytics/HTTPAnalyticsTransport.ts","/npm/@100mslive/hms-video@0.9.28/src/sdk/store/Store.ts","/npm/@100mslive/hms-video@0.9.28/src/sdk/WakeLockManager.ts","/npm/@100mslive/hms-video@0.9.28/src/analytics/AnalyticsEventsService.ts","/npm/@100mslive/hms-video@0.9.28/src/audio-sink-manager/AudioSinkManager.ts","/npm/@100mslive/hms-video@0.9.28/src/device-manager/DeviceManager.ts","/npm/@100mslive/hms-video@0.9.28/src/device-manager/AudioOutputManager.ts","/npm/@100mslive/hms-video@0.9.28/src/events/EventBus.ts","/npm/@100mslive/hms-video@0.9.28/src/events/HMSInternalEvent.ts","/npm/@100mslive/hms-video@0.9.28/src/notification-manager/HMSNotifications.ts","/npm/@100mslive/hms-video@0.9.28/src/notification-manager/managers/ActiveSpeakerManager.ts","/npm/@100mslive/hms-video@0.9.28/src/notification-manager/managers/BroadcastManager.ts","/npm/@100mslive/hms-video@0.9.28/src/notification-manager/managers/ConnectionQualityManager.ts","/npm/@100mslive/hms-video@0.9.28/src/notification-manager/managers/TrackManager.ts","/npm/@100mslive/hms-video@0.9.28/src/notification-manager/managers/onDemandTrackManager.ts","/npm/@100mslive/hms-video@0.9.28/src/notification-manager/managers/PeerListManager.ts","/npm/@100mslive/hms-video@0.9.28/src/utils/date.ts","/npm/@100mslive/hms-video@0.9.28/src/notification-manager/managers/PeerManager.ts","/npm/@100mslive/hms-video@0.9.28/src/notification-manager/managers/PolicyChangeManager.ts","/npm/@100mslive/hms-video@0.9.28/src/session-store/interactivity-center/HMSWhiteboardCenter.ts","/npm/@100mslive/hms-video@0.9.28/src/session-store/interactivity-center/HMSInteractivityCenter.ts","/npm/@100mslive/hms-video@0.9.28/src/notification-manager/managers/PollsManager.ts","/npm/@100mslive/hms-video@0.9.28/src/notification-manager/managers/RequestManager.ts","/npm/@100mslive/hms-video@0.9.28/src/notification-manager/managers/RoomUpdateManager.ts","/npm/@100mslive/hms-video@0.9.28/src/notification-manager/managers/SessionMetadataManager.ts","/npm/@100mslive/hms-video@0.9.28/src/notification-manager/managers/WhiteboardManager.ts","/npm/@100mslive/hms-video@0.9.28/src/notification-manager/NotificationManager.ts","/npm/@100mslive/hms-video@0.9.28/src/playlist-manager/AudioContextManager.ts","/npm/@100mslive/hms-video@0.9.28/src/utils/typed-event-emitter.ts","/npm/@100mslive/hms-video@0.9.28/src/playlist-manager/PlaylistAudioManager.ts","/npm/@100mslive/hms-video@0.9.28/src/playlist-manager/PlaylistVideoManager.ts","/npm/@100mslive/hms-video@0.9.28/src/playlist-manager/PlaylistManager.ts","/npm/@100mslive/hms-video@0.9.28/src/session-store/index.ts","/npm/@100mslive/hms-video@0.9.28/src/transport/models/JoinParameters.ts","/npm/@100mslive/hms-video@0.9.28/src/transport/models/TransportFailureCategory.ts","/npm/@100mslive/hms-video@0.9.28/src/transport/models/TransportState.ts","/npm/@100mslive/hms-video@0.9.28/src/utils/promise.ts","/npm/@100mslive/hms-video@0.9.28/src/transport/RetryScheduler.ts","/npm/@100mslive/hms-video@0.9.28/src/analytics/signal-transport/LocalStoageEvents.ts","/npm/@100mslive/hms-video@0.9.28/src/analytics/AnalyticsTransport.ts","/npm/@100mslive/hms-video@0.9.28/src/analytics/signal-transport/SignalAnalyticsTransport.ts","/npm/@100mslive/hms-video@0.9.28/src/analytics/stats/BaseStatsAnalytics.ts","/npm/@100mslive/hms-video@0.9.28/src/analytics/stats/PublishStatsAnalytics.ts","/npm/@100mslive/hms-video@0.9.28/src/analytics/stats/SubscribeStatsAnalytics.ts","/npm/@100mslive/hms-video@0.9.28/src/connection/model.ts","/npm/@100mslive/hms-video@0.9.28/src/utils/session-description.ts","/npm/@100mslive/hms-video@0.9.28/src/connection/HMSConnection.ts","/npm/@100mslive/hms-video@0.9.28/src/connection/publish/publishConnection.ts","/npm/@100mslive/hms-video@0.9.28/src/connection/subscribe/subscribeConnection.ts","/npm/@100mslive/hms-video@0.9.28/src/connection/HMSDataChannel.ts","/npm/@100mslive/hms-video@0.9.28/src/signal/init/index.ts","/npm/@100mslive/hms-video@0.9.28/src/signal/jsonrpc/index.ts","/npm/@100mslive/hms-video@0.9.28/src/utils/network-info.ts","/npm/@100mslive/hms-video@0.9.28/src/transport/index.ts","/npm/@100mslive/hms-video@0.9.28/src/utils/fetch.ts","/npm/@100mslive/hms-video@0.9.28/src/utils/jwt.ts","/npm/@100mslive/hms-video@0.9.28/src/sdk/index.ts"],"names":[],"mappings":"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","file":"/npm/@100mslive/hms-video@0.9.28/dist/index.cjs.js","sourceRoot":"","sourcesContent":["/**\n * Minified by jsDelivr using Terser v5.39.0.\n * Original file: /npm/@100mslive/hms-video@0.9.28/dist/index.cjs.js\n *\n * Do NOT use SRI with dynamically generated files! More information: https://www.jsdelivr.com/using-sri-with-dynamic-files\n */\n","{\n  \"name\": \"@100mslive/hms-video\",\n  \"version\": \"0.9.28\",\n  \"license\": \"MIT\",\n  \"main\": \"dist/index.cjs.js\",\n  \"typings\": \"dist/index.d.ts\",\n  \"module\": \"dist/index.js\",\n  \"files\": [\n    \"dist\",\n    \"src\"\n  ],\n  \"engines\": {\n    \"node\": \">=10\"\n  },\n  \"exports\": {\n    \".\": {\n      \"require\": \"./dist/index.cjs.js\",\n      \"import\": \"./dist/index.js\",\n      \"default\": \"./dist/index.js\"\n    }\n  },\n  \"scripts\": {\n    \"prestart\": \"rm -rf dist && yarn types:build\",\n    \"start\": \"concurrently \\\"yarn dev\\\" \\\"yarn types\\\"\",\n    \"dev\": \"node ../../scripts/dev\",\n    \"build:only\": \"node ../../scripts/build\",\n    \"build\": \"yarn build:only && yarn types:build\",\n    \"types\": \"tsc -w\",\n    \"types:build\": \"tsc -p tsconfig.json\",\n    \"test\": \"jest --maxWorkers=1\",\n    \"lint\": \"eslint -c ../../.eslintrc .\",\n    \"lint:fix\": \"yarn lint --fix\",\n    \"prepare\": \"yarn build\",\n    \"size\": \"size-limit\",\n    \"analyze\": \"size-limit --why\",\n    \"format\": \"prettier --write src/**/*.ts\"\n  },\n  \"author\": \"100ms <tech-common@100ms.live>\",\n  \"devDependencies\": {\n    \"@types/dom-screen-wake-lock\": \"^1.0.1\",\n    \"@types/sdp-transform\": \"^2.4.4\",\n    \"@types/ua-parser-js\": \"^0.7.36\",\n    \"@types/uuid\": \"^8.3.0\",\n    \"jest-canvas-mock\": \"^2.3.1\",\n    \"jsdom-worker\": \"^0.3.0\",\n    \"tslib\": \"^2.2.0\"\n  },\n  \"dependencies\": {\n    \"eventemitter2\": \"^6.4.7\",\n    \"sdp-transform\": \"^2.14.1\",\n    \"ua-parser-js\": \"^1.0.1\",\n    \"uuid\": \"^8.3.2\",\n    \"webrtc-adapter\": \"^8.0.0\"\n  },\n  \"gitHead\": \"2616c7f5408ccbe73ba402514ca7b87b310d377c\"\n}\n","export * from './sdk';\nexport * from './internal';\n","import { HMSPeer } from './peer';\nimport { HMSRole } from '../../interfaces';\nimport { HMSMessage } from '../../interfaces/message';\nimport { SendMessage } from '../../notification-manager';\nimport { ISignalParamsProvider } from '../../signal/ISignalSendParamsProvider';\n\nexport default class Message implements HMSMessage, ISignalParamsProvider<SendMessage> {\n  sender?: HMSPeer;\n  recipientPeer?: HMSPeer;\n  recipientRoles?: HMSRole[];\n  message: any;\n  time: Date;\n  type: string;\n  id?: string;\n\n  constructor({ sender, message, type = 'chat', recipientPeer, recipientRoles, time, id }: HMSMessage) {\n    this.sender = sender;\n    this.message = message;\n    this.type = type;\n    this.recipientPeer = recipientPeer;\n    this.recipientRoles = recipientRoles;\n    this.time = time;\n    this.id = id;\n  }\n\n  toSignalParams() {\n    const roles = this.recipientRoles?.map(role => role.name);\n    const peer = this.recipientPeer?.peerId;\n    const sendParams: SendMessage = {\n      info: {\n        message: this.message,\n        type: this.type,\n      },\n    };\n    if (roles?.length) {\n      sendParams.roles = roles;\n    }\n    if (peer) {\n      sendParams.peer_id = peer;\n    }\n    return sendParams;\n  }\n\n  toString() {\n    return `{\n      sender: ${this.sender};\n      recipientPeer: ${this.recipientPeer};\n      recipientRoles: ${this.recipientRoles?.map(role => role.name)};\n      message: ${this.message};\n      time: ${this.time};\n      type: ${this.type};\n      id: ${this.id}\n    }`;\n  }\n}\n","import { HMSHLS, HMSRecording, HMSRoom, HMSRTMP } from '../../interfaces/room';\n\nexport default class Room implements HMSRoom {\n  id: string;\n  joinedAt?: Date | undefined;\n  templateId?: string | undefined;\n  sessionId?: string;\n  startedAt?: Date;\n  recording: HMSRecording = { server: { running: false }, browser: { running: false }, hls: { running: false } };\n  rtmp: HMSRTMP = { running: false };\n  hls: HMSHLS = { running: false, variants: [] };\n  name?: string;\n  peerCount?: number;\n  description?: string;\n  max_size?: number;\n  large_room_optimization?: boolean;\n\n  constructor(id: string) {\n    this.id = id;\n  }\n}\n","export const RENEGOTIATION_CALLBACK_ID = 'renegotiation-callback-id';\nexport const API_DATA_CHANNEL = 'ion-sfu';\nexport const ANALYTICS_BUFFER_SIZE = 100;\n\n/**\n * Maximum number of retries that transport-layer will try\n * before giving up on the connection and returning a failure\n *\n * Refer https://100ms.atlassian.net/browse/HMS-2369\n */\nexport const MAX_TRANSPORT_RETRIES = 5;\nexport const MAX_TRANSPORT_RETRY_DELAY = 60;\n\nexport const DEFAULT_SIGNAL_PING_TIMEOUT = 12_000;\nexport const DEFAULT_SIGNAL_PING_INTERVAL = 3_000;\nexport const PONG_RESPONSE_TIMES_SIZE = 5;\n\nexport const SUBSCRIBE_ICE_CONNECTION_CALLBACK_ID = 'SUBSCRIBE_ICE_CONNECTION_CALLBACK_ID';\nexport const SUBSCRIBE_TIMEOUT = 60_000;\n\nexport const ICE_DISCONNECTION_TIMEOUT = 5_000;\n\nexport const RTC_STATS_MONITOR_INTERVAL = 1_000;\n\nexport const MAINTAIN_TRACK_HISTORY = false;\n\nexport const CLIENT_ANAYLTICS_PROD_ENDPOINT = 'https://event.100ms.live/v2/client/report';\nexport const CLIENT_ANAYLTICS_QA_ENDPOINT = 'https://event-nonprod.100ms.live/v2/client/report';\nexport const CLIENT_ANAYLTICS_STORAGE_LIMIT = 100;\n\nexport const PUBLISH_STATS_SAMPLE_WINDOW = 30;\nexport const PUBLISH_STATS_PUSH_INTERVAL = 300;\n\nexport const SUBSCRIBE_STATS_SAMPLE_WINDOW = 10;\nexport const SUBSCRIBE_STATS_PUSH_INTERVAL = 60;\n\nexport const HMSEvents = {\n  DEVICE_CHANGE: 'device-change',\n  LOCAL_AUDIO_ENABLED: 'local-audio-enabled',\n  LOCAL_VIDEO_ENABLED: 'local-video-enabled',\n  STATS_UPDATE: 'stats-update', // emitted by HMSWebrtcInternals\n  RTC_STATS_UPDATE: 'rtc-stats-update', // emitted by RTCStatsMonitor\n  TRACK_DEGRADED: 'track-degraded',\n  TRACK_RESTORED: 'track-restored',\n  TRACK_AUDIO_LEVEL_UPDATE: 'track-audio-level-update',\n  LOCAL_AUDIO_SILENCE: 'local-audio-silence',\n  ANALYTICS: 'analytics',\n  AUDIO_PLUGIN_FAILED: 'audio-plugin-failed',\n  POLICY_CHANGE: 'policy-change',\n  LOCAL_ROLE_UPDATE: 'local-role-update',\n  AUDIO_TRACK_UPDATE: 'audio-track-update',\n  AUDIO_TRACK_ADDED: 'audio-track-added',\n  AUDIO_TRACK_REMOVED: 'audio-track-removed',\n  AUTOPLAY_ERROR: 'autoplay-error',\n  LEAVE: 'leave',\n};\n\nexport const PROTOCOL_VERSION = '2.5';\n\nexport const PROTOCOL_SPEC = '20231201';\n\nexport const HAND_RAISE_GROUP_NAME = '_handraise';\n\nexport const DEFAULT_PLAYLIST_VIDEO_BITRATE = 1000;\n\nexport const DEFAULT_PLAYLIST_AUDIO_BITRATE = 64;\n","import { HMSPeer as IHMSPeer } from '../../../interfaces/peer';\nimport { HMSRole } from '../../../interfaces/role';\nimport { HMSAudioTrack, HMSTrack, HMSVideoTrack } from '../../../media/tracks';\nimport { HAND_RAISE_GROUP_NAME } from '../../../utils/constants';\n\nexport type HMSPeerInit = {\n  peerId: string;\n  name: string;\n  isLocal: boolean;\n  customerUserId?: string;\n  metadata?: string;\n  role?: HMSRole;\n  joinedAt?: Date;\n  fromRoomState?: boolean;\n  metworkQuality?: number;\n  groups?: string[];\n  realtime?: boolean;\n  isHandRaised?: boolean;\n};\n\nexport class HMSPeer implements IHMSPeer {\n  readonly peerId: string;\n  readonly isLocal: boolean;\n  name: string;\n  customerUserId?: string = '';\n  metadata?: string = '';\n  audioTrack?: HMSAudioTrack;\n  videoTrack?: HMSVideoTrack;\n  auxiliaryTracks: HMSTrack[] = [];\n  role?: HMSRole;\n  joinedAt?: Date;\n  networkQuality?: number;\n  groups?: string[];\n  realtime?: boolean;\n\n  constructor({ peerId, name, isLocal, customerUserId, metadata, role, joinedAt, groups, realtime }: HMSPeerInit) {\n    this.name = name;\n    this.peerId = peerId;\n    this.isLocal = isLocal;\n    this.customerUserId = customerUserId;\n    this.metadata = metadata;\n    this.joinedAt = joinedAt;\n    this.groups = groups;\n    this.realtime = realtime;\n\n    if (role) {\n      this.role = role;\n    }\n  }\n\n  get isHandRaised() {\n    return !!this.groups?.includes(HAND_RAISE_GROUP_NAME);\n  }\n\n  /**\n   * @internal\n   */\n  updateRole(newRole: HMSRole) {\n    this.role = newRole;\n  }\n  /**\n   * @internal\n   */\n  updateName(newName: string) {\n    this.name = newName;\n  }\n\n  updateNetworkQuality(quality: number) {\n    this.networkQuality = quality;\n  }\n  /**\n   * @internal\n   */\n  updateMetadata(data: string) {\n    this.metadata = data;\n  }\n\n  updateGroups(groups: string[]) {\n    this.groups = groups;\n  }\n\n  toString() {\n    return `{\n      name: ${this.name};\n      role: ${this.role?.name};\n      peerId: ${this.peerId};\n      customerUserId: ${this.customerUserId};\n      ${this.audioTrack ? `audioTrack: ${this.audioTrack?.trackId};` : ''}\n      ${this.videoTrack ? `videoTrack: ${this.videoTrack?.trackId};` : ''}\n      groups: ${this.groups?.join()}\n    }`;\n  }\n}\n","import { v4 as uuidv4 } from 'uuid';\n\nexport default class HMSIdFactory {\n  static makePeerId = () => uuidv4();\n}\n","import { HMSPeer, HMSPeerInit } from './HMSPeer';\nimport { HMSLocalPeer as IHMSLocalPeer } from '../../../interfaces/peer';\nimport { HMSRole } from '../../../interfaces/role';\nimport { HMSLocalAudioTrack, HMSLocalTrack, HMSLocalVideoTrack } from '../../../media/tracks';\nimport HMSIdFactory from '../../../utils/id-factory';\n\ntype HMSLocalPeerInit = Omit<HMSPeerInit, 'isLocal' | 'peerId'> & { asRole?: HMSRole };\n\nexport class HMSLocalPeer extends HMSPeer implements IHMSLocalPeer {\n  isLocal = true;\n  declare audioTrack?: HMSLocalAudioTrack;\n  declare videoTrack?: HMSLocalVideoTrack;\n  auxiliaryTracks: HMSLocalTrack[] = [];\n  asRole?: HMSRole;\n\n  constructor(peerData: HMSLocalPeerInit) {\n    super({ ...peerData, peerId: HMSIdFactory.makePeerId(), isLocal: true });\n    this.asRole = peerData.asRole;\n  }\n\n  isInPreview() {\n    return !!this.asRole;\n  }\n\n  toString(): string {\n    return `{\n      name: ${this.name};\n      role: ${this.role?.name};\n      peerId: ${this.peerId};\n      customerUserId: ${this.customerUserId};\n      ${this.asRole ? `asRole: ${this.asRole.name};` : ''}\n      ${this.audioTrack ? `audioTrack: ${this.audioTrack?.trackId};` : ''}\n      ${this.videoTrack ? `videoTrack: ${this.videoTrack?.trackId};` : ''}\n    }`;\n  }\n}\n","import { UAParser } from 'ua-parser-js';\n\nexport const parsedUserAgent = new UAParser();\n\nexport const isBrowser = typeof window !== 'undefined';\n\nexport const isNode =\n  typeof window === 'undefined' && !parsedUserAgent.getBrowser().name?.toLowerCase().includes('electron');\n\nexport enum ENV {\n  PROD = 'prod',\n  QA = 'qa',\n  DEV = 'dev',\n}\n\nconst checkIsSupported = () => {\n  if (isNode) {\n    return false;\n  }\n  // @TODO: Get this from preview/init API from server\n  return true;\n};\n\nexport const isSupported = checkIsSupported();\n\nexport const isMobile = () => parsedUserAgent.getDevice().type === 'mobile';\n\nexport const isPageHidden = () => typeof document !== 'undefined' && document.hidden;\n\nexport const isIOS = () => parsedUserAgent.getOS().name?.toLowerCase() === 'ios';\n","import { HMSPeer, HMSPeerInit } from './HMSPeer';\nimport { HMSRemotePeer as IHMSRemotePeer } from '../../../interfaces/peer';\nimport { HMSRemoteAudioTrack, HMSRemoteTrack, HMSRemoteVideoTrack } from '../../../media/tracks';\n\ntype HMSRemotePeerInit = Omit<HMSPeerInit, 'isLocal'>;\n\nexport class HMSRemotePeer extends HMSPeer implements IHMSRemotePeer {\n  isLocal = false;\n  declare audioTrack?: HMSRemoteAudioTrack;\n  declare videoTrack?: HMSRemoteVideoTrack;\n  auxiliaryTracks: HMSRemoteTrack[] = [];\n  fromRoomState = false;\n\n  constructor(peerData: HMSRemotePeerInit) {\n    super({ ...peerData, isLocal: false });\n    this.fromRoomState = !!peerData.fromRoomState;\n  }\n}\n","import { HMSRemotePeer } from '../../sdk/models/peer';\nimport { IStore } from '../../sdk/store';\nimport { PeerNotificationInfo } from '../HMSNotifications';\n\nexport const createRemotePeer = (notifPeer: PeerNotificationInfo, store: IStore) => {\n  return new HMSRemotePeer({\n    peerId: notifPeer.peer_id,\n    name: notifPeer.info.name,\n    role: store.getPolicyForRole(notifPeer.role),\n    customerUserId: notifPeer.info.user_id,\n    metadata: notifPeer.info.data,\n    groups: notifPeer.groups,\n  });\n};\n","import { HMSRemotePeer } from './models/peer';\nimport { IStore } from './store';\nimport { HMSPeerListIteratorOptions } from '../interfaces/peer-list-iterator';\nimport { PeerNotificationInfo } from '../notification-manager';\nimport { createRemotePeer } from '../notification-manager/managers/utils';\nimport { PeersIterationResponse } from '../signal/interfaces';\nimport ITransport from '../transport/ITransport';\n\nexport class HMSPeerListIterator {\n  private isEnd = false;\n  private iterator: string | null = null;\n  private total = 0;\n  private defaultPaginationLimit = 10;\n  constructor(private transport: ITransport, private store: IStore, private options?: HMSPeerListIteratorOptions) {}\n\n  private validateConnection() {\n    if (!this.transport || !this.store) {\n      throw Error(`Use usePaginatedParticipants or hmsActions.getPeerListIterator after preview or join has happened`);\n    }\n  }\n\n  hasNext(): boolean {\n    return !this.isEnd;\n  }\n\n  getTotal(): number {\n    return this.total;\n  }\n\n  async findPeers() {\n    this.validateConnection();\n    const response = await this.transport.findPeers({\n      ...(this.options || {}),\n      limit: this.options?.limit || this.defaultPaginationLimit,\n    });\n    this.updateState(response);\n    return this.processPeers(response.peers);\n  }\n\n  async next() {\n    this.validateConnection();\n    let response: PeersIterationResponse;\n    if (!this.iterator && !this.isEnd) {\n      return await this.findPeers();\n    } else if (this.iterator) {\n      response = await this.transport.peerIterNext({\n        iterator: this.iterator,\n        limit: this.options?.limit || this.defaultPaginationLimit,\n      });\n      this.updateState(response);\n      return this.processPeers(response.peers);\n    }\n    return [];\n  }\n\n  private processPeers(peers: PeerNotificationInfo[]) {\n    const hmsPeers: HMSRemotePeer[] = [];\n    peers.forEach(peer => {\n      const hmsPeer = createRemotePeer(peer, this.store);\n      hmsPeers.push(hmsPeer);\n    });\n    return hmsPeers;\n  }\n\n  private updateState(response: PeersIterationResponse) {\n    this.isEnd = response.eof;\n    this.total = response.total;\n    // iterator is only received once in findpeer -  reuse the same iterator\n    if (response.iterator) {\n      this.iterator = response.iterator;\n    }\n  }\n}\n","import { v4 as uuid } from 'uuid';\nimport { IStore } from './store';\nimport AnalyticsEventFactory from '../analytics/AnalyticsEventFactory';\nimport { AnalyticsTimer, TimedEvent } from '../analytics/AnalyticsTimer';\nimport { DeviceManager } from '../device-manager';\nimport { ErrorCodes } from '../error/ErrorCodes';\nimport { ErrorFactory } from '../error/ErrorFactory';\nimport { HMSAction } from '../error/HMSAction';\nimport { HMSException } from '../error/HMSException';\nimport { BuildGetMediaError, HMSGetMediaActions } from '../error/utils';\nimport { EventBus } from '../events/EventBus';\nimport { HMSAudioCodec, HMSScreenShareConfig, HMSVideoCodec, ScreenCaptureHandleConfig } from '../interfaces';\nimport InitialSettings from '../interfaces/settings';\nimport { HMSLocalAudioTrack, HMSLocalTrack, HMSLocalVideoTrack, HMSTrackType } from '../internal';\nimport {\n  HMSAudioTrackSettings,\n  HMSAudioTrackSettingsBuilder,\n  HMSTrackSettings,\n  HMSTrackSettingsBuilder,\n  HMSVideoTrackSettings,\n  HMSVideoTrackSettingsBuilder,\n} from '../media/settings';\nimport { HMSLocalStream } from '../media/streams/HMSLocalStream';\nimport { IFetchAVTrackOptions } from '../transport/ITransport';\nimport ITransportObserver from '../transport/ITransportObserver';\nimport HMSLogger from '../utils/logger';\nimport { HMSAudioContextHandler } from '../utils/media';\n\nconst defaultSettings = {\n  isAudioMuted: false,\n  isVideoMuted: false,\n  audioInputDeviceId: 'default',\n  audioOutputDeviceId: 'default',\n  videoDeviceId: 'default',\n};\n\nlet blankCanvas: HTMLCanvasElement | undefined;\nlet intervalID: ReturnType<typeof setInterval> | undefined;\n\nexport class LocalTrackManager {\n  readonly TAG: string = '[LocalTrackManager]';\n  private captureHandleIdentifier?: string;\n\n  constructor(\n    private store: IStore,\n    private observer: ITransportObserver,\n    private deviceManager: DeviceManager,\n    private eventBus: EventBus,\n    private analyticsTimer: AnalyticsTimer,\n  ) {\n    this.setScreenCaptureHandleConfig();\n  }\n\n  // eslint-disable-next-line complexity\n  async getTracksToPublish(initialSettings: InitialSettings = defaultSettings): Promise<HMSLocalTrack[]> {\n    const trackSettings = this.getAVTrackSettings(initialSettings);\n    if (!trackSettings) {\n      return [];\n    }\n    const canPublishAudio = !!trackSettings.audio;\n    const canPublishVideo = !!trackSettings.video;\n    let tracksToPublish: Array<HMSLocalTrack> = [];\n    const { videoTrack, audioTrack } = await this.updateCurrentLocalTrackSettings(trackSettings);\n    const localStream = (videoTrack?.stream || audioTrack?.stream) as HMSLocalStream | undefined;\n    // The track gets added to the store only after it is published.\n    const isVideoTrackPublished = Boolean(videoTrack && this.store.getTrackById(videoTrack.trackId));\n    const isAudioTrackPublished = Boolean(audioTrack && this.store.getTrackById(audioTrack.trackId));\n\n    if (isVideoTrackPublished && isAudioTrackPublished) {\n      // there is nothing to publish\n      return [];\n    }\n\n    const fetchTrackOptions: IFetchAVTrackOptions = {\n      audio: canPublishAudio && !audioTrack && (initialSettings.isAudioMuted ? 'empty' : true),\n      video: canPublishVideo && !videoTrack && (initialSettings.isVideoMuted ? 'empty' : true),\n    };\n\n    if (fetchTrackOptions.audio) {\n      this.analyticsTimer.start(TimedEvent.LOCAL_AUDIO_TRACK);\n    }\n    if (fetchTrackOptions.video) {\n      this.analyticsTimer.start(TimedEvent.LOCAL_VIDEO_TRACK);\n    }\n    try {\n      HMSLogger.d(this.TAG, 'Init Local Tracks', { fetchTrackOptions });\n      tracksToPublish = await this.getLocalTracks(fetchTrackOptions, trackSettings, localStream);\n    } catch (error) {\n      tracksToPublish = await this.retryGetLocalTracks(\n        error as HMSException,\n        trackSettings,\n        fetchTrackOptions,\n        localStream,\n      );\n    }\n    if (fetchTrackOptions.audio) {\n      this.analyticsTimer.end(TimedEvent.LOCAL_AUDIO_TRACK);\n    }\n    if (fetchTrackOptions.video) {\n      this.analyticsTimer.end(TimedEvent.LOCAL_VIDEO_TRACK);\n    }\n\n    if (videoTrack && canPublishVideo && !isVideoTrackPublished) {\n      tracksToPublish.push(videoTrack);\n    }\n    if (audioTrack && canPublishAudio && !isAudioTrackPublished) {\n      tracksToPublish.push(audioTrack);\n    }\n    return tracksToPublish;\n  }\n\n  /**\n   * @throws {HMSException}\n   */\n  async getLocalTracks(\n    fetchTrackOptions: IFetchAVTrackOptions = { audio: true, video: true },\n    settings: HMSTrackSettings,\n    localStream?: HMSLocalStream,\n  ): Promise<Array<HMSLocalTrack>> {\n    try {\n      const nativeTracks = await this.getNativeLocalTracks(fetchTrackOptions, settings);\n      return this.createHMSLocalTracks(nativeTracks, settings, localStream);\n    } catch (error) {\n      // TOOD: On OverConstrained error, retry with dropping all constraints.\n      // Just retry getusermedia again - it sometimes work when AbortError or NotFoundError is thrown on a few devices\n      this.eventBus.analytics.publish(\n        AnalyticsEventFactory.publish({\n          devices: this.deviceManager.getDevices(),\n          error: error as Error,\n          settings,\n        }),\n      );\n      throw error;\n    }\n  }\n\n  /**\n   * @throws {HMSException}\n   */\n  private async getNativeLocalTracks(\n    fetchTrackOptions: IFetchAVTrackOptions = { audio: false, video: false },\n    settings: HMSTrackSettings,\n  ) {\n    const trackSettings = new HMSTrackSettings(\n      fetchTrackOptions.video === true ? settings.video : null,\n      fetchTrackOptions.audio === true ? settings.audio : null,\n      settings.simulcast,\n    );\n    const nativeTracks: MediaStreamTrack[] = [];\n\n    if (trackSettings.audio || trackSettings.video) {\n      nativeTracks.push(...(await this.getAVTracks(trackSettings)));\n    }\n    nativeTracks.push(...this.getEmptyTracks(fetchTrackOptions));\n    return nativeTracks;\n  }\n\n  async getLocalScreen(partialConfig?: HMSScreenShareConfig) {\n    const config = await this.getOrDefaultScreenshareConfig(partialConfig);\n    const screenSettings = this.getScreenshareSettings(config.videoOnly);\n    const constraints = {\n      video: { ...screenSettings?.video.toConstraints(true), displaySurface: config.displaySurface },\n      preferCurrentTab: config.preferCurrentTab,\n      selfBrowserSurface: config.selfBrowserSurface,\n      surfaceSwitching: config.surfaceSwitching,\n      systemAudio: config.systemAudio,\n    } as MediaStreamConstraints;\n    if (screenSettings?.audio) {\n      const audioConstraints: MediaTrackConstraints = screenSettings?.audio?.toConstraints();\n      // remove advanced constraints as it not supported for screenshare audio\n      delete audioConstraints.advanced;\n      constraints.audio = {\n        ...audioConstraints,\n        autoGainControl: false,\n        noiseSuppression: false,\n        // @ts-ignore\n        googAutoGainControl: false,\n        echoCancellation: false,\n      };\n    }\n    let stream;\n    try {\n      HMSLogger.d('retrieving screenshare with ', { config }, { constraints });\n      // @ts-ignore [https://github.com/microsoft/TypeScript/issues/33232]\n      stream = (await navigator.mediaDevices.getDisplayMedia(constraints)) as MediaStream;\n    } catch (err) {\n      HMSLogger.w(this.TAG, 'error in getting screenshare - ', err);\n      const error = BuildGetMediaError(err as Error, HMSGetMediaActions.SCREEN);\n      this.eventBus.analytics.publish(\n        AnalyticsEventFactory.publish({\n          error: error as Error,\n          devices: this.deviceManager.getDevices(),\n          settings: new HMSTrackSettings(screenSettings?.video, screenSettings?.audio, false),\n        }),\n      );\n      throw error;\n    }\n\n    const tracks: Array<HMSLocalTrack> = [];\n    const local = new HMSLocalStream(stream);\n    const nativeVideoTrack = stream.getVideoTracks()[0];\n    const videoTrack = new HMSLocalVideoTrack(local, nativeVideoTrack, 'screen', this.eventBus, screenSettings?.video);\n    videoTrack.setSimulcastDefinitons(this.store.getSimulcastDefinitionsForPeer(this.store.getLocalPeer()!, 'screen'));\n\n    try {\n      const isCurrentTabShared = this.validateCurrentTabCapture(videoTrack, config.forceCurrentTab);\n      videoTrack.isCurrentTab = isCurrentTabShared;\n      await videoTrack.cropTo(config.cropTarget);\n    } catch (err) {\n      stream.getTracks().forEach(track => track.stop());\n      throw err;\n    }\n\n    tracks.push(videoTrack);\n    const nativeAudioTrack = stream.getAudioTracks()[0];\n    if (nativeAudioTrack) {\n      const audioTrack = new HMSLocalAudioTrack(\n        local,\n        nativeAudioTrack,\n        'screen',\n        this.eventBus,\n        screenSettings?.audio,\n      );\n      tracks.push(audioTrack);\n    }\n\n    HMSLogger.v(this.TAG, 'getLocalScreen', tracks);\n    return tracks;\n  }\n\n  setScreenCaptureHandleConfig(config?: Partial<ScreenCaptureHandleConfig>) {\n    // @ts-ignore\n    if (!navigator.mediaDevices?.setCaptureHandleConfig || this.isInIframe()) {\n      // setCaptureHandleConfig can't be called from within an iframe\n      return;\n    }\n    config = config || {};\n    Object.assign(config, { handle: uuid(), exposeOrigin: false, permittedOrigins: [window.location.origin] });\n    HMSLogger.d('setting capture handle - ', config.handle);\n    // @ts-ignore\n    navigator.mediaDevices.setCaptureHandleConfig(config);\n    this.captureHandleIdentifier = config.handle;\n  }\n\n  validateCurrentTabCapture(track: HMSLocalVideoTrack, forceCurrentTab: boolean): boolean {\n    const trackHandle = track.getCaptureHandle();\n    const isCurrentTabShared = !!(this.captureHandleIdentifier && trackHandle?.handle === this.captureHandleIdentifier);\n    if (forceCurrentTab && !isCurrentTabShared) {\n      HMSLogger.e(this.TAG, 'current tab was not shared with forceCurrentTab as true');\n      throw ErrorFactory.TracksErrors.CurrentTabNotShared();\n    }\n    return isCurrentTabShared;\n  }\n\n  async requestPermissions() {\n    try {\n      const stream = await navigator.mediaDevices.getUserMedia({\n        audio: true,\n        video: true,\n      });\n      // Stop stream\n      stream.getTracks().forEach(track => track.stop());\n    } catch (error) {\n      HMSLogger.e(this.TAG, error);\n    }\n  }\n\n  static getEmptyVideoTrack(prevTrack?: MediaStreamTrack): MediaStreamTrack {\n    const width = prevTrack?.getSettings()?.width || 320;\n    const height = prevTrack?.getSettings()?.height || 240;\n    const frameRate = 1; // fps TODO: experiment, see if this can be reduced\n    if (!blankCanvas) {\n      blankCanvas = document.createElement('canvas');\n      blankCanvas.width = width;\n      blankCanvas.height = height;\n      blankCanvas.getContext('2d')?.fillRect(0, 0, width, height);\n    }\n    if (!intervalID) {\n      // This is needed to send some data so the track is received on sfu\n      intervalID = setInterval(() => {\n        const ctx = blankCanvas?.getContext('2d');\n        if (ctx) {\n          ctx.fillRect(0, 0, 1, 1);\n        }\n      }, 1000 / frameRate);\n    }\n\n    const stream = blankCanvas.captureStream(frameRate);\n    const emptyTrack = stream.getVideoTracks()[0];\n    emptyTrack.enabled = false;\n    return emptyTrack;\n  }\n\n  static getEmptyAudioTrack(): MediaStreamTrack {\n    const ctx = HMSAudioContextHandler.getAudioContext();\n    const oscillator = ctx.createOscillator();\n    const dst = ctx.createMediaStreamDestination();\n    oscillator.connect(dst);\n    oscillator.start();\n    const emptyTrack = dst.stream.getAudioTracks()[0];\n    emptyTrack.enabled = false;\n    return emptyTrack;\n  }\n\n  static cleanup() {\n    clearInterval(intervalID);\n    intervalID = undefined;\n    blankCanvas = undefined;\n  }\n\n  /**\n   * @throws {HMSException}\n   */\n  private async getAVTracks(settings: HMSTrackSettings): Promise<Array<MediaStreamTrack>> {\n    try {\n      const stream = await navigator.mediaDevices.getUserMedia({\n        audio: settings.audio ? settings.audio.toConstraints() : false,\n        video: settings.video ? settings.video.toConstraints() : false,\n      });\n\n      return stream.getVideoTracks().concat(stream.getAudioTracks());\n    } catch (error) {\n      await this.deviceManager.init();\n      const videoError = !!(!this.deviceManager.hasWebcamPermission && settings.video);\n      const audioError = !!(!this.deviceManager.hasMicrophonePermission && settings.audio);\n      /**\n       * TODO: Only permission error throws correct device info in error(audio or video or both),\n       * Right now for other errors such as overconstrained error we are unable to get whether audio/video failure.\n       * Fix this by checking the native error message.\n       */\n      const errorType = this.getErrorType(videoError, audioError);\n      throw BuildGetMediaError(error as Error, errorType);\n    }\n  }\n\n  private getAVTrackSettings(initialSettings: InitialSettings): HMSTrackSettings | null {\n    const audioSettings = this.getAudioSettings(initialSettings);\n    const videoSettings = this.getVideoSettings(initialSettings);\n    if (!audioSettings && !videoSettings) {\n      return null;\n    }\n    return new HMSTrackSettingsBuilder().video(videoSettings).audio(audioSettings).build();\n  }\n\n  private isInIframe() {\n    try {\n      return window.self !== window.top;\n    } catch (e) {\n      return true;\n    }\n  }\n\n  // eslint-disable-next-line complexity\n  private async retryGetLocalTracks(\n    error: HMSException,\n    trackSettings: HMSTrackSettings,\n    fetchTrackOptions: IFetchAVTrackOptions,\n    localStream?: HMSLocalStream,\n  ): Promise<Array<HMSLocalTrack>> {\n    if (error instanceof HMSException && error.action === HMSAction.TRACK) {\n      this.observer.onFailure(error);\n\n      const overConstrainedFailure = error.code === ErrorCodes.TracksErrors.OVER_CONSTRAINED;\n      const audioFailure = error.message.includes('audio');\n      const videoFailure = error.message.includes('video');\n      if (overConstrainedFailure) {\n        // TODO: Use this once TODO@L#250 is completed\n        // const newTrackSettings = new HMSTrackSettingsBuilder()\n        //   .video(videoFailure ? new HMSVideoTrackSettings() : trackSettings.video)\n        //   .audio(audioFailure ? new HMSAudioTrackSettings() : trackSettings.audio)\n        //   .build();\n        const newTrackSettings = new HMSTrackSettingsBuilder()\n          .video(new HMSVideoTrackSettings())\n          .audio(new HMSAudioTrackSettings())\n          .build();\n\n        HMSLogger.w(this.TAG, 'Fetch AV Tracks failed with overconstrained error', { fetchTrackOptions }, { error });\n\n        try {\n          // Try get local tracks with no constraints\n          return await this.getLocalTracks(fetchTrackOptions, newTrackSettings, localStream);\n        } catch (error) {\n          /**\n           * This error shouldn't be overconstrained error(as we've dropped all constraints).\n           * If it's an overconstrained error, change error code to avoid recursive loop\n           * Try get local tracks for empty tracks\n           */\n          const nativeError: Error | undefined = error instanceof HMSException ? error.nativeError : (error as Error);\n          let ex = error;\n          if (nativeError?.name === 'OverconstrainedError') {\n            const newError = ErrorFactory.TracksErrors.GenericTrack(\n              HMSAction.TRACK,\n              'Overconstrained error after dropping all constraints',\n            );\n            newError.addNativeError(nativeError);\n            ex = newError;\n          }\n\n          return await this.retryGetLocalTracks(ex as HMSException, trackSettings, fetchTrackOptions, localStream);\n        }\n      }\n\n      fetchTrackOptions.audio = audioFailure ? 'empty' : fetchTrackOptions.audio;\n      fetchTrackOptions.video = videoFailure ? 'empty' : fetchTrackOptions.video;\n      HMSLogger.w(this.TAG, 'Fetch AV Tracks failed', { fetchTrackOptions }, error);\n      try {\n        return await this.getLocalTracks(fetchTrackOptions, trackSettings, localStream);\n      } catch (error) {\n        HMSLogger.w(this.TAG, 'Fetch empty tacks failed', error);\n        fetchTrackOptions.audio = fetchTrackOptions.audio && 'empty';\n        fetchTrackOptions.video = fetchTrackOptions.video && 'empty';\n        this.observer.onFailure(error as HMSException);\n        return await this.getLocalTracks(fetchTrackOptions, trackSettings, localStream);\n      }\n    } else {\n      HMSLogger.w(this.TAG, 'Fetch AV Tracks failed - unknown exception', error);\n      this.observer.onFailure(error);\n      return [];\n    }\n  }\n\n  private getErrorType(videoError: boolean, audioError: boolean): HMSGetMediaActions {\n    if (videoError && audioError) {\n      return HMSGetMediaActions.AV;\n    }\n    if (videoError) {\n      return HMSGetMediaActions.VIDEO;\n    }\n    if (audioError) {\n      return HMSGetMediaActions.AUDIO;\n    }\n    return HMSGetMediaActions.UNKNOWN;\n  }\n\n  private getEmptyTracks(fetchTrackOptions: IFetchAVTrackOptions) {\n    const nativeTracks: MediaStreamTrack[] = [];\n    if (fetchTrackOptions.audio === 'empty') {\n      nativeTracks.push(LocalTrackManager.getEmptyAudioTrack());\n    }\n\n    if (fetchTrackOptions.video === 'empty') {\n      nativeTracks.push(LocalTrackManager.getEmptyVideoTrack());\n    }\n    return nativeTracks;\n  }\n\n  private async updateCurrentLocalTrackSettings(trackSettings: HMSTrackSettings | null) {\n    const localTracks = this.store.getLocalPeerTracks();\n    const videoTrack = localTracks.find(t => t.type === HMSTrackType.VIDEO && t.source === 'regular') as\n      | HMSLocalVideoTrack\n      | undefined;\n    const audioTrack = localTracks.find(t => t.type === HMSTrackType.AUDIO && t.source === 'regular') as\n      | HMSLocalAudioTrack\n      | undefined;\n\n    const screenVideoTrack = localTracks.find(t => t.type === HMSTrackType.VIDEO && t.source === 'screen') as\n      | HMSLocalVideoTrack\n      | undefined;\n\n    if (trackSettings?.video) {\n      await videoTrack?.setSettings(trackSettings.video);\n    }\n\n    if (trackSettings?.audio) {\n      await audioTrack?.setSettings(trackSettings.audio);\n    }\n\n    const screenSettings = this.getScreenshareSettings(true);\n    if (screenSettings?.video) {\n      await screenVideoTrack?.setSettings(screenSettings?.video);\n    }\n\n    return { videoTrack, audioTrack };\n  }\n\n  private getAudioSettings(initialSettings: InitialSettings) {\n    const publishParams = this.store.getPublishParams();\n    if (!publishParams || !publishParams.allowed?.includes('audio')) {\n      return null;\n    }\n    const localPeer = this.store.getLocalPeer();\n    const audioTrack = localPeer?.audioTrack;\n    // Get device from the tracks already added in preview\n    const audioDeviceId = audioTrack?.settings.deviceId || initialSettings.audioInputDeviceId;\n\n    return new HMSAudioTrackSettingsBuilder()\n      .codec(publishParams.audio.codec as HMSAudioCodec)\n      .maxBitrate(publishParams.audio.bitRate)\n      .deviceId(audioDeviceId || defaultSettings.audioInputDeviceId)\n      .build();\n  }\n\n  private getVideoSettings(initialSettings: InitialSettings) {\n    const publishParams = this.store.getPublishParams();\n    if (!publishParams || !publishParams.allowed?.includes('video')) {\n      return null;\n    }\n    const localPeer = this.store.getLocalPeer();\n    const videoTrack = localPeer?.videoTrack;\n    // Get device from the tracks already added in preview\n    const videoDeviceId = videoTrack?.settings.deviceId || initialSettings.videoDeviceId;\n    const video = publishParams.video;\n    return new HMSVideoTrackSettingsBuilder()\n      .codec(video.codec as HMSVideoCodec)\n      .maxBitrate(video.bitRate)\n      .maxFramerate(video.frameRate)\n      .setWidth(video.width) // take simulcast width if available\n      .setHeight(video.height) // take simulcast width if available\n      .deviceId(videoDeviceId || defaultSettings.videoDeviceId)\n      .build();\n  }\n\n  private getScreenshareSettings(isVideoOnly = false) {\n    const publishParams = this.store.getPublishParams();\n    if (!publishParams || !publishParams.allowed?.includes('screen')) {\n      return null;\n    }\n    const screen = publishParams.screen;\n    return {\n      video: new HMSVideoTrackSettingsBuilder()\n        // Don't cap maxBitrate for screenshare.\n        // If publish params doesn't have bitRate value - don't set maxBitrate.\n        .maxBitrate(screen.bitRate, false)\n        .codec(screen.codec as HMSVideoCodec)\n        .maxFramerate(screen.frameRate)\n        .setWidth(screen.width)\n        .setHeight(screen.height)\n        .build(),\n      audio: isVideoOnly ? undefined : new HMSAudioTrackSettingsBuilder().build(),\n    };\n  }\n\n  // eslint-disable-next-line complexity\n  private async getOrDefaultScreenshareConfig(partialConfig?: Partial<HMSScreenShareConfig>) {\n    type RequiredConfig = HMSScreenShareConfig &\n      Required<Omit<HMSScreenShareConfig, 'cropTarget' | 'cropElement' | 'displaySurface'>>;\n    const config: RequiredConfig = Object.assign(\n      {\n        videoOnly: false,\n        audioOnly: false,\n        forceCurrentTab: false,\n        preferCurrentTab: false,\n        selfBrowserSurface: 'exclude', // don't give self tab in options\n        surfaceSwitching: 'include', // give option to switch tabs while sharing\n        systemAudio: 'exclude', // system audio share leads to echo in windows\n        displaySurface: 'monitor',\n      },\n      partialConfig || {},\n    );\n    if (config.forceCurrentTab) {\n      config.videoOnly = true; // there will be echo otherwise\n      config.preferCurrentTab = true;\n      config.selfBrowserSurface = 'include';\n      config.surfaceSwitching = 'exclude';\n    }\n    if (config.preferCurrentTab) {\n      config.selfBrowserSurface = 'include';\n      config.displaySurface = undefined; // so the default selected is the current tab\n    }\n    // @ts-ignore\n    if (config.cropElement && window.CropTarget?.fromElement) {\n      // @ts-ignore\n      config.cropTarget = await window.CropTarget.fromElement(config.cropElement);\n    }\n    return config;\n  }\n\n  private createHMSLocalTracks(\n    nativeTracks: MediaStreamTrack[],\n    settings: HMSTrackSettings,\n    localStream?: HMSLocalStream,\n  ) {\n    const nativeVideoTrack = nativeTracks.find(track => track.kind === 'video');\n    const nativeAudioTrack = nativeTracks.find(track => track.kind === 'audio');\n    if (localStream) {\n      nativeTracks.forEach(track => localStream?.nativeStream.addTrack(track));\n    } else {\n      localStream = new HMSLocalStream(new MediaStream(nativeTracks));\n    }\n\n    const tracks: Array<HMSLocalTrack> = [];\n    if (nativeAudioTrack && settings?.audio) {\n      const audioTrack = new HMSLocalAudioTrack(\n        localStream,\n        nativeAudioTrack,\n        'regular',\n        this.eventBus,\n        settings.audio,\n      );\n      tracks.push(audioTrack);\n    }\n\n    if (nativeVideoTrack && settings?.video) {\n      const videoTrack = new HMSLocalVideoTrack(\n        localStream,\n        nativeVideoTrack,\n        'regular',\n        this.eventBus,\n        settings.video,\n      );\n      videoTrack.setSimulcastDefinitons(\n        this.store.getSimulcastDefinitionsForPeer(this.store.getLocalPeer()!, 'regular'),\n      );\n      tracks.push(videoTrack);\n    }\n    return tracks;\n  }\n}\n","import { v4 as uuid } from 'uuid';\nimport { AnalyticsEventLevel } from './AnalyticsEventLevel';\nimport { domainCategory } from './domain-analytics';\nimport { ISignalParamsProvider } from '../signal/ISignalSendParamsProvider';\nimport { getAnalyticsDeviceId } from '../utils/analytics-deviceId';\nimport { createUserAgent } from '../utils/user-agent';\n\ninterface AnalyticsEventInit {\n  name: string;\n  level: AnalyticsEventLevel;\n  includesPII?: boolean;\n  properties?: Record<string, any>;\n  timestamp?: number;\n}\n\ninterface SignalEventParams {\n  name: string;\n  info: any;\n  timestamp: number;\n}\n\nexport default class AnalyticsEvent implements ISignalParamsProvider<SignalEventParams> {\n  name: string;\n  level: AnalyticsEventLevel;\n  includesPII: boolean;\n  properties: Record<string, any>;\n  metadata: {\n    token?: string;\n    peer: {\n      peer_id?: string;\n      session_id?: string;\n      room_id?: string;\n      role?: string;\n      room_name?: string;\n      joined_at?: number;\n      template_id?: string;\n      session_started_at?: number;\n      user_name?: string;\n      user_data?: string;\n    };\n    userAgent: string;\n  } = {\n    peer: {},\n    userAgent: createUserAgent(),\n  };\n  timestamp: number;\n  event_id: string;\n  device_id: string;\n\n  constructor({ name, level, properties, includesPII, timestamp }: AnalyticsEventInit) {\n    this.name = name;\n    this.level = level;\n    this.includesPII = includesPII || false;\n    this.properties = properties || {};\n    this.timestamp = timestamp || new Date().getTime(); // Timestamp of generating the event\n    this.event_id = uuid();\n    this.device_id = getAnalyticsDeviceId();\n  }\n\n  toSignalParams() {\n    return {\n      name: this.name,\n      info: { ...this.properties, timestamp: this.timestamp, domain: domainCategory },\n      timestamp: new Date().getTime(), // Timestamp of sending the event\n    };\n  }\n}\n","import { DomainCategory } from './AnalyticsEventDomains';\nimport { isBrowser } from '../utils/support';\n\nfunction getDomainCategory() {\n  // this function gives us the domain category(sutom, hms , local) of the base url.\n  // below if statement checks if it's running in a browser ; or if we can use 'window' safely\n\n  if (isBrowser && window) {\n    const baseurl = window.location.hostname;\n\n    if (baseurl === 'localhost' || baseurl === '127.0.0.1') {\n      return DomainCategory.LOCAL;\n    }\n\n    if (baseurl.includes('app.100ms.live')) {\n      return DomainCategory.HMS;\n    } else {\n      return DomainCategory.CUSTOM;\n    }\n  }\n\n  return DomainCategory.CUSTOM;\n}\n\nexport const domainCategory = getDomainCategory();\n","import { v4 as uuid } from 'uuid';\nimport { LocalStorage } from './local-storage';\n\nexport const getAnalyticsDeviceId = () => {\n  let id;\n  const storage = new LocalStorage<string>('hms-analytics-deviceId');\n  const storageId = storage.get();\n  if (storageId) {\n    id = storageId;\n  } else {\n    id = uuid();\n    storage.set(id);\n  }\n  return id;\n};\n","export enum HMSLogLevel {\n  VERBOSE,\n  DEBUG,\n  INFO,\n  WARN,\n  TIME,\n  TIMEEND,\n  ERROR,\n  NONE,\n}\n\n// @ts-ignore - window.expect is available only when in test environment\nconst isTestEnv = typeof window !== 'undefined' && typeof window.expect !== 'undefined';\n/**\n * TODO: fix this so logs show the real file and line numbers where they originated from instead of this class\n * https://stackoverflow.com/questions/13815640/a-proper-wrapper-for-console-log-with-correct-line-number\n */\nexport default class HMSLogger {\n  static level: HMSLogLevel = isTestEnv ? HMSLogLevel.NONE : HMSLogLevel.VERBOSE;\n\n  static v(tag: string, ...data: any[]) {\n    this.log(HMSLogLevel.VERBOSE, tag, ...data);\n  }\n\n  static d(tag: string, ...data: any[]) {\n    this.log(HMSLogLevel.DEBUG, tag, ...data);\n  }\n\n  static i(tag: string, ...data: any[]) {\n    this.log(HMSLogLevel.INFO, tag, ...data);\n  }\n\n  static w(tag: string, ...data: any[]) {\n    this.log(HMSLogLevel.WARN, tag, ...data);\n  }\n\n  static e(tag: string, ...data: any[]) {\n    this.log(HMSLogLevel.ERROR, tag, ...data);\n  }\n\n  static time(mark: string) {\n    this.log(HMSLogLevel.TIME, '[HMSPerformanceTiming]', mark);\n  }\n\n  static timeEnd(mark: string) {\n    this.log(HMSLogLevel.TIMEEND, '[HMSPerformanceTiming]', mark, mark);\n  }\n\n  static cleanup() {\n    performance.clearMarks();\n    performance.clearMeasures();\n  }\n\n  // eslint-disable-next-line complexity\n  private static log(level: HMSLogLevel, tag: string, ...data: any[]) {\n    if (this.level.valueOf() > level.valueOf()) {\n      return;\n    }\n\n    switch (level) {\n      case HMSLogLevel.VERBOSE: {\n        console.log(tag, ...data);\n        break;\n      }\n      case HMSLogLevel.DEBUG: {\n        console.debug(tag, ...data);\n        break;\n      }\n      case HMSLogLevel.INFO: {\n        console.info(tag, ...data);\n        break;\n      }\n      case HMSLogLevel.WARN: {\n        console.warn(tag, ...data);\n        break;\n      }\n      case HMSLogLevel.ERROR: {\n        console.error(tag, ...data);\n        break;\n      }\n      case HMSLogLevel.TIME: {\n        performance.mark(data[0]);\n        break;\n      }\n      case HMSLogLevel.TIMEEND: {\n        const mark = data[0];\n        try {\n          const entry = performance.measure(mark, mark);\n          // @ts-ignore\n          this.log(HMSLogLevel.DEBUG, tag, mark, entry?.duration);\n          performance.clearMarks(mark);\n          performance.clearMeasures(mark);\n        } catch (error) {\n          this.log(HMSLogLevel.DEBUG, tag, mark, error);\n        }\n        break;\n      }\n    }\n  }\n}\n","/*\n * ErrorCodes.ts\n *\n * Created by codegen\n * Copyright © 2021 100ms. All rights reserved.\n */\n\nexport const ErrorCodes = {\n  // https://www.rfc-editor.org/rfc/rfc6455#section-7.4.1\n  WebSocketConnectionErrors: {\n    // Error connecting to ws or init config not available\n    FAILED_TO_CONNECT: 1000,\n\n    // Network connection lost\n    WEBSOCKET_CONNECTION_LOST: 1003,\n\n    // Abnormal close without receiving a Close control frame\n    ABNORMAL_CLOSE: 1006,\n  },\n\n  APIErrors: {\n    // [INIT]: Server error\n    SERVER_ERRORS: 2000,\n    //init config not available\n    INIT_CONFIG_NOT_AVAILABLE: 2002,\n\n    // Endpoint is not reachable.\n    ENDPOINT_UNREACHABLE: 2003,\n\n    // Token is not in proper JWT format\n    INVALID_TOKEN_FORMAT: 2004,\n  },\n\n  TracksErrors: {\n    // [PUBLISH]: Error with getusermedia request\n    GENERIC_TRACK: 3000,\n\n    // [PUBLISH]: No permission to access capture device - {device_type}\n    CANT_ACCESS_CAPTURE_DEVICE: 3001,\n\n    // [PUBLISH]: Capture device is no longer available - {device_type}\n    DEVICE_NOT_AVAILABLE: 3002,\n\n    // [PUBLISH]: Capture device is in use by another application - {device_type}\n    DEVICE_IN_USE: 3003,\n\n    // Lost access to capture device midway - {device_type}\n    DEVICE_LOST_MIDWAY: 3004,\n\n    // There is no media to return. Please select either video or audio or both.\n    NOTHING_TO_RETURN: 3005,\n\n    // Cannot enable simulcast when no video settings are provided\n    INVALID_VIDEO_SETTINGS: 3006,\n\n    // Codec can't be changed mid call.\n    CODEC_CHANGE_NOT_PERMITTED: 3007,\n\n    // When the browser throws autoplay exception if something is played before interacting\n    AUTOPLAY_ERROR: 3008,\n\n    // Over constrained error - device hardware unable to satisfy requested constraints\n    OVER_CONSTRAINED: 3009,\n\n    // No audio detected from track, indicates problem with device hardware\n    NO_AUDIO_DETECTED: 3010,\n\n    // Operating System denied permission\n    SYSTEM_DENIED_PERMISSION: 3011,\n\n    // Current tab is not shared when forceCurrentTab was set to true for screenshare\n    CURRENT_TAB_NOT_SHARED: 3012,\n\n    // any error that occurs while playing audio of remote audio tracks\n    AUDIO_PLAYBACK_ERROR: 3013,\n\n    // Selected device not detected on change\n    SELECTED_DEVICE_MISSING: 3014,\n  },\n\n  WebrtcErrors: {\n    // [{action}]: Failed to create offer.\n    CREATE_OFFER_FAILED: 4001,\n\n    // [{action}]: Failed to create answer.\n    CREATE_ANSWER_FAILED: 4002,\n\n    // [{action}]: Failed to set offer.\n    SET_LOCAL_DESCRIPTION_FAILED: 4003,\n\n    // [{action}]: Failed to set answer.\n    SET_REMOTE_DESCRIPTION_FAILED: 4004,\n\n    // [{action}]: Ice connection state FAILED\n    ICE_FAILURE: 4005,\n\n    // [{action}]: Ice connection state FAILED\n    ICE_DISCONNECTED: 4006,\n\n    STATS_FAILED: 4007,\n  },\n\n  WebsocketMethodErrors: {\n    // [JOIN]: {server_error}\n    SERVER_ERRORS: 5000,\n\n    // [JOIN]: You have already joined this room.\n    ALREADY_JOINED: 5001,\n\n    // [JOIN]: Cannot join if preview is in progress\n    CANNOT_JOIN_PREVIEW_IN_PROGRESS: 5002,\n  },\n\n  GenericErrors: {\n    // Client is not connected\n    NOT_CONNECTED: 6000,\n\n    // Unknown signalling error: {action} {error_info}\n    SIGNALLING: 6001,\n\n    // Unknown exception: {error_info}\n    UNKNOWN: 6002,\n\n    // WebRTC engine is not ready yet\n    NOT_READY: 6003,\n\n    // Failed to parse JSON message - {json_message}\n    JSON_PARSING_FAILED: 6004,\n\n    // Track Metadata Missing\n    TRACK_METADATA_MISSING: 6005,\n\n    // RTC Track missing\n    RTC_TRACK_MISSING: 6006,\n\n    // Peer Metadata Missing\n    PEER_METADATA_MISSING: 6007,\n\n    // Joined with invalid role\n    INVALID_ROLE: 6008,\n\n    PREVIEW_IN_PROGRESS: 6009,\n\n    MISSING_MEDIADEVICES: 6010,\n\n    MISSING_RTCPEERCONNECTION: 6011,\n    LOCAL_STORAGE_ACCESS_DENIED: 6012,\n    // peer not present or role not present or any general validation\n    VALIDATION_FAILED: 6013,\n  },\n\n  PlaylistErrors: {\n    NO_ENTRY_TO_PLAY: 8001,\n    NO_ENTRY_IS_PLAYING: 8002,\n  },\n};\n","import { HMSAction } from './HMSAction';\nimport { IAnalyticsPropertiesProvider } from '../analytics/IAnalyticsPropertiesProvider';\nimport { HMSSignalMethod } from '../signal/jsonrpc/models';\n\nexport class HMSException extends Error implements IAnalyticsPropertiesProvider {\n  action: string;\n  nativeError?: Error;\n\n  constructor(\n    public readonly code: number,\n    public name: string,\n    action: HMSAction | HMSSignalMethod,\n    public message: string,\n    public description: string,\n    public isTerminal: boolean = false,\n  ) {\n    super(message);\n\n    // Ref: https://github.com/Microsoft/TypeScript/wiki/Breaking-Changes#extending-built-ins-like-error-array-and-map-may-no-longer-work\n    Object.setPrototypeOf(this, HMSException.prototype);\n    this.action = action.toString();\n  }\n\n  toAnalyticsProperties() {\n    return {\n      error_name: this.name,\n      error_code: this.code,\n      error_message: this.message,\n      error_description: this.description,\n      action: this.action,\n      is_terminal: this.isTerminal,\n    };\n  }\n\n  addNativeError(error: Error) {\n    this.nativeError = error;\n  }\n\n  toString() {\n    return `{\n      code: ${this.code};\n      name: ${this.name};\n      action: ${this.action};\n      message: ${this.message};\n      description: ${this.description};\n      isTerminal: ${this.isTerminal};\n      nativeError: ${this.nativeError?.message};\n    }`;\n  }\n}\n","import { HMSAction } from '../../error/HMSAction';\n\nexport interface JsonRpcRequest {\n  id: string;\n  method: string;\n  params: Map<string, any>;\n}\n\nexport interface JsonRpcResponse {\n  id: string;\n  result: any;\n  error: {\n    code: number;\n    message: string;\n  };\n}\n\nexport enum HMSSignalMethod {\n  JOIN = 'join',\n  OFFER = 'offer',\n  ANSWER = 'answer',\n  TRICKLE = 'trickle',\n  TRACK_UPDATE = 'track-update',\n  BROADCAST = 'broadcast',\n  ANALYTICS = 'analytics',\n  SERVER_ERROR = 'on-error',\n  SERVER_WARNING = 'on-warning',\n  SDK_NOTIFICATION = 'sdk-notification',\n  LEAVE = 'leave',\n  END_ROOM = 'end-room',\n  PING = 'ping',\n  ROLE_CHANGE_REQUEST = 'role-change-request',\n  ROLE_CHANGE = 'role-change',\n  TRACK_UPDATE_REQUEST = 'track-update-request',\n  PEER_LEAVE_REQUEST = 'peer-leave-request',\n  CHANGE_TRACK_MUTE_STATE_REQUEST = 'change-track-mute-state-request',\n  START_RTMP_OR_RECORDING_REQUEST = 'rtmp-start',\n  STOP_RTMP_AND_RECORDING_REQUEST = 'rtmp-stop',\n  UPDATE_PEER_METADATA = 'peer-update',\n  START_HLS_STREAMING = 'hls-start',\n  STOP_HLS_STREAMING = 'hls-stop',\n  HLS_TIMED_METADATA = 'hls-timed-metadata',\n  SET_METADATA = 'set-metadata',\n  GET_METADATA = 'get-metadata',\n  LISTEN_METADATA_CHANGE = 'listen-metadata-change',\n  POLL_INFO_SET = 'poll-info-set',\n  POLL_INFO_GET = 'poll-info-get',\n  POLL_QUESTIONS_SET = 'poll-questions-set',\n  POLL_QUESTIONS_GET = 'poll-questions-get',\n  POLL_START = 'poll-start',\n  POLL_STOP = 'poll-stop',\n  POLL_RESPONSE_SET = 'poll-response',\n  POLL_LIST = 'poll-list',\n  POLL_RESPONSES = 'poll-responses',\n  POLL_RESULT = 'poll-result',\n  POLL_LEADERBOARD = 'poll-leaderboard',\n  GET_PEER = 'get-peer',\n  FIND_PEER = 'find-peer',\n  PEER_ITER_NEXT = 'peer-iter-next',\n  GROUP_JOIN = 'group-join',\n  GROUP_LEAVE = 'group-leave',\n  GROUP_ADD = 'group-add',\n  GROUP_REMOVE = 'group-remove',\n  WHITEBOARD_CREATE = 'whiteboard-create',\n  WHITEBOARD_GET = 'whiteboard-get',\n}\n\nexport function convertSignalMethodtoErrorAction(method: HMSSignalMethod): HMSAction {\n  switch (method) {\n    case HMSSignalMethod.JOIN:\n      return HMSAction.JOIN;\n    case HMSSignalMethod.OFFER:\n      return HMSAction.PUBLISH;\n    case HMSSignalMethod.ANSWER:\n      return HMSAction.SUBSCRIBE;\n    case HMSSignalMethod.TRACK_UPDATE:\n      return HMSAction.TRACK;\n    default:\n      return HMSAction.NONE;\n  }\n}\n","/*\n * ErrorFactory.ts\n *\n * Created by codegen\n * Copyright © 2021 100ms. All rights reserved.\n */\n\nimport { ErrorCodes } from './ErrorCodes';\nimport { HMSAction } from './HMSAction';\nimport { HMSException } from './HMSException';\nimport { HMSSignalMethod } from '../signal/jsonrpc/models';\n\nconst terminalActions: (HMSSignalMethod | HMSAction)[] = [\n  HMSSignalMethod.JOIN,\n  HMSSignalMethod.OFFER,\n  HMSSignalMethod.ANSWER,\n  HMSSignalMethod.TRICKLE,\n  HMSSignalMethod.SERVER_ERROR,\n  HMSAction.JOIN,\n];\n\nexport const ErrorFactory = {\n  WebSocketConnectionErrors: {\n    FailedToConnect(action: HMSAction, description = '') {\n      return new HMSException(\n        ErrorCodes.WebSocketConnectionErrors.FAILED_TO_CONNECT,\n        'WebsocketFailedToConnect',\n        action,\n        `[WS]: ${description}`,\n        `[WS]: ${description}`,\n      );\n    },\n\n    WebSocketConnectionLost(action: HMSAction, description = '') {\n      return new HMSException(\n        ErrorCodes.WebSocketConnectionErrors.WEBSOCKET_CONNECTION_LOST,\n        'WebSocketConnectionLost',\n        action,\n        `Network connection lost `,\n        description,\n      );\n    },\n\n    AbnormalClose(action: HMSAction, description = '') {\n      return new HMSException(\n        ErrorCodes.WebSocketConnectionErrors.ABNORMAL_CLOSE,\n        'WebSocketAbnormalClose',\n        action,\n        `Websocket closed abnormally`,\n        description,\n      );\n    },\n  },\n\n  APIErrors: {\n    ServerErrors(code: number, action: HMSAction, description = '', isTerminal = true) {\n      return new HMSException(\n        code,\n        'ServerErrors',\n        action,\n        `[${action}]: Server error ${description}`,\n        description,\n        isTerminal,\n      );\n    },\n\n    EndpointUnreachable(action: HMSAction, description = '') {\n      return new HMSException(\n        ErrorCodes.APIErrors.ENDPOINT_UNREACHABLE,\n        'EndpointUnreachable',\n        action,\n        `Endpoint is not reachable - ${description}`,\n        description,\n      );\n    },\n\n    InvalidTokenFormat(action: HMSAction, description = '') {\n      return new HMSException(\n        ErrorCodes.APIErrors.INVALID_TOKEN_FORMAT,\n        'InvalidTokenFormat',\n        action,\n        `Token is not in proper JWT format - ${description}`,\n        description,\n        true,\n      );\n    },\n\n    InitConfigNotAvailable(action: HMSAction, description = '') {\n      return new HMSException(\n        ErrorCodes.APIErrors.INIT_CONFIG_NOT_AVAILABLE,\n        'InitError',\n        action,\n        `[INIT]: ${description}`,\n        `[INIT]: ${description}`,\n      );\n    },\n  },\n\n  TracksErrors: {\n    GenericTrack(action: HMSAction, description = '') {\n      return new HMSException(\n        ErrorCodes.TracksErrors.GENERIC_TRACK,\n        'GenericTrack',\n        action,\n        `[TRACK]: ${description}`,\n        `[TRACK]: ${description}`,\n      );\n    },\n\n    CantAccessCaptureDevice(action: HMSAction, deviceInfo: string, description = '') {\n      return new HMSException(\n        ErrorCodes.TracksErrors.CANT_ACCESS_CAPTURE_DEVICE,\n        'CantAccessCaptureDevice',\n        action,\n        `User denied permission to access capture device - ${deviceInfo}`,\n        description,\n      );\n    },\n\n    DeviceNotAvailable(action: HMSAction, deviceInfo: string, description = '') {\n      return new HMSException(\n        ErrorCodes.TracksErrors.DEVICE_NOT_AVAILABLE,\n        'DeviceNotAvailable',\n        action,\n        `[TRACK]: Capture device is no longer available - ${deviceInfo}`,\n        description,\n      );\n    },\n\n    DeviceInUse(action: HMSAction, deviceInfo: string, description = '') {\n      return new HMSException(\n        ErrorCodes.TracksErrors.DEVICE_IN_USE,\n        'DeviceInUse',\n        action,\n        `[TRACK]: Capture device is in use by another application - ${deviceInfo}`,\n        description,\n      );\n    },\n\n    DeviceLostMidway(action: HMSAction, deviceInfo: string, description = '') {\n      return new HMSException(\n        ErrorCodes.TracksErrors.DEVICE_LOST_MIDWAY,\n        'DeviceLostMidway',\n        action,\n        `Lost access to capture device midway - ${deviceInfo}`,\n        description,\n      );\n    },\n\n    NothingToReturn(\n      action: HMSAction,\n      description = '',\n      message = `There is no media to return. Please select either video or audio or both.`,\n    ) {\n      return new HMSException(\n        ErrorCodes.TracksErrors.NOTHING_TO_RETURN,\n        'NothingToReturn',\n        action,\n        message,\n        description,\n      );\n    },\n\n    InvalidVideoSettings(action: HMSAction, description = '') {\n      return new HMSException(\n        ErrorCodes.TracksErrors.INVALID_VIDEO_SETTINGS,\n        'InvalidVideoSettings',\n        action,\n        `Cannot enable simulcast when no video settings are provided`,\n        description,\n      );\n    },\n\n    AutoplayBlocked(action: HMSAction, description = '') {\n      return new HMSException(\n        ErrorCodes.TracksErrors.AUTOPLAY_ERROR,\n        'AutoplayBlocked',\n        action,\n        \"Autoplay blocked because the user didn't interact with the document first\",\n        description,\n      );\n    },\n\n    CodecChangeNotPermitted(action: HMSAction, description = '') {\n      return new HMSException(\n        ErrorCodes.TracksErrors.CODEC_CHANGE_NOT_PERMITTED,\n        'CodecChangeNotPermitted',\n        action,\n        `Codec can't be changed mid call.`,\n        description,\n      );\n    },\n\n    OverConstrained(action: HMSAction, deviceInfo: string, description = '') {\n      return new HMSException(\n        ErrorCodes.TracksErrors.OVER_CONSTRAINED,\n        'OverConstrained',\n        action,\n        `[TRACK]: Requested constraints cannot be satisfied with the device hardware - ${deviceInfo}`,\n        description,\n      );\n    },\n\n    NoAudioDetected(action: HMSAction, description = 'Please check the mic or use another audio input') {\n      return new HMSException(\n        ErrorCodes.TracksErrors.NO_AUDIO_DETECTED,\n        'NoAudioDetected',\n        action,\n        'No audio input detected from microphone',\n        description,\n      );\n    },\n\n    SystemDeniedPermission(action: HMSAction, deviceInfo: string, description = '') {\n      return new HMSException(\n        ErrorCodes.TracksErrors.SYSTEM_DENIED_PERMISSION,\n        'SystemDeniedPermission',\n        action,\n        `Operating System denied permission to access capture device - ${deviceInfo}`,\n        description,\n      );\n    },\n\n    CurrentTabNotShared() {\n      return new HMSException(\n        ErrorCodes.TracksErrors.CURRENT_TAB_NOT_SHARED,\n        'CurrentTabNotShared',\n        HMSAction.TRACK,\n        'The app requires you to share the current tab',\n        'You must screen share the current tab in order to proceed',\n      );\n    },\n\n    AudioPlaybackError(description: string) {\n      return new HMSException(\n        ErrorCodes.TracksErrors.AUDIO_PLAYBACK_ERROR,\n        'Audio playback error',\n        HMSAction.TRACK,\n        description,\n        description,\n      );\n    },\n\n    SelectedDeviceMissing(deviceType: string) {\n      return new HMSException(\n        ErrorCodes.TracksErrors.SELECTED_DEVICE_MISSING,\n        'SelectedDeviceMissing',\n        HMSAction.TRACK,\n        `Could not detect selected ${deviceType} device`,\n        `Please check connection to the ${deviceType} device`,\n        false,\n      );\n    },\n  },\n\n  WebrtcErrors: {\n    CreateOfferFailed(action: HMSAction, description = '') {\n      return new HMSException(\n        ErrorCodes.WebrtcErrors.CREATE_OFFER_FAILED,\n        'CreateOfferFailed',\n        action,\n        `[${action.toString()}]: Failed to create offer. `,\n        description,\n      );\n    },\n\n    CreateAnswerFailed(action: HMSAction, description = '') {\n      return new HMSException(\n        ErrorCodes.WebrtcErrors.CREATE_ANSWER_FAILED,\n        'CreateAnswerFailed',\n        action,\n        `[${action.toString()}]: Failed to create answer. `,\n        description,\n      );\n    },\n\n    SetLocalDescriptionFailed(action: HMSAction, description = '') {\n      return new HMSException(\n        ErrorCodes.WebrtcErrors.SET_LOCAL_DESCRIPTION_FAILED,\n        'SetLocalDescriptionFailed',\n        action,\n        `[${action.toString()}]: Failed to set offer. `,\n        description,\n      );\n    },\n\n    SetRemoteDescriptionFailed(action: HMSAction, description = '') {\n      return new HMSException(\n        ErrorCodes.WebrtcErrors.SET_REMOTE_DESCRIPTION_FAILED,\n        'SetRemoteDescriptionFailed',\n        action,\n        `[${action.toString()}]: Failed to set answer. `,\n        description,\n        true,\n      );\n    },\n\n    ICEFailure(action: HMSAction, description = '', isTerminal = false) {\n      return new HMSException(\n        ErrorCodes.WebrtcErrors.ICE_FAILURE,\n        'ICEFailure',\n        action,\n        `[${action.toString()}]: Ice connection state FAILED`,\n        description,\n        isTerminal,\n      );\n    },\n\n    ICEDisconnected(action: HMSAction, description = '') {\n      return new HMSException(\n        ErrorCodes.WebrtcErrors.ICE_DISCONNECTED,\n        'ICEDisconnected',\n        action,\n        `[${action.toString()}]: Ice connection state DISCONNECTED`,\n        description,\n      );\n    },\n\n    StatsFailed(action: HMSAction, description = '') {\n      return new HMSException(\n        ErrorCodes.WebrtcErrors.STATS_FAILED,\n        'StatsFailed',\n        action,\n        `Failed to WebRTC get stats - ${description}`,\n        description,\n      );\n    },\n  },\n\n  WebsocketMethodErrors: {\n    ServerErrors(code: number, action: HMSAction | HMSSignalMethod, description: string) {\n      return new HMSException(code, 'ServerErrors', action, description, description, terminalActions.includes(action));\n    },\n\n    AlreadyJoined(action: HMSAction, description = '') {\n      return new HMSException(\n        ErrorCodes.WebsocketMethodErrors.ALREADY_JOINED,\n        'AlreadyJoined',\n        action,\n        `[JOIN]: You have already joined this room.`,\n        description,\n      );\n    },\n\n    CannotJoinPreviewInProgress(action: HMSAction, description = '') {\n      return new HMSException(\n        ErrorCodes.WebsocketMethodErrors.CANNOT_JOIN_PREVIEW_IN_PROGRESS,\n        'CannotJoinPreviewInProgress',\n        action,\n        `[JOIN]: Cannot join if preview is in progress`,\n        description,\n      );\n    },\n  },\n\n  GenericErrors: {\n    NotConnected(action: HMSAction, description = '') {\n      return new HMSException(\n        ErrorCodes.GenericErrors.NOT_CONNECTED,\n        'NotConnected',\n        action,\n        `Client is not connected`,\n        description,\n      );\n    },\n\n    Signalling(action: HMSAction, description: string) {\n      return new HMSException(\n        ErrorCodes.GenericErrors.SIGNALLING,\n        'Signalling',\n        action,\n        `Unknown signalling error: ${action.toString()} ${description} `,\n        description,\n      );\n    },\n\n    Unknown(action: HMSAction, description: string) {\n      return new HMSException(\n        ErrorCodes.GenericErrors.UNKNOWN,\n        'Unknown',\n        action,\n        `Unknown exception: ${description}`,\n        description,\n      );\n    },\n\n    NotReady(action: HMSAction, description = '') {\n      return new HMSException(ErrorCodes.GenericErrors.NOT_READY, 'NotReady', action, description, description);\n    },\n\n    JsonParsingFailed(action: HMSAction, jsonMessage: string, description = '') {\n      return new HMSException(\n        ErrorCodes.GenericErrors.JSON_PARSING_FAILED,\n        'JsonParsingFailed',\n        action,\n        `Failed to parse JSON message - ${jsonMessage}`,\n        description,\n      );\n    },\n\n    TrackMetadataMissing(action: HMSAction, description = '') {\n      return new HMSException(\n        ErrorCodes.GenericErrors.TRACK_METADATA_MISSING,\n        'TrackMetadataMissing',\n        action,\n        `Track Metadata Missing`,\n        description,\n      );\n    },\n\n    RTCTrackMissing(action: HMSAction, description = '') {\n      return new HMSException(\n        ErrorCodes.GenericErrors.RTC_TRACK_MISSING,\n        'RTCTrackMissing',\n        action,\n        `RTC Track missing`,\n        description,\n      );\n    },\n\n    PeerMetadataMissing(action: HMSAction, description = '') {\n      return new HMSException(\n        ErrorCodes.GenericErrors.PEER_METADATA_MISSING,\n        'PeerMetadataMissing',\n        action,\n        `Peer Metadata Missing`,\n        description,\n      );\n    },\n\n    ValidationFailed(message: string, entity?: any) {\n      return new HMSException(\n        ErrorCodes.GenericErrors.VALIDATION_FAILED,\n        'ValidationFailed',\n        HMSAction.VALIDATION,\n        message,\n        entity ? JSON.stringify(entity) : '',\n      );\n    },\n\n    InvalidRole(action: HMSAction, description: string) {\n      return new HMSException(\n        ErrorCodes.GenericErrors.INVALID_ROLE,\n        'InvalidRole',\n        action,\n        `Invalid role. Join with valid role`,\n        description,\n        true,\n      );\n    },\n\n    PreviewAlreadyInProgress(action: HMSAction, description = '') {\n      return new HMSException(\n        ErrorCodes.GenericErrors.PREVIEW_IN_PROGRESS,\n        'PreviewAlreadyInProgress',\n        action,\n        `[Preview]: Cannot join if preview is in progress`,\n        description,\n      );\n    },\n\n    LocalStorageAccessDenied(description = 'Access to localStorage has been denied') {\n      return new HMSException(\n        ErrorCodes.GenericErrors.LOCAL_STORAGE_ACCESS_DENIED,\n        'LocalStorageAccessDenied',\n        HMSAction.NONE,\n        `LocalStorageAccessDenied`,\n        description,\n      );\n    },\n\n    MissingMediaDevices() {\n      return new HMSException(\n        ErrorCodes.GenericErrors.MISSING_MEDIADEVICES,\n        'MissingMediaDevices',\n        HMSAction.JOIN,\n        `navigator.mediaDevices is undefined. 100ms SDK won't work on this website as WebRTC is not supported on HTTP endpoints(missing navigator.mediaDevices). Please ensure you're using the SDK either on localhost or a valid HTTPS endpoint.`,\n        '',\n        true,\n      );\n    },\n\n    MissingRTCPeerConnection() {\n      return new HMSException(\n        ErrorCodes.GenericErrors.MISSING_RTCPEERCONNECTION,\n        'MissingRTCPeerConnection',\n        HMSAction.JOIN,\n        `RTCPeerConnection which is a core requirement for WebRTC call was not found, this could be due to an unsupported browser or browser extensions blocking WebRTC`,\n        '',\n        true,\n      );\n    },\n  },\n\n  MediaPluginErrors: {\n    PlatformNotSupported(action: HMSAction, description = '') {\n      return new HMSException(\n        7001,\n        'PlatformNotSupported',\n        action,\n        'Check HMS Docs to see the list of supported platforms',\n        description,\n      );\n    },\n\n    InitFailed(action: HMSAction, description = '') {\n      return new HMSException(7002, 'InitFailed', action, 'Plugin init failed', description);\n    },\n\n    ProcessingFailed(action: HMSAction, description = '') {\n      return new HMSException(7003, 'ProcessingFailed', action, 'Plugin processing failed', description);\n    },\n\n    AddAlreadyInProgress(action: HMSAction, description = '') {\n      return new HMSException(7004, 'AddAlreadyInProgress', action, 'Plugin add already in progress', description);\n    },\n\n    DeviceNotSupported(action: HMSAction, description = '') {\n      return new HMSException(\n        7005,\n        'DeviceNotSupported',\n        action,\n        'Check HMS Docs to see the list of supported devices',\n        description,\n      );\n    },\n  },\n\n  PlaylistErrors: {\n    NoEntryToPlay(action: HMSAction, description: string) {\n      return new HMSException(\n        ErrorCodes.PlaylistErrors.NO_ENTRY_TO_PLAY,\n        'NoEntryToPlay',\n        action,\n        'Reached end of playlist',\n        description,\n      );\n    },\n    NoEntryPlaying(action: HMSAction, description: string) {\n      return new HMSException(\n        ErrorCodes.PlaylistErrors.NO_ENTRY_IS_PLAYING,\n        'NoEntryIsPlaying',\n        action,\n        'No entry is playing at this time',\n        description,\n      );\n    },\n  },\n};\n","import HMSLogger from './logger';\nimport { isBrowser } from './support';\nimport { ErrorFactory } from '../error/ErrorFactory';\n\nclass LocalStorage {\n  valuesMap = new Map();\n  getItem(key: string) {\n    if (this.valuesMap.has(key)) {\n      return String(this.valuesMap.get(key));\n    }\n    return null;\n  }\n\n  setItem(key: string, val: string) {\n    this.valuesMap.set(key, val);\n  }\n\n  removeItem(key: string) {\n    this.valuesMap.delete(key);\n  }\n\n  clear() {\n    this.valuesMap.clear();\n  }\n\n  key(i: number) {\n    if (arguments.length === 0) {\n      throw new TypeError(\"Failed to execute 'key' on 'Storage': 1 argument required, but only 0 present.\"); // this is a TypeError implemented on Chrome, Firefox throws Not enough arguments to Storage.key.\n    }\n    const arr = Array.from(this.valuesMap.keys());\n    return arr[i];\n  }\n\n  get length() {\n    return this.valuesMap.size;\n  }\n}\n\nexport const initializeLocalstoragePolyfill = () => {\n  try {\n    if (isBrowser && !localStorage) {\n      window.localStorage = new LocalStorage();\n    }\n  } catch (e) {\n    HMSLogger.e('Error initialising localStorage', ErrorFactory.GenericErrors.LocalStorageAccessDenied());\n  }\n};\n","import { initializeLocalstoragePolyfill } from './local-storage-polyfill';\nimport HMSLogger from './logger';\nimport { isBrowser } from './support';\nimport { ErrorFactory } from '../error/ErrorFactory';\n\nexport class LocalStorage<T> {\n  private storage: Storage | null = null;\n\n  constructor(public readonly key: string) {}\n\n  /**\n   * localstorage is not available in SSR, so get it only at time of use\n   */\n  getStorage() {\n    try {\n      if (isBrowser && !this.storage) {\n        initializeLocalstoragePolyfill();\n        this.storage = window.localStorage;\n      }\n      return this.storage;\n    } catch (e) {\n      HMSLogger.e('Error initialising localStorage', ErrorFactory.GenericErrors.LocalStorageAccessDenied());\n      return null;\n    }\n  }\n\n  get(): T | undefined {\n    const stringItem = this.getStorage()?.getItem(this.key);\n    if (!stringItem) {\n      return;\n    }\n    const item = JSON.parse(stringItem) as T;\n    return item;\n  }\n\n  set(value: T) {\n    const stringValue = JSON.stringify(value);\n    this.getStorage()?.setItem(this.key, stringValue);\n  }\n\n  clear() {\n    this.getStorage()?.removeItem(this.key);\n  }\n}\n","import HMSLogger from './logger';\nimport { ErrorFactory } from '../error/ErrorFactory';\n\nconst TAG = `[VALIDATIONS]`;\n\n/**\n * Check only for presence(not truthy) of a value.\n * Use in places where 0, false need to be considered valid.\n */\nexport function isPresent(value: any) {\n  return value !== undefined && value !== null;\n}\n\n/**\n * checks if RTCPeerConnection constructor is available\n */\nexport const validateRTCPeerConnection = () => {\n  if (!isPresent(RTCPeerConnection)) {\n    const error = ErrorFactory.GenericErrors.MissingRTCPeerConnection();\n    HMSLogger.e(TAG, error);\n    throw error;\n  }\n};\n\n/**\n * navigator.mediaDevices is undefined in insecure contexts served over HTTP protocol\n */\nexport const validateMediaDevicesExistence = () => {\n  if (!isPresent(navigator.mediaDevices)) {\n    const error = ErrorFactory.GenericErrors.MissingMediaDevices();\n    HMSLogger.e(TAG, error);\n    throw error;\n  }\n};\n","import { ENV, isNode, parsedUserAgent } from './support';\nimport { isPresent } from './validations';\nimport { DomainCategory } from '../analytics/AnalyticsEventDomains';\nimport { domainCategory } from '../analytics/domain-analytics';\nimport { HMSFrameworkInfo } from '../interfaces';\n\nconst sdk_version = require('../../package.json').version;\n\ntype UserAgent = {\n  os: string;\n  os_version: string;\n  sdk: 'web';\n  sdk_version: string;\n  env: 'debug' | 'prod';\n  domain: DomainCategory;\n  is_prebuilt: boolean;\n  device_model?: string;\n  framework?: HMSFrameworkInfo['type'] | 'node';\n  framework_version?: HMSFrameworkInfo['version'];\n  framework_sdk_version?: HMSFrameworkInfo['sdkVersion'];\n};\n\nexport function createUserAgent(sdkEnv: ENV = ENV.PROD, frameworkInfo?: HMSFrameworkInfo): string {\n  const sdk = 'web';\n  const env = domainCategory !== DomainCategory.LOCAL && sdkEnv === ENV.PROD ? 'prod' : 'debug';\n\n  if (isNode) {\n    return convertObjectToString({\n      os: 'web_nodejs',\n      os_version: process.version,\n      sdk,\n      sdk_version,\n      env,\n      domain: domainCategory,\n      is_prebuilt: !!frameworkInfo?.isPrebuilt,\n      framework: 'node',\n      framework_version: process.version,\n      framework_sdk_version: frameworkInfo?.sdkVersion,\n    });\n  }\n\n  const parsedOs = parsedUserAgent.getOS();\n  const parsedDevice = parsedUserAgent.getDevice();\n  const parsedBrowser = parsedUserAgent.getBrowser();\n\n  const os = replaceSpaces(`web_${parsedOs.name}`);\n  const os_version = parsedOs.version || '';\n\n  const browser = replaceSpaces(`${parsedBrowser.name}_${parsedBrowser.version}`);\n  let device_model = browser;\n  if (parsedDevice.type) {\n    const deviceVendor = replaceSpaces(`${parsedDevice.vendor}_${parsedDevice.type}`);\n    device_model = `${deviceVendor}/${browser}`;\n  }\n\n  return convertObjectToString({\n    os,\n    os_version,\n    sdk,\n    sdk_version,\n    device_model,\n    env,\n    domain: domainCategory,\n    is_prebuilt: !!frameworkInfo?.isPrebuilt,\n    framework: frameworkInfo?.type,\n    framework_version: frameworkInfo?.version,\n    framework_sdk_version: frameworkInfo?.sdkVersion,\n  });\n}\n\nfunction replaceSpaces(s: string) {\n  return s.replace(/ /g, '_');\n}\n\nconst convertObjectToString = (object: UserAgent, delimiter = ',') =>\n  Object.keys(object)\n    .filter(key => isPresent(object[key as keyof UserAgent]))\n    .map(key => `${key}:${object[key as keyof UserAgent]}`)\n    .join(delimiter);\n","import { PublishAnalyticPayload, SubscribeAnalyticPayload } from './stats/interfaces';\nimport { AdditionalAnalyticsProperties } from './AdditionalAnalyticsProperties';\nimport AnalyticsEvent from './AnalyticsEvent';\nimport { AnalyticsEventLevel } from './AnalyticsEventLevel';\nimport { IAnalyticsPropertiesProvider } from './IAnalyticsPropertiesProvider';\nimport { HMSException } from '../error/HMSException';\nimport { DeviceMap, SelectedDevices } from '../interfaces';\nimport { HMSRemoteVideoTrack } from '../media//tracks/HMSRemoteVideoTrack';\nimport { HMSTrackSettings } from '../media/settings/HMSTrackSettings';\n\nexport default class AnalyticsEventFactory {\n  private static KEY_REQUESTED_AT = 'requested_at';\n  private static KEY_RESPONDED_AT = 'responded_at';\n\n  static connect(\n    error?: Error,\n    additionalProperties?: AdditionalAnalyticsProperties,\n    requestedAt: Date = new Date(),\n    respondedAt: Date = new Date(),\n    endpoint?: string,\n  ) {\n    const name = this.eventNameFor('connect', error === undefined);\n    const level = error ? AnalyticsEventLevel.ERROR : AnalyticsEventLevel.INFO;\n\n    const properties = this.getPropertiesWithError(\n      {\n        ...additionalProperties,\n        [this.KEY_REQUESTED_AT]: requestedAt?.getTime(),\n        [this.KEY_RESPONDED_AT]: respondedAt?.getTime(),\n        endpoint,\n      },\n      error,\n    );\n\n    return new AnalyticsEvent({ name, level, properties });\n  }\n\n  static disconnect(error?: Error, additionalProperties?: AdditionalAnalyticsProperties) {\n    const name = 'disconnected';\n    const level = error ? AnalyticsEventLevel.ERROR : AnalyticsEventLevel.INFO;\n    const properties = this.getPropertiesWithError(additionalProperties, error);\n\n    return new AnalyticsEvent({ name, level, properties });\n  }\n\n  static preview({\n    error,\n    ...props\n  }: {\n    error?: Error;\n    time?: number;\n    init_response_time?: number;\n    ws_connect_time?: number;\n    on_policy_change_time?: number;\n    local_audio_track_time?: number;\n    local_video_track_time?: number;\n  }) {\n    const name = this.eventNameFor('preview', error === undefined);\n    const level = error ? AnalyticsEventLevel.ERROR : AnalyticsEventLevel.INFO;\n    const properties = this.getPropertiesWithError(props, error);\n\n    return new AnalyticsEvent({ name, level, properties });\n  }\n\n  static join({\n    error,\n    ...props\n  }: {\n    error?: Error;\n    is_preview_called?: boolean;\n    start?: Date;\n    end?: Date;\n    time?: number;\n    init_response_time?: number;\n    ws_connect_time?: number;\n    on_policy_change_time?: number;\n    local_audio_track_time?: number;\n    local_video_track_time?: number;\n    retries_join?: number;\n  }) {\n    const name = this.eventNameFor('join', error === undefined);\n    const level = error ? AnalyticsEventLevel.ERROR : AnalyticsEventLevel.INFO;\n\n    const properties = this.getPropertiesWithError({ ...props, is_preview_called: !!props.is_preview_called }, error);\n\n    return new AnalyticsEvent({ name, level, properties });\n  }\n\n  static publish({ devices, settings, error }: { devices?: DeviceMap; settings?: HMSTrackSettings; error?: Error }) {\n    const name = this.eventNameFor('publish', error === undefined);\n    const level = error ? AnalyticsEventLevel.ERROR : AnalyticsEventLevel.INFO;\n    const properties = this.getPropertiesWithError(\n      {\n        devices,\n        audio: settings?.audio,\n        video: settings?.video,\n      },\n      error,\n    );\n    return new AnalyticsEvent({\n      name,\n      level,\n      properties,\n    });\n  }\n\n  static hlsPlayerError(error: HMSException) {\n    return new AnalyticsEvent({\n      name: 'hlsPlayerError',\n      level: AnalyticsEventLevel.ERROR,\n      properties: this.getErrorProperties(error),\n    });\n  }\n  static subscribeFail(error: Error) {\n    const name = this.eventNameFor('subscribe', false);\n    const level = AnalyticsEventLevel.ERROR;\n    const properties = this.getErrorProperties(error);\n\n    return new AnalyticsEvent({ name, level, properties });\n  }\n\n  static leave() {\n    return new AnalyticsEvent({ name: 'leave', level: AnalyticsEventLevel.INFO });\n  }\n\n  static autoplayError() {\n    return new AnalyticsEvent({ name: 'autoplayError', level: AnalyticsEventLevel.ERROR });\n  }\n\n  static audioPlaybackError(error: HMSException) {\n    return new AnalyticsEvent({\n      name: 'audioPlaybackError',\n      level: AnalyticsEventLevel.ERROR,\n      properties: this.getErrorProperties(error),\n    });\n  }\n\n  static deviceChange({\n    selection,\n    type,\n    devices,\n    error,\n  }: {\n    selection: Partial<SelectedDevices>;\n    type?: 'change' | 'list' | 'audioInput' | 'audioOutput' | 'video';\n    devices: DeviceMap;\n    error?: Error;\n  }) {\n    const name = this.eventNameFor(error ? 'publish' : `device.${type}`, error === undefined);\n    const level = error ? AnalyticsEventLevel.ERROR : AnalyticsEventLevel.INFO;\n    const properties = this.getPropertiesWithError({ selection, devices }, error);\n    return new AnalyticsEvent({\n      name,\n      level,\n      properties,\n    });\n  }\n\n  static performance(stats: IAnalyticsPropertiesProvider) {\n    const name = 'perf.stats';\n    const level = AnalyticsEventLevel.INFO;\n    const properties = stats.toAnalyticsProperties();\n\n    return new AnalyticsEvent({ name, level, properties });\n  }\n\n  static rtcStats(stats: IAnalyticsPropertiesProvider) {\n    const name = 'rtc.stats';\n    const level = AnalyticsEventLevel.INFO;\n    const properties = stats.toAnalyticsProperties();\n\n    return new AnalyticsEvent({ name, level, properties });\n  }\n\n  static rtcStatsFailed(error: HMSException) {\n    const name = 'rtc.stats.failed';\n    const level = AnalyticsEventLevel.ERROR;\n\n    return new AnalyticsEvent({ name, level, properties: this.getErrorProperties(error) });\n  }\n\n  /**\n   * TODO: remove once everything is switched to server side degradation, this\n   * event can be handled on server side as well.\n   */\n  static degradationStats(track: HMSRemoteVideoTrack, isDegraded: boolean) {\n    const name = 'video.degradation.stats';\n    const level = AnalyticsEventLevel.INFO;\n    let properties: any = {\n      degradedAt: track.degradedAt,\n      trackId: track.trackId,\n    };\n\n    if (!isDegraded && track.degradedAt instanceof Date) {\n      // not degraded => restored\n      const restoredAt = new Date();\n      const duration = restoredAt.valueOf() - track.degradedAt.valueOf();\n      properties = { ...properties, duration, restoredAt };\n    }\n\n    return new AnalyticsEvent({ name, level, properties });\n  }\n\n  static audioDetectionFail(error: Error, device?: MediaDeviceInfo): AnalyticsEvent {\n    const properties = this.getPropertiesWithError({ device }, error);\n    const level = AnalyticsEventLevel.ERROR;\n    const name = 'audiopresence.failed';\n\n    return new AnalyticsEvent({ name, level, properties });\n  }\n\n  static previewNetworkQuality(properties: { downLink?: string; score?: number; error?: string }) {\n    return new AnalyticsEvent({\n      name: 'perf.networkquality.preview',\n      level: properties.error ? AnalyticsEventLevel.ERROR : AnalyticsEventLevel.INFO,\n      properties,\n    });\n  }\n\n  static publishStats(properties: PublishAnalyticPayload) {\n    return new AnalyticsEvent({\n      name: 'publisher.stats',\n      level: AnalyticsEventLevel.INFO,\n      properties,\n    });\n  }\n\n  static subscribeStats(properties: SubscribeAnalyticPayload) {\n    return new AnalyticsEvent({\n      name: 'subscriber.stats',\n      level: AnalyticsEventLevel.INFO,\n      properties,\n    });\n  }\n\n  private static eventNameFor(name: string, ok: boolean) {\n    const suffix = ok ? 'success' : 'failed';\n    return `${name}.${suffix}`;\n  }\n\n  private static getPropertiesWithError(initialProperties: any, error?: Error) {\n    const errorProperties = this.getErrorProperties(error);\n    initialProperties = { ...errorProperties, ...initialProperties };\n    return initialProperties;\n  }\n\n  private static getErrorProperties(error?: Error): Record<string, any> {\n    if (error) {\n      return error instanceof HMSException\n        ? error.toAnalyticsProperties()\n        : {\n            error_name: error.name,\n            error_message: error.message,\n            error_description: error.cause,\n          };\n    } else {\n      return {};\n    }\n  }\n}\n","import HMSLogger from '../utils/logger';\n\nexport type TimedEventName = 'init' | 'websocket-open' | 'on-policy-change' | 'local-tracks' | 'preview' | 'join';\n\nexport enum TimedEvent {\n  INIT = 'init_response_time',\n  WEBSOCKET_CONNECT = 'ws_connect_time',\n  ON_POLICY_CHANGE = 'on_policy_change_time',\n  LOCAL_AUDIO_TRACK = 'local_audio_track_time',\n  LOCAL_VIDEO_TRACK = 'local_video_track_time',\n  JOIN = 'join_time',\n  PREVIEW = 'preview_time',\n  PEER_LIST = 'peer_list_time',\n  ROOM_STATE = 'room_state_time',\n  JOIN_RESPONSE = 'join_response_time',\n  GET_TOKEN = 'GET_TOKEN',\n}\n\nconst defaultEventNames = [\n  TimedEvent.INIT,\n  TimedEvent.WEBSOCKET_CONNECT,\n  TimedEvent.ON_POLICY_CHANGE,\n  TimedEvent.LOCAL_AUDIO_TRACK,\n  TimedEvent.LOCAL_VIDEO_TRACK,\n  TimedEvent.PEER_LIST,\n  TimedEvent.ROOM_STATE,\n  TimedEvent.JOIN_RESPONSE,\n];\n\nexport class AnalyticsTimer {\n  private eventPerformanceMeasures: Partial<Record<TimedEvent, PerformanceMeasure>> = {};\n\n  start(eventName: TimedEvent) {\n    performance.mark(eventName);\n  }\n\n  end(eventName: TimedEvent) {\n    try {\n      this.eventPerformanceMeasures[eventName] = performance.measure(eventName, eventName);\n      HMSLogger.d('[HMSPerformanceTiming]', eventName, this.eventPerformanceMeasures[eventName]?.duration);\n    } catch (error) {\n      HMSLogger.w('[AnalyticsTimer]', `Error in measuring performance for event ${eventName}`, { error });\n    }\n  }\n\n  getTimeTaken(eventName: TimedEvent) {\n    return this.eventPerformanceMeasures[eventName]?.duration;\n  }\n\n  getTimes(...eventNames: TimedEvent[]) {\n    return [...defaultEventNames, ...eventNames].reduce(\n      (timeObject, eventName) => ({ ...timeObject, [eventName]: this.getTimeTaken(eventName) }),\n      {},\n    );\n  }\n\n  cleanup() {\n    this.eventPerformanceMeasures = {};\n  }\n}\n","import adapter from 'webrtc-adapter';\nimport { ErrorFactory } from './ErrorFactory';\nimport { HMSAction } from './HMSAction';\nimport { HMSException } from './HMSException';\n\nexport enum HMSGetMediaActions {\n  UNKNOWN = 'unknown(video or audio)',\n  AUDIO = 'audio',\n  VIDEO = 'video',\n  AV = 'audio, video',\n  SCREEN = 'screen',\n}\n\nfunction getDefaultError(error: string, deviceInfo: string) {\n  const message = error.toLowerCase();\n  if (message.includes('device not found')) {\n    return ErrorFactory.TracksErrors.DeviceNotAvailable(HMSAction.TRACK, deviceInfo, error);\n  } else if (message.includes('permission denied')) {\n    return ErrorFactory.TracksErrors.CantAccessCaptureDevice(HMSAction.TRACK, deviceInfo, error);\n  } else {\n    return ErrorFactory.TracksErrors.GenericTrack(HMSAction.TRACK, error);\n  }\n}\n\n/**\n * # Edge Cases:\n * - Screenshare error: The problem is when block at OS level, chrome throws NotAllowedError(HMS code - 3001) while firefox throws NotFoundError(HMS code - 3002),\n * we will handle this internally and throw error as User block - 3001 and OS block - 3011 for all browsers.\n * Chrome -\n * User blocked - NotAllowedError - Permission denied\n * System blocked - NotAllowedError - Permission denied by system\n */\n// eslint-disable-next-line complexity\nfunction convertMediaErrorToHMSException(err: Error, deviceInfo = ''): HMSException {\n  /**\n   * Note: Adapter detects all chromium browsers as 'chrome'\n   */\n  const chromeSystemDenied =\n    adapter.browserDetails.browser === 'chrome' &&\n    err.name === 'NotAllowedError' &&\n    err.message.includes('denied by system');\n\n  if (chromeSystemDenied) {\n    return ErrorFactory.TracksErrors.SystemDeniedPermission(HMSAction.TRACK, deviceInfo, err.message);\n  }\n\n  if (adapter.browserDetails.browser === 'firefox' && err.name === 'NotFoundError') {\n    const hmsError = ErrorFactory.TracksErrors.SystemDeniedPermission(HMSAction.TRACK, deviceInfo, err.message);\n    hmsError.description = `Capture device is either blocked at Operating System level or not available - ${deviceInfo}`;\n    return hmsError;\n  }\n\n  switch (err.name) {\n    case 'OverconstrainedError':\n      return ErrorFactory.TracksErrors.OverConstrained(\n        HMSAction.TRACK,\n        deviceInfo,\n        (err as OverconstrainedError).constraint,\n      );\n    case 'NotAllowedError':\n      return ErrorFactory.TracksErrors.CantAccessCaptureDevice(HMSAction.TRACK, deviceInfo, err.message);\n    case 'NotFoundError':\n      return ErrorFactory.TracksErrors.DeviceNotAvailable(HMSAction.TRACK, deviceInfo, err.message);\n    case 'NotReadableError':\n      return ErrorFactory.TracksErrors.DeviceInUse(HMSAction.TRACK, deviceInfo, err.message);\n    case 'TypeError':\n      return ErrorFactory.TracksErrors.NothingToReturn(HMSAction.TRACK, err.message);\n    default:\n      return getDefaultError(err.message, deviceInfo);\n  }\n}\n\nexport function BuildGetMediaError(err: Error, deviceInfo: string): HMSException {\n  const exception = convertMediaErrorToHMSException(err, deviceInfo);\n  exception.addNativeError(err);\n  return exception;\n}\n","import adapter from 'webrtc-adapter';\nimport './utils/local-storage-polyfill';\nimport HMSLogger from './utils/logger';\nconst sdk_version = require('../package.json').version;\n\nHMSLogger.d('adapter', `${adapter.browserDetails.browser} v${adapter.browserDetails.version}`);\nHMSLogger.d('sdk version', sdk_version);\n\nexport * from './media/streams';\nexport * from './media/tracks';\nexport * from './utils/media';\nexport * from './utils/device-error';\nexport * from './utils/support';\nexport * from './error/HMSException';\nexport * from './interfaces';\nexport * from './rtc-stats';\nexport * from './plugins';\nexport * from './utils/logger';\nexport * from './sdk/HMSPeerListIterator';\n","import { HMSTrack } from '../tracks';\n\nexport class HMSMediaStream {\n  readonly nativeStream: MediaStream;\n  id: string;\n\n  readonly tracks = new Array<HMSTrack>();\n\n  constructor(nativeStream: MediaStream) {\n    this.nativeStream = nativeStream;\n    this.id = nativeStream.id;\n  }\n\n  /**\n   * This is only used when onDemandTracks flag is enabled in Init\n   * @param id\n   */\n  updateId(id: string) {\n    this.id = id;\n  }\n}\n","export const stringifyMediaStreamTrack = (track: MediaStreamTrack) => {\n  if (!track) {\n    return '';\n  }\n  return `{\n    trackId: ${track.id};\n    kind: ${track.kind};\n    enabled: ${track.enabled};\n    muted: ${track.muted};\n    readyState: ${track.readyState};\n  }`;\n};\n","import { HMSTrackType } from './HMSTrackType';\nimport { stringifyMediaStreamTrack } from '../../utils/json';\nimport HMSLogger from '../../utils/logger';\nimport { HMSMediaStream } from '../streams';\n\nexport type HMSTrackSource = 'regular' | 'screen' | 'plugin' | 'audioplaylist' | 'videoplaylist' | string;\n\nexport abstract class HMSTrack {\n  /**\n   * @internal\n   */\n  readonly stream: HMSMediaStream;\n  source?: HMSTrackSource;\n  peerId?: string;\n  transceiver?: RTCRtpTransceiver;\n\n  /**\n   * @internal to print as a helpful identifier alongside logs\n   */\n  logIdentifier = '';\n\n  /** The native mediastream track, for local, this changes on mute/unmute(for video),\n   * and on device change.\n   * @internal */\n  nativeTrack: MediaStreamTrack;\n\n  /**\n   * Firefox doesn't respect the track id as sent from the backend when calling peerconnection.ontrack callback. This\n   * breaks correlation of future track updates from backend. So we're storing the sdp track id as present in the\n   * original offer along with the track as well and will let this override the native track id for any correlation\n   * purpose.\n   * This applies for remote tracks only.\n   * @internal */\n  private sdpTrackId?: string;\n\n  /**\n   * @internal\n   * The local track id is changed on mute/unmute or when device id changes, this is abstracted as an internal\n   * detail of HMSTrack and the variable is used for this enacapsulation where the first track id is remembered\n   * and treated as the fixed track id for this HMSTrack. This simplifies things for the user of the sdk who\n   * do not have to worry about changing track IDs.\n   * This applies for local tracks only.\n   */\n  private firstTrackId?: string;\n\n  abstract readonly type: HMSTrackType;\n\n  public get enabled(): boolean {\n    return this.nativeTrack.enabled;\n  }\n\n  /**\n   * firstTrackId => encapsulates change in local track ids\n   * sdpTrackId => fixes remote track updates correlation on firefox\n   */\n  public get trackId(): string {\n    return this.firstTrackId || this.sdpTrackId || this.nativeTrack.id;\n  }\n\n  getMediaTrackSettings(): MediaTrackSettings {\n    return this.nativeTrack.getSettings();\n  }\n\n  async setEnabled(value: boolean): Promise<void> {\n    this.nativeTrack.enabled = value;\n  }\n\n  protected constructor(stream: HMSMediaStream, track: MediaStreamTrack, source?: HMSTrackSource) {\n    this.stream = stream;\n    this.nativeTrack = track;\n    this.source = source;\n  }\n\n  /**\n   * @internal\n   */\n  setSdpTrackId(sdpTrackId: string) {\n    this.sdpTrackId = sdpTrackId;\n  }\n\n  /**\n   * @internal\n   */\n  protected setFirstTrackId(trackId: string) {\n    this.firstTrackId = trackId;\n  }\n\n  /**\n   * @internal\n   * take care of -\n   * 1. https://bugs.chromium.org/p/chromium/issues/detail?id=1232649\n   * 2. stopping any tracks\n   * 3. plugins related cleanups and stopping\n   */\n  cleanup() {\n    HMSLogger.d('[HMSTrack]', 'Stopping track', this.toString());\n    this.nativeTrack?.stop();\n  }\n\n  toString() {\n    return `{\n      streamId: ${this.stream.id};\n      peerId: ${this.peerId};\n      trackId: ${this.trackId};\n      mid: ${this.transceiver?.mid || '-'};\n      logIdentifier: ${this.logIdentifier};\n      source: ${this.source};\n      enabled: ${this.enabled};\n      nativeTrack: ${stringifyMediaStreamTrack(this.nativeTrack)};\n    }`;\n  }\n}\n","export enum HMSTrackType {\n  AUDIO = 'audio',\n  VIDEO = 'video',\n}\n","import { HMSTrack, HMSTrackSource } from './HMSTrack';\nimport { HMSTrackType } from './HMSTrackType';\nimport HMSLogger from '../../utils/logger';\nimport { HMSMediaStream, HMSRemoteStream } from '../streams';\n\nexport class HMSAudioTrack extends HMSTrack {\n  readonly type: HMSTrackType = HMSTrackType.AUDIO;\n  private audioElement: HTMLAudioElement | null = null;\n  private outputDevice?: MediaDeviceInfo;\n\n  constructor(stream: HMSMediaStream, track: MediaStreamTrack, source?: string) {\n    super(stream, track, source as HMSTrackSource);\n    if (track.kind !== 'audio') {\n      throw new Error(\"Expected 'track' kind = 'audio'\");\n    }\n  }\n\n  getVolume() {\n    return this.audioElement ? this.audioElement.volume * 100 : null;\n  }\n\n  async setVolume(value: number) {\n    if (value < 0 || value > 100) {\n      throw Error('Please pass a valid number between 0-100');\n    }\n    // Don't subscribe to audio when volume is 0\n    await this.subscribeToAudio(value === 0 ? false : this.enabled);\n    if (this.audioElement) {\n      this.audioElement.volume = value / 100;\n    }\n  }\n\n  setAudioElement(element: HTMLAudioElement | null) {\n    HMSLogger.d('[HMSAudioTrack]', this.logIdentifier, 'adding audio element', `${this}`, element);\n    this.audioElement = element;\n  }\n\n  /**\n   * @internal\n   * @returns {HTMLAudioElement | null}\n   */\n  getAudioElement(): HTMLAudioElement | null {\n    return this.audioElement;\n  }\n\n  getOutputDevice() {\n    return this.outputDevice;\n  }\n\n  cleanup() {\n    super.cleanup();\n    if (this.audioElement) {\n      this.audioElement.srcObject = null;\n      this.audioElement.remove();\n      this.audioElement = null;\n    }\n  }\n\n  async setOutputDevice(device?: MediaDeviceInfo) {\n    if (!device) {\n      HMSLogger.d('[HMSAudioTrack]', this.logIdentifier, 'device is null', `${this}`);\n      return;\n    }\n    if (!this.audioElement) {\n      HMSLogger.d('[HMSAudioTrack]', this.logIdentifier, 'no audio element to set output', `${this}`);\n      this.outputDevice = device;\n      return;\n    }\n    try {\n      // @ts-ignore\n      if (typeof this.audioElement.setSinkId === 'function') {\n        // @ts-ignore\n        await this.audioElement?.setSinkId(device.deviceId);\n        this.outputDevice = device;\n      }\n    } catch (error) {\n      HMSLogger.d('[HMSAudioTrack]', 'error in setSinkId', error);\n    }\n  }\n\n  protected async subscribeToAudio(value: boolean) {\n    if (this.stream instanceof HMSRemoteStream) {\n      await this.stream.setAudio(value, this.trackId, this.logIdentifier);\n    }\n  }\n}\n","import { DeviceMap, SelectedDevices } from '../interfaces';\nimport { LocalStorage } from '../utils/local-storage';\nimport HMSLogger from '../utils/logger';\n\ntype DeviceInfo = { deviceId?: string; groupId?: string };\n/**\n * This class is to manage storing and retrieving selected devices\n * from localstorage\n * @internal\n */\nclass DeviceStorage {\n  private storage = new LocalStorage<SelectedDevices>('hms-device-selection');\n  private remember = false;\n  private devices?: DeviceMap;\n  private readonly TAG = '[HMSDeviceStorage]';\n\n  setDevices(devices: DeviceMap) {\n    this.devices = devices;\n  }\n\n  rememberDevices(value: boolean) {\n    this.remember = value;\n  }\n\n  /**\n   * This will update the passed in type value in storage\n   * @param {string} type - One of audioInput | videoInput | audioOutput\n   * @param {DeviceInfo} param\n   * @returns {void}\n   */\n  updateSelection(type: 'audioInput' | 'videoInput' | 'audioOutput', { deviceId, groupId }: DeviceInfo) {\n    if (!this.devices || !this.remember) {\n      return;\n    }\n    const newSelection = this.devices[type].find(device => this.isSame({ deviceId, groupId }, device));\n    if (!newSelection) {\n      HMSLogger.w(this.TAG, `Could not find device with deviceId: ${deviceId}, groupId: ${groupId}`);\n      return;\n    }\n    const selectedDevices = this.storage.get() || {};\n    if (type === 'audioOutput') {\n      selectedDevices[type] = newSelection as MediaDeviceInfo;\n    } else {\n      selectedDevices[type] = newSelection as MediaDeviceInfo;\n    }\n    this.storage.set(selectedDevices);\n  }\n\n  getSelection() {\n    if (!this.remember) {\n      return undefined;\n    }\n    return this.storage.get();\n  }\n\n  cleanup() {\n    this.remember = false;\n    this.devices = undefined;\n  }\n\n  private isSame(current: DeviceInfo, device: DeviceInfo) {\n    // Safari doesn't give groupId from nativeTrack. Check if groupId's match or current groupId is not present\n    return current.deviceId === device.deviceId && (current.groupId === device.groupId || !current.groupId);\n  }\n}\n\nexport const DeviceStorageManager = new DeviceStorage();\n","/**\n * A plugin implementing this interface can be registered with HMSLocalAudioTrack to transform, process or\n * analyze the local audio track.These can include applications like background noise removal, speech commands, live\n * analysis of audio etc. The below functions are required for the sdk to properly use the plugin, usually\n * the plugin would also be exposing some public functions of its own for the UI to control its working.\n */\n\nexport interface HMSAudioPlugin {\n  /**\n   * This function will be called by the SDK for audio track which the plugin needs to process.\n   * The reason audio context is also part of the interface is that it's recommeneded to reuse on audio context\n   * instead of creating new for every use - https://developer.mozilla.org/en-US/docs/Web/API/AudioContext\n   */\n  processAudioTrack(ctx: AudioContext, source: AudioNode): Promise<AudioNode>;\n\n  /**\n   * This function will be called before the call to init, it is used to check whether the plugin supports current\n   * OS, browser and audio device or not. An error object will be thrown back to the user if they try to use an unsupported plugin.\n   */\n  checkSupport(ctx?: AudioContext): HMSPluginSupportResult;\n\n  /**\n   * @deprecated. Will be deleted in future updates. Use checkSupport instead.\n   */\n  isSupported(): boolean;\n\n  /**\n   * This function will be called in the beginning for initialization which may include tasks like setting up\n   * variables, loading ML models etc. This can be used by a plugin to ensure it's prepared at the time\n   * processAudio is called.\n   */\n  init(): Promise<void> | void;\n\n  /**\n   * The name is meant to uniquely specify a plugin instance. This will be used to track number of plugins\n   * added to the track, and same name won't be allowed twice.\n   */\n  getName(): string;\n\n  /**\n   This sets the Plugin type @see HMSAudioPluginType, processing will happen\n   based on the type of plugin\n   */\n  getPluginType(): HMSAudioPluginType;\n  /*\n   * the plugin can use this function to dispose off its resources. It'll be called when the plugin instance is\n   * no longer needed at the end.\n   */\n  stop(): void;\n}\n\n/**\n * Specifies the type of the plugin a transforming plugin will get an output audio node to give the resulting\n * transformation. While an analyzing plugin will only be passed the input node.\n * For analyse plugins, you can return the source node passed to plugin.processTrack to not modify anything\n */\nexport enum HMSAudioPluginType {\n  TRANSFORM = 'TRANSFORM',\n  ANALYZE = 'ANALYZE',\n}\n\nexport interface HMSPluginSupportResult {\n  isSupported: boolean;\n  errType?: HMSPluginUnsupportedTypes;\n  errMsg?: string;\n}\n\nexport enum HMSPluginUnsupportedTypes {\n  PLATFORM_NOT_SUPPORTED = 'PLATFORM_NOT_SUPPORTED',\n  DEVICE_NOT_SUPPORTED = 'DEVICE_NOT_SUPPORTED',\n}\n","import AnalyticsEvent from './AnalyticsEvent';\nimport { AnalyticsEventLevel } from './AnalyticsEventLevel';\nimport { HMSException } from '../error/HMSException';\n\nexport default class MediaPluginsAnalyticsFactory {\n  static failure(pluginName: string, error: HMSException) {\n    const name = 'mediaPlugin.failed';\n    const level = AnalyticsEventLevel.ERROR;\n    const properties = { plugin_name: pluginName, ...error.toAnalyticsProperties() };\n\n    return new AnalyticsEvent({ name, level, properties });\n  }\n\n  static audioPluginFailure(pluginName: string, sampleRate: number, error: HMSException) {\n    const name = 'mediaPlugin.failed';\n    const level = AnalyticsEventLevel.ERROR;\n    const properties = { plugin_name: pluginName, sampleRate: sampleRate, ...error.toAnalyticsProperties() };\n\n    return new AnalyticsEvent({ name, level, properties });\n  }\n\n  static audioPluginStats({\n    pluginName,\n    duration,\n    loadTime,\n    sampleRate,\n  }: {\n    pluginName: string;\n    duration: number;\n    loadTime: number;\n    sampleRate: number;\n  }) {\n    const name = 'mediaPlugin.stats';\n    const level = AnalyticsEventLevel.INFO;\n    const properties = {\n      plugin_name: pluginName,\n      duration: duration,\n      load_time: loadTime,\n      sampleRate: sampleRate,\n    };\n    return new AnalyticsEvent({ name, level, properties });\n  }\n\n  static stats({\n    pluginName,\n    duration,\n    loadTime,\n    avgPreProcessingTime,\n    avgProcessingTime,\n    inputFrameRate,\n    pluginFrameRate,\n  }: {\n    pluginName: string;\n    duration: number;\n    loadTime: number;\n    avgPreProcessingTime: number;\n    avgProcessingTime: number;\n    inputFrameRate: number;\n    pluginFrameRate: number;\n  }) {\n    const name = 'mediaPlugin.stats';\n    const level = AnalyticsEventLevel.INFO;\n    const properties = {\n      plugin_name: pluginName,\n      duration: duration,\n      load_time: loadTime,\n      avg_preprocessing_time: avgPreProcessingTime,\n      avg_processing_time: avgProcessingTime,\n      input_frame_rate: inputFrameRate,\n      plugin_frame_rate: pluginFrameRate,\n    };\n    return new AnalyticsEvent({ name, level, properties });\n  }\n}\n","import MediaPluginsAnalyticsFactory from '../../analytics/MediaPluginsAnalyticsFactory';\nimport { ErrorFactory } from '../../error/ErrorFactory';\nimport { HMSAction } from '../../error/HMSAction';\nimport { HMSException } from '../../error/HMSException';\nimport { EventBus } from '../../events/EventBus';\nimport HMSLogger from '../../utils/logger';\n\nexport class AudioPluginsAnalytics {\n  private readonly TAG = '[AudioPluginsAnalytics]';\n  private readonly initTime: Record<string, number>;\n  private readonly addedTimestamps: Record<string, number>;\n  private readonly pluginAdded: Record<string, boolean>;\n  private readonly pluginSampleRate: Record<string, number>;\n\n  constructor(private eventBus: EventBus) {\n    this.initTime = {};\n    this.addedTimestamps = {};\n    this.pluginAdded = {};\n    this.pluginSampleRate = {};\n  }\n\n  added(name: string, sampleRate: number) {\n    this.pluginAdded[name] = true;\n    this.addedTimestamps[name] = Date.now();\n    this.initTime[name] = 0;\n    this.pluginSampleRate[name] = sampleRate;\n  }\n\n  removed(name: string) {\n    //send stats\n    if (this.pluginAdded[name]) {\n      const stats = {\n        pluginName: name,\n        // duration in seconds\n        duration: Math.floor((Date.now() - this.addedTimestamps[name]) / 1000),\n        loadTime: this.initTime[name],\n        sampleRate: this.pluginSampleRate[name],\n      };\n      //send stats\n      this.eventBus.analytics.publish(MediaPluginsAnalyticsFactory.audioPluginStats(stats));\n      //clean the plugin details\n      this.clean(name);\n    }\n  }\n\n  failure(name: string, error: HMSException) {\n    // send failure event\n    if (this.pluginAdded[name]) {\n      this.eventBus.analytics.publish(\n        MediaPluginsAnalyticsFactory.audioPluginFailure(name, this.pluginSampleRate[name], error),\n      );\n      //clean the plugin details\n      this.clean(name);\n    }\n  }\n\n  async initWithTime<T>(name: string, initFn: () => Promise<T>) {\n    if (this.initTime[name]) {\n      HMSLogger.i(this.TAG, `Plugin Already loaded ${name}, time it took: ${this.initTime[name]}`);\n      return;\n    }\n    let time: number | undefined = undefined;\n    try {\n      time = await this.timeInMs(initFn);\n      HMSLogger.i(this.TAG, `Time taken for Plugin ${name} initialization : ${time}`);\n    } catch (e) {\n      //Failed during initialization of plugin(model loading etc...)\n      const err = ErrorFactory.MediaPluginErrors.InitFailed(\n        HMSAction.AUDIO_PLUGINS,\n        `failed during initialization of plugin${(e as Error).message || e}`,\n      );\n      HMSLogger.e(this.TAG, err);\n      this.failure(name, err);\n      throw err;\n    }\n    if (time) {\n      this.initTime[name] = time;\n    }\n  }\n\n  private async timeInMs<T>(fn: () => Promise<T>): Promise<number> {\n    const start = Date.now();\n    await fn();\n    return Math.floor(Date.now() - start);\n  }\n\n  private clean(name: string) {\n    delete this.addedTimestamps[name];\n    delete this.initTime[name];\n    delete this.pluginAdded[name];\n    delete this.pluginSampleRate[name];\n  }\n}\n","import { AudioPluginsAnalytics } from './AudioPluginsAnalytics';\nimport { HMSAudioPlugin, HMSPluginUnsupportedTypes } from './HMSAudioPlugin'; //HMSAudioPluginType\nimport { ErrorFactory } from '../../error/ErrorFactory';\nimport { HMSAction } from '../../error/HMSAction';\nimport { EventBus } from '../../events/EventBus';\nimport { HMSLocalAudioTrack } from '../../media/tracks';\nimport HMSLogger from '../../utils/logger';\n\nconst DEFAULT_SAMPLE_RATE = 48000;\n\n//Handling sample rate error in case of firefox\nconst checkBrowserSupport = () => {\n  return navigator.userAgent.indexOf('Firefox') !== -1;\n};\n\n/**\n * This class manages applying different plugins on a local audio track. Plugins which need to modify the audio\n * are called in the order they were added. Plugins which do not need to modify the audio are called\n * with the original input.\n *\n * Concepts -\n * Audio Plugin - A module which can take in input audio, do some processing on it and return an AudioNode\n *\n * For Each Plugin, an AudioNode will be created and the source will be created from local audio track.\n * Each Audio node will be connected in the following order\n * source -> first plugin -> second plugin -> third plugin .. so on\n * @see HMSAudioPlugin\n */\nexport class HMSAudioPluginsManager {\n  private readonly TAG = '[AudioPluginsManager]';\n  private readonly hmsTrack: HMSLocalAudioTrack;\n  // Map maintains the insertion order\n  private readonly pluginsMap: Map<string, HMSAudioPlugin>;\n  private audioContext?: AudioContext;\n\n  private sourceNode?: MediaStreamAudioSourceNode;\n  private destinationNode?: MediaStreamAudioDestinationNode;\n  private prevAudioNode?: any;\n  private analytics: AudioPluginsAnalytics;\n  // This will replace the native track in peer connection when plugins are enabled\n  private outputTrack?: MediaStreamTrack;\n  private pluginAddInProgress = false;\n\n  constructor(track: HMSLocalAudioTrack, eventBus: EventBus) {\n    this.hmsTrack = track;\n    this.pluginsMap = new Map();\n    this.analytics = new AudioPluginsAnalytics(eventBus);\n    this.createAudioContext();\n  }\n\n  getPlugins(): string[] {\n    return Array.from(this.pluginsMap.keys());\n  }\n\n  async addPlugin(plugin: HMSAudioPlugin) {\n    const name = plugin.getName?.();\n    if (!name) {\n      HMSLogger.w('no name provided by the plugin');\n      return;\n    }\n    if (this.pluginAddInProgress) {\n      const err = ErrorFactory.MediaPluginErrors.AddAlreadyInProgress(\n        HMSAction.AUDIO_PLUGINS,\n        'Add Plugin is already in Progress',\n      );\n      this.analytics.added(name, this.audioContext!.sampleRate);\n      this.analytics.failure(name, err);\n      HMSLogger.w(\"can't add another plugin when previous add is in progress\");\n      throw err;\n    }\n\n    this.pluginAddInProgress = true;\n\n    try {\n      await this.addPluginInternal(plugin);\n    } finally {\n      this.pluginAddInProgress = false;\n    }\n  }\n\n  // eslint-disable-next-line complexity\n  private async addPluginInternal(plugin: HMSAudioPlugin) {\n    const name = plugin.getName?.();\n    if (this.pluginsMap.get(name)) {\n      HMSLogger.w(this.TAG, `plugin - ${name} already added.`);\n      return;\n    }\n\n    await this.validateAndThrow(name, plugin);\n\n    try {\n      if (this.pluginsMap.size === 0) {\n        await this.initAudioNodes();\n      } else if (this.prevAudioNode) {\n        // Previous node will be connected to destination. Disconnect that\n        this.prevAudioNode.disconnect();\n      }\n      this.analytics.added(name, this.audioContext!.sampleRate);\n      await this.analytics.initWithTime(name, async () => plugin.init());\n      this.pluginsMap.set(name, plugin);\n      await this.processPlugin(plugin);\n      await this.connectToDestination();\n    } catch (err) {\n      HMSLogger.e(this.TAG, 'failed to add plugin', err);\n      throw err;\n    }\n  }\n\n  validatePlugin(plugin: HMSAudioPlugin) {\n    return plugin.checkSupport(this.audioContext);\n  }\n\n  async validateAndThrow(name: string, plugin: HMSAudioPlugin) {\n    const result = this.validatePlugin(plugin);\n    if (result.isSupported) {\n      HMSLogger.i(this.TAG, `plugin is supported,- ${plugin.getName()}`);\n    } else {\n      //Needed to re-add in the reprocess case, to send error message in case of failure\n      this.analytics.added(name, this.audioContext!.sampleRate);\n      if (result.errType === HMSPluginUnsupportedTypes.PLATFORM_NOT_SUPPORTED) {\n        const err = ErrorFactory.MediaPluginErrors.PlatformNotSupported(\n          HMSAction.AUDIO_PLUGINS,\n          'platform not supported, see docs',\n        );\n        this.analytics.failure(name, err);\n        await this.cleanup();\n        throw err;\n      } else if (result.errType === HMSPluginUnsupportedTypes.DEVICE_NOT_SUPPORTED) {\n        const err = ErrorFactory.MediaPluginErrors.DeviceNotSupported(\n          HMSAction.AUDIO_PLUGINS,\n          'audio device not supported, see docs',\n        );\n        this.analytics.failure(name, err);\n        await this.cleanup();\n        throw err;\n      }\n    }\n  }\n\n  async removePlugin(plugin: HMSAudioPlugin) {\n    await this.removePluginInternal(plugin);\n    if (this.pluginsMap.size === 0) {\n      // remove all previous nodes\n      await this.cleanup();\n      HMSLogger.i(this.TAG, `No plugins left, stopping plugins loop`);\n      await this.hmsTrack.setProcessedTrack(undefined);\n    } else {\n      // Reprocess the remaining plugins again because there is no way to connect\n      // the source of the removed plugin to destination of removed plugin\n      await this.reprocessPlugins();\n    }\n  }\n\n  async cleanup() {\n    for (const plugin of this.pluginsMap.values()) {\n      await this.removePluginInternal(plugin);\n    }\n    await this.hmsTrack.setProcessedTrack(undefined);\n    //disconnect nodes, stop track\n    this.sourceNode?.disconnect();\n    this.prevAudioNode?.disconnect();\n    this.outputTrack?.stop();\n\n    // reset all variables\n    this.sourceNode = undefined;\n    this.destinationNode = undefined;\n    this.prevAudioNode = undefined;\n    this.outputTrack = undefined;\n  }\n\n  //Keeping it separate since we are initializing context only once\n  async closeContext() {\n    this.audioContext?.close();\n    this.audioContext = undefined;\n  }\n\n  async reprocessPlugins() {\n    if (this.pluginsMap.size === 0 || !this.sourceNode) {\n      return;\n    }\n    const plugins = Array.from(this.pluginsMap.values()); // make a copy of plugins\n    await this.cleanup();\n    await this.initAudioNodes();\n    for (const plugin of plugins) {\n      await this.addPlugin(plugin);\n    }\n  }\n\n  private async initAudioNodes() {\n    if (this.audioContext) {\n      if (!this.sourceNode) {\n        const audioStream = new MediaStream([this.hmsTrack.nativeTrack]);\n        this.sourceNode = this.audioContext.createMediaStreamSource(audioStream);\n      }\n      if (!this.destinationNode) {\n        this.destinationNode = this.audioContext.createMediaStreamDestination();\n        this.outputTrack = this.destinationNode.stream.getAudioTracks()[0];\n        try {\n          await this.hmsTrack.setProcessedTrack(this.outputTrack);\n        } catch (err) {\n          HMSLogger.e(this.TAG, 'error in setting processed track', err);\n          throw err;\n        }\n      }\n    }\n  }\n\n  private async processPlugin(plugin: HMSAudioPlugin) {\n    try {\n      const currentNode = await plugin.processAudioTrack(\n        this.audioContext!, // it is always present at this point\n        this.prevAudioNode || this.sourceNode,\n      );\n      if (this.prevAudioNode) {\n        // if previous node was present while adding this plugin\n        // it is disconnected from destination, connect the previous node to\n        // to the current node\n        this.prevAudioNode.connect(currentNode);\n      }\n      this.prevAudioNode = currentNode;\n    } catch (err) {\n      const name = plugin.getName();\n      //TODO error happened on processing of plugin notify UI\n      HMSLogger.e(this.TAG, `error in processing plugin ${name}`, err);\n      //remove plugin from loop and stop analytics for it\n      await this.removePluginInternal(plugin);\n    }\n  }\n\n  private async connectToDestination() {\n    try {\n      if (this.prevAudioNode && this.destinationNode && this.prevAudioNode.context === this.destinationNode.context) {\n        this.prevAudioNode.connect(this.destinationNode);\n      }\n    } catch (err) {\n      HMSLogger.e(this.TAG, 'error in connecting to destination node', err);\n    }\n  }\n\n  private async removePluginInternal(plugin: HMSAudioPlugin) {\n    const name = plugin.getName?.();\n    if (!this.pluginsMap.get(name)) {\n      HMSLogger.w(this.TAG, `plugin - ${name} not found to remove.`);\n      return;\n    }\n    HMSLogger.i(this.TAG, `removing plugin ${name}`);\n    this.pluginsMap.delete(name);\n    plugin.stop();\n    this.analytics.removed(name);\n  }\n\n  private createAudioContext() {\n    if (!this.audioContext) {\n      if (checkBrowserSupport()) {\n        /**\n        Not setting default sample rate for firefox since connecting\n        audio nodes from context with different sample rate is not\n        supported in firefox\n */\n        this.audioContext = new AudioContext();\n      } else {\n        this.audioContext = new AudioContext({ sampleRate: DEFAULT_SAMPLE_RATE });\n      }\n    }\n  }\n}\n","import { BuildGetMediaError, HMSGetMediaActions } from '../error/utils';\nimport { HMSAudioTrackSettings, HMSVideoTrackSettings } from '../media/settings';\n\nexport async function getAudioTrack(settings: HMSAudioTrackSettings): Promise<MediaStreamTrack> {\n  try {\n    const stream = await navigator.mediaDevices.getUserMedia({\n      audio: settings ? settings.toConstraints() : false,\n    });\n    return stream.getAudioTracks()[0];\n  } catch (err) {\n    throw BuildGetMediaError(err as Error, HMSGetMediaActions.AUDIO);\n  }\n}\n\nexport async function getVideoTrack(settings: HMSVideoTrackSettings): Promise<MediaStreamTrack> {\n  try {\n    const stream = await navigator.mediaDevices.getUserMedia({\n      video: settings ? settings.toConstraints() : false,\n    });\n    return stream.getVideoTracks()[0];\n  } catch (err) {\n    throw BuildGetMediaError(err as Error, HMSGetMediaActions.VIDEO);\n  }\n}\n\n// To differentiate between normal track and empty track.\nexport function isEmptyTrack(track: MediaStreamTrack) {\n  // Firefox gives '' as label for empty track(created from audio context)\n  return 'canvas' in track || track.label === 'MediaStreamAudioDestinationNode' || track.label === '';\n}\n","import HMSLogger from './logger';\nimport { BuildGetMediaError, HMSGetMediaActions } from '../error/utils';\n\nexport async function getLocalStream(constraints: MediaStreamConstraints): Promise<MediaStream> {\n  try {\n    const stream = await navigator.mediaDevices.getUserMedia(constraints);\n    return stream;\n  } catch (err) {\n    throw BuildGetMediaError(err as Error, HMSGetMediaActions.AV);\n  }\n}\n\nexport async function getLocalScreen(constraints: MediaStreamConstraints['video']): Promise<MediaStream> {\n  try {\n    // @ts-ignore [https://github.com/microsoft/TypeScript/issues/33232]\n    const stream = await navigator.mediaDevices.getDisplayMedia({ video: constraints, audio: false });\n    return stream;\n  } catch (err) {\n    throw BuildGetMediaError(err as Error, HMSGetMediaActions.SCREEN);\n  }\n}\n\ninterface MediaDeviceGroups {\n  audioinput: MediaDeviceInfo[];\n  audiooutput: MediaDeviceInfo[];\n  videoinput: MediaDeviceInfo[];\n}\n\nexport async function getLocalDevices(): Promise<MediaDeviceGroups> {\n  try {\n    const devices = await navigator.mediaDevices.enumerateDevices();\n    const deviceGroups: MediaDeviceGroups = {\n      audioinput: [],\n      audiooutput: [],\n      videoinput: [],\n    };\n    devices.forEach(device => deviceGroups[device.kind].push(device));\n    return deviceGroups;\n  } catch (err) {\n    throw BuildGetMediaError(err as Error, HMSGetMediaActions.AV);\n  }\n}\n\nexport interface HMSAudioContext {\n  audioContext: AudioContext | null;\n  getAudioContext: () => AudioContext;\n  resumeContext: () => Promise<void>;\n}\n\nexport const HMSAudioContextHandler: HMSAudioContext = {\n  audioContext: null,\n  getAudioContext() {\n    if (!this.audioContext) {\n      this.audioContext = new AudioContext();\n    }\n    return this.audioContext;\n  },\n  async resumeContext() {\n    try {\n      return await this.getAudioContext().resume();\n    } catch (error) {\n      HMSLogger.e('AudioContext', error);\n    }\n  },\n};\n","export interface IQueue<T> {\n  size(): number;\n  enqueue(item: T): void;\n  dequeue(): T | undefined;\n}\n\nexport class Queue<T> implements IQueue<T> {\n  protected storage: T[] = [];\n\n  constructor(private capacity: number = Infinity) {}\n\n  size() {\n    return this.storage.length;\n  }\n\n  toList() {\n    return this.storage.slice(0);\n  }\n\n  enqueue(item: T) {\n    if (this.size() === this.capacity) {\n      this.dequeue();\n    }\n    this.storage.push(item);\n  }\n\n  dequeue() {\n    return this.storage.shift();\n  }\n\n  aggregate<R>(aggregationFn: (values: T[]) => R): R {\n    return aggregationFn(this.storage);\n  }\n}\n","export const worker = `(function metronomeWorkerSetup() {\n  function ticker() {\n    self.postMessage('tick');\n  }\n  self.onmessage = function (event) {\n    const [data, time] = event.data;\n    switch (data) {\n      case 'start':\n        setTimeout(ticker, time);\n        break;\n      default:\n        break;\n    }\n  };\n})()`;\n\n/**\n * Delay for a @see ms amount of time\n * @param ms -- time in milliseconds\n */\nexport function sleep(ms: number): Promise<void> {\n  if (ms < 0) {\n    throw Error('`ms` should be a positive integer');\n  }\n\n  return new Promise(resolve => {\n    setTimeout(resolve, ms);\n  });\n}\n\nexport function workerSleep(ms: number): Promise<void> {\n  if (ms < 0) {\n    throw Error('`ms` should be a positive integer');\n  }\n  if (typeof Worker === 'undefined') {\n    return sleep(ms);\n  }\n  const WorkerThread = new Worker(URL.createObjectURL(new Blob([worker], { type: 'application/javascript' })));\n  WorkerThread.postMessage(['start', ms]);\n  return new Promise(resolve => {\n    WorkerThread.onmessage = event => {\n      if (event.data === 'tick') {\n        resolve();\n        WorkerThread.terminate();\n      }\n    };\n  });\n}\n\n/**\n * Debounce Fn - Function to limit the number of executions of the passed in\n * function in a given time duration\n * @param fn Function to be called\n * @param delay time by which the function execution has to be delayed\n * @returns {void}\n */\nexport function debounce<T extends (...args: any) => any>(fn: T, delay = 300) {\n  let timer: any | undefined;\n  return function (...args: []) {\n    clearTimeout(timer);\n    timer = undefined;\n    //@ts-ignore\n    //eslint-disable-next-line\n    const context = this;\n    timer = setTimeout(() => {\n      fn.apply(context, args);\n    }, delay);\n  };\n}\n","import HMSLogger from './logger';\nimport { HMSAudioContextHandler } from './media';\nimport { Queue } from './queue';\nimport { sleep } from './timer-utils';\nimport { HMSInternalEvent } from '../events/HMSInternalEvent';\nimport { HMSLocalAudioTrack } from '../internal';\n\n/** Send update only if audio level is above THRESHOLD */\nconst THRESHOLD = 35;\n\n/** Send update only if audio level is changed by UPDATE_THRESHOLD */\nconst UPDATE_THRESHOLD = 5;\n\nexport interface ITrackAudioLevelUpdate {\n  track: HMSLocalAudioTrack;\n  audioLevel: number;\n}\n\nexport class TrackAudioLevelMonitor {\n  private readonly TAG = '[TrackAudioLevelMonitor]';\n  private audioLevel = 0;\n  private analyserNode?: AnalyserNode;\n  private isMonitored = false;\n  /** Frequency of polling audio level from track */\n  private interval = 100;\n  /** Store past audio levels for this duration */\n  private historyInterval = 700;\n  private history = new Queue<number>(this.historyInterval / this.interval);\n\n  constructor(\n    private track: HMSLocalAudioTrack,\n    private audioLevelEvent: HMSInternalEvent<ITrackAudioLevelUpdate>,\n    private silenceEvent: HMSInternalEvent<{ track: HMSLocalAudioTrack }>,\n  ) {\n    try {\n      const stream = new MediaStream([this.track.nativeTrack]);\n      this.analyserNode = this.createAnalyserNodeForStream(stream);\n    } catch (ex) {\n      HMSLogger.w(this.TAG, 'Unable to initialize AudioContext', ex);\n    }\n  }\n\n  /**\n   * To detect silence we check if the track is unmuted and silent in the current moment\n   * periodically. If the track is found to be silent more than a threshold number of times\n   * we send the event. The threshold number of time is there to reduce the chance of false\n   * positives.\n   */\n  detectSilence = async () => {\n    const tickInterval = 20;\n    const tickThreshold = 50;\n    let silenceCounter = 0;\n\n    while (this.isMonitored) {\n      if (this.track.enabled) {\n        if (this.isSilentThisInstant()) {\n          silenceCounter++;\n          if (silenceCounter > tickThreshold) {\n            this.silenceEvent.publish({ track: this.track });\n            break;\n          }\n        } else {\n          // bail out immediately if sound is found\n          break;\n        }\n      }\n      await sleep(tickInterval);\n    }\n  };\n\n  start() {\n    this.stop();\n    this.isMonitored = true;\n    HMSLogger.d(this.TAG, 'Starting track Monitor', `${this.track}`);\n    this.loop().then(() => HMSLogger.d(this.TAG, 'Stopping track Monitor', `${this.track}`));\n  }\n\n  stop() {\n    if (!this.analyserNode) {\n      HMSLogger.d(this.TAG, 'AudioContext not initialized');\n      return;\n    }\n\n    this.sendAudioLevel(0);\n    this.isMonitored = false;\n  }\n\n  private async loop() {\n    while (this.isMonitored) {\n      this.sendAudioLevel(this.getMaxAudioLevelOverPeriod());\n      await sleep(this.interval);\n    }\n  }\n\n  private sendAudioLevel(audioLevel = 0) {\n    audioLevel = audioLevel > THRESHOLD ? audioLevel : 0;\n    const isSignificantChange = Math.abs(this.audioLevel - audioLevel) > UPDATE_THRESHOLD;\n    if (isSignificantChange) {\n      this.audioLevel = audioLevel;\n      const audioLevelUpdate: ITrackAudioLevelUpdate = { track: this.track, audioLevel: this.audioLevel };\n      this.audioLevelEvent.publish(audioLevelUpdate);\n    }\n  }\n\n  private getMaxAudioLevelOverPeriod() {\n    if (!this.analyserNode) {\n      HMSLogger.d(this.TAG, 'AudioContext not initialized');\n      return;\n    }\n    const newLevel = this.calculateAudioLevel();\n    newLevel !== undefined && this.history.enqueue(newLevel);\n    return this.history.aggregate(values => Math.max(...values));\n  }\n\n  private calculateAudioLevel() {\n    if (!this.analyserNode) {\n      HMSLogger.d(this.TAG, 'AudioContext not initialized');\n      return;\n    }\n\n    const data = new Uint8Array(this.analyserNode.fftSize);\n    this.analyserNode.getByteTimeDomainData(data);\n    const lowest = 0.009;\n    let max = lowest;\n    for (const frequency of data) {\n      max = Math.max(max, (frequency - 128) / 128);\n    }\n    const normalized = (Math.log(lowest) - Math.log(max)) / Math.log(lowest);\n    const percent = Math.ceil(Math.min(Math.max(normalized * 100, 0), 100));\n    return percent;\n  }\n\n  private isSilentThisInstant() {\n    if (!this.analyserNode) {\n      HMSLogger.d(this.TAG, 'AudioContext not initialized');\n      return;\n    }\n\n    const data = new Uint8Array(this.analyserNode.fftSize);\n    this.analyserNode.getByteTimeDomainData(data);\n\n    // For absolute silence(in case of mic/software failures), all frequencies are 128 or 0.\n    return !data.some(frequency => frequency !== 128 && frequency !== 0);\n  }\n\n  private createAnalyserNodeForStream(stream: MediaStream): AnalyserNode {\n    const audioContext = HMSAudioContextHandler.getAudioContext();\n    const analyser = audioContext.createAnalyser();\n    const source = audioContext.createMediaStreamSource(stream);\n    source.connect(analyser);\n    return analyser;\n  }\n}\n","import { HMSChangeMultiTrackStateRequest, HMSChangeTrackStateRequest } from './change-track-state';\nimport { DeviceChangeListener } from './devices';\nimport { HMSLeaveRoomRequest } from './leave-room-request';\nimport { HMSMessage } from './message';\nimport { HMSConnectionQuality } from './peer';\nimport { HMSRoleChangeRequest } from './role-change-request';\nimport { HMSRoom } from './room';\nimport { HMSPoll, HMSWhiteboard, SessionStoreUpdate } from './session-store';\nimport { HMSSpeaker } from './speaker';\nimport { HMSException } from '../error/HMSException';\nimport { HMSTrack } from '../media/tracks/HMSTrack';\nimport { HMSPeer } from '../sdk/models/peer';\n\nexport enum HMSRoomUpdate {\n  RECORDING_STATE_UPDATED = 'RECORDING_STATE_UPDATED',\n  BROWSER_RECORDING_STATE_UPDATED = 'BROWSER_RECORDING_STATE_UPDATED',\n  SERVER_RECORDING_STATE_UPDATED = 'SERVER_RECORDING_STATE_UPDATED',\n  RTMP_STREAMING_STATE_UPDATED = 'RTMP_STREAMING_STATE_UPDATED',\n  HLS_STREAMING_STATE_UPDATED = 'HLS_STREAMING_STATE_UPDATED',\n  ROOM_PEER_COUNT_UPDATED = 'ROOM_PEER_COUNT_UPDATED',\n}\n\nexport enum HMSPeerUpdate {\n  PEER_JOINED,\n  PEER_LEFT,\n  AUDIO_TOGGLED,\n  VIDEO_TOGGLED,\n  BECAME_DOMINANT_SPEAKER,\n  RESIGNED_DOMINANT_SPEAKER,\n  STARTED_SPEAKING,\n  STOPPED_SPEAKING,\n  ROLE_UPDATED,\n  PEER_LIST,\n  NAME_UPDATED,\n  METADATA_UPDATED,\n  HAND_RAISE_CHANGED,\n  PEER_REMOVED,\n  PEER_ADDED,\n}\n\nexport enum HMSTrackUpdate {\n  TRACK_ADDED,\n  TRACK_REMOVED,\n  TRACK_MUTED,\n  TRACK_UNMUTED,\n  TRACK_DESCRIPTION_CHANGED,\n  TRACK_DEGRADED,\n  TRACK_RESTORED,\n}\n\nexport enum HMSPollsUpdate {\n  POLL_CREATED,\n  POLL_STARTED,\n  POLL_STOPPED,\n  POLL_STATS_UPDATED,\n  // POLL_LEADERBOARD_SHARED,\n}\n\nexport interface HMSAudioListener {\n  onAudioLevelUpdate(speakers: HMSSpeaker[]): void;\n}\n\nexport interface HMSConnectionQualityListener {\n  onConnectionQualityUpdate(qualityUpdates: HMSConnectionQuality[]): void;\n}\n\nexport interface SessionStoreListener {\n  onSessionStoreUpdate(values: SessionStoreUpdate[]): void;\n}\n\nexport interface InteractivityListener {\n  onPollsUpdate(type: HMSPollsUpdate, polls: HMSPoll[]): void;\n  onWhiteboardUpdate(whiteboard: HMSWhiteboard): void;\n}\n\nexport interface HMSUpdateListener extends DeviceChangeListener, SessionStoreListener, InteractivityListener {\n  onJoin(room: HMSRoom): void;\n  onRoomUpdate(type: HMSRoomUpdate, room: HMSRoom): void;\n  onPeerUpdate(type: HMSPeerUpdate, peer: HMSPeer | HMSPeer[] | null): void;\n  onTrackUpdate(type: HMSTrackUpdate, track: HMSTrack, peer: HMSPeer): void;\n  onMessageReceived(message: HMSMessage): void;\n  onError(error: HMSException): void;\n  onReconnecting(error: HMSException): void;\n  onReconnected(): void;\n  onRoleChangeRequest(request: HMSRoleChangeRequest): void;\n  onRoleUpdate(newRole: string): void;\n  onChangeTrackStateRequest(request: HMSChangeTrackStateRequest): void;\n  onChangeMultiTrackStateRequest(request: HMSChangeMultiTrackStateRequest): void;\n  onRemovedFromRoom(request: HMSLeaveRoomRequest): void;\n  onNetworkQuality?(score: number): void;\n  onPreview(room: HMSRoom, localTracks: HMSTrack[]): void;\n}\n","import { ServerError } from './internal';\nimport { HMSException } from '../error/HMSException';\n\nexport enum HMSRecordingState {\n  NONE = 'none',\n  INITIALISED = 'initialised',\n  STARTED = 'started',\n  PAUSED = 'paused',\n  RESUMED = 'resumed',\n  STOPPED = 'stopped',\n  FAILED = 'failed',\n}\n\nexport enum HMSStreamingState {\n  NONE = 'none',\n  INITIALISED = 'initialised',\n  STARTED = 'started',\n  STOPPED = 'stopped',\n  FAILED = 'failed',\n}\n\nexport interface HMSRoom {\n  id: string;\n  name?: string;\n  sessionId?: string;\n  joinedAt?: Date;\n  startedAt?: Date;\n  recording: HMSRecording;\n  rtmp: HMSRTMP;\n  hls: HMSHLS;\n  peerCount?: number;\n  templateId?: string;\n  description?: string;\n  max_size?: number;\n  large_room_optimization?: boolean;\n  /**\n   * @alpha\n   */\n  isEffectsEnabled?: boolean;\n  /**\n   * @alpha\n   */\n  effectsKey?: string;\n}\n\nexport interface HMSRecording {\n  browser: HMSBrowserRecording;\n  server: HMSSFURecording;\n  hls: HMSHLSRecording;\n}\n\nexport interface HMSBrowserRecording {\n  running: boolean;\n  startedAt?: Date;\n  state?: HMSRecordingState;\n  error?: HMSException;\n}\n\nexport interface HMSSFURecording {\n  running: boolean;\n  startedAt?: Date;\n  state?: HMSRecordingState;\n  error?: HMSException;\n}\n\nexport interface HMSHLSRecording {\n  running: boolean;\n  initialisedAt?: Date;\n  startedAt?: Date;\n  state?: HMSRecordingState;\n  error?: ServerError;\n  /**\n   * if the final output is one file or one file per hls layer\n   */\n  singleFilePerLayer?: boolean;\n  /**\n   * if video on demand needs to be turned on, false by default\n   */\n  hlsVod?: boolean;\n}\n\nexport interface HMSRTMP {\n  running: boolean;\n  /**\n   * @alpha\n   **/\n  startedAt?: Date;\n  state?: HMSStreamingState;\n  error?: HMSException;\n}\n\nexport interface HMSHLS {\n  running: boolean;\n  variants: Array<HLSVariant>;\n  error?: HMSException;\n}\n\nexport interface HLSVariant {\n  url: string;\n  meetingURL?: string;\n  metadata?: string;\n  startedAt?: Date;\n  initialisedAt?: Date;\n  state?: HMSStreamingState;\n}\n","export enum HMSSimulcastLayer {\n  NONE = 'none',\n  LOW = 'low',\n  MEDIUM = 'medium',\n  HIGH = 'high',\n}\n\nexport interface SimulcastLayer {\n  rid: string;\n  scaleResolutionDownBy: number;\n  maxBitrate: number;\n  maxFramerate: number;\n}\n\nexport interface SimulcastResolution {\n  width: number;\n  height: number;\n}\n\nexport interface SimulcastLayers {\n  layers?: SimulcastLayer[];\n}\n\nexport type HMSPreferredSimulcastLayer = Exclude<HMSSimulcastLayer, HMSSimulcastLayer.NONE>;\nexport interface HMSSimulcastLayerDefinition {\n  layer: HMSPreferredSimulcastLayer;\n  resolution: SimulcastResolution;\n}\n\nexport type RID = 'f' | 'h' | 'q';\n\nexport const simulcastMapping = {\n  f: HMSSimulcastLayer.HIGH,\n  h: HMSSimulcastLayer.MEDIUM,\n  q: HMSSimulcastLayer.LOW,\n};\n","export enum HMSVideoCodec {\n  VP8 = 'vp8',\n  VP9 = 'vp9',\n  H264 = 'h264',\n}\n\nexport enum HMSAudioCodec {\n  OPUS = 'opus',\n}\n\n/**\n * Refer https://developer.mozilla.org/en-US/docs/Web/API/MediaTrackConstraints/facingMode\n * for more details.\n */\nexport enum HMSFacingMode {\n  USER = 'user',\n  ENVIRONMENT = 'environment',\n  LEFT = 'left',\n  RIGHT = 'right',\n}\n\nexport interface HMSAudioTrackSettings {\n  volume?: number;\n  codec?: HMSAudioCodec;\n  maxBitrate?: number;\n  deviceId?: string;\n  advanced?: Array<MediaTrackConstraintSet>;\n}\n\nexport interface HMSVideoTrackSettings {\n  width?: number;\n  height?: number;\n  codec?: HMSVideoCodec;\n  maxFramerate?: number;\n  maxBitrate?: number;\n  deviceId?: string;\n  advanced?: Array<MediaTrackConstraintSet>;\n  facingMode?: HMSFacingMode;\n}\n\n/**\n * Config to have control over screenshare being captured. Note that\n * not all fields are supported on all browsers. Even when they're supported\n * the fields acts as hints and the browser can override them.\n */\nexport interface HMSScreenShareConfig {\n  /**\n   * discard the video and only share audio track with others, useful\n   * for sharing music.\n   * @default false\n   */\n  audioOnly?: boolean;\n  /**\n   * do not give an option to share audio while screen sharing.\n   * @default false\n   */\n  videoOnly?: boolean;\n  /**\n   * preselect the relevant tab in screenshare menu\n   * browser - for preferring a browser tab\n   * window - for application window\n   * monitor - for full screen\n   * @default monitor\n   */\n  displaySurface?: 'browser' | 'monitor' | 'window';\n  /**\n   * show the current tab first in supported browser, throws\n   * error if user doesn't select current tab for sharing.\n   * @default false\n   */\n  forceCurrentTab?: boolean;\n  /**\n   * show the current tab first in supported browser, but don't throw error\n   * if user selects something else.\n   * @default false\n   */\n  preferCurrentTab?: boolean;\n  /**\n   * whether to show an option for sharing the current tab in the screen share\n   * prompt. Screen sharing current tab might lead to hall of mirrors effect.\n   * Default is exclude, if either of forceCurrentTab or preferCurrentTab are true,\n   * this is set to include.\n   * @default exclude\n   */\n  selfBrowserSurface?: 'include' | 'exclude';\n  /**\n   * whether to hint browser to show a \"share this tab instead\" option when\n   * tab is shared.\n   * Default is include, set to exclude if forceCurrentTab is true\n   * @default include\n   */\n  surfaceSwitching?: 'include' | 'exclude';\n  /**\n   * whether to show option for sharing system level audio if full screen\n   * is being shared. Not applicable if isVideoOnly is true.\n   * Note that sharing system audio will cause echo if mic is on.\n   * @default exclude\n   */\n  systemAudio?: 'include' | 'exclude';\n  /**\n   * used for region capture in screenshare, if the current tab is being screenshared\n   * the screenshare video track will be cropped to only this element. Will throw\n   * error if the element is not present in DOM.\n   */\n  cropElement?: HTMLDivElement;\n  /**\n   * used for region capture in screenshare, the screenshare video track will be\n   * cropped to only the passed in cropTarget. This cropTarget must come from\n   * the tab which is being shared\n   */\n  cropTarget?: object;\n}\n\nexport interface ScreenCaptureHandle {\n  handle: string;\n  exposeOrigin: boolean;\n}\n\nexport interface ScreenCaptureHandleConfig extends ScreenCaptureHandle {\n  permittedOrigins: string[];\n}\n","import { HMSException } from '../error/HMSException';\n\nexport interface HMSDeviceChangeEvent {\n  error?: HMSException;\n  devices: DeviceMap;\n  selection?: MediaDeviceInfo;\n  type: 'audioOutput' | 'audioInput' | 'video';\n}\n\nexport enum DeviceType {\n  videoInput = 'videoInput',\n  audioInput = 'audioInput',\n  audioOutput = 'audioOutput',\n}\n\nexport interface DeviceMap {\n  [DeviceType.audioInput]: MediaDeviceInfo[];\n  [DeviceType.audioOutput]: MediaDeviceInfo[];\n  [DeviceType.videoInput]: MediaDeviceInfo[];\n}\n\nexport interface DeviceChangeListener {\n  onDeviceChange?(event: HMSDeviceChangeEvent): void;\n}\n\nexport type SelectedDevices = {\n  [DeviceType.audioInput]?: MediaDeviceInfo;\n  [DeviceType.videoInput]?: MediaDeviceInfo;\n  [DeviceType.audioOutput]?: MediaDeviceInfo;\n};\n","export enum HMSPlaylistType {\n  audio = 'audio',\n  video = 'video',\n}\n\nexport interface HMSPlaylistItem<T> {\n  /**\n   * uniquely identifies a playlist item\n   */\n  id: string;\n  name: string;\n  type: HMSPlaylistType;\n  /**\n   * the url to play from, local files are not supported currently.\n   */\n  url: string;\n  /**\n   * any additional info, for eg. composer, musician etc.\n   */\n  metadata?: T;\n  /**\n   * duration in seconds\n   */\n  duration?: number;\n}\n\nexport interface HMSPlaylistProgressEvent {\n  type: HMSPlaylistType;\n  progress: number;\n}\n\nexport interface HMSPlaylistManager {\n  getList<T>(type: HMSPlaylistType): HMSPlaylistItem<T>[];\n  setList<T>(list: HMSPlaylistItem<T>[]): void;\n  clearList(type: HMSPlaylistType): Promise<void>;\n  playNext(type: HMSPlaylistType): Promise<void>;\n  playPrevious(type: HMSPlaylistType): Promise<void>;\n  removeItem(id: string, type: HMSPlaylistType): Promise<boolean>;\n  /**\n   * Seek forward/backward on selected type relative to currentTime\n   * @param value - number in seconds to go forward(if negative, it goes backwards)\n   * @param {HMSPlaylistType} type\n   */\n  seek(value: number, type: HMSPlaylistType): void;\n  /**\n   * Seek forward/backward on selected type - absolute value\n   * @param value - point in playlist item to go to\n   * @param {HMSPlaylistType} type\n   */\n  seekTo(value: number, type: HMSPlaylistType): void;\n  /**\n   * set volume on the selected type\n   * @param value - number between 0-100\n   * @param type\n   */\n  setVolume(value: number, type: HMSPlaylistType): void;\n  /**\n   * Get volume of selected type, between 0-100\n   * @param type\n   */\n  getVolume(type: HMSPlaylistType): number;\n  isPlaying(type: HMSPlaylistType): boolean;\n  getCurrentIndex(type: HMSPlaylistType): number;\n  getCurrentSelection<T>(type: HMSPlaylistType): HMSPlaylistItem<T> | undefined;\n  /**\n   * Returns a value between 0-100\n   * @param {HMSPlaylistType} type\n   */\n  getCurrentProgress(type: HMSPlaylistType): number;\n  /**\n   * Get the currentTime of audio/video based on type\n   * @param {HMSPlaylistType} type\n   */\n  getCurrentTime(type: HMSPlaylistType): number;\n  setEnabled(enabled: boolean, info: { id: string; type: HMSPlaylistType }): Promise<void>;\n  stop(type: HMSPlaylistType): Promise<void>;\n  /**\n   * Subscriber to progress event with a callback\n   * @param fn\n   */\n  onProgress(fn: (event: HMSPlaylistProgressEvent) => void): void;\n  /**\n   * This will be called when a new track is played\n   * @param fn\n   */\n  onNewTrackStart<T>(fn: (item: HMSPlaylistItem<T>) => void): void;\n\n  onPlaylistEnded(fn: (type: HMSPlaylistType) => void): void;\n  onCurrentTrackEnded<T>(fn: (item: HMSPlaylistItem<T>) => void): void;\n  /**\n   * Function to autoplay status i.e. whether next item in playlist after the current one ends\n   * @param {HMSPlaylistType} type\n   * @param {boolean} autoplay\n   */\n  setIsAutoplayOn(type: HMSPlaylistType, autoplay: boolean): void;\n  /**\n   * Get the current playback rate of audio/video playlist\n   * @param {HMSPlaylistType} type\n   */\n  getPlaybackRate(type: HMSPlaylistType): number;\n  /**\n   * set the current playback rate of audio/video playlist\n   * @param {HMSPlaylistType}type\n   * @param {number}value - number between 0.25 and 2.0\n   */\n  setPlaybackRate(type: HMSPlaylistType, value: number): void;\n}\n\nexport interface HMSPlaylistSettings {\n  video: {\n    bitrate: number;\n  };\n  audio: {\n    bitrate: number;\n  };\n}\n","import { HMSRoleName } from '../role';\n\nexport type HMSPollUserTrackingMode = 'peerID' | 'customerID' | 'userName';\n\nexport type HMSPollState = 'created' | 'started' | 'stopped';\n\nexport interface HMSPoll {\n  id: string;\n  title: string;\n  state?: HMSPollState;\n  type: 'poll' | 'quiz';\n  duration?: number;\n  anonymous?: boolean;\n  visibility?: boolean;\n  locked?: boolean;\n  mode?: HMSPollUserTrackingMode;\n  createdBy?: string;\n  startedBy?: string;\n  stoppedBy?: string;\n  createdAt?: Date;\n  startedAt?: Date;\n  stoppedAt?: Date;\n  questions?: HMSPollQuestion[];\n  rolesThatCanVote?: HMSRoleName[];\n  rolesThatCanViewResponses?: HMSRoleName[];\n  result?: HMSPollResult;\n}\n\nexport interface HMSPollCreateParams\n  extends Pick<\n    HMSPoll,\n    | 'id'\n    | 'title'\n    | 'type'\n    | 'duration'\n    | 'anonymous'\n    | 'visibility'\n    | 'locked'\n    | 'mode'\n    | 'rolesThatCanVote'\n    | 'rolesThatCanViewResponses'\n  > {\n  questions?: HMSPollQuestionCreateParams[];\n}\n\nexport interface HMSPollQuestion {\n  index: number;\n  text: string;\n  type: HMSPollQuestionType;\n  skippable?: boolean;\n  duration?: number;\n  once?: boolean;\n  weight?: number;\n  negative?: boolean;\n  answerMinLen?: number;\n  answerMaxLen?: number;\n  options?: HMSPollQuestionOption[];\n  answer?: HMSPollQuestionAnswer;\n  responses?: HMSPollQuestionResponse[];\n  result?: HMSPollQuestionResult;\n}\n\nexport interface HMSPollQuestionCreateParams extends Pick<HMSPollQuestion, 'text' | 'skippable' | 'type' | 'answer'> {\n  index?: number;\n  options?: HMSPollQuestionOptionCreateParams[];\n  weight?: number;\n}\n\nexport interface HMSPollQuestionAnswer {\n  hidden: boolean; // if true answer will not be returned when poll is running\n  option?: number; // option index for correct answer, in case of single choice\n  options?: number[]; // list of options that shoould be in answer\n  text?: string; // answer text for answer.\n  case?: boolean; // if false case is ignored when comparing.\n  trim?: boolean; // if true, empty space is trimmer from start and end of asnwer.\n}\n\nexport enum HMSPollQuestionType {\n  SINGLE_CHOICE = 'single-choice',\n  MULTIPLE_CHOICE = 'multiple-choice',\n  SHORT_ANSWER = 'short-answer',\n  LONG_ANSWER = 'long-answer',\n}\n\nexport enum HMSPollStates {\n  CREATED = 'created',\n  STARTED = 'started',\n  STOPPED = 'stopped',\n}\n\nexport interface HMSPollQuestionOption {\n  index: number;\n  text: string;\n  weight?: number;\n  voteCount?: number;\n}\n\nexport interface HMSPollQuestionOptionCreateParams extends Pick<HMSPollQuestionOption, 'text' | 'weight'> {\n  isCorrectAnswer?: boolean;\n}\n\nexport interface HMSPollQuestionResponse {\n  id?: string;\n  questionIndex: number;\n  peer?: HMSPollResponsePeerInfo;\n  type?: HMSPollQuestionType;\n  skipped?: boolean;\n  option?: number;\n  options?: number[];\n  text?: string;\n  update?: boolean; // SDK Needs to track whether we previously answered and set accordingly\n  duration?: number; // Time it took to answer the question for leaderboard\n  responseFinal?: boolean; // Indicates whether this is last update when fetching responses\n}\n\nexport type HMSPollQuestionResponseCreateParams = Omit<\n  HMSPollQuestionResponse,\n  'type' | 'peer' | 'update' | 'responseFinal'\n>;\n\ninterface HMSPollResponsePeerInfo {\n  userHash?: string;\n  peerid?: string;\n  userid?: string;\n  username?: string;\n}\n\nexport interface HMSPollResult {\n  /**\n   * The number of unique users who responded to the poll\n   */\n  totalUsers?: number;\n  /**\n   * The maximum number of users in the room during the poll.\n   */\n  maxUsers?: number;\n  totalResponses?: number;\n}\n\nexport interface HMSPollQuestionResult {\n  correctResponses?: number;\n  skippedCount?: number;\n  totalResponses?: number;\n}\n\nexport interface HMSQuizLeaderboardEntry {\n  position: number;\n  score: number;\n  totalResponses: number;\n  correctResponses: number;\n  duration: number;\n  peer: HMSPollResponsePeerInfo;\n}\n\nexport interface HMSQuizLeaderboardSummary {\n  avgScore: number;\n  avgTime: number;\n  votedUsers: number;\n  totalUsers: number;\n  correctAnswers: number;\n}\n\nexport interface HMSQuizLeaderboardResponse {\n  entries: HMSQuizLeaderboardEntry[];\n  hasNext: boolean;\n  summary?: HMSQuizLeaderboardSummary;\n}\n","import { IAnalyticsPropertiesProvider } from '../../analytics/IAnalyticsPropertiesProvider';\nimport { HMSAudioCodec, HMSAudioTrackSettings as IHMSAudioTrackSettings } from '../../interfaces';\n\nexport class HMSAudioTrackSettingsBuilder {\n  private _volume = 1.0;\n  private _codec?: HMSAudioCodec = HMSAudioCodec.OPUS;\n  private _maxBitrate?: number = 32;\n  private _deviceId = 'default';\n  private _advanced: Array<MediaTrackConstraintSet> = [\n    // @ts-ignore\n    { googEchoCancellation: { exact: true } },\n    // @ts-ignore\n    { googExperimentalEchoCancellation: { exact: true } },\n    // @ts-ignore\n    { autoGainControl: { exact: true } },\n    // @ts-ignore\n    { noiseSuppression: { exact: true } },\n    // @ts-ignore\n    { googHighpassFilter: { exact: true } },\n    // @ts-ignore\n    { googAudioMirroring: { exact: true } },\n  ];\n\n  volume(volume: number) {\n    if (!(0.0 <= volume && volume <= 1.0)) {\n      throw Error('volume can only be in range [0.0, 1.0]');\n    }\n    this._volume = volume;\n    return this;\n  }\n\n  codec(codec?: HMSAudioCodec) {\n    this._codec = codec;\n    return this;\n  }\n\n  maxBitrate(maxBitrate?: number) {\n    if (maxBitrate && maxBitrate <= 0) {\n      throw Error('maxBitrate should be >= 1');\n    }\n    this._maxBitrate = maxBitrate;\n    return this;\n  }\n\n  deviceId(deviceId: string) {\n    // TODO: Validate if device-id is OK\n    this._deviceId = deviceId;\n    return this;\n  }\n\n  advanced(advanced: Array<MediaTrackConstraintSet>) {\n    this._advanced = advanced;\n    return this;\n  }\n\n  build() {\n    return new HMSAudioTrackSettings(this._volume, this._codec, this._maxBitrate, this._deviceId, this._advanced);\n  }\n}\n\nexport class HMSAudioTrackSettings implements IHMSAudioTrackSettings, IAnalyticsPropertiesProvider {\n  readonly volume?: number;\n  readonly codec?: HMSAudioCodec;\n  readonly maxBitrate?: number;\n  readonly deviceId?: string;\n  readonly advanced?: Array<MediaTrackConstraintSet>;\n\n  constructor(\n    volume?: number,\n    codec?: HMSAudioCodec,\n    maxBitrate?: number,\n    deviceId?: string,\n    advanced?: Array<MediaTrackConstraintSet>,\n  ) {\n    this.volume = volume;\n    this.codec = codec;\n    this.maxBitrate = maxBitrate;\n    this.deviceId = deviceId;\n    this.advanced = advanced;\n  }\n\n  toConstraints(): MediaTrackConstraints {\n    return {\n      deviceId: this.deviceId,\n      advanced: this.advanced,\n    };\n  }\n\n  toAnalyticsProperties() {\n    return {\n      audio_bitrate: this.maxBitrate,\n      audio_codec: this.codec,\n    };\n  }\n}\n","import { IAnalyticsPropertiesProvider } from '../../analytics/IAnalyticsPropertiesProvider';\nimport { HMSFacingMode, HMSVideoCodec, HMSVideoTrackSettings as IHMSVideoTrackSettings } from '../../interfaces';\nimport { isMobile } from '../../utils/support';\n\nexport class HMSVideoTrackSettingsBuilder {\n  private _width?: number = 320;\n  private _height?: number = 180;\n  private _codec?: HMSVideoCodec = HMSVideoCodec.VP8;\n  private _maxFramerate?: number = 30;\n  private _maxBitrate?: number = 150;\n  private _deviceId?: string;\n  private _facingMode?: HMSFacingMode;\n  private _advanced: Array<MediaTrackConstraintSet> = [];\n\n  setWidth(width?: number) {\n    this._width = width;\n    return this;\n  }\n\n  setHeight(height?: number) {\n    this._height = height;\n    return this;\n  }\n\n  codec(codec?: HMSVideoCodec) {\n    this._codec = codec;\n    return this;\n  }\n\n  maxFramerate(maxFramerate?: number) {\n    if (maxFramerate && maxFramerate <= 0) {\n      throw Error('maxFramerate should be >= 1');\n    }\n    this._maxFramerate = maxFramerate;\n    return this;\n  }\n\n  /**\n   * @param useDefault Ignored if maxBitrate is valid.\n   * If true and maxBitrate is undefined - sets a default value.\n   * If false and maxBitrate is undefined - sets undefined.\n   */\n  maxBitrate(maxBitrate?: number, useDefault = true) {\n    if (typeof maxBitrate === 'number' && maxBitrate <= 0) {\n      throw Error('maxBitrate should be >= 1');\n    }\n    this._maxBitrate = maxBitrate;\n    if (!this._maxBitrate && useDefault) {\n      this._maxBitrate = 150_000;\n    }\n    return this;\n  }\n\n  deviceId(deviceId: string) {\n    // TODO: Validate if device-id is OK\n    this._deviceId = deviceId;\n    return this;\n  }\n\n  advanced(advanced: Array<MediaTrackConstraintSet>) {\n    this._advanced = advanced;\n    return this;\n  }\n\n  facingMode(mode: HMSFacingMode) {\n    this._facingMode = mode;\n    return this;\n  }\n\n  build() {\n    return new HMSVideoTrackSettings(\n      this._width,\n      this._height,\n      this._codec,\n      this._maxFramerate,\n      this._deviceId,\n      this._advanced,\n      this._maxBitrate,\n      this._facingMode,\n    );\n  }\n}\n\nexport class HMSVideoTrackSettings implements IHMSVideoTrackSettings, IAnalyticsPropertiesProvider {\n  readonly width?: number;\n  readonly height?: number;\n  readonly codec?: HMSVideoCodec;\n  readonly maxFramerate?: number;\n  readonly maxBitrate?: number;\n  readonly deviceId?: string;\n  readonly advanced?: Array<MediaTrackConstraintSet>;\n  facingMode?: HMSFacingMode;\n\n  constructor(\n    width?: number,\n    height?: number,\n    codec?: HMSVideoCodec,\n    maxFramerate?: number,\n    deviceId?: string | undefined,\n    advanced?: Array<MediaTrackConstraintSet>,\n    maxBitrate?: number,\n    facingMode?: HMSFacingMode,\n  ) {\n    this.width = width;\n    this.height = height;\n    this.codec = codec;\n    this.maxFramerate = maxFramerate;\n    this.maxBitrate = maxBitrate;\n    this.deviceId = deviceId;\n    this.advanced = advanced;\n    this.facingMode = facingMode;\n  }\n\n  toConstraints(isScreenShare?: boolean): MediaTrackConstraints {\n    let dimensionConstraintKey = 'ideal';\n    if (isScreenShare) {\n      dimensionConstraintKey = 'max';\n    }\n    const aspectRatio = this.improviseConstraintsAspect();\n    return {\n      width: { [dimensionConstraintKey]: aspectRatio.width },\n      height: { [dimensionConstraintKey]: aspectRatio.height },\n      frameRate: this.maxFramerate,\n      deviceId: this.deviceId,\n      facingMode: this.facingMode,\n    };\n  }\n\n  toAnalyticsProperties() {\n    return {\n      width: this.width,\n      height: this.height,\n      video_bitrate: this.maxBitrate,\n      framerate: this.maxFramerate,\n      video_codec: this.codec,\n      facingMode: this.facingMode,\n    };\n  }\n\n  // reverse the height and width if mobile as mobile web browsers override the height and width basis orientation\n  private improviseConstraintsAspect(): Partial<IHMSVideoTrackSettings> {\n    if (isMobile() && this.height && this.width && this.height > this.width) {\n      return {\n        width: this.height,\n        height: this.width,\n      };\n    }\n    return {\n      width: this.width,\n      height: this.height,\n    };\n  }\n}\n","import { HMSAudioTrackSettings, HMSAudioTrackSettingsBuilder } from './HMSAudioTrackSettings';\nimport { HMSVideoTrackSettings, HMSVideoTrackSettingsBuilder } from './HMSVideoTrackSettings';\nimport { IAnalyticsPropertiesProvider } from '../../analytics/IAnalyticsPropertiesProvider';\nimport { ErrorFactory } from '../../error/ErrorFactory';\nimport { HMSAction } from '../../error/HMSAction';\n\nexport class HMSTrackSettingsBuilder {\n  private _video: HMSVideoTrackSettings | null = new HMSVideoTrackSettingsBuilder().build();\n  private _audio: HMSAudioTrackSettings | null = new HMSAudioTrackSettingsBuilder().build();\n  private _screen: HMSVideoTrackSettings | null = new HMSVideoTrackSettingsBuilder().build();\n  private _simulcast = false;\n\n  video(video: HMSVideoTrackSettings | null) {\n    this._video = video;\n    return this;\n  }\n\n  audio(audio: HMSAudioTrackSettings | null) {\n    this._audio = audio;\n    return this;\n  }\n\n  screen(screen: HMSVideoTrackSettings | null) {\n    this._screen = screen;\n    return this;\n  }\n\n  simulcast(enabled: boolean) {\n    this._simulcast = enabled;\n    return this;\n  }\n\n  build() {\n    if (this._audio === null && this._video === null) {\n      throw ErrorFactory.TracksErrors.NothingToReturn(HMSAction.TRACK);\n    }\n\n    if (this._video === null && this._simulcast) {\n      throw ErrorFactory.TracksErrors.InvalidVideoSettings(\n        HMSAction.TRACK,\n        'Cannot enable simulcast when no video settings are provided',\n      );\n    }\n\n    return new HMSTrackSettings(this._video, this._audio, this._simulcast, this._screen || undefined);\n  }\n}\n\nexport class HMSTrackSettings implements IAnalyticsPropertiesProvider {\n  readonly video: HMSVideoTrackSettings | null | undefined;\n  readonly audio: HMSAudioTrackSettings | null | undefined;\n  readonly screen: HMSVideoTrackSettings | null;\n  readonly simulcast: boolean;\n\n  constructor(\n    video: HMSVideoTrackSettings | null | undefined,\n    audio: HMSAudioTrackSettings | null | undefined,\n    simulcast: boolean,\n    screen: HMSVideoTrackSettings | null = null,\n  ) {\n    this.video = video;\n    this.audio = audio;\n    this.simulcast = simulcast;\n    this.screen = screen;\n  }\n\n  toAnalyticsProperties() {\n    let properties = {\n      audio_enabled: this.audio !== null,\n      video_enabled: this.video !== null,\n    };\n\n    if (this.audio) {\n      properties = { ...this.audio.toAnalyticsProperties(), ...properties };\n    }\n\n    if (this.video) {\n      properties = { ...this.video.toAnalyticsProperties(), ...properties };\n    }\n\n    return properties;\n  }\n}\n","import { HMSAudioTrack } from './HMSAudioTrack';\nimport AnalyticsEventFactory from '../../analytics/AnalyticsEventFactory';\nimport { DeviceStorageManager } from '../../device-manager/DeviceStorage';\nimport { HMSException } from '../../error/HMSException';\nimport { EventBus } from '../../events/EventBus';\nimport { HMSAudioTrackSettings as IHMSAudioTrackSettings } from '../../interfaces';\nimport { HMSAudioPlugin, HMSPluginSupportResult } from '../../plugins';\nimport { HMSAudioPluginsManager } from '../../plugins/audio';\nimport HMSLogger from '../../utils/logger';\nimport { isBrowser, isIOS } from '../../utils/support';\nimport { getAudioTrack, isEmptyTrack } from '../../utils/track';\nimport { TrackAudioLevelMonitor } from '../../utils/track-audio-level-monitor';\nimport { HMSAudioTrackSettings, HMSAudioTrackSettingsBuilder } from '../settings';\nimport { HMSLocalStream } from '../streams';\n\nfunction generateHasPropertyChanged(newSettings: Partial<HMSAudioTrackSettings>, oldSettings: HMSAudioTrackSettings) {\n  return function hasChanged(prop: 'codec' | 'volume' | 'maxBitrate' | 'deviceId' | 'advanced') {\n    return prop in newSettings && newSettings[prop] !== oldSettings[prop];\n  };\n}\n\nexport class HMSLocalAudioTrack extends HMSAudioTrack {\n  private readonly TAG = '[HMSLocalAudioTrack]';\n  settings: HMSAudioTrackSettings;\n  private pluginsManager: HMSAudioPluginsManager;\n  private processedTrack?: MediaStreamTrack;\n  private manuallySelectedDeviceId?: string;\n\n  audioLevelMonitor?: TrackAudioLevelMonitor;\n\n  /**\n   * see the doc in HMSLocalVideoTrack\n   * @internal\n   */\n  publishedTrackId?: string;\n\n  /**\n   * will be false for preview tracks\n   */\n  isPublished = false;\n\n  constructor(\n    stream: HMSLocalStream,\n    track: MediaStreamTrack,\n    source: string,\n    private eventBus: EventBus,\n    settings: HMSAudioTrackSettings = new HMSAudioTrackSettingsBuilder().build(),\n  ) {\n    super(stream, track, source);\n    stream.tracks.push(this);\n\n    this.settings = settings;\n    // Replace the 'default' or invalid deviceId with the actual deviceId\n    // This is to maintain consistency with selected devices as in some cases there will be no 'default' device\n    if (settings.deviceId !== track.getSettings().deviceId && !isEmptyTrack(track)) {\n      this.settings = this.buildNewSettings({ deviceId: track.getSettings().deviceId });\n    }\n    this.pluginsManager = new HMSAudioPluginsManager(this, eventBus);\n    this.setFirstTrackId(track.id);\n    if (isIOS() && isBrowser) {\n      document.addEventListener('visibilitychange', this.handleVisibilityChange);\n    }\n  }\n\n  getManuallySelectedDeviceId() {\n    return this.manuallySelectedDeviceId;\n  }\n\n  resetManuallySelectedDeviceId() {\n    this.manuallySelectedDeviceId = undefined;\n  }\n\n  private handleVisibilityChange = async () => {\n    if (document.visibilityState === 'visible') {\n      await this.replaceTrackWith(this.settings);\n    }\n  };\n\n  private async replaceTrackWith(settings: HMSAudioTrackSettings) {\n    const prevTrack = this.nativeTrack;\n    /*\n     * Note: Do not change the order of this.\n     * stop the previous before acquiring the new track otherwise this can lead to\n     * no audio when the above getAudioTrack throws an error. ex: DeviceInUse error\n     */\n    prevTrack?.stop();\n    const isLevelMonitored = Boolean(this.audioLevelMonitor);\n    try {\n      const newTrack = await getAudioTrack(settings);\n      newTrack.enabled = this.enabled;\n      HMSLogger.d(this.TAG, 'replaceTrack, Previous track stopped', prevTrack, 'newTrack', newTrack);\n\n      const localStream = this.stream as HMSLocalStream;\n      // change nativeTrack so plugin can start its work\n      await localStream.replaceSenderTrack(prevTrack, this.processedTrack || newTrack);\n      await localStream.replaceStreamTrack(prevTrack, newTrack);\n      this.nativeTrack = newTrack;\n      isLevelMonitored && this.initAudioLevelMonitor();\n    } catch (e) {\n      if (this.isPublished) {\n        this.eventBus.analytics.publish(\n          AnalyticsEventFactory.publish({\n            error: e as Error,\n          }),\n        );\n      }\n      throw e;\n    }\n    try {\n      await this.pluginsManager.reprocessPlugins();\n    } catch (e) {\n      this.eventBus.audioPluginFailed.publish(e as HMSException);\n    }\n  }\n\n  async setEnabled(value: boolean) {\n    if (value === this.enabled) {\n      return;\n    }\n\n    // Replace silent empty track with an actual audio track, if enabled.\n    if (value && isEmptyTrack(this.nativeTrack)) {\n      await this.replaceTrackWith(this.settings);\n    }\n    await super.setEnabled(value);\n    if (value) {\n      this.settings = this.buildNewSettings({ deviceId: this.nativeTrack.getSettings().deviceId });\n    }\n    this.eventBus.localAudioEnabled.publish({ enabled: value, track: this });\n  }\n\n  /**\n   * verify if the track id being passed is of this track for correlating server messages like audio level\n   */\n  isPublishedTrackId(trackId: string) {\n    return this.publishedTrackId === trackId;\n  }\n\n  async setSettings(settings: Partial<IHMSAudioTrackSettings>, internal = false) {\n    const newSettings = this.buildNewSettings(settings);\n\n    if (isEmptyTrack(this.nativeTrack)) {\n      // if it is an empty track, cache the settings for when it is unmuted\n      this.settings = newSettings;\n      return;\n    }\n    await this.handleDeviceChange(newSettings, internal);\n    await this.handleSettingsChange(newSettings);\n    this.settings = newSettings;\n  }\n\n  /**\n   * @see HMSAudioPlugin\n   */\n  getPlugins(): string[] {\n    return this.pluginsManager.getPlugins();\n  }\n\n  /**\n   * @see HMSAudioPlugin\n   */\n  async addPlugin(plugin: HMSAudioPlugin): Promise<void> {\n    return this.pluginsManager.addPlugin(plugin);\n  }\n\n  /**\n   * @see HMSAudioPlugin\n   */\n  async removePlugin(plugin: HMSAudioPlugin): Promise<void> {\n    return this.pluginsManager.removePlugin(plugin);\n  }\n\n  /**\n   * @see HMSAudioPlugin\n   */\n  validatePlugin(plugin: HMSAudioPlugin): HMSPluginSupportResult {\n    return this.pluginsManager.validatePlugin(plugin);\n  }\n\n  /**\n   * @internal\n   */\n  async setProcessedTrack(processedTrack?: MediaStreamTrack) {\n    // if all plugins are removed reset everything back to native track\n    if (!processedTrack) {\n      if (this.processedTrack) {\n        // remove, reset back to the native track\n        await (this.stream as HMSLocalStream).replaceSenderTrack(this.processedTrack, this.nativeTrack);\n      }\n      this.processedTrack = undefined;\n      return;\n    }\n    if (processedTrack !== this.processedTrack) {\n      if (this.processedTrack) {\n        // replace previous processed track with new one\n        await (this.stream as HMSLocalStream).replaceSenderTrack(this.processedTrack, processedTrack);\n      } else {\n        // there is no prev processed track, replace native with new one\n        await (this.stream as HMSLocalStream).replaceSenderTrack(this.nativeTrack, processedTrack);\n      }\n      this.processedTrack = processedTrack;\n    }\n  }\n\n  initAudioLevelMonitor() {\n    if (this.audioLevelMonitor) {\n      this.destroyAudioLevelMonitor();\n    }\n    HMSLogger.d(this.TAG, 'Monitor Audio Level for', this, this.getMediaTrackSettings().deviceId);\n    this.audioLevelMonitor = new TrackAudioLevelMonitor(\n      this,\n      this.eventBus.trackAudioLevelUpdate,\n      this.eventBus.localAudioSilence,\n    );\n    this.audioLevelMonitor.start();\n    this.audioLevelMonitor.detectSilence();\n  }\n\n  destroyAudioLevelMonitor() {\n    this.audioLevelMonitor?.stop();\n    this.audioLevelMonitor = undefined;\n  }\n\n  async cleanup() {\n    super.cleanup();\n    await this.pluginsManager.cleanup();\n    await this.pluginsManager.closeContext();\n    this.transceiver = undefined;\n    this.processedTrack?.stop();\n    this.isPublished = false;\n    this.destroyAudioLevelMonitor();\n    if (isIOS() && isBrowser) {\n      document.removeEventListener('visibilitychange', this.handleVisibilityChange);\n    }\n  }\n\n  /**\n   * @internal\n   * published track id will be different in case there was some processing done using plugins.\n   */\n  getTrackIDBeingSent() {\n    return this.processedTrack ? this.processedTrack.id : this.nativeTrack.id;\n  }\n\n  /**\n   * @internal\n   */\n  getTrackBeingSent() {\n    return this.processedTrack || this.nativeTrack;\n  }\n\n  private buildNewSettings(settings: Partial<HMSAudioTrackSettings>) {\n    const { volume, codec, maxBitrate, deviceId, advanced } = { ...this.settings, ...settings };\n    const newSettings = new HMSAudioTrackSettings(volume, codec, maxBitrate, deviceId, advanced);\n    return newSettings;\n  }\n\n  private handleSettingsChange = async (settings: HMSAudioTrackSettings) => {\n    const stream = this.stream as HMSLocalStream;\n    const hasPropertyChanged = generateHasPropertyChanged(settings, this.settings);\n    if (hasPropertyChanged('maxBitrate') && settings.maxBitrate) {\n      await stream.setMaxBitrateAndFramerate(this);\n    }\n\n    if (hasPropertyChanged('advanced')) {\n      await this.replaceTrackWith(settings);\n    }\n  };\n\n  /**\n   * Replace audio track with new track on device change if enabled\n   * @param settings - AudioSettings Object constructed with new settings\n   * @param internal - whether the change was because of internal sdk call or external client call\n   */\n  private handleDeviceChange = async (settings: HMSAudioTrackSettings, internal = false) => {\n    const hasPropertyChanged = generateHasPropertyChanged(settings, this.settings);\n    if (hasPropertyChanged('deviceId')) {\n      this.manuallySelectedDeviceId = !internal ? settings.deviceId : this.manuallySelectedDeviceId;\n      await this.replaceTrackWith(settings);\n      if (!internal) {\n        DeviceStorageManager.updateSelection('audioInput', {\n          deviceId: settings.deviceId,\n          groupId: this.nativeTrack.getSettings().groupId,\n        });\n      }\n    }\n  };\n}\n","import { HMSAudioTrack } from './HMSAudioTrack';\n\nexport class HMSRemoteAudioTrack extends HMSAudioTrack {\n  async setEnabled(value: boolean): Promise<void> {\n    if (value === this.enabled) {\n      return;\n    }\n    await super.setEnabled(value);\n    await this.subscribeToAudio(value);\n  }\n}\n","import { HMSTrack, HMSTrackSource } from './HMSTrack';\nimport { HMSTrackType } from './HMSTrackType';\nimport { VideoElementManager } from './VideoElementManager';\nimport { HMSMediaStream } from '../streams';\n\nexport class HMSVideoTrack extends HMSTrack {\n  readonly type: HMSTrackType = HMSTrackType.VIDEO;\n  private sinkCount = 0;\n  videoHandler!: VideoElementManager;\n\n  constructor(stream: HMSMediaStream, track: MediaStreamTrack, source?: string) {\n    super(stream, track, source as HMSTrackSource);\n    if (track.kind !== 'video') {\n      throw new Error(\"Expected 'track' kind = 'video'\");\n    }\n  }\n\n  setVideoHandler(videoHandler: VideoElementManager) {\n    this.videoHandler = videoHandler;\n  }\n\n  /**\n   * sink=video element rendering the video\n   */\n  hasSinks() {\n    return this.sinkCount > 0;\n  }\n\n  getSinks() {\n    return this.videoHandler.getVideoElements() || [];\n  }\n\n  attach(videoElement: HTMLVideoElement) {\n    this.videoHandler.addVideoElement(videoElement);\n  }\n\n  detach(videoElement: HTMLVideoElement) {\n    this.videoHandler.removeVideoElement(videoElement);\n  }\n\n  /**\n   * attaches the track to the passed in video element\n   * @param videoElement\n   */\n  addSink(videoElement: HTMLVideoElement) {\n    this.addSinkInternal(videoElement, this.nativeTrack);\n  }\n\n  /**\n   * removes the track from the passed in video element\n   * @param videoElement\n   */\n  removeSink(videoElement: HTMLVideoElement) {\n    if (videoElement.srcObject !== null) {\n      videoElement.srcObject = null;\n      this.reduceSinkCount();\n    }\n  }\n\n  cleanup(): void {\n    super.cleanup();\n    this.videoHandler.cleanup();\n  }\n\n  protected addSinkInternal(videoElement: HTMLVideoElement, track: MediaStreamTrack) {\n    const srcObject = videoElement.srcObject;\n    if (srcObject !== null && srcObject instanceof MediaStream) {\n      const existingTrack = srcObject.getVideoTracks()[0];\n      if (existingTrack?.id === track.id) {\n        if (!existingTrack.muted && existingTrack.readyState === 'live') {\n          // it's already attached, attaching again would just cause flickering\n          return;\n        } else {\n          this.reduceSinkCount();\n        }\n      } else {\n        this.reduceSinkCount();\n      }\n    }\n    videoElement.srcObject = new MediaStream([track]);\n    this.sinkCount++;\n  }\n\n  private reduceSinkCount() {\n    if (this.sinkCount > 0) {\n      this.sinkCount--;\n    }\n  }\n}\n","import { v4 as uuid } from 'uuid';\nimport { getClosestLayer, layerToIntMapping } from './trackUtils';\nimport { HMSPreferredSimulcastLayer } from '../../interfaces/simulcast-layers';\nimport { HMSLocalVideoTrack, HMSRemoteVideoTrack } from '../../internal';\nimport { HMSIntersectionObserver } from '../../utils/intersection-observer';\nimport HMSLogger from '../../utils/logger';\nimport { HMSResizeObserver } from '../../utils/resize-observer';\nimport { isBrowser } from '../../utils/support';\n\n/**\n * This class is to manager video elements for video tracks.\n * This will handle attaching/detaching when element is in view or out of view.\n * This will also handle selecting appropriate layer when element size changesx\n */\nexport class VideoElementManager {\n  private readonly TAG = '[VideoElementManager]';\n  private resizeObserver?: typeof HMSResizeObserver;\n  private intersectionObserver?: typeof HMSIntersectionObserver;\n  private videoElements = new Set<HTMLVideoElement>();\n  private entries = new WeakMap<HTMLVideoElement, DOMRectReadOnly>();\n  private id: string;\n\n  constructor(private track: HMSLocalVideoTrack | HMSRemoteVideoTrack) {\n    this.init();\n    this.id = uuid();\n  }\n\n  updateSinks(requestLayer = false) {\n    for (const videoElement of this.videoElements) {\n      if (this.track.enabled) {\n        this.track.addSink(videoElement, requestLayer);\n      } else {\n        this.track.removeSink(videoElement, requestLayer);\n      }\n    }\n  }\n\n  // eslint-disable-next-line complexity\n  async addVideoElement(videoElement: HTMLVideoElement) {\n    if (this.videoElements.has(videoElement)) {\n      return;\n    }\n    // Call init again, to initialize again if for some reason it failed in constructor\n    // it will be a no-op if initialize already\n    this.init();\n    HMSLogger.d(this.TAG, `Adding video element for ${this.track}`, this.id);\n    this.videoElements.add(videoElement);\n    if (this.videoElements.size >= 10) {\n      HMSLogger.w(\n        this.TAG,\n        `${this.track}`,\n        `the track is added to ${this.videoElements.size} video elements, while this may be intentional, it's likely that there is a bug leading to unnecessary creation of video elements in the UI`,\n      );\n    }\n\n    if (this.intersectionObserver?.isSupported()) {\n      this.intersectionObserver.observe(videoElement, this.handleIntersection);\n    } else if (isBrowser) {\n      if (this.isElementInViewport(videoElement)) {\n        this.track.addSink(videoElement);\n      } else {\n        this.track.removeSink(videoElement);\n      }\n    }\n    if (this.resizeObserver) {\n      this.resizeObserver.observe(videoElement, this.handleResize);\n    } else if (this.track instanceof HMSRemoteVideoTrack) {\n      await this.track.setPreferredLayer(this.track.getPreferredLayer());\n    }\n  }\n\n  removeVideoElement(videoElement: HTMLVideoElement): void {\n    this.track.removeSink(videoElement);\n    this.videoElements.delete(videoElement);\n    this.entries.delete(videoElement);\n    this.resizeObserver?.unobserve(videoElement);\n    this.intersectionObserver?.unobserve(videoElement);\n    HMSLogger.d(this.TAG, `Removing video element for ${this.track}`);\n  }\n\n  getVideoElements(): HTMLVideoElement[] {\n    return Array.from(this.videoElements);\n  }\n\n  private init() {\n    if (isBrowser) {\n      this.resizeObserver = HMSResizeObserver;\n      this.intersectionObserver = HMSIntersectionObserver;\n    }\n  }\n\n  private handleIntersection = async (entry: IntersectionObserverEntry) => {\n    const isVisibile = getComputedStyle(entry.target).visibility === 'visible';\n    // .contains check is needed for pip component as the video tiles are not mounted to dom element\n    if (this.track.enabled && ((entry.isIntersecting && isVisibile) || !document.contains(entry.target))) {\n      HMSLogger.d(this.TAG, 'add sink intersection', `${this.track}`, this.id);\n      this.entries.set(entry.target as HTMLVideoElement, entry.boundingClientRect);\n      await this.selectMaxLayer();\n      await this.track.addSink(entry.target as HTMLVideoElement);\n    } else {\n      HMSLogger.d(this.TAG, 'remove sink intersection', `${this.track}`, this.id);\n      await this.track.removeSink(entry.target as HTMLVideoElement);\n    }\n  };\n\n  private handleResize = async (entry: ResizeObserverEntry) => {\n    if (!this.track.enabled || !(this.track instanceof HMSRemoteVideoTrack)) {\n      return;\n    }\n    this.entries.set(entry.target as HTMLVideoElement, entry.contentRect);\n    await this.selectMaxLayer();\n  };\n\n  /**\n   *  Taken from\n   *  https://stackoverflow.com/a/125106/4321808\n   */\n  // eslint-disable-next-line complexity\n  private isElementInViewport(el: HTMLElement) {\n    let top = el.offsetTop;\n    let left = el.offsetLeft;\n    const width = el.offsetWidth;\n    const height = el.offsetHeight;\n    const { hidden } = el;\n    const { opacity, display } = getComputedStyle(el);\n\n    while (el.offsetParent) {\n      el = el.offsetParent as HTMLElement;\n      top += el.offsetTop;\n      left += el.offsetLeft;\n    }\n\n    return (\n      top < window.pageYOffset + window.innerHeight &&\n      left < window.pageXOffset + window.innerWidth &&\n      top + height > window.pageYOffset &&\n      left + width > window.pageXOffset &&\n      !hidden &&\n      (opacity !== '' ? parseFloat(opacity) > 0 : true) &&\n      display !== 'none'\n    );\n  }\n\n  // eslint-disable-next-line complexity\n  private async selectMaxLayer() {\n    if (!(this.track instanceof HMSRemoteVideoTrack) || this.videoElements.size === 0) {\n      return;\n    }\n    let maxLayer!: HMSPreferredSimulcastLayer;\n    for (const element of this.videoElements) {\n      const entry = this.entries.get(element);\n      if (!entry) {\n        continue;\n      }\n      const { width, height } = entry;\n      if (width === 0 || height === 0) {\n        continue;\n      }\n      const layer = getClosestLayer(this.track.getSimulcastDefinitions(), { width, height });\n      if (!maxLayer) {\n        maxLayer = layer;\n      } else {\n        maxLayer = layerToIntMapping[layer] > layerToIntMapping[maxLayer] ? layer : maxLayer;\n      }\n    }\n    if (maxLayer) {\n      HMSLogger.d(this.TAG, `selecting max layer ${maxLayer} for the track`, `${this.track}`);\n      await this.track.setPreferredLayer(maxLayer);\n    }\n  }\n\n  cleanup = () => {\n    this.videoElements.forEach(videoElement => {\n      videoElement.srcObject = null;\n      this.resizeObserver?.unobserve(videoElement);\n      this.intersectionObserver?.unobserve(videoElement);\n    });\n    this.videoElements.clear();\n    this.resizeObserver = undefined;\n    this.intersectionObserver = undefined;\n  };\n}\n","import { HMSPreferredSimulcastLayer, HMSSimulcastLayer, HMSSimulcastLayerDefinition } from '../../interfaces';\n\nexport const layerToIntMapping = {\n  [HMSSimulcastLayer.NONE]: -1,\n  [HMSSimulcastLayer.LOW]: 0,\n  [HMSSimulcastLayer.MEDIUM]: 1,\n  [HMSSimulcastLayer.HIGH]: 2,\n};\nconst DELTA_THRESHOLD = 0.5;\n\n/**\n * Given the simulcast layers and the current video element dimensions, this function finds the\n * layer with dimensions closer to the video element dimensions.\n */\n// eslint-disable-next-line complexity\nexport const getClosestLayer = (\n  simulcastLayers: HMSSimulcastLayerDefinition[],\n  videoElementDimensions: { width: number; height: number },\n): HMSPreferredSimulcastLayer => {\n  let closestLayer: HMSPreferredSimulcastLayer = HMSSimulcastLayer.HIGH;\n  // when both width and height are equal pick height to select a better quality\n  const maxDimension = videoElementDimensions.width > videoElementDimensions.height ? 'width' : 'height';\n  const layers = [...simulcastLayers].sort((a, b) => layerToIntMapping[a.layer] - layerToIntMapping[b.layer]);\n  const videoDimesion = videoElementDimensions[maxDimension] * (window?.devicePixelRatio || 1);\n  for (let i = 0; i < layers.length; i++) {\n    const { resolution, layer } = layers[i];\n    const layerDimension = resolution[maxDimension];\n    // we break here because the layers are already sorted, the next would always be greater if the below condition satisifes\n    if (videoDimesion <= layerDimension) {\n      closestLayer = layer;\n      break;\n    } else {\n      const nextLayer = layers[i + 1];\n      const nextLayerDimension = nextLayer ? nextLayer.resolution[maxDimension] : Number.POSITIVE_INFINITY;\n      // calculating which layer this dimension is closer to\n      const proximityPercent = (videoDimesion - layerDimension) / (nextLayerDimension - layerDimension);\n      if (proximityPercent < DELTA_THRESHOLD) {\n        // the element's dimension is closer to the current layer\n        closestLayer = layer;\n        break;\n      }\n    }\n  }\n  return closestLayer;\n};\n","import HMSLogger from './logger';\nimport { isBrowser } from './support';\n\nexport interface HMSIntersectionObserverCallback {\n  (entry: IntersectionObserverEntry): void;\n}\n\n/**\n * This is a wrapper around IntersectionObserver which will call the callback passed\n * for an element while observing, only when that element is intersecting\n */\nexport class HMSIntersectionObserverWrapper {\n  private intersectionObserver?: IntersectionObserver;\n  private readonly TAG = '[HMSIntersectionObserverWrapper]';\n  private listeners = new WeakMap<HTMLElement, HMSIntersectionObserverCallback>();\n  constructor() {\n    this.createObserver();\n  }\n\n  isSupported() {\n    const isSupported = isBrowser && typeof window.IntersectionObserver !== 'undefined';\n    if (!isSupported) {\n      HMSLogger.w(this.TAG, 'IntersectionObserver is not supported, fallback will be used instead');\n    }\n    return isSupported;\n  }\n\n  observe = (element: HTMLElement, onIntersection: HMSIntersectionObserverCallback) => {\n    this.createObserver();\n    // unobserve before observing the element\n    this.unobserve(element);\n    this.intersectionObserver?.observe(element);\n    this.listeners.set(element, onIntersection);\n  };\n\n  unobserve = (element: HTMLElement) => {\n    this.intersectionObserver?.unobserve(element);\n    this.listeners.delete(element);\n  };\n\n  private createObserver = () => {\n    if (this.isSupported() && !this.intersectionObserver) {\n      this.intersectionObserver = new IntersectionObserver(this.handleIntersection);\n    }\n  };\n\n  private handleIntersection = (entries: IntersectionObserverEntry[]) => {\n    for (const entry of entries) {\n      this.listeners.get(entry.target as HTMLElement)?.(entry);\n    }\n  };\n}\n\nexport const HMSIntersectionObserver = new HMSIntersectionObserverWrapper();\n","import HMSLogger from './logger';\nimport { isBrowser } from './support';\nimport { debounce } from './timer-utils';\n\nexport interface HMSResizeObserverCallback {\n  (entry: ResizeObserverEntry): void;\n}\n\n/**\n * This is a wrapper around ResizeObserver which will call the callback passed\n * for an element while observing, only when that element is intersecting\n */\nexport class HMSResizeObserverWrapper {\n  private resizeObserver?: ResizeObserver;\n  private readonly TAG = '[HMSResizeObserverWrapper]';\n  private listeners = new WeakMap<HTMLElement, HMSResizeObserverCallback>();\n  constructor() {\n    this.createObserver();\n  }\n\n  isSupported() {\n    const isSupported = isBrowser && typeof window.ResizeObserver !== 'undefined';\n    if (!isSupported) {\n      HMSLogger.w(this.TAG, 'Resize Observer is not supported');\n    }\n    return isSupported;\n  }\n\n  observe = (\n    element: HTMLElement,\n    onResize: HMSResizeObserverCallback,\n    options: ResizeObserverOptions = { box: 'border-box' },\n  ) => {\n    this.createObserver();\n    // unobserve before observing the element\n    this.unobserve(element);\n    this.resizeObserver?.observe(element, options);\n    this.listeners.set(element, onResize);\n  };\n\n  unobserve = (element: HTMLElement) => {\n    this.resizeObserver?.unobserve(element);\n    this.listeners.delete(element);\n  };\n\n  private createObserver = () => {\n    if (this.isSupported() && !this.resizeObserver) {\n      this.resizeObserver = new ResizeObserver(debounce(this.handleResize, 300));\n    }\n  };\n\n  private handleResize = (entries: ResizeObserverEntry[]) => {\n    for (const entry of entries) {\n      this.listeners.get(entry.target as HTMLElement)?.(entry);\n    }\n  };\n}\n\nexport const HMSResizeObserver = new HMSResizeObserverWrapper();\n","import { HMSPluginSupportResult } from '../audio';\n\n/**\n * A plugin implementing this interface can be registered with HMSLocalVideoTrack to transform, process or\n * analyze the local video track.These can include applications like video filters, virtual background, live\n * analysis of video etc. The below functions are required for the sdk to properly use the plugin, usually\n * the plugin would also be exposing some public functions of its own for the UI to control its working.\n */\nexport interface HMSVideoPlugin {\n  /**\n   * The name is meant to uniquely specify a plugin instance. This will be used to track number of plugins\n   * added to the track, and same name won't be allowed twice.\n   */\n  getName(): string;\n\n  /**\n   * This function will be called before the call to init, it is used to check whether the plugin supports current\n   * OS and device or not. An error will be thrown back to the user if they try to use an unsupported plugin.\n   */\n  checkSupport(): HMSPluginSupportResult;\n\n  /**\n   * @deprecated. Will be deleted in future updates. Use checkSupport instead.\n   */\n  isSupported(): boolean;\n\n  /**\n   * This function will be called in the beginning for initialization which may include tasks like setting up\n   * variables, loading ML models etc. This can be used by a plugin to ensure it's prepared at the time\n   * processVideoFrame is called.\n   */\n  init(): Promise<void>;\n\n  /**\n   * @see HMSVideoPluginType\n   */\n  getPluginType(): HMSVideoPluginType;\n\n  getContextType?(): HMSVideoPluginCanvasContextType;\n\n  /**\n   * This function will be called by the SDK for every video frame which the plugin needs to process.\n   * PluginFrameRate - the rate at which the plugin is expected to process the video frames. This is not necessarily\n   * equal to the capture frame rate. The user can specify this rate, and the sdk might also change it on basis of\n   * device type, or CPU usage.\n   * For an analyzing plugin, the below function will be called at plugin framerate.\n   * For a transforming plugin, the sdk will pass in the input and output at real frame rate with an additional boolean\n   * pass. The expectation is that the plugin should use results of previous runs instead of doing a complex processing\n   * again when pass is set to true. This helps in maintaining the framerate of the video as well as bringing down\n   * CPU usage in case of complex processing.\n   * @param input input canvas containing the input frame\n   * @param output the output canvas which should contain the output frame\n   * @param skipProcessing use results from previous run if true\n   */\n  processVideoFrame(\n    input: HTMLCanvasElement,\n    output?: HTMLCanvasElement,\n    skipProcessing?: boolean,\n  ): Promise<void> | void;\n\n  /**\n   * the plugin can use this function to dispose off its resources. It'll be called when the processor instance is\n   * no longer needed at the end.\n   */\n  stop(): void;\n}\n\n/**\n * Specifies the type of the plugin a transforming plugin will get an output canvas to give the resulting\n * transformation. While an analyzing plugin will only be passed the input canvas.\n */\nexport enum HMSVideoPluginType {\n  TRANSFORM = 'TRANSFORM',\n  ANALYZE = 'ANALYZE',\n}\n\nexport enum HMSVideoPluginCanvasContextType {\n  '2D' = '2d',\n  WEBGL = 'webgl',\n  'WEBGL2' = 'webgl2',\n}\n","export class RunningAverage {\n  private total = 0;\n  private count = 0;\n\n  add(item: number) {\n    this.count++;\n    this.total += item;\n  }\n\n  getAvg(): number {\n    return Math.floor(this.total / this.count);\n  }\n\n  reset() {\n    this.total = 0;\n    this.count = 0;\n  }\n}\n","import MediaPluginsAnalyticsFactory from '../../analytics/MediaPluginsAnalyticsFactory';\nimport { ErrorFactory } from '../../error/ErrorFactory';\nimport { HMSAction } from '../../error/HMSAction';\nimport { HMSException } from '../../error/HMSException';\nimport { EventBus } from '../../events/EventBus';\nimport HMSLogger from '../../utils/logger';\nimport { RunningAverage } from '../../utils/math';\n\nexport class VideoPluginsAnalytics {\n  private readonly TAG = '[VideoPluginsAnalytics]';\n  private readonly initTime: Record<string, number>;\n  private readonly addedTimestamps: Record<string, number>;\n  private readonly preProcessingAvgs: RunningAverage;\n  private readonly processingAvgs: Record<string, RunningAverage>;\n  private readonly pluginAdded: Record<string, boolean>;\n  private readonly pluginInputFrameRate: Record<string, number>;\n  private readonly pluginFrameRate: Record<string, number>;\n\n  constructor(private eventBus: EventBus) {\n    this.initTime = {};\n    this.preProcessingAvgs = new RunningAverage();\n    this.addedTimestamps = {};\n    this.processingAvgs = {};\n    this.pluginAdded = {};\n    this.pluginInputFrameRate = {};\n    this.pluginFrameRate = {};\n  }\n\n  added(name: string, inputFrameRate: number, pluginFrameRate?: number) {\n    this.pluginAdded[name] = true;\n    this.addedTimestamps[name] = Date.now();\n    this.initTime[name] = 0;\n    this.processingAvgs[name] = new RunningAverage();\n    this.pluginInputFrameRate[name] = inputFrameRate;\n    this.pluginFrameRate[name] = pluginFrameRate || inputFrameRate;\n  }\n\n  removed(name: string) {\n    //send stats\n    if (this.pluginAdded[name]) {\n      const stats = {\n        pluginName: name,\n        // duration in seconds\n        duration: Math.floor((Date.now() - this.addedTimestamps[name]) / 1000),\n        loadTime: this.initTime[name],\n        avgPreProcessingTime: this.preProcessingAvgs.getAvg(), //Do we need this in stat not plugin specific\n        avgProcessingTime: this.processingAvgs[name]?.getAvg(),\n        inputFrameRate: this.pluginInputFrameRate[name],\n        pluginFrameRate: this.pluginFrameRate[name],\n      };\n      //send stats\n      this.eventBus.analytics.publish(MediaPluginsAnalyticsFactory.stats(stats));\n      //clean the plugin details\n      this.clean(name);\n    }\n  }\n\n  failure(name: string, error: HMSException) {\n    // send failure event\n    if (this.pluginAdded[name]) {\n      this.eventBus.analytics.publish(MediaPluginsAnalyticsFactory.failure(name, error));\n      //clean the plugin details\n      this.clean(name);\n    }\n  }\n\n  async initWithTime<T>(name: string, initFn: () => Promise<T>) {\n    if (this.initTime[name]) {\n      HMSLogger.i(this.TAG, `Plugin Already loaded ${name}, time it took: ${this.initTime[name]}`);\n      return;\n    }\n    let time: number | undefined = undefined;\n    try {\n      time = await this.timeInMs(initFn);\n      HMSLogger.i(this.TAG, `Time taken for Plugin ${name} initialization : ${time}`);\n    } catch (e) {\n      //Failed during initialization of plugin(model loading etc...)\n      const err = ErrorFactory.MediaPluginErrors.InitFailed(\n        HMSAction.VIDEO_PLUGINS,\n        `failed during initialization of plugin${(e as Error).message || e}`,\n      );\n      HMSLogger.e(this.TAG, err);\n      this.failure(name, err);\n      throw err;\n    }\n    if (time) {\n      this.initTime[name] = time;\n    }\n  }\n\n  async preProcessWithTime<T>(preProcessFn: () => Promise<T>) {\n    //TODO: check if it is required to maintain and shall we handle preprocess failures\n    const time = await this.timeInMs(preProcessFn);\n    this.preProcessingAvgs.add(time);\n  }\n\n  async processWithTime<T>(name: string, processFn: () => Promise<T>) {\n    let time: number | undefined = undefined;\n    try {\n      time = await this.timeInMs(processFn);\n    } catch (e) {\n      //Failed during processing of plugin\n      const err = ErrorFactory.MediaPluginErrors.ProcessingFailed(\n        HMSAction.VIDEO_PLUGINS,\n        `Failed during processing of plugin${(e as Error).message || e}`,\n      );\n      HMSLogger.e(this.TAG, err);\n      this.failure(name, err);\n      throw err;\n    }\n    if (time) {\n      this.processingAvgs[name]?.add(time);\n    }\n  }\n\n  private async timeInMs<T>(fn: () => Promise<T>): Promise<number> {\n    const start = Date.now();\n    await fn();\n    return Math.floor(Date.now() - start);\n  }\n\n  private clean(name: string) {\n    delete this.addedTimestamps[name];\n    delete this.initTime[name];\n    delete this.processingAvgs[name];\n    delete this.pluginAdded[name];\n    delete this.pluginInputFrameRate[name];\n    delete this.pluginFrameRate[name];\n  }\n}\n","/* eslint-disable complexity */\nimport { HMSVideoPlugin, HMSVideoPluginCanvasContextType, HMSVideoPluginType } from './HMSVideoPlugin';\nimport { VideoPluginsAnalytics } from './VideoPluginsAnalytics';\nimport { ErrorFactory } from '../../error/ErrorFactory';\nimport { HMSAction } from '../../error/HMSAction';\nimport { EventBus } from '../../events/EventBus';\nimport { HMSLocalVideoTrack } from '../../media/tracks';\nimport HMSLogger from '../../utils/logger';\nimport { workerSleep } from '../../utils/timer-utils';\nimport { HMSPluginUnsupportedTypes } from '../audio';\n\nconst DEFAULT_FRAME_RATE = 24;\nconst DEFAULT_WIDTH = 320;\nconst DEFAULT_HEIGHT = 240;\n\ninterface CanvasElement extends HTMLCanvasElement {\n  captureStream(frameRate?: number): MediaStream;\n}\n\n/**\n * This class manages applying different plugins on a local video track. Plugins which need to modify the video\n * are called in the order they were added. Plugins which do not need to modify the video frames are called\n * with the original input.\n *\n * Concepts -\n * Video Plugin - A module which can take in input video painted on a canvas, do some processing on it and optionally\n * render its output on a passed in output canvas which will be shown in the UI.\n *\n * frameRate - the frame rate of the input video as present in track.getSettings, this is the rate at which new frames\n * are being produced and the rate we need to maintain in output as well.\n *\n * pluginFrameRate - this is the rate at which the plugin is supposed to do its processing. The processing can be an\n * expensive operation and can result in high usage of resources like CPU. This rate would usually be lower than the\n * real frame rate.\n *\n * pluginsLoop - a loop is run at framerate in this class, on each loop if the original track is unmuted all added\n * plugins are called one by one in the order they were called.\n *\n * @see HMSVideoPlugin\n */\nexport class HMSVideoPluginsManager {\n  private readonly TAG = '[VideoPluginsManager]';\n\n  /**\n   * plugins loop is the loop in which all plugins are applied\n   */\n  private pluginsLoopRunning = false;\n  private pluginsLoopState: 'paused' | 'running' = 'paused';\n  private readonly hmsTrack: HMSLocalVideoTrack;\n  private readonly pluginsMap: Map<string, HMSVideoPlugin>; // plugin names to their instance mapping\n  private inputVideo?: HTMLVideoElement;\n  private inputCanvas?: CanvasElement;\n  private outputCanvas?: CanvasElement;\n  private outputTrack?: MediaStreamTrack;\n  private analytics: VideoPluginsAnalytics;\n  private pluginAddInProgress = false;\n  private pluginNumFramesToSkip: Record<string, number>;\n  private pluginNumFramesSkipped: Record<string, number>;\n  private canvases: Array<CanvasElement>; //array of canvases to store intermediate result\n\n  constructor(track: HMSLocalVideoTrack, eventBus: EventBus) {\n    this.hmsTrack = track;\n    this.pluginsMap = new Map();\n    this.pluginNumFramesToSkip = {};\n    this.pluginNumFramesSkipped = {};\n    this.analytics = new VideoPluginsAnalytics(eventBus);\n    this.canvases = new Array<CanvasElement>();\n  }\n\n  getPlugins(): string[] {\n    return Array.from(this.pluginsMap.keys());\n  }\n\n  /**\n   * @param plugin\n   * @param pluginFrameRate\n   */\n  async addPlugin(plugin: HMSVideoPlugin, pluginFrameRate?: number) {\n    if (this.pluginAddInProgress) {\n      const name = plugin.getName?.();\n      if (!name || name === '') {\n        HMSLogger.w('no name provided by the plugin');\n        return;\n      }\n\n      const err = ErrorFactory.MediaPluginErrors.AddAlreadyInProgress(\n        HMSAction.VIDEO_PLUGINS,\n        'Add Plugin is already in Progress',\n      );\n      this.analytics.failure(name, err);\n\n      HMSLogger.w(\"can't add another plugin when previous add is in progress\");\n      throw err;\n    }\n\n    this.pluginAddInProgress = true;\n\n    try {\n      await this.addPluginInternal(plugin, pluginFrameRate);\n    } finally {\n      this.pluginAddInProgress = false;\n    }\n  }\n\n  private async addPluginInternal(plugin: HMSVideoPlugin, pluginFrameRate?: number) {\n    const name = plugin.getName?.();\n    if (!name || name === '') {\n      HMSLogger.w('no name provided by the plugin');\n      return;\n    }\n    if (this.pluginsMap.has(name)) {\n      HMSLogger.w(this.TAG, `plugin - ${plugin.getName()} already added.`);\n      return;\n    }\n    //TODO: assuming this inputFrameRate from getMediaTrackSettings will not change once set\n    //TODO: even if it changes will not have the info/params to know the change\n    const inputFrameRate = this.hmsTrack.getMediaTrackSettings().frameRate || DEFAULT_FRAME_RATE;\n\n    let numFramesToSkip = 0;\n    if (pluginFrameRate && pluginFrameRate > 0) {\n      HMSLogger.i(this.TAG, `adding plugin ${plugin.getName()} with framerate ${pluginFrameRate}`);\n      if (pluginFrameRate < inputFrameRate) {\n        numFramesToSkip = Math.ceil(inputFrameRate / pluginFrameRate) - 1;\n      }\n      this.analytics.added(name, inputFrameRate, pluginFrameRate);\n    } else {\n      HMSLogger.i(this.TAG, `adding plugin ${plugin.getName()}`);\n      this.analytics.added(name, inputFrameRate);\n    }\n\n    HMSLogger.i(this.TAG, 'numFrames to skip processing', numFramesToSkip);\n    this.pluginNumFramesToSkip[name] = numFramesToSkip;\n    this.pluginNumFramesSkipped[name] = numFramesToSkip;\n\n    this.validateAndThrow(name, plugin);\n\n    try {\n      await this.analytics.initWithTime(name, async () => await plugin.init());\n      this.pluginsMap.set(name, plugin);\n      // add new canvases according to new added plugins\n      if (this.pluginsMap.size + 1 > this.canvases.length) {\n        for (let i = this.canvases.length; i <= this.pluginsMap.size; i++) {\n          this.canvases[i] = document.createElement('canvas') as CanvasElement;\n        }\n      }\n      await this.startPluginsLoop(plugin.getContextType?.());\n    } catch (err) {\n      HMSLogger.e(this.TAG, 'failed to add plugin', err);\n      await this.removePlugin(plugin);\n      throw err;\n    }\n  }\n\n  validatePlugin(plugin: HMSVideoPlugin) {\n    return plugin.checkSupport();\n  }\n\n  validateAndThrow(name: string, plugin: HMSVideoPlugin) {\n    const result = this.validatePlugin(plugin);\n    if (result.isSupported) {\n      HMSLogger.i(this.TAG, `plugin is supported,- ${plugin.getName()}`);\n    } else {\n      let error;\n      switch (result.errType) {\n        case HMSPluginUnsupportedTypes.PLATFORM_NOT_SUPPORTED:\n          error = ErrorFactory.MediaPluginErrors.PlatformNotSupported(\n            HMSAction.VIDEO_PLUGINS,\n            'platform not supported, see docs',\n          );\n          this.analytics.failure(name, error);\n          throw error;\n        case HMSPluginUnsupportedTypes.DEVICE_NOT_SUPPORTED:\n          error = ErrorFactory.MediaPluginErrors.DeviceNotSupported(\n            HMSAction.VIDEO_PLUGINS,\n            'video device not supported, see docs',\n          );\n          this.analytics.failure(name, error);\n          throw error;\n      }\n    }\n  }\n\n  async removePlugin(plugin: HMSVideoPlugin) {\n    const name = plugin.getName();\n    if (!this.pluginsMap.get(name)) {\n      HMSLogger.w(this.TAG, `plugin - ${name} not found to remove.`);\n      return;\n    }\n    HMSLogger.i(this.TAG, `removing plugin ${name}`);\n    this.removePluginEntry(name);\n    if (this.pluginsMap.size === 0) {\n      HMSLogger.i(this.TAG, `No plugins left, stopping plugins loop`);\n      await this.stopPluginsLoop();\n    }\n    plugin.stop();\n    this.analytics.removed(name);\n  }\n\n  removePluginEntry(name: string) {\n    this.pluginsMap.delete(name);\n    if (this.pluginNumFramesToSkip[name]) {\n      delete this.pluginNumFramesToSkip[name];\n    }\n    if (this.pluginNumFramesSkipped[name]) {\n      delete this.pluginNumFramesSkipped[name];\n    }\n  }\n\n  /**\n   * when video is unmuted it takes some time for all the plugins to be re run and an output stream to be\n   * produced. It can await on this function to confirm and tell the new unmuted state.\n   * If this is not awaited on video will freeze with a frame from past run.\n   */\n  async waitForRestart() {\n    if (!this.pluginsLoopRunning || this.pluginsLoopState === 'running') {\n      return;\n    }\n    while (this.pluginsLoopState === 'paused') {\n      await workerSleep(100);\n    }\n  }\n\n  /**\n   * remove every plugin one by one\n   */\n  async cleanup() {\n    for (const plugin of this.pluginsMap.values()) {\n      await this.removePlugin(plugin);\n    }\n    // memory cleanup\n    this.outputTrack?.stop();\n  }\n\n  private initElementsAndStream(contextType?: HMSVideoPluginCanvasContextType) {\n    if (!this.inputCanvas) {\n      this.inputCanvas = document.createElement('canvas') as CanvasElement;\n    }\n    this.outputCanvas = document.createElement('canvas') as CanvasElement;\n    if (!this.inputVideo) {\n      this.inputVideo = document.createElement('video');\n    }\n    // FF issue https://bugzilla.mozilla.org/show_bug.cgi?id=1388974\n    this.inputCanvas.getContext('2d');\n    this.outputCanvas.getContext(contextType || HMSVideoPluginCanvasContextType['2D']);\n    // capture stream automatically uses the framerate at which the output canvas is changing\n    const outputStream = this.outputCanvas.captureStream();\n    this.outputTrack = outputStream.getVideoTracks()[0];\n  }\n\n  private async startPluginsLoop(contextType?: HMSVideoPluginCanvasContextType) {\n    if (this.pluginsLoopRunning) {\n      return;\n    }\n    this.initElementsAndStream(contextType);\n    this.pluginsLoopRunning = true;\n    try {\n      await this.hmsTrack.setProcessedTrack(this.outputTrack);\n    } catch (err) {\n      this.pluginsLoopRunning = false;\n      HMSLogger.e(this.TAG, 'error in setting processed track', err);\n      throw err;\n    }\n    // can't await on pluginsLoop as it'll run for a long long time\n    this.pluginsLoop().then(() => {\n      HMSLogger.d(this.TAG, 'processLoop stopped');\n    });\n  }\n\n  private async stopPluginsLoop() {\n    this.pluginsLoopRunning = false;\n    await this.hmsTrack.setProcessedTrack(undefined);\n    this.resetCanvases();\n    this.outputTrack?.stop();\n    if (this.inputVideo) {\n      this.inputVideo.srcObject = null;\n      this.inputVideo = undefined;\n    }\n  }\n\n  private async pluginsLoop() {\n    while (this.pluginsLoopRunning) {\n      const inputFrameRate = this.hmsTrack.getMediaTrackSettings().frameRate || DEFAULT_FRAME_RATE;\n      const sleepTimeMs = Math.floor(1000 / inputFrameRate);\n      if (!this.hmsTrack.enabled || this.hmsTrack.nativeTrack.readyState === 'ended') {\n        if (this.pluginsLoopState === 'running') {\n          // mute just happened, reset canvases to black so even if it is sent to remote, it\n          // is a black screen instead of a stucked frame from previous run\n          this.resetCanvases();\n        }\n        this.pluginsLoopState = 'paused';\n        await workerSleep(sleepTimeMs);\n        continue;\n      }\n      let processingTime = 0;\n      try {\n        await this.analytics.preProcessWithTime(async () => await this.doPreProcessing());\n        const start = Date.now();\n        await this.processFramesThroughPlugins();\n        processingTime = Math.floor(Date.now() - start);\n        if (processingTime > sleepTimeMs) {\n          processingTime = sleepTimeMs;\n        }\n      } catch (err) {\n        // TODO: handle failures properly, detect which plugin failed, stop it and notify back to the UI\n        HMSLogger.e(this.TAG, 'error in plugins loop', err);\n      }\n      this.pluginsLoopState = 'running';\n      // take into account processing time to decide time to wait for the next loop\n      await workerSleep(sleepTimeMs - processingTime);\n    }\n  }\n\n  private async doPreProcessing() {\n    await this.addTrackToVideo(); // ensure current native track is playing in video\n    await this.updateInputCanvas(); // put the latest video frame on input canvas\n  }\n\n  /**\n   * pass the input canvas through all plugins in a loop\n   * @private\n   */\n  private async processFramesThroughPlugins() {\n    this.canvases[0] = this.inputCanvas!;\n    let i = 0;\n    for (const plugin of this.pluginsMap.values()) {\n      const name = plugin.getName();\n      if (!plugin) {\n        continue;\n      }\n      try {\n        const skipProcessing = this.checkIfSkipRequired(name);\n\n        if (plugin.getPluginType() === HMSVideoPluginType.TRANSFORM) {\n          const process = async (input: CanvasElement, output: CanvasElement) => {\n            try {\n              await plugin.processVideoFrame(input, output, skipProcessing);\n            } catch (err) {\n              HMSLogger.e(this.TAG, `error in processing plugin ${name}`, err);\n            }\n          };\n          if (!skipProcessing) {\n            const currentCanvas = this.canvases[i];\n            const nextCanvas = this.canvases[i + 1];\n            if (i === this.pluginsMap.size - 1) {\n              await this.analytics.processWithTime(name, async () => process(currentCanvas, this.outputCanvas!));\n            } else {\n              await this.analytics.processWithTime(name, async () => process(currentCanvas, nextCanvas));\n            }\n          } else {\n            if (i === this.pluginsMap.size - 1) {\n              await process(this.canvases[i], this.outputCanvas!);\n            } else {\n              await process(this.canvases[i], this.canvases[i + 1]);\n            }\n          }\n        } else if (plugin.getPluginType() === HMSVideoPluginType.ANALYZE && !skipProcessing) {\n          // there is no need to await for this case\n          await this.analytics.processWithTime(name, async () => await plugin.processVideoFrame(this.inputCanvas!));\n        }\n      } catch (err) {\n        //TODO error happened on processing of plugin notify UI\n        HMSLogger.e(this.TAG, `error in processing plugin ${name}`, err);\n        //remove plugin from loop and stop analytics for it\n        await this.removePlugin(plugin);\n      }\n      i++;\n    }\n  }\n\n  /**\n   * add the current native track to the inputVideoElement if it's not already added.\n   * @private\n   */\n  private async addTrackToVideo() {\n    if (!this.inputVideo) {\n      return;\n    }\n    const srcObject = this.inputVideo.srcObject;\n    if (srcObject !== null && srcObject instanceof MediaStream) {\n      const existingTrackID = srcObject.getVideoTracks()[0]?.id;\n      if (existingTrackID === this.hmsTrack.nativeTrack.id) {\n        // it's already attached\n        return;\n      }\n    }\n    this.inputVideo.pause();\n    this.inputVideo.srcObject = new MediaStream([this.hmsTrack.nativeTrack]);\n    this.inputVideo.muted = true;\n    this.inputVideo.playsInline = true;\n    await this.inputVideo.play();\n  }\n\n  /**\n   * get the new video frame from input video element and put it on canvas\n   * @private\n   */\n  private async updateInputCanvas() {\n    if (!this.inputCanvas || !this.inputVideo) {\n      return;\n    }\n    const { width = DEFAULT_WIDTH, height = DEFAULT_HEIGHT } = this.hmsTrack.getMediaTrackSettings();\n    // TODO: should we reduce height/width to optimize?\n    if (this.inputCanvas.height !== height) {\n      this.inputCanvas.height = height;\n    }\n    if (this.inputCanvas.width !== width) {\n      this.inputCanvas.width = width;\n    }\n    const ctx = this.inputCanvas.getContext('2d');\n    ctx!.drawImage(this.inputVideo, 0, 0, width, height);\n  }\n\n  private resetCanvases() {\n    if (!this.outputCanvas || !this.inputCanvas) {\n      return;\n    }\n    const inputCtx = this.inputCanvas.getContext('2d');\n    if (inputCtx) {\n      inputCtx.fillStyle = `rgb(0, 0, 0)`;\n      inputCtx.fillRect(0, 0, this.outputCanvas.width, this.outputCanvas.height);\n    }\n    this.canvases = [];\n  }\n\n  /**\n    N = ceil(inputFrameRate/pluginFrameRate) - 1\n    N = this.pluginNumFramesToSkip[name] = frames to skip for every processed frame\n    all the frames we are skipping are using the previous frame output\n   **/\n  private checkIfSkipRequired(name: string) {\n    let skip = false;\n\n    if (this.pluginNumFramesSkipped[name] < this.pluginNumFramesToSkip[name]) {\n      this.pluginNumFramesSkipped[name]++;\n      skip = true;\n    } else {\n      skip = false;\n      this.pluginNumFramesSkipped[name] = 0;\n    }\n\n    return skip;\n  }\n}\n","import { HMSMediaStreamPlugin } from './HMSMediaStreamPlugin';\nimport HMSLogger from '../../utils/logger';\n\nexport class HMSMediaStreamPluginsManager {\n  private plugins = new Set<HMSMediaStreamPlugin>();\n\n  addPlugins(plugins: HMSMediaStreamPlugin[]): void {\n    plugins.forEach(plugin => this.plugins.add(plugin));\n  }\n\n  removePlugins(plugins: HMSMediaStreamPlugin[]) {\n    plugins.forEach(plugin => {\n      this.plugins.delete(plugin);\n    });\n  }\n\n  applyPlugins(inputStream: MediaStream): MediaStream {\n    let processedStream = inputStream;\n    for (const plugin of this.plugins) {\n      try {\n        processedStream = plugin.apply(processedStream);\n      } catch (e) {\n        HMSLogger.e('Could not apply plugin', e, plugin);\n      }\n    }\n    return processedStream;\n  }\n\n  getPlugins(): string[] {\n    return Array.from(this.plugins).map(plugin => plugin.getName());\n  }\n}\n","import { HMSVideoTrack } from './HMSVideoTrack';\nimport { VideoElementManager } from './VideoElementManager';\nimport AnalyticsEventFactory from '../../analytics/AnalyticsEventFactory';\nimport { DeviceStorageManager } from '../../device-manager/DeviceStorage';\nimport { ErrorFactory } from '../../error/ErrorFactory';\nimport { HMSAction } from '../../error/HMSAction';\nimport { EventBus } from '../../events/EventBus';\nimport {\n  HMSFacingMode,\n  HMSSimulcastLayerDefinition,\n  HMSVideoTrackSettings as IHMSVideoTrackSettings,\n  ScreenCaptureHandle,\n} from '../../interfaces';\nimport { HMSPluginSupportResult, HMSVideoPlugin } from '../../plugins';\nimport { HMSMediaStreamPlugin, HMSVideoPluginsManager } from '../../plugins/video';\nimport { HMSMediaStreamPluginsManager } from '../../plugins/video/HMSMediaStreamPluginsManager';\nimport { LocalTrackManager } from '../../sdk/LocalTrackManager';\nimport HMSLogger from '../../utils/logger';\nimport { getVideoTrack, isEmptyTrack } from '../../utils/track';\nimport { HMSVideoTrackSettings, HMSVideoTrackSettingsBuilder } from '../settings';\nimport { HMSLocalStream } from '../streams';\n\nfunction generateHasPropertyChanged(newSettings: Partial<HMSVideoTrackSettings>, oldSettings: HMSVideoTrackSettings) {\n  return function hasChanged(\n    prop: 'codec' | 'width' | 'height' | 'maxFramerate' | 'maxBitrate' | 'deviceId' | 'advanced' | 'facingMode',\n  ) {\n    return prop in newSettings && newSettings[prop] !== oldSettings[prop];\n  };\n}\n\nexport class HMSLocalVideoTrack extends HMSVideoTrack {\n  settings: HMSVideoTrackSettings;\n  private pluginsManager: HMSVideoPluginsManager;\n  private mediaStreamPluginsManager: HMSMediaStreamPluginsManager;\n  private processedTrack?: MediaStreamTrack;\n  private _layerDefinitions: HMSSimulcastLayerDefinition[] = [];\n  private TAG = '[HMSLocalVideoTrack]';\n\n  /**\n   * true if it's screenshare and current tab is what is being shared. Browser dependent, Chromium only\n   * at the point of writing this comment.\n   */\n  isCurrentTab = false;\n\n  /**\n   * @internal\n   * This is required for handling remote mute/unmute as the published track will not necessarily be same as\n   * the first track id or current native track's id.\n   * It won't be same as first track id if the native track was changed after preview started but before join happened,\n   * with device change, or mute/unmute.\n   * It won't be same as native track id, as the native track can change post join(and publish), when the nativetrack\n   * changes, replacetrack is used which doesn't involve republishing which means from server's point of view, the track id\n   * is same as what was initially published.\n   * This will only be available if the track was actually published and won't be set for preview tracks.\n   */\n  publishedTrackId?: string;\n\n  /**\n   * will be false for preview tracks\n   */\n  isPublished = false;\n\n  constructor(\n    stream: HMSLocalStream,\n    track: MediaStreamTrack,\n    source: string,\n    private eventBus: EventBus,\n    settings: HMSVideoTrackSettings = new HMSVideoTrackSettingsBuilder().build(),\n  ) {\n    super(stream, track, source);\n    stream.tracks.push(this);\n    this.setVideoHandler(new VideoElementManager(this));\n    this.settings = settings;\n    // Replace the 'default' or invalid deviceId with the actual deviceId\n    // This is to maintain consistency with selected devices as in some cases there will be no 'default' device\n    if (settings.deviceId !== track.getSettings().deviceId && track.enabled) {\n      this.settings = this.buildNewSettings({ deviceId: track.getSettings().deviceId });\n    }\n    this.pluginsManager = new HMSVideoPluginsManager(this, eventBus);\n    this.mediaStreamPluginsManager = new HMSMediaStreamPluginsManager();\n    this.setFirstTrackId(this.trackId);\n  }\n\n  /** @internal */\n  setSimulcastDefinitons(definitions: HMSSimulcastLayerDefinition[]) {\n    this._layerDefinitions = definitions;\n  }\n\n  /**\n   * Method to get available simulcast definitions for the track\n   * @returns {HMSSimulcastLayerDefinition[]}\n   */\n  getSimulcastDefinitions(): HMSSimulcastLayerDefinition[] {\n    return this._layerDefinitions;\n  }\n\n  /**\n   * use this function to set the enabled state of a track. If true the track will be unmuted and muted otherwise.\n   * @param value\n   */\n  async setEnabled(value: boolean): Promise<void> {\n    if (value === this.enabled) {\n      return;\n    }\n    if (this.source === 'regular') {\n      let track: MediaStreamTrack;\n      if (value) {\n        track = await this.replaceTrackWith(this.settings);\n      } else {\n        track = await this.replaceTrackWithBlank();\n      }\n      await this.replaceSender(track, value);\n      this.nativeTrack?.stop();\n      this.nativeTrack = track;\n      await super.setEnabled(value);\n      if (value) {\n        await this.pluginsManager.waitForRestart();\n        await this.processPlugins();\n        this.settings = this.buildNewSettings({ deviceId: track.getSettings().deviceId });\n      }\n      this.videoHandler.updateSinks();\n    }\n    this.eventBus.localVideoEnabled.publish({ enabled: value, track: this });\n  }\n\n  private async processPlugins() {\n    try {\n      const plugins = this.mediaStreamPluginsManager.getPlugins();\n      if (plugins.length > 0) {\n        const processedStream = this.mediaStreamPluginsManager.applyPlugins(new MediaStream([this.nativeTrack]));\n        const newTrack = processedStream.getVideoTracks()[0];\n        await this.setProcessedTrack(newTrack);\n      } else {\n        await this.setProcessedTrack();\n      }\n    } catch (e) {\n      console.error('error in processing plugin(s)', e);\n    }\n  }\n\n  async addStreamPlugins(plugins: HMSMediaStreamPlugin[]) {\n    if (this.pluginsManager.getPlugins().length > 0) {\n      throw Error('Plugins of type HMSMediaStreamPlugin and HMSVideoPlugin cannot be used together');\n    }\n    this.mediaStreamPluginsManager.addPlugins(plugins);\n    await this.processPlugins();\n  }\n\n  async removeStreamPlugins(plugins: HMSMediaStreamPlugin[]) {\n    this.mediaStreamPluginsManager.removePlugins(plugins);\n    await this.processPlugins();\n  }\n\n  /**\n   * verify if the track id being passed is of this track for correlating server messages like degradation\n   */\n  isPublishedTrackId(trackId: string) {\n    return this.publishedTrackId === trackId;\n  }\n\n  /**\n   * @see HMSVideoTrack#addSink()\n   */\n  addSink(videoElement: HTMLVideoElement) {\n    this.addSinkInternal(videoElement, this.processedTrack || this.nativeTrack);\n  }\n\n  /**\n   * This function can be used to set media track settings. Frequent options -\n   * deviceID: can be used to change to different input source\n   * width, height - can be used to change capture dimensions\n   * maxFramerate - can be used to control the capture framerate\n   * @param settings\n   */\n  async setSettings(settings: Partial<IHMSVideoTrackSettings>, internal = false) {\n    const newSettings = this.buildNewSettings(settings);\n    await this.handleDeviceChange(newSettings, internal);\n    if (!this.enabled || isEmptyTrack(this.nativeTrack)) {\n      // if track is muted, we just cache the settings for when it is unmuted\n      this.settings = newSettings;\n      return;\n    }\n    await this.handleSettingsChange(newSettings);\n    this.settings = newSettings;\n  }\n\n  /**\n   * @see HMSVideoPlugin\n   */\n  getPlugins(): string[] {\n    return this.mediaStreamPluginsManager.getPlugins().length > 0\n      ? this.mediaStreamPluginsManager.getPlugins()\n      : this.pluginsManager.getPlugins();\n  }\n\n  /**\n   * @see HMSVideoPlugin\n   */\n  async addPlugin(plugin: HMSVideoPlugin, pluginFrameRate?: number): Promise<void> {\n    if (this.mediaStreamPluginsManager.getPlugins().length > 0) {\n      throw Error('Plugins of type HMSVideoPlugin and HMSMediaStreamPlugin cannot be used together');\n    }\n    return this.pluginsManager.addPlugin(plugin, pluginFrameRate);\n  }\n\n  /**\n   * @see HMSVideoPlugin\n   */\n  async removePlugin(plugin: HMSVideoPlugin): Promise<void> {\n    return this.pluginsManager.removePlugin(plugin);\n  }\n\n  /**\n   * @see HMSVideoPlugin\n   */\n  validatePlugin(plugin: HMSVideoPlugin): HMSPluginSupportResult {\n    return this.pluginsManager.validatePlugin(plugin);\n  }\n\n  /**\n   * @internal\n   */\n  async cleanup() {\n    super.cleanup();\n    this.transceiver = undefined;\n    await this.pluginsManager.cleanup();\n    this.processedTrack?.stop();\n    this.isPublished = false;\n  }\n\n  /**\n   * only for screenshare track to crop to a cropTarget\n   * @internal\n   */\n  async cropTo(cropTarget?: object) {\n    if (!cropTarget) {\n      return;\n    }\n    if (this.source !== 'screen') {\n      return;\n    }\n    try {\n      // @ts-ignore\n      if (this.nativeTrack.cropTo) {\n        // @ts-ignore\n        await this.nativeTrack.cropTo(cropTarget);\n      }\n    } catch (err) {\n      HMSLogger.e(this.TAG, 'failed to crop screenshare capture - ', err);\n      throw ErrorFactory.TracksErrors.GenericTrack(HMSAction.TRACK, 'failed to crop screenshare capture');\n    }\n  }\n\n  /**\n   * only for screenshare track to get the captureHandle\n   * TODO: add an API for capturehandlechange event\n   * @internal\n   */\n  getCaptureHandle(): ScreenCaptureHandle | undefined {\n    // @ts-ignore\n    if (this.nativeTrack.getCaptureHandle) {\n      // @ts-ignore\n      return this.nativeTrack.getCaptureHandle();\n    }\n    return undefined;\n  }\n\n  /**\n   * once the plugin manager has done its processing it can set or remove processed track via this method\n   * note that replacing sender track only makes sense if the native track is enabled. if it's disabled there is\n   * no point in replacing it. We'll update the processed track variable though so next time unmute happens\n   * it's set properly.\n   * @internal\n   */\n  async setProcessedTrack(processedTrack?: MediaStreamTrack) {\n    // required replacement will happen when video is unmuted\n    if (!this.nativeTrack.enabled) {\n      this.processedTrack = processedTrack;\n      return;\n    }\n    await this.removeOrReplaceProcessedTrack(processedTrack);\n    this.videoHandler.updateSinks();\n  }\n\n  /**\n   * @internal\n   * sent track id will be different in case there was some processing done using plugins.\n   * replace track is used to, start sending data from a new track without un publishing the prior one. There\n   * are thus two track ids - the one which was initially published and should be unpublished when required.\n   * The one whose data is currently being sent, which will be used when removing from connection senders.\n   */\n  getTrackIDBeingSent() {\n    return this.getTrackBeingSent().id;\n  }\n\n  getTrackBeingSent() {\n    return this.enabled ? this.processedTrack || this.nativeTrack : this.nativeTrack;\n  }\n\n  /**\n   * will change the facingMode to environment if current facing mode is user or vice versa.\n   * will be useful when on mobile web to toggle between front and back camera's\n   */\n  async switchCamera() {\n    const currentFacingMode = this.getMediaTrackSettings().facingMode;\n    if (!currentFacingMode || this.source !== 'regular') {\n      HMSLogger.d(this.TAG, 'facingMode not supported');\n      return;\n    }\n    const facingMode = currentFacingMode === HMSFacingMode.ENVIRONMENT ? HMSFacingMode.USER : HMSFacingMode.ENVIRONMENT;\n    this.nativeTrack?.stop();\n    const track = await this.replaceTrackWith(this.buildNewSettings({ facingMode: facingMode, deviceId: undefined }));\n    await this.replaceSender(track, this.enabled);\n    this.nativeTrack = track;\n    this.videoHandler.updateSinks();\n    this.settings = this.buildNewSettings({ deviceId: this.nativeTrack.getSettings().deviceId, facingMode });\n    DeviceStorageManager.updateSelection('videoInput', {\n      deviceId: this.settings.deviceId,\n      groupId: this.nativeTrack.getSettings().groupId,\n    });\n  }\n\n  /**\n   * called when the video is unmuted\n   * @private\n   */\n  private async replaceTrackWith(settings: HMSVideoTrackSettings) {\n    const prevTrack = this.nativeTrack;\n    /**\n     * not stopping previous track results in device in use more frequently, as many devices will not allow even if\n     * you are requesting for a new device.\n     * Note: Do not change the order of this.\n     */\n    prevTrack?.stop();\n    try {\n      const newTrack = await getVideoTrack(settings);\n      HMSLogger.d(this.TAG, 'replaceTrack, Previous track stopped', prevTrack, 'newTrack', newTrack);\n      // Replace deviceId with actual deviceId when it is default\n      if (this.settings.deviceId === 'default') {\n        this.settings = this.buildNewSettings({ deviceId: this.nativeTrack.getSettings().deviceId });\n      }\n      return newTrack;\n    } catch (error) {\n      if (this.isPublished) {\n        this.eventBus.analytics.publish(\n          AnalyticsEventFactory.publish({\n            error: error as Error,\n          }),\n        );\n      }\n      throw error;\n    }\n  }\n\n  /**\n   * called when the video is muted. A blank track is used to replace the original track. This is in order to\n   * turn off the camera light and keep the bytes flowing to avoid av sync, timestamp issues.\n   * @private\n   */\n  private async replaceTrackWithBlank() {\n    const prevTrack = this.nativeTrack;\n    const newTrack = LocalTrackManager.getEmptyVideoTrack(prevTrack);\n    prevTrack?.stop();\n    HMSLogger.d(this.TAG, 'replaceTrackWithBlank, Previous track stopped', prevTrack, 'newTrack', newTrack);\n    return newTrack;\n  }\n\n  private async replaceSender(newTrack: MediaStreamTrack, enabled: boolean) {\n    const localStream = this.stream as HMSLocalStream;\n    if (enabled) {\n      await localStream.replaceSenderTrack(this.nativeTrack, this.processedTrack || newTrack);\n    } else {\n      await localStream.replaceSenderTrack(this.processedTrack || this.nativeTrack, newTrack);\n    }\n    localStream.replaceStreamTrack(this.nativeTrack, newTrack);\n  }\n\n  private buildNewSettings = (settings: Partial<HMSVideoTrackSettings>) => {\n    const { width, height, codec, maxFramerate, maxBitrate, deviceId, advanced, facingMode } = {\n      ...this.settings,\n      ...settings,\n    };\n    const newSettings = new HMSVideoTrackSettings(\n      width,\n      height,\n      codec,\n      maxFramerate,\n      deviceId,\n      advanced,\n      maxBitrate,\n      facingMode,\n    );\n    return newSettings;\n  };\n\n  // eslint-disable-next-line complexity\n  private handleSettingsChange = async (settings: HMSVideoTrackSettings) => {\n    const stream = this.stream as HMSLocalStream;\n    const hasPropertyChanged = generateHasPropertyChanged(settings, this.settings);\n    if (hasPropertyChanged('maxBitrate') && settings.maxBitrate) {\n      await stream.setMaxBitrateAndFramerate(this);\n    }\n\n    if (hasPropertyChanged('width') || hasPropertyChanged('height') || hasPropertyChanged('advanced')) {\n      if (this.source === 'video') {\n        const track = await this.replaceTrackWith(settings);\n        await this.replaceSender(track, this.enabled);\n        this.nativeTrack = track;\n        this.videoHandler.updateSinks();\n      } else {\n        await this.nativeTrack.applyConstraints(settings.toConstraints());\n      }\n    }\n  };\n\n  /**\n   * Replace video track with new track on device change\n   * @param settings - VideoSettings Object constructed with new settings\n   * @param internal - whether the change was because of internal sdk call or external client call\n   */\n  private handleDeviceChange = async (settings: HMSVideoTrackSettings, internal = false) => {\n    const hasPropertyChanged = generateHasPropertyChanged(settings, this.settings);\n\n    if (hasPropertyChanged('deviceId') && this.source === 'regular') {\n      if (this.enabled) {\n        delete settings.facingMode;\n        const track = await this.replaceTrackWith(settings);\n        await this.replaceSender(track, this.enabled);\n        this.nativeTrack = track;\n        this.videoHandler.updateSinks();\n      }\n      if (!internal) {\n        DeviceStorageManager.updateSelection('videoInput', {\n          deviceId: settings.deviceId,\n          groupId: this.nativeTrack.getSettings().groupId,\n        });\n      }\n    }\n  };\n\n  /**\n   * This will either remove or update the processedTrack value on the class instance.\n   * It will also replace sender if the processedTrack is updated\n   * @param {MediaStreamTrack|undefined}processedTrack\n   */\n  private removeOrReplaceProcessedTrack = async (processedTrack?: MediaStreamTrack) => {\n    // if all plugins are removed reset everything back to native track\n    if (!processedTrack) {\n      if (this.processedTrack) {\n        // remove, reset back to the native track\n        await (this.stream as HMSLocalStream).replaceSenderTrack(this.processedTrack, this.nativeTrack);\n      }\n      this.processedTrack = undefined;\n    } else if (processedTrack !== this.processedTrack) {\n      if (this.processedTrack) {\n        // replace previous processed track with new one\n        await (this.stream as HMSLocalStream).replaceSenderTrack(this.processedTrack, processedTrack);\n      } else {\n        // there is no prev processed track, replace native with new one\n        await (this.stream as HMSLocalStream).replaceSenderTrack(this.nativeTrack, processedTrack);\n      }\n      this.processedTrack = processedTrack;\n    }\n  };\n}\n","import { HMSVideoTrack } from './HMSVideoTrack';\nimport { VideoElementManager } from './VideoElementManager';\nimport { VideoTrackLayerUpdate } from '../../connection/channel-messages';\nimport {\n  HMSPreferredSimulcastLayer,\n  HMSSimulcastLayer,\n  HMSSimulcastLayerDefinition,\n} from '../../interfaces/simulcast-layers';\nimport { MAINTAIN_TRACK_HISTORY } from '../../utils/constants';\nimport HMSLogger from '../../utils/logger';\nimport { isEmptyTrack } from '../../utils/track';\nimport { HMSRemoteStream } from '../streams';\n\nexport class HMSRemoteVideoTrack extends HMSVideoTrack {\n  private _degraded = false;\n  private _degradedAt: Date | null = null;\n  private _layerDefinitions: HMSSimulcastLayerDefinition[] = [];\n  private history = new TrackHistory();\n  private preferredLayer: HMSPreferredSimulcastLayer = HMSSimulcastLayer.HIGH;\n  private bizTrackId!: string;\n\n  constructor(stream: HMSRemoteStream, track: MediaStreamTrack, source?: string) {\n    super(stream, track, source);\n    this.setVideoHandler(new VideoElementManager(this));\n  }\n\n  setTrackId(trackId: string) {\n    this.bizTrackId = trackId;\n  }\n\n  get trackId(): string {\n    return this.bizTrackId || super.trackId;\n  }\n\n  public get degraded() {\n    return this._degraded;\n  }\n\n  public get degradedAt() {\n    return this._degradedAt;\n  }\n\n  async setEnabled(value: boolean): Promise<void> {\n    if (value === this.enabled) {\n      return;\n    }\n\n    super.setEnabled(value);\n    this.videoHandler.updateSinks(true);\n  }\n\n  async setPreferredLayer(layer: HMSPreferredSimulcastLayer) {\n    //@ts-ignore\n    if (layer === HMSSimulcastLayer.NONE) {\n      HMSLogger.w(`layer ${HMSSimulcastLayer.NONE} will be ignored`);\n      return;\n    }\n    this.preferredLayer = layer;\n    if (!this.shouldSendVideoLayer(layer, 'preferLayer')) {\n      return;\n    }\n    if (!this.hasSinks()) {\n      HMSLogger.d(\n        `[Remote Track] ${this.logIdentifier}\n        streamId=${this.stream.id} \n        trackId=${this.trackId}\n        saving ${layer}, source=${this.source}\n        Track does not have any sink`,\n      );\n      return;\n    }\n    await this.requestLayer(layer, 'preferLayer');\n    this.pushInHistory(`uiPreferLayer-${layer}`);\n  }\n\n  /**\n   * @deprecated\n   * @returns {HMSSimulcastLayer}\n   */\n  getSimulcastLayer() {\n    return (this.stream as HMSRemoteStream).getSimulcastLayer();\n  }\n\n  getLayer() {\n    return (this.stream as HMSRemoteStream).getVideoLayer();\n  }\n\n  getPreferredLayer() {\n    return this.preferredLayer;\n  }\n\n  replaceTrack(track: HMSRemoteVideoTrack) {\n    this.nativeTrack = track.nativeTrack;\n    if (track.transceiver) {\n      this.transceiver = track.transceiver;\n      // replace dummy streamId with actual streamId retaining all other properties\n      this.stream.updateId(track.stream.id);\n    }\n    this.videoHandler.updateSinks();\n  }\n\n  async addSink(videoElement: HTMLVideoElement, shouldSendVideoLayer = true) {\n    // if the native track is empty track, just request the preferred layer else attach it\n    if (isEmptyTrack(this.nativeTrack)) {\n      await this.requestLayer(this.preferredLayer, 'addSink');\n    } else {\n      super.addSink(videoElement);\n      if (shouldSendVideoLayer) {\n        await this.updateLayer('addSink');\n      }\n    }\n    this.pushInHistory(`uiSetLayer-high`);\n  }\n\n  async removeSink(videoElement: HTMLVideoElement, shouldSendVideoLayer = true) {\n    super.removeSink(videoElement);\n    if (shouldSendVideoLayer) {\n      await this.updateLayer('removeSink');\n    }\n    this._degraded = false;\n    this.pushInHistory('uiSetLayer-none');\n  }\n\n  /**\n   * Method to get available simulcast definitions for the track\n   * @returns {HMSSimulcastLayerDefinition[]}\n   */\n  getSimulcastDefinitions() {\n    // send a clone to store as it will freeze the object from further updates\n    return [...this._layerDefinitions];\n  }\n\n  /** @internal */\n  setSimulcastDefinitons(definitions: HMSSimulcastLayerDefinition[]) {\n    this._layerDefinitions = definitions;\n  }\n\n  /**\n   * @internal\n   * SFU will change track's layer(degrade or restore) and tell the sdk to update\n   * it locally.\n   * @returns {boolean} isDegraded - returns true if degraded\n   * */\n  setLayerFromServer(layerUpdate: VideoTrackLayerUpdate) {\n    this._degraded =\n      this.enabled &&\n      (layerUpdate.publisher_degraded || layerUpdate.subscriber_degraded) &&\n      layerUpdate.current_layer === HMSSimulcastLayer.NONE;\n    this._degradedAt = this._degraded ? new Date() : this._degradedAt;\n    const currentLayer = layerUpdate.current_layer;\n    HMSLogger.d(\n      `[Remote Track] ${this.logIdentifier} \n      streamId=${this.stream.id} \n      trackId=${this.trackId}\n      layer update from sfu\n      currLayer=${layerUpdate.current_layer}\n      preferredLayer=${layerUpdate.expected_layer}\n      sub_degraded=${layerUpdate.subscriber_degraded}\n      pub_degraded=${layerUpdate.publisher_degraded}\n      isDegraded=${this._degraded}`,\n    );\n    // No need to send preferLayer update, as server has done it already\n    (this.stream as HMSRemoteStream).setVideoLayerLocally(currentLayer, this.logIdentifier, 'setLayerFromServer');\n    this.pushInHistory(`sfuLayerUpdate-${currentLayer}`);\n    return this._degraded;\n  }\n\n  private async updateLayer(source: string) {\n    const newLayer = this.degraded || !this.enabled || !this.hasSinks() ? HMSSimulcastLayer.NONE : this.preferredLayer;\n    if (!this.shouldSendVideoLayer(newLayer, source)) {\n      return;\n    }\n    await this.requestLayer(newLayer, source);\n  }\n\n  private pushInHistory(action: string) {\n    if (MAINTAIN_TRACK_HISTORY) {\n      this.history.push({ name: action, layer: this.getLayer(), degraded: this.degraded });\n    }\n  }\n\n  private async requestLayer(layer: HMSSimulcastLayer, source: string) {\n    try {\n      const response = await (this.stream as HMSRemoteStream).setVideoLayer(\n        layer,\n        this.trackId,\n        this.logIdentifier,\n        source,\n      );\n      HMSLogger.d(\n        `[Remote Track] ${this.logIdentifier} \n      streamId=${this.stream.id}\n      trackId=${this.trackId}\n      Requested layer ${layer}, source=${source}`,\n      );\n      return response;\n    } catch (error) {\n      HMSLogger.d(\n        `[Remote Track] ${this.logIdentifier} \n      streamId=${this.stream.id}\n      trackId=${this.trackId}\n      Failed to set layer ${layer}, source=${source}\n      error=${(error as Error).message}`,\n      );\n      throw error;\n    }\n  }\n\n  /**\n   * given the new layer, figure out if the update should be sent to server or not.\n   * It won't be sent if the track is already on the targetLayer. If the track is\n   * degraded though and the target layer is none, update will be sent.\n   * If there are tracks degraded on a page and user paginates away to other page,\n   * it's necessary to send the layer none message to SFU so it knows that the app\n   * is no longer interested in the track and doesn't recover degraded tracks on non\n   * visible pages.\n   *\n   * TODO: if track is degraded, send the update if target layer is lower than current layer\n   * @private\n   */\n  private shouldSendVideoLayer(targetLayer: HMSSimulcastLayer, source: string) {\n    const currLayer = this.getLayer();\n    if (this.degraded && targetLayer === HMSSimulcastLayer.NONE) {\n      return true;\n    }\n    if (currLayer === targetLayer) {\n      HMSLogger.d(\n        `[Remote Track] ${this.logIdentifier}`,\n        `Not sending update, already on layer ${targetLayer}, source=${source}`,\n      );\n      return false;\n    }\n    return true;\n  }\n}\n\n/**\n * to store history of everything that happened to a remote track which decides\n * it's current layer and degraded status.\n */\nclass TrackHistory {\n  history: Record<string, any>[] = [];\n\n  push(action: Record<string, any>) {\n    action.time = new Date().toISOString().split('T')[1];\n    this.history.push(action);\n  }\n}\n","import { HMSMediaStream } from './HMSMediaStream';\nimport HMSPublishConnection from '../../connection/publish/publishConnection';\nimport { SimulcastLayer } from '../../interfaces';\nimport { stringifyMediaStreamTrack } from '../../utils/json';\nimport HMSLogger from '../../utils/logger';\nimport { isNode } from '../../utils/support';\nimport { HMSLocalTrack, HMSLocalVideoTrack } from '../tracks';\n\nexport class HMSLocalStream extends HMSMediaStream {\n  /** Connection set when publish is called for the first track */\n  private readonly TAG = '[HMSLocalStream]';\n  private connection: HMSPublishConnection | null = null;\n\n  setConnection(connection: HMSPublishConnection) {\n    this.connection = connection;\n  }\n\n  addTransceiver(track: HMSLocalTrack, simulcastLayers: SimulcastLayer[]) {\n    const transceiver = this.connection!.addTransceiver(track.getTrackBeingSent(), {\n      streams: [this.nativeStream],\n      direction: 'sendonly',\n      sendEncodings: this.getTrackEncodings(track, simulcastLayers),\n    });\n    this.setPreferredCodec(transceiver, track.nativeTrack.kind);\n    track.transceiver = transceiver;\n    return transceiver;\n  }\n\n  async setMaxBitrateAndFramerate(track: HMSLocalTrack): Promise<void> {\n    await this.connection?.setMaxBitrateAndFramerate(track);\n  }\n\n  // @ts-ignore\n  setPreferredCodec(_transceiver: RTCRtpTransceiver, _kind: string) {\n    // TODO: Some browsers don't support setCodecPreferences, resort to SDPMunging?\n  }\n\n  replaceStreamTrack(track: MediaStreamTrack, withTrack: MediaStreamTrack) {\n    this.nativeStream.addTrack(withTrack);\n    this.nativeStream.removeTrack(track);\n    HMSLogger.d(\n      this.TAG,\n      'Native stream tracks after replace',\n      this.nativeStream.getAudioTracks().map(stringifyMediaStreamTrack),\n      `prev Track - ${stringifyMediaStreamTrack(track)}`,\n      `new Track - ${stringifyMediaStreamTrack(withTrack)}`,\n    );\n  }\n\n  /**\n   * On mute and unmute of video tracks as well as for changing cameras, we replace the track with new track,\n   * so as to avoid a renegotiation with the backend and reflect changes faster.\n   * In case of video plugins we need to replace the track sent to remote without stopping the original one. As\n   * if the original is stopped, plugin would stop getting input frames to process. So only the track in the\n   * sender needs to be replaced.\n   */\n  async replaceSenderTrack(track: MediaStreamTrack, withTrack: MediaStreamTrack) {\n    if (!this.connection || this.connection.connectionState === 'closed') {\n      HMSLogger.d(this.TAG, `publish connection is not initialised or closed`);\n      return;\n    }\n    const sender = this.connection.getSenders().find(sender => sender.track && sender.track.id === track.id);\n\n    if (sender === undefined) {\n      HMSLogger.w(this.TAG, `No sender found for trackId=${track.id}`);\n      return;\n    }\n    await sender.replaceTrack(withTrack);\n  }\n\n  removeSender(track: HMSLocalTrack) {\n    if (!this.connection || this.connection.connectionState === 'closed') {\n      HMSLogger.d(this.TAG, `publish connection is not initialised or closed`);\n      return;\n    }\n    const sender = track.transceiver?.sender;\n    if (!sender) {\n      HMSLogger.w(this.TAG, `No sender found for trackId=${track.trackId}`);\n      return;\n    }\n    this.connection?.removeTrack(sender);\n    const toRemoveLocalTrackIdx = this.tracks.indexOf(track);\n    if (toRemoveLocalTrackIdx !== -1) {\n      this.tracks.splice(toRemoveLocalTrackIdx, 1);\n    } else {\n      HMSLogger.w(this.TAG, `Cannot find ${track.trackId} in locally stored tracks`);\n    }\n  }\n\n  private getTrackEncodings(track: HMSLocalTrack, simulcastLayers: SimulcastLayer[]) {\n    const trackEncodings: RTCRtpEncodingParameters[] = [];\n    if (track instanceof HMSLocalVideoTrack) {\n      if (simulcastLayers.length > 0) {\n        HMSLogger.d(this.TAG, 'Simulcast enabled with layers', simulcastLayers);\n        trackEncodings.push(...simulcastLayers);\n      } else {\n        const encodings: RTCRtpEncodingParameters = { active: this.nativeStream.active };\n        if (track.settings.maxBitrate && !isNode) {\n          encodings.maxBitrate = track.settings.maxBitrate;\n        }\n        trackEncodings.push(encodings);\n      }\n    }\n    return trackEncodings;\n  }\n}\n","import { HMSMediaStream } from './HMSMediaStream';\nimport HMSSubscribeConnection from '../../connection/subscribe/subscribeConnection';\nimport { HMSSimulcastLayer } from '../../interfaces';\nimport HMSLogger from '../../utils/logger';\n\n/** @internal */\nexport class HMSRemoteStream extends HMSMediaStream {\n  private readonly connection: HMSSubscribeConnection;\n  private audio = true;\n  private video = HMSSimulcastLayer.NONE;\n\n  constructor(nativeStream: MediaStream, connection: HMSSubscribeConnection) {\n    super(nativeStream);\n    this.connection = connection;\n  }\n\n  async setAudio(enabled: boolean, trackId: string, identifier?: string) {\n    if (this.audio === enabled) {\n      return;\n    }\n\n    this.audio = enabled;\n    HMSLogger.d(\n      `[Remote stream] ${identifier || ''} \n    streamId=${this.id}\n    trackId=${trackId}\n    subscribing audio - ${this.audio}`,\n    );\n    await this.connection.sendOverApiDataChannelWithResponse({\n      params: {\n        subscribed: this.audio,\n        track_id: trackId,\n      },\n      method: 'prefer-audio-track-state',\n    });\n  }\n\n  /**\n   * Sets the video layer after receiving new state from SFU. This is used when server side subscribe\n   * degradation is ON.\n   * @param layer is simulcast layer to be set\n   * @param identifier is stream identifier to be printed in logs\n   */\n  setVideoLayerLocally(layer: HMSSimulcastLayer, identifier: string, source: string) {\n    this.video = layer;\n    HMSLogger.d(`[Remote stream] ${identifier}\n    streamId=${this.id}\n    source: ${source}\n    Setting layer field to=${layer}`);\n  }\n\n  /**\n   * Sets the video layer and updates the track state to SFU via api datachannel. This is used when client\n   * side subscribe degradation is ON or client unsubscribes the current track.\n   * @param layer is simulcast layer to be set\n   * @param identifier is stream identifier to be printed in logs\n   */\n  setVideoLayer(layer: HMSSimulcastLayer, trackId: string, identifier: string, source: string) {\n    HMSLogger.d(\n      `[Remote stream] ${identifier} \n      streamId=${this.id}\n      trackId=${trackId} \n      source: ${source} request ${layer} layer`,\n    );\n    this.setVideoLayerLocally(layer, identifier, source);\n    return this.connection.sendOverApiDataChannelWithResponse({\n      params: {\n        max_spatial_layer: this.video,\n        track_id: trackId,\n      },\n      method: 'prefer-video-track-state',\n    });\n  }\n\n  /**\n   * @deprecated\n   * @returns {HMSSimulcastLayer}\n   */\n  getSimulcastLayer() {\n    return this.video;\n  }\n\n  getVideoLayer() {\n    return this.video;\n  }\n\n  isAudioSubscribed() {\n    return this.audio;\n  }\n}\n","import { getLocalStream } from './media';\nimport { getAudioTrack, getVideoTrack } from './track';\nimport { HMSAction } from '../error/HMSAction';\nimport { HMSException } from '../error/HMSException';\nimport { HMSAudioTrackSettingsBuilder } from '../media/settings/HMSAudioTrackSettings';\nimport { HMSVideoTrackSettingsBuilder } from '../media/settings/HMSVideoTrackSettings';\n\n// Errors out when there's any device error, returns false when there are no device errors.\nexport async function validateDeviceAV() {\n  const videoTrackSettings = new HMSVideoTrackSettingsBuilder().build();\n  const audioTrackSettings = new HMSAudioTrackSettingsBuilder().build();\n  /**\n   * Check audio failure.\n   * If audio failure - check AV failure.\n   * If AV failure - throw AV failure.\n   * If AV passed - throw audio failure.\n   *\n   * If audio passed - check video failure.\n   * If video failure - throw video failure.\n   * If video passed - no error - return false.\n   */\n  try {\n    const track = await getAudioTrack(audioTrackSettings);\n    track.stop();\n  } catch (audioError) {\n    if (isHMSDeviceError(audioError)) {\n      const stream = await getLocalStream({ audio: false, video: true });\n      stream.getTracks().forEach(track => track.stop());\n      throw audioError;\n    }\n  }\n\n  const track = await getVideoTrack(videoTrackSettings);\n  track.stop();\n  return false;\n}\n\nfunction isHMSDeviceError(error: any) {\n  return error instanceof HMSException && error.action === HMSAction.TRACK;\n}\n","import AnalyticsEventFactory from '../analytics/AnalyticsEventFactory';\nimport { ErrorFactory } from '../error/ErrorFactory';\nimport { HMSAction } from '../error/HMSAction';\nimport { EventBus } from '../events/EventBus';\nimport { RID } from '../interfaces';\nimport {\n  HMSLocalTrackStats,\n  HMSPeerStats,\n  HMSTrackStats,\n  MissingInboundStats,\n  PeerConnectionType,\n  RTCRemoteInboundRtpStreamStats,\n} from '../interfaces/webrtc-stats';\nimport { HMSLocalTrack, HMSRemoteTrack } from '../media/tracks';\nimport HMSLogger from '../utils/logger';\nimport { isPresent } from '../utils/validations';\n\nexport const getLocalTrackStats = async (\n  eventBus: EventBus,\n  track: HMSLocalTrack,\n  peerName?: string,\n  prevTrackStats?: Record<string, HMSTrackStats>,\n): Promise<Record<string, HMSTrackStats> | undefined> => {\n  let trackReport: RTCStatsReport | undefined;\n  const trackStats: Record<string, HMSTrackStats> = {};\n  if (!track.transceiver?.sender.track) {\n    return;\n  }\n  try {\n    trackReport = await track.transceiver.sender.getStats();\n    const mimeTypes: { [key: string]: string } = {}; // codecId -> mimeType\n    const outbound: Record<string, RTCOutboundRtpStreamStats> = {};\n    const inbound: Record<string, RTCInboundRtpStreamStats & MissingInboundStats> = {};\n    trackReport?.forEach(stat => {\n      switch (stat.type) {\n        case 'outbound-rtp':\n          outbound[stat.id] = stat;\n          break;\n        case 'remote-inbound-rtp':\n          inbound[stat.ssrc] = stat;\n          break;\n        case 'codec':\n          mimeTypes[stat.id] = stat.mimeType;\n          break;\n        default:\n          break;\n      }\n    });\n\n    Object.keys({ ...outbound }).forEach(stat => {\n      const codecId = outbound[stat]?.codecId;\n      const mimeType = codecId ? mimeTypes[codecId] : undefined;\n      let codec: string | undefined;\n      if (mimeType) {\n        codec = mimeType.substring(mimeType.indexOf('/') + 1);\n      }\n      const out = { ...outbound[stat], rid: (outbound[stat] as HMSLocalTrackStats)?.rid as RID | undefined };\n      const inStats = inbound[out.ssrc];\n      trackStats[stat] = {\n        ...out,\n        bitrate: computeBitrate('bytesSent', out, prevTrackStats?.[stat]),\n        packetsLost: inStats?.packetsLost,\n        jitter: inStats?.jitter,\n        roundTripTime: inStats?.roundTripTime,\n        totalRoundTripTime: inStats?.totalRoundTripTime,\n        peerName,\n        peerID: track.peerId,\n        enabled: track.enabled,\n        codec,\n      };\n    });\n  } catch (err: any) {\n    eventBus.analytics.publish(\n      AnalyticsEventFactory.rtcStatsFailed(\n        ErrorFactory.WebrtcErrors.StatsFailed(\n          HMSAction.TRACK,\n          `Error getting local track stats ${track.trackId} - ${err.message}`,\n        ),\n      ),\n    );\n    HMSLogger.w('[HMSWebrtcStats]', 'Error in getting local track stats', track, err, (err as Error).name);\n  }\n  return trackStats;\n};\n\nexport const getTrackStats = async (\n  eventBus: EventBus,\n  track: HMSRemoteTrack,\n  peerName?: string,\n  prevTrackStats?: HMSTrackStats,\n): Promise<HMSTrackStats | undefined> => {\n  let trackReport: RTCStatsReport | undefined;\n  try {\n    trackReport = await track.transceiver?.receiver.getStats();\n  } catch (err: any) {\n    eventBus.analytics.publish(\n      AnalyticsEventFactory.rtcStatsFailed(\n        ErrorFactory.WebrtcErrors.StatsFailed(\n          HMSAction.TRACK,\n          `Error getting remote track stats ${track.trackId} - ${err.message}`,\n        ),\n      ),\n    );\n    HMSLogger.w('[HMSWebrtcStats]', 'Error in getting remote track stats', track, err);\n  }\n  const trackStats = getRelevantStatsFromTrackReport(trackReport);\n\n  const bitrate = computeBitrate('bytesReceived', trackStats, prevTrackStats);\n\n  const packetsLostRate = computeStatRate('packetsLost', trackStats, prevTrackStats);\n\n  if (trackStats?.remote) {\n    Object.assign(trackStats.remote, {\n      packetsLostRate: computeStatRate('packetsLost', trackStats.remote, prevTrackStats?.remote),\n    });\n  }\n\n  return (\n    trackStats &&\n    Object.assign(trackStats, {\n      bitrate,\n      packetsLostRate,\n      peerId: track.peerId,\n      enabled: track.enabled,\n      peerName,\n      codec: trackStats.codec,\n    })\n  );\n};\n\nconst getRelevantStatsFromTrackReport = (trackReport?: RTCStatsReport) => {\n  let streamStats: RTCInboundRtpStreamStats | (RTCOutboundRtpStreamStats & { rid?: RID }) | undefined;\n  // Valid by Webrtc spec, not in TS\n  // let remoteStreamStats: RTCRemoteInboundRtpStreamStats | RTCRemoteOutboundRtpStreamStats;\n  let remoteStreamStats: RTCRemoteInboundRtpStreamStats | undefined;\n\n  const mimeTypes: { [key: string]: string } = {}; // codecId -> mimeType\n  trackReport?.forEach(stat => {\n    switch (stat.type) {\n      case 'inbound-rtp':\n        streamStats = stat;\n        break;\n      case 'outbound-rtp':\n        streamStats = stat;\n        break;\n      case 'remote-inbound-rtp':\n        remoteStreamStats = stat;\n        break;\n      case 'codec':\n        mimeTypes[stat.id] = stat.mimeType;\n        break;\n      default:\n        break;\n    }\n  });\n\n  const mimeType = streamStats?.codecId ? mimeTypes[streamStats.codecId] : undefined;\n  let codec: string | undefined;\n  if (mimeType) {\n    codec = mimeType.substring(mimeType.indexOf('/') + 1);\n  }\n\n  return (\n    streamStats &&\n    Object.assign(streamStats, {\n      remote: remoteStreamStats,\n      codec: codec,\n    })\n  );\n};\n\nexport const getLocalPeerStatsFromReport = (\n  type: PeerConnectionType,\n  report?: RTCStatsReport,\n  prevStats?: HMSPeerStats,\n): (RTCIceCandidatePairStats & { bitrate: number }) | undefined => {\n  const activeCandidatePair = getActiveCandidatePairFromReport(report);\n  const bitrate = computeBitrate(\n    (type === 'publish' ? 'bytesSent' : 'bytesReceived') as any,\n    activeCandidatePair,\n    prevStats && prevStats[type],\n  );\n\n  return activeCandidatePair && Object.assign(activeCandidatePair, { bitrate });\n};\n\nexport const getActiveCandidatePairFromReport = (report?: RTCStatsReport): RTCIceCandidatePairStats | undefined => {\n  let activeCandidatePair: RTCIceCandidatePairStats | undefined;\n  report?.forEach(stat => {\n    if (stat.type === 'transport') {\n      // TS doesn't have correct types for RTCStatsReports\n      // @ts-expect-error\n      activeCandidatePair = report?.get(stat.selectedCandidatePairId);\n    }\n  });\n\n  // Fallback for Firefox.\n  if (!activeCandidatePair) {\n    report?.forEach(stat => {\n      if (stat.type === 'candidate-pair' && stat.selected) {\n        activeCandidatePair = stat;\n      }\n    });\n  }\n\n  return activeCandidatePair;\n};\n\nexport const getPacketsLostAndJitterFromReport = (report?: RTCStatsReport): { packetsLost: number; jitter: number } => {\n  const result = { packetsLost: 0, jitter: 0 };\n  report?.forEach(stat => {\n    if (stat.packetsLost) {\n      result.packetsLost += stat.packetsLost;\n    }\n    if (stat.jitter > result.jitter) {\n      result.jitter = stat.jitter;\n    }\n  });\n\n  return result;\n};\n\nexport const union = <T>(arr1: T[], arr2: T[]): T[] => {\n  return Array.from(new Set(arr1.concat(arr2)));\n};\n\n/**\n * Ref: https://github.dev/peermetrics/webrtc-stats/blob/b5c1fed68325543e6f563c6d3f4450a4b51e12b7/src/utils.ts#L62\n */\nexport const computeBitrate = <T extends HMSTrackStats>(\n  statName: keyof T,\n  newReport?: Partial<T>,\n  oldReport?: Partial<T>,\n): number => computeStatRate(statName, newReport, oldReport) * 8; // Bytes to bits\n\nconst computeStatRate = <T extends HMSTrackStats>(\n  statName: keyof T,\n  newReport?: Partial<T>,\n  oldReport?: Partial<T>,\n): number => {\n  const newVal = newReport && newReport[statName];\n  const oldVal = oldReport ? oldReport[statName] : null;\n  const conditions = [newReport, oldReport, isPresent(newVal), isPresent(oldVal)];\n  if (conditions.every(condition => !!condition)) {\n    // Type not null checked in `isPresent`\n    // * 1000 - ms to s\n    return (\n      computeNumberRate(\n        newVal as unknown as number,\n        oldVal as unknown as number,\n        newReport?.timestamp,\n        oldReport?.timestamp,\n      ) * 1000\n    );\n  } else {\n    return 0;\n  }\n};\n\nexport const computeNumberRate = (newVal?: number, oldVal?: number, newTimestamp?: number, oldTimestamp?: number) => {\n  if (isPresent(newVal) && isPresent(oldVal) && newTimestamp && oldTimestamp) {\n    return ((newVal as number) - (oldVal as number)) / (newTimestamp - oldTimestamp);\n  } else {\n    return 0;\n  }\n};\n","import {\n  computeNumberRate,\n  getLocalPeerStatsFromReport,\n  getLocalTrackStats,\n  getPacketsLostAndJitterFromReport,\n  getTrackStats,\n  union,\n} from './utils';\nimport AnalyticsEventFactory from '../analytics/AnalyticsEventFactory';\nimport { ErrorFactory } from '../error/ErrorFactory';\nimport { HMSAction } from '../error/HMSAction';\nimport { EventBus } from '../events/EventBus';\nimport { HMSPeerStats, HMSTrackStats, PeerConnectionType } from '../interfaces/webrtc-stats';\nimport { HMSLocalTrack, HMSRemoteAudioTrack, HMSRemoteTrack, HMSRemoteVideoTrack } from '../media/tracks';\nimport { IStore } from '../sdk/store';\nimport HMSLogger from '../utils/logger';\n\nexport class HMSWebrtcStats {\n  private readonly TAG = '[HMSWebrtcStats]';\n  private localPeerID?: string;\n  private peerStats: Record<string, HMSPeerStats> = {};\n  private remoteTrackStats: Record<string, HMSTrackStats> = {};\n  private localTrackStats: Record<string, Record<string, HMSTrackStats>> = {};\n\n  /**\n   * Removed localPeerID check in other places as it will be present before\n   * this is initialized\n   */\n  constructor(\n    private getStats: Record<PeerConnectionType, RTCPeerConnection['getStats'] | undefined>,\n    private store: IStore,\n    private readonly eventBus: EventBus,\n  ) {\n    this.localPeerID = this.store.getLocalPeer()?.peerId;\n  }\n\n  getLocalPeerStats = (): HMSPeerStats | undefined => {\n    return this.peerStats[this.localPeerID!];\n  };\n\n  getRemoteTrackStats = (trackId: string): HMSTrackStats | undefined => {\n    return this.remoteTrackStats[trackId];\n  };\n\n  getAllRemoteTracksStats = () => {\n    return this.remoteTrackStats;\n  };\n\n  getLocalTrackStats = () => {\n    return this.localTrackStats;\n  };\n\n  /**\n   * @internal\n   */\n  updateStats = async () => {\n    await this.updateLocalPeerStats();\n    await this.updateLocalTrackStats();\n    await this.updateRemoteTrackStats();\n  };\n\n  private updateLocalPeerStats = async () => {\n    const prevLocalPeerStats = this.getLocalPeerStats();\n    let publishReport: RTCStatsReport | undefined;\n    try {\n      publishReport = await this.getStats.publish?.();\n    } catch (err: any) {\n      this.eventBus.analytics.publish(\n        AnalyticsEventFactory.rtcStatsFailed(ErrorFactory.WebrtcErrors.StatsFailed(HMSAction.PUBLISH, err.message)),\n      );\n      HMSLogger.w(this.TAG, 'Error in getting publish stats', err);\n    }\n    const publishStats: HMSPeerStats['publish'] | undefined =\n      publishReport && getLocalPeerStatsFromReport('publish', publishReport, prevLocalPeerStats);\n\n    let subscribeReport: RTCStatsReport | undefined;\n    try {\n      subscribeReport = await this.getStats.subscribe?.();\n    } catch (err: any) {\n      this.eventBus.analytics.publish(\n        AnalyticsEventFactory.rtcStatsFailed(ErrorFactory.WebrtcErrors.StatsFailed(HMSAction.SUBSCRIBE, err.message)),\n      );\n      HMSLogger.w(this.TAG, 'Error in getting subscribe stats', err);\n    }\n    const baseSubscribeStats =\n      subscribeReport && getLocalPeerStatsFromReport('subscribe', subscribeReport, prevLocalPeerStats);\n    const { packetsLost, jitter } = getPacketsLostAndJitterFromReport(subscribeReport);\n    const packetsLostRate = computeNumberRate(\n      packetsLost,\n      prevLocalPeerStats?.subscribe?.packetsLost,\n      baseSubscribeStats?.timestamp,\n      prevLocalPeerStats?.subscribe?.timestamp,\n    );\n\n    const subscribeStats: HMSPeerStats['subscribe'] =\n      baseSubscribeStats && Object.assign(baseSubscribeStats, { packetsLostRate, jitter, packetsLost });\n\n    this.peerStats[this.localPeerID!] = { publish: publishStats, subscribe: subscribeStats };\n  };\n\n  private updateRemoteTrackStats = async () => {\n    const tracks = Array.from(this.store.getTracksMap().values()).filter(\n      track => track instanceof HMSRemoteVideoTrack || track instanceof HMSRemoteAudioTrack,\n    );\n    const trackIds = tracks.map(track => track.trackId);\n    Object.keys(this.remoteTrackStats).forEach(trackId => {\n      if (!trackIds.includes(trackId)) {\n        delete this.remoteTrackStats[trackId];\n      }\n    });\n    for (const track of tracks) {\n      const peerName = track.peerId && this.store.getPeerById(track.peerId)?.name;\n      const prevTrackStats = this.getRemoteTrackStats(track.trackId);\n      const trackStats = await getTrackStats(this.eventBus, track as HMSRemoteTrack, peerName, prevTrackStats);\n      if (trackStats) {\n        this.remoteTrackStats[track.trackId] = trackStats;\n      }\n    }\n  };\n\n  private updateLocalTrackStats = async () => {\n    const tracks = this.store.getLocalPeerTracks().reduce<Record<string, HMSLocalTrack>>((res, track) => {\n      res[track.getTrackIDBeingSent()] = track;\n      return res;\n    }, {});\n    const trackIDs = union(Object.keys(this.localTrackStats), Object.keys(tracks));\n    for (const trackID of trackIDs) {\n      const track = tracks[trackID] as HMSLocalTrack;\n      if (track) {\n        const peerName = this.store.getLocalPeer()?.name;\n        const trackStats = await getLocalTrackStats(this.eventBus, track, peerName, this.localTrackStats[trackID]);\n        if (trackStats) {\n          this.localTrackStats[trackID] = trackStats;\n        }\n      } else {\n        delete this.localTrackStats[trackID];\n      }\n    }\n  };\n}\n","import { HMSWebrtcStats } from './HMSWebrtcStats';\nimport AnalyticsEventFactory from '../analytics/AnalyticsEventFactory';\nimport { ErrorFactory } from '../error/ErrorFactory';\nimport { HMSAction } from '../error/HMSAction';\nimport { EventBus } from '../events/EventBus';\nimport { IStore } from '../sdk/store';\nimport { RTC_STATS_MONITOR_INTERVAL } from '../utils/constants';\nimport HMSLogger from '../utils/logger';\nimport { sleep } from '../utils/timer-utils';\n\nexport class HMSWebrtcInternals {\n  private readonly TAG = '[HMSWebrtcInternals]';\n  private readonly interval = RTC_STATS_MONITOR_INTERVAL;\n  private isMonitored = false;\n  private hmsStats?: HMSWebrtcStats;\n\n  constructor(\n    private readonly store: IStore,\n    private readonly eventBus: EventBus,\n    private publishConnection?: RTCPeerConnection,\n    private subscribeConnection?: RTCPeerConnection,\n  ) {}\n\n  getPublishPeerConnection() {\n    return this.publishConnection;\n  }\n\n  getSubscribePeerConnection() {\n    return this.subscribeConnection;\n  }\n\n  getCurrentStats() {\n    return this.hmsStats;\n  }\n\n  onStatsChange(statsChangeCb: (stats: HMSWebrtcStats) => void) {\n    this.eventBus.statsUpdate.subscribe(statsChangeCb);\n    return () => {\n      this.eventBus.statsUpdate.unsubscribe(statsChangeCb);\n    };\n  }\n\n  private handleStatsUpdate = async () => {\n    await this.hmsStats?.updateStats();\n    this.eventBus.statsUpdate.publish(this.hmsStats);\n  };\n\n  /**\n   *\n   * @internal\n   */\n  setPeerConnections({ publish, subscribe }: { publish?: RTCPeerConnection; subscribe?: RTCPeerConnection }) {\n    this.publishConnection = publish;\n    this.subscribeConnection = subscribe;\n\n    this.hmsStats = new HMSWebrtcStats(\n      {\n        publish: this.publishConnection?.getStats.bind(this.publishConnection),\n        subscribe: this.subscribeConnection?.getStats.bind(this.subscribeConnection),\n      },\n      this.store,\n      this.eventBus,\n    );\n  }\n\n  /**\n   * @internal\n   */\n  async start() {\n    if (this.isMonitored) {\n      HMSLogger.d(this.TAG, 'Already started');\n      return;\n    }\n    this.stop();\n    this.isMonitored = true;\n    HMSLogger.d(this.TAG, 'Starting Webrtc Stats Monitor');\n    this.startLoop()\n      .then(() => HMSLogger.d(this.TAG, 'Stopping Webrtc Stats Monitor'))\n      .catch(e => {\n        this.eventBus.analytics.publish(\n          AnalyticsEventFactory.rtcStatsFailed(ErrorFactory.WebrtcErrors.StatsFailed(HMSAction.PUBLISH, e.message)),\n        );\n        HMSLogger.e(this.TAG, e.message);\n      });\n  }\n\n  private stop() {\n    this.isMonitored = false;\n  }\n\n  private async startLoop() {\n    while (this.isMonitored) {\n      await this.handleStatsUpdate();\n      await sleep(this.interval);\n    }\n  }\n\n  /**\n   * @internal\n   */\n  cleanup() {\n    this.stop();\n    this.eventBus.statsUpdate.removeAllListeners();\n  }\n}\n","import AnalyticsEventFactory from '../analytics/AnalyticsEventFactory';\nimport { EventBus } from '../events/EventBus';\nimport { HMSUpdateListener } from '../interfaces';\nimport { NetworkHealth, ScoreMap } from '../signal/init/models';\nimport HMSLogger from '../utils/logger';\nimport { sleep } from '../utils/timer-utils';\n\nexport class NetworkTestManager {\n  private readonly TAG = '[NetworkTestManager]';\n  private controller = new AbortController();\n  private score?: number;\n  constructor(private eventBus: EventBus, private listener?: HMSUpdateListener) {}\n\n  start = async (networkHealth: NetworkHealth) => {\n    if (!networkHealth) {\n      return;\n    }\n    const { url, timeout, scoreMap } = networkHealth;\n    const signal = this.controller.signal;\n\n    const startTime = Date.now();\n    let downloadedSize = 0;\n    const timeoutPromise = sleep(timeout).then(() => {\n      this.controller.abort();\n    });\n    try {\n      const res = await fetch(`${url}?${Date.now()}`, { signal });\n      const reader = res.body?.getReader();\n      if (!reader) {\n        throw Error('unable to process request');\n      }\n      const readData = async () => {\n        if (!reader) {\n          return;\n        }\n        try {\n          let completed = false;\n          while (!completed) {\n            const { value, done } = await reader.read();\n            completed = done;\n            if (value) {\n              downloadedSize += value.byteLength;\n              this.sendScore({ scoreMap, downloadedSize, startTime });\n            }\n          }\n        } catch (error) {\n          if ((error as Error).name !== 'AbortError') {\n            HMSLogger.d(this.TAG, error);\n          }\n        }\n      };\n\n      return Promise.race([readData(), timeoutPromise])\n        .then(() => {\n          this.sendScore({ scoreMap, downloadedSize, startTime, finished: true });\n        })\n        .catch(error => {\n          HMSLogger.d(this.TAG, error);\n          this.updateScoreToListener(0);\n          this.eventBus.analytics.publish(\n            AnalyticsEventFactory.previewNetworkQuality({ error: (error as Error).message }),\n          );\n        });\n    } catch (error) {\n      if ((error as Error).name !== 'AbortError') {\n        HMSLogger.d(this.TAG, error);\n        this.updateScoreToListener(0);\n        this.eventBus.analytics.publish(\n          AnalyticsEventFactory.previewNetworkQuality({ error: (error as Error).message }),\n        );\n      } else {\n        HMSLogger.d(this.TAG, error);\n      }\n    }\n  };\n\n  stop = () => {\n    if (!this.controller.signal.aborted) {\n      this.controller.abort();\n    }\n  };\n\n  private sendScore = ({\n    scoreMap,\n    downloadedSize,\n    startTime,\n    finished = false,\n  }: {\n    scoreMap: ScoreMap;\n    downloadedSize: number;\n    startTime: number;\n    finished?: boolean;\n  }) => {\n    const totalTimeInSecs = (Date.now() - startTime) / 1000;\n    const sizeInKB = downloadedSize / 1024;\n    const bitrate = (sizeInKB / totalTimeInSecs) * 8;\n    let calculatedScore = -1;\n    for (const score in scoreMap) {\n      const thresholds = scoreMap[score];\n      if (bitrate >= thresholds.low && (!thresholds.high || bitrate <= thresholds.high)) {\n        calculatedScore = Number(score);\n      }\n    }\n    this.updateScoreToListener(calculatedScore);\n    if (finished) {\n      this.eventBus.analytics.publish(\n        AnalyticsEventFactory.previewNetworkQuality({ score: calculatedScore, downLink: bitrate.toFixed(2) }),\n      );\n    }\n  };\n\n  private updateScoreToListener(newQualityScore: number) {\n    if (newQualityScore === this.score) {\n      return;\n    }\n    this.score = newQualityScore;\n    this.listener?.onNetworkQuality?.(newQualityScore);\n  }\n}\n","import { IStore } from './store';\nimport { DeviceManager } from '../device-manager';\nimport { HMSRole } from '../interfaces';\nimport InitialSettings from '../interfaces/settings';\nimport { SimulcastLayers } from '../interfaces/simulcast-layers';\nimport { HMSPeerUpdate, HMSTrackUpdate, HMSUpdateListener } from '../interfaces/update-listener';\nimport { HMSLocalTrack } from '../media/tracks';\nimport ITransport from '../transport/ITransport';\n\nexport default class RoleChangeManager {\n  constructor(\n    private store: IStore,\n    private transport: ITransport,\n    private deviceManager: DeviceManager,\n    private publish: (settings: InitialSettings) => Promise<void>,\n    private removeAuxiliaryTrack: (trackId: string) => void,\n    private listener?: HMSUpdateListener,\n  ) {}\n\n  handleLocalPeerRoleUpdate = async ({ oldRole, newRole }: { oldRole: HMSRole; newRole: HMSRole }) => {\n    const localPeer = this.store.getLocalPeer();\n\n    if (!localPeer) {\n      return;\n    }\n\n    await this.diffRolesAndPublishTracks({ oldRole, newRole });\n    this.listener?.onPeerUpdate(HMSPeerUpdate.ROLE_UPDATED, localPeer);\n  };\n\n  diffRolesAndPublishTracks = async ({ oldRole, newRole }: { oldRole: HMSRole; newRole: HMSRole }) => {\n    const wasPublishing = new Set(oldRole.publishParams.allowed);\n    const isPublishing = new Set(newRole.publishParams.allowed);\n\n    const removeVideo = this.removeTrack(wasPublishing, isPublishing, 'video');\n\n    const removeAudio = this.removeTrack(wasPublishing, isPublishing, 'audio');\n    const removeScreen = this.removeTrack(wasPublishing, isPublishing, 'screen');\n\n    const videoHasSimulcastDifference = this.hasSimulcastDifference(\n      oldRole.publishParams.simulcast?.video,\n      newRole.publishParams.simulcast?.video,\n    );\n    const screenHasSimulcastDifference = this.hasSimulcastDifference(\n      oldRole.publishParams.simulcast?.screen,\n      newRole.publishParams.simulcast?.screen,\n    );\n\n    const prevVideoEnabled = this.store.getLocalPeer()?.videoTrack?.enabled;\n\n    await this.removeAudioTrack(removeAudio);\n    await this.removeVideoTracks(removeVideo || videoHasSimulcastDifference);\n    await this.removeScreenTracks(removeScreen || screenHasSimulcastDifference);\n\n    const settings = this.getSettings();\n\n    if (videoHasSimulcastDifference) {\n      settings.isVideoMuted = !prevVideoEnabled;\n    }\n\n    // call publish with new settings, local track manager will diff policies\n    await this.publish(settings);\n    await this.syncDevices(settings, newRole);\n  };\n\n  private async syncDevices(initialSettings: InitialSettings, newRole: HMSRole) {\n    if ((!initialSettings.isAudioMuted || !initialSettings.isVideoMuted) && newRole.publishParams.allowed.length > 0) {\n      await this.deviceManager.init(true);\n    }\n  }\n  private async removeVideoTracks(removeVideo: boolean) {\n    if (!removeVideo) {\n      return;\n    }\n    const localPeer = this.store.getLocalPeer();\n    // TODO check auxillary tracks for regular audio and video too\n    if (localPeer?.videoTrack) {\n      // TODO: stop processed track and cleanup plugins loop non async\n      // vb can throw change role off otherwise\n      if (localPeer.videoTrack.isPublished) {\n        await this.transport.unpublish([localPeer.videoTrack]);\n      } else {\n        await localPeer.videoTrack.cleanup();\n      }\n      this.listener?.onTrackUpdate(HMSTrackUpdate.TRACK_REMOVED, localPeer.videoTrack, localPeer);\n      localPeer.videoTrack = undefined;\n    }\n    await this.removeAuxTracks(track => track.source !== 'screen' && track.type === 'video');\n  }\n\n  private async removeAudioTrack(removeAudio: boolean) {\n    if (!removeAudio) {\n      return;\n    }\n    const localPeer = this.store.getLocalPeer();\n    if (localPeer?.audioTrack) {\n      if (localPeer.audioTrack.isPublished) {\n        await this.transport.unpublish([localPeer.audioTrack]);\n      } else {\n        await localPeer.audioTrack.cleanup();\n      }\n      this.listener?.onTrackUpdate(HMSTrackUpdate.TRACK_REMOVED, localPeer.audioTrack, localPeer);\n      localPeer.audioTrack = undefined;\n    }\n    await this.removeAuxTracks(track => track.source !== 'screen' && track.type === 'audio');\n  }\n\n  private async removeScreenTracks(removeScreen: boolean) {\n    if (!removeScreen) {\n      return;\n    }\n    await this.removeAuxTracks(track => track.source === 'screen');\n  }\n\n  private async removeAuxTracks(predicate: (track: HMSLocalTrack) => boolean) {\n    const localPeer = this.store.getLocalPeer();\n    if (localPeer?.auxiliaryTracks) {\n      const localAuxTracks = [...localPeer.auxiliaryTracks];\n      for (const track of localAuxTracks) {\n        if (predicate(track)) {\n          await this.removeAuxiliaryTrack(track.trackId);\n        }\n      }\n    }\n  }\n\n  private removeTrack(wasPublishing: Set<string>, isPublishing: Set<string>, type: string) {\n    return wasPublishing.has(type) && !isPublishing.has(type);\n  }\n\n  private hasSimulcastDifference(oldLayers?: SimulcastLayers, newLayers?: SimulcastLayers) {\n    if (!oldLayers && !newLayers) {\n      return false;\n    }\n    if (oldLayers?.layers?.length !== newLayers?.layers?.length) {\n      return true;\n    }\n\n    // return true if anyone layer has different maxBitrate/maxFramerate\n    return !!oldLayers?.layers?.some(layer => {\n      const newLayer = newLayers?.layers?.find(newLayer => newLayer.rid === layer.rid);\n      return newLayer?.maxBitrate !== layer.maxBitrate || newLayer?.maxFramerate !== layer.maxFramerate;\n    });\n  }\n\n  private getSettings(): InitialSettings {\n    const initialSettings = this.store.getConfig()?.settings;\n\n    return {\n      isAudioMuted: initialSettings?.isAudioMuted ?? true,\n      isVideoMuted: initialSettings?.isVideoMuted ?? true,\n      audioInputDeviceId: initialSettings?.audioInputDeviceId || 'default',\n      audioOutputDeviceId: initialSettings?.audioOutputDeviceId || 'default',\n      videoDeviceId: initialSettings?.videoDeviceId || 'default',\n    };\n  }\n}\n","import AnalyticsEvent from './AnalyticsEvent';\nimport { IAnalyticsTransportProvider } from './IAnalyticsTransportProvider';\nimport {\n  CLIENT_ANAYLTICS_PROD_ENDPOINT,\n  CLIENT_ANAYLTICS_QA_ENDPOINT,\n  CLIENT_ANAYLTICS_STORAGE_LIMIT,\n} from '../utils/constants';\nimport { LocalStorage } from '../utils/local-storage';\nimport HMSLogger from '../utils/logger';\nimport { ENV } from '../utils/support';\n\ninterface ClientEventBody {\n  event: string;\n  event_id: string;\n  peer: {\n    peer_id?: string;\n    role?: string;\n    joined_at?: number;\n    left_at?: number;\n    room_id?: string;\n    room_name?: string;\n    session_started_at?: number;\n    user_data?: string;\n    user_name?: string;\n    template_id?: string;\n    session_id?: string;\n  };\n  timestamp: number;\n  cluster: {\n    websocket_url: string;\n  };\n  payload: Record<string, any>;\n  device_id: string;\n}\n\nclass ClientAnalyticsTransport implements IAnalyticsTransportProvider {\n  readonly TAG = '[HTTPAnalyticsTransport]';\n  private failedEvents = new LocalStorage<AnalyticsEvent[]>('client-events');\n  isConnected = true;\n  private env: null | ENV = null;\n  private websocketURL = '';\n\n  setEnv(env: ENV) {\n    this.env = env;\n    this.flushFailedEvents();\n  }\n\n  setWebsocketEndpoint(ws: string) {\n    this.websocketURL = ws;\n  }\n\n  sendEvent(event: AnalyticsEvent) {\n    if (!this.env) {\n      this.addEventToStorage(event);\n      return;\n    }\n    const requestBody: ClientEventBody = {\n      event: event.name,\n      payload: event.properties,\n      event_id: String(event.timestamp),\n      peer: event.metadata.peer,\n      timestamp: event.timestamp,\n      device_id: event.device_id,\n      cluster: {\n        websocket_url: this.websocketURL,\n      },\n    };\n    const url = this.env === ENV.PROD ? CLIENT_ANAYLTICS_PROD_ENDPOINT : CLIENT_ANAYLTICS_QA_ENDPOINT;\n    fetch(url, {\n      method: 'POST',\n      headers: {\n        'Content-Type': 'application/json',\n        Authorization: `Bearer ${event.metadata.token}`,\n        user_agent_v2: event.metadata.userAgent,\n      },\n      body: JSON.stringify(requestBody),\n    })\n      .then(response => {\n        // Ignore invalid token or expired token messages\n        if (response.status === 401) {\n          this.removeFromStorage(event);\n          return;\n        }\n        if (response.status !== 200) {\n          throw Error(response.statusText);\n        }\n        this.removeFromStorage(event);\n      })\n      .catch(error => {\n        HMSLogger.v(this.TAG, 'Failed to send event', error, event);\n        this.addEventToStorage(event);\n      });\n  }\n  flushFailedEvents() {\n    const events = this.failedEvents.get();\n    events?.forEach(event => this.sendEvent(event));\n  }\n\n  private addEventToStorage(event: AnalyticsEvent): void {\n    const existingEvents = this.failedEvents.get() || [];\n    if (!existingEvents.find(existingEvent => existingEvent.timestamp === event.timestamp)) {\n      if (existingEvents.length === CLIENT_ANAYLTICS_STORAGE_LIMIT) {\n        existingEvents.shift();\n      }\n      existingEvents.push(event);\n      this.failedEvents.set(existingEvents);\n    }\n  }\n\n  private removeFromStorage(event: AnalyticsEvent): void {\n    const events = this.failedEvents.get() || [];\n    const index = events.findIndex(storageEvent => storageEvent.timestamp === event.timestamp);\n    if (index > -1) {\n      events.splice(index, 1);\n      this.failedEvents.set(events);\n    }\n  }\n}\n\nexport const HTTPAnalyticsTransport = new ClientAnalyticsTransport();\n","import { IStore, KnownRoles, TrackStateEntry } from './IStore';\nimport { HTTPAnalyticsTransport } from '../../analytics/HTTPAnalyticsTransport';\nimport { DeviceStorageManager } from '../../device-manager/DeviceStorage';\nimport { ErrorFactory } from '../../error/ErrorFactory';\nimport { HMSAction } from '../../error/HMSAction';\nimport { HMSConfig, HMSFrameworkInfo, HMSPermissionType, HMSPoll, HMSSpeaker, HMSWhiteboard } from '../../interfaces';\nimport { SelectedDevices } from '../../interfaces/devices';\nimport { IErrorListener } from '../../interfaces/error-listener';\nimport {\n  HMSSimulcastLayerDefinition,\n  RID,\n  SimulcastLayer,\n  SimulcastLayers,\n  simulcastMapping,\n} from '../../interfaces/simulcast-layers';\nimport {\n  HMSAudioTrack,\n  HMSLocalTrack,\n  HMSRemoteAudioTrack,\n  HMSRemoteVideoTrack,\n  HMSTrack,\n  HMSTrackSource,\n  HMSTrackType,\n  HMSVideoTrack,\n} from '../../media/tracks';\nimport { PolicyParams } from '../../notification-manager';\nimport { ENV } from '../../utils/support';\nimport { createUserAgent } from '../../utils/user-agent';\nimport HMSRoom from '../models/HMSRoom';\nimport { HMSLocalPeer, HMSPeer, HMSRemotePeer } from '../models/peer';\n\nclass Store implements IStore {\n  private room?: HMSRoom;\n  private knownRoles: KnownRoles = {};\n  private localPeerId?: string;\n  private peers: Record<string, HMSPeer> = {};\n  private tracks = new Map<HMSTrack, HMSTrack>();\n  private templateAppData?: Record<string, string>;\n  // Not used currently. Will be used exclusively for preview tracks.\n  // private previewTracks: Record<string, HMSTrack> = {};\n  private peerTrackStates: Record<string, TrackStateEntry> = {};\n  private speakers: HMSSpeaker[] = [];\n  private videoLayers?: SimulcastLayers;\n  // private screenshareLayers?: SimulcastLayers;\n  private config?: HMSConfig;\n  private errorListener?: IErrorListener;\n  private roleDetailsArrived = false;\n  private env: ENV = ENV.PROD;\n  private simulcastEnabled = false;\n  private userAgent: string = createUserAgent(this.env);\n  private polls = new Map<string, HMSPoll>();\n  private whiteboards = new Map<string, HMSWhiteboard>();\n\n  getConfig() {\n    return this.config;\n  }\n\n  setSimulcastEnabled(enabled: boolean) {\n    this.simulcastEnabled = enabled;\n  }\n\n  getEnv() {\n    return this.env;\n  }\n\n  getPublishParams() {\n    const peer = this.getLocalPeer();\n    const role = peer?.asRole || peer?.role;\n    return role?.publishParams;\n  }\n\n  getRoom() {\n    return this.room;\n  }\n\n  getPolicyForRole(role: string) {\n    return this.knownRoles[role];\n  }\n\n  getKnownRoles() {\n    return this.knownRoles;\n  }\n\n  getTemplateAppData() {\n    return this.templateAppData;\n  }\n\n  getLocalPeer() {\n    if (this.localPeerId && this.peers[this.localPeerId]) {\n      return this.peers[this.localPeerId] as HMSLocalPeer;\n    }\n    return undefined;\n  }\n\n  getRemotePeers() {\n    return Object.values(this.peers).filter(peer => !peer.isLocal) as HMSRemotePeer[];\n  }\n\n  getPeers(): HMSPeer[] {\n    return Object.values(this.peers);\n  }\n\n  getPeerMap() {\n    return this.peers;\n  }\n\n  getPeerById(peerId: string) {\n    if (this.peers[peerId]) {\n      return this.peers[peerId];\n    }\n    return undefined;\n  }\n\n  getTracksMap() {\n    return this.tracks;\n  }\n\n  getTracks() {\n    return Array.from(this.tracks.values());\n  }\n\n  getVideoTracks() {\n    return this.getTracks().filter(track => track.type === HMSTrackType.VIDEO) as HMSVideoTrack[];\n  }\n\n  getRemoteVideoTracks() {\n    return this.getTracks().filter(track => track instanceof HMSRemoteVideoTrack) as HMSRemoteVideoTrack[];\n  }\n\n  getAudioTracks() {\n    return this.getTracks().filter(track => track.type === HMSTrackType.AUDIO) as HMSAudioTrack[];\n  }\n\n  getPeerTracks(peerId?: string) {\n    const peer = peerId ? this.peers[peerId] : undefined;\n    const tracks: HMSTrack[] = [];\n    peer?.videoTrack && tracks.push(peer.videoTrack);\n    peer?.audioTrack && tracks.push(peer.audioTrack);\n    return tracks.concat(peer?.auxiliaryTracks || []);\n  }\n\n  getLocalPeerTracks() {\n    return this.getPeerTracks(this.localPeerId) as HMSLocalTrack[];\n  }\n\n  hasTrack(track: HMSTrack) {\n    return this.tracks.has(track);\n  }\n\n  getTrackById(trackId: string) {\n    const track = Array.from(this.tracks.values()).find(track => track.trackId === trackId);\n    if (track) {\n      return track;\n    }\n    const localPeer = this.getLocalPeer();\n    /**\n     * handle case of audio level coming from server for local peer's track where local peer\n     * didn't initially gave audio permission. So track.firstTrackId is that of dummy track and\n     * this.tracks[trackId] doesn't exist.\n     * Example repro which this solves -\n     * - call preview with audio muted, unmute audio in preview then join the room, now initial\n     * track id is that from dummy track but the track id which server knows will be different\n     */\n    if (localPeer) {\n      if (localPeer.audioTrack?.isPublishedTrackId(trackId)) {\n        return localPeer.audioTrack;\n      } else if (localPeer.videoTrack?.isPublishedTrackId(trackId)) {\n        return localPeer.videoTrack;\n      }\n    }\n    return undefined;\n  }\n\n  getPeerByTrackId(trackId: string) {\n    const track = Array.from(this.tracks.values()).find(track => track.trackId === trackId);\n    return track?.peerId ? this.peers[track.peerId] : undefined;\n  }\n\n  getSpeakers() {\n    return this.speakers;\n  }\n\n  getSpeakerPeers() {\n    return this.speakers.map(speaker => speaker.peer);\n  }\n\n  getUserAgent() {\n    return this.userAgent;\n  }\n\n  createAndSetUserAgent(frameworkInfo?: HMSFrameworkInfo) {\n    this.userAgent = createUserAgent(this.env, frameworkInfo);\n  }\n\n  setRoom(room: HMSRoom) {\n    this.room = room;\n  }\n\n  setKnownRoles(params: PolicyParams) {\n    this.knownRoles = params.known_roles;\n    this.addPluginsToRoles(params.plugins);\n    this.roleDetailsArrived = true;\n    this.templateAppData = params.app_data;\n    if (!this.simulcastEnabled) {\n      return;\n    }\n    const publishParams = this.knownRoles[params.name]?.publishParams;\n    this.videoLayers = this.convertSimulcastLayers(publishParams.simulcast?.video);\n    // this.screenshareLayers = this.convertSimulcastLayers(publishParams.simulcast?.screen);\n    this.updatePeersPolicy();\n  }\n\n  hasRoleDetailsArrived(): boolean {\n    return this.roleDetailsArrived;\n  }\n\n  // eslint-disable-next-line complexity\n  setConfig(config: HMSConfig) {\n    DeviceStorageManager.rememberDevices(Boolean(config.rememberDeviceSelection));\n    if (config.rememberDeviceSelection) {\n      const devices: SelectedDevices | undefined = DeviceStorageManager.getSelection();\n      if (devices) {\n        if (!config.settings) {\n          config.settings = {};\n        }\n        if (devices.audioInput?.deviceId) {\n          config.settings.audioInputDeviceId = config.settings.audioInputDeviceId || devices.audioInput.deviceId;\n        }\n        if (devices.audioOutput?.deviceId) {\n          config.settings.audioOutputDeviceId = config.settings.audioOutputDeviceId || devices.audioOutput.deviceId;\n        }\n        if (devices.videoInput?.deviceId) {\n          config.settings.videoDeviceId = config.settings.videoDeviceId || devices.videoInput.deviceId;\n        }\n      }\n    }\n    config.autoManageVideo = config.autoManageVideo !== false;\n    config.autoManageWakeLock = config.autoManageWakeLock !== false;\n    this.config = config;\n    this.setEnv();\n  }\n\n  addPeer(peer: HMSPeer) {\n    this.peers[peer.peerId] = peer;\n    if (peer.isLocal) {\n      this.localPeerId = peer.peerId;\n    }\n  }\n\n  /**\n   * @param {HMSTrack} track the published track that has to be added\n   *\n   * Note: Only use this method to add published tracks not preview traks\n   */\n  addTrack(track: HMSTrack) {\n    this.tracks.set(track, track);\n  }\n\n  getTrackState(trackId: string) {\n    return this.peerTrackStates[trackId];\n  }\n\n  setTrackState(trackStateEntry: TrackStateEntry) {\n    this.peerTrackStates[trackStateEntry.trackInfo.track_id] = trackStateEntry;\n  }\n\n  removePeer(peerId: string) {\n    if (this.localPeerId === peerId) {\n      this.localPeerId = undefined;\n    }\n    delete this.peers[peerId];\n  }\n\n  removeTrack(track: HMSTrack) {\n    this.tracks.delete(track);\n  }\n\n  updateSpeakers(speakers: HMSSpeaker[]) {\n    this.speakers = speakers;\n  }\n\n  async updateAudioOutputVolume(value: number) {\n    for (const track of this.getAudioTracks()) {\n      await track.setVolume(value);\n    }\n  }\n\n  async updateAudioOutputDevice(device: MediaDeviceInfo) {\n    const promises: Promise<void>[] = [];\n    this.getAudioTracks().forEach(track => {\n      if (track instanceof HMSRemoteAudioTrack) {\n        promises.push(track.setOutputDevice(device));\n      }\n    });\n    await Promise.all(promises);\n  }\n\n  getSimulcastLayers(source: HMSTrackSource): SimulcastLayer[] {\n    // Enable only when backend enables and source is video or screen. ignore videoplaylist\n    if (!this.simulcastEnabled || !['screen', 'regular'].includes(source)) {\n      return [];\n    }\n    if (source === 'screen') {\n      return []; //this.screenshareLayers?.layers || []; uncomment this when screenshare simulcast supported\n    }\n    return this.videoLayers?.layers || [];\n  }\n\n  /**\n   * Convert maxBitrate from kbps to bps\n   * @internal\n   * @param simulcastLayers\n   * @returns {SimulcastLayers}\n   */\n  private convertSimulcastLayers(simulcastLayers?: SimulcastLayers) {\n    if (!simulcastLayers) {\n      return;\n    }\n    return {\n      ...simulcastLayers,\n      layers: (simulcastLayers.layers || []).map(layer => {\n        return {\n          ...layer,\n          maxBitrate: layer.maxBitrate * 1000,\n        };\n      }),\n    };\n  }\n\n  getSimulcastDefinitionsForPeer(peer: HMSPeer, source: HMSTrackSource) {\n    // TODO: remove screen check when screenshare simulcast is supported\n    if ([!peer || !peer.role, source === 'screen', !this.simulcastEnabled].some(value => !!value)) {\n      return [];\n    }\n\n    const publishParams = this.getPolicyForRole(peer.role!.name).publishParams;\n    let simulcastLayers: SimulcastLayers | undefined;\n    let width: number;\n    let height: number;\n    if (source === 'regular') {\n      simulcastLayers = publishParams.simulcast?.video;\n      width = publishParams.video.width;\n      height = publishParams.video.height;\n    } else if (source === 'screen') {\n      simulcastLayers = publishParams.simulcast?.screen;\n      width = publishParams.screen.width;\n      height = publishParams.screen.height;\n    }\n    return (\n      simulcastLayers?.layers?.map(value => {\n        const layer = simulcastMapping[value.rid as RID];\n        const resolution = {\n          width: Math.floor(width / value.scaleResolutionDownBy),\n          height: Math.floor(height / value.scaleResolutionDownBy),\n        };\n        return {\n          layer,\n          resolution,\n        } as HMSSimulcastLayerDefinition;\n      }) || []\n    );\n  }\n\n  setPoll(poll: HMSPoll) {\n    this.polls.set(poll.id, poll);\n  }\n\n  getPoll(id: string): HMSPoll | undefined {\n    return this.polls.get(id);\n  }\n\n  setWhiteboard(whiteboard: HMSWhiteboard) {\n    this.whiteboards.set(whiteboard.id, whiteboard);\n  }\n\n  getWhiteboard(id?: string): HMSWhiteboard | undefined {\n    return id ? this.whiteboards.get(id) : this.whiteboards.values().next().value;\n  }\n\n  getErrorListener() {\n    return this.errorListener;\n  }\n\n  cleanup() {\n    const tracks = this.getTracks();\n    for (const track of tracks) {\n      track.cleanup();\n    }\n    this.room = undefined;\n    this.config = undefined;\n    this.localPeerId = undefined;\n    this.roleDetailsArrived = false;\n  }\n\n  setErrorListener(listener: IErrorListener) {\n    this.errorListener = listener;\n  }\n\n  private updatePeersPolicy() {\n    this.getPeers().forEach(peer => {\n      if (!peer.role) {\n        this.errorListener?.onError(ErrorFactory.GenericErrors.InvalidRole(HMSAction.VALIDATION, ''));\n        return;\n      }\n      peer.role = this.getPolicyForRole(peer.role.name);\n    });\n  }\n  private addPluginsToRoles(plugins: PolicyParams['plugins']) {\n    if (!plugins) {\n      return;\n    }\n\n    const addPermissionToRole = (\n      role: string,\n      pluginName: keyof PolicyParams['plugins'],\n      permission: HMSPermissionType,\n    ) => {\n      const rolePermissions = this.knownRoles[role].permissions;\n      if (!rolePermissions[pluginName]) {\n        rolePermissions[pluginName] = [];\n      }\n      rolePermissions[pluginName]?.push(permission);\n    };\n\n    Object.keys(plugins).forEach(plugin => {\n      const pluginName = plugin as keyof PolicyParams['plugins'];\n      if (!plugins[pluginName]) {\n        return;\n      }\n\n      const permissions = plugins[pluginName].permissions;\n      permissions?.admin?.forEach(role => addPermissionToRole(role, pluginName, 'admin'));\n      permissions?.reader?.forEach(role => addPermissionToRole(role, pluginName, 'read'));\n      permissions?.writer?.forEach(role => addPermissionToRole(role, pluginName, 'write'));\n    });\n  }\n  private setEnv() {\n    const endPoint = this.config?.initEndpoint!;\n    const url = endPoint.split('https://')[1];\n    let env: ENV = ENV.PROD;\n    if (url.startsWith(ENV.PROD)) {\n      env = ENV.PROD;\n    } else if (url.startsWith(ENV.QA)) {\n      env = ENV.QA;\n    } else if (url.startsWith(ENV.DEV)) {\n      env = ENV.DEV;\n    }\n    this.env = env;\n    HTTPAnalyticsTransport.setEnv(env);\n  }\n}\n\nexport { Store };\n","import HMSLogger from '../utils/logger';\n\nexport class WakeLockManager {\n  private readonly TAG = '[WakeLockManager]';\n  private wakeLock: WakeLockSentinel | null = null;\n\n  acquireLock = async () => {\n    await this.requestWakeLock();\n    document?.addEventListener('visibilitychange', this.visibilityHandler);\n  };\n\n  cleanup = async () => {\n    if (this.wakeLock && !this.wakeLock.released) {\n      try {\n        await this.wakeLock.release();\n        HMSLogger.d(this.TAG, 'Wake lock released');\n      } catch (err) {\n        const error = err as Error;\n        HMSLogger.w(this.TAG, 'Error while releasing wake lock', `name=${error.name}, message=${error.message}`);\n      }\n    }\n    this.wakeLock = null;\n  };\n\n  private visibilityHandler = async () => {\n    if (document?.visibilityState === 'visible' && (!this.wakeLock || this.wakeLock.released)) {\n      HMSLogger.d(this.TAG, 'Re-acquiring wake lock due to visibility change');\n      await this.requestWakeLock();\n    }\n  };\n\n  // Function that attempts to request a screen wake lock.\n  private requestWakeLock = async () => {\n    try {\n      if (!('wakeLock' in navigator)) {\n        HMSLogger.d(this.TAG, 'Wake lock feature not supported');\n        return;\n      }\n      this.wakeLock = await navigator.wakeLock.request('screen');\n      HMSLogger.d(this.TAG, 'Wake lock acquired');\n    } catch (err) {\n      const error = err as Error;\n      HMSLogger.w(this.TAG, 'Error acquiring wake lock', `name=${error.name}, message=${error.message}`);\n    }\n  };\n}\n","import AnalyticsEvent from './AnalyticsEvent';\nimport { HMSAnalyticsLevel } from './AnalyticsEventLevel';\nimport { AnalyticsTransport } from './AnalyticsTransport';\nimport { HTTPAnalyticsTransport } from './HTTPAnalyticsTransport';\nimport { IStore } from '../sdk/store';\nimport { ANALYTICS_BUFFER_SIZE } from '../utils/constants';\nimport HMSLogger from '../utils/logger';\n\nexport class AnalyticsEventsService {\n  private bufferSize = ANALYTICS_BUFFER_SIZE;\n  private readonly TAG = '[AnalyticsEventsService]';\n\n  private transport: AnalyticsTransport | null = null;\n  private pendingEvents: AnalyticsEvent[] = [];\n\n  level: HMSAnalyticsLevel = HMSAnalyticsLevel.INFO;\n\n  constructor(private store: IStore) {}\n\n  setTransport(transport: AnalyticsTransport) {\n    this.transport = transport;\n  }\n\n  reset() {\n    this.transport = null;\n    this.pendingEvents = [];\n  }\n\n  queue(event: AnalyticsEvent) {\n    if (event.level >= this.level) {\n      this.pendingEvents.push(event);\n\n      if (this.pendingEvents.length > this.bufferSize) {\n        const removedEvent = this.pendingEvents.shift();\n        HMSLogger.d(this.TAG, 'Max buffer size reached', 'Removed event to accommodate new events', removedEvent);\n      }\n    }\n    return this;\n  }\n\n  flushFailedClientEvents() {\n    HTTPAnalyticsTransport.flushFailedEvents();\n  }\n\n  flush() {\n    try {\n      while (this.pendingEvents.length > 0) {\n        const event = this.pendingEvents.shift();\n        if (event) {\n          event.metadata.peer.peer_id = this.store.getLocalPeer()?.peerId;\n          event.metadata.userAgent = this.store.getUserAgent();\n          if (this.transport && this.transport.transportProvider.isConnected) {\n            this.transport.sendEvent(event);\n          } else {\n            this.sendClientEventOnHTTP(event);\n          }\n        }\n      }\n    } catch (error) {\n      HMSLogger.w(this.TAG, 'Flush Failed', error);\n    }\n  }\n\n  private sendClientEventOnHTTP(event: AnalyticsEvent) {\n    const room = this.store.getRoom();\n    const localPeer = this.store.getLocalPeer();\n    event.metadata.token = this.store.getConfig()?.authToken;\n    event.metadata.peer = {\n      session_id: room?.sessionId,\n      room_id: room?.id,\n      room_name: room?.name,\n      template_id: room?.templateId,\n      joined_at: room?.joinedAt?.getTime(),\n      session_started_at: room?.startedAt?.getTime(),\n      role: localPeer?.role?.name,\n      user_name: localPeer?.name,\n      user_data: localPeer?.metadata,\n      peer_id: localPeer?.peerId,\n    };\n    HTTPAnalyticsTransport.sendEvent(event);\n  }\n}\n","import { v4 as uuid } from 'uuid';\nimport AnalyticsEventFactory from '../analytics/AnalyticsEventFactory';\nimport { DeviceManager } from '../device-manager';\nimport { ErrorFactory } from '../error/ErrorFactory';\nimport { HMSAction } from '../error/HMSAction';\nimport { EventBus } from '../events/EventBus';\nimport { HMSDeviceChangeEvent, HMSTrackUpdate, HMSUpdateListener } from '../interfaces';\nimport { HMSRemoteAudioTrack } from '../media/tracks';\nimport { HMSRemotePeer } from '../sdk/models/peer';\nimport { IStore } from '../sdk/store';\nimport HMSLogger from '../utils/logger';\nimport { isMobile } from '../utils/support';\nimport { sleep } from '../utils/timer-utils';\n\n/**\n * Following are the errors thrown when autoplay is blocked in different browsers\n * Firefox - DOMException: The play method is not allowed by the user agent or the platform in the current context, possibly because the user denied permission.\n * Safari - NotAllowedError: The request is not allowed by the user agent or the platform in the current context, possibly because the user denied permission.\n * Chrome - DOMException: play() failed because the user didn't interact with the document first.\n * Brave - DOMException: play() can only be initiated by a user gesture.\n */\ntype AudioSinkState = {\n  autoplayFailed?: boolean;\n  initialized: boolean;\n  // this promise will be set for the first track. remaining tracks will be processed once it's know whether\n  // autoplay is allowed or not\n  autoplayCheckPromise?: Promise<void>;\n};\n\nconst INITIAL_STATE: AudioSinkState = {\n  autoplayFailed: undefined,\n  initialized: false,\n  autoplayCheckPromise: undefined,\n};\n\nexport class AudioSinkManager {\n  private audioSink?: HTMLElement;\n  private autoPausedTracks: Set<HMSRemoteAudioTrack> = new Set();\n  private readonly TAG = '[AudioSinkManager]:';\n  private volume = 100;\n  private state = { ...INITIAL_STATE };\n  private listener?: HMSUpdateListener;\n\n  constructor(private store: IStore, private deviceManager: DeviceManager, private eventBus: EventBus) {\n    this.eventBus.audioTrackAdded.subscribe(this.handleTrackAdd);\n    this.eventBus.audioTrackRemoved.subscribe(this.handleTrackRemove);\n    this.eventBus.audioTrackUpdate.subscribe(this.handleTrackUpdate);\n    this.eventBus.deviceChange.subscribe(this.handleAudioDeviceChange);\n  }\n\n  setListener(listener?: HMSUpdateListener) {\n    this.listener = listener;\n  }\n\n  private get outputDevice() {\n    return this.deviceManager.outputDevice;\n  }\n\n  getVolume() {\n    return this.volume;\n  }\n\n  async setVolume(value: number) {\n    await this.store.updateAudioOutputVolume(value);\n    this.volume = value;\n  }\n\n  /**\n   *  This function is to be called only on user interaction when\n   *  autoplay error is received.\n   */\n  async unblockAutoplay() {\n    if (this.autoPausedTracks.size > 0) {\n      this.unpauseAudioTracks();\n    }\n  }\n\n  init(elementId?: string) {\n    if (this.state.initialized || this.audioSink) {\n      return;\n    }\n    this.state.initialized = true;\n    const audioSink = document.createElement('div');\n    audioSink.id = `HMS-SDK-audio-sink-${uuid()}`;\n    const userElement = elementId && document.getElementById(elementId);\n    const audioSinkParent = userElement || document.body;\n    audioSinkParent.append(audioSink);\n\n    this.audioSink = audioSink;\n    HMSLogger.d(this.TAG, 'audio sink created', this.audioSink);\n  }\n\n  cleanup() {\n    this.audioSink?.remove();\n    this.audioSink = undefined;\n    this.eventBus.audioTrackAdded.unsubscribe(this.handleTrackAdd);\n    this.eventBus.audioTrackRemoved.unsubscribe(this.handleTrackRemove);\n    this.eventBus.audioTrackUpdate.unsubscribe(this.handleTrackUpdate);\n    this.eventBus.deviceChange.unsubscribe(this.handleAudioDeviceChange);\n    this.autoPausedTracks = new Set();\n    this.state = { ...INITIAL_STATE };\n  }\n\n  private handleAudioPaused = async (event: any) => {\n    const audioEl = event.target as HTMLAudioElement;\n    //@ts-ignore\n    const track = audioEl.srcObject?.getAudioTracks()[0];\n    if (!track?.enabled) {\n      // No need to play if already disabled\n      return;\n    }\n    // this means the audio paused because of external factors(headset removal)\n    HMSLogger.d(this.TAG, 'Audio Paused', event.target.id);\n    const audioTrack = this.store.getTrackById(event.target.id);\n    if (audioTrack) {\n      if (isMobile()) {\n        // Play after a delay since mobile devices don't call onDevice change event\n        await sleep(500);\n        this.playAudioFor(audioTrack as HMSRemoteAudioTrack);\n      } else {\n        this.autoPausedTracks.add(audioTrack as HMSRemoteAudioTrack);\n      }\n    }\n  };\n\n  private handleTrackUpdate = ({ track }: { track: HMSRemoteAudioTrack; enabled: boolean }) => {\n    HMSLogger.d(this.TAG, 'Track updated', `${track}`);\n  };\n\n  private handleTrackAdd = async ({\n    track,\n    peer,\n    callListener = true,\n  }: {\n    track: HMSRemoteAudioTrack;\n    peer: HMSRemotePeer;\n    callListener?: boolean;\n  }) => {\n    const audioEl = document.createElement('audio');\n    audioEl.style.display = 'none';\n    audioEl.id = track.trackId;\n    audioEl.addEventListener('pause', this.handleAudioPaused);\n\n    audioEl.onerror = async () => {\n      HMSLogger.e(this.TAG, 'error on audio element', audioEl.error);\n      const ex = ErrorFactory.TracksErrors.AudioPlaybackError(\n        `Audio playback error for track - ${track.trackId} code - ${audioEl?.error?.code}`,\n      );\n      this.eventBus.analytics.publish(AnalyticsEventFactory.audioPlaybackError(ex));\n      if (audioEl?.error?.code === MediaError.MEDIA_ERR_DECODE) {\n        this.removeAudioElement(audioEl, track);\n        await sleep(500);\n        await this.handleTrackAdd({ track, peer, callListener: false });\n      }\n    };\n    track.setAudioElement(audioEl);\n    track.setVolume(this.volume);\n    HMSLogger.d(this.TAG, 'Audio track added', `${track}`);\n    this.init(); // call to create sink element if not already created\n    await this.autoSelectAudioOutput();\n    this.audioSink?.append(audioEl);\n    this.outputDevice && (await track.setOutputDevice(this.outputDevice));\n    audioEl.srcObject = new MediaStream([track.nativeTrack]);\n    callListener && this.listener?.onTrackUpdate(HMSTrackUpdate.TRACK_ADDED, track, peer);\n    await this.handleAutoplayError(track);\n  };\n\n  private handleAutoplayError = async (track: HMSRemoteAudioTrack) => {\n    /**\n     * if it's not known whether autoplay will succeed, wait for it to be known\n     */\n    if (this.state.autoplayFailed === undefined) {\n      if (!this.state.autoplayCheckPromise) {\n        // it's the first track, try to play it, that'll tell us whether autoplay is allowed\n        this.state.autoplayCheckPromise = new Promise<void>(resolve => {\n          this.playAudioFor(track).then(resolve);\n        });\n      }\n      // and wait for the result to be known\n      await this.state.autoplayCheckPromise;\n    }\n    /**\n     * Don't play the track if autoplay failed, add to paused list\n     */\n    if (this.state.autoplayFailed) {\n      this.autoPausedTracks.add(track);\n      return;\n    }\n    await this.playAudioFor(track);\n  };\n\n  private handleAudioDeviceChange = (event: HMSDeviceChangeEvent) => {\n    // if there is no selection that means this is an init request. No need to do anything\n    if (event.error || !event.selection || event.type === 'video') {\n      return;\n    }\n    this.unpauseAudioTracks();\n  };\n\n  /**\n   * try to play audio for the passed in track, assume autoplay error happened if play fails\n   * @param track\n   * @private\n   */\n  private async playAudioFor(track: HMSRemoteAudioTrack) {\n    const audioEl = track.getAudioElement();\n    if (!audioEl) {\n      HMSLogger.w(this.TAG, 'No audio element found on track', track.trackId);\n      return;\n    }\n    try {\n      await audioEl.play();\n      this.state.autoplayFailed = false;\n      this.autoPausedTracks.delete(track);\n      HMSLogger.d(this.TAG, 'Played track', `${track}`);\n    } catch (err) {\n      this.autoPausedTracks.add(track);\n      HMSLogger.w(this.TAG, 'Failed to play track', `${track}`, err as Error);\n      const error = err as Error;\n      if (!this.state.autoplayFailed && error.name === 'NotAllowedError') {\n        this.state.autoplayFailed = true;\n        const ex = ErrorFactory.TracksErrors.AutoplayBlocked(HMSAction.AUTOPLAY, '');\n        ex.addNativeError(error);\n        this.eventBus.analytics.publish(AnalyticsEventFactory.autoplayError());\n        this.eventBus.autoplayError.publish(ex);\n      }\n    }\n  }\n\n  private handleTrackRemove = (track: HMSRemoteAudioTrack) => {\n    this.autoPausedTracks.delete(track);\n    const audioEl = document.getElementById(track.trackId) as HTMLAudioElement;\n    if (audioEl) {\n      this.removeAudioElement(audioEl, track);\n    }\n    // Reset autoplay error thrown because if all tracks are removed and a new track is added\n    // Autoplay error is thrown in safari\n    if (this.audioSink && this.audioSink.childElementCount === 0) {\n      this.state.autoplayCheckPromise = undefined;\n      this.state.autoplayFailed = undefined;\n    }\n    HMSLogger.d(this.TAG, 'Audio track removed', `${track}`);\n  };\n\n  private unpauseAudioTracks = async () => {\n    const promises: Promise<void>[] = [];\n    this.autoPausedTracks.forEach(track => {\n      promises.push(this.playAudioFor(track));\n    });\n    // Return after all pending tracks are played\n    await Promise.all(promises);\n  };\n\n  private removeAudioElement = (audioEl: HTMLAudioElement, track: HMSRemoteAudioTrack) => {\n    if (audioEl) {\n      HMSLogger.d(this.TAG, 'removing audio element', `${track}`);\n      audioEl.removeEventListener('pause', this.handleAudioPaused);\n      audioEl.srcObject = null;\n      audioEl.remove();\n      track.setAudioElement(null);\n    }\n  };\n\n  /**\n   * Mweb is not able to play via call channel by default, this is to switch from media channel to call channel\n   */\n  private autoSelectAudioOutput = async () => {\n    if (this.audioSink?.children.length === 0) {\n      const device = this.deviceManager.audioInput?.find(device => device.label.includes('earpiece'));\n      const localAudioTrack = this.store.getLocalPeer()?.audioTrack;\n      if (localAudioTrack && device) {\n        await localAudioTrack.setSettings({ deviceId: device?.deviceId });\n        await localAudioTrack.setSettings({ deviceId: 'default' });\n      }\n    }\n  };\n}\n","import { DeviceStorageManager } from './DeviceStorage';\nimport AnalyticsEventFactory from '../analytics/AnalyticsEventFactory';\nimport { ErrorFactory } from '../error/ErrorFactory';\nimport { HMSException } from '../error/HMSException';\nimport { EventBus } from '../events/EventBus';\nimport { DeviceMap, HMSDeviceChangeEvent, SelectedDevices } from '../interfaces';\nimport { HMSAudioTrackSettingsBuilder, HMSVideoTrackSettingsBuilder } from '../media/settings';\nimport { HMSLocalAudioTrack, HMSLocalTrack, HMSLocalVideoTrack } from '../media/tracks';\nimport { IStore } from '../sdk/store';\nimport HMSLogger from '../utils/logger';\nimport { debounce } from '../utils/timer-utils';\n\ntype DeviceAndGroup = Partial<MediaTrackSettings>;\n\ninterface HMSDeviceManager extends DeviceMap {\n  outputDevice?: MediaDeviceInfo;\n  hasWebcamPermission: boolean;\n  hasMicrophonePermission: boolean;\n}\n\nexport class DeviceManager implements HMSDeviceManager {\n  audioInput: MediaDeviceInfo[] = [];\n  audioOutput: MediaDeviceInfo[] = [];\n  videoInput: MediaDeviceInfo[] = [];\n  outputDevice?: MediaDeviceInfo;\n  // true if user has allowed the permission\n  // false if user has denied the permission or prompt was never shown or ignored\n  // or if the camera/mic is not available in the device\n  hasWebcamPermission = false;\n  hasMicrophonePermission = false;\n\n  private readonly TAG = '[Device Manager]:';\n  private initialized = false;\n  private videoInputChanged = false;\n  private audioInputChanged = false;\n\n  constructor(private store: IStore, private eventBus: EventBus) {\n    const isLocalTrackEnabled = ({ enabled, track }: { enabled: boolean; track: HMSLocalTrack }) =>\n      enabled && track.source === 'regular';\n    this.eventBus.localVideoEnabled.waitFor(isLocalTrackEnabled).then(async () => {\n      await this.enumerateDevices();\n      if (this.videoInputChanged) {\n        this.eventBus.deviceChange.publish({ devices: this.getDevices() } as HMSDeviceChangeEvent);\n      }\n    });\n    this.eventBus.localAudioEnabled.waitFor(isLocalTrackEnabled).then(async () => {\n      await this.enumerateDevices();\n      if (this.audioInputChanged) {\n        this.eventBus.deviceChange.publish({ devices: this.getDevices() } as HMSDeviceChangeEvent);\n      }\n    });\n  }\n\n  updateOutputDevice = async (deviceId?: string) => {\n    const newDevice = this.audioOutput.find(device => device.deviceId === deviceId);\n    if (newDevice) {\n      this.outputDevice = newDevice;\n      await this.store.updateAudioOutputDevice(newDevice);\n      DeviceStorageManager.updateSelection('audioOutput', { deviceId: newDevice.deviceId, groupId: newDevice.groupId });\n    }\n    return newDevice;\n  };\n\n  async init(force = false) {\n    if (this.initialized && !force) {\n      return;\n    }\n    !this.initialized && navigator.mediaDevices.addEventListener('devicechange', this.handleDeviceChange);\n    this.initialized = true;\n    await this.enumerateDevices();\n    this.logDevices('Init');\n    await this.setOutputDevice();\n    this.eventBus.deviceChange.publish({\n      devices: this.getDevices(),\n    } as HMSDeviceChangeEvent);\n    this.eventBus.analytics.publish(\n      AnalyticsEventFactory.deviceChange({\n        selection: this.getCurrentSelection(),\n        type: 'list',\n        devices: this.getDevices(),\n      }),\n    );\n  }\n\n  getDevices(): DeviceMap {\n    return {\n      audioInput: this.audioInput,\n      audioOutput: this.audioOutput,\n      videoInput: this.videoInput,\n    };\n  }\n\n  cleanup() {\n    this.initialized = false;\n    this.audioInput = [];\n    this.audioOutput = [];\n    this.videoInput = [];\n    this.outputDevice = undefined;\n    navigator.mediaDevices.removeEventListener('devicechange', this.handleDeviceChange);\n  }\n\n  getCurrentSelection = (): SelectedDevices => {\n    const localPeer = this.store.getLocalPeer();\n    const audioDevice = this.createIdentifier(localPeer?.audioTrack?.getMediaTrackSettings());\n    const videoDevice = this.createIdentifier(localPeer?.videoTrack?.getMediaTrackSettings());\n    const audioSelection = this.audioInput.find(device => {\n      const id = this.createIdentifier(device);\n      return id === audioDevice;\n    });\n    const videoSelection = this.videoInput.find(device => this.createIdentifier(device) === videoDevice);\n    return {\n      audioInput: audioSelection,\n      videoInput: videoSelection,\n      audioOutput: this.outputDevice,\n    };\n  };\n\n  private createIdentifier(deviceInfo?: DeviceAndGroup) {\n    if (!deviceInfo) {\n      return '';\n    }\n    return `${deviceInfo.deviceId}${deviceInfo.groupId}`;\n  }\n\n  private computeChange = (prevDevices: string[], currentDevices: MediaDeviceInfo[]) => {\n    if (prevDevices.length !== currentDevices.length) {\n      return true;\n    }\n    return currentDevices.some(device => !prevDevices.includes(this.createIdentifier(device)));\n  };\n\n  private enumerateDevices = async () => {\n    try {\n      const devices = await navigator.mediaDevices.enumerateDevices();\n      const prevVideoInput = this.videoInput.map(this.createIdentifier);\n      const prevAudioInput = this.audioInput.map(this.createIdentifier);\n      this.audioInput = [];\n      this.audioOutput = [];\n      this.videoInput = [];\n      devices.forEach(device => {\n        if (device.kind === 'audioinput' && device.label) {\n          this.hasMicrophonePermission = true;\n          this.audioInput.push(device as MediaDeviceInfo);\n        } else if (device.kind === 'audiooutput') {\n          this.audioOutput.push(device);\n        } else if (device.kind === 'videoinput' && device.label) {\n          this.hasWebcamPermission = true;\n          this.videoInput.push(device as MediaDeviceInfo);\n        }\n      });\n      this.videoInputChanged = this.computeChange(prevVideoInput, this.videoInput);\n      this.audioInputChanged = this.computeChange(prevAudioInput, this.audioInput);\n      DeviceStorageManager.setDevices({\n        videoInput: [...this.videoInput],\n        audioInput: [...this.audioInput],\n        audioOutput: [...this.audioOutput],\n      });\n      this.logDevices('Enumerate Devices');\n    } catch (error) {\n      HMSLogger.e(this.TAG, 'Failed enumerating devices', error);\n    }\n  };\n\n  private handleDeviceChange = debounce(async () => {\n    await this.enumerateDevices();\n    this.logDevices('After Device Change');\n    const localPeer = this.store.getLocalPeer();\n    const audioTrack = localPeer?.audioTrack;\n    await this.setOutputDevice(true);\n    if (audioTrack) {\n      await this.handleAudioInputDeviceChange(localPeer?.audioTrack);\n    }\n    await this.handleVideoInputDeviceChange(localPeer?.videoTrack);\n    this.eventBus.analytics.publish(\n      AnalyticsEventFactory.deviceChange({\n        selection: this.getCurrentSelection(),\n        type: 'change',\n        devices: this.getDevices(),\n      }),\n    );\n  }, 500).bind(this);\n\n  /**\n   * Function to get the device after device change\n   * Chrome and Edge provide a default device from which we select the actual device\n   * Firefox and safari give 0th device as system default\n   * @returns {MediaDeviceInfo}\n   */\n  getNewAudioInputDevice() {\n    const localPeer = this.store.getLocalPeer();\n    const audioTrack = localPeer?.audioTrack;\n    const manualSelection = this.audioInput.find(\n      device => device.deviceId === audioTrack?.getManuallySelectedDeviceId(),\n    );\n    if (manualSelection) {\n      return manualSelection;\n    }\n    // if manually selected device is not available, reset on the track\n    audioTrack?.resetManuallySelectedDeviceId();\n    const defaultDevice = this.audioInput.find(device => device.deviceId === 'default');\n    if (defaultDevice) {\n      // Selecting a non-default device so that the deviceId comparision does not give\n      // false positives when device is removed, because the other available device\n      // get's the deviceId as default once this device is removed\n      const nextDevice = this.audioInput.find(device => {\n        return device.deviceId !== 'default' && defaultDevice.label.includes(device.label);\n      });\n      return nextDevice;\n    }\n    return this.audioInput[0];\n  }\n\n  /**\n   * This method is to select the input/output from same group\n   * same group meaning both input/output are of same device\n   * This method might override the default coming from browser and system so as to select options from same\n   * device type. This is required in certain cases where browser's default is not correct.\n   * Algo:\n   * 1. find the non default input device if selected one is default by matching device label\n   * 2. find the corresponding output device which has the same group id or same label\n   * 3. select the previous selected device if nothing was found\n   * 4. select the default one if no matching device was found and previous device doesn't exist anymore\n   * 5. select the first option if there is no default\n   */\n  async setOutputDevice(deviceChange = false) {\n    const inputDevice = this.getNewAudioInputDevice();\n    const prevSelection = this.createIdentifier(this.outputDevice);\n    this.outputDevice = this.getAudioOutputDeviceMatchingInput(inputDevice);\n    if (!this.outputDevice) {\n      // there is no matching device, let's revert back to the prev selected device\n      this.outputDevice = this.audioOutput.find(device => this.createIdentifier(device) === prevSelection);\n      if (!this.outputDevice) {\n        // prev device doesn't exist as well, select default deviceId device if available, otherwise select 0th device\n        this.outputDevice = this.audioOutput.find(device => device.deviceId === 'default') || this.audioOutput[0];\n      }\n    }\n    await this.store.updateAudioOutputDevice(this.outputDevice);\n    // send event only on device change and device is not same as previous\n    if (deviceChange && prevSelection !== this.createIdentifier(this.outputDevice)) {\n      this.eventBus.analytics.publish(\n        AnalyticsEventFactory.deviceChange({\n          selection: { audioOutput: this.outputDevice },\n          devices: this.getDevices(),\n          type: 'audioOutput',\n        }),\n      );\n      this.eventBus.deviceChange.publish({\n        selection: this.outputDevice,\n        type: 'audioOutput',\n        devices: this.getDevices(),\n      } as HMSDeviceChangeEvent);\n    }\n  }\n\n  private handleAudioInputDeviceChange = async (audioTrack?: HMSLocalAudioTrack) => {\n    if (!audioTrack) {\n      HMSLogger.d(this.TAG, 'No Audio track on local peer');\n      return;\n    }\n    // no need to proceed further if input has not changed\n    if (!this.audioInputChanged) {\n      HMSLogger.d(this.TAG, 'No Change in AudioInput Device');\n      return;\n    }\n    const newSelection = this.getNewAudioInputDevice();\n    if (!newSelection || !newSelection.deviceId) {\n      this.eventBus.analytics.publish(\n        AnalyticsEventFactory.deviceChange({\n          selection: { audioInput: newSelection },\n          error: ErrorFactory.TracksErrors.SelectedDeviceMissing('audio'),\n          devices: this.getDevices(),\n          type: 'audioInput',\n        }),\n      );\n\n      HMSLogger.e(this.TAG, 'Audio device not found');\n      return;\n    }\n    const { settings } = audioTrack;\n    const newAudioTrackSettings = new HMSAudioTrackSettingsBuilder()\n      .codec(settings.codec)\n      .maxBitrate(settings.maxBitrate)\n      .deviceId(newSelection.deviceId)\n      .build();\n    try {\n      await audioTrack.setSettings(newAudioTrackSettings, true);\n      this.eventBus.deviceChange.publish({\n        devices: this.getDevices(),\n        selection: newSelection,\n        type: 'audioInput',\n      } as HMSDeviceChangeEvent);\n      this.logDevices('Audio Device Change Success');\n    } catch (error) {\n      HMSLogger.e(this.TAG, '[Audio Device Change]', error);\n      this.eventBus.analytics.publish(\n        AnalyticsEventFactory.deviceChange({\n          selection: { audioInput: newSelection },\n          devices: this.getDevices(),\n          type: 'audioInput',\n          error: error as HMSException,\n        }),\n      );\n      this.eventBus.deviceChange.publish({\n        error,\n        selection: newSelection,\n        type: 'audioInput',\n        devices: this.getDevices(),\n      } as HMSDeviceChangeEvent);\n    }\n  };\n\n  private handleVideoInputDeviceChange = async (videoTrack?: HMSLocalVideoTrack) => {\n    if (!videoTrack) {\n      HMSLogger.d(this.TAG, 'No video track on local peer');\n      return;\n    }\n    // no need to proceed further if input has not changed\n    if (!this.videoInputChanged) {\n      HMSLogger.d(this.TAG, 'No Change in VideoInput Device');\n      return;\n    }\n    const newSelection = this.videoInput[0];\n    if (!newSelection || !newSelection.deviceId) {\n      this.eventBus.analytics.publish(\n        AnalyticsEventFactory.deviceChange({\n          selection: { videoInput: newSelection },\n          error: ErrorFactory.TracksErrors.SelectedDeviceMissing('video'),\n          devices: this.getDevices(),\n          type: 'video',\n        }),\n      );\n      HMSLogger.e(this.TAG, 'Video device not found');\n      return;\n    }\n    const { settings } = videoTrack;\n    const newVideoTrackSettings = new HMSVideoTrackSettingsBuilder()\n      .codec(settings.codec)\n      .maxBitrate(settings.maxBitrate)\n      .maxFramerate(settings.maxFramerate)\n      .setWidth(settings.width)\n      .setHeight(settings.height)\n      .deviceId(newSelection.deviceId)\n      .build();\n    try {\n      await (videoTrack as HMSLocalVideoTrack).setSettings(newVideoTrackSettings, true);\n      // On replace track, enabled will be true. Need to be set to previous state\n      // videoTrack.setEnabled(enabled); // TODO: remove this once verified on qa.\n      this.eventBus.deviceChange.publish({\n        devices: this.getDevices(),\n        selection: newSelection,\n        type: 'video',\n      } as HMSDeviceChangeEvent);\n      this.logDevices('Video Device Change Success');\n    } catch (error) {\n      HMSLogger.e(this.TAG, '[Video Device Change]', error);\n      this.eventBus.analytics.publish(\n        AnalyticsEventFactory.deviceChange({\n          selection: { videoInput: newSelection },\n          devices: this.getDevices(),\n          type: 'video',\n          error: error as HMSException,\n        }),\n      );\n      this.eventBus.deviceChange.publish({\n        error: error as Error,\n        type: 'video',\n        selection: newSelection,\n        devices: this.getDevices(),\n      } as HMSDeviceChangeEvent);\n    }\n  };\n\n  // eslint-disable-next-line complexity\n  private getAudioOutputDeviceMatchingInput(inputDevice?: MediaDeviceInfo) {\n    const blacklist = this.store.getConfig()?.settings?.speakerAutoSelectionBlacklist || [];\n    if (blacklist === 'all' || !inputDevice) {\n      return;\n    }\n\n    const inputLabel = inputDevice.label.toLowerCase() || '';\n    if (blacklist.some(label => inputLabel.includes(label.toLowerCase()))) {\n      return;\n    }\n\n    const matchingLabel = this.audioOutput.find(\n      device => inputDevice.deviceId !== 'default' && device.label === inputDevice.label,\n    );\n\n    if (matchingLabel) {\n      return matchingLabel;\n    }\n\n    const matchingGroupId = this.audioOutput.find(device => device.groupId === inputDevice.groupId);\n\n    // Select the device with matching group only when it is the default device\n    // if a earphone without mic is connected, the above would pick system speakers instead of the earphone\n    if (\n      matchingGroupId &&\n      this.audioOutput[0].deviceId === 'default' &&\n      matchingGroupId.groupId === this.audioOutput[0].groupId\n    ) {\n      return matchingGroupId;\n    }\n\n    return;\n  }\n\n  private logDevices(label = '') {\n    HMSLogger.d(\n      this.TAG,\n      label,\n      JSON.stringify(\n        {\n          videoInput: [...this.videoInput],\n          audioInput: [...this.audioInput],\n          audioOutput: [...this.audioOutput],\n          selected: this.getCurrentSelection(),\n        },\n        null,\n        4,\n      ),\n    );\n  }\n}\n","import { DeviceManager } from './DeviceManager';\nimport { AudioSinkManager } from '../audio-sink-manager';\nimport { HMSAudioContextHandler } from '../utils/media';\n\nexport interface IAudioOutputManager {\n  getDevice(): MediaDeviceInfo | undefined;\n  setDevice(deviceId: string): Promise<MediaDeviceInfo | undefined>;\n  getVolume(): number;\n  setVolume(value: number): void;\n}\n\nexport class AudioOutputManager implements IAudioOutputManager {\n  constructor(private deviceManager: DeviceManager, private audioSinkManager: AudioSinkManager) {}\n\n  getVolume() {\n    return this.audioSinkManager.getVolume();\n  }\n\n  setVolume(value: number) {\n    if (value < 0 || value > 100) {\n      throw Error('Please pass a valid number between 0-100');\n    }\n    this.audioSinkManager.setVolume(value);\n  }\n\n  getDevice() {\n    return this.deviceManager.outputDevice;\n  }\n\n  setDevice(deviceId?: string) {\n    return this.deviceManager.updateOutputDevice(deviceId);\n  }\n\n  async unblockAutoplay() {\n    await this.audioSinkManager.unblockAutoplay();\n    /**\n     * similar to autoplay error when there's no user interaction,\n     * audio context is paused due to which empty audio tracks do not send any data and therefore it doesn't reach SFU.\n     * resume audio context on user interaction to enable empty audio tracks to send data and be forwarded to remote peers\n     */\n    await HMSAudioContextHandler.resumeContext();\n  }\n}\n","import { EventEmitter2 as EventEmitter } from 'eventemitter2';\nimport { HMSInternalEvent } from './HMSInternalEvent';\nimport AnalyticsEvent from '../analytics/AnalyticsEvent';\nimport { HMSException } from '../error/HMSException';\nimport { HMSDeviceChangeEvent, HMSRole } from '../interfaces';\nimport {\n  HMSLocalAudioTrack,\n  HMSLocalVideoTrack,\n  HMSRemoteAudioTrack,\n  HMSRemoteVideoTrack,\n  HMSWebrtcStats,\n} from '../internal';\nimport { PolicyParams } from '../notification-manager/HMSNotifications';\nimport { HMSRemotePeer } from '../sdk/models/peer';\nimport { HMSEvents } from '../utils/constants';\nimport { ITrackAudioLevelUpdate } from '../utils/track-audio-level-monitor';\n\nexport class EventBus {\n  private eventEmitter: EventEmitter = new EventEmitter();\n  readonly deviceChange = new HMSInternalEvent<HMSDeviceChangeEvent>(HMSEvents.DEVICE_CHANGE, this.eventEmitter);\n  readonly localAudioEnabled = new HMSInternalEvent<{ enabled: boolean; track: HMSLocalAudioTrack }>(\n    HMSEvents.LOCAL_AUDIO_ENABLED,\n    this.eventEmitter,\n  );\n  readonly localVideoEnabled = new HMSInternalEvent<{ enabled: boolean; track: HMSLocalVideoTrack }>(\n    HMSEvents.LOCAL_VIDEO_ENABLED,\n    this.eventEmitter,\n  );\n\n  /**\n   * Emitter which processes raw RTC stats from rtcStatsUpdate and calls client callback\n   */\n  readonly statsUpdate = new HMSInternalEvent<HMSWebrtcStats>(HMSEvents.STATS_UPDATE, this.eventEmitter);\n\n  readonly trackDegraded = new HMSInternalEvent<HMSRemoteVideoTrack>(HMSEvents.TRACK_DEGRADED, this.eventEmitter);\n  readonly trackRestored = new HMSInternalEvent<HMSRemoteVideoTrack>(HMSEvents.TRACK_RESTORED, this.eventEmitter);\n\n  /**\n   * Emits audio level updates for audio tracks(used with local track in preview)\n   */\n  readonly trackAudioLevelUpdate = new HMSInternalEvent<ITrackAudioLevelUpdate>(\n    HMSEvents.TRACK_AUDIO_LEVEL_UPDATE,\n    this.eventEmitter,\n  );\n\n  readonly audioPluginFailed = new HMSInternalEvent<HMSException>(HMSEvents.AUDIO_PLUGIN_FAILED, this.eventEmitter);\n\n  readonly localAudioSilence = new HMSInternalEvent<{ track: HMSLocalAudioTrack }>(\n    HMSEvents.LOCAL_AUDIO_SILENCE,\n    this.eventEmitter,\n  );\n\n  readonly analytics = new HMSInternalEvent<AnalyticsEvent>(HMSEvents.ANALYTICS, this.eventEmitter);\n\n  readonly policyChange = new HMSInternalEvent<PolicyParams>(HMSEvents.POLICY_CHANGE, this.eventEmitter);\n\n  readonly localRoleUpdate = new HMSInternalEvent<{ oldRole: HMSRole; newRole: HMSRole }>(\n    HMSEvents.LOCAL_ROLE_UPDATE,\n    this.eventEmitter,\n  );\n\n  readonly audioTrackUpdate = new HMSInternalEvent<{ track: HMSRemoteAudioTrack; enabled: boolean }>(\n    HMSEvents.AUDIO_TRACK_UPDATE,\n    this.eventEmitter,\n  );\n\n  readonly audioTrackAdded = new HMSInternalEvent<{ track: HMSRemoteAudioTrack; peer: HMSRemotePeer }>(\n    HMSEvents.AUDIO_TRACK_ADDED,\n    this.eventEmitter,\n  );\n\n  readonly audioTrackRemoved = new HMSInternalEvent<HMSRemoteAudioTrack>(\n    HMSEvents.AUDIO_TRACK_REMOVED,\n    this.eventEmitter,\n  );\n\n  readonly autoplayError = new HMSInternalEvent<HMSException>(HMSEvents.AUTOPLAY_ERROR, this.eventEmitter);\n\n  readonly leave = new HMSInternalEvent<HMSException | undefined>(HMSEvents.LEAVE, this.eventEmitter);\n}\n","import type { WaitForFilter, WaitForOptions } from 'eventemitter2';\nimport { EventEmitter2 as EventEmitter } from 'eventemitter2';\n\nexport class HMSInternalEvent<T> {\n  constructor(private eventName: string, private eventEmitter: EventEmitter) {}\n\n  publish = (event?: T) => {\n    this.eventEmitter.emit(this.eventName, event);\n  };\n  subscribe = (fn: (event: T) => void | Promise<void>) => {\n    this.eventEmitter.on(this.eventName, fn);\n  };\n  subscribeOnce = (fn: (event: T) => void | Promise<void>) => {\n    this.eventEmitter.once(this.eventName, fn);\n  };\n  unsubscribe = (fn: (event: T) => void | Promise<void>) => {\n    this.eventEmitter.off(this.eventName, fn);\n  };\n  waitFor = (predicate: WaitForFilter) => {\n    return this.eventEmitter.waitFor(this.eventName, {\n      filter: predicate,\n    } as WaitForOptions);\n  };\n  removeAllListeners = () => {\n    this.eventEmitter.removeAllListeners(this.eventName);\n  };\n}\n","import { VideoTrackLayerUpdate } from '../connection/channel-messages';\nimport { HMSRole } from '../interfaces/role';\nimport { HMSLocalTrack } from '../media/tracks';\nimport { HMSTrack, HMSTrackSource } from '../media/tracks/HMSTrack';\nimport { PollInfoParams, PollResult, Track } from '../signal/interfaces';\n\n/**\n * Interfaces for message received from BIZ Signal through Websocket.\n * These messages are handled by NotificationManager\n * which will call the corresponding HMSUpdateListener callbacks.\n */\n\nexport interface ServerError {\n  code: number;\n  message?: string;\n}\n\nexport interface TrackStateNotification {\n  tracks: {\n    [track_id: string]: TrackState;\n  };\n  peer: PeerNotificationInfo;\n}\n\nexport interface OnTrackLayerUpdateNotification {\n  tracks: {\n    [track_id: string]: VideoTrackLayerUpdate;\n  };\n}\n\nexport interface PeerNotificationInfo {\n  peer_id: string;\n  role: string;\n  groups: string[];\n  info: Info;\n}\n\nexport interface Info {\n  name: string;\n  data: string;\n  user_id: string;\n}\n\nexport enum HMSRecordingState {\n  NONE = 'none',\n  INITIALISED = 'initialised',\n  STARTED = 'started',\n  PAUSED = 'paused',\n  RESUMED = 'resumed',\n  STOPPED = 'stopped',\n  FAILED = 'failed',\n}\n\nexport enum HMSStreamingState {\n  NONE = 'none',\n  INITIALISED = 'initialised',\n  STARTED = 'started',\n  STOPPED = 'stopped',\n  FAILED = 'failed',\n}\n\ninterface PluginPermissions {\n  permissions?: {\n    // list of roles\n    admin?: Array<string>;\n    writer?: Array<string>;\n    reader?: Array<string>;\n  };\n}\n\nexport interface PolicyParams {\n  name: string;\n  known_roles: {\n    [role: string]: HMSRole;\n  };\n  plugins: {\n    [plugin in 'whiteboard']?: PluginPermissions;\n  };\n  template_id: string;\n  app_data?: Record<string, string>;\n}\n\n/**\n * This is in a format biz sends/received the track metadata\n */\nexport class TrackState implements Track {\n  mute: boolean;\n  type: 'audio' | 'video';\n  source: HMSTrackSource;\n  description: string;\n  track_id: string;\n  stream_id: string;\n\n  constructor(track: HMSLocalTrack | Track) {\n    this.type = track.type;\n    this.source = track.source || 'regular';\n    this.description = '';\n    if (track instanceof HMSTrack) {\n      this.mute = !track.enabled;\n      this.track_id = track.publishedTrackId!;\n      this.stream_id = track.stream.id;\n    } else {\n      this.mute = track.mute;\n      this.track_id = track.track_id;\n      this.stream_id = track.stream_id;\n    }\n  }\n}\n\nexport interface PeerNotification {\n  peer_id: string;\n  info: Info;\n  role: string;\n  joined_at?: number;\n  tracks: {\n    [track_id: string]: TrackState;\n  };\n  groups: string[];\n  realtime?: boolean;\n  is_from_room_state?: boolean;\n}\n\nexport interface RoomState {\n  name: string;\n  session_id?: string;\n  started_at?: number;\n  recording?: {\n    sfu: {\n      started_at?: number;\n      enabled: boolean;\n      state?: HMSRecordingState;\n    };\n    browser: {\n      started_at?: number;\n      enabled: boolean;\n      state?: HMSRecordingState;\n    };\n    hls: {\n      initialised_at?: number;\n      started_at?: number;\n      enabled: boolean;\n      state?: HMSRecordingState;\n      config?: {\n        hls_vod: boolean;\n        single_file_per_layer: boolean;\n      };\n    };\n  };\n  streaming?: {\n    enabled: boolean;\n    rtmp: { enabled: boolean; started_at?: number; state?: HMSStreamingState };\n    hls: HLSNotification;\n  };\n}\n\nexport interface PeerListNotification {\n  peers: {\n    [peer_id: string]: PeerNotification;\n  };\n  room: RoomState;\n}\n\nexport interface PeriodicRoomState {\n  peer_count: number;\n  room: RoomState;\n  peers?: {\n    [peer_id: string]: PeerNotification;\n  };\n}\n\ninterface Speaker {\n  peer_id: string;\n  track_id: string;\n  level: number;\n}\n\nexport interface SpeakerList {\n  'speaker-list': Speaker[];\n}\n\ninterface ConnectionQuality {\n  peer_id: string;\n  downlink_score: number;\n}\n\nexport interface ConnectionQualityList {\n  peers: ConnectionQuality[];\n}\n\n/**\n * Represents the role change request received from the server\n */\nexport interface RoleChangeRequestParams {\n  requested_by?: string;\n  role: string;\n  token: string;\n}\n\nexport interface TrackUpdateRequestNotification {\n  requested_by?: string;\n  track_id: string;\n  stream_id: string;\n  mute: boolean;\n}\n\nexport interface ChangeTrackMuteStateNotification {\n  requested_by?: string;\n  roles?: string[];\n  type?: 'audio' | 'video';\n  source?: HMSTrackSource;\n  value: boolean;\n}\n\nexport interface PeerLeaveRequestNotification {\n  requested_by?: string;\n  reason: string;\n  room_end: boolean;\n}\n\nexport interface MessageNotification {\n  peer?: {\n    peer_id: string;\n    groups: string[];\n    role: string;\n    info: {\n      name: string;\n      data: any;\n      user_id: string;\n    };\n  };\n  roles?: string[];\n  message_id: string;\n  private: boolean;\n  timestamp: number;\n  info: MessageNotificationInfo;\n}\n\nexport interface SendMessage {\n  info: MessageNotificationInfo;\n  roles?: string[];\n  peer_id?: string;\n}\n\nexport interface MessageNotificationInfo {\n  message: any;\n  type: string;\n}\nexport enum RecordingNotificationType {\n  SFU = 'sfu',\n  BROWSER = 'Browser',\n  HLS = 'HLS',\n}\nexport interface RecordingNotification {\n  type: RecordingNotificationType;\n  initialised_at?: number; // only used for type hls\n  started_at?: number;\n  peer?: PeerNotificationInfo;\n  error?: ServerError;\n  state?: HMSRecordingState;\n  hls_recording?: HLSRecording; // only used for type hls\n}\n\nexport interface RTMPNotification {\n  peer?: PeerNotificationInfo;\n  error?: ServerError;\n  started_at?: number;\n  state?: HMSStreamingState;\n}\n\nexport interface HLSRecording {\n  hls_vod: boolean;\n  single_file_per_layer: boolean;\n}\n\nexport interface HLSNotification {\n  enabled: boolean;\n  variants?: Array<HLSVariantInfo>;\n  error?: ServerError;\n  hls_recording?: HLSRecording;\n}\n\nexport interface HLSVariantInfo {\n  url: string;\n  meeting_url?: string;\n  metadata?: string;\n  started_at?: number;\n  initialised_at?: number;\n  state?: HMSStreamingState;\n}\n\nexport interface MetadataChangeNotification {\n  values: {\n    change_version?: number;\n    updated_by?: string;\n    data: any;\n    key: string;\n    updated_at?: number;\n  }[];\n}\n\nexport interface PollStartNotification {\n  polls: PollInfoParams[];\n}\n\nexport type PollStopNotification = PollStartNotification;\n\nexport interface PollStats extends PollResult {\n  poll_id: string;\n}\nexport interface PollStatsNotification {\n  polls: PollStats[];\n}\n\nexport interface RoomInfo {\n  room_id: string;\n  name: string;\n  description: string;\n  max_size: number;\n  large_room_optimization: boolean;\n}\n\nexport interface SessionInfo {\n  session_id: string;\n  room_id: string;\n  peer_count: number;\n  track_count: number;\n}\n\nexport interface WhiteboardInfo {\n  id: string;\n  title?: string;\n  owner?: string;\n  state?: string;\n  attributes?: Array<{ name: string; value: unknown }>;\n}\n","import { HMSAudioListener, HMSPeerUpdate, HMSSpeaker, HMSUpdateListener } from '../../interfaces';\nimport { HMSAudioTrack } from '../../media/tracks';\nimport { IStore } from '../../sdk/store';\nimport { SpeakerList } from '../HMSNotifications';\n\nexport class ActiveSpeakerManager {\n  constructor(private store: IStore, public listener?: HMSUpdateListener, public audioListener?: HMSAudioListener) {}\n\n  handleActiveSpeakers(speakerList: SpeakerList) {\n    const speakers = speakerList['speaker-list'];\n    const hmsSpeakers: HMSSpeaker[] = speakers.map(speaker => ({\n      audioLevel: speaker.level,\n      peer: this.store.getPeerById(speaker.peer_id)!,\n      track: this.store.getTrackById(speaker.track_id) as HMSAudioTrack,\n    }));\n\n    this.audioListener?.onAudioLevelUpdate(hmsSpeakers);\n    this.store.updateSpeakers(hmsSpeakers);\n    const dominantSpeaker = speakers[0];\n\n    if (dominantSpeaker) {\n      const dominantSpeakerPeer = this.store.getPeerById(dominantSpeaker.peer_id);\n      this.listener?.onPeerUpdate(HMSPeerUpdate.BECAME_DOMINANT_SPEAKER, dominantSpeakerPeer!);\n    } else {\n      this.listener?.onPeerUpdate(HMSPeerUpdate.RESIGNED_DOMINANT_SPEAKER, null);\n    }\n  }\n}\n","import { createRemotePeer } from './utils';\nimport { HMSUpdateListener } from '../../interfaces';\nimport Message from '../../sdk/models/HMSMessage';\nimport { IStore } from '../../sdk/store';\nimport HMSLogger from '../../utils/logger';\nimport { HMSNotificationMethod } from '../HMSNotificationMethod';\nimport { MessageNotification } from '../HMSNotifications';\n\nexport class BroadcastManager {\n  private readonly TAG = '[BroadcastManager]';\n  constructor(private store: IStore, public listener?: HMSUpdateListener) {}\n\n  handleNotification(method: string, notification: any) {\n    if (method !== HMSNotificationMethod.BROADCAST) {\n      return;\n    }\n    this.handleBroadcast(notification);\n  }\n\n  private handleBroadcast(messageNotification: MessageNotification) {\n    const notifPeer = messageNotification.peer;\n    const notifMessage = messageNotification.info;\n    const notifRoles = messageNotification.roles;\n\n    const sender = this.getSender(notifPeer);\n    const recipientPeer = messageNotification.private ? this.store.getLocalPeer() : undefined;\n    const recipientRoles = [];\n\n    if (notifRoles?.length) {\n      const knownRoles = this.store.getKnownRoles();\n      for (const role of notifRoles) {\n        knownRoles[role] && recipientRoles.push(knownRoles[role]);\n      }\n    }\n\n    const hmsMessage = new Message({\n      ...notifMessage,\n      sender,\n      recipientRoles,\n      recipientPeer,\n      time: new Date(messageNotification.timestamp),\n      id: messageNotification.message_id,\n    });\n    HMSLogger.d(this.TAG, `Received Message from sender=${notifPeer?.peer_id}: ${hmsMessage}`);\n    this.listener?.onMessageReceived(hmsMessage);\n  }\n\n  private getSender(notifPeer?: MessageNotification['peer']) {\n    // If sender peerId is available in store, use that peer.\n    let sender = notifPeer ? this.store.getPeerById(notifPeer.peer_id) : undefined;\n    // If not available in store, use peer data from received broadcast message from Biz\n    // notifPeer can be undefined when message is sent via api\n    if (!sender && notifPeer) {\n      sender = createRemotePeer(notifPeer, this.store);\n    }\n    return sender;\n  }\n}\n","import { HMSConnectionQuality, HMSConnectionQualityListener } from '../../interfaces';\nimport { IStore } from '../../sdk/store';\nimport { ConnectionQualityList } from '../HMSNotifications';\n\nexport class ConnectionQualityManager {\n  constructor(private store: IStore, public listener?: HMSConnectionQualityListener) {}\n\n  handleQualityUpdate(qualityList: ConnectionQualityList) {\n    const peers = qualityList.peers;\n    const hmsPeers: HMSConnectionQuality[] = peers.map(peer => {\n      const storePeer = this.store.getPeerById(peer.peer_id);\n      if (storePeer) {\n        storePeer.updateNetworkQuality(peer.downlink_score);\n      }\n      return {\n        peerID: peer.peer_id,\n        downlinkQuality: peer.downlink_score,\n      };\n    });\n    this.listener?.onConnectionQualityUpdate(hmsPeers);\n  }\n}\n","import { createRemotePeer } from './utils';\nimport { VideoTrackLayerUpdate } from '../../connection/channel-messages';\nimport { EventBus } from '../../events/EventBus';\nimport { HMSRemotePeer, HMSTrackUpdate, HMSUpdateListener } from '../../interfaces';\nimport { HMSRemoteAudioTrack, HMSRemoteTrack, HMSRemoteVideoTrack, HMSTrackType } from '../../media/tracks';\nimport { HMSPeer } from '../../sdk/models/peer';\nimport { IStore } from '../../sdk/store';\nimport HMSLogger from '../../utils/logger';\nimport { OnTrackLayerUpdateNotification, TrackState, TrackStateNotification } from '../HMSNotifications';\n\n/**\n * Handles:\n * - Incoming track meta-data from BIZ(signal) to match a track to a peer.\n * - Incoming MediaStreamTracks(wrapped in HMSTracks) from RTCMediaChannel.\n * - Mute/unmute track meta-data updates from BIZ.\n *\n * Since track meta-data and RTC tracks come in asynchronously,\n * we store the track meta-data(TrackState) in SDK Store and tracks temporarily here in tracksToProcess.\n *\n * Once we have both TrackState and track,\n * we add it to peer, send listener.onTrackUpdate and remove it from tracksToProcess.\n *\n * Gotchas:\n * - TRACK_UPDATE comes before TRACK_ADD -> update state, process pending tracks when TRACK_ADD arrives.\n */\nexport class TrackManager {\n  public TAG = '[TrackManager]';\n  private tracksToProcess: Map<string, HMSRemoteTrack> = new Map();\n\n  constructor(public store: IStore, public eventBus: EventBus, public listener?: HMSUpdateListener) {}\n\n  /**\n   * Add event from biz on track-add\n   * @param params TrackStateNotification\n   */\n  handleTrackMetadataAdd(params: TrackStateNotification) {\n    HMSLogger.d(this.TAG, `TRACK_METADATA_ADD`, JSON.stringify(params, null, 2));\n\n    for (const trackId in params.tracks) {\n      const trackInfo = params.tracks[trackId];\n      this.store.setTrackState({\n        peerId: params.peer.peer_id,\n        trackInfo,\n      });\n    }\n    this.processPendingTracks();\n  }\n\n  /**\n   * Sets the tracks to peer and returns the peer\n   */\n  handleTrackAdd = (track: HMSRemoteTrack) => {\n    HMSLogger.d(this.TAG, `ONTRACKADD`, `${track}`);\n    this.tracksToProcess.set(track.trackId, track);\n    this.processPendingTracks();\n  };\n\n  handleTrackRemovedPermanently = (notification: TrackStateNotification) => {\n    HMSLogger.d(this.TAG, `ONTRACKREMOVE`, notification);\n    const trackIds = Object.keys(notification.tracks);\n\n    trackIds.forEach(trackId => {\n      const trackStateEntry = this.store.getTrackState(trackId);\n\n      if (!trackStateEntry) {\n        return;\n      }\n\n      const track = this.store.getTrackById(trackId);\n      if (!track) {\n        HMSLogger.d(this.TAG, 'Track not found in store');\n        return;\n      }\n\n      // emit this event here as peer will already be removed(if left the room) by the time this event is received\n      track.type === HMSTrackType.AUDIO && this.eventBus.audioTrackRemoved.publish(track as HMSRemoteAudioTrack);\n      this.store.removeTrack(track);\n      const hmsPeer = this.store.getPeerById(trackStateEntry.peerId);\n      if (!hmsPeer) {\n        return;\n      }\n      this.removePeerTracks(hmsPeer, track as HMSRemoteTrack);\n      this.listener?.onTrackUpdate(HMSTrackUpdate.TRACK_REMOVED, track, hmsPeer);\n    });\n  };\n\n  /**\n   * Sets the track of corresponding peer to null and returns the peer\n   */\n  handleTrackRemove(track: HMSRemoteTrack, remove = true) {\n    HMSLogger.d(this.TAG, `ONTRACKREMOVE`, `${track}`);\n\n    const trackStateEntry = this.store.getTrackState(track.trackId);\n\n    if (!trackStateEntry) {\n      return;\n    }\n\n    const storeHasTrack = this.store.hasTrack(track);\n    if (!storeHasTrack) {\n      HMSLogger.d(this.TAG, 'Track not found in store');\n      return;\n    }\n\n    // remove tracks only when onDemandTracks flag is false\n    if (remove) {\n      this.store.removeTrack(track);\n      const hmsPeer = this.store.getPeerById(trackStateEntry.peerId);\n      if (!hmsPeer) {\n        return;\n      }\n      this.removePeerTracks(hmsPeer, track);\n      this.listener?.onTrackUpdate(HMSTrackUpdate.TRACK_REMOVED, track, hmsPeer);\n\n      // emit this event here as peer will already be removed(if left the room) by the time this event is received\n      track.type === HMSTrackType.AUDIO && this.eventBus.audioTrackRemoved.publish(track as HMSRemoteAudioTrack);\n    }\n  }\n\n  handleTrackLayerUpdate = (params: OnTrackLayerUpdateNotification) => {\n    for (const trackId in params.tracks) {\n      const trackEntry = params.tracks[trackId];\n      const track = this.store.getTrackById(trackId);\n      if (!track) {\n        continue;\n      }\n\n      const peer = this.store.getPeerByTrackId(trackId)!;\n      if (!peer) {\n        continue;\n      }\n\n      if (track instanceof HMSRemoteVideoTrack) {\n        this.setLayer(track, trackEntry);\n      }\n    }\n  };\n\n  // eslint-disable-next-line complexity\n  handleTrackUpdate = (params: TrackStateNotification, callListener = true) => {\n    let hmsPeer = this.store.getPeerById(params.peer.peer_id);\n    const notifPeer = params.peer;\n    if (!hmsPeer && !notifPeer) {\n      HMSLogger.d(this.TAG, 'Track Update ignored - Peer not added to store');\n      return;\n    }\n    if (!hmsPeer) {\n      hmsPeer = createRemotePeer(notifPeer, this.store);\n      this.store.addPeer(hmsPeer);\n    }\n\n    for (const trackId in params.tracks) {\n      const currentTrackStateInfo = Object.assign({}, this.store.getTrackState(trackId)?.trackInfo);\n\n      const trackEntry = params.tracks[trackId];\n      const track = this.store.getTrackById(trackId);\n\n      this.store.setTrackState({\n        peerId: params.peer.peer_id,\n        trackInfo: { ...currentTrackStateInfo, ...trackEntry },\n      });\n\n      // TRACK_UPDATE came before TRACK_ADD -> update state, process pending tracks when TRACK_ADD arrives.\n      if (!track || this.tracksToProcess.has(trackId)) {\n        this.processTrackInfo(trackEntry, params.peer.peer_id, callListener);\n        this.processPendingTracks();\n      } else {\n        track.setEnabled(!trackEntry.mute);\n        const eventType = this.processTrackUpdate(track as HMSRemoteTrack, currentTrackStateInfo, trackEntry);\n        if (eventType) {\n          this.listener?.onTrackUpdate(eventType, track, hmsPeer);\n        }\n      }\n    }\n  };\n\n  processTrackInfo = (_trackInfo: TrackState, _peerId: string, _callListener?: boolean) => {};\n\n  processPendingTracks = () => {\n    const tracksCopy = new Map(this.tracksToProcess);\n    tracksCopy.forEach(track => {\n      const state = this.store.getTrackState(track.trackId);\n      if (!state) {\n        HMSLogger.d(this.TAG, 'TrackState not added to store', `peerId - ${track.peerId}`, `trackId -${track.trackId}`);\n        return;\n      }\n\n      const hmsPeer = this.store.getPeerById(state.peerId);\n      if (!hmsPeer) {\n        HMSLogger.d(this.TAG, 'Peer not added to store, peerId', state.peerId);\n        return;\n      }\n\n      track.source = state.trackInfo.source;\n      track.peerId = hmsPeer.peerId;\n      // set log identifier to initial name of the peer\n      track.logIdentifier = hmsPeer.name;\n      track.setEnabled(!state.trackInfo.mute);\n      this.addAudioTrack(hmsPeer, track);\n      this.addVideoTrack(hmsPeer, track);\n      /**\n       * Don't call onTrackUpdate for audio elements immediately because the operations(eg: setVolume) performed\n       * on onTrackUpdate can be overriden in AudioSinkManager when audio element is created\n       **/\n      track.type === HMSTrackType.AUDIO\n        ? this.eventBus.audioTrackAdded.publish({ track: track as HMSRemoteAudioTrack, peer: hmsPeer as HMSRemotePeer })\n        : this.listener?.onTrackUpdate(HMSTrackUpdate.TRACK_ADDED, track, hmsPeer);\n      this.tracksToProcess.delete(track.trackId);\n    });\n  };\n\n  private setLayer(track: HMSRemoteVideoTrack, layerUpdate: VideoTrackLayerUpdate) {\n    const peer = this.store.getPeerByTrackId(track.trackId);\n    if (!peer) {\n      return;\n    }\n    const isDegraded = track.setLayerFromServer(layerUpdate);\n    if (isDegraded) {\n      this.listener?.onTrackUpdate(HMSTrackUpdate.TRACK_DEGRADED, track, peer);\n    } else {\n      this.listener?.onTrackUpdate(HMSTrackUpdate.TRACK_RESTORED, track, peer);\n    }\n  }\n\n  removePeerTracks(hmsPeer: HMSPeer, track: HMSRemoteTrack) {\n    const auxiliaryTrackIndex = hmsPeer.auxiliaryTracks.indexOf(track);\n    if (auxiliaryTrackIndex > -1) {\n      hmsPeer.auxiliaryTracks.splice(auxiliaryTrackIndex, 1);\n      HMSLogger.d(this.TAG, 'auxiliary track removed', `${track}`);\n    } else {\n      if (track.type === HMSTrackType.AUDIO && hmsPeer.audioTrack === track) {\n        hmsPeer.audioTrack = undefined;\n        HMSLogger.d(this.TAG, 'audio track removed', `${track}`);\n      } else if (track.type === HMSTrackType.VIDEO && hmsPeer.videoTrack === track) {\n        hmsPeer.videoTrack = undefined;\n        HMSLogger.d(this.TAG, 'video track removed', `${track}`);\n      }\n    }\n  }\n\n  private addAudioTrack(hmsPeer: HMSPeer, track: HMSRemoteTrack) {\n    if (track.type !== HMSTrackType.AUDIO) {\n      return;\n    }\n    if (track.source === 'regular' && (!hmsPeer.audioTrack || hmsPeer.audioTrack?.trackId === track.trackId)) {\n      hmsPeer.audioTrack = track as HMSRemoteAudioTrack;\n    } else {\n      hmsPeer.auxiliaryTracks.push(track);\n    }\n    this.store.addTrack(track);\n    HMSLogger.d(this.TAG, 'audio track added', `${track}`);\n  }\n\n  addVideoTrack(hmsPeer: HMSPeer, track: HMSRemoteTrack) {\n    if (track.type !== HMSTrackType.VIDEO) {\n      return;\n    }\n    const remoteTrack = track as HMSRemoteVideoTrack;\n    const simulcastDefinitions = this.store.getSimulcastDefinitionsForPeer(hmsPeer, remoteTrack.source!);\n    remoteTrack.setSimulcastDefinitons(simulcastDefinitions);\n    if (this.addAsPrimaryVideoTrack(hmsPeer, remoteTrack)) {\n      if (!hmsPeer.videoTrack) {\n        hmsPeer.videoTrack = remoteTrack;\n      } else {\n        (hmsPeer.videoTrack as HMSRemoteVideoTrack).replaceTrack(remoteTrack);\n      }\n      this.store.addTrack(hmsPeer.videoTrack);\n    } else {\n      const index = hmsPeer.auxiliaryTracks.findIndex(track => track.trackId === remoteTrack.trackId);\n      if (index === -1) {\n        hmsPeer.auxiliaryTracks.push(remoteTrack);\n        this.store.addTrack(remoteTrack);\n      } else {\n        (hmsPeer.auxiliaryTracks[index] as HMSRemoteVideoTrack).replaceTrack(remoteTrack);\n        this.store.addTrack(hmsPeer.auxiliaryTracks[index]);\n      }\n    }\n    HMSLogger.d(this.TAG, 'video track added', `${track}`);\n  }\n\n  addAsPrimaryVideoTrack(hmsPeer: HMSPeer, track: HMSRemoteTrack) {\n    return track.source === 'regular' && (!hmsPeer.videoTrack || hmsPeer.videoTrack?.trackId === track.trackId);\n  }\n\n  private processTrackUpdate(track: HMSRemoteTrack, currentTrackState: TrackState, trackState: TrackState) {\n    let eventType;\n    if (currentTrackState.mute !== trackState.mute) {\n      eventType = trackState.mute ? HMSTrackUpdate.TRACK_MUTED : HMSTrackUpdate.TRACK_UNMUTED;\n      track.type === HMSTrackType.AUDIO &&\n        this.eventBus.audioTrackUpdate.publish({ track: track as HMSRemoteAudioTrack, enabled: !trackState.mute });\n    } else if (currentTrackState.description !== trackState.description) {\n      eventType = HMSTrackUpdate.TRACK_DESCRIPTION_CHANGED;\n    }\n    return eventType;\n  }\n}\n","import { TrackManager } from './TrackManager';\nimport { EventBus } from '../../events/EventBus';\nimport { HMSPeer, HMSTrackUpdate, HMSUpdateListener } from '../../interfaces';\nimport { HMSRemoteStream } from '../../media/streams/HMSRemoteStream';\nimport { HMSRemoteTrack, HMSRemoteVideoTrack } from '../../media/tracks';\nimport { LocalTrackManager } from '../../sdk/LocalTrackManager';\nimport { IStore } from '../../sdk/store';\nimport HMSTransport from '../../transport';\nimport HMSLogger from '../../utils/logger';\nimport { isEmptyTrack } from '../../utils/track';\nimport { TrackState, TrackStateNotification } from '../HMSNotifications';\n\nexport class OnDemandTrackManager extends TrackManager {\n  TAG = '[OnDemandTrackManager]';\n\n  constructor(store: IStore, eventBus: EventBus, private transport: HMSTransport, listener?: HMSUpdateListener) {\n    super(store, eventBus, listener);\n  }\n\n  handleTrackMetadataAdd(params: TrackStateNotification) {\n    super.handleTrackMetadataAdd(params);\n    for (const trackId in params.tracks) {\n      if (params.tracks[trackId].type === 'video') {\n        this.processTrackInfo(params.tracks[trackId], params.peer.peer_id);\n      }\n    }\n  }\n\n  handleTrackRemove(track: HMSRemoteTrack) {\n    const isRegularVideo = track.type === 'video' && track.source === 'regular';\n    super.handleTrackRemove(track, !isRegularVideo);\n    if (isRegularVideo) {\n      this.processTrackInfo(\n        {\n          track_id: track.trackId,\n          mute: !track.enabled,\n          type: track.type,\n          source: track.source,\n          stream_id: track.stream.id,\n        } as TrackState,\n        track.peerId!,\n        false,\n      );\n    }\n  }\n\n  /**\n   * Add a blank track for the track received from biz so that the UI can render and show video element\n   * which will trigger the prefer-video-track-state request which results in the actual track being\n   * received from the sfu.\n   * This will also be called when track is removed, as it can be removed when none is sent to sfu to\n   * reduce the overall offer size\n   * @param {TrackState} trackInfo\n   * @param {string} peerId\n   * @param {boolean} callListener\n   * @returns\n   */\n  processTrackInfo = (trackInfo: TrackState, peerId: string, callListener = true) => {\n    if (trackInfo.type !== 'video') {\n      return;\n    }\n    const hmsPeer = this.store.getPeerById(peerId);\n    if (!hmsPeer || !this.isPeerRoleSubscribed(peerId)) {\n      HMSLogger.d(this.TAG, `no peer in store for peerId: ${peerId}`);\n      return;\n    }\n    const remoteStream = new HMSRemoteStream(new MediaStream(), this.transport.getSubscribeConnection()!);\n    const emptyTrack = LocalTrackManager.getEmptyVideoTrack();\n    emptyTrack.enabled = !trackInfo.mute;\n    const track = new HMSRemoteVideoTrack(remoteStream, emptyTrack, trackInfo.source);\n    track.setTrackId(trackInfo.track_id);\n    track.peerId = hmsPeer.peerId;\n    track.logIdentifier = hmsPeer.name;\n    this.addVideoTrack(hmsPeer, track);\n    if (callListener) {\n      this.listener?.onTrackUpdate(HMSTrackUpdate.TRACK_ADDED, hmsPeer.videoTrack!, hmsPeer);\n    }\n  };\n\n  addAsPrimaryVideoTrack(hmsPeer: HMSPeer, track: HMSRemoteTrack) {\n    if (track.source !== 'regular') {\n      return false;\n    }\n    if (!hmsPeer.videoTrack) {\n      return true;\n    }\n    if (hmsPeer.videoTrack.trackId === track.trackId) {\n      return true;\n    }\n    return hmsPeer.videoTrack.enabled && isEmptyTrack(hmsPeer.videoTrack.nativeTrack);\n  }\n\n  private isPeerRoleSubscribed(peerId?: string) {\n    if (!peerId) {\n      return true;\n    }\n    const localPeer = this.store.getLocalPeer();\n    const peer = this.store.getPeerById(peerId);\n    return peer && localPeer?.role?.subscribeParams?.subscribeToRoles?.includes(peer.role?.name!);\n  }\n}\n","import { PeerManager } from './PeerManager';\nimport { TrackManager } from './TrackManager';\nimport { HMSUpdateListener } from '../..';\nimport { HMSTrackUpdate } from '../../interfaces';\nimport { HMSPeer } from '../../sdk/models/peer';\nimport { IStore } from '../../sdk/store';\nimport HMSLogger from '../../utils/logger';\nimport { HMSNotificationMethod } from '../HMSNotificationMethod';\nimport { PeerListNotification, PeerNotification, PeriodicRoomState } from '../HMSNotifications';\n\n/**\n * Handles:\n * - Initial Peer List - get peer and track meta-data for peers who are already in the room when you join\n * - Reconnect Peer List - Handle peer and track changes in the room missed out due to reconnection\n *\n * Cases to handle in reconnect peer list:\n * - Add additional peers as peer join\n * - Remove missing peers as peer leave\n * - For existing peers:\n *    - Add new tracks as track add\n *    - Remove missing tracks as track remove\n *    - Track state change(enabled) as track update\n */\nexport class PeerListManager {\n  private readonly TAG = '[PeerListManager]';\n  constructor(\n    private store: IStore,\n    private peerManager: PeerManager,\n    private trackManager: TrackManager,\n    public listener?: HMSUpdateListener,\n  ) {}\n\n  handleNotification(method: string, notification: any, isReconnecting: boolean) {\n    if (method === HMSNotificationMethod.PEER_LIST) {\n      const peerList = notification as PeerListNotification;\n      if (isReconnecting) {\n        HMSLogger.d(this.TAG, `RECONNECT_PEER_LIST event`, JSON.stringify(peerList, null, 2));\n        this.handleReconnectPeerList(peerList);\n      } else {\n        // TODO: Don't call initial peerlist if atleast 1room state had happen\n        HMSLogger.d(this.TAG, `PEER_LIST event`, JSON.stringify(peerList, null, 2));\n        this.handleInitialPeerList(peerList);\n      }\n    } else if (method === HMSNotificationMethod.ROOM_STATE) {\n      const roomState = notification as PeriodicRoomState;\n      this.handlePreviewRoomState(roomState);\n    }\n  }\n\n  private handleInitialPeerList = (peerList: PeerListNotification) => {\n    const peers = Object.values(peerList.peers);\n    this.peerManager.handlePeerList(peers);\n  };\n\n  private handleReconnectPeerList = (peerList: PeerListNotification) => {\n    this.handleRepeatedPeerList(peerList.peers);\n  };\n\n  private handlePreviewRoomState = (roomState: PeriodicRoomState) => {\n    if (!this.store.hasRoleDetailsArrived()) {\n      // we can't process the peers yet we don't know enough about them(role info)\n      return;\n    }\n    const roomPeers = roomState.peers;\n    if (roomPeers === null || roomPeers === undefined) {\n      // in this case, room state doesn't say anything about the peers,\n      // there can be optimisations in place to not send this field when it's unchanged from previously sent value.\n      // If there are no peers either roomState.peers will be empty object\n      // or peer_count will be 0(handled below)\n      if (roomState.peer_count === 0) {\n        this.handleRepeatedPeerList({});\n      }\n      return;\n    }\n    // we don't get tracks inside the peer object in room state, we're adding\n    // an empty value here so rest of the code flow can ignore this change, the below\n    // can be changed when tracks will be sent as a separate object in future\n    Object.keys(roomPeers).forEach(peer => {\n      roomPeers[peer].tracks = {};\n      roomPeers[peer].is_from_room_state = true;\n    });\n    this.handleRepeatedPeerList(roomPeers);\n  };\n\n  private handleRepeatedPeerList = (peersMap: Record<string, PeerNotification>) => {\n    const currentPeerList = this.store.getRemotePeers();\n    const peers = Object.values(peersMap);\n    const peersToRemove = currentPeerList.filter(hmsPeer => !peersMap[hmsPeer.peerId]);\n    if (peersToRemove.length > 0) {\n      HMSLogger.d(this.TAG, `${peersToRemove}`);\n    }\n\n    // Send peer-leave updates to all the missing peers\n    peersToRemove.forEach(peer => {\n      const peerNotification: PeerNotification = {\n        peer_id: peer.peerId,\n        role: peer.role?.name || '',\n        info: {\n          name: peer.name,\n          data: peer.metadata || '',\n          user_id: peer.customerUserId || '',\n        },\n        tracks: {},\n        groups: [],\n        realtime: peer.realtime,\n      };\n\n      this.peerManager.handlePeerLeave(peerNotification);\n    });\n\n    const peerList: PeerNotification[] = [];\n    // Check for any tracks which are added/removed\n    peers.forEach(newPeerNotification => {\n      const oldPeer = this.store.getPeerById(newPeerNotification.peer_id);\n      const newPeerTrackStates = Object.values(newPeerNotification.tracks);\n\n      if (oldPeer) {\n        // Peer already present in room, we take diff between the tracks\n        const tracks = this.store.getPeerTracks(oldPeer.peerId);\n\n        // Remove all the tracks which are not present in the peer.tracks\n        tracks.forEach(track => {\n          if (!newPeerNotification.tracks[track.trackId]) {\n            this.removePeerTrack(oldPeer, track.trackId);\n            this.listener?.onTrackUpdate(HMSTrackUpdate.TRACK_REMOVED, track, oldPeer);\n          }\n        });\n\n        // Add track-metadata for all the new tracks\n        newPeerTrackStates.forEach(trackData => {\n          if (!this.store.getTrackById(trackData.track_id)) {\n            // NOTE: We assume that, once the connection is re-established,\n            //  transport layer will send a native onTrackAdd\n            this.store.setTrackState({\n              peerId: oldPeer.peerId,\n              trackInfo: trackData,\n            });\n          }\n        });\n\n        // Handle RTC track add and track state change.\n        this.trackManager.handleTrackUpdate(\n          {\n            peer: newPeerNotification,\n            tracks: newPeerNotification.tracks,\n          },\n          false,\n        );\n\n        // Update peer's role locally, new role is received from the reconnect peer-list\n        this.peerManager.handlePeerUpdate(newPeerNotification);\n        peerList.push(newPeerNotification);\n      } else {\n        // New peer joined while reconnecting\n        peerList.push(newPeerNotification);\n      }\n    });\n    if (peerList.length > 0) {\n      this.peerManager.handlePeerList(peerList);\n    }\n  };\n\n  private removePeerTrack(peer: HMSPeer, trackId: string) {\n    HMSLogger.d(this.TAG, `removing track - ${trackId} from ${peer}`);\n    if (peer.audioTrack?.trackId === trackId) {\n      peer.audioTrack = undefined;\n    } else if (peer.videoTrack?.trackId === trackId) {\n      peer.videoTrack = undefined;\n    } else {\n      const trackIndex = peer.auxiliaryTracks.findIndex(track => track.trackId === trackId);\n      trackIndex >= 0 && peer.auxiliaryTracks.splice(trackIndex, 1);\n    }\n  }\n}\n","export const convertDateNumToDate = (dateNum?: number): Date | undefined => {\n  return dateNum ? new Date(dateNum) : undefined;\n};\n","import { TrackManager } from './TrackManager';\nimport { createRemotePeer } from './utils';\nimport { HMSPeerUpdate, HMSTrackUpdate, HMSUpdateListener } from '../../interfaces';\nimport { HMSRemoteVideoTrack } from '../../media/tracks';\nimport { HMSPeer, HMSRemotePeer } from '../../sdk/models/peer';\nimport { IStore } from '../../sdk/store';\nimport { HAND_RAISE_GROUP_NAME } from '../../utils/constants';\nimport { convertDateNumToDate } from '../../utils/date';\nimport HMSLogger from '../../utils/logger';\nimport { HMSNotificationMethod } from '../HMSNotificationMethod';\nimport { PeerNotification } from '../HMSNotifications';\n\n/**\n * Handles:\n * - New peer join\n * - Peer Leave\n * - Role update for peer\n *\n * Notes:\n * - Peer join comes with track meta-data,\n * we add it to the store and call TrackManager to process it when RTC Track comes in.\n */\nexport class PeerManager {\n  private readonly TAG = '[PeerManager]';\n  constructor(private store: IStore, private trackManager: TrackManager, public listener?: HMSUpdateListener) {}\n\n  handleNotification(method: string, notification: any) {\n    switch (method) {\n      case HMSNotificationMethod.PEER_JOIN: {\n        const peer = notification as PeerNotification;\n        this.handlePeerJoin(peer);\n        break;\n      }\n\n      case HMSNotificationMethod.PEER_LEAVE: {\n        const peer = notification as PeerNotification;\n        this.handlePeerLeave(peer);\n        break;\n      }\n      case HMSNotificationMethod.PEER_UPDATE:\n        this.handlePeerUpdate(notification as PeerNotification);\n        break;\n      default:\n        break;\n    }\n  }\n\n  handlePeerList = (peers: PeerNotification[]) => {\n    if (peers.length === 0) {\n      this.listener?.onPeerUpdate(HMSPeerUpdate.PEER_LIST, []);\n      return;\n    }\n    const hmsPeers: HMSRemotePeer[] = [];\n    const newPeers = new Set(peers.map(peer => peer.peer_id));\n    this.store.getRemotePeers().forEach(({ peerId, fromRoomState }) => {\n      /**\n       * Remove only if the peer join happened from preview roomstate update. This will prevent the peer joined\n       * from peer-join event post join from being removed from the store.\n       */\n      if (!newPeers.has(peerId) && fromRoomState) {\n        this.store.removePeer(peerId);\n      }\n    });\n    for (const peer of peers) {\n      hmsPeers.push(this.makePeer(peer));\n    }\n    this.listener?.onPeerUpdate(HMSPeerUpdate.PEER_LIST, hmsPeers);\n    this.trackManager.processPendingTracks();\n  };\n\n  handlePeerJoin = (peer: PeerNotification) => {\n    const hmsPeer = this.makePeer(peer);\n\n    this.listener?.onPeerUpdate(HMSPeerUpdate.PEER_JOINED, hmsPeer);\n    this.trackManager.processPendingTracks();\n  };\n\n  handlePeerLeave = (peer: PeerNotification) => {\n    const hmsPeer = this.store.getPeerById(peer.peer_id);\n    this.store.removePeer(peer.peer_id);\n    HMSLogger.d(this.TAG, `PEER_LEAVE`, peer.peer_id, `remainingPeers=${this.store.getPeers().length}`);\n\n    if (!hmsPeer) {\n      return;\n    }\n\n    if (hmsPeer.audioTrack) {\n      this.listener?.onTrackUpdate(HMSTrackUpdate.TRACK_REMOVED, hmsPeer.audioTrack, hmsPeer);\n    }\n\n    if (hmsPeer.videoTrack) {\n      this.listener?.onTrackUpdate(HMSTrackUpdate.TRACK_REMOVED, hmsPeer.videoTrack, hmsPeer);\n    }\n\n    hmsPeer.auxiliaryTracks?.forEach(track => {\n      this.listener?.onTrackUpdate(HMSTrackUpdate.TRACK_REMOVED, track, hmsPeer);\n    });\n\n    this.listener?.onPeerUpdate(HMSPeerUpdate.PEER_LEFT, hmsPeer);\n  };\n\n  // eslint-disable-next-line complexity\n  handlePeerUpdate(notification: PeerNotification) {\n    let peer = this.store.getPeerById(notification.peer_id);\n    if (!peer && notification.realtime) {\n      // create peer if not already created in store\n      peer = this.makePeer(notification);\n      this.listener?.onPeerUpdate(\n        peer.isHandRaised ? HMSPeerUpdate.HAND_RAISE_CHANGED : HMSPeerUpdate.PEER_ADDED,\n        peer,\n      );\n      return;\n    }\n\n    // if peer is present but not realtime now, remove it from store\n    if (peer && !peer.isLocal && !notification.realtime) {\n      this.store.removePeer(peer.peerId);\n      this.listener?.onPeerUpdate(HMSPeerUpdate.PEER_REMOVED, peer);\n      return;\n    }\n\n    if (!peer) {\n      HMSLogger.d(this.TAG, `peer ${notification.peer_id} not found`);\n      return;\n    }\n\n    if (peer.role && peer.role.name !== notification.role) {\n      const newRole = this.store.getPolicyForRole(notification.role);\n      peer.updateRole(newRole);\n      this.updateSimulcastLayersForPeer(peer);\n      this.listener?.onPeerUpdate(HMSPeerUpdate.ROLE_UPDATED, peer);\n    }\n    const wasHandRaised = peer.isHandRaised;\n    peer.updateGroups(notification.groups);\n    const isHandRaised = notification.groups?.includes(HAND_RAISE_GROUP_NAME);\n    if (wasHandRaised !== isHandRaised) {\n      this.listener?.onPeerUpdate(HMSPeerUpdate.HAND_RAISE_CHANGED, peer);\n    }\n    this.handlePeerInfoUpdate({ peer, ...notification.info });\n  }\n\n  handlePeerInfoUpdate({ peer, name, data }: { peer?: HMSPeer; name?: string; data?: string }) {\n    if (!peer) {\n      return;\n    }\n    if (name && peer.name !== name) {\n      peer.updateName(name);\n      this.listener?.onPeerUpdate(HMSPeerUpdate.NAME_UPDATED, peer);\n    }\n    if (data && peer.metadata !== data) {\n      peer.updateMetadata(data);\n      this.listener?.onPeerUpdate(HMSPeerUpdate.METADATA_UPDATED, peer);\n    }\n  }\n\n  private makePeer(peer: PeerNotification) {\n    let hmsPeer = this.store.getPeerById(peer.peer_id) as HMSRemotePeer;\n    if (!hmsPeer) {\n      hmsPeer = createRemotePeer(peer, this.store);\n      hmsPeer.realtime = peer.realtime;\n      hmsPeer.joinedAt = convertDateNumToDate(peer.joined_at);\n      hmsPeer.fromRoomState = !!peer.is_from_room_state;\n      this.store.addPeer(hmsPeer);\n      HMSLogger.d(this.TAG, `adding to the peerList`, `${hmsPeer}`);\n    }\n\n    for (const trackId in peer.tracks) {\n      const trackInfo = peer.tracks[trackId];\n      this.store.setTrackState({\n        peerId: peer.peer_id,\n        trackInfo,\n      });\n      if (trackInfo.type === 'video') {\n        this.trackManager.processTrackInfo(trackInfo, peer.peer_id, false);\n      }\n    }\n    return hmsPeer;\n  }\n\n  private updateSimulcastLayersForPeer(peer: HMSPeer) {\n    this.store.getPeerTracks(peer.peerId).forEach(track => {\n      if (track.type === 'video' && ['regular', 'screen'].includes(track.source!)) {\n        const remoteTrack = track as HMSRemoteVideoTrack;\n        const simulcastDefinitions = this.store.getSimulcastDefinitionsForPeer(peer, remoteTrack.source!);\n        remoteTrack.setSimulcastDefinitons(simulcastDefinitions);\n      }\n    });\n  }\n}\n","import { EventBus } from '../../events/EventBus';\nimport { IStore } from '../../sdk/store';\nimport HMSLogger from '../../utils/logger';\nimport { PolicyParams } from '../HMSNotifications';\n\n/**\n * Handles:\n * - Set policy with publishParams, simulcast layers to store\n * - Emit 'local-peer-role-update' to trigger RoleChangeManager to publish/unpublish local tracks\n * - Emit 'policy-change' to finish preview before calling listener.onPreview\n */\nexport class PolicyChangeManager {\n  constructor(private store: IStore, private eventBus: EventBus) {}\n\n  handlePolicyChange(params: PolicyParams) {\n    const localPeer = this.store.getLocalPeer();\n\n    if (localPeer && !localPeer.role) {\n      const newRole = params.known_roles[params.name];\n      localPeer.updateRole(newRole);\n    }\n\n    this.store.setKnownRoles(params);\n    const room = this.store.getRoom();\n    if (room) {\n      room.templateId = params.template_id;\n    } else {\n      HMSLogger.w('[PolicyChangeManager]', 'on policy change - room not present');\n    }\n    // handle when role is not present in known_roles\n    // const publishParams = params.known_roles[params.name]?.publishParams;\n    // this.store.setPublishParams(publishParams);\n\n    this.updateLocalPeerRole(params);\n    this.eventBus.policyChange.publish(params);\n  }\n\n  private updateLocalPeerRole(params: PolicyParams) {\n    const localPeer = this.store.getLocalPeer();\n    if (localPeer?.role && localPeer.role.name !== params.name) {\n      const newRole = this.store.getPolicyForRole(params.name);\n      const oldRole = localPeer.role;\n      localPeer.updateRole(newRole);\n      if (newRole.name === localPeer.asRole?.name) {\n        delete localPeer.asRole;\n      }\n      this.eventBus.localRoleUpdate.publish({ oldRole, newRole });\n    }\n  }\n}\n","import { HMSWhiteboard, InteractivityListener } from '../../interfaces';\nimport { HMSWhiteboardInteractivityCenter } from '../../interfaces/session-store/interactivity-center';\nimport { IStore } from '../../sdk/store';\nimport { InitFlags } from '../../signal/init/models';\nimport { HMSWhiteboardCreateOptions } from '../../signal/interfaces';\nimport HMSTransport from '../../transport';\nimport HMSLogger from '../../utils/logger';\n\nexport class WhiteboardInteractivityCenter implements HMSWhiteboardInteractivityCenter {\n  private TAG = '[HMSWhiteboardInteractivityCenter]';\n  constructor(\n    private readonly transport: HMSTransport,\n    private store: IStore,\n    private listener?: InteractivityListener,\n  ) {}\n\n  // @TODO: remove when whiteboard released for general audience\n  get isEnabled() {\n    return this.transport.isFlagEnabled(InitFlags.FLAG_WHITEBOARD_ENABLED);\n  }\n\n  async open(createOptions?: HMSWhiteboardCreateOptions) {\n    if (!this.isEnabled) {\n      return HMSLogger.w(this.TAG, 'Whiteboard is not enabled for customer');\n    }\n    const prevWhiteboard = this.store.getWhiteboard(createOptions?.id);\n    let id = prevWhiteboard?.id;\n\n    if (!prevWhiteboard) {\n      const response = await this.transport.createWhiteboard(this.getCreateOptionsWithDefaults(createOptions));\n      id = response.id;\n    }\n    if (!id) {\n      throw new Error(`Whiteboard ID: ${id} not found`);\n    }\n\n    const response = await this.transport.getWhiteboard({ id });\n    const whiteboard: HMSWhiteboard = {\n      ...prevWhiteboard,\n      title: createOptions?.title,\n      attributes: createOptions?.attributes,\n      id: response.id,\n      token: response.token,\n      addr: response.addr,\n      owner: response.owner,\n      permissions: response.permissions || [],\n      open: true,\n    };\n\n    this.store.setWhiteboard(whiteboard);\n    this.listener?.onWhiteboardUpdate(whiteboard);\n  }\n\n  async close(id?: string) {\n    if (!this.isEnabled) {\n      return HMSLogger.w(this.TAG, 'Whiteboard is not enabled for customer');\n    }\n\n    const prevWhiteboard = this.store.getWhiteboard(id);\n    if (!prevWhiteboard) {\n      throw new Error(`Whiteboard ID: ${id} not found`);\n    }\n    const whiteboard: HMSWhiteboard = { id: prevWhiteboard.id, title: prevWhiteboard.title, open: false };\n\n    this.store.setWhiteboard(whiteboard);\n    this.listener?.onWhiteboardUpdate(whiteboard);\n  }\n\n  setListener(listener?: InteractivityListener) {\n    this.listener = listener;\n  }\n\n  private getCreateOptionsWithDefaults(createOptions?: HMSWhiteboardCreateOptions): HMSWhiteboardCreateOptions {\n    const roles = Object.values(this.store.getKnownRoles());\n    const reader: Array<string> = [];\n    const writer: Array<string> = [];\n    const admin: Array<string> = [];\n\n    roles.forEach(role => {\n      if (role.permissions.whiteboard?.includes('read')) {\n        reader.push(role.name);\n      }\n      if (role.permissions.whiteboard?.includes('write')) {\n        writer.push(role.name);\n      }\n      if (role.permissions.whiteboard?.includes('admin')) {\n        admin.push(role.name);\n      }\n    });\n\n    return {\n      title: createOptions?.title || `${this.store.getRoom()?.id} Whiteboard`,\n      reader: createOptions?.reader || reader,\n      writer: createOptions?.writer || writer,\n      admin: createOptions?.admin || admin,\n    };\n  }\n}\n","import { WhiteboardInteractivityCenter } from './HMSWhiteboardCenter';\nimport {\n  HMSInteractivityCenter,\n  HMSPollQuestionCreateParams,\n  HMSPollsUpdate,\n  InteractivityListener,\n} from '../../interfaces';\nimport {\n  HMSPoll,\n  HMSPollCreateParams,\n  HMSPollQuestionAnswer,\n  HMSPollQuestionOption,\n  HMSPollQuestionResponse,\n  HMSPollQuestionResponseCreateParams,\n  HMSPollQuestionType,\n  HMSPollStates,\n  HMSPollUserTrackingMode,\n  HMSQuizLeaderboardResponse,\n} from '../../interfaces/session-store/polls';\nimport { IStore } from '../../sdk/store';\nimport { PollInfoParams, PollQuestionParams, PollResponseParams } from '../../signal/interfaces';\nimport HMSTransport from '../../transport';\nimport { convertDateNumToDate } from '../../utils/date';\n\nexport class InteractivityCenter implements HMSInteractivityCenter {\n  whiteboard: WhiteboardInteractivityCenter;\n  constructor(private transport: HMSTransport, private store: IStore, private listener?: InteractivityListener) {\n    this.whiteboard = new WhiteboardInteractivityCenter(transport, store, listener);\n  }\n\n  setListener(listener?: InteractivityListener) {\n    this.listener = listener;\n    this.whiteboard.setListener(listener);\n  }\n\n  async createPoll(pollParams: HMSPollCreateParams) {\n    const HMS_USER_TRACKING_MODE_MAP: Record<HMSPollUserTrackingMode, string> = {\n      customerID: 'userid',\n      peerID: 'peerid',\n      userName: 'username',\n    };\n\n    const { poll_id: serverPollID } = await this.transport.setPollInfo({\n      ...pollParams,\n      mode: pollParams.mode ? HMS_USER_TRACKING_MODE_MAP[pollParams.mode] : undefined,\n      poll_id: pollParams.id,\n      vote: pollParams.rolesThatCanVote,\n      responses: pollParams.rolesThatCanViewResponses,\n    });\n\n    if (!pollParams.id) {\n      pollParams.id = serverPollID;\n    }\n\n    if (Array.isArray(pollParams.questions)) {\n      await this.addQuestionsToPoll(pollParams.id, pollParams.questions);\n    }\n\n    const questions = await this.transport.getPollQuestions({ poll_id: pollParams.id, index: 0, count: 50 });\n\n    const poll = createHMSPollFromPollParams({\n      ...pollParams,\n      poll_id: pollParams.id,\n      state: 'created',\n      created_by: this.store.getLocalPeer()?.peerId,\n    });\n\n    poll.questions = questions.questions.map(({ question, options, answer }) => ({ ...question, options, answer }));\n\n    this.listener?.onPollsUpdate(HMSPollsUpdate.POLL_CREATED, [poll]);\n  }\n\n  async startPoll(poll: string | HMSPollCreateParams): Promise<void> {\n    if (typeof poll === 'string') {\n      await this.transport.startPoll({ poll_id: poll });\n    } else {\n      await this.createPoll(poll);\n      await this.transport.startPoll({ poll_id: poll.id });\n    }\n  }\n\n  async addQuestionsToPoll(pollID: string, questions: HMSPollQuestionCreateParams[]): Promise<void> {\n    if (questions.length > 0) {\n      await this.transport.setPollQuestions({\n        poll_id: pollID,\n        questions: questions.map((question, index) => this.createQuestionSetParams(question, index)),\n      });\n    }\n  }\n\n  async stopPoll(pollID: string): Promise<void> {\n    await this.transport.stopPoll({ poll_id: pollID });\n  }\n\n  async addResponsesToPoll(pollID: string, responses: HMSPollQuestionResponseCreateParams[]) {\n    const poll = this.store.getPoll(pollID);\n    if (!poll) {\n      throw new Error('Invalid poll ID - Poll not found');\n    }\n    const responsesParams: PollResponseParams[] = responses.map(response => {\n      const question = this.getQuestionInPoll(poll, response.questionIndex);\n      if (question.type === HMSPollQuestionType.SINGLE_CHOICE) {\n        response.option = response.option || response.options?.[0] || -1;\n        delete response.text;\n        delete response.options;\n      } else if (question.type === HMSPollQuestionType.MULTIPLE_CHOICE) {\n        response.options?.sort();\n        delete response.text;\n        delete response.option;\n      } else {\n        delete response.option;\n        delete response.options;\n      }\n\n      if (response.skipped) {\n        delete response.option;\n        delete response.options;\n        delete response.text;\n      }\n\n      return { duration: 0, type: question.type, question: response.questionIndex, ...response };\n    });\n\n    await this.transport.setPollResponses({ poll_id: pollID, responses: responsesParams });\n  }\n\n  async getPolls(): Promise<HMSPoll[]> {\n    const pollsList = await this.transport.getPollsList({ count: 50 });\n    const polls: HMSPoll[] = [];\n    for (const pollParams of pollsList.polls) {\n      const questions = await this.transport.getPollQuestions({ poll_id: pollParams.poll_id, index: 0, count: 50 });\n      const poll = createHMSPollFromPollParams(pollParams);\n      poll.questions = questions.questions.map(({ question, options, answer }) => ({ ...question, options, answer }));\n\n      polls.push(poll);\n      this.store.setPoll(poll);\n    }\n\n    return polls;\n  }\n\n  getResponses(_pollID: string): Promise<HMSPollQuestionResponse[]> {\n    throw new Error('Method not implemented.');\n  }\n\n  private createQuestionSetParams(questionParams: HMSPollQuestionCreateParams, index: number): PollQuestionParams {\n    const question: PollQuestionParams['question'] = { ...questionParams, index: index + 1 };\n    let options: HMSPollQuestionOption[] | undefined;\n    const answer: HMSPollQuestionAnswer = questionParams.answer || { hidden: false };\n    if (\n      Array.isArray(questionParams.options) &&\n      [HMSPollQuestionType.SINGLE_CHOICE, HMSPollQuestionType.MULTIPLE_CHOICE].includes(questionParams.type)\n    ) {\n      options = questionParams.options?.map((option, index) => ({\n        index: index + 1,\n        text: option.text,\n        weight: option.weight,\n      }));\n\n      delete answer?.text;\n      if (questionParams.type === HMSPollQuestionType.SINGLE_CHOICE) {\n        answer.option = questionParams.options.findIndex(option => option.isCorrectAnswer) + 1 || undefined;\n      } else {\n        answer.options = questionParams.options\n          .map((option, index) => (option.isCorrectAnswer ? index + 1 : undefined))\n          .filter((val): val is number => !!val);\n      }\n    } else {\n      delete answer?.options;\n      delete answer?.option;\n    }\n\n    return { question, options, answer };\n  }\n\n  private getQuestionInPoll(poll: HMSPoll, questionIndex: number) {\n    const question = poll?.questions?.find(question => question.index === questionIndex);\n    if (!question) {\n      throw new Error('Invalid question index - Question not found in poll');\n    }\n\n    return question;\n  }\n\n  async fetchLeaderboard(poll: HMSPoll, offset: number, count: number): Promise<HMSQuizLeaderboardResponse> {\n    const canReadPolls = this.store.getLocalPeer()?.role?.permissions.pollRead || false;\n\n    if (poll.anonymous || poll.state !== HMSPollStates.STOPPED || !canReadPolls) {\n      return { entries: [], hasNext: false };\n    }\n    const pollLeaderboard = await this.transport.fetchLeaderboard({\n      poll_id: poll.id,\n      count,\n      offset,\n    });\n\n    const summary = {\n      avgScore: pollLeaderboard.avg_score,\n      avgTime: pollLeaderboard.avg_time,\n      votedUsers: pollLeaderboard.voted_users,\n      totalUsers: pollLeaderboard.total_users,\n      correctAnswers: pollLeaderboard.correct_users,\n    };\n\n    const leaderboardEntries = pollLeaderboard.questions.map(question => {\n      return {\n        position: question.position,\n        totalResponses: question.total_responses,\n        correctResponses: question.correct_responses,\n        duration: question.duration,\n        peer: question.peer,\n        score: question.score,\n      };\n    });\n\n    return { entries: leaderboardEntries, hasNext: !pollLeaderboard.last, summary };\n  }\n}\n\nexport const createHMSPollFromPollParams = (pollParams: PollInfoParams): HMSPoll => {\n  const BIZ_USER_TRACKING_MODE_MAP: Record<string, HMSPollUserTrackingMode> = {\n    userid: 'customerID',\n    peerid: 'peerID',\n    username: 'userName',\n  };\n\n  return {\n    id: pollParams.poll_id,\n    title: pollParams.title,\n    startedBy: pollParams.started_by,\n    createdBy: pollParams.created_by,\n    anonymous: pollParams.anonymous,\n    type: pollParams.type,\n    duration: pollParams.duration,\n    locked: pollParams.locked, // poll is locked automatically when it starts\n    mode: pollParams.mode ? BIZ_USER_TRACKING_MODE_MAP[pollParams.mode] : undefined,\n    visibility: pollParams.visibility,\n    rolesThatCanVote: pollParams.vote || [],\n    rolesThatCanViewResponses: pollParams.responses || [],\n    state: pollParams.state,\n    stoppedBy: pollParams.stopped_by,\n    startedAt: convertDateNumToDate(pollParams.started_at),\n    stoppedAt: convertDateNumToDate(pollParams.stopped_at),\n    createdAt: convertDateNumToDate(pollParams.created_at),\n  };\n};\n","import { HMSPoll, HMSPollQuestionResponse, HMSPollsUpdate, HMSUpdateListener } from '../../interfaces';\nimport { IStore } from '../../sdk/store';\nimport { createHMSPollFromPollParams } from '../../session-store/interactivity-center/HMSInteractivityCenter';\nimport { PollResult } from '../../signal/interfaces';\nimport HMSTransport from '../../transport';\nimport { convertDateNumToDate } from '../../utils/date';\nimport { HMSNotificationMethod } from '../HMSNotificationMethod';\nimport { PollStartNotification, PollStatsNotification, PollStopNotification } from '../HMSNotifications';\n\nexport class PollsManager {\n  constructor(private store: IStore, private transport: HMSTransport, public listener?: HMSUpdateListener) {}\n\n  handleNotification(method: string, notification: any) {\n    switch (method) {\n      case HMSNotificationMethod.POLL_START: {\n        this.handlePollStart(notification as PollStartNotification);\n        break;\n      }\n\n      case HMSNotificationMethod.POLL_STOP: {\n        this.handlePollStop(notification as PollStopNotification);\n        break;\n      }\n      case HMSNotificationMethod.POLL_STATS:\n        this.handlePollStats(notification as PollStatsNotification);\n\n        break;\n      default:\n        break;\n    }\n  }\n\n  private async handlePollStart(notification: PollStartNotification) {\n    const polls: HMSPoll[] = [];\n    for (const pollParams of notification.polls) {\n      if (this.store.getPoll(pollParams.poll_id)) {\n        return;\n      }\n\n      const questions = await this.transport.getPollQuestions({ poll_id: pollParams.poll_id, index: 0, count: 50 });\n\n      const poll = createHMSPollFromPollParams(pollParams);\n      poll.questions = questions.questions.map(({ question, options, answer }) => ({ ...question, options, answer }));\n\n      await this.updatePollResponses(poll, true);\n\n      polls.push(poll);\n      this.store.setPoll(poll);\n    }\n    this.listener?.onPollsUpdate(HMSPollsUpdate.POLL_STARTED, polls);\n  }\n\n  private async handlePollStop(notification: PollStopNotification) {\n    const stoppedPolls: HMSPoll[] = [];\n\n    for (const poll of notification.polls) {\n      const savedPoll = this.store.getPoll(poll.poll_id);\n      if (savedPoll) {\n        savedPoll.state = 'stopped';\n        savedPoll.stoppedAt = convertDateNumToDate(poll.stopped_at);\n        savedPoll.stoppedBy = poll.stopped_by;\n\n        const pollResult = await this.transport.getPollResult({ poll_id: poll.poll_id });\n        this.updatePollResult(savedPoll, pollResult);\n        stoppedPolls.push(savedPoll);\n      }\n    }\n\n    if (stoppedPolls.length > 0) {\n      this.listener?.onPollsUpdate(HMSPollsUpdate.POLL_STOPPED, stoppedPolls);\n    }\n  }\n\n  private async handlePollStats(notification: PollStatsNotification) {\n    const updatedPolls: HMSPoll[] = [];\n    for (const updatedPoll of notification.polls) {\n      const savedPoll = this.store.getPoll(updatedPoll.poll_id);\n      if (!savedPoll) {\n        return;\n      }\n\n      this.updatePollResult(savedPoll, updatedPoll);\n      await this.updatePollResponses(savedPoll, false);\n\n      updatedPolls.push(savedPoll);\n    }\n\n    if (updatedPolls.length > 0) {\n      this.listener?.onPollsUpdate(HMSPollsUpdate.POLL_STATS_UPDATED, updatedPolls);\n    }\n  }\n\n  private updatePollResult(savedPoll: HMSPoll, pollResult: PollResult) {\n    savedPoll.result = { ...savedPoll.result };\n    savedPoll.result.totalUsers = pollResult.user_count;\n    savedPoll.result.maxUsers = pollResult.max_user;\n    savedPoll.result.totalResponses = pollResult.total_response;\n\n    pollResult.questions?.forEach(updatedQuestion => {\n      const savedQuestion = savedPoll.questions?.find(question => question.index === updatedQuestion.question);\n      if (!savedQuestion) {\n        return;\n      }\n      savedQuestion.result = { ...savedQuestion.result };\n      savedQuestion.result.correctResponses = updatedQuestion.correct;\n      savedQuestion.result.skippedCount = updatedQuestion.skipped;\n      savedQuestion.result.totalResponses = updatedQuestion.total;\n\n      updatedQuestion.options?.forEach((updatedVoteCount, index) => {\n        const savedOption = savedQuestion.options?.[index];\n        if (savedOption && savedOption.voteCount !== updatedVoteCount) {\n          savedOption.voteCount = updatedVoteCount;\n        }\n      });\n    });\n  }\n\n  private async updatePollResponses(poll: HMSPoll, self: boolean) {\n    const serverResponseParams = await this.transport.getPollResponses({\n      poll_id: poll.id,\n      index: 0,\n      count: 50,\n      self,\n    });\n\n    serverResponseParams.responses?.forEach(({ response, peer, final }) => {\n      const question = poll?.questions?.find(question => question.index === response.question);\n      if (!question) {\n        return;\n      }\n      const pollResponse: HMSPollQuestionResponse = {\n        id: response.response_id,\n        questionIndex: response.question,\n        option: response.option,\n        options: response.options,\n        text: response.text,\n        responseFinal: final,\n        peer: { peerid: peer.peerid, userHash: peer.hash, userid: peer.userid, username: peer.username },\n        skipped: response.skipped,\n        type: response.type,\n        update: response.update,\n      };\n\n      if (Array.isArray(question.responses) && question.responses.length > 0) {\n        if (!question.responses.find(({ id }) => id === pollResponse.id)) {\n          question.responses.push(pollResponse);\n        }\n      } else {\n        question.responses = [pollResponse];\n      }\n    });\n  }\n}\n","import { HMSRemotePeer, HMSRoleChangeRequest, HMSUpdateListener } from '../../interfaces';\nimport { HMSLocalTrack, HMSTrackSource } from '../../media/tracks';\nimport { IStore } from '../../sdk/store';\nimport { HMSNotificationMethod } from '../HMSNotificationMethod';\nimport {\n  ChangeTrackMuteStateNotification,\n  RoleChangeRequestParams,\n  TrackUpdateRequestNotification,\n} from '../HMSNotifications';\n\n/**\n * Handles request from remote peers to change something on the local side. For eg. role change, track mute/unmute.\n */\nexport class RequestManager {\n  constructor(private store: IStore, public listener?: HMSUpdateListener) {}\n\n  handleNotification(method: string, notification: any) {\n    switch (method) {\n      case HMSNotificationMethod.ROLE_CHANGE_REQUEST:\n        this.handleRoleChangeRequest(notification as RoleChangeRequestParams);\n        break;\n\n      case HMSNotificationMethod.TRACK_UPDATE_REQUEST:\n        this.handleTrackUpdateRequest(notification as TrackUpdateRequestNotification);\n        break;\n\n      case HMSNotificationMethod.CHANGE_TRACK_MUTE_STATE_UPDATE:\n        this.handleChangeTrackStateRequest(notification as ChangeTrackMuteStateNotification);\n        break;\n      default:\n        return;\n    }\n  }\n\n  private handleRoleChangeRequest(notification: RoleChangeRequestParams) {\n    const request: HMSRoleChangeRequest = {\n      requestedBy: notification.requested_by\n        ? (this.store.getPeerById(notification.requested_by) as HMSRemotePeer)\n        : undefined,\n      role: this.store.getPolicyForRole(notification.role),\n      token: notification.token,\n    };\n\n    this.listener?.onRoleChangeRequest(request);\n  }\n\n  // eslint-disable-next-line complexity\n  private handleTrackUpdateRequest(trackUpdateRequest: TrackUpdateRequestNotification) {\n    const { requested_by, track_id, mute } = trackUpdateRequest;\n    const peer = requested_by ? this.store.getPeerById(requested_by) : undefined;\n    const track = this.store.getLocalPeerTracks().find(track => track.publishedTrackId === track_id);\n\n    if (!track) {\n      return;\n    }\n\n    const sendNotification = () => {\n      this.listener?.onChangeTrackStateRequest({ requestedBy: peer as HMSRemotePeer, track, enabled: !mute });\n    };\n\n    if (mute) {\n      // if track is already in the same state as change state, do nothing\n      if (track.enabled === !mute) {\n        return;\n      }\n      /**\n       * Directly mute track when request arrives\n       */\n      track.setEnabled(!mute).then(sendNotification);\n    } else {\n      /**\n       * Notify UI to unmute for requesting consent\n       */\n      sendNotification();\n    }\n  }\n\n  private handleChangeTrackStateRequest(request: ChangeTrackMuteStateNotification) {\n    const { type, source, value, requested_by } = request;\n    const peer = requested_by ? this.store.getPeerById(requested_by) : undefined;\n\n    // value true means the track has to be muted\n    const enabled = !value;\n    const tracksToBeUpdated = this.getTracksToBeUpdated({ type, source, enabled });\n    //Do nothing if all tracks are already in same state as the request\n    if (tracksToBeUpdated.length === 0) {\n      return;\n    }\n    // if track is to be muted, mute and send the notification, otherwise send notification\n    if (!enabled) {\n      const promises: Promise<void>[] = [];\n\n      for (const track of tracksToBeUpdated) {\n        promises.push(track.setEnabled(false));\n      }\n      Promise.all(promises).then(() => {\n        this.listener?.onChangeMultiTrackStateRequest({\n          requestedBy: peer as HMSRemotePeer,\n          tracks: tracksToBeUpdated,\n          enabled: false,\n        });\n      });\n    } else {\n      this.listener?.onChangeMultiTrackStateRequest({\n        requestedBy: peer as HMSRemotePeer,\n        tracks: tracksToBeUpdated,\n        type,\n        source,\n        enabled: true,\n      });\n    }\n  }\n\n  /**\n   * Filter the local tracks based on type, source and enabled state\n   * @returns {HMSLocalTrack[]}\n   */\n  private getTracksToBeUpdated({\n    type,\n    source,\n    enabled,\n  }: {\n    type?: 'audio' | 'video';\n    source?: HMSTrackSource;\n    enabled: boolean;\n  }) {\n    const localPeerTracks = this.store.getLocalPeerTracks();\n    let tracks: HMSLocalTrack[] = localPeerTracks;\n    if (type) {\n      tracks = tracks.filter(track => track.type === type);\n    }\n    if (source) {\n      tracks = tracks.filter(track => track.source === source);\n    }\n    // filter out tracks which are already in the desired state\n    return tracks.filter(track => track.enabled !== enabled);\n  }\n}\n","import { HMSAction } from '../../error/HMSAction';\nimport { HMSException } from '../../error/HMSException';\nimport {\n  HLSVariant,\n  HMSBrowserRecording,\n  HMSHLS,\n  HMSHLSRecording,\n  HMSRoomUpdate,\n  HMSSFURecording,\n  HMSUpdateListener,\n} from '../../interfaces';\nimport { ServerError } from '../../interfaces/internal';\nimport { IStore } from '../../sdk/store';\nimport { convertDateNumToDate } from '../../utils/date';\nimport HMSLogger from '../../utils/logger';\nimport { HMSNotificationMethod } from '../HMSNotificationMethod';\nimport {\n  HLSNotification,\n  HMSRecordingState,\n  HMSStreamingState,\n  PeerListNotification,\n  PeriodicRoomState,\n  RecordingNotification,\n  RecordingNotificationType,\n  RoomInfo,\n  RoomState,\n  RTMPNotification,\n  SessionInfo,\n} from '../HMSNotifications';\n\nexport class RoomUpdateManager {\n  private readonly TAG = '[RoomUpdateManager]';\n\n  constructor(private store: IStore, public listener?: HMSUpdateListener) {}\n\n  // eslint-disable-next-line complexity\n  handleNotification(method: HMSNotificationMethod, notification: any) {\n    switch (method) {\n      case HMSNotificationMethod.PEER_LIST:\n        this.onRoomState((notification as PeerListNotification).room);\n        break;\n      case HMSNotificationMethod.RTMP_UPDATE:\n        this.updateRTMPStatus(notification as RTMPNotification);\n        break;\n      case HMSNotificationMethod.RECORDING_UPDATE:\n        this.updateRecordingStatus(notification as RecordingNotification);\n        break;\n      case HMSNotificationMethod.ROOM_STATE:\n        this.handlePreviewRoomState(notification as PeriodicRoomState);\n        break;\n      case HMSNotificationMethod.ROOM_INFO:\n        this.handleRoomInfo(notification as RoomInfo);\n        break;\n      case HMSNotificationMethod.SESSION_INFO:\n        this.handleSessionInfo(notification as SessionInfo);\n        break;\n      case HMSNotificationMethod.HLS_UPDATE:\n        this.updateHLSStatus(notification as HLSNotification);\n        break;\n      default:\n        break;\n    }\n  }\n\n  private handleRoomInfo(notification: RoomInfo) {\n    const room = this.store.getRoom();\n    if (!room) {\n      HMSLogger.w(this.TAG, 'on session info - room not present');\n      return;\n    }\n    room.description = notification.description;\n    room.large_room_optimization = notification.large_room_optimization;\n    room.max_size = notification.max_size;\n    room.name = notification.name;\n  }\n\n  private handleSessionInfo(notification: SessionInfo) {\n    const room = this.store.getRoom();\n    if (!room) {\n      HMSLogger.w(this.TAG, 'on session info - room not present');\n      return;\n    }\n    room.sessionId = notification.session_id;\n    if (room.peerCount !== notification.peer_count) {\n      room.peerCount = notification.peer_count;\n      this.listener?.onRoomUpdate(HMSRoomUpdate.ROOM_PEER_COUNT_UPDATED, room);\n    }\n  }\n\n  private handlePreviewRoomState(notification: PeriodicRoomState) {\n    const { room } = notification;\n    this.onRoomState(room);\n  }\n\n  private onRoomState(roomNotification: RoomState) {\n    const { recording, streaming, session_id, started_at, name } = roomNotification;\n    const room = this.store.getRoom();\n    if (!room) {\n      HMSLogger.w(this.TAG, 'on room state - room not present');\n      return;\n    }\n\n    room.name = name;\n\n    room.rtmp.running = this.isStreamingRunning(streaming?.rtmp?.state);\n    room.rtmp.startedAt = convertDateNumToDate(streaming?.rtmp?.started_at);\n    room.rtmp.state = streaming?.rtmp?.state;\n\n    room.recording.server = this.getPeerListSFURecording(recording);\n    room.recording.browser = this.getPeerListBrowserRecording(recording);\n    room.recording.hls = this.getPeerListHLSRecording(recording);\n\n    room.hls = this.convertHls(streaming?.hls);\n\n    room.sessionId = session_id;\n    room.startedAt = convertDateNumToDate(started_at);\n    this.listener?.onRoomUpdate(HMSRoomUpdate.RECORDING_STATE_UPDATED, room);\n  }\n\n  private isRecordingRunning(state?: HMSRecordingState): boolean {\n    if (!state) {\n      return false;\n    }\n    return ![\n      HMSRecordingState.NONE,\n      HMSRecordingState.PAUSED,\n      HMSRecordingState.STOPPED,\n      HMSRecordingState.FAILED,\n    ].includes(state);\n  }\n\n  private isStreamingRunning(state?: HMSStreamingState): boolean {\n    if (!state) {\n      return false;\n    }\n    return ![HMSStreamingState.NONE, HMSStreamingState.STOPPED, HMSStreamingState.FAILED].includes(state);\n  }\n\n  private initHLS(notification?: HLSNotification): HMSHLS {\n    const room = this.store.getRoom();\n    const hls: HMSHLS = {\n      running: true,\n      variants: [],\n    };\n    if (!room) {\n      HMSLogger.w(this.TAG, 'on hls - room not present');\n      return hls;\n    }\n    if (!notification?.variants) {\n      return hls;\n    }\n    notification.variants.forEach((_: HLSVariant, index: number) => {\n      hls.variants.push({\n        initialisedAt: convertDateNumToDate(notification?.variants?.[index].initialised_at),\n        url: '',\n      });\n    });\n    return hls;\n  }\n  private updateHLSStatus(notification: HLSNotification) {\n    const room = this.store.getRoom();\n    const running =\n      notification.variants && notification.variants.length > 0\n        ? this.isStreamingRunning(notification.variants[0].state)\n        : false;\n    if (!room) {\n      HMSLogger.w(this.TAG, 'on hls - room not present');\n      return;\n    }\n    notification.enabled = running;\n    room.hls = this.convertHls(notification);\n    this.listener?.onRoomUpdate(HMSRoomUpdate.HLS_STREAMING_STATE_UPDATED, room);\n  }\n\n  private convertHls(hlsNotification?: HLSNotification) {\n    const isInitialised =\n      hlsNotification?.variants && hlsNotification.variants.length > 0\n        ? hlsNotification.variants[0].state === HMSStreamingState.INITIALISED\n        : false;\n    // handling for initialized state\n    if (isInitialised) {\n      return this.initHLS(hlsNotification);\n    }\n    const hls: HMSHLS = {\n      running: !!hlsNotification?.enabled,\n      variants: [],\n      error: this.toSdkError(hlsNotification?.error),\n    };\n    hlsNotification?.variants?.forEach(variant => {\n      hls.variants.push({\n        meetingURL: variant?.meeting_url,\n        url: variant?.url,\n        metadata: variant?.metadata,\n        startedAt: convertDateNumToDate(variant?.started_at),\n        initialisedAt: convertDateNumToDate(variant?.initialised_at),\n        state: variant.state,\n      });\n    });\n    return hls;\n  }\n\n  private getHLSRecording(hlsNotification?: RecordingNotification): HMSHLSRecording {\n    let hlsRecording: HMSHLSRecording = { running: false };\n    const running = this.isRecordingRunning(hlsNotification?.state);\n    if (running || hlsNotification?.state === HMSRecordingState.PAUSED) {\n      hlsRecording = {\n        running,\n        singleFilePerLayer: !!hlsNotification?.hls_recording?.single_file_per_layer,\n        hlsVod: !!hlsNotification?.hls_recording?.hls_vod,\n        startedAt: convertDateNumToDate(hlsNotification?.started_at),\n        initialisedAt: convertDateNumToDate(hlsNotification?.initialised_at),\n        state: hlsNotification?.state,\n        error: this.toSdkError(hlsNotification?.error),\n      };\n    }\n    return hlsRecording;\n  }\n\n  private getPeerListHLSRecording(recording?: RoomState['recording']): HMSHLSRecording {\n    const hlsNotification = recording?.hls;\n    const running = this.isRecordingRunning(hlsNotification?.state);\n    return {\n      running,\n      startedAt: convertDateNumToDate(hlsNotification?.started_at),\n      initialisedAt: convertDateNumToDate(hlsNotification?.initialised_at),\n      state: hlsNotification?.state,\n      singleFilePerLayer: hlsNotification?.config?.single_file_per_layer,\n      hlsVod: hlsNotification?.config?.hls_vod,\n    };\n  }\n  private getPeerListBrowserRecording(recording?: RoomState['recording']): HMSBrowserRecording {\n    const browserNotification = recording?.browser;\n    const running = this.isRecordingRunning(browserNotification?.state);\n    return {\n      running,\n      startedAt: convertDateNumToDate(browserNotification?.started_at),\n      state: browserNotification?.state,\n    };\n  }\n  private getPeerListSFURecording(recording?: RoomState['recording']): HMSSFURecording {\n    const sfuNotification = recording?.sfu;\n    const running = this.isRecordingRunning(sfuNotification?.state);\n    return {\n      running,\n      startedAt: convertDateNumToDate(sfuNotification?.started_at),\n      state: sfuNotification?.state,\n    };\n  }\n\n  private updateRecordingStatus(notification: RecordingNotification) {\n    const room = this.store.getRoom();\n    const running = this.isRecordingRunning(notification.state);\n    if (!room) {\n      HMSLogger.w(this.TAG, `set recording status running=${running} - room not present`);\n      return;\n    }\n\n    let action: HMSRoomUpdate;\n    if (notification.type === RecordingNotificationType.SFU) {\n      room.recording.server = {\n        running,\n        startedAt: running ? convertDateNumToDate(notification.started_at) : undefined,\n        error: this.toSdkError(notification.error),\n        state: notification.state,\n      };\n      action = HMSRoomUpdate.SERVER_RECORDING_STATE_UPDATED;\n    } else if (notification.type === RecordingNotificationType.HLS) {\n      room.recording.hls = this.getHLSRecording(notification);\n      action = HMSRoomUpdate.RECORDING_STATE_UPDATED;\n    } else {\n      room.recording.browser = {\n        running,\n        startedAt: running ? convertDateNumToDate(notification.started_at) : undefined,\n        error: this.toSdkError(notification.error),\n        state: notification?.state,\n      };\n      action = HMSRoomUpdate.BROWSER_RECORDING_STATE_UPDATED;\n    }\n    this.listener?.onRoomUpdate(action, room);\n  }\n\n  private updateRTMPStatus(notification: RTMPNotification) {\n    const room = this.store.getRoom();\n    const running = this.isStreamingRunning(notification.state);\n    if (!room) {\n      HMSLogger.w(this.TAG, 'on policy change - room not present');\n      return;\n    }\n    if (!running) {\n      room.rtmp = {\n        running,\n        state: notification.state,\n        error: this.toSdkError(notification.error),\n      };\n      this.listener?.onRoomUpdate(HMSRoomUpdate.RTMP_STREAMING_STATE_UPDATED, room);\n      return;\n    }\n    room.rtmp = {\n      running,\n      startedAt: running ? convertDateNumToDate(notification.started_at) : undefined,\n      state: notification.state,\n      error: this.toSdkError(notification.error),\n    };\n    this.listener?.onRoomUpdate(HMSRoomUpdate.RTMP_STREAMING_STATE_UPDATED, room);\n  }\n\n  private toSdkError(error?: ServerError): HMSException | undefined {\n    if (!error?.code) {\n      return undefined;\n    }\n    const errMsg = error.message || 'error in streaming/recording';\n    const sdkError = new HMSException(error.code, 'ServerErrors', HMSAction.NONE, errMsg, errMsg);\n    HMSLogger.e(this.TAG, 'error in streaming/recording', sdkError);\n    return sdkError;\n  }\n}\n","import { HMSUpdateListener, SessionStoreUpdate } from '../../interfaces';\nimport { IStore } from '../../sdk/store';\nimport { convertDateNumToDate } from '../../utils/date';\nimport { HMSNotificationMethod } from '../HMSNotificationMethod';\nimport { MetadataChangeNotification } from '../HMSNotifications';\n\nexport class SessionMetadataManager {\n  constructor(private store: IStore, public listener?: HMSUpdateListener) {}\n\n  handleNotification(method: string, notification: any) {\n    if (method !== HMSNotificationMethod.METADATA_CHANGE) {\n      return;\n    }\n    this.handleMetadataChange(notification);\n  }\n\n  private handleMetadataChange(notification: MetadataChangeNotification) {\n    const updates: SessionStoreUpdate[] = notification.values.map(update => ({\n      key: update.key,\n      value: update.data,\n      updatedAt: convertDateNumToDate(update.updated_at),\n      updatedBy: update.updated_by ? this.store.getPeerById(update.updated_by) : undefined,\n    }));\n    this.listener?.onSessionStoreUpdate(updates);\n  }\n}\n","import { HMSUpdateListener, HMSWhiteboard } from '../../interfaces';\nimport { IStore } from '../../sdk/store';\nimport HMSTransport from '../../transport';\nimport { HMSNotificationMethod } from '../HMSNotificationMethod';\nimport { WhiteboardInfo } from '../HMSNotifications';\n\nexport class WhiteboardManager {\n  constructor(private store: IStore, private transport: HMSTransport, public listener?: HMSUpdateListener) {}\n\n  handleNotification(method: string, notification: any) {\n    switch (method) {\n      case HMSNotificationMethod.WHITEBOARD_UPDATE: {\n        this.handleWhiteboardUpdate(notification as WhiteboardInfo);\n        break;\n      }\n      default:\n        break;\n    }\n  }\n\n  private async handleWhiteboardUpdate(notification: WhiteboardInfo) {\n    const localPeer = this.store.getLocalPeer();\n    const prev = this.store.getWhiteboard(notification.id);\n    const isOwner = notification.owner === localPeer?.peerId || notification.owner === localPeer?.customerUserId;\n    const open = notification.state === 'open';\n    const whiteboard: HMSWhiteboard = {\n      id: notification.id,\n      title: notification.title,\n      attributes: notification.attributes,\n    };\n    whiteboard.open = isOwner ? prev?.open : open;\n    whiteboard.owner = whiteboard.open ? notification.owner : undefined;\n\n    if (!isOwner && whiteboard.open) {\n      const response = await this.transport.getWhiteboard({ id: notification.id });\n      whiteboard.token = response.token;\n      whiteboard.addr = response.addr;\n      whiteboard.permissions = response.permissions;\n    }\n\n    this.store.setWhiteboard(whiteboard);\n    this.listener?.onWhiteboardUpdate(whiteboard);\n  }\n}\n","import { ActiveSpeakerManager } from './managers/ActiveSpeakerManager';\nimport { BroadcastManager } from './managers/BroadcastManager';\nimport { ConnectionQualityManager } from './managers/ConnectionQualityManager';\nimport { OnDemandTrackManager } from './managers/onDemandTrackManager';\nimport { PeerListManager } from './managers/PeerListManager';\nimport { PeerManager } from './managers/PeerManager';\nimport { PolicyChangeManager } from './managers/PolicyChangeManager';\nimport { PollsManager } from './managers/PollsManager';\nimport { RequestManager } from './managers/RequestManager';\nimport { RoomUpdateManager } from './managers/RoomUpdateManager';\nimport { SessionMetadataManager } from './managers/SessionMetadataManager';\nimport { TrackManager } from './managers/TrackManager';\nimport { WhiteboardManager } from './managers/WhiteboardManager';\nimport { HMSNotificationMethod } from './HMSNotificationMethod';\nimport {\n  ConnectionQualityList,\n  OnTrackLayerUpdateNotification,\n  PolicyParams,\n  SpeakerList,\n  TrackStateNotification,\n} from './HMSNotifications';\nimport { EventBus } from '../events/EventBus';\nimport { HMSAudioListener, HMSConnectionQualityListener, HMSUpdateListener } from '../interfaces';\nimport { HMSRemoteTrack } from '../media/tracks';\nimport { IStore } from '../sdk/store';\nimport { InitFlags } from '../signal/init/models';\nimport HMSTransport from '../transport';\nimport HMSLogger from '../utils/logger';\n\nexport class NotificationManager {\n  private readonly TAG = '[HMSNotificationManager]';\n  private trackManager: TrackManager;\n  private peerManager: PeerManager;\n  private peerListManager: PeerListManager;\n  private activeSpeakerManager: ActiveSpeakerManager;\n  private connectionQualityManager: ConnectionQualityManager;\n  private broadcastManager: BroadcastManager;\n  private policyChangeManager: PolicyChangeManager;\n  private requestManager: RequestManager;\n  private roomUpdateManager: RoomUpdateManager;\n  private sessionMetadataManager: SessionMetadataManager;\n  private pollsManager: PollsManager;\n  private whiteboardManager: WhiteboardManager;\n  /**\n   * room state can be sent before join in preview stage as well but that is outdated, based on\n   * eventual consistency and doesn't have all data. If we get at least one consistent room update\n   * from that point onwards we can rely on live server updates and ignore periodic room state messages\n   */\n  private hasConsistentRoomStateArrived = false;\n\n  constructor(\n    private store: IStore,\n    eventBus: EventBus,\n    private transport: HMSTransport,\n    private listener?: HMSUpdateListener,\n    private audioListener?: HMSAudioListener,\n    private connectionQualityListener?: HMSConnectionQualityListener,\n  ) {\n    const isOnDemandTracksEnabled = this.transport.isFlagEnabled(InitFlags.FLAG_ON_DEMAND_TRACKS);\n    this.trackManager = isOnDemandTracksEnabled\n      ? new OnDemandTrackManager(this.store, eventBus, this.transport, this.listener)\n      : new TrackManager(this.store, eventBus, this.listener);\n\n    this.peerManager = new PeerManager(this.store, this.trackManager, this.listener);\n    this.peerListManager = new PeerListManager(this.store, this.peerManager, this.trackManager, this.listener);\n    this.broadcastManager = new BroadcastManager(this.store, this.listener);\n    this.policyChangeManager = new PolicyChangeManager(this.store, eventBus);\n    this.requestManager = new RequestManager(this.store, this.listener);\n    this.activeSpeakerManager = new ActiveSpeakerManager(this.store, this.listener, this.audioListener);\n    this.connectionQualityManager = new ConnectionQualityManager(this.store, this.connectionQualityListener);\n    this.roomUpdateManager = new RoomUpdateManager(this.store, this.listener);\n    this.sessionMetadataManager = new SessionMetadataManager(this.store, this.listener);\n    this.pollsManager = new PollsManager(this.store, this.transport, this.listener);\n    this.whiteboardManager = new WhiteboardManager(this.store, this.transport, this.listener);\n  }\n\n  setListener(listener?: HMSUpdateListener) {\n    this.listener = listener;\n    this.trackManager.listener = listener;\n    this.peerManager.listener = listener;\n    this.peerListManager.listener = listener;\n    this.broadcastManager.listener = listener;\n    this.requestManager.listener = listener;\n    this.activeSpeakerManager.listener = listener;\n    this.roomUpdateManager.listener = listener;\n    this.sessionMetadataManager.listener = listener;\n    this.pollsManager.listener = listener;\n    this.whiteboardManager.listener = listener;\n  }\n\n  setAudioListener(audioListener?: HMSAudioListener) {\n    this.audioListener = audioListener;\n    this.activeSpeakerManager.audioListener = audioListener;\n  }\n\n  setConnectionQualityListener(qualityListener?: HMSConnectionQualityListener) {\n    this.connectionQualityListener = qualityListener;\n    this.connectionQualityManager.listener = qualityListener;\n  }\n\n  handleNotification(message: { method: string; params: any }, isReconnecting = false) {\n    const method = message.method as HMSNotificationMethod;\n    const notification = message.params;\n\n    if (\n      ![\n        HMSNotificationMethod.ACTIVE_SPEAKERS,\n        HMSNotificationMethod.SFU_STATS,\n        HMSNotificationMethod.CONNECTION_QUALITY,\n        undefined, // this is is to ignore notifications without any method\n      ].includes(method)\n    ) {\n      HMSLogger.d(this.TAG, `Received notification - ${method}`, { notification });\n    }\n    if (method === HMSNotificationMethod.SFU_STATS) {\n      if (window.HMS?.ON_SFU_STATS && typeof window.HMS?.ON_SFU_STATS === 'function') {\n        window.HMS.ON_SFU_STATS(message.params);\n      }\n    }\n\n    if (this.ignoreNotification(method)) {\n      return;\n    }\n\n    this.roomUpdateManager.handleNotification(method, notification);\n    this.peerManager.handleNotification(method, notification);\n    this.requestManager.handleNotification(method, notification);\n    this.peerListManager.handleNotification(method, notification, isReconnecting);\n    this.broadcastManager.handleNotification(method, notification);\n    this.sessionMetadataManager.handleNotification(method, notification);\n    this.pollsManager.handleNotification(method, notification);\n    this.whiteboardManager.handleNotification(method, notification);\n    this.handleIsolatedMethods(method, notification);\n  }\n\n  // eslint-disable-next-line complexity\n  handleIsolatedMethods(method: string, notification: any) {\n    switch (method) {\n      case HMSNotificationMethod.TRACK_METADATA_ADD: {\n        this.trackManager.handleTrackMetadataAdd(notification as TrackStateNotification);\n        break;\n      }\n      case HMSNotificationMethod.TRACK_UPDATE: {\n        this.trackManager.handleTrackUpdate(notification as TrackStateNotification);\n        break;\n      }\n      case HMSNotificationMethod.TRACK_REMOVE: {\n        if (!notification.peer) {\n          HMSLogger.d(this.TAG, `Ignoring sfu notification - ${method}`, { notification });\n          return;\n        }\n        this.trackManager.handleTrackRemovedPermanently(notification as TrackStateNotification);\n        break;\n      }\n      case HMSNotificationMethod.ON_SFU_TRACK_LAYER_UPDATE: {\n        this.trackManager.handleTrackLayerUpdate(notification as OnTrackLayerUpdateNotification);\n        break;\n      }\n      case HMSNotificationMethod.ACTIVE_SPEAKERS:\n        this.activeSpeakerManager.handleActiveSpeakers(notification as SpeakerList);\n        break;\n\n      case HMSNotificationMethod.CONNECTION_QUALITY:\n        this.connectionQualityManager.handleQualityUpdate(notification as ConnectionQualityList);\n        break;\n\n      case HMSNotificationMethod.POLICY_CHANGE:\n        this.policyChangeManager.handlePolicyChange(notification as PolicyParams);\n        break;\n\n      default:\n        break;\n    }\n  }\n\n  ignoreNotification = (method: string): boolean => {\n    if (method === HMSNotificationMethod.PEER_LIST) {\n      this.hasConsistentRoomStateArrived = true;\n    } else if (method === HMSNotificationMethod.ROOM_STATE) {\n      // ignore periodic inconsistent room state if consistent one has arrived at least once\n      return this.hasConsistentRoomStateArrived;\n    }\n    return false;\n  };\n\n  handleTrackAdd = (track: HMSRemoteTrack) => {\n    this.trackManager.handleTrackAdd(track);\n  };\n\n  handleTrackRemove = (track: HMSRemoteTrack) => {\n    this.trackManager.handleTrackRemove(track);\n  };\n\n  updateLocalPeer = ({ name, metadata }: { name?: string; metadata?: string }) => {\n    const peer = this.store.getLocalPeer();\n    this.peerManager.handlePeerInfoUpdate({ peer, name, data: metadata });\n  };\n}\n","import HMSLogger from '../utils/logger';\n\nexport class AudioContextManager {\n  private audioContext: AudioContext;\n  private destinationNode?: MediaStreamAudioDestinationNode;\n  private source: MediaElementAudioSourceNode;\n  private readonly TAG = '[AudioContextManager]';\n\n  constructor(element: HTMLMediaElement) {\n    this.audioContext = new AudioContext();\n    this.source = this.audioContext.createMediaElementSource(element);\n    this.source.connect(this.audioContext.destination);\n  }\n\n  /**\n   * Resume AudioContext if it is suspended\n   * Note: when the browser tab is muted by default, AudioContext will be in suspended state\n   * It has to be resumed for the video/audio to be played.\n   */\n  async resumeContext() {\n    if (this.audioContext.state === 'suspended') {\n      await this.audioContext.resume();\n      HMSLogger.d(this.TAG, 'AudioContext is resumed');\n    }\n  }\n\n  getAudioTrack() {\n    // Always create a destinationNode to get new audio track id\n    if (this.destinationNode) {\n      this.source.disconnect(this.destinationNode);\n    }\n    this.destinationNode = this.audioContext.createMediaStreamDestination();\n    this.source.connect(this.destinationNode);\n    return this.destinationNode.stream.getAudioTracks()[0];\n  }\n\n  cleanup() {\n    if (this.audioContext.state !== 'closed') {\n      this.audioContext.close().catch(e => {\n        HMSLogger.d(this.TAG, 'AudioContext close error', e.message);\n      });\n    }\n  }\n}\n","import { EventEmitter2 as EventEmitter } from 'eventemitter2';\n\n/**\n * Typed Event Emitter Reference:\n * https://rjzaworski.com/2019/10/event-emitters-in-typescript#a-typescript-event-emitter-interface\n */\n\nexport type EventMap = Record<string, any>;\n\nexport type EventKey<T extends EventMap> = string & keyof T;\nexport type EventReceiver<T> = (params: T) => void;\n\n// interface Emitter<T extends EventMap> {\n//   on<K extends EventKey<T>>(eventName: K, fn: EventReceiver<T[K]>): void;\n//   off<K extends EventKey<T>>(eventName: K, fn: EventReceiver<T[K]>): void;\n//   emit<K extends EventKey<T>>(eventName: K, params: T[K]): void;\n// }\n\nexport abstract class TypedEventEmitter<T extends EventMap> extends EventEmitter {\n  on<K extends EventKey<T>>(eventName: K, fn: EventReceiver<T[K]>) {\n    return super.on(eventName, fn);\n  }\n\n  off<K extends EventKey<T>>(eventName: K, fn: EventReceiver<T[K]>) {\n    return super.off(eventName, fn);\n  }\n\n  emit<K extends EventKey<T>>(eventName: K, params: T[K]) {\n    return super.emit(eventName, params);\n  }\n\n  listeners<K extends EventKey<T>>(eventName: K): EventReceiver<T[K]>[] {\n    return super.listeners(eventName) as EventReceiver<T[K]>[];\n  }\n}\n","import { AudioContextManager } from './AudioContextManager';\nimport HMSLogger from '../utils/logger';\nimport { TypedEventEmitter } from '../utils/typed-event-emitter';\n\n/**\n * This class handles audio playlist management\n * - An audio element and audio context which processes audio from audio element is created\n *   in the constructor\n * It handles playback in the following steps\n *  - set's the url on the audio element created in the constructor\n *  - oncanplaythrough event of the audio element\n *    - resume the audio context if it is suspended\n *    - play the audio element\n *    - Get audio track from the audio context manager\n *    - The track is passed to playlist manager to publish\n */\nexport class PlaylistAudioManager extends TypedEventEmitter<{ ended: null; progress: Event }> {\n  private audioElement: HTMLAudioElement | null = null;\n  private track?: MediaStreamTrack;\n  private audioContextManager!: AudioContextManager;\n  private readonly TAG = '[PlaylistAudioManager]';\n  // This is to handle audio playing when seekTo is called when audio is paused\n  private seeked = false;\n\n  async play(url: string) {\n    this.audioElement = this.getAudioElement();\n    return new Promise<MediaStreamTrack[]>((resolve, reject) => {\n      this.audioElement = this.getAudioElement();\n      this.audioElement.src = url;\n      this.seeked = false;\n      this.audioElement.onerror = () => {\n        const error = `Error loading ${url}`;\n        HMSLogger.e(this.TAG, error);\n        this.stop();\n        reject(error);\n      };\n      // oncanplaythrough is called when enough media is loaded for play to be possible in two cases -\n      //    * when play is called for the first time\n      //    * when user seeks jumps to any mid track timestamp\n      this.audioElement.oncanplaythrough = async () => {\n        try {\n          if (!this.audioElement) {\n            return;\n          }\n          this.audioContextManager.resumeContext();\n          // Create audio track only once and reuse, it will be updated with current content\n          if (!this.track) {\n            await this.audioElement.play();\n            const audioTrack = this.audioContextManager.getAudioTrack();\n            this.track = audioTrack;\n            resolve([audioTrack]);\n          } else {\n            if (!this.seeked) {\n              // if this was called in response to a play call\n              await this.audioElement.play();\n              resolve([this.track]);\n            } else {\n              // if seek happened, there is no play call/promise to be resolved, just reset seeked\n              this.seeked = false;\n            }\n          }\n        } catch (err) {\n          HMSLogger.e(this.TAG, 'Error playing audio', url, (err as ErrorEvent).message);\n          reject(err);\n        }\n      };\n      this.audioElement.onseeked = () => {\n        this.seeked = true;\n      };\n    });\n  }\n\n  getTracks() {\n    return this.track ? [this.track.id] : [];\n  }\n\n  getElement() {\n    if (!this.audioElement) {\n      this.audioElement = this.getAudioElement();\n    }\n    return this.audioElement;\n  }\n\n  stop() {\n    this.audioElement?.pause();\n    this.audioElement?.removeAttribute('src');\n    this.audioElement = null;\n    this.audioContextManager?.cleanup();\n    this.track = undefined;\n  }\n\n  private getAudioElement() {\n    if (this.audioElement) {\n      return this.audioElement;\n    }\n    const audioElement = document.createElement('audio');\n    audioElement.crossOrigin = 'anonymous';\n    audioElement.addEventListener('timeupdate', event => this.emit('progress', event));\n    audioElement.addEventListener('ended', () => {\n      this.emit('ended', null);\n    });\n    this.audioContextManager = new AudioContextManager(audioElement);\n    return audioElement;\n  }\n}\n","import { AudioContextManager } from './AudioContextManager';\nimport HMSLogger from '../utils/logger';\nimport { TypedEventEmitter } from '../utils/typed-event-emitter';\n\n/**\n * This class handles video playlist management\n * - An video element, canvas and audio context which processes audio from video element is created\n *   in the constructor\n * It handles playback in the following steps\n *  - set's the url on the video element created in the constructor\n *  - oncanplaythrough event of the video element\n *    - resume the audio context if it is suspended\n *    - set width/height on canvas\n *    - captureStream on canvas element if not already captured\n *    - play the video element\n *    - on video element is played, it is drawn to canvas\n *    - Get audio track from the audio context manager\n *    - add audioTrack to canvas stream\n *    - The audio and video tracks are passed to playlist manager to publish\n */\nexport class PlaylistVideoManager extends TypedEventEmitter<{ ended: null; progress: Event }> {\n  private readonly TAG = '[PlaylistVideoManager]';\n  private videoElement: HTMLVideoElement | null = null;\n  private canvasContext: CanvasRenderingContext2D | null = null;\n  private canvas!: HTMLCanvasElement;\n  private timer: any;\n  private tracks: MediaStreamTrack[] = [];\n  private audioContextManager!: AudioContextManager;\n  private DEFAUL_FPS = 24;\n  // This is to handle video playing when seekTo is called when video is paused\n  private seeked = false;\n\n  play(url: string) {\n    this.videoElement = this.getVideoElement();\n    this.createCanvas();\n    return new Promise<MediaStreamTrack[]>((resolve, reject) => {\n      this.videoElement = this.getVideoElement();\n      this.videoElement.src = url;\n      this.seeked = false;\n      this.videoElement.onerror = () => {\n        const error = `Error loading ${url}`;\n        HMSLogger.e(this.TAG, error);\n        this.stop();\n        reject(error);\n      };\n      // oncanplaythrough is called when enough media is loaded for play to be possible in two cases -\n      //    * when play is called for the first time\n      //    * when user jumps to any mid track timestamp using seekTo\n      this.videoElement.oncanplaythrough = async () => {\n        try {\n          if (!this.videoElement) {\n            return;\n          }\n          this.canvas.width = this.videoElement.videoWidth;\n          this.canvas.height = this.videoElement.videoHeight;\n          // Capture stream only once and reuse the same tracks. it will be autoupdated with the selected video\n          if (this.tracks.length === 0) {\n            this.clearCanvasAndTracks();\n            //@ts-ignore\n            const stream = this.canvas.captureStream();\n            if (!stream) {\n              HMSLogger.e(this.TAG, 'Browser does not support captureStream');\n              return;\n            }\n            this.videoElement.onplay = this.drawImage;\n            await this.audioContextManager.resumeContext();\n            await this.videoElement.play();\n            const audioTrack = this.audioContextManager.getAudioTrack();\n            stream.addTrack(audioTrack);\n            stream.getTracks().forEach((track: MediaStreamTrack) => {\n              this.tracks.push(track);\n            });\n            resolve(this.tracks);\n          } else {\n            // No need to capture canvas stream/get audio track. They wull be auto updated\n            if (!this.seeked) {\n              // if this was called in response to a play call\n              await this.videoElement.play();\n              resolve(this.tracks);\n            } else {\n              // if seek happened, there is no play call/promise to be resolved, just reset seeked\n              this.seeked = false;\n              // This event will be called on seekTo when paused. Just draw the one frame on canvas.\n              this.canvasContext?.drawImage(this.videoElement, 0, 0, this.canvas?.width, this.canvas?.height);\n            }\n          }\n        } catch (err) {\n          HMSLogger.e(this.TAG, 'Error playing video', url, (err as ErrorEvent).message);\n          reject(err);\n        }\n      };\n      this.videoElement.onseeked = () => {\n        this.seeked = true;\n      };\n    });\n  }\n\n  getTracks() {\n    return this.tracks.map(track => track.id);\n  }\n\n  getElement() {\n    if (!this.videoElement) {\n      this.videoElement = this.getVideoElement();\n    }\n    return this.videoElement;\n  }\n\n  stop() {\n    this.videoElement?.pause();\n    this.videoElement?.removeAttribute('src');\n    this.videoElement = null;\n    this.audioContextManager?.cleanup();\n    this.clearCanvasAndTracks();\n  }\n\n  private clearCanvasAndTracks() {\n    this.tracks = [];\n    // clear canvas before playing new video\n    this.canvasContext?.clearRect(0, 0, this.canvas.width, this.canvas.height);\n    clearTimeout(this.timer);\n  }\n\n  private drawImage = () => {\n    if (this.videoElement && !this.videoElement.paused && !this.videoElement.ended) {\n      this.canvasContext?.drawImage(this.videoElement, 0, 0, this.canvas?.width, this.canvas?.height);\n      this.timer = setTimeout(() => {\n        this.drawImage();\n      }, 1000 / this.DEFAUL_FPS);\n    }\n  };\n\n  private getVideoElement() {\n    if (this.videoElement) {\n      return this.videoElement;\n    }\n    const videoElement = document.createElement('video');\n    videoElement.crossOrigin = 'anonymous';\n    videoElement.addEventListener('timeupdate', event => this.emit('progress', event));\n    videoElement.addEventListener('ended', () => {\n      this.emit('ended', null);\n    });\n    this.audioContextManager = new AudioContextManager(videoElement);\n    return videoElement;\n  }\n\n  private createCanvas() {\n    if (!this.canvas) {\n      this.canvas = document.createElement('canvas');\n      this.canvasContext = this.canvas.getContext('2d');\n    }\n  }\n}\n","import { PlaylistAudioManager } from './PlaylistAudioManager';\nimport { PlaylistVideoManager } from './PlaylistVideoManager';\nimport { ErrorFactory } from '../error/ErrorFactory';\nimport { HMSAction } from '../error/HMSAction';\nimport { EventBus } from '../events/EventBus';\nimport { HMSSdk } from '../index';\nimport { HMSPlaylistItem, HMSPlaylistManager, HMSPlaylistProgressEvent, HMSPlaylistType } from '../interfaces';\nimport { HMSLocalTrack } from '../media/tracks';\nimport { stringifyMediaStreamTrack } from '../utils/json';\nimport HMSLogger from '../utils/logger';\nimport { TypedEventEmitter } from '../utils/typed-event-emitter';\n\ntype PlaylistManagerState<T> = {\n  audio: {\n    list: HMSPlaylistItem<T>[];\n    currentIndex: number;\n    isAutoplayOn: boolean;\n  };\n  video: {\n    list: HMSPlaylistItem<T>[];\n    currentIndex: number;\n    isAutoplayOn: boolean;\n  };\n};\n\nconst INITIAL_STATE: PlaylistManagerState<any> = {\n  audio: {\n    list: [],\n    currentIndex: -1,\n    isAutoplayOn: true,\n  },\n  video: {\n    list: [],\n    currentIndex: -1,\n    isAutoplayOn: true,\n  },\n};\n\nexport class PlaylistManager\n  extends TypedEventEmitter<{\n    newTrackStart: HMSPlaylistItem<any>;\n    playlistEnded: HMSPlaylistType;\n    currentTrackEnded: HMSPlaylistItem<any>;\n  }>\n  implements HMSPlaylistManager\n{\n  private state = { audio: { ...INITIAL_STATE.audio }, video: { ...INITIAL_STATE.video } };\n  private audioManager: PlaylistAudioManager;\n  private videoManager: PlaylistVideoManager;\n  private readonly TAG = '[PlaylistManager]';\n\n  constructor(private sdk: HMSSdk, private eventBus: EventBus) {\n    super();\n    this.audioManager = new PlaylistAudioManager();\n    this.videoManager = new PlaylistVideoManager();\n    this.addListeners();\n  }\n\n  getList<T>(type: HMSPlaylistType = HMSPlaylistType.audio): HMSPlaylistItem<T>[] {\n    return this.state[type].list;\n  }\n\n  setList<T>(list: HMSPlaylistItem<T>[]): void {\n    if (!list || list.length === 0) {\n      HMSLogger.w(this.TAG, `Please pass in a list of HMSPlaylistItem's`);\n      return;\n    }\n    list.forEach((item: HMSPlaylistItem<T>) => {\n      if (!this.state[item.type].list.find(_item => _item.id === item.id)) {\n        this.state[item.type].list.push(item);\n      }\n    });\n  }\n\n  async clearList(type: HMSPlaylistType): Promise<void> {\n    if (this.isPlaying(type)) {\n      await this.stop(type);\n    }\n    this.state[type].list = [];\n  }\n\n  async removeItem(id: string, type: HMSPlaylistType): Promise<boolean> {\n    const { list, currentIndex } = this.state[type];\n    const index = list.findIndex(playItem => id === playItem.id);\n    if (index > -1) {\n      // stop if the item is playing\n      if (currentIndex === index && this.isPlaying(type)) {\n        await this.stop(type);\n      }\n      list.splice(index, 1);\n      return true;\n    }\n    return false;\n  }\n\n  seek(value: number, type: HMSPlaylistType = HMSPlaylistType.audio): void {\n    const { currentIndex } = this.state[type];\n    if (currentIndex === -1) {\n      throw ErrorFactory.PlaylistErrors.NoEntryToPlay(HMSAction.PLAYLIST, 'No item is currently playing');\n    }\n    const element = this.getElement(type);\n    if (element) {\n      const updatedValue = Math.max(element.currentTime + value, 0);\n      element.currentTime = Math.min(updatedValue, element.duration);\n    }\n  }\n\n  seekTo(value: number, type: HMSPlaylistType = HMSPlaylistType.audio): void {\n    const { currentIndex } = this.state[type];\n    if (currentIndex === -1) {\n      throw ErrorFactory.PlaylistErrors.NoEntryToPlay(HMSAction.PLAYLIST, 'No item is currently playing');\n    }\n    if (value < 0) {\n      throw Error('value cannot be negative');\n    }\n    const element = this.getElement(type);\n    if (element) {\n      element.currentTime = Math.min(value, element.duration);\n    }\n  }\n\n  setVolume(value: number, type: HMSPlaylistType = HMSPlaylistType.audio): void {\n    if (value < 0 || value > 100) {\n      throw Error('Please pass a valid number between 0-100');\n    }\n    const element = this.getElement(type);\n    if (element) {\n      element.volume = value * 0.01;\n    }\n  }\n\n  getVolume(type: HMSPlaylistType = HMSPlaylistType.audio): number {\n    const element = this.getElement(type);\n    if (element) {\n      return Math.floor(element.volume * 100);\n    }\n    return 0;\n  }\n\n  getCurrentTime(type: HMSPlaylistType = HMSPlaylistType.audio) {\n    const element = this.getElement(type);\n    return element?.currentTime || 0;\n  }\n\n  getCurrentIndex(type: HMSPlaylistType = HMSPlaylistType.audio) {\n    return this.state[type].currentIndex;\n  }\n\n  getCurrentProgress(type: HMSPlaylistType = HMSPlaylistType.audio) {\n    const { list, currentIndex } = this.state[type];\n    const activeUrl = list[currentIndex]?.url;\n    const element = this.getElement(type);\n    if (!activeUrl || !element) {\n      return 0;\n    }\n    return Math.floor(100 * (element.currentTime / element.duration));\n  }\n\n  getCurrentSelection(type: HMSPlaylistType = HMSPlaylistType.audio) {\n    const { list, currentIndex } = this.state[type];\n    if (currentIndex === -1) {\n      return undefined;\n    }\n    return list[currentIndex];\n  }\n\n  isPlaying(type: HMSPlaylistType = HMSPlaylistType.audio) {\n    const element = this.getElement(type);\n    return !!element && !element.paused;\n  }\n\n  setIsAutoplayOn(type: HMSPlaylistType = HMSPlaylistType.audio, autoplay: boolean) {\n    this.state[type].isAutoplayOn = autoplay;\n  }\n\n  getPlaybackRate(type: HMSPlaylistType = HMSPlaylistType.audio) {\n    const element = this.getElement(type);\n    return element ? element.playbackRate : 1.0;\n  }\n\n  setPlaybackRate(type: HMSPlaylistType = HMSPlaylistType.audio, value: number) {\n    if (value < 0.25 || value > 2.0) {\n      throw Error('Please pass a value between 0.25 and 2.0');\n    }\n    const element = this.getElement(type);\n    if (element) {\n      element.playbackRate = value;\n    }\n  }\n\n  async setEnabled(\n    enabled: boolean,\n    { id, type = HMSPlaylistType.audio }: { id: string; type: HMSPlaylistType },\n  ): Promise<void> {\n    const list = this.state[type].list;\n    const currentIndex = list.findIndex(item => item.id === id);\n    if (!id || currentIndex === -1) {\n      HMSLogger.w(this.TAG, 'Pass a valid id');\n      return;\n    }\n    const url = this.state[type].list[currentIndex].url;\n    if (enabled) {\n      await this.play(url, type);\n    } else {\n      await this.pause(url, type);\n    }\n    this.state[type].currentIndex = currentIndex;\n    this.setDuration(type);\n  }\n\n  async playNext(type: HMSPlaylistType = HMSPlaylistType.audio): Promise<void> {\n    const { list, currentIndex } = this.state[type];\n    if (currentIndex >= list.length - 1) {\n      throw ErrorFactory.PlaylistErrors.NoEntryToPlay(HMSAction.PLAYLIST, 'Reached end of playlist');\n    }\n    await this.play(list[currentIndex + 1].url, type);\n    this.state[type].currentIndex = currentIndex + 1;\n    this.setDuration(type);\n  }\n\n  async playPrevious(type: HMSPlaylistType = HMSPlaylistType.audio): Promise<void> {\n    const { list, currentIndex } = this.state[type];\n    if (currentIndex <= 0) {\n      throw ErrorFactory.PlaylistErrors.NoEntryToPlay(HMSAction.PLAYLIST, 'Reached start of playlist');\n    }\n    await this.play(list[currentIndex - 1].url, type);\n    this.state[type].currentIndex = currentIndex - 1;\n    this.setDuration(type);\n  }\n\n  async stop(type: HMSPlaylistType = HMSPlaylistType.audio): Promise<void> {\n    const manager = type === HMSPlaylistType.audio ? this.audioManager : this.videoManager;\n    manager.getElement()?.pause(); //pause local video/audio and remove tracks in next step\n    await this.removeTracks(type);\n    manager.stop();\n    this.state[type].currentIndex = -1;\n  }\n\n  cleanup() {\n    this.state = { audio: { ...INITIAL_STATE.audio }, video: { ...INITIAL_STATE.video } };\n    this.eventBus.localAudioEnabled.unsubscribe(this.handlePausePlaylist);\n    this.eventBus.localVideoEnabled.unsubscribe(this.handlePausePlaylist);\n    this.audioManager.stop();\n    this.videoManager.stop();\n  }\n\n  onProgress(fn: (progress: HMSPlaylistProgressEvent) => void) {\n    this.videoManager.on('progress', () => {\n      try {\n        fn({\n          type: HMSPlaylistType.video,\n          progress: this.getCurrentProgress(HMSPlaylistType.video),\n        });\n      } catch (error) {\n        HMSLogger.e(this.TAG, 'Error in onProgress callback');\n      }\n    });\n    this.audioManager.on('progress', () => {\n      try {\n        fn({\n          type: HMSPlaylistType.audio,\n          progress: this.getCurrentProgress(HMSPlaylistType.audio),\n        });\n      } catch (error) {\n        HMSLogger.e(this.TAG, 'Error in onProgress callback');\n      }\n    });\n  }\n\n  onNewTrackStart<T>(fn: (item: HMSPlaylistItem<T>) => void) {\n    this.on('newTrackStart', fn);\n  }\n\n  onPlaylistEnded(fn: (type: HMSPlaylistType) => void) {\n    this.on('playlistEnded', fn);\n  }\n\n  onCurrentTrackEnded<T>(fn: (item: HMSPlaylistItem<T>) => void) {\n    this.on('currentTrackEnded', fn);\n  }\n\n  private getElement(type: HMSPlaylistType = HMSPlaylistType.audio) {\n    return type === HMSPlaylistType.audio ? this.audioManager.getElement() : this.videoManager.getElement();\n  }\n\n  private async removeTracks(type: HMSPlaylistType = HMSPlaylistType.audio) {\n    const manager = type === HMSPlaylistType.audio ? this.audioManager : this.videoManager;\n    const tracks = manager.getTracks();\n    for (const trackId of tracks) {\n      await this.removeTrack(trackId);\n    }\n  }\n\n  private async play(url: string, type: HMSPlaylistType = HMSPlaylistType.audio): Promise<void> {\n    const manager = type === HMSPlaylistType.audio ? this.audioManager : this.videoManager;\n    const element = manager.getElement();\n    if (this.isItemCurrentlyPlaying(url, type)) {\n      HMSLogger.w(this.TAG, `The ${type} is currently playing`);\n      return;\n    }\n    if (element?.src.includes(url)) {\n      await element.play();\n    } else {\n      element?.pause();\n      const tracks: MediaStreamTrack[] = await manager.play(url);\n      for (const track of tracks) {\n        await this.addTrack(track, type === HMSPlaylistType.audio ? 'audioplaylist' : 'videoplaylist');\n      }\n    }\n  }\n\n  private isItemCurrentlyPlaying(url: string, type: HMSPlaylistType): boolean {\n    const element = this.getElement(type);\n    return !!(element && !element.paused && element.src.includes(url));\n  }\n\n  private setDuration(type: HMSPlaylistType = HMSPlaylistType.audio) {\n    const element = this.getElement(type);\n    const { list, currentIndex } = this.state[type];\n    if (list[currentIndex]) {\n      list[currentIndex].duration = element?.duration || 0;\n    }\n    this.emit('newTrackStart', list[currentIndex]);\n  }\n\n  private async pause(url: string, type: HMSPlaylistType = HMSPlaylistType.audio): Promise<void> {\n    const el = this.getElement(type);\n    if (el && !el.paused && el.src.includes(url)) {\n      el.pause();\n      HMSLogger.d(this.TAG, 'paused url', url);\n    } else {\n      HMSLogger.w(this.TAG, 'The passed in url is not currently playing');\n    }\n  }\n\n  private handlePausePlaylist = async ({ enabled, track }: { enabled: boolean; track: HMSLocalTrack }) => {\n    if (enabled) {\n      return;\n    }\n    let type: HMSPlaylistType | undefined = undefined;\n    if (track.source === 'audioplaylist') {\n      type = HMSPlaylistType.audio;\n    }\n    if (track.source === 'videoplaylist') {\n      type = HMSPlaylistType.video;\n    }\n    if (!type) {\n      return;\n    }\n    this.getElement(type)?.pause();\n  };\n\n  private addListeners() {\n    this.audioManager.on('ended', () => this.handleEnded(HMSPlaylistType.audio));\n    this.videoManager.on('ended', () => this.handleEnded(HMSPlaylistType.video));\n    this.eventBus.localAudioEnabled.subscribe(this.handlePausePlaylist);\n    this.eventBus.localVideoEnabled.subscribe(this.handlePausePlaylist);\n  }\n\n  /**\n   * Remove tracks if reached the end of list otherwise play next\n   * @param {HMSPlaylistType} type\n   */\n  private async handleEnded(type: HMSPlaylistType = HMSPlaylistType.audio) {\n    const { list, currentIndex, isAutoplayOn } = this.state[type];\n    if (currentIndex === list.length - 1) {\n      await this.stop(type);\n      this.emit('playlistEnded', type);\n    } else {\n      if (isAutoplayOn) {\n        this.playNext(type);\n      } else {\n        // when autoplay not allowed, pause the media element\n        await this.pause(list[currentIndex].url, type);\n      }\n    }\n    this.emit('currentTrackEnded', list[currentIndex]);\n  }\n\n  private addTrack = async (track: MediaStreamTrack, source: string) => {\n    await this.sdk.addTrack(track, source);\n    HMSLogger.d(this.TAG, 'Playlist track added', stringifyMediaStreamTrack(track));\n  };\n\n  private removeTrack = async (trackId: string) => {\n    await this.sdk.removeTrack(trackId, true);\n    HMSLogger.d(this.TAG, 'Playlist track removed', trackId);\n  };\n}\n","import { HMSSessionStore } from '../interfaces';\nimport ITransport from '../transport/ITransport';\nimport { convertDateNumToDate } from '../utils/date';\n\nexport class SessionStore implements HMSSessionStore {\n  private observedKeys: Set<string> = new Set();\n\n  constructor(private transport: ITransport) {}\n\n  async get(key: string) {\n    const { data, updated_at } = await this.transport.getSessionMetadata(key);\n\n    return { value: data, updatedAt: convertDateNumToDate(updated_at) };\n  }\n\n  async set(key: string, data: any) {\n    const { data: value, updated_at } = await this.transport.setSessionMetadata({ key, data });\n    const updatedAt = convertDateNumToDate(updated_at);\n    return { value, updatedAt };\n  }\n\n  async observe(keys: string[]) {\n    const prevObservedKeys = new Set(this.observedKeys);\n    keys.forEach(key => this.observedKeys.add(key));\n\n    if (this.observedKeys.size !== prevObservedKeys.size) {\n      try {\n        await this.transport.listenMetadataChange(Array.from(this.observedKeys));\n      } catch (e) {\n        this.observedKeys = prevObservedKeys;\n        throw e;\n      }\n    }\n  }\n\n  async unobserve(keys: string[]) {\n    const prevObservedKeys = new Set(this.observedKeys);\n    this.observedKeys = new Set([...this.observedKeys].filter(key => !keys.includes(key)));\n\n    if (this.observedKeys.size !== prevObservedKeys.size) {\n      try {\n        await this.transport.listenMetadataChange(Array.from(this.observedKeys));\n      } catch (e) {\n        this.observedKeys = prevObservedKeys;\n        throw e;\n      }\n    }\n  }\n}\n","export class JoinParameters {\n  constructor(\n    public authToken: string,\n    public peerId: string,\n    public peerName: string = '',\n    public data: string = '',\n    public endpoint: string = 'https://prod-init.100ms.live/init',\n    public autoSubscribeVideo: boolean = false,\n  ) {}\n}\n","export enum TransportFailureCategory {\n  ConnectFailed,\n  SignalDisconnect,\n  JoinWSMessageFailed,\n  PublishIceConnectionFailed,\n  SubscribeIceConnectionFailed,\n}\n\nexport const Dependencies = {\n  [TransportFailureCategory.ConnectFailed]: [],\n  [TransportFailureCategory.SignalDisconnect]: [],\n  [TransportFailureCategory.JoinWSMessageFailed]: [TransportFailureCategory.SignalDisconnect],\n  [TransportFailureCategory.PublishIceConnectionFailed]: [TransportFailureCategory.SignalDisconnect],\n  [TransportFailureCategory.SubscribeIceConnectionFailed]: [TransportFailureCategory.SignalDisconnect],\n};\n","export enum TransportState {\n  Disconnected = 'Disconnected',\n  Connecting = 'Connecting',\n  Joined = 'Joined',\n  Preview = 'Preview',\n  Failed = 'Failed',\n  Reconnecting = 'Reconnecting',\n  Leaving = 'Leaving',\n}\n","export interface PromiseCallbacks<T, K = void> {\n  resolve: (value: T) => void;\n  reject: (reason?: any) => void;\n  metadata?: K;\n}\n\nexport class PromiseWithCallbacks<T> {\n  promise: Promise<T>;\n  resolve!: (value: T) => void;\n  reject!: (reason?: any) => void;\n\n  constructor(cb: (resolve: (value: T) => void, reject: (reason?: any) => void) => any) {\n    this.promise = new Promise<T>((resolve, reject) => {\n      this.resolve = resolve;\n      this.reject = reject;\n      cb(resolve, reject);\n    });\n  }\n}\n","import { Dependencies as TFCDependencies, TransportFailureCategory as TFC } from './models/TransportFailureCategory';\nimport { TransportState } from './models/TransportState';\nimport { HMSException } from '../error/HMSException';\nimport { MAX_TRANSPORT_RETRIES, MAX_TRANSPORT_RETRY_DELAY } from '../utils/constants';\nimport HMSLogger from '../utils/logger';\nimport { PromiseWithCallbacks } from '../utils/promise';\n\n/**\n * Task which is executed by [RetryScheduler.schedule] until max retry count\n * is reached.\n *\n * Any exception raised while executing the task assumes that task is failed.\n * Failed tasks are retried if max retry count is not reached.\n *\n * @returns True if the task if successful, otherwise False\n *\n *\n */\ntype RetryTask = () => Promise<boolean>;\n\ninterface ScheduleTaskParams {\n  category: TFC;\n  error: HMSException;\n  task: RetryTask;\n  originalState: TransportState;\n  maxFailedRetries?: number;\n  changeState?: boolean;\n}\n\nexport class RetryScheduler {\n  private readonly TAG = '[RetryScheduler]';\n  private inProgress = new Map<TFC, PromiseWithCallbacks<number>>();\n  private retryTaskIds: number[] = [];\n\n  constructor(\n    private onStateChange: (state: TransportState, error?: HMSException) => Promise<void>,\n    private sendEvent: (error: HMSException, category: TFC) => void,\n  ) {}\n\n  async schedule({\n    category,\n    error,\n    task,\n    originalState,\n    maxFailedRetries = MAX_TRANSPORT_RETRIES,\n    changeState = true,\n  }: ScheduleTaskParams) {\n    await this.scheduleTask({ category, error, changeState, task, originalState, maxFailedRetries });\n  }\n\n  reset() {\n    this.retryTaskIds.forEach(future => clearTimeout(future));\n    this.retryTaskIds = [];\n    this.inProgress.clear();\n  }\n\n  isTaskInProgress(category: TFC) {\n    return !!this.inProgress.get(category);\n  }\n\n  // eslint-disable-next-line complexity\n  private async scheduleTask({\n    category,\n    error,\n    changeState,\n    task,\n    originalState,\n    maxFailedRetries = MAX_TRANSPORT_RETRIES,\n    failedRetryCount = 0,\n  }: ScheduleTaskParams & { failedRetryCount?: number }): Promise<void> {\n    HMSLogger.d(this.TAG, 'schedule: ', { category: TFC[category], error });\n\n    // First schedule call\n    if (failedRetryCount === 0) {\n      const inProgressTask = this.inProgress.get(category);\n      if (inProgressTask) {\n        HMSLogger.d(this.TAG, `schedule: Already a task for ${TFC[category]} scheduled, waiting for its completion`);\n        await inProgressTask.promise;\n        return;\n      }\n\n      const taskPromise = new PromiseWithCallbacks<number>((_, __) => {});\n      this.inProgress.set(category, taskPromise);\n\n      this.sendEvent(error, category);\n    }\n\n    let hasFailedDependency = false;\n    const dependencies = TFCDependencies[category];\n\n    for (const dependencyIndexString in dependencies) {\n      const dependency = dependencies[parseInt(dependencyIndexString)];\n      try {\n        const dependencyTask = this.inProgress.get(dependency);\n        if (dependencyTask) {\n          HMSLogger.d(\n            this.TAG,\n            `schedule: Suspending retry task of ${TFC[category]}, waiting for ${TFC[dependency]} to recover`,\n          );\n          await dependencyTask.promise;\n          HMSLogger.d(\n            this.TAG,\n            `schedule: Resuming retry task ${TFC[category]} as it's dependency ${TFC[dependency]} is recovered`,\n          );\n        }\n      } catch (ex) {\n        HMSLogger.d(\n          this.TAG,\n          `schedule: Stopping retry task of ${TFC[category]} as it's dependency ${TFC[dependency]} failed to recover`,\n        );\n        hasFailedDependency = true;\n        break;\n      }\n    }\n\n    if (failedRetryCount >= maxFailedRetries || hasFailedDependency) {\n      error.description += `. [${TFC[category]}] Could not recover after ${failedRetryCount} tries`;\n\n      if (hasFailedDependency) {\n        error.description += ` Could not recover all of it's required dependencies - [${(dependencies as Array<TFC>)\n          .map(dep => TFC[dep])\n          .toString()}]`;\n      }\n      error.isTerminal = true;\n\n      // @NOTE: Don't reject to throw error for dependencies, use onStateChange\n      // const taskPromise = this.inProgress.get(category);\n      this.inProgress.delete(category);\n      // taskPromise?.reject(error);\n      this.sendEvent(error, category);\n\n      this.reset();\n\n      if (changeState) {\n        this.onStateChange(TransportState.Failed, error);\n      } else {\n        throw error;\n      }\n\n      return;\n    }\n\n    if (changeState) {\n      this.onStateChange(TransportState.Reconnecting, error);\n    }\n\n    const delay = this.getDelayForRetryCount(category, failedRetryCount);\n\n    HMSLogger.d(\n      this.TAG,\n      `schedule: [${TFC[category]}] [failedRetryCount=${failedRetryCount}] Scheduling retry task in ${delay}ms`,\n    );\n\n    let taskSucceeded: boolean;\n    try {\n      taskSucceeded = await this.setTimeoutPromise(task, delay);\n    } catch (ex) {\n      taskSucceeded = false;\n      HMSLogger.w(\n        this.TAG,\n        `[${TFC[category]}] Un-caught exception ${(ex as HMSException).name} in retry-task, initiating retry`,\n        ex,\n      );\n    }\n\n    if (taskSucceeded) {\n      const taskPromise = this.inProgress.get(category);\n      this.inProgress.delete(category);\n      taskPromise?.resolve(failedRetryCount);\n\n      if (changeState && this.inProgress.size === 0) {\n        this.onStateChange(originalState);\n      }\n      HMSLogger.d(this.TAG, `schedule: [${TFC[category]}] [failedRetryCount=${failedRetryCount}] Recovered ♻️`);\n    } else {\n      await this.scheduleTask({\n        category,\n        error,\n        changeState,\n        task,\n        originalState,\n        maxFailedRetries,\n        failedRetryCount: failedRetryCount + 1,\n      });\n    }\n  }\n\n  private getBaseDelayForTask(category: TFC, n: number) {\n    if (category === TFC.JoinWSMessageFailed) {\n      // linear backoff(2 + jitter for every retry)\n      return 2;\n    }\n    // exponential backoff\n    return Math.pow(2, n);\n  }\n\n  private getDelayForRetryCount(category: TFC, n: number) {\n    const delay = this.getBaseDelayForTask(category, n);\n    const jitter = category === TFC.JoinWSMessageFailed ? Math.random() * 2 : Math.random();\n    return Math.round(Math.min(delay + jitter, MAX_TRANSPORT_RETRY_DELAY) * 1000);\n  }\n\n  private async setTimeoutPromise<T>(task: () => Promise<T>, delay: number): Promise<T> {\n    return new Promise((resolve, reject) => {\n      const timeoutId = window.setTimeout(async () => {\n        try {\n          const value: T = await task();\n          value && this.retryTaskIds.splice(this.retryTaskIds.indexOf(timeoutId), 1);\n          resolve(value);\n        } catch (error) {\n          reject(error);\n        }\n      }, delay);\n\n      this.retryTaskIds.push(timeoutId);\n    });\n  }\n}\n","import { ANALYTICS_BUFFER_SIZE } from '../../utils/constants';\nimport { LocalStorage } from '../../utils/local-storage';\nimport { Queue } from '../../utils/queue';\nimport AnalyticsEvent from '../AnalyticsEvent';\n\nexport class LocalStorageEvents extends Queue<AnalyticsEvent> {\n  private localStorage = new LocalStorage<AnalyticsEvent[]>('hms-analytics');\n\n  constructor() {\n    super(ANALYTICS_BUFFER_SIZE);\n    // @TODO: Currently we don't send failed events of old sessions. So reset localstorage for every session.\n    // Once support for failed events from old sessions is added, remove clear and init queue from localstorage.\n    this.localStorage.clear();\n    this.initLocalStorageQueue();\n  }\n\n  enqueue(event: AnalyticsEvent) {\n    super.enqueue(event);\n    this.localStorage.set(this.storage);\n  }\n\n  dequeue() {\n    const removedEvent = super.dequeue();\n    this.localStorage.set(this.storage);\n    return removedEvent;\n  }\n\n  private initLocalStorageQueue() {\n    this.localStorage.get()?.forEach(event => {\n      const eventInstance = new AnalyticsEvent(event);\n      super.enqueue(eventInstance);\n    });\n  }\n}\n","import AnalyticsEvent from './AnalyticsEvent';\nimport { HTTPAnalyticsTransport } from './HTTPAnalyticsTransport';\nimport { IAnalyticsTransportProvider } from './IAnalyticsTransportProvider';\nimport HMSLogger from '../utils/logger';\nimport { Queue } from '../utils/queue';\n\nexport abstract class AnalyticsTransport {\n  abstract transportProvider: IAnalyticsTransportProvider;\n  abstract failedEvents: Queue<AnalyticsEvent>;\n  private readonly TAG = '[AnalyticsTransport]';\n\n  sendEvent(event: AnalyticsEvent) {\n    try {\n      this.sendSingleEvent(event);\n      this.flushFailedEvents();\n    } catch (error) {\n      HMSLogger.w(this.TAG, 'sendEvent failed', error);\n    }\n  }\n\n  flushFailedEvents(currentPeerId?: string) {\n    try {\n      HMSLogger.d(this.TAG, 'Flushing failed events', this.failedEvents);\n      while (this.failedEvents.size() > 0) {\n        const event = this.failedEvents.dequeue();\n        if (event) {\n          const isEventFromCurrentPeer = event.metadata?.peer.peer_id === currentPeerId;\n          if (isEventFromCurrentPeer || !event.metadata.peer.peer_id) {\n            this.sendSingleEvent(event);\n          } else {\n            HTTPAnalyticsTransport.sendEvent(event);\n          }\n        }\n      }\n    } catch (error) {\n      HMSLogger.w(this.TAG, 'flushFailedEvents failed', error);\n    }\n  }\n\n  private sendSingleEvent(event: AnalyticsEvent) {\n    try {\n      this.transportProvider.sendEvent(event);\n      HMSLogger.d(this.TAG, 'Sent event', event.name, event);\n    } catch (error) {\n      HMSLogger.w(this.TAG, `${this.transportProvider.TAG}.sendEvent failed, adding to local storage events`, {\n        event,\n        error,\n      });\n      this.failedEvents.enqueue(event);\n      throw error;\n    }\n  }\n}\n","import { LocalStorageEvents } from './LocalStoageEvents';\nimport { ISignal } from '../../signal/ISignal';\nimport { AnalyticsTransport } from '../AnalyticsTransport';\n\nexport class SignalAnalyticsTransport extends AnalyticsTransport {\n  failedEvents = new LocalStorageEvents();\n\n  constructor(public transportProvider: ISignal) {\n    super();\n  }\n}\n","import {\n  LocalAudioTrackAnalytics,\n  LocalBaseSample,\n  LocalVideoSample,\n  LocalVideoTrackAnalytics,\n  PublishAnalyticPayload,\n  RemoteAudioSample,\n  RemoteAudioTrackAnalytics,\n  RemoteVideoSample,\n  RemoteVideoTrackAnalytics,\n  SubscribeAnalyticPayload,\n} from './interfaces';\nimport { EventBus } from '../../events/EventBus';\nimport { HMSTrackStats } from '../../interfaces';\nimport { HMSTrack } from '../../internal';\nimport { HMSWebrtcStats } from '../../rtc-stats';\nimport { IStore } from '../../sdk/store';\nimport HMSLogger from '../../utils/logger';\nimport { sleep } from '../../utils/timer-utils';\n\nexport abstract class BaseStatsAnalytics {\n  private shouldSendEvent = false;\n  protected sequenceNum = 1;\n\n  constructor(\n    protected store: IStore,\n    protected eventBus: EventBus,\n    protected readonly sampleWindowSize: number,\n    protected readonly pushInterval: number,\n  ) {\n    this.start();\n  }\n\n  start() {\n    if (this.shouldSendEvent) {\n      return;\n    }\n    this.stop();\n    this.shouldSendEvent = true;\n    this.eventBus.statsUpdate.subscribe(this.handleStatsUpdate.bind(this));\n    this.startLoop().catch(e => HMSLogger.e('[StatsAnanlytics]', e.message));\n  }\n\n  stop = () => {\n    if (this.shouldSendEvent) {\n      this.sendEvent();\n    }\n    this.eventBus.statsUpdate.unsubscribe(this.handleStatsUpdate.bind(this));\n    this.shouldSendEvent = false;\n  };\n\n  private async startLoop() {\n    while (this.shouldSendEvent) {\n      await sleep(this.pushInterval * 1000);\n      this.sendEvent();\n    }\n  }\n\n  protected abstract sendEvent(): void;\n\n  protected abstract toAnalytics(): PublishAnalyticPayload | SubscribeAnalyticPayload;\n\n  protected abstract handleStatsUpdate(hmsStats: HMSWebrtcStats): void;\n}\n\ntype TempPublishStats = HMSTrackStats & { availableOutgoingBitrate?: number };\n\nexport abstract class RunningTrackAnalytics {\n  readonly sampleWindowSize: number;\n  track: HMSTrack;\n  track_id: string;\n  source: string;\n  ssrc: string;\n  kind: string;\n  rid?: string;\n  samples: (LocalBaseSample | LocalVideoSample | RemoteAudioSample | RemoteVideoSample)[] = [];\n\n  protected tempStats: TempPublishStats[] = [];\n\n  constructor({\n    track,\n    ssrc,\n    rid,\n    kind,\n    sampleWindowSize,\n  }: {\n    track: HMSTrack;\n    ssrc: string;\n    kind: string;\n    rid?: string;\n    sampleWindowSize: number;\n  }) {\n    this.track = track;\n    this.ssrc = ssrc;\n    this.rid = rid;\n    this.kind = kind;\n    this.track_id = this.track.trackId;\n    this.source = this.track.source!;\n    this.sampleWindowSize = sampleWindowSize;\n  }\n\n  push(stat: TempPublishStats) {\n    this.tempStats.push(stat);\n\n    if (this.shouldCreateSample()) {\n      this.samples.push(this.createSample());\n      this.tempStats.length = 0;\n    }\n  }\n\n  protected abstract toAnalytics: () =>\n    | LocalAudioTrackAnalytics\n    | LocalVideoTrackAnalytics\n    | RemoteAudioTrackAnalytics\n    | RemoteVideoTrackAnalytics;\n\n  protected abstract createSample: () => LocalBaseSample | LocalVideoSample | RemoteAudioSample | RemoteVideoSample;\n\n  protected getLatestStat() {\n    return this.tempStats[this.tempStats.length - 1];\n  }\n\n  protected getFirstStat() {\n    return this.tempStats[0];\n  }\n\n  protected abstract shouldCreateSample: () => boolean;\n\n  protected calculateSum(key: keyof TempPublishStats) {\n    const checkStat = this.getLatestStat()[key];\n    if (typeof checkStat !== 'number') {\n      return;\n    }\n    return this.tempStats.reduce((partialSum, stat) => {\n      return partialSum + ((stat[key] || 0) as number);\n    }, 0);\n  }\n\n  protected calculateAverage(key: keyof TempPublishStats, round = true) {\n    const sum = this.calculateSum(key);\n    const avg = sum !== undefined ? sum / this.tempStats.length : undefined;\n    return avg ? (round ? Math.round(avg) : avg) : undefined;\n  }\n\n  protected calculateDifferenceForSample(key: keyof TempPublishStats) {\n    const firstValue = Number(this.tempStats[0][key]) || 0;\n    const latestValue = Number(this.getLatestStat()[key]) || 0;\n\n    return latestValue - firstValue;\n  }\n\n  protected calculateInstancesOfHigh(key: keyof TempPublishStats, threshold: number) {\n    const checkStat = this.getLatestStat()[key];\n    if (typeof checkStat !== 'number') {\n      return;\n    }\n\n    return this.tempStats.reduce((partialSum, stat) => {\n      return partialSum + (((stat[key] || 0) as number) > threshold ? 1 : 0);\n    }, 0);\n  }\n}\n\nexport const hasResolutionChanged = (newStat: TempPublishStats, prevStat: TempPublishStats) =>\n  newStat && prevStat && (newStat.frameWidth !== prevStat.frameWidth || newStat.frameHeight !== prevStat.frameHeight);\n\nexport const hasEnabledStateChanged = (newStat: TempPublishStats, prevStat: TempPublishStats) =>\n  newStat && prevStat && newStat.enabled !== prevStat.enabled;\n\nexport const removeUndefinedFromObject = <T extends Record<string, any>>(data: T) => {\n  return Object.entries(data)\n    .filter(([, value]) => value !== undefined)\n    .reduce((obj, [key, value]) => {\n      obj[key as keyof T] = value;\n      return obj;\n    }, {} as T);\n};\n","import {\n  BaseStatsAnalytics,\n  hasEnabledStateChanged,\n  hasResolutionChanged,\n  removeUndefinedFromObject,\n  RunningTrackAnalytics,\n} from './BaseStatsAnalytics';\nimport {\n  LocalAudioTrackAnalytics,\n  LocalBaseSample,\n  LocalVideoSample,\n  LocalVideoTrackAnalytics,\n  PublishAnalyticPayload,\n} from './interfaces';\nimport { HMSTrackStats } from '../../interfaces';\nimport { HMSWebrtcStats } from '../../rtc-stats';\nimport { PUBLISH_STATS_SAMPLE_WINDOW } from '../../utils/constants';\nimport AnalyticsEventFactory from '../AnalyticsEventFactory';\n\nexport class PublishStatsAnalytics extends BaseStatsAnalytics {\n  protected trackAnalytics: Map<string, RunningLocalTrackAnalytics> = new Map();\n\n  protected toAnalytics(): PublishAnalyticPayload {\n    const audio: LocalAudioTrackAnalytics[] = [];\n    const video: LocalVideoTrackAnalytics[] = [];\n    this.trackAnalytics.forEach(trackAnalytic => {\n      if (trackAnalytic.track.type === 'audio') {\n        audio.push(trackAnalytic.toAnalytics());\n      } else if (trackAnalytic.track.type === 'video') {\n        video.push(trackAnalytic.toAnalytics());\n      }\n    });\n    return {\n      audio,\n      video,\n      joined_at: this.store.getRoom()?.joinedAt?.getTime()!,\n      sequence_num: this.sequenceNum++,\n      max_window_sec: PUBLISH_STATS_SAMPLE_WINDOW,\n    };\n  }\n\n  protected sendEvent() {\n    this.eventBus.analytics.publish(AnalyticsEventFactory.publishStats(this.toAnalytics()));\n  }\n\n  protected handleStatsUpdate(hmsStats: HMSWebrtcStats) {\n    const localTracksStats = hmsStats.getLocalTrackStats();\n    Object.keys(localTracksStats).forEach(trackIDBeingSent => {\n      const trackStats = localTracksStats[trackIDBeingSent];\n      const track = this.store.getLocalPeerTracks().find(track => track.getTrackIDBeingSent() === trackIDBeingSent);\n      Object.keys(trackStats).forEach(statId => {\n        const layerStats = trackStats[statId];\n        const identifier = track && this.getTrackIdentifier(track?.trackId, layerStats);\n        if (identifier && this.trackAnalytics.has(identifier)) {\n          this.trackAnalytics.get(identifier)?.push({\n            ...layerStats,\n            availableOutgoingBitrate: hmsStats.getLocalPeerStats()?.publish?.availableOutgoingBitrate,\n          });\n        } else {\n          if (track) {\n            const trackAnalytics = new RunningLocalTrackAnalytics({\n              track,\n              sampleWindowSize: this.sampleWindowSize,\n              rid: layerStats.rid,\n              ssrc: layerStats.ssrc.toString(),\n              kind: layerStats.kind,\n            });\n            trackAnalytics.push({\n              ...layerStats,\n              availableOutgoingBitrate: hmsStats.getLocalPeerStats()?.publish?.availableOutgoingBitrate,\n            });\n            this.trackAnalytics.set(this.getTrackIdentifier(track?.trackId, layerStats), trackAnalytics);\n          }\n        }\n      });\n    });\n  }\n\n  private getTrackIdentifier(trackId: string, stats: HMSTrackStats) {\n    return stats.rid ? `${trackId}:${stats.rid}` : trackId;\n  }\n}\n\nclass RunningLocalTrackAnalytics extends RunningTrackAnalytics {\n  samples: (LocalBaseSample | LocalVideoSample)[] = [];\n\n  protected createSample = (): LocalBaseSample | LocalVideoSample => {\n    const latestStat = this.getLatestStat();\n\n    const qualityLimitationDurations = latestStat.qualityLimitationDurations;\n    const total_quality_limitation = qualityLimitationDurations && {\n      bandwidth_sec: qualityLimitationDurations.bandwidth,\n      cpu_sec: qualityLimitationDurations.cpu,\n      other_sec: qualityLimitationDurations.other,\n    };\n\n    const resolution = latestStat.frameHeight\n      ? {\n          height_px: this.getLatestStat().frameHeight,\n          width_px: this.getLatestStat().frameWidth,\n        }\n      : undefined;\n    const avg_jitter = this.calculateAverage('jitter', false);\n    const avg_jitter_ms = avg_jitter ? Math.round(avg_jitter * 1000) : undefined;\n\n    const avg_round_trip_time = this.calculateAverage('roundTripTime', false);\n    const avg_round_trip_time_ms = avg_round_trip_time ? Math.round(avg_round_trip_time * 1000) : undefined;\n\n    return removeUndefinedFromObject({\n      timestamp: Date.now(),\n      avg_available_outgoing_bitrate_bps: this.calculateAverage('availableOutgoingBitrate'),\n      avg_bitrate_bps: this.calculateAverage('bitrate'),\n      avg_fps: this.calculateAverage('framesPerSecond'),\n      total_packets_lost: this.calculateDifferenceForSample('packetsLost'),\n      total_packets_sent: this.calculateDifferenceForSample('packetsSent'),\n      total_packet_sent_delay_sec: parseFloat(this.calculateDifferenceForSample('totalPacketSendDelay').toFixed(4)),\n      total_fir_count: this.calculateDifferenceForSample('firCount'),\n      total_pli_count: this.calculateDifferenceForSample('pliCount'),\n      total_nack_count: this.calculateDifferenceForSample('nackCount'),\n      avg_jitter_ms,\n      avg_round_trip_time_ms,\n      total_quality_limitation,\n      resolution,\n    });\n  };\n\n  protected shouldCreateSample = () => {\n    const length = this.tempStats.length;\n    const newStat = this.tempStats[length - 1];\n    const prevStat = this.tempStats[length - 2];\n\n    return (\n      length === PUBLISH_STATS_SAMPLE_WINDOW ||\n      hasEnabledStateChanged(newStat, prevStat) ||\n      (newStat.kind === 'video' && hasResolutionChanged(newStat, prevStat))\n    );\n  };\n\n  toAnalytics = (): LocalAudioTrackAnalytics | LocalVideoTrackAnalytics => {\n    return {\n      track_id: this.track_id,\n      ssrc: this.ssrc,\n      source: this.source,\n      rid: this.rid,\n      samples: this.samples,\n    };\n  };\n}\n","import {\n  BaseStatsAnalytics,\n  hasEnabledStateChanged,\n  hasResolutionChanged,\n  removeUndefinedFromObject,\n  RunningTrackAnalytics,\n} from './BaseStatsAnalytics';\nimport {\n  RemoteAudioSample,\n  RemoteAudioTrackAnalytics,\n  RemoteVideoSample,\n  RemoteVideoTrackAnalytics,\n  SubscribeAnalyticPayload,\n} from './interfaces';\nimport { HMSWebrtcStats } from '../../rtc-stats';\nimport { SUBSCRIBE_STATS_SAMPLE_WINDOW } from '../../utils/constants';\nimport AnalyticsEventFactory from '../AnalyticsEventFactory';\n\nexport class SubscribeStatsAnalytics extends BaseStatsAnalytics {\n  protected trackAnalytics: Map<string, RunningRemoteTrackAnalytics> = new Map();\n\n  protected toAnalytics(): SubscribeAnalyticPayload {\n    const audio: RemoteAudioTrackAnalytics[] = [];\n    const video: RemoteVideoTrackAnalytics[] = [];\n    this.trackAnalytics.forEach(trackAnalytic => {\n      if (trackAnalytic.track.type === 'audio') {\n        audio.push(trackAnalytic.toAnalytics());\n      } else if (trackAnalytic.track.type === 'video') {\n        video.push(trackAnalytic.toAnalytics());\n      }\n    });\n    return {\n      audio,\n      video,\n      joined_at: this.store.getRoom()?.joinedAt?.getTime()!,\n      sequence_num: this.sequenceNum++,\n      max_window_sec: SUBSCRIBE_STATS_SAMPLE_WINDOW,\n    };\n  }\n\n  protected sendEvent() {\n    this.eventBus.analytics.publish(AnalyticsEventFactory.subscribeStats(this.toAnalytics()));\n  }\n\n  protected handleStatsUpdate(hmsStats: HMSWebrtcStats) {\n    const remoteTracksStats = hmsStats.getAllRemoteTracksStats();\n    Object.keys(remoteTracksStats).forEach(trackID => {\n      const trackStats = remoteTracksStats[trackID];\n      const track = this.store.getTrackById(trackID);\n      if (this.trackAnalytics.has(trackID)) {\n        this.trackAnalytics.get(trackID)?.push({ ...trackStats });\n      } else {\n        if (track) {\n          const trackAnalytics = new RunningRemoteTrackAnalytics({\n            track,\n            sampleWindowSize: this.sampleWindowSize,\n            ssrc: trackStats.ssrc.toString(),\n            kind: trackStats.kind,\n          });\n          trackAnalytics.push({ ...trackStats });\n          this.trackAnalytics.set(trackID, trackAnalytics);\n        }\n      }\n    });\n  }\n}\n\nclass RunningRemoteTrackAnalytics extends RunningTrackAnalytics {\n  samples: (RemoteAudioSample | RemoteVideoSample)[] = [];\n\n  protected createSample = (): RemoteAudioSample | RemoteVideoSample => {\n    const latestStat = this.getLatestStat();\n    const firstStat = this.getFirstStat();\n\n    const baseSample = {\n      timestamp: Date.now(),\n      fec_packets_discarded: this.calculateDifferenceForSample('fecPacketsDiscarded'),\n      fec_packets_received: this.calculateDifferenceForSample('fecPacketsReceived'),\n      total_samples_duration: this.calculateDifferenceForSample('totalSamplesDuration'),\n      total_packets_received: this.calculateDifferenceForSample('packetsReceived'),\n      total_packets_lost: this.calculateDifferenceForSample('packetsLost'),\n      total_pli_count: this.calculateDifferenceForSample('pliCount'),\n      total_nack_count: this.calculateDifferenceForSample('nackCount'),\n    };\n\n    if (latestStat.kind === 'video') {\n      return removeUndefinedFromObject<RemoteAudioSample | RemoteVideoSample>(baseSample);\n    } else {\n      const audio_concealed_samples =\n        (latestStat.concealedSamples || 0) -\n        (latestStat.silentConcealedSamples || 0) -\n        ((firstStat.concealedSamples || 0) - (firstStat.silentConcealedSamples || 0));\n\n      return removeUndefinedFromObject<RemoteAudioSample>(\n        Object.assign(baseSample, {\n          audio_concealed_samples,\n          audio_level: this.calculateInstancesOfHigh('audioLevel', 0.05),\n          audio_total_samples_received: this.calculateDifferenceForSample('totalSamplesReceived'),\n          audio_concealment_events: this.calculateDifferenceForSample('concealmentEvents'),\n        }),\n      );\n    }\n  };\n\n  protected shouldCreateSample = () => {\n    const length = this.tempStats.length;\n    const newStat = this.tempStats[length - 1];\n    const prevStat = this.tempStats[length - 2];\n\n    return (\n      length === SUBSCRIBE_STATS_SAMPLE_WINDOW ||\n      hasEnabledStateChanged(newStat, prevStat) ||\n      (newStat.kind === 'video' && hasResolutionChanged(newStat, prevStat))\n    );\n  };\n\n  toAnalytics = (): RemoteAudioTrackAnalytics | RemoteVideoTrackAnalytics => {\n    return {\n      track_id: this.track_id,\n      ssrc: this.ssrc,\n      source: this.source,\n      rid: this.rid,\n      samples: this.samples,\n    };\n  };\n}\n","// Sent in trickle messages as target - biz understands only 0 and 1\nexport enum HMSConnectionRole {\n  Publish = 0,\n  Subscribe = 1,\n}\n\nexport interface HMSTrickle {\n  candidate: RTCIceCandidateInit;\n  target: HMSConnectionRole;\n}\n","import * as sdpTransform from 'sdp-transform';\nimport { isPresent } from './validations';\nimport { TrackState } from '../notification-manager';\n\n/**\n * @DISCUSS: Should we have a wrapper over RTCSessionDescriptionInit(SDP) and have these methods in it?\n */\n\nexport function fixMsid(desc: RTCSessionDescriptionInit, tracks?: Map<string, TrackState>): RTCSessionDescriptionInit {\n  const parsedSdp = sdpTransform.parse(desc.sdp!);\n\n  if (!parsedSdp.origin?.username.startsWith('mozilla')) {\n    // This isn't firefox, so we return the original offer without doing anything\n    return desc;\n  }\n\n  const mediaTracks = tracks ? Array.from(tracks.values()) : [];\n\n  parsedSdp.media.forEach(m => {\n    const streamId = m.msid?.split(' ')[0];\n    // check for both type and streamid as both video and screenshare have same type but different stream_id\n    const trackId = mediaTracks.find(val => val.type === m.type && val.stream_id === streamId)?.track_id;\n    if (trackId) {\n      m.msid = m.msid?.replace(/\\s(.+)/, ` ${trackId}`);\n    }\n  });\n\n  return { type: desc.type, sdp: sdpTransform.write(parsedSdp) };\n}\n\n/**\n * Get the track ID from the SDP using the transceiver's mid from RTCTrackEvent\n * @TODO: This could take more processing time in a large room and when the SDP is big.\n * Consider using this for Firefox only?\n */\nexport function getSdpTrackIdForMid(\n  desc?: RTCSessionDescriptionInit | null,\n  mid?: RTCRtpTransceiver['mid'],\n): string | undefined {\n  if (!desc?.sdp || !mid) {\n    return undefined;\n  }\n  const parsedSdp = sdpTransform.parse(desc.sdp);\n  const trackSection = parsedSdp.media.find(media => isPresent(media.mid) && parseInt(media.mid!) === parseInt(mid));\n  const trackId = trackSection?.msid?.split(' ')[1];\n  return trackId;\n}\n\nexport function enableOpusDtx(desc: RTCSessionDescriptionInit): RTCSessionDescriptionInit {\n  if (desc.sdp!.includes('usedtx=1')) {\n    return desc;\n  }\n\n  return { type: desc.type, sdp: desc.sdp!.replace('useinbandfec=1', 'useinbandfec=1;usedtx=1') };\n}\n","import { HMSConnectionRole } from './model';\nimport { ErrorFactory } from '../error/ErrorFactory';\nimport { HMSAction } from '../error/HMSAction';\nimport { HMSLocalTrack, HMSLocalVideoTrack } from '../media/tracks';\nimport { TrackState } from '../notification-manager';\nimport { ISignal } from '../signal/ISignal';\nimport HMSLogger from '../utils/logger';\nimport { enableOpusDtx, fixMsid } from '../utils/session-description';\n\nconst TAG = '[HMSConnection]';\ninterface RTCIceCandidatePair {\n  local: RTCIceCandidate;\n  remote: RTCIceCandidate;\n}\n\nexport default abstract class HMSConnection {\n  readonly role: HMSConnectionRole;\n  protected readonly signal: ISignal;\n\n  abstract readonly nativeConnection: RTCPeerConnection;\n  /**\n   * We keep a list of pending IceCandidates received\n   * from the signalling server. When the peer-connection\n   * is initialized we call [addIceCandidate] for each.\n   *\n   * WARN:\n   *  - [HMSPublishConnection] keeps the complete list of candidates (for\n   *      ice-connection failed/disconnect) forever.\n   *  - [HMSSubscribeConnection] clears this list as soon as we call [addIceCandidate]\n   */\n  readonly candidates = new Array<RTCIceCandidateInit>();\n\n  selectedCandidatePair?: RTCIceCandidatePair;\n\n  protected constructor(role: HMSConnectionRole, signal: ISignal) {\n    this.role = role;\n    this.signal = signal;\n  }\n\n  public get iceConnectionState(): RTCIceConnectionState {\n    return this.nativeConnection.iceConnectionState;\n  }\n\n  public get connectionState(): RTCPeerConnectionState {\n    return this.nativeConnection.connectionState;\n  }\n\n  private get action() {\n    return this.role === HMSConnectionRole.Publish ? HMSAction.PUBLISH : HMSAction.SUBSCRIBE;\n  }\n\n  addTransceiver(track: MediaStreamTrack, init: RTCRtpTransceiverInit): RTCRtpTransceiver {\n    return this.nativeConnection.addTransceiver(track, init);\n  }\n\n  async createOffer(tracks?: Map<string, TrackState>, options?: RTCOfferOptions): Promise<RTCSessionDescriptionInit> {\n    try {\n      const offer = await this.nativeConnection.createOffer(options);\n      HMSLogger.d(TAG, `[role=${this.role}] createOffer offer=${JSON.stringify(offer, null, 1)}`);\n      return enableOpusDtx(fixMsid(offer, tracks));\n    } catch (error) {\n      throw ErrorFactory.WebrtcErrors.CreateOfferFailed(this.action, (error as Error).message);\n    }\n  }\n\n  async createAnswer(options: RTCOfferOptions | undefined = undefined): Promise<RTCSessionDescriptionInit> {\n    try {\n      const answer = await this.nativeConnection.createAnswer(options);\n      HMSLogger.d(TAG, `[role=${this.role}] createAnswer answer=${JSON.stringify(answer, null, 1)}`);\n      return answer;\n    } catch (error) {\n      throw ErrorFactory.WebrtcErrors.CreateAnswerFailed(this.action, (error as Error).message);\n    }\n  }\n\n  async setLocalDescription(description: RTCSessionDescriptionInit): Promise<void> {\n    try {\n      HMSLogger.d(TAG, `[role=${this.role}] setLocalDescription description=${JSON.stringify(description, null, 1)}`);\n      await this.nativeConnection.setLocalDescription(description);\n    } catch (error) {\n      throw ErrorFactory.WebrtcErrors.SetLocalDescriptionFailed(this.action, (error as Error).message);\n    }\n  }\n\n  async setRemoteDescription(description: RTCSessionDescriptionInit): Promise<void> {\n    try {\n      HMSLogger.d(TAG, `[role=${this.role}] setRemoteDescription description=${JSON.stringify(description, null, 1)}`);\n      await this.nativeConnection.setRemoteDescription(description);\n    } catch (error) {\n      throw ErrorFactory.WebrtcErrors.SetRemoteDescriptionFailed(this.action, (error as Error).message);\n    }\n  }\n\n  async addIceCandidate(candidate: RTCIceCandidateInit): Promise<void> {\n    if (this.nativeConnection.signalingState === 'closed') {\n      HMSLogger.d(TAG, `[role=${this.role}] addIceCandidate signalling state closed`);\n      return;\n    }\n    HMSLogger.d(TAG, `[role=${this.role}] addIceCandidate candidate=${JSON.stringify(candidate, null, 1)}`);\n    await this.nativeConnection.addIceCandidate(candidate);\n  }\n\n  public get remoteDescription(): RTCSessionDescription | null {\n    return this.nativeConnection.remoteDescription;\n  }\n\n  getSenders(): Array<RTCRtpSender> {\n    return this.nativeConnection.getSenders();\n  }\n\n  logSelectedIceCandidatePairs() {\n    /**\n     * for the very first peer in the room we don't have any subscribe ice candidates\n     * because the peer hasn't subscribed to anything.\n     *\n     * For all peers joining after this peer, we have published and subscribed at the time of join itself\n     * so we're able to log both publish and subscribe ice candidates.\n     * Added try catch for the whole section as the getSenders and getReceivers is throwing errors in load test\n     */\n    try {\n      const transmitters = this.role === HMSConnectionRole.Publish ? this.getSenders() : this.getReceivers();\n\n      transmitters.forEach(transmitter => {\n        const kindOfTrack = transmitter.track?.kind;\n        if (transmitter.transport) {\n          const iceTransport = transmitter.transport.iceTransport;\n\n          const logSelectedCandidate = () => {\n            // @ts-expect-error\n            if (typeof iceTransport.getSelectedCandidatePair === 'function') {\n              // @ts-expect-error\n              this.selectedCandidatePair = iceTransport.getSelectedCandidatePair();\n              HMSLogger.d(\n                TAG,\n                `${HMSConnectionRole[this.role]} connection`,\n                `selected ${kindOfTrack || 'unknown'} candidate pair`,\n                JSON.stringify(this.selectedCandidatePair, null, 2),\n              );\n            }\n          };\n\n          // @ts-expect-error\n          if (typeof iceTransport.onselectedcandidatepairchange === 'function') {\n            // @ts-expect-error\n            iceTransport.onselectedcandidatepairchange = logSelectedCandidate;\n          }\n          logSelectedCandidate();\n        }\n      });\n    } catch (error) {\n      HMSLogger.w(\n        TAG,\n        `Error in logging selected ice candidate pair for ${HMSConnectionRole[this.role]} connection`,\n        error,\n      );\n    }\n  }\n\n  removeTrack(sender: RTCRtpSender) {\n    if (this.nativeConnection.signalingState !== 'closed') {\n      this.nativeConnection.removeTrack(sender);\n    }\n  }\n\n  async setMaxBitrateAndFramerate(track: HMSLocalTrack) {\n    const maxBitrate = track.settings.maxBitrate;\n    const maxFramerate = track instanceof HMSLocalVideoTrack && track.settings.maxFramerate;\n    const sender = this.getSenders().find(s => s?.track?.id === track.getTrackIDBeingSent());\n\n    if (sender) {\n      const params = sender.getParameters();\n      // modify only for non-simulcast encodings\n      if (params.encodings.length === 1) {\n        if (maxBitrate) {\n          params.encodings[0].maxBitrate = maxBitrate * 1000;\n        }\n        if (maxFramerate) {\n          // @ts-ignore\n          params.encodings[0].maxFramerate = maxFramerate;\n        }\n      }\n      await sender.setParameters(params);\n    } else {\n      HMSLogger.w(\n        TAG,\n        `no sender found to setMaxBitrate for track - ${track.trackId}, sentTrackId - ${track.getTrackIDBeingSent()}`,\n      );\n    }\n  }\n\n  async getStats() {\n    return await this.nativeConnection.getStats();\n  }\n\n  async close() {\n    this.nativeConnection.close();\n  }\n\n  private getReceivers() {\n    return this.nativeConnection.getReceivers();\n  }\n}\n","import { IPublishConnectionObserver } from './IPublishConnectionObserver';\nimport { ISignal } from '../../signal/ISignal';\nimport { API_DATA_CHANNEL } from '../../utils/constants';\nimport HMSLogger from '../../utils/logger';\nimport HMSConnection from '../HMSConnection';\nimport { HMSConnectionRole } from '../model';\n\nexport default class HMSPublishConnection extends HMSConnection {\n  private readonly TAG = '[HMSPublishConnection]';\n  private readonly observer: IPublishConnectionObserver;\n  readonly nativeConnection: RTCPeerConnection;\n  readonly channel: RTCDataChannel;\n\n  constructor(signal: ISignal, config: RTCConfiguration, observer: IPublishConnectionObserver) {\n    super(HMSConnectionRole.Publish, signal);\n    this.observer = observer;\n\n    this.nativeConnection = new RTCPeerConnection(config);\n    this.channel = this.nativeConnection.createDataChannel(API_DATA_CHANNEL, {\n      protocol: 'SCTP',\n    });\n    this.channel.onerror = ev => HMSLogger.e(this.TAG, `publish data channel onerror ${ev}`, ev);\n\n    this.nativeConnection.onicecandidate = ({ candidate }) => {\n      if (candidate) {\n        signal.trickle(this.role, candidate);\n      }\n    };\n\n    this.nativeConnection.oniceconnectionstatechange = () => {\n      this.observer.onIceConnectionChange(this.nativeConnection.iceConnectionState);\n    };\n\n    // @TODO(eswar): Remove this. Use iceconnectionstate change with interval and threshold.\n    this.nativeConnection.onconnectionstatechange = () => {\n      this.observer.onConnectionStateChange(this.nativeConnection.connectionState);\n\n      // here it replaces the original listener if already present and\n      // handles cases where sctp transport is reinitialised\n      if (this.nativeConnection.sctp) {\n        this.nativeConnection.sctp.transport.onstatechange = () => {\n          this.observer.onDTLSTransportStateChange(this.nativeConnection.sctp?.transport.state);\n        };\n        this.nativeConnection.sctp.transport.onerror = (event: Event) => {\n          this.observer.onDTLSTransportError(\n            new Error((event as RTCErrorEvent)?.error?.errorDetail) || 'DTLS Transport failed',\n          );\n        };\n      }\n    };\n  }\n\n  initAfterJoin() {\n    this.nativeConnection.onnegotiationneeded = async () => {\n      HMSLogger.d(this.TAG, `onnegotiationneeded`);\n      await this.observer.onRenegotiationNeeded();\n    };\n  }\n}\n","import EventEmitter from 'eventemitter2';\nimport { v4 as uuid } from 'uuid';\nimport ISubscribeConnectionObserver from './ISubscribeConnectionObserver';\nimport { HMSRemoteStream, HMSSimulcastLayer } from '../../internal';\nimport { HMSRemoteAudioTrack } from '../../media/tracks/HMSRemoteAudioTrack';\nimport { HMSRemoteVideoTrack } from '../../media/tracks/HMSRemoteVideoTrack';\nimport { InitFlags } from '../../signal/init/models';\nimport { ISignal } from '../../signal/ISignal';\nimport { API_DATA_CHANNEL } from '../../utils/constants';\nimport HMSLogger from '../../utils/logger';\nimport { getSdpTrackIdForMid } from '../../utils/session-description';\nimport { workerSleep } from '../../utils/timer-utils';\nimport { PreferAudioLayerParams, PreferLayerResponse, PreferVideoLayerParams } from '../channel-messages';\nimport HMSConnection from '../HMSConnection';\nimport HMSDataChannel from '../HMSDataChannel';\nimport { HMSConnectionRole } from '../model';\n\nexport default class HMSSubscribeConnection extends HMSConnection {\n  private readonly TAG = '[HMSSubscribeConnection]';\n  private readonly remoteStreams = new Map<string, HMSRemoteStream>();\n  private readonly observer: ISubscribeConnectionObserver;\n  private readonly MAX_RETRIES = 3;\n\n  readonly nativeConnection: RTCPeerConnection;\n\n  private pendingMessageQueue: string[] = [];\n\n  private apiChannel?: HMSDataChannel;\n  private eventEmitter = new EventEmitter({ maxListeners: 60 });\n\n  private initNativeConnectionCallbacks() {\n    this.nativeConnection.oniceconnectionstatechange = () => {\n      this.observer.onIceConnectionChange(this.nativeConnection.iceConnectionState);\n    };\n\n    // @TODO(eswar): Remove this. Use iceconnectionstate change with interval and threshold.\n    this.nativeConnection.onconnectionstatechange = () => {\n      this.observer.onConnectionStateChange(this.nativeConnection.connectionState);\n    };\n\n    this.nativeConnection.ondatachannel = e => {\n      if (e.channel.label !== API_DATA_CHANNEL) {\n        // TODO: this.observer.onDataChannel(e.channel);\n        return;\n      }\n\n      this.apiChannel = new HMSDataChannel(\n        e.channel,\n        {\n          onMessage: (value: string) => {\n            this.eventEmitter.emit('message', value);\n            this.observer.onApiChannelMessage(value);\n          },\n        },\n        `role=${this.role}`,\n      );\n\n      e.channel.onopen = this.handlePendingApiMessages;\n    };\n\n    this.nativeConnection.onicecandidate = e => {\n      if (e.candidate !== null) {\n        this.signal.trickle(this.role, e.candidate);\n      }\n    };\n\n    this.nativeConnection.ontrack = e => {\n      const stream = e.streams[0];\n      const streamId = stream.id;\n\n      if (!this.remoteStreams.has(streamId)) {\n        const remote = new HMSRemoteStream(stream, this);\n        this.remoteStreams.set(streamId, remote);\n      }\n\n      stream.addEventListener('removetrack', (ev: MediaStreamTrackEvent) => {\n        if (ev.track.id !== e.track.id) {\n          return;\n        }\n        /*\n         * this match has to be with nativetrack.id instead of track.trackId as the latter refers to sdp track id for\n         * ease of correlating update messages coming from the backend. The two track ids are usually the same, but\n         * can be different for some browsers. checkout sdptrackid field in HMSTrack for more details.\n         */\n        const toRemoveTrackIdx = remote.tracks.findIndex(\n          track => track.nativeTrack.id === ev.track.id && e.transceiver.mid === track.transceiver?.mid,\n        );\n        if (toRemoveTrackIdx >= 0) {\n          const toRemoveTrack = remote.tracks[toRemoveTrackIdx];\n          this.observer.onTrackRemove(toRemoveTrack);\n          remote.tracks.splice(toRemoveTrackIdx, 1);\n          // If the length becomes 0 we assume that stream is removed entirely\n          if (remote.tracks.length === 0) {\n            this.remoteStreams.delete(streamId);\n          }\n        }\n      });\n\n      const remote = this.remoteStreams.get(streamId)!;\n      const TrackCls = e.track.kind === 'audio' ? HMSRemoteAudioTrack : HMSRemoteVideoTrack;\n      const track = new TrackCls(remote, e.track);\n      // reset the simulcast layer to none when new video tracks are added, UI will subscribe when required\n      if (e.track.kind === 'video') {\n        remote.setVideoLayerLocally(HMSSimulcastLayer.NONE, 'addTrack', 'subscribeConnection');\n      }\n      track.transceiver = e.transceiver;\n      const trackId = getSdpTrackIdForMid(this.remoteDescription, e.transceiver?.mid);\n      trackId && track.setSdpTrackId(trackId);\n      remote.tracks.push(track);\n      this.observer.onTrackAdd(track);\n    };\n  }\n\n  constructor(\n    signal: ISignal,\n    config: RTCConfiguration,\n    private isFlagEnabled: (flag: InitFlags) => boolean,\n    observer: ISubscribeConnectionObserver,\n  ) {\n    super(HMSConnectionRole.Subscribe, signal);\n    this.observer = observer;\n\n    this.nativeConnection = new RTCPeerConnection(config);\n    this.initNativeConnectionCallbacks();\n  }\n\n  sendOverApiDataChannel(message: string) {\n    if (this.apiChannel && this.apiChannel.readyState === 'open') {\n      this.apiChannel.send(message);\n    } else {\n      HMSLogger.w(this.TAG, `API Data channel not ${this.apiChannel ? 'open' : 'present'}, queueing`, message);\n      this.pendingMessageQueue.push(message);\n    }\n  }\n\n  async sendOverApiDataChannelWithResponse<T extends PreferAudioLayerParams | PreferVideoLayerParams>(\n    message: T,\n    requestId?: string,\n  ): Promise<PreferLayerResponse> {\n    const id = uuid();\n    if (message.method === 'prefer-video-track-state') {\n      const disableAutoUnsubscribe = this.isFlagEnabled(InitFlags.FLAG_DISABLE_VIDEO_TRACK_AUTO_UNSUBSCRIBE);\n      if (disableAutoUnsubscribe && message.params.max_spatial_layer === HMSSimulcastLayer.NONE) {\n        HMSLogger.d(this.TAG, 'video auto unsubscribe is disabled, request is ignored');\n        return { id } as PreferLayerResponse;\n      }\n    }\n    const request = JSON.stringify({\n      id: requestId || id,\n      jsonrpc: '2.0',\n      ...message,\n    });\n    return this.sendMessage(request, id);\n  }\n\n  async close() {\n    await super.close();\n    this.apiChannel?.close();\n  }\n\n  private handlePendingApiMessages = () => {\n    this.eventEmitter.emit('open', true);\n    if (this.pendingMessageQueue.length > 0) {\n      HMSLogger.d(this.TAG, 'Found pending message queue, sending messages');\n      this.pendingMessageQueue.forEach(msg => this.sendOverApiDataChannel(msg));\n      this.pendingMessageQueue.length = 0;\n    }\n  };\n\n  // eslint-disable-next-line complexity\n  private sendMessage = async (request: string, requestId: string): Promise<PreferLayerResponse> => {\n    if (this.apiChannel?.readyState !== 'open') {\n      await this.eventEmitter.waitFor('open');\n    }\n    let response: PreferLayerResponse;\n    for (let i = 0; i < this.MAX_RETRIES; i++) {\n      this.apiChannel!.send(request);\n      response = await this.waitForResponse(requestId);\n      const error = response.error;\n      if (error) {\n        // Don't retry or do anything, track is already removed\n        if (error.code === 404) {\n          HMSLogger.d(this.TAG, `Track not found ${requestId}`, { request, try: i + 1, error });\n          break;\n        }\n        HMSLogger.d(this.TAG, `Failed sending ${requestId}`, { request, try: i + 1, error });\n        const shouldRetry = error.code / 100 === 5 || error.code === 429;\n        if (!shouldRetry) {\n          throw Error(`code=${error.code}, message=${error.message}`);\n        }\n        const delay = (2 + Math.random() * 2) * 1000;\n        await workerSleep(delay);\n      } else {\n        break;\n      }\n    }\n    return response!;\n  };\n\n  private waitForResponse = async (requestId: string): Promise<PreferLayerResponse> => {\n    const res = await this.eventEmitter.waitFor('message', function (value) {\n      return value.includes(requestId);\n    });\n    const response = JSON.parse(res[0] as string);\n    HMSLogger.d(this.TAG, `response for ${requestId} -`, JSON.stringify(response, null, 2));\n    return response;\n  };\n}\n","import HMSLogger from '../utils/logger';\n\nexport interface DataChannelObserver {\n  onMessage(value: string): void;\n}\n\nexport default class HMSDataChannel {\n  private readonly TAG = '[HMSDataChannel]';\n  private readonly nativeChannel: RTCDataChannel;\n  private readonly observer: DataChannelObserver;\n  private readonly metadata: string;\n\n  public get id() {\n    return this.nativeChannel.id;\n  }\n\n  public get label() {\n    return this.nativeChannel.label;\n  }\n\n  public get readyState() {\n    return this.nativeChannel.readyState;\n  }\n\n  constructor(nativeChannel: RTCDataChannel, observer: DataChannelObserver, metadata = '') {\n    this.nativeChannel = nativeChannel;\n    this.observer = observer;\n    this.metadata = metadata;\n\n    nativeChannel.onmessage = e => {\n      // HMSLogger.d(this.TAG, `[${this.metadata}] onMessage: label=${this.label}, message=${e.data}`);\n      this.observer.onMessage(e.data);\n    };\n  }\n\n  send(message: string) {\n    HMSLogger.d(this.TAG, `[${this.metadata}] Sending [size=${message.length}] message=${message}`);\n    this.nativeChannel.send(message);\n  }\n\n  close() {\n    this.nativeChannel.close();\n  }\n}\n","import { InitConfig } from './models';\nimport { ErrorFactory } from '../../error/ErrorFactory';\nimport { HMSAction } from '../../error/HMSAction';\nimport HMSLogger from '../../utils/logger';\n\nconst TAG = '[InitService]';\nexport default class InitService {\n  private static handleError(response: Response, body: { code: number; message: string }) {\n    switch (response.status) {\n      case 404:\n        throw ErrorFactory.APIErrors.EndpointUnreachable(HMSAction.INIT, body.message || response.statusText);\n      case 200:\n        break;\n      default:\n        throw ErrorFactory.APIErrors.ServerErrors(\n          body.code || response.status,\n          HMSAction.INIT,\n          body.message || response?.statusText,\n        );\n    }\n  }\n\n  static async fetchInitConfig({\n    token,\n    peerId,\n    userAgent,\n    initEndpoint = 'https://prod-init.100ms.live',\n    region = '',\n  }: {\n    token: string;\n    peerId: string;\n    userAgent: string;\n    initEndpoint?: string;\n    region?: string;\n  }): Promise<InitConfig> {\n    HMSLogger.d(TAG, `fetchInitConfig: initEndpoint=${initEndpoint} token=${token} peerId=${peerId} region=${region} `);\n    const url = getUrl(initEndpoint, peerId, userAgent, region);\n    try {\n      const response = await fetch(url, {\n        headers: {\n          Authorization: `Bearer ${token}`,\n        },\n      });\n      try {\n        const config = await response.clone().json();\n        this.handleError(response, config);\n        HMSLogger.d(TAG, `config is ${JSON.stringify(config, null, 2)}`);\n        return transformInitConfig(config);\n      } catch (err) {\n        const text = await response.text();\n        HMSLogger.e(TAG, 'json error', (err as Error).message, text);\n        throw ErrorFactory.APIErrors.ServerErrors(response.status, HMSAction.INIT, text);\n      }\n    } catch (err) {\n      const error = err as Error;\n      if (['Failed to fetch', 'NetworkError', 'ECONNRESET'].some(message => error.message.includes(message))) {\n        throw ErrorFactory.APIErrors.EndpointUnreachable(HMSAction.INIT, error.message);\n      }\n      throw error;\n    }\n  }\n}\n\nexport function getUrl(endpoint: string, peerId: string, userAgent: string, region?: string) {\n  try {\n    const url = new URL('/init', endpoint);\n\n    if (region && region.trim().length > 0) {\n      url.searchParams.set('region', region.trim());\n    }\n    url.searchParams.set('peer_id', peerId);\n    url.searchParams.set('user_agent_v2', userAgent);\n    return url.toString();\n  } catch (err) {\n    const error = err as Error;\n    HMSLogger.e(TAG, error.name, error.message);\n    throw error;\n  }\n}\n\nexport function transformInitConfig(config: any): InitConfig {\n  return {\n    ...config,\n    rtcConfiguration: { ...config.rtcConfiguration, iceServers: config.rtcConfiguration?.ice_servers },\n  };\n}\n","import { v4 as uuid } from 'uuid';\nimport { convertSignalMethodtoErrorAction, HMSSignalMethod, JsonRpcRequest, JsonRpcResponse } from './models';\nimport AnalyticsEvent from '../../analytics/AnalyticsEvent';\nimport { HMSConnectionRole, HMSTrickle } from '../../connection/model';\nimport { ErrorFactory } from '../../error/ErrorFactory';\nimport { HMSAction } from '../../error/HMSAction';\nimport { HMSException } from '../../error/HMSException';\nimport Message from '../../sdk/models/HMSMessage';\nimport {\n  DEFAULT_SIGNAL_PING_INTERVAL,\n  DEFAULT_SIGNAL_PING_TIMEOUT,\n  PONG_RESPONSE_TIMES_SIZE,\n} from '../../utils/constants';\nimport HMSLogger from '../../utils/logger';\nimport { PromiseCallbacks } from '../../utils/promise';\nimport { Queue } from '../../utils/queue';\nimport { isPageHidden } from '../../utils/support';\nimport { workerSleep } from '../../utils/timer-utils';\nimport {\n  AcceptRoleChangeParams,\n  BroadcastResponse,\n  CreateWhiteboardResponse,\n  findPeersRequestParams,\n  getPeerRequestParams,\n  GetSessionMetadataResponse,\n  GetWhiteboardResponse,\n  HLSRequestParams,\n  HLSTimedMetadataParams,\n  HMSPermissionType,\n  HMSWhiteboardCreateOptions,\n  JoinLeaveGroupResponse,\n  MultiTrackUpdateRequestParams,\n  peerIterRequestParams,\n  PeersIterationResponse,\n  PollInfoGetParams,\n  PollInfoGetResponse,\n  PollInfoSetParams,\n  PollInfoSetResponse,\n  PollLeaderboardGetParams,\n  PollLeaderboardGetResponse,\n  PollListParams,\n  PollListResponse,\n  PollQuestionsGetParams,\n  PollQuestionsGetResponse,\n  PollQuestionsSetParams,\n  PollQuestionsSetResponse,\n  PollResponseSetParams,\n  PollResponseSetResponse,\n  PollResponsesGetParams,\n  PollResponsesGetResponse,\n  PollResultParams,\n  PollResultResponse,\n  PollStartParams,\n  PollStartResponse,\n  PollStopParams,\n  PollStopResponse,\n  RemovePeerRequest,\n  RequestForBulkRoleChangeParams,\n  RequestForRoleChangeParams,\n  SetSessionMetadataParams,\n  SetSessionMetadataResponse,\n  StartRTMPOrRecordingRequestParams,\n  Track,\n  TrackUpdateRequestParams,\n  UpdatePeerRequestParams,\n} from '../interfaces';\nimport { ISignal } from '../ISignal';\nimport { ISignalEventsObserver } from '../ISignalEventsObserver';\n\nexport default class JsonRpcSignal implements ISignal {\n  readonly TAG = '[SIGNAL]: ';\n  readonly observer: ISignalEventsObserver;\n  readonly pongResponseTimes = new Queue<number>(PONG_RESPONSE_TIMES_SIZE);\n\n  /**\n   * Sometimes before [join] is completed, there could be a lot of trickles\n   * Sending [HMSTrickle]` before [join] web socket message leads to\n   * error: [500] no rtc transport exists for this Peer\n   *\n   * We keep a list of pending trickles and send them immediately after [join]\n   * is done.\n   */\n  private isJoinCompleted = false;\n  private pendingTrickle: Array<HMSTrickle> = [];\n\n  private socket: WebSocket | null = null;\n\n  private callbacks = new Map<string, PromiseCallbacks<string, { method: HMSSignalMethod }>>();\n\n  private _isConnected = false;\n  private id = 0;\n\n  private onCloseHandler: (event: CloseEvent) => void = () => {};\n\n  public get isConnected(): boolean {\n    return this._isConnected;\n  }\n\n  public setIsConnected(newValue: boolean, reason = '') {\n    HMSLogger.d(this.TAG, `isConnected set id: ${this.id}, oldValue: ${this._isConnected}, newValue: ${newValue}`);\n    if (this._isConnected === newValue) {\n      return;\n    }\n\n    if (this._isConnected && !newValue) {\n      // went offline\n      this._isConnected = newValue;\n      this.rejectPendingCalls(reason);\n      this.observer.onOffline(reason);\n    } else if (!this._isConnected && newValue) {\n      // went online\n      this._isConnected = newValue;\n      this.observer.onOnline();\n    }\n  }\n\n  constructor(observer: ISignalEventsObserver) {\n    this.observer = observer;\n    window.addEventListener('offline', this.offlineListener);\n    window.addEventListener('online', this.onlineListener);\n\n    this.onMessageHandler = this.onMessageHandler.bind(this);\n  }\n\n  getPongResponseTimes() {\n    return this.pongResponseTimes.toList();\n  }\n\n  private async internalCall<T>(method: string, params: any): Promise<T> {\n    const id = uuid();\n    const message = { method, params, id, jsonrpc: '2.0' } as JsonRpcRequest;\n\n    this.socket?.send(JSON.stringify(message));\n\n    try {\n      const response = await new Promise<any>((resolve, reject) => {\n        this.callbacks.set(id, { resolve, reject, metadata: { method: method as HMSSignalMethod } });\n      });\n\n      return response;\n    } catch (ex) {\n      if (ex instanceof HMSException) {\n        throw ex;\n      }\n\n      const error = ex as JsonRpcResponse['error'];\n      throw ErrorFactory.WebsocketMethodErrors.ServerErrors(\n        Number(error.code),\n        convertSignalMethodtoErrorAction(method as HMSSignalMethod),\n        error.message,\n      );\n    }\n  }\n\n  private notify(method: string, params: any) {\n    const message = { method, params };\n\n    if (this.socket?.readyState === WebSocket.OPEN) {\n      this.socket?.send(JSON.stringify(message));\n    }\n  }\n\n  open(uri: string): Promise<void> {\n    return new Promise((resolve, reject) => {\n      let promiseSettled = false;\n      // cleanup\n      if (this.socket) {\n        this.socket.close();\n        this.socket.removeEventListener('close', this.onCloseHandler);\n        this.socket.removeEventListener('message', this.onMessageHandler);\n      }\n\n      this.socket = new WebSocket(uri); // @DISCUSS: Inject WebSocket as a dependency so that it can be easier to mock and test\n\n      const errorListener = () => {\n        /**\n         * there was an error received from websocket leading to disconnection, this can happen either if server\n         * disconnects the websocket for some reason, there is a network disconnect or a firewall/antivirus on user's\n         * device is breaking the websocket connecting(which can happen even after a successful connect).\n         */\n        HMSLogger.e(this.TAG, 'Error from websocket');\n        promiseSettled = true;\n        // above error does not contain any description hence not sent here\n        reject(\n          ErrorFactory.WebSocketConnectionErrors.FailedToConnect(HMSAction.JOIN, `Error opening websocket connection`),\n        );\n      };\n\n      this.onCloseHandler = (event: CloseEvent) => {\n        HMSLogger.w(`Websocket closed code=${event.code}`);\n        if (promiseSettled) {\n          this.setIsConnected(false, `code: ${event.code}${event.code !== 1000 ? ', unexpected websocket close' : ''}`);\n        } else {\n          promiseSettled = true;\n          reject(\n            ErrorFactory.WebSocketConnectionErrors.AbnormalClose(\n              HMSAction.JOIN,\n              `Error opening websocket connection - websocket closed unexpectedly with code=${event.code}`,\n            ),\n          );\n        }\n      };\n\n      this.socket.addEventListener('error', errorListener);\n\n      const openHandler = () => {\n        promiseSettled = true;\n        resolve();\n        this.setIsConnected(true);\n        this.id++;\n        this.socket?.removeEventListener('open', openHandler);\n        this.socket?.removeEventListener('error', errorListener);\n        this.pingPongLoop(this.id);\n      };\n\n      this.socket.addEventListener('open', openHandler);\n      this.socket.addEventListener('close', this.onCloseHandler);\n      this.socket.addEventListener('message', this.onMessageHandler);\n    });\n  }\n\n  async close(): Promise<void> {\n    window.removeEventListener('offline', this.offlineListener);\n    window.removeEventListener('online', this.onlineListener);\n\n    // For `1000` Refer: https://tools.ietf.org/html/rfc6455#section-7.4.1\n    if (this.socket) {\n      this.socket.close(1000, 'Normal Close');\n      this.setIsConnected(false, 'code: 1000, normal websocket close');\n      this.socket.removeEventListener('close', this.onCloseHandler);\n      this.socket.removeEventListener('message', this.onMessageHandler);\n    } else {\n      this.setIsConnected(false, 'websocket not connected yet');\n    }\n  }\n\n  async join(\n    name: string,\n    data: string,\n    disableVidAutoSub: boolean,\n    serverSubDegrade: boolean,\n    simulcast: boolean,\n    onDemandTracks: boolean,\n    offer?: RTCSessionDescriptionInit,\n  ): Promise<RTCSessionDescriptionInit> {\n    if (!this.isConnected) {\n      throw ErrorFactory.WebSocketConnectionErrors.WebSocketConnectionLost(\n        HMSAction.JOIN,\n        'Failed to send join over WS connection',\n      );\n    }\n    const params = {\n      name,\n      disableVidAutoSub,\n      data,\n      offer,\n      server_sub_degrade: serverSubDegrade,\n      simulcast,\n      onDemandTracks,\n    };\n    const response: RTCSessionDescriptionInit = await this.internalCall(HMSSignalMethod.JOIN, params);\n\n    this.isJoinCompleted = true;\n    this.pendingTrickle.forEach(({ target, candidate }) => this.trickle(target, candidate));\n    this.pendingTrickle.length = 0;\n\n    HMSLogger.d(this.TAG, `join: response=${JSON.stringify(response, null, 1)}`);\n    return response;\n  }\n\n  trickle(target: HMSConnectionRole, candidate: RTCIceCandidateInit) {\n    if (this.isJoinCompleted) {\n      this.notify(HMSSignalMethod.TRICKLE, { target, candidate });\n    } else {\n      this.pendingTrickle.push({ target, candidate });\n    }\n  }\n\n  async offer(desc: RTCSessionDescriptionInit, tracks: Map<string, any>): Promise<RTCSessionDescriptionInit> {\n    const response = await this.call(HMSSignalMethod.OFFER, {\n      desc,\n      tracks: Object.fromEntries(tracks),\n    });\n    return response as RTCSessionDescriptionInit;\n  }\n\n  answer(desc: RTCSessionDescriptionInit) {\n    this.notify(HMSSignalMethod.ANSWER, { desc });\n  }\n\n  trackUpdate(tracks: Map<string, Track>) {\n    this.notify(HMSSignalMethod.TRACK_UPDATE, { tracks: Object.fromEntries(tracks) });\n  }\n\n  async broadcast(message: Message) {\n    return await this.call<BroadcastResponse>(HMSSignalMethod.BROADCAST, message.toSignalParams());\n  }\n\n  leave() {\n    this.notify(HMSSignalMethod.LEAVE, {});\n  }\n\n  async endRoom(lock: boolean, reason: string) {\n    await this.call(HMSSignalMethod.END_ROOM, { lock, reason });\n  }\n\n  sendEvent(event: AnalyticsEvent) {\n    if (!this.isConnected) {\n      throw Error(`${this.TAG} not connected. Could not send event ${event}`);\n    }\n    this.notify(HMSSignalMethod.ANALYTICS, event.toSignalParams());\n  }\n\n  ping(timeout: number): Promise<number> {\n    const pingTime = Date.now();\n    const timer: Promise<number> = new Promise(resolve => {\n      setTimeout(() => {\n        resolve(Date.now() - pingTime);\n      }, timeout + 1);\n    });\n    const pongTimeDiff = this.internalCall(HMSSignalMethod.PING, { timestamp: pingTime })\n      .then(() => Date.now() - pingTime)\n      .catch(() => Date.now() - pingTime);\n\n    return Promise.race([timer, pongTimeDiff]);\n  }\n\n  async requestRoleChange(params: RequestForRoleChangeParams) {\n    await this.call(HMSSignalMethod.ROLE_CHANGE_REQUEST, params);\n  }\n\n  async requestBulkRoleChange(params: RequestForBulkRoleChangeParams) {\n    await this.call(HMSSignalMethod.ROLE_CHANGE_REQUEST, params);\n  }\n\n  async acceptRoleChangeRequest(params: AcceptRoleChangeParams) {\n    await this.call(HMSSignalMethod.ROLE_CHANGE, params);\n  }\n\n  async requestTrackStateChange(params: TrackUpdateRequestParams) {\n    await this.call(HMSSignalMethod.TRACK_UPDATE_REQUEST, params);\n  }\n\n  async requestMultiTrackStateChange(params: MultiTrackUpdateRequestParams) {\n    await this.call(HMSSignalMethod.CHANGE_TRACK_MUTE_STATE_REQUEST, params);\n  }\n\n  async removePeer(params: RemovePeerRequest) {\n    await this.call(HMSSignalMethod.PEER_LEAVE_REQUEST, params);\n  }\n\n  async startRTMPOrRecording(params: StartRTMPOrRecordingRequestParams) {\n    await this.call(HMSSignalMethod.START_RTMP_OR_RECORDING_REQUEST, { ...params });\n  }\n\n  async stopRTMPAndRecording() {\n    await this.call(HMSSignalMethod.STOP_RTMP_AND_RECORDING_REQUEST, {});\n  }\n\n  async startHLSStreaming(params: HLSRequestParams): Promise<void> {\n    await this.call(HMSSignalMethod.START_HLS_STREAMING, { ...params });\n  }\n\n  async stopHLSStreaming(params?: HLSRequestParams): Promise<void> {\n    await this.call(HMSSignalMethod.STOP_HLS_STREAMING, { ...params });\n  }\n\n  async sendHLSTimedMetadata(params?: HLSTimedMetadataParams): Promise<void> {\n    await this.call(HMSSignalMethod.HLS_TIMED_METADATA, { ...params });\n  }\n\n  async updatePeer(params: UpdatePeerRequestParams) {\n    await this.call(HMSSignalMethod.UPDATE_PEER_METADATA, { ...params });\n  }\n\n  async getPeer(params: getPeerRequestParams) {\n    await this.call(HMSSignalMethod.GET_PEER, { ...params });\n  }\n\n  async joinGroup(name: string): Promise<JoinLeaveGroupResponse> {\n    return await this.call(HMSSignalMethod.GROUP_JOIN, { name });\n  }\n\n  async leaveGroup(name: string): Promise<JoinLeaveGroupResponse> {\n    return await this.call(HMSSignalMethod.GROUP_LEAVE, { name });\n  }\n\n  async addToGroup(peerId: string, name: string) {\n    await this.call(HMSSignalMethod.GROUP_ADD, { name, peer_id: peerId });\n  }\n\n  async removeFromGroup(peerId: string, name: string): Promise<void> {\n    await this.call(HMSSignalMethod.GROUP_REMOVE, { name, peer_id: peerId });\n  }\n\n  async peerIterNext(params: peerIterRequestParams): Promise<PeersIterationResponse> {\n    return await this.call(HMSSignalMethod.PEER_ITER_NEXT, params);\n  }\n\n  async findPeers(params: findPeersRequestParams): Promise<PeersIterationResponse> {\n    return await this.call(HMSSignalMethod.FIND_PEER, params);\n  }\n\n  setSessionMetadata(params: SetSessionMetadataParams) {\n    if (!this.isConnected) {\n      throw ErrorFactory.WebSocketConnectionErrors.WebSocketConnectionLost(\n        HMSAction.RECONNECT_SIGNAL,\n        'Failed to set session store value due to network disconnection',\n      );\n    }\n    return this.call<SetSessionMetadataResponse>(HMSSignalMethod.SET_METADATA, { ...params });\n  }\n\n  listenMetadataChange(keys: string[]): Promise<void> {\n    if (!this.isConnected) {\n      throw ErrorFactory.WebSocketConnectionErrors.WebSocketConnectionLost(\n        HMSAction.RECONNECT_SIGNAL,\n        'Failed to observe session store key due to network disconnection',\n      );\n    }\n    return this.call(HMSSignalMethod.LISTEN_METADATA_CHANGE, { keys });\n  }\n\n  getSessionMetadata(key?: string) {\n    if (!this.isConnected) {\n      throw ErrorFactory.WebSocketConnectionErrors.WebSocketConnectionLost(\n        HMSAction.RECONNECT_SIGNAL,\n        'Failed to set session store value due to network disconnection',\n      );\n    }\n    return this.call<GetSessionMetadataResponse>(HMSSignalMethod.GET_METADATA, { key });\n  }\n\n  setPollInfo(params: PollInfoSetParams) {\n    return this.call<PollInfoSetResponse>(HMSSignalMethod.POLL_INFO_SET, { ...params });\n  }\n\n  getPollInfo(params: PollInfoGetParams) {\n    return this.call<PollInfoGetResponse>(HMSSignalMethod.POLL_INFO_GET, { ...params });\n  }\n\n  setPollQuestions(params: PollQuestionsSetParams) {\n    return this.call<PollQuestionsSetResponse>(HMSSignalMethod.POLL_QUESTIONS_SET, { ...params });\n  }\n\n  startPoll(params: PollStartParams) {\n    return this.call<PollStartResponse>(HMSSignalMethod.POLL_START, { ...params });\n  }\n\n  stopPoll(params: PollStopParams) {\n    return this.call<PollStopResponse>(HMSSignalMethod.POLL_STOP, { ...params });\n  }\n\n  getPollQuestions(params: PollQuestionsGetParams): Promise<PollQuestionsGetResponse> {\n    return this.call<PollQuestionsGetResponse>(HMSSignalMethod.POLL_QUESTIONS_GET, { ...params });\n  }\n\n  setPollResponses(params: PollResponseSetParams): Promise<PollResponseSetResponse> {\n    return this.call<PollResponseSetResponse>(HMSSignalMethod.POLL_RESPONSE_SET, { ...params });\n  }\n\n  getPollResponses(params: PollResponsesGetParams): Promise<PollResponsesGetResponse> {\n    return this.call<PollResponsesGetResponse>(HMSSignalMethod.POLL_RESPONSES, { ...params });\n  }\n\n  getPollsList(params: PollListParams): Promise<PollListResponse> {\n    return this.call<PollListResponse>(HMSSignalMethod.POLL_LIST, { ...params });\n  }\n\n  getPollResult(params: PollResultParams): Promise<PollResultResponse> {\n    return this.call<PollResultResponse>(HMSSignalMethod.POLL_RESULT, { ...params });\n  }\n\n  createWhiteboard(params: HMSWhiteboardCreateOptions) {\n    this.validateConnection();\n    return this.call<CreateWhiteboardResponse>(HMSSignalMethod.WHITEBOARD_CREATE, { ...params });\n  }\n\n  getWhiteboard(params: { id: string; permission?: Array<HMSPermissionType> }) {\n    this.validateConnection();\n    return this.call<GetWhiteboardResponse>(HMSSignalMethod.WHITEBOARD_GET, { ...params });\n  }\n\n  fetchPollLeaderboard(params: PollLeaderboardGetParams): Promise<PollLeaderboardGetResponse> {\n    return this.call<PollLeaderboardGetResponse>(HMSSignalMethod.POLL_LEADERBOARD, { ...params });\n  }\n\n  private validateConnection() {\n    if (!this.isConnected) {\n      throw ErrorFactory.WebSocketConnectionErrors.WebSocketConnectionLost(\n        HMSAction.RECONNECT_SIGNAL,\n        'Failed to send message due to network disconnection',\n      );\n    }\n  }\n\n  private onMessageHandler(event: MessageEvent) {\n    const text: string = event.data;\n    const response = JSON.parse(text);\n    this.resolvePingOnAnyResponse();\n    if (response.id) {\n      this.handleResponseWithId(response);\n    } else if (response.method) {\n      this.handleResponseWithMethod(response);\n    } else {\n      throw Error(`WebSocket message has no 'method' or 'id' field, message=${response}`);\n    }\n  }\n\n  private handleResponseWithId(response: any) {\n    /** This is a response to [call] */\n    const typedResponse = response as JsonRpcResponse;\n    const id: string = typedResponse.id;\n    if (this.callbacks.has(id)) {\n      const cb = this.callbacks.get(id)!;\n      this.callbacks.delete(id);\n      if (typedResponse.result) {\n        cb.resolve(typedResponse.result);\n      } else {\n        cb.reject(typedResponse.error);\n      }\n    } else {\n      this.observer.onNotification(typedResponse);\n    }\n  }\n\n  private handleResponseWithMethod(response: any) {\n    switch (response.method) {\n      case HMSSignalMethod.OFFER:\n        this.observer.onOffer(response.params);\n        break;\n      case HMSSignalMethod.TRICKLE:\n        this.observer.onTrickle(response.params);\n        break;\n      case HMSSignalMethod.SERVER_ERROR:\n        this.observer.onServerError(\n          ErrorFactory.WebsocketMethodErrors.ServerErrors(\n            Number(response.params.code),\n            HMSSignalMethod.SERVER_ERROR,\n            response.params.message,\n          ),\n        );\n        break;\n      case HMSSignalMethod.SERVER_WARNING:\n        HMSLogger.w(this.TAG, response.params);\n        break;\n      default:\n        this.observer.onNotification(response);\n        break;\n    }\n  }\n\n  private resolvePingOnAnyResponse = () => {\n    this.callbacks.forEach((callback, key) => {\n      if (callback.metadata?.method === HMSSignalMethod.PING) {\n        //@ts-ignore\n        callback.resolve({ timestamp: Date.now() });\n        this.callbacks.delete(key);\n      }\n    });\n  };\n\n  private rejectPendingCalls(reason = '') {\n    this.callbacks.forEach((callback, id) => {\n      if (callback.metadata?.method !== HMSSignalMethod.PING) {\n        HMSLogger.e(this.TAG, `rejecting pending callback ${callback.metadata?.method}, id=${id}`);\n        callback.reject(\n          ErrorFactory.WebSocketConnectionErrors.WebSocketConnectionLost(\n            callback.metadata?.method\n              ? convertSignalMethodtoErrorAction(callback.metadata?.method)\n              : HMSAction.RECONNECT_SIGNAL,\n            reason,\n          ),\n        );\n        this.callbacks.delete(id);\n      }\n    });\n  }\n\n  private async pingPongLoop(id: number) {\n    const pingTimeout = window.HMS?.PING_TIMEOUT || DEFAULT_SIGNAL_PING_TIMEOUT;\n    if (this.isConnected) {\n      const pongTimeDiff = await this.ping(pingTimeout);\n      this.pongResponseTimes.enqueue(pongTimeDiff);\n      if (pongTimeDiff > pingTimeout) {\n        HMSLogger.d(this.TAG, `Pong timeout ${id}, pageHidden=${isPageHidden()}`);\n        if (this.id === id) {\n          this.setIsConnected(false, 'ping pong failure');\n        }\n      } else {\n        setTimeout(() => this.pingPongLoop(id), window.HMS?.PING_INTERVAL || DEFAULT_SIGNAL_PING_INTERVAL);\n      }\n    }\n  }\n\n  private async call<T>(method: HMSSignalMethod, params: Record<string, any>): Promise<T> {\n    const MAX_RETRIES = 3;\n    let error: HMSException = ErrorFactory.WebsocketMethodErrors.ServerErrors(500, method, `Default ${method} error`);\n    this.validateConnection();\n    let retry;\n    for (retry = 1; retry <= MAX_RETRIES; retry++) {\n      try {\n        HMSLogger.d(this.TAG, `Try number ${retry} sending ${method}`, params);\n        return await this.internalCall(method, params);\n      } catch (err) {\n        error = err as HMSException;\n        HMSLogger.e(this.TAG, `Failed sending ${method} try: ${retry}`, { method, params, error });\n        const shouldRetry = parseInt(`${error.code / 100}`) === 5 || error.code === 429;\n        if (!shouldRetry) {\n          break;\n        }\n\n        const delay = (2 + Math.random() * 2) * 1000;\n        await workerSleep(delay);\n      }\n    }\n    HMSLogger.e(`Sending ${method} over WS failed after ${Math.min(retry, MAX_RETRIES)} retries`, {\n      method,\n      params,\n      error,\n    });\n    throw error;\n  }\n\n  private offlineListener = () => {\n    HMSLogger.d(this.TAG, 'Window network offline');\n    this.setIsConnected(false, 'Window network offline');\n  };\n\n  private onlineListener = () => {\n    HMSLogger.d(this.TAG, 'Window network online');\n    this.observer.onNetworkOnline();\n  };\n}\n","// @ts-nocheck\nimport { isBrowser } from './support';\n\nexport const getNetworkInfo = () => {\n  if (!isBrowser || typeof navigator.connection === 'undefined') {\n    return;\n  }\n\n  const connection = navigator.connection;\n  const networkInfo = {\n    downlink: connection.downlink,\n    downlinkMax: connection.downlinkMax,\n    effectiveType: connection.effectiveType,\n    rtt: connection.rtt,\n    saveData: connection.saveData,\n    type: connection.type,\n  };\n  return networkInfo;\n};\n","import { JoinParameters } from './models/JoinParameters';\nimport { TransportFailureCategory } from './models/TransportFailureCategory';\nimport { TransportState } from './models/TransportState';\nimport ITransport from './ITransport';\nimport ITransportObserver from './ITransportObserver';\nimport { RetryScheduler } from './RetryScheduler';\nimport { AdditionalAnalyticsProperties } from '../analytics/AdditionalAnalyticsProperties';\nimport AnalyticsEvent from '../analytics/AnalyticsEvent';\nimport AnalyticsEventFactory from '../analytics/AnalyticsEventFactory';\nimport { AnalyticsEventsService } from '../analytics/AnalyticsEventsService';\nimport { AnalyticsTimer, TimedEvent } from '../analytics/AnalyticsTimer';\nimport { HTTPAnalyticsTransport } from '../analytics/HTTPAnalyticsTransport';\nimport { SignalAnalyticsTransport } from '../analytics/signal-transport/SignalAnalyticsTransport';\nimport { PublishStatsAnalytics, SubscribeStatsAnalytics } from '../analytics/stats';\nimport { HMSConnectionRole, HMSTrickle } from '../connection/model';\nimport { IPublishConnectionObserver } from '../connection/publish/IPublishConnectionObserver';\nimport HMSPublishConnection from '../connection/publish/publishConnection';\nimport ISubscribeConnectionObserver from '../connection/subscribe/ISubscribeConnectionObserver';\nimport HMSSubscribeConnection from '../connection/subscribe/subscribeConnection';\nimport { DeviceManager } from '../device-manager';\nimport { ErrorCodes } from '../error/ErrorCodes';\nimport { ErrorFactory } from '../error/ErrorFactory';\nimport { HMSAction } from '../error/HMSAction';\nimport { HMSException } from '../error/HMSException';\nimport { EventBus } from '../events/EventBus';\nimport {\n  HLSConfig,\n  HLSTimedMetadata,\n  HMSPermissionType,\n  HMSRole,\n  HMSRoleChangeRequest,\n  HMSWhiteboardCreateOptions,\n} from '../interfaces';\nimport { RTMPRecordingConfig } from '../interfaces/rtmp-recording-config';\nimport { HMSLocalStream } from '../media/streams/HMSLocalStream';\nimport { HMSLocalTrack, HMSLocalVideoTrack, HMSTrack } from '../media/tracks';\nimport { TrackState } from '../notification-manager';\nimport { HMSWebrtcInternals } from '../rtc-stats/HMSWebrtcInternals';\nimport Message from '../sdk/models/HMSMessage';\nimport { IStore } from '../sdk/store';\nimport InitService from '../signal/init';\nimport { InitConfig, InitFlags } from '../signal/init/models';\nimport {\n  CreateWhiteboardResponse,\n  findPeersRequestParams,\n  HLSRequestParams,\n  HLSTimedMetadataParams,\n  HLSVariant,\n  JoinLeaveGroupResponse,\n  MultiTrackUpdateRequestParams,\n  peerIterRequestParams,\n  PeersIterationResponse,\n  PollInfoGetParams,\n  PollInfoGetResponse,\n  PollInfoSetParams,\n  PollInfoSetResponse,\n  PollLeaderboardGetParams,\n  PollLeaderboardGetResponse,\n  PollListParams,\n  PollListResponse,\n  PollQuestionsGetParams,\n  PollQuestionsGetResponse,\n  PollQuestionsSetParams,\n  PollQuestionsSetResponse,\n  PollResponseSetParams,\n  PollResponseSetResponse,\n  PollResponsesGetParams,\n  PollResponsesGetResponse,\n  PollResultParams,\n  PollResultResponse,\n  PollStartParams,\n  PollStartResponse,\n  PollStopParams,\n  SetSessionMetadataParams,\n  StartRTMPOrRecordingRequestParams,\n  TrackUpdateRequestParams,\n} from '../signal/interfaces';\nimport { ISignal } from '../signal/ISignal';\nimport { ISignalEventsObserver } from '../signal/ISignalEventsObserver';\nimport JsonRpcSignal from '../signal/jsonrpc';\nimport {\n  ICE_DISCONNECTION_TIMEOUT,\n  MAX_TRANSPORT_RETRIES,\n  PROTOCOL_SPEC,\n  PROTOCOL_VERSION,\n  PUBLISH_STATS_PUSH_INTERVAL,\n  PUBLISH_STATS_SAMPLE_WINDOW,\n  RENEGOTIATION_CALLBACK_ID,\n  SUBSCRIBE_ICE_CONNECTION_CALLBACK_ID,\n  SUBSCRIBE_STATS_PUSH_INTERVAL,\n  SUBSCRIBE_STATS_SAMPLE_WINDOW,\n  SUBSCRIBE_TIMEOUT,\n} from '../utils/constants';\nimport HMSLogger from '../utils/logger';\nimport { getNetworkInfo } from '../utils/network-info';\nimport { PromiseCallbacks } from '../utils/promise';\n\nconst TAG = '[HMSTransport]:';\n\n// @DISCUSS: action and extra are not used at all.\ninterface CallbackTriple {\n  promise: PromiseCallbacks<boolean>;\n  action: HMSAction;\n  extra: any;\n}\n\ninterface NegotiateJoinParams {\n  name: string;\n  data: string;\n  autoSubscribeVideo: boolean;\n}\n\nexport default class HMSTransport implements ITransport {\n  private state: TransportState = TransportState.Disconnected;\n  private trackStates: Map<string, TrackState> = new Map();\n  private publishConnection: HMSPublishConnection | null = null;\n  private subscribeConnection: HMSSubscribeConnection | null = null;\n  private initConfig?: InitConfig;\n  private endpoint!: string;\n  private joinParameters?: JoinParameters;\n  private retryScheduler: RetryScheduler;\n  private webrtcInternals?: HMSWebrtcInternals;\n  private publishStatsAnalytics?: PublishStatsAnalytics;\n  private subscribeStatsAnalytics?: SubscribeStatsAnalytics;\n  private maxSubscribeBitrate = 0;\n  joinRetryCount = 0;\n\n  constructor(\n    private observer: ITransportObserver,\n    private deviceManager: DeviceManager,\n    private store: IStore,\n    private eventBus: EventBus,\n    private analyticsEventsService: AnalyticsEventsService,\n    private analyticsTimer: AnalyticsTimer,\n  ) {\n    this.webrtcInternals = new HMSWebrtcInternals(\n      this.store,\n      this.eventBus,\n      this.publishConnection?.nativeConnection,\n      this.subscribeConnection?.nativeConnection,\n    );\n\n    const onStateChange = async (state: TransportState, error?: HMSException) => {\n      if (state !== this.state) {\n        this.state = state;\n        await this.observer.onStateChange(this.state, error);\n      }\n    };\n    this.retryScheduler = new RetryScheduler(onStateChange, this.sendErrorAnalyticsEvent.bind(this));\n\n    this.eventBus.statsUpdate.subscribe(stats => {\n      const currentSubscribeBitrate = stats.getLocalPeerStats()?.subscribe?.bitrate || 0;\n      this.maxSubscribeBitrate = Math.max(this.maxSubscribeBitrate, currentSubscribeBitrate);\n    });\n\n    this.eventBus.localAudioEnabled.subscribe(({ track }) => this.trackUpdate(track));\n    this.eventBus.localVideoEnabled.subscribe(({ track }) => this.trackUpdate(track));\n  }\n\n  /**\n   * Map of callbacks used to wait for an event to fire.\n   * Used here for:\n   *  1. publish/unpublish waits for [IPublishConnectionObserver.onRenegotiationNeeded] to complete\n   */\n  private readonly callbacks = new Map<string, CallbackTriple>();\n\n  private signalObserver: ISignalEventsObserver = {\n    onOffer: async (jsep: RTCSessionDescriptionInit) => {\n      try {\n        if (!this.subscribeConnection) {\n          return;\n        }\n        await this.subscribeConnection.setRemoteDescription(jsep);\n        HMSLogger.d(\n          TAG,\n          `[SUBSCRIBE] Adding ${this.subscribeConnection.candidates.length} ice-candidates`,\n          this.subscribeConnection.candidates,\n        );\n        for (const candidate of this.subscribeConnection.candidates) {\n          await this.subscribeConnection.addIceCandidate(candidate);\n        }\n        this.subscribeConnection.candidates.length = 0;\n        const answer = await this.subscribeConnection.createAnswer();\n        await this.subscribeConnection.setLocalDescription(answer);\n        this.signal.answer(answer);\n        HMSLogger.d(TAG, '[role=SUBSCRIBE] onOffer renegotiation DONE ✅');\n      } catch (err) {\n        HMSLogger.d(TAG, '[role=SUBSCRIBE] onOffer renegotiation FAILED ❌', err);\n        this.state = TransportState.Failed;\n        let ex: HMSException;\n        if (err instanceof HMSException) {\n          ex = err;\n        } else {\n          ex = ErrorFactory.GenericErrors.Unknown(HMSAction.PUBLISH, (err as Error).message);\n        }\n        this.observer.onFailure(ex);\n        this.eventBus.analytics.publish(AnalyticsEventFactory.subscribeFail(ex));\n      }\n    },\n\n    onTrickle: async (trickle: HMSTrickle) => {\n      const connection =\n        trickle.target === HMSConnectionRole.Publish ? this.publishConnection : this.subscribeConnection;\n      if (!connection?.remoteDescription) {\n        // ICE candidates can't be added without any remote session description\n        connection?.candidates.push(trickle.candidate);\n      } else {\n        await connection.addIceCandidate(trickle.candidate);\n      }\n    },\n\n    onNotification: (message: any) => this.observer.onNotification(message),\n\n    onServerError: async (error: HMSException) => {\n      await this.observer.onStateChange(TransportState.Failed, error);\n    },\n\n    onFailure: (error: HMSException) => {\n      // @DISCUSS: Should we remove this? Pong failure would have already scheduled signal retry.\n      if (this.joinParameters) {\n        this.retryScheduler.schedule({\n          category: TransportFailureCategory.SignalDisconnect,\n          error,\n          task: this.retrySignalDisconnectTask,\n          originalState: this.state,\n        });\n      }\n    },\n\n    onOffline: async (reason: string) => {\n      HMSLogger.d(TAG, 'socket offline', TransportState[this.state]);\n      try {\n        if (this.state !== TransportState.Leaving && this.joinParameters) {\n          this.retryScheduler.schedule({\n            category: TransportFailureCategory.SignalDisconnect,\n            error: ErrorFactory.WebSocketConnectionErrors.WebSocketConnectionLost(HMSAction.RECONNECT_SIGNAL, reason),\n            task: this.retrySignalDisconnectTask,\n            originalState: this.state,\n          });\n        }\n      } catch (e) {\n        console.error(e);\n      }\n    },\n\n    // this is called when socket connection is successful\n    onOnline: () => {\n      HMSLogger.d(TAG, 'socket online', TransportState[this.state]);\n      this.analyticsSignalTransport.flushFailedEvents(this.store.getLocalPeer()?.peerId);\n    },\n    // this is called when window.online event is triggered\n    onNetworkOnline: () => {\n      this.analyticsEventsService.flushFailedClientEvents();\n    },\n  };\n\n  private signal: ISignal = new JsonRpcSignal(this.signalObserver);\n  private analyticsSignalTransport = new SignalAnalyticsTransport(this.signal);\n\n  private publishDtlsStateTimer = 0;\n  private lastPublishDtlsState: RTCDtlsTransportState = 'new';\n\n  private publishConnectionObserver: IPublishConnectionObserver = {\n    onRenegotiationNeeded: async () => {\n      await this.performPublishRenegotiation();\n    },\n\n    // eslint-disable-next-line complexity\n    onDTLSTransportStateChange: (state?: RTCDtlsTransportState) => {\n      const log = state === 'failed' ? HMSLogger.w.bind(HMSLogger) : HMSLogger.d.bind(HMSLogger);\n      log(TAG, `Publisher on dtls transport state change: ${state}`);\n\n      if (!state || this.lastPublishDtlsState === state) {\n        return;\n      }\n\n      this.lastPublishDtlsState = state;\n      if (this.publishDtlsStateTimer !== 0) {\n        clearTimeout(this.publishDtlsStateTimer);\n        this.publishDtlsStateTimer = 0;\n      }\n\n      if (state !== 'connecting' && state !== 'failed') {\n        return;\n      }\n\n      const timeout = this.initConfig?.config?.dtlsStateTimeouts?.[state];\n      if (!timeout || timeout <= 0) {\n        return;\n      }\n\n      // if we're in connecting check again after timeout\n      // hotfix: mitigate https://100ms.atlassian.net/browse/LIVE-1924\n      this.publishDtlsStateTimer = window.setTimeout(() => {\n        const newState = this.publishConnection?.nativeConnection.connectionState;\n        if (newState && state && newState === state) {\n          // stuck in either `connecting` or `failed` state for long time\n          const err = ErrorFactory.WebrtcErrors.ICEFailure(\n            HMSAction.PUBLISH,\n            `DTLS transport state ${state} timeout:${timeout}ms`,\n            true,\n          );\n          this.eventBus.analytics.publish(AnalyticsEventFactory.disconnect(err));\n          this.observer.onFailure(err);\n        }\n      }, timeout);\n    },\n\n    onDTLSTransportError: (error: Error) => {\n      HMSLogger.e(TAG, `onDTLSTransportError ${error.name} ${error.message}`, error);\n      this.eventBus.analytics.publish(AnalyticsEventFactory.disconnect(error));\n    },\n\n    onIceConnectionChange: async (newState: RTCIceConnectionState) => {\n      const log = newState === 'disconnected' ? HMSLogger.w.bind(HMSLogger) : HMSLogger.d.bind(HMSLogger);\n      log(TAG, `Publish ice connection state change: ${newState}`);\n\n      // @TODO: Uncomment this and remove connectionstatechange\n      if (newState === 'failed') {\n        // await this.handleIceConnectionFailure(HMSConnectionRole.Publish);\n      }\n    },\n\n    // @TODO(eswar): Remove this. Use iceconnectionstate change with interval and threshold.\n    onConnectionStateChange: async (newState: RTCPeerConnectionState) => {\n      const log = newState === 'disconnected' ? HMSLogger.w.bind(HMSLogger) : HMSLogger.d.bind(HMSLogger);\n      log(TAG, `Publish connection state change: ${newState}`);\n\n      if (newState === 'connected') {\n        this.publishConnection?.logSelectedIceCandidatePairs();\n      }\n\n      if (newState === 'disconnected') {\n        // if state stays disconnected for 5 seconds, retry\n        setTimeout(() => {\n          if (this.publishConnection?.connectionState === 'disconnected') {\n            this.handleIceConnectionFailure(\n              HMSConnectionRole.Publish,\n              ErrorFactory.WebrtcErrors.ICEDisconnected(\n                HMSAction.PUBLISH,\n                `local candidate - ${this.publishConnection?.selectedCandidatePair?.local.candidate}; remote candidate - ${this.publishConnection?.selectedCandidatePair?.remote.candidate}`,\n              ),\n            );\n          }\n        }, ICE_DISCONNECTION_TIMEOUT);\n      }\n\n      if (newState === 'failed') {\n        await this.handleIceConnectionFailure(\n          HMSConnectionRole.Publish,\n          ErrorFactory.WebrtcErrors.ICEFailure(\n            HMSAction.PUBLISH,\n            `local candidate - ${this.publishConnection?.selectedCandidatePair?.local.candidate}; remote candidate - ${this.publishConnection?.selectedCandidatePair?.remote.candidate}`,\n          ),\n        );\n      }\n    },\n  };\n\n  private subscribeConnectionObserver: ISubscribeConnectionObserver = {\n    onApiChannelMessage: (message: string) => {\n      this.observer.onNotification(JSON.parse(message));\n    },\n\n    onTrackAdd: (track: HMSTrack) => {\n      HMSLogger.d(TAG, '[Subscribe] onTrackAdd', `${track}`);\n      this.observer.onTrackAdd(track);\n    },\n\n    onTrackRemove: (track: HMSTrack) => {\n      HMSLogger.d(TAG, '[Subscribe] onTrackRemove', `${track}`);\n      this.observer.onTrackRemove(track);\n    },\n\n    onIceConnectionChange: async (newState: RTCIceConnectionState) => {\n      const log = newState === 'disconnected' ? HMSLogger.w.bind(HMSLogger) : HMSLogger.d.bind(HMSLogger);\n      log(TAG, `Subscribe ice connection state change: ${newState}`);\n\n      if (newState === 'failed') {\n        // await this.handleIceConnectionFailure(HMSConnectionRole.Subscribe);\n      }\n\n      if (newState === 'connected') {\n        const callback = this.callbacks.get(SUBSCRIBE_ICE_CONNECTION_CALLBACK_ID);\n        this.callbacks.delete(SUBSCRIBE_ICE_CONNECTION_CALLBACK_ID);\n\n        if (callback) {\n          callback.promise.resolve(true);\n        }\n      }\n    },\n\n    // @TODO(eswar): Remove this. Use iceconnectionstate change with interval and threshold.\n    onConnectionStateChange: async (newState: RTCPeerConnectionState) => {\n      const log = newState === 'disconnected' ? HMSLogger.w.bind(HMSLogger) : HMSLogger.d.bind(HMSLogger);\n      log(TAG, `Subscribe connection state change: ${newState}`);\n\n      if (newState === 'failed') {\n        await this.handleIceConnectionFailure(\n          HMSConnectionRole.Subscribe,\n          ErrorFactory.WebrtcErrors.ICEFailure(\n            HMSAction.SUBSCRIBE,\n            `local candidate - ${this.subscribeConnection?.selectedCandidatePair?.local.candidate}; remote candidate - ${this.subscribeConnection?.selectedCandidatePair?.remote.candidate}`,\n          ),\n        );\n      }\n\n      if (newState === 'disconnected') {\n        setTimeout(() => {\n          if (this.subscribeConnection?.connectionState === 'disconnected') {\n            this.handleIceConnectionFailure(\n              HMSConnectionRole.Subscribe,\n              ErrorFactory.WebrtcErrors.ICEDisconnected(\n                HMSAction.SUBSCRIBE,\n                `local candidate - ${this.subscribeConnection?.selectedCandidatePair?.local.candidate}; remote candidate - ${this.subscribeConnection?.selectedCandidatePair?.remote.candidate}`,\n              ),\n            );\n          }\n        }, ICE_DISCONNECTION_TIMEOUT);\n      }\n\n      if (newState === 'connected') {\n        this.handleSubscribeConnectionConnected();\n      }\n    },\n  };\n\n  getWebrtcInternals() {\n    return this.webrtcInternals;\n  }\n\n  isFlagEnabled(flag: InitFlags) {\n    const config = this.initConfig?.config;\n    const flags = config?.enabledFlags || [];\n    return flags.includes(flag);\n  }\n\n  async preview(\n    token: string,\n    endpoint: string,\n    peerId: string,\n    customData: { name: string; metaData: string },\n    autoSubscribeVideo = false,\n  ): Promise<InitConfig | void> {\n    const initConfig = await this.connect(token, endpoint, peerId, customData, autoSubscribeVideo);\n    this.state = TransportState.Preview;\n    this.observer.onStateChange(this.state);\n    return initConfig;\n  }\n\n  async join(\n    authToken: string,\n    peerId: string,\n    customData: { name: string; metaData: string },\n    initEndpoint: string,\n    autoSubscribeVideo = false,\n  ): Promise<void> {\n    HMSLogger.d(TAG, 'join: started ⏰');\n    try {\n      if (!this.signal.isConnected || !this.initConfig) {\n        await this.connect(authToken, initEndpoint, peerId, customData, autoSubscribeVideo);\n      }\n\n      this.validateNotDisconnected('connect');\n\n      if (this.initConfig) {\n        await this.waitForLocalRoleAvailability();\n        await this.createConnectionsAndNegotiateJoin(customData, autoSubscribeVideo);\n        await this.initRtcStatsMonitor();\n\n        HMSLogger.d(TAG, '✅ join: Negotiated over PUBLISH connection');\n      }\n    } catch (error) {\n      HMSLogger.e(TAG, `join: failed ❌ [token=${authToken}]`, error);\n      this.state = TransportState.Failed;\n      const ex = error as HMSException;\n      // set isTerminal to true if not already when error code is 500(internal biz server error)\n      ex.isTerminal = ex.isTerminal || ex.code === 500;\n      await this.observer.onStateChange(this.state, ex);\n      throw ex;\n    }\n\n    HMSLogger.d(TAG, '✅ join: successful');\n    this.state = TransportState.Joined;\n    this.observer.onStateChange(this.state);\n  }\n\n  async connect(\n    token: string,\n    endpoint: string,\n    peerId: string,\n    customData: { name: string; metaData: string },\n    autoSubscribeVideo = false,\n  ): Promise<InitConfig | void> {\n    this.setTransportStateForConnect();\n    this.joinParameters = new JoinParameters(\n      token,\n      peerId,\n      customData.name,\n      customData.metaData,\n      endpoint,\n      autoSubscribeVideo,\n    );\n    try {\n      const response = await this.internalConnect(token, endpoint, peerId);\n      return response;\n    } catch (error) {\n      const shouldRetry =\n        error instanceof HMSException &&\n        ([\n          ErrorCodes.WebSocketConnectionErrors.WEBSOCKET_CONNECTION_LOST,\n          ErrorCodes.WebSocketConnectionErrors.FAILED_TO_CONNECT,\n          ErrorCodes.WebSocketConnectionErrors.ABNORMAL_CLOSE,\n          ErrorCodes.APIErrors.ENDPOINT_UNREACHABLE,\n        ].includes(error.code) ||\n          error.code.toString().startsWith('5') ||\n          error.code.toString().startsWith('429'));\n\n      if (shouldRetry) {\n        const task = async () => {\n          await this.internalConnect(token, endpoint, peerId);\n          return Boolean(this.initConfig && this.initConfig.endpoint);\n        };\n\n        await this.retryScheduler.schedule({\n          category: TransportFailureCategory.ConnectFailed,\n          error,\n          task,\n          originalState: this.state,\n          maxFailedRetries: MAX_TRANSPORT_RETRIES,\n          changeState: false,\n        });\n      } else {\n        throw error;\n      }\n    }\n  }\n\n  async leave(notifyServer: boolean): Promise<void> {\n    this.retryScheduler.reset();\n    this.joinParameters = undefined;\n    HMSLogger.d(TAG, 'leaving in transport');\n    try {\n      this.state = TransportState.Leaving;\n      this.publishStatsAnalytics?.stop();\n      this.subscribeStatsAnalytics?.stop();\n      this.webrtcInternals?.cleanup();\n      await this.publishConnection?.close();\n      await this.subscribeConnection?.close();\n      if (notifyServer) {\n        try {\n          this.signal.leave();\n          HMSLogger.d(TAG, 'signal leave done');\n        } catch (err) {\n          HMSLogger.w(TAG, 'failed to send leave on websocket to server', err);\n        }\n      }\n      this.analyticsEventsService.flushFailedClientEvents();\n      this.analyticsEventsService.reset();\n      await this.signal.close();\n    } catch (err) {\n      this.eventBus.analytics.publish(AnalyticsEventFactory.disconnect(err as Error));\n      HMSLogger.e(TAG, 'leave: FAILED ❌', err);\n    } finally {\n      this.state = TransportState.Disconnected;\n      this.observer.onStateChange(this.state);\n    }\n  }\n\n  handleLocalRoleUpdate = async ({ oldRole, newRole }: { oldRole: HMSRole; newRole: HMSRole }) => {\n    const changedFromNonWebRTCToWebRTC = !this.doesRoleNeedWebRTC(oldRole) && this.doesRoleNeedWebRTC(newRole);\n    if (!changedFromNonWebRTCToWebRTC) {\n      return;\n    }\n\n    HMSLogger.d(\n      TAG,\n      'Local peer role updated to webrtc role, creating PeerConnections and performing inital publish negotiation ⏳',\n    );\n    this.createPeerConnections();\n    await this.negotiateOnFirstPublish();\n  };\n\n  async publish(tracks: Array<HMSLocalTrack>): Promise<void> {\n    for (const track of tracks) {\n      try {\n        await this.publishTrack(track);\n      } catch (error) {\n        this.eventBus.analytics.publish(\n          AnalyticsEventFactory.publish({\n            devices: this.deviceManager.getDevices(),\n            error: error as Error,\n          }),\n        );\n      }\n    }\n  }\n\n  async unpublish(tracks: Array<HMSLocalTrack>): Promise<void> {\n    for (const track of tracks) {\n      await this.unpublishTrack(track);\n    }\n  }\n\n  async sendMessage(message: Message) {\n    return await this.signal.broadcast(message);\n  }\n\n  /**\n   * TODO: check if track.publishedTrackId be used instead of the hack to match with track with same type and\n   * source. The hack won't work if there are multiple tracks with same source and type.\n   */\n  trackUpdate(track: HMSLocalTrack) {\n    const currentTrackStates = Array.from(this.trackStates.values());\n    const originalTrackState = currentTrackStates.find(\n      trackState => track.type === trackState.type && track.source === trackState.source,\n    );\n    if (originalTrackState) {\n      const newTrackState = new TrackState({\n        ...originalTrackState,\n        mute: !track.enabled,\n      });\n      this.trackStates.set(originalTrackState.track_id, newTrackState);\n      HMSLogger.d(TAG, 'Track Update', this.trackStates, track);\n      this.signal.trackUpdate(new Map([[originalTrackState.track_id, newTrackState]]));\n    }\n  }\n\n  async changeRole(forPeerId: string, toRole: string, force = false) {\n    await this.signal.requestRoleChange({\n      requested_for: forPeerId,\n      role: toRole,\n      force,\n    });\n  }\n\n  async changeRoleOfPeer(forPeerId: string, toRole: string, force: boolean) {\n    await this.signal.requestRoleChange({\n      requested_for: forPeerId,\n      role: toRole,\n      force,\n    });\n  }\n\n  async changeRoleOfPeersWithRoles(roles: HMSRole[], toRole: string) {\n    await this.signal.requestBulkRoleChange({\n      roles: roles.map((role: HMSRole) => role.name),\n      role: toRole,\n      force: true,\n    });\n  }\n\n  async acceptRoleChange(request: HMSRoleChangeRequest) {\n    await this.signal.acceptRoleChangeRequest({\n      requested_by: request.requestedBy?.peerId,\n      role: request.role.name,\n      token: request.token,\n    });\n  }\n\n  async endRoom(lock: boolean, reason: string) {\n    await this.signal.endRoom(lock, reason);\n  }\n\n  async removePeer(peerId: string, reason: string) {\n    await this.signal.removePeer({ requested_for: peerId, reason });\n  }\n\n  async startRTMPOrRecording(params: RTMPRecordingConfig) {\n    const signalParams: StartRTMPOrRecordingRequestParams = {\n      meeting_url: params.meetingURL,\n      record: params.record,\n    };\n\n    if (params.rtmpURLs?.length) {\n      signalParams.rtmp_urls = params.rtmpURLs;\n    }\n\n    if (params.resolution) {\n      signalParams.resolution = params.resolution;\n    }\n\n    await this.signal.startRTMPOrRecording(signalParams);\n  }\n\n  async stopRTMPOrRecording() {\n    await this.signal.stopRTMPAndRecording();\n  }\n\n  async startHLSStreaming(params?: HLSConfig) {\n    const hlsParams: HLSRequestParams = {};\n    if (params && params.variants && params.variants.length > 0) {\n      hlsParams.variants = params.variants.map(variant => {\n        const hlsVariant: HLSVariant = { meeting_url: variant.meetingURL };\n        if (variant.metadata) {\n          hlsVariant.metadata = variant.metadata;\n        }\n        return hlsVariant;\n      });\n    }\n    if (params?.recording) {\n      hlsParams.hls_recording = {\n        single_file_per_layer: params.recording.singleFilePerLayer,\n        hls_vod: params.recording.hlsVod,\n      };\n    }\n    await this.signal.startHLSStreaming(hlsParams);\n  }\n\n  async stopHLSStreaming(params?: HLSConfig) {\n    if (params) {\n      const hlsParams: HLSRequestParams = {\n        variants: params?.variants?.map(variant => {\n          const hlsVariant: HLSVariant = { meeting_url: variant.meetingURL };\n          if (variant.metadata) {\n            hlsVariant.metadata = variant.metadata;\n          }\n          return hlsVariant;\n        }),\n      };\n      await this.signal.stopHLSStreaming(hlsParams);\n    }\n    await this.signal.stopHLSStreaming();\n  }\n\n  async sendHLSTimedMetadata(metadataList: HLSTimedMetadata[]) {\n    if (metadataList.length > 0) {\n      const hlsMtParams: HLSTimedMetadataParams = {\n        metadata_objs: metadataList,\n      };\n\n      await this.signal.sendHLSTimedMetadata(hlsMtParams);\n    }\n  }\n  async changeName(name: string) {\n    const peer = this.store.getLocalPeer();\n    if (peer && peer.name !== name) {\n      await this.signal.updatePeer({\n        name: name,\n      });\n    }\n  }\n\n  async changeMetadata(metadata: string) {\n    await this.signal.updatePeer({\n      data: metadata,\n    });\n  }\n\n  getSessionMetadata(key?: string) {\n    return this.signal.getSessionMetadata(key);\n  }\n\n  setSessionMetadata(params: SetSessionMetadataParams) {\n    return this.signal.setSessionMetadata(params);\n  }\n\n  listenMetadataChange(keys: string[]): Promise<void> {\n    return this.signal.listenMetadataChange(keys);\n  }\n\n  setPollInfo(params: PollInfoSetParams): Promise<PollInfoSetResponse> {\n    return this.signal.setPollInfo(params);\n  }\n\n  async fetchLeaderboard(params: PollLeaderboardGetParams): Promise<PollLeaderboardGetResponse> {\n    return this.signal.fetchPollLeaderboard(params);\n  }\n\n  getPollInfo(params: PollInfoGetParams): Promise<PollInfoGetResponse> {\n    return this.signal.getPollInfo(params);\n  }\n\n  setPollQuestions(params: PollQuestionsSetParams): Promise<PollQuestionsSetResponse> {\n    return this.signal.setPollQuestions(params);\n  }\n\n  getPollQuestions(params: PollQuestionsGetParams): Promise<PollQuestionsGetResponse> {\n    return this.signal.getPollQuestions(params);\n  }\n\n  startPoll(params: PollStartParams): Promise<PollStartResponse> {\n    return this.signal.startPoll(params);\n  }\n\n  stopPoll(params: PollStopParams): Promise<PollStartResponse> {\n    return this.signal.stopPoll(params);\n  }\n\n  setPollResponses(params: PollResponseSetParams): Promise<PollResponseSetResponse> {\n    return this.signal.setPollResponses(params);\n  }\n\n  getPollResponses(params: PollResponsesGetParams): Promise<PollResponsesGetResponse> {\n    return this.signal.getPollResponses(params);\n  }\n\n  getPollsList(params: PollListParams): Promise<PollListResponse> {\n    return this.signal.getPollsList(params);\n  }\n\n  getPollResult(params: PollResultParams): Promise<PollResultResponse> {\n    return this.signal.getPollResult(params);\n  }\n\n  getWhiteboard(params: { id: string; permission?: Array<HMSPermissionType> }) {\n    return this.signal.getWhiteboard(params);\n  }\n\n  createWhiteboard(params: HMSWhiteboardCreateOptions): Promise<CreateWhiteboardResponse> {\n    return this.signal.createWhiteboard(params);\n  }\n\n  async joinGroup(name: string): Promise<JoinLeaveGroupResponse> {\n    return this.signal.joinGroup(name);\n  }\n\n  async leaveGroup(name: string): Promise<JoinLeaveGroupResponse> {\n    return this.signal.leaveGroup(name);\n  }\n\n  async addToGroup(peerId: string, name: string) {\n    this.signal.addToGroup(peerId, name);\n  }\n\n  async removeFromGroup(peerId: string, name: string): Promise<void> {\n    this.signal.removeFromGroup(peerId, name);\n  }\n\n  findPeers(params: findPeersRequestParams): Promise<PeersIterationResponse> {\n    return this.signal.findPeers(params);\n  }\n  peerIterNext(params: peerIterRequestParams): Promise<PeersIterationResponse> {\n    return this.signal.peerIterNext(params);\n  }\n\n  async changeTrackState(trackUpdateRequest: TrackUpdateRequestParams) {\n    await this.signal.requestTrackStateChange(trackUpdateRequest);\n  }\n\n  async changeMultiTrackState(trackUpdateRequest: MultiTrackUpdateRequestParams) {\n    await this.signal.requestMultiTrackStateChange(trackUpdateRequest);\n  }\n\n  private async publishTrack(track: HMSLocalTrack): Promise<void> {\n    track.publishedTrackId = track.getTrackIDBeingSent();\n    HMSLogger.d(\n      TAG,\n      `⏳ publishTrack: trackId=${track.trackId}, toPublishTrackId=${track.publishedTrackId}`,\n      `${track}`,\n    );\n    this.trackStates.set(track.publishedTrackId, new TrackState(track));\n    const p = new Promise<boolean>((resolve, reject) => {\n      this.callbacks.set(RENEGOTIATION_CALLBACK_ID, {\n        promise: { resolve, reject },\n        action: HMSAction.PUBLISH,\n        extra: {},\n      });\n    });\n    const stream = track.stream as HMSLocalStream;\n    stream.setConnection(this.publishConnection!);\n    const simulcastLayers = this.store.getSimulcastLayers(track.source!);\n    stream.addTransceiver(track, simulcastLayers);\n    HMSLogger.time(`publish-${track.trackId}-${track.type}`);\n    await p;\n    HMSLogger.timeEnd(`publish-${track.trackId}-${track.type}`);\n    // add track to store after publish\n    this.store.addTrack(track);\n\n    await stream\n      .setMaxBitrateAndFramerate(track)\n      .then(() => {\n        HMSLogger.d(\n          TAG,\n          `Setting maxBitrate=${track.settings.maxBitrate} kpbs${\n            track instanceof HMSLocalVideoTrack ? ` and maxFramerate=${track.settings.maxFramerate}` : ''\n          } for ${track.source} ${track.type} ${track.trackId}`,\n        );\n      })\n      .catch(error => HMSLogger.w(TAG, 'Failed setting maxBitrate and maxFramerate', error));\n\n    track.isPublished = true;\n\n    HMSLogger.d(TAG, `✅ publishTrack: trackId=${track.trackId}`, `${track}`, this.callbacks);\n  }\n\n  private async unpublishTrack(track: HMSLocalTrack): Promise<void> {\n    HMSLogger.d(TAG, `⏳ unpublishTrack: trackId=${track.trackId}`, `${track}`);\n    if (track.publishedTrackId && this.trackStates.has(track.publishedTrackId)) {\n      this.trackStates.delete(track.publishedTrackId);\n    } else {\n      // TODO: hotfix to unpublish replaced video track id, solve it properly\n      // it won't work when there are multiple regular video tracks, hmslocalvideotrack can store\n      // the original initial track id for a proper fix\n      const currentTrackStates = Array.from(this.trackStates.values());\n      const originalTrackState = currentTrackStates.find(\n        trackState => track.type === trackState.type && track.source === trackState.source,\n      );\n      if (originalTrackState) {\n        this.trackStates.delete(originalTrackState.track_id);\n      }\n    }\n    const p = new Promise<boolean>((resolve, reject) => {\n      this.callbacks.set(RENEGOTIATION_CALLBACK_ID, {\n        promise: { resolve, reject },\n        action: HMSAction.UNPUBLISH,\n        extra: {},\n      });\n    });\n    const stream = track.stream as HMSLocalStream;\n    stream.removeSender(track);\n    await p;\n    await track.cleanup();\n    // remove track from store on unpublish\n    this.store.removeTrack(track);\n    HMSLogger.d(TAG, `✅ unpublishTrack: trackId=${track.trackId}`, this.callbacks);\n  }\n\n  private waitForLocalRoleAvailability() {\n    if (this.store.hasRoleDetailsArrived()) {\n      return;\n    } else {\n      return new Promise<void>(resolve => {\n        this.eventBus.policyChange.subscribeOnce(() => resolve());\n      });\n    }\n  }\n\n  private async createConnectionsAndNegotiateJoin(\n    customData: { name: string; metaData: string },\n    autoSubscribeVideo = false,\n  ) {\n    const isWebRTC = this.doesLocalPeerNeedWebRTC();\n    if (isWebRTC) {\n      this.createPeerConnections();\n    }\n\n    this.analyticsTimer.start(TimedEvent.JOIN_RESPONSE);\n    await this.negotiateJoinWithRetry({\n      name: customData.name,\n      data: customData.metaData,\n      autoSubscribeVideo,\n      isWebRTC,\n    });\n    this.analyticsTimer.end(TimedEvent.JOIN_RESPONSE);\n  }\n\n  private createPeerConnections() {\n    if (this.initConfig) {\n      if (!this.publishConnection) {\n        this.publishConnection = new HMSPublishConnection(\n          this.signal,\n          this.initConfig.rtcConfiguration,\n          this.publishConnectionObserver,\n        );\n      }\n\n      if (!this.subscribeConnection) {\n        this.subscribeConnection = new HMSSubscribeConnection(\n          this.signal,\n          this.initConfig.rtcConfiguration,\n          this.isFlagEnabled.bind(this),\n          this.subscribeConnectionObserver,\n        );\n      }\n    }\n  }\n\n  private async negotiateJoinWithRetry({\n    name,\n    data,\n    autoSubscribeVideo,\n    isWebRTC = true,\n  }: NegotiateJoinParams & { isWebRTC: boolean }) {\n    try {\n      await this.negotiateJoin({ name, data, autoSubscribeVideo, isWebRTC });\n    } catch (error) {\n      HMSLogger.e(TAG, 'Join negotiation failed ❌', error);\n      const hmsError =\n        error instanceof HMSException\n          ? error\n          : ErrorFactory.WebsocketMethodErrors.ServerErrors(\n              500,\n              HMSAction.JOIN,\n              `Websocket join error - ${(error as Error).message}`,\n            );\n      const shouldRetry =\n        parseInt(`${hmsError.code / 100}`) === 5 ||\n        [ErrorCodes.WebSocketConnectionErrors.WEBSOCKET_CONNECTION_LOST, 429].includes(hmsError.code);\n\n      if (hmsError.code === 410) {\n        hmsError.isTerminal = true;\n      }\n\n      if (shouldRetry) {\n        this.joinRetryCount = 0;\n        hmsError.isTerminal = false;\n        const task = async () => {\n          this.joinRetryCount++;\n          return await this.negotiateJoin({ name, data, autoSubscribeVideo, isWebRTC });\n        };\n\n        await this.retryScheduler.schedule({\n          category: TransportFailureCategory.JoinWSMessageFailed,\n          error: hmsError,\n          task,\n          originalState: TransportState.Joined,\n          maxFailedRetries: 3,\n          changeState: false,\n        });\n      } else {\n        throw error;\n      }\n    }\n  }\n\n  private async negotiateJoin({\n    name,\n    data,\n    autoSubscribeVideo,\n    isWebRTC = true,\n  }: NegotiateJoinParams & { isWebRTC: boolean }): Promise<boolean> {\n    if (isWebRTC) {\n      return await this.negotiateJoinWebRTC({ name, data, autoSubscribeVideo });\n    } else {\n      return await this.negotiateJoinNonWebRTC({ name, data, autoSubscribeVideo });\n    }\n  }\n\n  private async negotiateJoinWebRTC({ name, data, autoSubscribeVideo }: NegotiateJoinParams): Promise<boolean> {\n    HMSLogger.d(TAG, '⏳ join: Negotiating over PUBLISH connection');\n    if (!this.publishConnection) {\n      HMSLogger.e(TAG, 'Publish peer connection not found, cannot negotiate');\n      return false;\n    }\n    const offer = await this.publishConnection.createOffer();\n    await this.publishConnection.setLocalDescription(offer);\n    const serverSubDegrade = this.isFlagEnabled(InitFlags.FLAG_SERVER_SUB_DEGRADATION);\n    const simulcast = this.isFlagEnabled(InitFlags.FLAG_SERVER_SIMULCAST);\n    const onDemandTracks = this.isFlagEnabled(InitFlags.FLAG_ON_DEMAND_TRACKS);\n    const answer = await this.signal.join(\n      name,\n      data,\n      !autoSubscribeVideo,\n      serverSubDegrade,\n      simulcast,\n      onDemandTracks,\n      offer,\n    );\n    await this.publishConnection.setRemoteDescription(answer);\n    for (const candidate of this.publishConnection.candidates) {\n      await this.publishConnection.addIceCandidate(candidate);\n    }\n\n    this.publishConnection.initAfterJoin();\n    return !!answer;\n  }\n\n  private async negotiateJoinNonWebRTC({ name, data, autoSubscribeVideo }: NegotiateJoinParams): Promise<boolean> {\n    HMSLogger.d(TAG, '⏳ join: Negotiating Non-WebRTC');\n    const serverSubDegrade = this.isFlagEnabled(InitFlags.FLAG_SERVER_SUB_DEGRADATION);\n    const simulcast = this.isFlagEnabled(InitFlags.FLAG_SERVER_SIMULCAST);\n    const onDemandTracks = this.isFlagEnabled(InitFlags.FLAG_ON_DEMAND_TRACKS);\n    const response = await this.signal.join(\n      name,\n      data,\n      !autoSubscribeVideo,\n      serverSubDegrade,\n      simulcast,\n      onDemandTracks,\n    );\n    return !!response;\n  }\n\n  /**\n   * Negotiate on first publish after changing role from non-webrtc peer to webrtc peer by sending offer\n   */\n  private async negotiateOnFirstPublish() {\n    HMSLogger.d(TAG, '⏳ Negotiating offer over PUBLISH connection');\n    if (!this.publishConnection) {\n      HMSLogger.e(TAG, 'Publish peer connection not found, cannot negotiate');\n      return false;\n    }\n    const offer = await this.publishConnection.createOffer(this.trackStates);\n    await this.publishConnection.setLocalDescription(offer);\n    const answer = await this.signal.offer(offer, this.trackStates);\n    await this.publishConnection.setRemoteDescription(answer);\n    for (const candidate of this.publishConnection.candidates) {\n      await this.publishConnection.addIceCandidate(candidate);\n    }\n\n    this.publishConnection.initAfterJoin();\n    return !!answer;\n  }\n\n  private async performPublishRenegotiation(constraints?: RTCOfferOptions) {\n    HMSLogger.d(TAG, `⏳ [role=PUBLISH] onRenegotiationNeeded START`, this.trackStates);\n    const callback = this.callbacks.get(RENEGOTIATION_CALLBACK_ID);\n    if (!callback) {\n      return;\n    }\n\n    if (!this.publishConnection) {\n      HMSLogger.e(TAG, 'Publish peer connection not found, cannot renegotiate');\n      return;\n    }\n\n    try {\n      const offer = await this.publishConnection.createOffer(this.trackStates, constraints);\n      await this.publishConnection.setLocalDescription(offer);\n      HMSLogger.time(`renegotiation-offer-exchange`);\n      const answer = await this.signal.offer(offer, this.trackStates);\n      this.callbacks.delete(RENEGOTIATION_CALLBACK_ID);\n      HMSLogger.timeEnd(`renegotiation-offer-exchange`);\n      await this.publishConnection.setRemoteDescription(answer);\n      callback.promise.resolve(true);\n      HMSLogger.d(TAG, `[role=PUBLISH] onRenegotiationNeeded DONE ✅`);\n    } catch (err) {\n      let ex: HMSException;\n      if (err instanceof HMSException) {\n        ex = err;\n      } else {\n        ex = ErrorFactory.GenericErrors.Unknown(HMSAction.PUBLISH, (err as Error).message);\n      }\n\n      callback!.promise.reject(ex);\n      HMSLogger.d(TAG, `[role=PUBLISH] onRenegotiationNeeded FAILED ❌`);\n    }\n  }\n\n  private async handleIceConnectionFailure(role: HMSConnectionRole, error: HMSException) {\n    // ice retry is already in progress(from disconnect state)\n    if (\n      this.retryScheduler.isTaskInProgress(\n        HMSConnectionRole.Publish\n          ? TransportFailureCategory.PublishIceConnectionFailed\n          : TransportFailureCategory.SubscribeIceConnectionFailed,\n      )\n    ) {\n      return;\n    }\n\n    if (role === HMSConnectionRole.Publish) {\n      this.retryScheduler.schedule({\n        category: TransportFailureCategory.PublishIceConnectionFailed,\n        error,\n        task: this.retryPublishIceFailedTask,\n        originalState: TransportState.Joined,\n      });\n    } else {\n      this.retryScheduler.schedule({\n        category: TransportFailureCategory.SubscribeIceConnectionFailed,\n        error,\n        task: this.retrySubscribeIceFailedTask,\n        originalState: TransportState.Joined,\n        maxFailedRetries: 1,\n      });\n    }\n  }\n\n  private async internalConnect(token: string, initEndpoint: string, peerId: string) {\n    HMSLogger.d(TAG, 'connect: started ⏰');\n    const connectRequestedAt = new Date();\n    try {\n      this.analyticsTimer.start(TimedEvent.INIT);\n      this.initConfig = await InitService.fetchInitConfig({\n        token,\n        peerId,\n        userAgent: this.store.getUserAgent(),\n        initEndpoint,\n      });\n      const room = this.store.getRoom();\n      if (room) {\n        room.effectsKey = this.initConfig.config.vb?.effectsKey;\n        room.isEffectsEnabled = this.isFlagEnabled(InitFlags.FLAG_EFFECTS_SDK_ENABLED);\n      }\n      this.analyticsTimer.end(TimedEvent.INIT);\n      HTTPAnalyticsTransport.setWebsocketEndpoint(this.initConfig.endpoint);\n      // if leave was called while init was going on, don't open websocket\n      this.validateNotDisconnected('post init');\n      await this.openSignal(token, peerId);\n      this.observer.onConnected();\n      this.store.setSimulcastEnabled(this.isFlagEnabled(InitFlags.FLAG_SERVER_SIMULCAST));\n      HMSLogger.d(TAG, 'Adding Analytics Transport: JsonRpcSignal');\n      this.analyticsEventsService.setTransport(this.analyticsSignalTransport);\n      this.analyticsEventsService.flush();\n      return this.initConfig;\n    } catch (error) {\n      if (this.state !== TransportState.Reconnecting) {\n        this.eventBus.analytics.publish(\n          AnalyticsEventFactory.connect(\n            error as Error,\n            this.getAdditionalAnalyticsProperties(),\n            connectRequestedAt,\n            new Date(),\n            initEndpoint,\n          ),\n        );\n      }\n      HMSLogger.e(TAG, '❌ internal connect: failed', error);\n      throw error;\n    }\n  }\n\n  // leave could be called between any two async tasks, which would make\n  // the state disconnected instead of connecting, throw error for those cases.\n  private validateNotDisconnected(stage: string) {\n    if (this.state === TransportState.Disconnected) {\n      HMSLogger.w(TAG, 'aborting join as transport state is disconnected');\n      throw ErrorFactory.GenericErrors.ValidationFailed(`leave called before join could complete - stage=${stage}`);\n    }\n  }\n\n  private async openSignal(token: string, peerId: string) {\n    if (!this.initConfig) {\n      throw ErrorFactory.APIErrors.InitConfigNotAvailable(HMSAction.INIT, 'Init Config not found');\n    }\n\n    HMSLogger.d(TAG, '⏳ internal connect: connecting to ws endpoint', this.initConfig.endpoint);\n    const url = new URL(this.initConfig.endpoint);\n    url.searchParams.set('peer', peerId);\n    url.searchParams.set('token', token);\n    url.searchParams.set('user_agent_v2', this.store.getUserAgent());\n    url.searchParams.set('protocol_version', PROTOCOL_VERSION);\n    url.searchParams.set('protocol_spec', PROTOCOL_SPEC);\n\n    this.endpoint = url.toString();\n    this.analyticsTimer.start(TimedEvent.WEBSOCKET_CONNECT);\n    await this.signal.open(this.endpoint);\n    this.analyticsTimer.end(TimedEvent.WEBSOCKET_CONNECT);\n    this.analyticsTimer.start(TimedEvent.ON_POLICY_CHANGE);\n    this.analyticsTimer.start(TimedEvent.ROOM_STATE);\n    HMSLogger.d(TAG, '✅ internal connect: connected to ws endpoint');\n  }\n\n  private async initRtcStatsMonitor() {\n    this.webrtcInternals?.setPeerConnections({\n      publish: this.publishConnection?.nativeConnection,\n      subscribe: this.subscribeConnection?.nativeConnection,\n    });\n\n    this.initStatsAnalytics();\n  }\n\n  private initStatsAnalytics() {\n    if (this.isFlagEnabled(InitFlags.FLAG_PUBLISH_STATS)) {\n      this.publishStatsAnalytics = new PublishStatsAnalytics(\n        this.store,\n        this.eventBus,\n        this.getValueFromInitConfig('publishStats', 'maxSampleWindowSize', PUBLISH_STATS_SAMPLE_WINDOW),\n        this.getValueFromInitConfig('publishStats', 'maxSamplePushInterval', PUBLISH_STATS_PUSH_INTERVAL),\n      );\n\n      this.getWebrtcInternals()?.start();\n    }\n\n    if (this.isFlagEnabled(InitFlags.FLAG_SUBSCRIBE_STATS)) {\n      this.subscribeStatsAnalytics = new SubscribeStatsAnalytics(\n        this.store,\n        this.eventBus,\n        this.getValueFromInitConfig('subscribeStats', 'maxSampleWindowSize', SUBSCRIBE_STATS_SAMPLE_WINDOW),\n        this.getValueFromInitConfig('subscribeStats', 'maxSamplePushInterval', SUBSCRIBE_STATS_PUSH_INTERVAL),\n      );\n\n      this.getWebrtcInternals()?.start();\n    }\n  }\n\n  private getValueFromInitConfig(\n    baseKey: 'publishStats' | 'subscribeStats',\n    subKey: 'maxSampleWindowSize' | 'maxSamplePushInterval',\n    defaultValue: number,\n  ) {\n    return this.initConfig?.config[baseKey]?.[subKey] || defaultValue;\n  }\n\n  /**\n   * Role does not need WebRTC(peer connections to communicate to SFU) if it cannot publish or subscribe to anything\n   * @returns boolean denoting if a peer cannot publish(video, audio or screen) and cannot subscribe to any role\n   */\n  private doesRoleNeedWebRTC(role: HMSRole) {\n    if (!this.isFlagEnabled(InitFlags.FLAG_NON_WEBRTC_DISABLE_OFFER)) {\n      return true;\n    }\n\n    const isPublishing = Boolean(role.publishParams.allowed && role.publishParams.allowed?.length > 0);\n    const isSubscribing = Boolean(\n      role.subscribeParams.subscribeToRoles && role.subscribeParams.subscribeToRoles?.length > 0,\n    );\n\n    return isPublishing || isSubscribing;\n  }\n\n  private doesLocalPeerNeedWebRTC() {\n    const localRole = this.store.getLocalPeer()?.role;\n    if (!localRole) {\n      return true;\n    }\n\n    return this.doesRoleNeedWebRTC(localRole);\n  }\n\n  private retryPublishIceFailedTask = async () => {\n    /**\n     * Proceed with the retry even if the connection state is connected as the offer could have failed\n     * which will cause missing tiles if it is not sent again.\n     * Do iceRestart only if not connected\n     */\n    if (this.publishConnection) {\n      const p = new Promise<boolean>((resolve, reject) => {\n        this.callbacks.set(RENEGOTIATION_CALLBACK_ID, {\n          promise: { resolve, reject },\n          action: HMSAction.RESTART_ICE,\n          extra: {},\n        });\n      });\n      await this.performPublishRenegotiation({ iceRestart: this.publishConnection.connectionState !== 'connected' });\n      await p;\n    }\n\n    return true;\n  };\n\n  private retrySubscribeIceFailedTask = async () => {\n    if (this.subscribeConnection && this.subscribeConnection.connectionState !== 'connected') {\n      const p = new Promise<boolean>((resolve, reject) => {\n        // Use subscribe constant string\n        this.callbacks.set(SUBSCRIBE_ICE_CONNECTION_CALLBACK_ID, {\n          promise: { resolve, reject },\n          action: HMSAction.RESTART_ICE,\n          extra: {},\n        });\n      });\n\n      const timeout = new Promise(resolve => {\n        setTimeout(resolve, SUBSCRIBE_TIMEOUT, false);\n      });\n\n      return Promise.race([p, timeout]) as Promise<boolean>;\n    }\n\n    return true;\n  };\n\n  private retrySignalDisconnectTask = async () => {\n    HMSLogger.d(TAG, 'retrySignalDisconnectTask', { signalConnected: this.signal.isConnected });\n    // Check if ws is disconnected - otherwise if only publishIce fails\n    // and ws connect is success then we don't need to reconnect to WebSocket\n    if (!this.signal.isConnected) {\n      await this.internalConnect(\n        this.joinParameters!.authToken,\n        this.joinParameters!.endpoint,\n        this.joinParameters!.peerId,\n      );\n    }\n\n    // Only retry publish failed task after joining the call - not needed in preview signal reconnect\n    const ok = this.store.getRoom()?.joinedAt\n      ? this.signal.isConnected && (await this.retryPublishIceFailedTask())\n      : this.signal.isConnected;\n    // Send track update to sync local track state changes during reconnection\n    this.signal.trackUpdate(this.trackStates);\n\n    return ok;\n  };\n\n  private handleSubscribeConnectionConnected() {\n    this.subscribeConnection?.logSelectedIceCandidatePairs();\n    const callback = this.callbacks.get(SUBSCRIBE_ICE_CONNECTION_CALLBACK_ID);\n    this.callbacks.delete(SUBSCRIBE_ICE_CONNECTION_CALLBACK_ID);\n\n    if (callback) {\n      callback.promise.resolve(true);\n    }\n  }\n\n  private setTransportStateForConnect() {\n    if (this.state === TransportState.Failed) {\n      this.state = TransportState.Disconnected;\n    }\n\n    if (this.state !== TransportState.Disconnected && this.state !== TransportState.Reconnecting) {\n      throw ErrorFactory.WebsocketMethodErrors.AlreadyJoined(\n        HMSAction.JOIN,\n        `Cannot join a meeting in ${this.state} state`,\n      );\n    }\n\n    if (this.state === TransportState.Disconnected) {\n      this.state = TransportState.Connecting;\n      this.observer.onStateChange(this.state);\n    }\n  }\n\n  private sendErrorAnalyticsEvent(error: HMSException, category: TransportFailureCategory) {\n    const additionalProps = this.getAdditionalAnalyticsProperties();\n    let event: AnalyticsEvent;\n    switch (category) {\n      case TransportFailureCategory.ConnectFailed:\n        event = AnalyticsEventFactory.connect(error, additionalProps);\n        break;\n      case TransportFailureCategory.SignalDisconnect:\n        event = AnalyticsEventFactory.disconnect(error, additionalProps);\n        break;\n      case TransportFailureCategory.JoinWSMessageFailed:\n        event = AnalyticsEventFactory.join({\n          error,\n          time: this.analyticsTimer.getTimeTaken(TimedEvent.JOIN),\n          init_response_time: this.analyticsTimer.getTimeTaken(TimedEvent.INIT),\n          ws_connect_time: this.analyticsTimer.getTimeTaken(TimedEvent.WEBSOCKET_CONNECT),\n          on_policy_change_time: this.analyticsTimer.getTimeTaken(TimedEvent.ON_POLICY_CHANGE),\n          local_audio_track_time: this.analyticsTimer.getTimeTaken(TimedEvent.LOCAL_AUDIO_TRACK),\n          local_video_track_time: this.analyticsTimer.getTimeTaken(TimedEvent.LOCAL_VIDEO_TRACK),\n          retries_join: this.joinRetryCount,\n        });\n        break;\n      case TransportFailureCategory.PublishIceConnectionFailed:\n        event = AnalyticsEventFactory.publish({ error });\n        break;\n      case TransportFailureCategory.SubscribeIceConnectionFailed:\n        event = AnalyticsEventFactory.subscribeFail(error);\n        break;\n    }\n    this.eventBus.analytics.publish(event!);\n  }\n\n  getSubscribeConnection() {\n    return this.subscribeConnection;\n  }\n\n  getAdditionalAnalyticsProperties(): AdditionalAnalyticsProperties {\n    const network_info = getNetworkInfo();\n    const document_hidden = typeof document !== 'undefined' && document.hidden;\n    const num_degraded_tracks = this.store.getRemoteVideoTracks().filter(track => track.degraded).length;\n    const publishBitrate = this.getWebrtcInternals()?.getCurrentStats()?.getLocalPeerStats()?.publish?.bitrate;\n    const subscribeBitrate = this.getWebrtcInternals()?.getCurrentStats()?.getLocalPeerStats()?.subscribe?.bitrate;\n\n    return {\n      network_info,\n      document_hidden,\n      num_degraded_tracks,\n      bitrate: {\n        publish: publishBitrate,\n        subscribe: subscribeBitrate,\n      },\n      max_sub_bitrate: this.maxSubscribeBitrate,\n      recent_pong_response_times: this.signal.getPongResponseTimes(),\n      transport_state: this.state,\n    };\n  }\n}\n","import { ErrorFactory } from '../error/ErrorFactory';\nimport { HMSAction } from '../error/HMSAction';\n\n/**\n * @param retryCodes codes from the server reponse that needs to be retried\n */\n// eslint-disable-next-line complexity\nexport const fetchWithRetry = async (\n  url: RequestInfo,\n  options: RequestInit,\n  retryCodes?: number[],\n): Promise<Response> => {\n  const MAX_RETRIES = 4;\n  let error = Error('something went wrong during fetch');\n  for (let i = 0; i < MAX_RETRIES; i++) {\n    try {\n      // fetch will throw error if there's a browser-level issue\n      const response = await fetch(url, options);\n      const data = await response.clone().json();\n      // throw error for additional codes to retry based on server's response\n      if (retryCodes && retryCodes.length && !response.ok && retryCodes.includes(data.code)) {\n        throw ErrorFactory.APIErrors.ServerErrors(data.code, HMSAction.GET_TOKEN, data.message, false);\n      }\n\n      return response;\n    } catch (err) {\n      error = err as unknown as Error;\n    }\n  }\n  if (['Failed to fetch', 'NetworkError'].some(message => error.message.includes(message))) {\n    throw ErrorFactory.APIErrors.EndpointUnreachable(HMSAction.GET_TOKEN, error.message);\n  }\n  throw error;\n};\n","import { ErrorFactory } from '../error/ErrorFactory';\nimport { HMSAction } from '../error/HMSAction';\n\nexport interface AuthToken {\n  roomId: string;\n  userId: string;\n  role: string;\n}\n\nexport default function decodeJWT(token?: string): AuthToken {\n  if (!token || token.length === 0) {\n    throw ErrorFactory.APIErrors.InvalidTokenFormat(\n      HMSAction.INIT,\n      'Token cannot be an empty string or undefined or null',\n    );\n  }\n\n  const parts = token.split('.');\n  if (parts.length !== 3) {\n    throw ErrorFactory.APIErrors.InvalidTokenFormat(\n      HMSAction.INIT,\n      `Expected 3 '.' separate fields - header, payload and signature respectively`,\n    );\n  }\n\n  const payloadStr = atob(parts[1]);\n  try {\n    const payload = JSON.parse(payloadStr);\n    return {\n      roomId: payload.room_id,\n      userId: payload.user_id,\n      role: payload.role,\n    } as AuthToken;\n  } catch (err) {\n    throw ErrorFactory.APIErrors.InvalidTokenFormat(\n      HMSAction.INIT,\n      `couldn't parse to json - ${(err as Error).message}`,\n    );\n  }\n}\n","import Message from './models/HMSMessage';\nimport HMSRoom from './models/HMSRoom';\nimport { HMSLocalPeer } from './models/peer';\nimport { HMSPeerListIterator } from './HMSPeerListIterator';\nimport { LocalTrackManager } from './LocalTrackManager';\nimport { NetworkTestManager } from './NetworkTestManager';\nimport RoleChangeManager from './RoleChangeManager';\nimport { IStore, Store } from './store';\nimport { WakeLockManager } from './WakeLockManager';\nimport AnalyticsEvent from '../analytics/AnalyticsEvent';\nimport AnalyticsEventFactory from '../analytics/AnalyticsEventFactory';\nimport { HMSAnalyticsLevel } from '../analytics/AnalyticsEventLevel';\nimport { AnalyticsEventsService } from '../analytics/AnalyticsEventsService';\nimport { AnalyticsTimer, TimedEvent } from '../analytics/AnalyticsTimer';\nimport { AudioSinkManager } from '../audio-sink-manager';\nimport { DeviceManager } from '../device-manager';\nimport { AudioOutputManager } from '../device-manager/AudioOutputManager';\nimport { DeviceStorageManager } from '../device-manager/DeviceStorage';\nimport { ErrorCodes } from '../error/ErrorCodes';\nimport { ErrorFactory } from '../error/ErrorFactory';\nimport { HMSAction } from '../error/HMSAction';\nimport { HMSException } from '../error/HMSException';\nimport { EventBus } from '../events/EventBus';\nimport {\n  HMSChangeMultiTrackStateParams,\n  HMSConfig,\n  HMSConnectionQualityListener,\n  HMSDeviceChangeEvent,\n  HMSFrameworkInfo,\n  HMSMessageInput,\n  HMSPlaylistSettings,\n  HMSPlaylistType,\n  HMSPreviewConfig,\n  HMSRole,\n  HMSRoleChangeRequest,\n  HMSScreenShareConfig,\n  TokenRequest,\n  TokenRequestOptions,\n} from '../interfaces';\nimport { DeviceChangeListener } from '../interfaces/devices';\nimport { IErrorListener } from '../interfaces/error-listener';\nimport { HLSConfig, HLSTimedMetadata } from '../interfaces/hls-config';\nimport { HMSInterface } from '../interfaces/hms';\nimport { HMSLeaveRoomRequest } from '../interfaces/leave-room-request';\nimport { HMSPeerListIteratorOptions } from '../interfaces/peer-list-iterator';\nimport { HMSPreviewListener } from '../interfaces/preview-listener';\nimport { RTMPRecordingConfig } from '../interfaces/rtmp-recording-config';\nimport InitialSettings from '../interfaces/settings';\nimport { HMSAudioListener, HMSPeerUpdate, HMSTrackUpdate, HMSUpdateListener } from '../interfaces/update-listener';\nimport { HMSLocalStream } from '../media/streams/HMSLocalStream';\nimport {\n  HMSLocalAudioTrack,\n  HMSLocalTrack,\n  HMSLocalVideoTrack,\n  HMSRemoteTrack,\n  HMSTrackSource,\n  HMSTrackType,\n  HMSVideoTrack,\n} from '../media/tracks';\nimport { HMSNotificationMethod, PeerLeaveRequestNotification } from '../notification-manager';\nimport { createRemotePeer } from '../notification-manager/managers/utils';\nimport { NotificationManager } from '../notification-manager/NotificationManager';\nimport { PlaylistManager } from '../playlist-manager';\nimport { SessionStore } from '../session-store';\nimport { InteractivityCenter } from '../session-store/interactivity-center';\nimport { InitConfig } from '../signal/init/models';\nimport HMSTransport from '../transport';\nimport ITransportObserver from '../transport/ITransportObserver';\nimport { TransportState } from '../transport/models/TransportState';\nimport {\n  DEFAULT_PLAYLIST_AUDIO_BITRATE,\n  DEFAULT_PLAYLIST_VIDEO_BITRATE,\n  HAND_RAISE_GROUP_NAME,\n} from '../utils/constants';\nimport { fetchWithRetry } from '../utils/fetch';\nimport decodeJWT from '../utils/jwt';\nimport HMSLogger, { HMSLogLevel } from '../utils/logger';\nimport { HMSAudioContextHandler } from '../utils/media';\nimport { isNode } from '../utils/support';\nimport { workerSleep } from '../utils/timer-utils';\nimport { validateMediaDevicesExistence, validateRTCPeerConnection } from '../utils/validations';\n\nconst INITIAL_STATE = {\n  published: false,\n  isInitialised: false,\n  isReconnecting: false,\n  isPreviewInProgress: false,\n  isPreviewCalled: false,\n  isJoinInProgress: false,\n  deviceManagersInitialised: false,\n};\n\nexport class HMSSdk implements HMSInterface {\n  private transport!: HMSTransport;\n  private readonly TAG = '[HMSSdk]:';\n  private listener?: HMSUpdateListener;\n  private errorListener?: IErrorListener;\n  private deviceChangeListener?: DeviceChangeListener;\n  private audioListener?: HMSAudioListener;\n  private store!: IStore;\n  private notificationManager?: NotificationManager;\n  private deviceManager!: DeviceManager;\n  private audioSinkManager!: AudioSinkManager;\n  private playlistManager!: PlaylistManager;\n  private audioOutput!: AudioOutputManager;\n  private transportState: TransportState = TransportState.Disconnected;\n  private roleChangeManager?: RoleChangeManager;\n  private localTrackManager!: LocalTrackManager;\n  private analyticsEventsService!: AnalyticsEventsService;\n  private analyticsTimer = new AnalyticsTimer();\n  private eventBus!: EventBus;\n  private networkTestManager!: NetworkTestManager;\n  private wakeLockManager!: WakeLockManager;\n  private sessionStore!: SessionStore;\n  private interactivityCenter!: InteractivityCenter;\n  private sdkState = { ...INITIAL_STATE };\n  private frameworkInfo?: HMSFrameworkInfo;\n  private playlistSettings: HMSPlaylistSettings = {\n    video: {\n      bitrate: DEFAULT_PLAYLIST_VIDEO_BITRATE,\n    },\n    audio: {\n      bitrate: DEFAULT_PLAYLIST_AUDIO_BITRATE,\n    },\n  };\n\n  private initNotificationManager() {\n    if (!this.notificationManager) {\n      this.notificationManager = new NotificationManager(\n        this.store,\n        this.eventBus,\n        this.transport!,\n        this.listener,\n        this.audioListener,\n      );\n    }\n  }\n\n  private initStoreAndManagers() {\n    if (this.sdkState.isInitialised) {\n      /**\n       * Set listener after both join and preview, since they can have different listeners\n       */\n      this.notificationManager?.setListener(this.listener);\n      this.audioSinkManager.setListener(this.listener);\n      this.interactivityCenter.setListener(this.listener);\n      return;\n    }\n\n    this.sdkState.isInitialised = true;\n    this.store = new Store();\n    this.eventBus = new EventBus();\n    this.wakeLockManager = new WakeLockManager();\n    this.networkTestManager = new NetworkTestManager(this.eventBus, this.listener);\n    this.playlistManager = new PlaylistManager(this, this.eventBus);\n    this.deviceManager = new DeviceManager(this.store, this.eventBus);\n    this.audioSinkManager = new AudioSinkManager(this.store, this.deviceManager, this.eventBus);\n    this.audioOutput = new AudioOutputManager(this.deviceManager, this.audioSinkManager);\n    this.audioSinkManager.setListener(this.listener);\n    this.eventBus.autoplayError.subscribe(this.handleAutoplayError);\n    this.localTrackManager = new LocalTrackManager(\n      this.store,\n      this.observer,\n      this.deviceManager,\n      this.eventBus,\n      this.analyticsTimer,\n    );\n    this.analyticsEventsService = new AnalyticsEventsService(this.store);\n    this.transport = new HMSTransport(\n      this.observer,\n      this.deviceManager,\n      this.store,\n      this.eventBus,\n      this.analyticsEventsService,\n      this.analyticsTimer,\n    );\n    this.sessionStore = new SessionStore(this.transport);\n    this.interactivityCenter = new InteractivityCenter(this.transport, this.store, this.listener);\n\n    /**\n     * Note: Subscribe to events here right after creating stores and managers\n     * to not miss events that are published before the handlers are subscribed.\n     */\n    this.eventBus.analytics.subscribe(this.sendAnalyticsEvent);\n    this.eventBus.deviceChange.subscribe(this.handleDeviceChange);\n    this.eventBus.audioPluginFailed.subscribe(this.handleAudioPluginError);\n  }\n\n  private validateJoined(name: string) {\n    if (!this.localPeer) {\n      throw ErrorFactory.GenericErrors.NotConnected(HMSAction.VALIDATION, `Not connected - ${name}`);\n    }\n  }\n\n  // @ts-ignore\n  private sendHLSAnalytics(error: HMSException) {\n    this.sendAnalyticsEvent(AnalyticsEventFactory.hlsPlayerError(error));\n  }\n\n  async refreshDevices() {\n    this.validateJoined('refreshDevices');\n    await this.deviceManager.init(true);\n  }\n\n  getWebrtcInternals() {\n    return this.transport?.getWebrtcInternals();\n  }\n\n  getSessionStore() {\n    return this.sessionStore;\n  }\n\n  getPlaylistManager(): PlaylistManager {\n    return this.playlistManager;\n  }\n\n  getRecordingState() {\n    return this.store.getRoom()?.recording;\n  }\n\n  getRTMPState() {\n    return this.store.getRoom()?.rtmp;\n  }\n\n  getHLSState() {\n    return this.store.getRoom()?.hls;\n  }\n\n  getTemplateAppData() {\n    return this.store.getTemplateAppData();\n  }\n\n  getInteractivityCenter() {\n    return this.interactivityCenter;\n  }\n\n  getPeerListIterator(options?: HMSPeerListIteratorOptions) {\n    return new HMSPeerListIterator(this.transport, this.store, options);\n  }\n\n  updatePlaylistSettings(options: HMSPlaylistSettings) {\n    if (options.video) {\n      Object.assign(this.playlistSettings.video, options.video);\n    }\n    if (options.audio) {\n      Object.assign(this.playlistSettings.audio, options.audio);\n    }\n  }\n\n  private handleAutoplayError = (error: HMSException) => {\n    this.errorListener?.onError?.(error);\n  };\n\n  private get localPeer(): HMSLocalPeer | undefined {\n    return this.store?.getLocalPeer();\n  }\n\n  private observer: ITransportObserver = {\n    onNotification: (message: any) => {\n      if (message.method === HMSNotificationMethod.PEER_LEAVE_REQUEST) {\n        this.handlePeerLeaveRequest(message.params as PeerLeaveRequestNotification);\n        return;\n      }\n\n      switch (message.method) {\n        case HMSNotificationMethod.POLICY_CHANGE:\n          this.analyticsTimer.end(TimedEvent.ON_POLICY_CHANGE);\n          break;\n        case HMSNotificationMethod.PEER_LIST:\n          this.analyticsTimer.end(TimedEvent.PEER_LIST);\n          this.sendJoinAnalyticsEvent(this.sdkState.isPreviewCalled);\n          break;\n        case HMSNotificationMethod.ROOM_STATE:\n          this.analyticsTimer.end(TimedEvent.ROOM_STATE);\n          break;\n        default:\n      }\n\n      this.notificationManager?.handleNotification(message, this.sdkState.isReconnecting);\n    },\n\n    onConnected: () => {\n      this.initNotificationManager();\n    },\n\n    onTrackAdd: (track: HMSRemoteTrack) => {\n      this.notificationManager?.handleTrackAdd(track);\n    },\n\n    onTrackRemove: (track: HMSRemoteTrack) => {\n      this.notificationManager?.handleTrackRemove(track);\n    },\n\n    onFailure: (exception: HMSException) => {\n      this.errorListener?.onError(exception);\n    },\n\n    onStateChange: async (state: TransportState, error?: HMSException) => {\n      const handleFailedState = async (error?: HMSException) => {\n        await this.internalLeave(true, error);\n        /**\n         * no need to call onError here when preview/join is in progress\n         * since preview/join will call onError when they receive leave event from the above call\n         */\n        if (!this.sdkState.isPreviewInProgress && !this.sdkState.isJoinInProgress) {\n          this.errorListener?.onError?.(error!);\n        }\n        this.sdkState.isReconnecting = false;\n      };\n\n      switch (state) {\n        case TransportState.Preview:\n        case TransportState.Joined:\n          this.initNotificationManager();\n          if (this.transportState === TransportState.Reconnecting) {\n            this.listener?.onReconnected();\n          }\n          break;\n        case TransportState.Failed:\n          await handleFailedState(error);\n          break;\n        case TransportState.Reconnecting:\n          this.sdkState.isReconnecting = true;\n          this.listener?.onReconnecting(error!);\n          break;\n      }\n\n      this.transportState = state;\n      HMSLogger.d(this.TAG, 'Transport State Change', this.transportState);\n    },\n  };\n\n  private handlePeerLeaveRequest = (message: PeerLeaveRequestNotification) => {\n    const peer = message.requested_by ? this.store.getPeerById(message.requested_by) : undefined;\n    const request: HMSLeaveRoomRequest = {\n      roomEnded: message.room_end,\n      reason: message.reason,\n      requestedBy: peer,\n    };\n    this.listener?.onRemovedFromRoom(request);\n    this.internalLeave(false);\n  };\n\n  async preview(config: HMSPreviewConfig, listener: HMSPreviewListener) {\n    validateMediaDevicesExistence();\n    validateRTCPeerConnection();\n\n    if (this.sdkState.isPreviewInProgress) {\n      return Promise.reject(\n        ErrorFactory.GenericErrors.PreviewAlreadyInProgress(HMSAction.PREVIEW, 'Preview already called'),\n      );\n    }\n\n    if ([TransportState.Joined, TransportState.Reconnecting].includes(this.transportState)) {\n      return this.midCallPreview(config.asRole, config.settings);\n    }\n\n    this.analyticsTimer.start(TimedEvent.PREVIEW);\n    this.setUpPreview(config, listener);\n\n    // Request permissions and populate devices before waiting for policy\n    if (config.alwaysRequestPermissions) {\n      this.localTrackManager.requestPermissions().then(async () => {\n        await this.initDeviceManagers();\n      });\n    }\n\n    let initSuccessful = false;\n    let networkTestFinished = false;\n    const timerId = setTimeout(() => {\n      // If init or network is not done by 3s send -1\n      if (!initSuccessful || !networkTestFinished) {\n        this.listener?.onNetworkQuality?.(-1);\n      }\n    }, 3000);\n    return new Promise<void>((resolve, reject) => {\n      const policyHandler = async () => {\n        if (this.localPeer) {\n          const newRole = config.asRole && this.store.getPolicyForRole(config.asRole);\n          this.localPeer.asRole = newRole || this.localPeer.role;\n        }\n        const tracks = await this.localTrackManager.getTracksToPublish(config.settings);\n        tracks.forEach(track => this.setLocalPeerTrack(track));\n        this.localPeer?.audioTrack && this.initPreviewTrackAudioLevelMonitor();\n        await this.initDeviceManagers();\n        this.sdkState.isPreviewInProgress = false;\n        this.analyticsTimer.end(TimedEvent.PREVIEW);\n        const room = this.store.getRoom();\n        if (room) {\n          listener.onPreview(room, tracks);\n        }\n        this.sendPreviewAnalyticsEvent();\n        resolve();\n      };\n\n      const errorHandler = (ex?: HMSException) => {\n        this.analyticsTimer.end(TimedEvent.PREVIEW);\n        ex && this.errorListener?.onError(ex);\n        this.sendPreviewAnalyticsEvent(ex);\n        this.sdkState.isPreviewInProgress = false;\n        reject(ex as HMSException);\n      };\n\n      this.eventBus.policyChange.subscribeOnce(policyHandler);\n      this.eventBus.leave.subscribeOnce(errorHandler);\n\n      this.transport\n        .preview(\n          config.authToken,\n          config.initEndpoint!,\n          this.localPeer!.peerId,\n          { name: config.userName, metaData: config.metaData || '' },\n          config.autoVideoSubscribe,\n        )\n        .then((initConfig: InitConfig | void) => {\n          initSuccessful = true;\n          clearTimeout(timerId);\n          if (initConfig && config.captureNetworkQualityInPreview) {\n            this.networkTestManager.start(initConfig.config?.networkHealth).then(() => {\n              networkTestFinished = true;\n            });\n          }\n        })\n        .catch(errorHandler);\n    });\n  }\n\n  private async midCallPreview(asRole?: string, settings?: InitialSettings): Promise<void> {\n    if (!this.localPeer || this.transportState !== TransportState.Joined) {\n      throw ErrorFactory.GenericErrors.NotConnected(HMSAction.VALIDATION, 'Not connected - midCallPreview');\n    }\n\n    const newRole = asRole && this.store.getPolicyForRole(asRole);\n    if (!newRole) {\n      throw ErrorFactory.GenericErrors.InvalidRole(HMSAction.PREVIEW, `role ${asRole} does not exist in policy`);\n    }\n    this.localPeer.asRole = newRole;\n\n    const tracks = await this.localTrackManager.getTracksToPublish(settings);\n    tracks.forEach(track => this.setLocalPeerTrack(track));\n    this.localPeer?.audioTrack && this.initPreviewTrackAudioLevelMonitor();\n    await this.initDeviceManagers();\n\n    this.listener?.onPreview(this.store.getRoom()!, tracks);\n  }\n\n  async cancelMidCallPreview() {\n    if (!this.localPeer || !this.localPeer.isInPreview()) {\n      HMSLogger.w(this.TAG, 'Cannot cancel mid call preview as preview is not in progress');\n    }\n\n    if (this.localPeer?.asRole && this.localPeer.role) {\n      const oldRole = this.localPeer.asRole;\n      const newRole = this.localPeer.role;\n      delete this.localPeer.asRole;\n      await this.roleChangeManager?.diffRolesAndPublishTracks({\n        oldRole,\n        newRole,\n      });\n\n      this.listener?.onPeerUpdate(HMSPeerUpdate.ROLE_UPDATED, this.localPeer);\n    }\n  }\n\n  private handleDeviceChange = (event: HMSDeviceChangeEvent) => {\n    HMSLogger.d(this.TAG, 'Device Change event', event);\n    this.deviceChangeListener?.onDeviceChange?.(event);\n    if (event.error && event.type) {\n      const track = event.type.includes('audio') ? this.localPeer?.audioTrack : this.localPeer?.videoTrack;\n      this.errorListener?.onError(event.error);\n      if (\n        [\n          ErrorCodes.TracksErrors.CANT_ACCESS_CAPTURE_DEVICE,\n          ErrorCodes.TracksErrors.DEVICE_IN_USE,\n          ErrorCodes.TracksErrors.DEVICE_NOT_AVAILABLE,\n        ].includes(event.error.code) &&\n        track\n      ) {\n        track.setEnabled(false);\n        this.listener?.onTrackUpdate(HMSTrackUpdate.TRACK_MUTED, track, this.localPeer!);\n      }\n    }\n  };\n\n  private handleAudioPluginError = (error: HMSException) => {\n    HMSLogger.e(this.TAG, 'Audio Plugin Error event', error);\n    this.errorListener?.onError(error);\n  };\n\n  async join(config: HMSConfig, listener: HMSUpdateListener) {\n    validateMediaDevicesExistence();\n    validateRTCPeerConnection();\n\n    if (this.sdkState.isPreviewInProgress) {\n      throw ErrorFactory.GenericErrors.NotReady(HMSAction.JOIN, \"Preview is in progress, can't join\");\n    }\n\n    this.analyticsTimer.start(TimedEvent.JOIN);\n    this.sdkState.isJoinInProgress = true;\n\n    const { roomId, userId, role } = decodeJWT(config.authToken);\n    const previewRole = this.localPeer?.asRole?.name || this.localPeer?.role?.name;\n    this.networkTestManager?.stop();\n    this.listener = listener;\n    this.commonSetup(config, roomId, listener);\n    this.removeDevicesFromConfig(config);\n    this.store.setConfig(config);\n    /** set after config since we need config to get env for user agent */\n    this.store.createAndSetUserAgent(this.frameworkInfo);\n    HMSAudioContextHandler.resumeContext();\n    // acquire screen lock to stay awake while in call\n    const storeConfig = this.store.getConfig();\n    if (storeConfig?.autoManageWakeLock) {\n      this.wakeLockManager.acquireLock();\n    }\n\n    if (!this.localPeer) {\n      this.createAndAddLocalPeerToStore(config, role, userId);\n    } else {\n      this.localPeer.name = config.userName;\n      this.localPeer.role = this.store.getPolicyForRole(role);\n      this.localPeer.customerUserId = userId;\n      this.localPeer.metadata = config.metaData;\n      delete this.localPeer.asRole;\n    }\n\n    this.roleChangeManager = new RoleChangeManager(\n      this.store,\n      this.transport,\n      this.deviceManager,\n      this.getAndPublishTracks.bind(this),\n      this.removeTrack.bind(this),\n      this.listener,\n    );\n    this.eventBus.localRoleUpdate.subscribe(this.handleLocalRoleUpdate);\n\n    HMSLogger.d(this.TAG, `⏳ Joining room ${roomId}`);\n\n    HMSLogger.time(`join-room-${roomId}`);\n\n    try {\n      await this.transport.join(\n        config.authToken,\n        this.localPeer!.peerId,\n        { name: config.userName, metaData: config.metaData! },\n        config.initEndpoint!,\n        config.autoVideoSubscribe,\n      );\n      HMSLogger.d(this.TAG, `✅ Joined room ${roomId}`);\n      this.analyticsTimer.start(TimedEvent.PEER_LIST);\n      await this.notifyJoin();\n      this.sdkState.isJoinInProgress = false;\n      await this.publish(config.settings, previewRole);\n    } catch (error) {\n      this.analyticsTimer.end(TimedEvent.JOIN);\n      this.sdkState.isJoinInProgress = false;\n      this.listener?.onError(error as HMSException);\n      this.sendJoinAnalyticsEvent(this.sdkState.isPreviewCalled, error as HMSException);\n      HMSLogger.e(this.TAG, 'Unable to join room', error);\n      throw error;\n    }\n    HMSLogger.timeEnd(`join-room-${roomId}`);\n  }\n\n  private stringifyMetadata(config: HMSConfig) {\n    if (config.metaData && typeof config.metaData !== 'string') {\n      config.metaData = JSON.stringify(config.metaData);\n    } else if (!config.metaData) {\n      config.metaData = '';\n    }\n  }\n\n  private cleanup() {\n    this.cleanDeviceManagers();\n    this.eventBus.analytics.unsubscribe(this.sendAnalyticsEvent);\n    this.analyticsTimer.cleanup();\n    DeviceStorageManager.cleanup();\n    this.playlistManager.cleanup();\n    this.wakeLockManager?.cleanup();\n    LocalTrackManager.cleanup();\n    this.notificationManager = undefined;\n    HMSLogger.cleanup();\n    this.sdkState = { ...INITIAL_STATE };\n    /**\n     * when leave is called after preview itself without join.\n     * Store won't have the tracks in this case\n     */\n    if (this.localPeer) {\n      this.localPeer.audioTrack?.cleanup();\n      this.localPeer.audioTrack = undefined;\n      this.localPeer.videoTrack?.cleanup();\n      this.localPeer.videoTrack = undefined;\n    }\n    this.store.cleanup();\n    this.listener = undefined;\n    if (this.roleChangeManager) {\n      this.eventBus.localRoleUpdate.unsubscribe(this.handleLocalRoleUpdate);\n    }\n  }\n\n  leave(notifyServer?: boolean) {\n    return this.internalLeave(notifyServer);\n  }\n\n  private async internalLeave(notifyServer = true, error?: HMSException) {\n    const room = this.store?.getRoom();\n    if (room) {\n      // Wait for preview or join to finish to prevent any race conditions happening because preview/join are called multiple times\n      // This can happen when useEffects are not properly handled in case of react apps\n      // when error is terminal this will go into infinite loop so error?.isTerminal check is needed\n      while ((this.sdkState.isPreviewInProgress || this.sdkState.isJoinInProgress) && !error?.isTerminal) {\n        await workerSleep(100);\n      }\n      const roomId = room.id;\n      this.networkTestManager?.stop();\n      this.eventBus.leave.publish(error);\n      HMSLogger.d(this.TAG, `⏳ Leaving room ${roomId}`);\n      // browsers often put limitation on amount of time a function set on window onBeforeUnload can take in case of\n      // tab refresh or close. Therefore prioritise the leave action over anything else, if tab is closed/refreshed\n      // we would want leave to succeed to stop stucked peer for others. The followup cleanup however is important\n      // for cases where uses stays on the page post leave.\n      await this.transport?.leave(notifyServer);\n      this.cleanup();\n      HMSLogger.d(this.TAG, `✅ Left room ${roomId}`);\n    }\n  }\n\n  async getAuthTokenByRoomCode(tokenRequest: TokenRequest, tokenRequestOptions?: TokenRequestOptions): Promise<string> {\n    const tokenAPIURL = (tokenRequestOptions || {}).endpoint || 'https://auth.100ms.live/v2/token';\n    this.analyticsTimer.start(TimedEvent.GET_TOKEN);\n    const response = await fetchWithRetry(\n      tokenAPIURL,\n      {\n        method: 'POST',\n        body: JSON.stringify({ code: tokenRequest.roomCode, user_id: tokenRequest.userId }),\n      },\n      [429, 500, 501, 502, 503, 504, 505, 506, 507, 508, 509, 510, 511],\n    );\n\n    const data = await response.json();\n    this.analyticsTimer.end(TimedEvent.GET_TOKEN);\n\n    if (!response.ok) {\n      throw ErrorFactory.APIErrors.ServerErrors(data.code, HMSAction.GET_TOKEN, data.message, false);\n    }\n\n    const { token } = data;\n    if (!token) {\n      throw Error(data.message);\n    }\n    return token;\n  }\n\n  getLocalPeer() {\n    return this.store.getLocalPeer();\n  }\n\n  getPeers() {\n    return this.store.getPeers();\n  }\n\n  getPeerMap() {\n    return this.store.getPeerMap();\n  }\n\n  getAudioOutput() {\n    return this.audioOutput;\n  }\n\n  sendMessage(type: string, message: string) {\n    this.sendMessageInternal({ message, type });\n  }\n\n  async sendBroadcastMessage(message: string, type?: string) {\n    return await this.sendMessageInternal({ message, type });\n  }\n\n  async sendGroupMessage(message: string, roles: HMSRole[], type?: string) {\n    const knownRoles = this.store.getKnownRoles();\n    const recipientRoles =\n      roles.filter(role => {\n        return knownRoles[role.name];\n      }) || [];\n    if (recipientRoles.length === 0) {\n      throw ErrorFactory.GenericErrors.ValidationFailed('No valid role is present', roles);\n    }\n    return await this.sendMessageInternal({ message, recipientRoles: roles, type });\n  }\n\n  async sendDirectMessage(message: string, peerId: string, type?: string) {\n    if (this.localPeer?.peerId === peerId) {\n      throw ErrorFactory.GenericErrors.ValidationFailed('Cannot send message to self');\n    }\n    const isLargeRoom = !!this.store.getRoom()?.large_room_optimization;\n    let recipientPeer = this.store.getPeerById(peerId);\n    if (!recipientPeer) {\n      if (isLargeRoom) {\n        const { peers } = await this.transport.findPeers({ peers: [peerId], limit: 1 });\n        if (peers.length === 0) {\n          throw ErrorFactory.GenericErrors.ValidationFailed('Invalid peer - peer not present in the room', peerId);\n        }\n        recipientPeer = createRemotePeer(peers[0], this.store);\n      } else {\n        throw ErrorFactory.GenericErrors.ValidationFailed('Invalid peer - peer not present in the room', peerId);\n      }\n    }\n\n    return await this.sendMessageInternal({ message, recipientPeer, type });\n  }\n\n  private async sendMessageInternal({ recipientRoles, recipientPeer, type = 'chat', message }: HMSMessageInput) {\n    if (message.replace(/\\u200b/g, ' ').trim() === '') {\n      HMSLogger.w(this.TAG, 'sendMessage', 'Ignoring empty message send');\n      throw ErrorFactory.GenericErrors.ValidationFailed('Empty message not allowed');\n    }\n    const hmsMessage = new Message({\n      sender: this.localPeer!,\n      type,\n      message,\n      recipientPeer,\n      recipientRoles,\n      time: new Date(),\n    });\n    HMSLogger.d(this.TAG, 'Sending Message: ', hmsMessage);\n    const response = await this.transport.sendMessage(hmsMessage);\n    hmsMessage.time = new Date(response.timestamp);\n    hmsMessage.id = response.message_id;\n    return hmsMessage;\n  }\n\n  async startScreenShare(onStop: () => void, config?: HMSScreenShareConfig) {\n    const publishParams = this.store.getPublishParams();\n    if (!publishParams) {\n      return;\n    }\n\n    const { allowed } = publishParams;\n    const canPublishScreen = allowed && allowed.includes('screen');\n\n    if (!canPublishScreen) {\n      HMSLogger.e(this.TAG, `Role ${this.localPeer?.role} cannot share screen`);\n      return;\n    }\n\n    if (this.localPeer?.auxiliaryTracks?.find(track => track.source === 'screen')) {\n      throw Error('Cannot share multiple screens');\n    }\n\n    const tracks = await this.getScreenshareTracks(onStop, config);\n    if (!this.localPeer) {\n      HMSLogger.d(this.TAG, 'Screenshared when not connected');\n      tracks.forEach(track => {\n        track.cleanup();\n      });\n      return;\n    }\n    await this.transport.publish(tracks);\n    tracks.forEach(track => {\n      track.peerId = this.localPeer?.peerId;\n      this.localPeer?.auxiliaryTracks.push(track);\n      this.listener?.onTrackUpdate(HMSTrackUpdate.TRACK_ADDED, track, this.localPeer!);\n    });\n  }\n\n  private async stopEndedScreenshare(onStop: () => void) {\n    HMSLogger.d(this.TAG, `✅ Screenshare ended natively`);\n    await this.stopScreenShare();\n    onStop();\n  }\n\n  async stopScreenShare() {\n    HMSLogger.d(this.TAG, `✅ Screenshare ended from app`);\n    const screenTracks = this.localPeer?.auxiliaryTracks.filter(t => t.source === 'screen');\n    if (screenTracks) {\n      for (const track of screenTracks) {\n        await this.removeTrack(track.trackId);\n      }\n    }\n  }\n\n  async addTrack(track: MediaStreamTrack, source: HMSTrackSource = 'regular'): Promise<void> {\n    if (!track) {\n      HMSLogger.w(this.TAG, 'Please pass a valid MediaStreamTrack');\n      return;\n    }\n    if (!this.localPeer) {\n      throw ErrorFactory.GenericErrors.NotConnected(HMSAction.VALIDATION, 'No local peer present, cannot addTrack');\n    }\n    const isTrackPresent = this.localPeer.auxiliaryTracks.find(t => t.trackId === track.id);\n    if (isTrackPresent) {\n      return;\n    }\n\n    const type = track.kind;\n    const nativeStream = new MediaStream([track]);\n    const stream = new HMSLocalStream(nativeStream);\n\n    const TrackKlass = type === 'audio' ? HMSLocalAudioTrack : HMSLocalVideoTrack;\n    const hmsTrack = new TrackKlass(stream, track, source, this.eventBus);\n    this.setPlaylistSettings({\n      track,\n      hmsTrack,\n      source,\n    });\n\n    await this.transport?.publish([hmsTrack]);\n    hmsTrack.peerId = this.localPeer?.peerId;\n    this.localPeer?.auxiliaryTracks.push(hmsTrack);\n    this.listener?.onTrackUpdate(HMSTrackUpdate.TRACK_ADDED, hmsTrack, this.localPeer!);\n  }\n\n  async removeTrack(trackId: string, internal = false) {\n    if (!this.localPeer) {\n      throw ErrorFactory.GenericErrors.NotConnected(HMSAction.VALIDATION, 'No local peer present, cannot removeTrack');\n    }\n    const trackIndex = this.localPeer.auxiliaryTracks.findIndex(t => t.trackId === trackId);\n    if (trackIndex > -1) {\n      const track = this.localPeer.auxiliaryTracks[trackIndex];\n      if (track.isPublished) {\n        await this.transport!.unpublish([track]);\n      } else {\n        await track.cleanup();\n      }\n      // Stop local playback when playlist track is removed\n      if (!internal) {\n        this.stopPlaylist(track);\n      }\n      this.localPeer.auxiliaryTracks.splice(trackIndex, 1);\n      this.listener?.onTrackUpdate(HMSTrackUpdate.TRACK_REMOVED, track, this.localPeer);\n    } else {\n      HMSLogger.w(this.TAG, `No track found for ${trackId}`);\n    }\n  }\n\n  setAnalyticsLevel(level: HMSAnalyticsLevel) {\n    this.analyticsEventsService.level = level;\n  }\n\n  setLogLevel(level: HMSLogLevel) {\n    HMSLogger.level = level;\n  }\n\n  addAudioListener(audioListener: HMSAudioListener) {\n    this.audioListener = audioListener;\n    this.notificationManager?.setAudioListener(audioListener);\n  }\n\n  addConnectionQualityListener(qualityListener: HMSConnectionQualityListener) {\n    this.notificationManager?.setConnectionQualityListener(qualityListener);\n  }\n\n  async changeRole(forPeerId: string, toRole: string, force = false) {\n    await this.transport?.changeRoleOfPeer(forPeerId, toRole, force);\n  }\n\n  async changeRoleOfPeer(forPeerId: string, toRole: string, force = false) {\n    await this.transport?.changeRoleOfPeer(forPeerId, toRole, force);\n  }\n\n  async changeRoleOfPeersWithRoles(roles: HMSRole[], toRole: string) {\n    if (roles.length <= 0 || !toRole) {\n      return;\n    }\n\n    await this.transport?.changeRoleOfPeersWithRoles(roles, toRole);\n  }\n\n  async acceptChangeRole(request: HMSRoleChangeRequest) {\n    await this.transport?.acceptRoleChange(request);\n  }\n\n  async endRoom(lock: boolean, reason: string) {\n    if (!this.localPeer) {\n      throw ErrorFactory.GenericErrors.NotConnected(HMSAction.VALIDATION, 'No local peer present, cannot end room');\n    }\n    await this.transport?.endRoom(lock, reason);\n    await this.leave();\n  }\n\n  async removePeer(peerId: string, reason: string) {\n    if (!this.localPeer) {\n      throw ErrorFactory.GenericErrors.NotConnected(HMSAction.VALIDATION, 'No local peer present, cannot remove peer');\n    }\n    await this.transport?.removePeer(peerId, reason);\n  }\n\n  async startRTMPOrRecording(params: RTMPRecordingConfig) {\n    if (!this.localPeer) {\n      throw ErrorFactory.GenericErrors.NotConnected(\n        HMSAction.VALIDATION,\n        'No local peer present, cannot start streaming or recording',\n      );\n    }\n    await this.transport?.startRTMPOrRecording(params);\n  }\n\n  async stopRTMPAndRecording() {\n    if (!this.localPeer) {\n      throw ErrorFactory.GenericErrors.NotConnected(\n        HMSAction.VALIDATION,\n        'No local peer present, cannot stop streaming or recording',\n      );\n    }\n    await this.transport?.stopRTMPOrRecording();\n  }\n\n  async startHLSStreaming(params?: HLSConfig) {\n    if (!this.localPeer) {\n      throw ErrorFactory.GenericErrors.NotConnected(\n        HMSAction.VALIDATION,\n        'No local peer present, cannot start HLS streaming',\n      );\n    }\n    await this.transport?.startHLSStreaming(params);\n  }\n\n  async stopHLSStreaming(params?: HLSConfig) {\n    if (!this.localPeer) {\n      throw ErrorFactory.GenericErrors.NotConnected(\n        HMSAction.VALIDATION,\n        'No local peer present, cannot stop HLS streaming',\n      );\n    }\n    await this.transport?.stopHLSStreaming(params);\n  }\n\n  async sendHLSTimedMetadata(metadataList: HLSTimedMetadata[]) {\n    this.validateJoined('sendHLSTimedMetadata');\n    await this.transport?.sendHLSTimedMetadata(metadataList);\n  }\n\n  async changeName(name: string) {\n    this.validateJoined('changeName');\n    await this.transport?.changeName(name);\n    this.notificationManager?.updateLocalPeer({ name });\n  }\n\n  async changeMetadata(metadata: string) {\n    this.validateJoined('changeMetadata');\n    await this.transport?.changeMetadata(metadata);\n    this.notificationManager?.updateLocalPeer({ metadata });\n  }\n\n  async setSessionMetadata(metadata: any) {\n    await this.transport.setSessionMetadata({ key: 'default', data: metadata });\n  }\n\n  async getSessionMetadata() {\n    const response = await this.transport.getSessionMetadata('default');\n    return response.data;\n  }\n\n  getRoles(): HMSRole[] {\n    return Object.values(this.store.getKnownRoles());\n  }\n\n  async changeTrackState(forRemoteTrack: HMSRemoteTrack, enabled: boolean) {\n    if (forRemoteTrack.type === HMSTrackType.VIDEO && forRemoteTrack.source !== 'regular') {\n      HMSLogger.w(this.TAG, `Muting non-regular video tracks is currently not supported`);\n      return;\n    }\n\n    if (forRemoteTrack.enabled === enabled) {\n      HMSLogger.w(this.TAG, `Aborting change track state, track already has enabled - ${enabled}`, forRemoteTrack);\n      return;\n    }\n\n    if (!this.store.getTrackById(forRemoteTrack.trackId)) {\n      throw ErrorFactory.GenericErrors.ValidationFailed('No track found for change track state', forRemoteTrack);\n    }\n\n    const peer = this.store.getPeerByTrackId(forRemoteTrack.trackId);\n\n    if (!peer) {\n      throw ErrorFactory.GenericErrors.ValidationFailed('No peer found for change track state', forRemoteTrack);\n    }\n\n    await this.transport?.changeTrackState({\n      requested_for: peer.peerId,\n      track_id: forRemoteTrack.trackId,\n      stream_id: forRemoteTrack.stream.id,\n      mute: !enabled,\n    });\n  }\n\n  async changeMultiTrackState(params: HMSChangeMultiTrackStateParams) {\n    if (typeof params.enabled !== 'boolean') {\n      throw ErrorFactory.GenericErrors.ValidationFailed('Pass a boolean for enabled');\n    }\n    const { enabled, roles, type, source } = params;\n    await this.transport?.changeMultiTrackState({\n      value: !enabled,\n      type,\n      source,\n      roles: roles?.map(role => role?.name),\n    });\n  }\n\n  async raiseLocalPeerHand() {\n    this.validateJoined('raiseLocalPeerHand');\n    await this.transport.joinGroup(HAND_RAISE_GROUP_NAME);\n  }\n  async lowerLocalPeerHand() {\n    this.validateJoined('lowerLocalPeerHand');\n    await this.transport.leaveGroup(HAND_RAISE_GROUP_NAME);\n  }\n  async raiseRemotePeerHand(peerId: string) {\n    await this.transport.addToGroup(peerId, HAND_RAISE_GROUP_NAME);\n  }\n  async lowerRemotePeerHand(peerId: string) {\n    await this.transport.removeFromGroup(peerId, HAND_RAISE_GROUP_NAME);\n  }\n\n  setFrameworkInfo(frameworkInfo: HMSFrameworkInfo) {\n    this.frameworkInfo = { ...this.frameworkInfo, ...frameworkInfo };\n  }\n\n  async attachVideo(track: HMSVideoTrack, videoElement: HTMLVideoElement) {\n    const config = this.store.getConfig();\n    if (config?.autoManageVideo) {\n      track.attach(videoElement);\n    } else {\n      await track.addSink(videoElement);\n    }\n  }\n\n  async detachVideo(track: HMSVideoTrack, videoElement: HTMLVideoElement) {\n    const config = this.store.getConfig();\n    if (config?.autoManageVideo) {\n      track.detach(videoElement);\n    } else {\n      await track.removeSink(videoElement);\n    }\n  }\n\n  private async publish(initialSettings?: InitialSettings, oldRole?: string) {\n    if ([this.store.getPublishParams(), !this.sdkState.published, !isNode].every(value => !!value)) {\n      // if preview asRole(oldRole) is used, use roleChangeManager to diff policy and publish, else do normal publish\n      const publishAction =\n        oldRole && oldRole !== this.localPeer?.role?.name\n          ? () =>\n              this.roleChangeManager?.diffRolesAndPublishTracks({\n                oldRole: this.store.getPolicyForRole(oldRole),\n                newRole: this.localPeer!.role!,\n              })\n          : () => this.getAndPublishTracks(initialSettings);\n\n      await publishAction?.()?.catch(error => {\n        HMSLogger.e(this.TAG, 'Error in publish', error);\n        this.listener?.onError(error);\n      });\n    }\n  }\n\n  private async getAndPublishTracks(initialSettings?: InitialSettings) {\n    const tracks = await this.localTrackManager.getTracksToPublish(initialSettings);\n    await this.setAndPublishTracks(tracks);\n    this.localPeer?.audioTrack?.initAudioLevelMonitor();\n    this.sdkState.published = true;\n  }\n\n  private handleLocalRoleUpdate = async ({ oldRole, newRole }: { oldRole: HMSRole; newRole: HMSRole }) => {\n    await this.transport.handleLocalRoleUpdate({ oldRole, newRole });\n    await this.roleChangeManager?.handleLocalPeerRoleUpdate({ oldRole, newRole });\n  };\n\n  private async setAndPublishTracks(tracks: HMSLocalTrack[]) {\n    for (const track of tracks) {\n      await this.transport.publish([track]);\n      this.setLocalPeerTrack(track);\n      this.listener?.onTrackUpdate(HMSTrackUpdate.TRACK_ADDED, track, this.localPeer!);\n    }\n    await this.initDeviceManagers();\n  }\n\n  private setLocalPeerTrack(track: HMSLocalTrack) {\n    track.peerId = this.localPeer?.peerId;\n    switch (track.type) {\n      case HMSTrackType.AUDIO:\n        this.localPeer!.audioTrack = track as HMSLocalAudioTrack;\n        break;\n\n      case HMSTrackType.VIDEO:\n        this.localPeer!.videoTrack = track as HMSLocalVideoTrack;\n        break;\n    }\n  }\n\n  private async initDeviceManagers() {\n    // No need to initialise and add listeners if already initialised in preview\n    if (this.sdkState.deviceManagersInitialised) {\n      return;\n    }\n    this.sdkState.deviceManagersInitialised = true;\n    await this.deviceManager.init();\n    if (!(await this.deviceManager.updateOutputDevice(this.store.getConfig()?.settings?.audioOutputDeviceId))) {\n      await this.deviceManager.updateOutputDevice(DeviceStorageManager.getSelection()?.audioOutput?.deviceId);\n    }\n    this.audioSinkManager.init(this.store.getConfig()?.audioSinkElementId);\n  }\n\n  private cleanDeviceManagers() {\n    this.eventBus.deviceChange.unsubscribe(this.handleDeviceChange);\n    this.eventBus.audioPluginFailed.unsubscribe(this.handleAudioPluginError);\n    this.eventBus.autoplayError.unsubscribe(this.handleAutoplayError);\n    this.deviceManager.cleanup();\n    this.audioSinkManager.cleanup();\n  }\n\n  private initPreviewTrackAudioLevelMonitor() {\n    const localAudioTrack = this.localPeer?.audioTrack;\n    localAudioTrack?.initAudioLevelMonitor();\n    this.eventBus.trackAudioLevelUpdate.subscribe(audioLevelUpdate => {\n      const hmsSpeakers =\n        audioLevelUpdate && audioLevelUpdate.track.trackId === localAudioTrack?.trackId\n          ? [{ audioLevel: audioLevelUpdate.audioLevel, peer: this.localPeer!, track: localAudioTrack! }]\n          : [];\n      this.store.updateSpeakers(hmsSpeakers);\n      this.audioListener?.onAudioLevelUpdate(hmsSpeakers);\n    });\n    this.eventBus.localAudioSilence.subscribe(this.sendAudioPresenceFailed);\n  }\n\n  private notifyJoin() {\n    const localPeer = this.store.getLocalPeer();\n    const room = this.store.getRoom();\n    if (!room) {\n      HMSLogger.w(this.TAG, 'notify join - room not present');\n      return;\n    }\n\n    room.joinedAt = new Date();\n    if (localPeer) {\n      localPeer.joinedAt = room.joinedAt;\n    }\n\n    if (localPeer?.role) {\n      this.analyticsTimer.end(TimedEvent.JOIN);\n      this.listener?.onJoin(room);\n      return;\n    }\n\n    return new Promise<void>((resolve, reject) => {\n      this.eventBus.policyChange.subscribeOnce(() => {\n        this.analyticsTimer.end(TimedEvent.JOIN);\n        this.listener?.onJoin(room);\n        resolve();\n      });\n\n      this.eventBus.leave.subscribeOnce(ex => {\n        reject(ex);\n      });\n    });\n  }\n\n  /**\n   * Init store and other managers, setup listeners, create local peer, room\n   * @param {HMSConfig} config\n   * @param {HMSPreviewListener} listener\n   */\n  private setUpPreview(config: HMSPreviewConfig, listener: HMSPreviewListener) {\n    this.listener = listener as unknown as HMSUpdateListener;\n    this.sdkState.isPreviewCalled = true;\n    this.sdkState.isPreviewInProgress = true;\n    const { roomId, userId, role } = decodeJWT(config.authToken);\n    this.commonSetup(config, roomId, listener);\n    this.store.setConfig(config);\n    /** set after config since we need config to get env for user agent */\n    this.store.createAndSetUserAgent(this.frameworkInfo);\n    this.createAndAddLocalPeerToStore(config, role, userId, config.asRole);\n  }\n\n  /**\n   * Set bitrate and dimensions for playlist track\n   */\n  private async setPlaylistSettings({\n    track,\n    hmsTrack,\n    source,\n  }: {\n    track: MediaStreamTrack;\n    hmsTrack: HMSLocalAudioTrack | HMSLocalVideoTrack;\n    source: string;\n  }) {\n    if (source === 'videoplaylist') {\n      const settings: { maxBitrate?: number; width?: number; height?: number } = {};\n      if (track.kind === 'audio') {\n        settings.maxBitrate = this.playlistSettings.audio?.bitrate || DEFAULT_PLAYLIST_AUDIO_BITRATE;\n      } else {\n        settings.maxBitrate = this.playlistSettings.video?.bitrate || DEFAULT_PLAYLIST_VIDEO_BITRATE;\n        const { width, height } = track.getSettings();\n        settings.width = width;\n        settings.height = height;\n      }\n      // TODO: rt update from policy once policy is updated\n      await hmsTrack.setSettings(settings);\n    } else if (source === 'audioplaylist') {\n      // TODO: rt update from policy once policy is updated\n      await hmsTrack.setSettings({ maxBitrate: 64 });\n    }\n  }\n\n  /**\n   * @param {HMSConfig} config\n   * @param {string} role\n   * @param {string} userId\n   */\n  private createAndAddLocalPeerToStore(config: HMSConfig, role: string, userId: string, asRole?: string) {\n    const policy = this.store.getPolicyForRole(role);\n    const asRolePolicy = asRole ? this.store.getPolicyForRole(asRole) : undefined;\n    const localPeer = new HMSLocalPeer({\n      name: config.userName || '',\n      customerUserId: userId,\n      metadata: config.metaData || '',\n      role: policy,\n      // default value is the original role if user didn't pass asRole in config\n      asRole: asRolePolicy || policy,\n    });\n\n    this.store.addPeer(localPeer);\n  }\n\n  /**\n   * init managers and set listeners - common for join and preview\n   * @param {HMSConfig} config\n   * @param {string} roomId\n   * @param {HMSPreviewListener | HMSUpdateListener} listener\n   */\n  private commonSetup(config: HMSConfig, roomId: string, listener: HMSPreviewListener | HMSUpdateListener) {\n    this.stringifyMetadata(config);\n    if (!config.initEndpoint) {\n      config.initEndpoint = 'https://prod-init.100ms.live';\n    }\n    this.errorListener = listener;\n    this.deviceChangeListener = listener;\n    this.initStoreAndManagers();\n    this.store.setErrorListener(this.errorListener);\n    if (!this.store.getRoom()) {\n      this.store.setRoom(new HMSRoom(roomId));\n    }\n  }\n\n  /**\n   * Remove deviceId's passed in config for join if preview was already called\n   * @param {HMSConfig} config\n   */\n  private removeDevicesFromConfig(config: HMSConfig) {\n    const storedConfig = this.store.getConfig();\n    if (storedConfig && config.settings) {\n      // preview was called\n      delete config.settings.audioOutputDeviceId;\n      delete config.settings.videoDeviceId;\n      delete config.settings.audioInputDeviceId;\n    }\n  }\n\n  /**\n   * Get screenshare based on policy and audioOnly flag\n   * @param {function} onStop\n   * @param config\n   * @returns\n   */\n  private async getScreenshareTracks(onStop: () => void, config?: HMSScreenShareConfig) {\n    const [videoTrack, audioTrack] = await this.localTrackManager.getLocalScreen(config);\n\n    const handleEnded = () => {\n      this.stopEndedScreenshare(onStop);\n    };\n\n    const tracks = [];\n    if (config?.audioOnly) {\n      videoTrack.nativeTrack.stop();\n      if (!audioTrack) {\n        throw ErrorFactory.TracksErrors.NothingToReturn(\n          HMSAction.TRACK,\n          'Select share audio when sharing screen',\n          'No audio found',\n        );\n      }\n      tracks.push(audioTrack);\n      audioTrack.nativeTrack.addEventListener('ended', handleEnded);\n    } else {\n      tracks.push(videoTrack);\n      videoTrack.nativeTrack.addEventListener('ended', handleEnded);\n      // audio track is not always available\n      if (audioTrack) {\n        tracks.push(audioTrack);\n      }\n    }\n    return tracks;\n  }\n\n  private sendAudioPresenceFailed = () => {\n    const error = ErrorFactory.TracksErrors.NoAudioDetected(HMSAction.PREVIEW);\n    HMSLogger.w(this.TAG, 'Audio Presence Failure', this.transportState, error);\n    // this.sendAnalyticsEvent(\n    //   AnalyticsEventFactory.audioDetectionFail(error, this.deviceManager.getCurrentSelection().audioInput),\n    // );\n    // this.listener?.onError(error);\n  };\n\n  private sendJoinAnalyticsEvent = (is_preview_called = false, error?: HMSException) => {\n    this.eventBus.analytics.publish(\n      AnalyticsEventFactory.join({\n        error,\n        ...this.analyticsTimer.getTimes(),\n        time: this.analyticsTimer.getTimeTaken(TimedEvent.JOIN),\n        is_preview_called,\n        retries_join: this.transport.joinRetryCount,\n      }),\n    );\n  };\n\n  private sendPreviewAnalyticsEvent = (error?: HMSException) => {\n    this.eventBus.analytics.publish(\n      AnalyticsEventFactory.preview({\n        error,\n        ...this.analyticsTimer.getTimes(),\n        time: this.analyticsTimer.getTimeTaken(TimedEvent.PREVIEW),\n      }),\n    );\n  };\n\n  private sendAnalyticsEvent = (event: AnalyticsEvent) => {\n    this.analyticsEventsService.queue(event).flush();\n  };\n\n  private stopPlaylist(track: HMSLocalTrack) {\n    if (track.source === 'audioplaylist') {\n      this.playlistManager.stop(HMSPlaylistType.audio);\n    } else if (track.source === 'videoplaylist') {\n      this.playlistManager.stop(HMSPlaylistType.video);\n    }\n  }\n}\n"]}