UNPKG

@100mslive/hms-video-store

Version:

@100mslive Core SDK which abstracts the complexities of webRTC while providing a reactive store for data management with a unidirectional data flow

227 lines (226 loc) • 12.7 kB
import { HMSNotifications } from './HMSNotifications'; import { Diagnostics } from '../diagnostics'; import { HMSSessionFeedback } from '../end-call-feedback'; import { IHMSActions } from '../IHMSActions'; import { IHMSStore } from '../IHMSStore'; import { HMSAudioPlugin, HMSChangeMultiTrackStateRequest as SDKHMSChangeMultiTrackStateRequest, HMSChangeTrackStateRequest as SDKHMSChangeTrackStateRequest, HMSException as SDKHMSException, HMSLocalAudioTrack as SDKHMSLocalAudioTrack, HMSLocalTrack as SDKHMSLocalTrack, HMSLogLevel, HMSMediaStreamPlugin, HMSPluginSupportResult, HMSScreenShareConfig, HMSTrack as SDKHMSTrack, HMSVideoPlugin } from '../internal'; import * as sdkTypes from '../internal'; import { MessageNotification } from '../notification-manager'; import { HMSChangeMultiTrackStateParams, HMSGenericTypes, HMSMessage, HMSPeer, HMSPeerListIteratorOptions, HMSRoleName, HMSTrackID, HMSTrackSource, IHMSPlaylistActions, IHMSSessionStoreActions } from '../schema'; import { HMSSdk } from '../sdk'; import { HMSRoleChangeRequest } from '../selectors'; import { FindPeerByNameRequestParams } from '../signal/interfaces'; import { HMSStats } from '../webrtc-stats'; /** * This class implements the IHMSActions interface for 100ms SDK. It connects with SDK * and takes control of data management by letting every action pass through it. The * passed in store is ensured to be the single source of truth reflecting current * room related data at any point in time. * * @privateRemarks * Things to keep in mind while updating store - * 1. Treat setState as an atomic operation, if an action results in multiple changes, * the changes should all happen within single setState function. * 2. While updating the state it's very important to not update the reference if * something is unchanged. Copy data in same reference object don't assign new * object. * 3. Mental Model(1) - Actions from backend -> Listeners of this class -> update store -> views update themselves * eg. for this - peer added, remote muted etc. * 4. Mental Model(2) - Actions from local -> View calls actions -> update store -> views update themselves * eg. local track enabled, join, leave etc. * 5. State is immutable, a new copy with new references is created when there is a change, * if you try to modify state outside of setState, there'll be an error. */ export declare class HMSSDKActions<T extends HMSGenericTypes = { sessionStore: Record<string, any>; }> implements IHMSActions<T> { private readonly sdk; private readonly store; private isRoomJoinCalled; private hmsNotifications; private ignoredMessageTypes; private actionBatcher; audioPlaylist: IHMSPlaylistActions; videoPlaylist: IHMSPlaylistActions; sessionStore: IHMSSessionStoreActions<T['sessionStore']>; private beamSpeakerLabelsLogger?; constructor(store: IHMSStore<T>, sdk: HMSSdk, notificationManager: HMSNotifications<T>); submitSessionFeedback(feedback: HMSSessionFeedback, eventEndpoint?: string): Promise<void>; getLocalTrack(trackID: string): SDKHMSLocalTrack | undefined; get interactivityCenter(): import("../session-store/interactivity-center").InteractivityCenter; setPlaylistSettings(settings: sdkTypes.HMSPlaylistSettings): void; refreshDevices(): Promise<void>; unblockAudio(): Promise<void>; setVolume(value: number, trackId?: HMSTrackID): Promise<void>; setAudioOutputDevice(deviceId: string): Promise<void>; setPreferredLayer(trackId: string, layer: sdkTypes.HMSPreferredSimulcastLayer): Promise<void>; getNativeTrackById(trackId: string): MediaStreamTrack | undefined; getTrackById(trackId: string): SDKHMSTrack | SDKHMSLocalAudioTrack | undefined; getAuthTokenByRoomCode(tokenRequest: sdkTypes.TokenRequest, tokenRequestOptions?: sdkTypes.TokenRequestOptions): Promise<string>; preview(config: sdkTypes.HMSPreviewConfig): Promise<void>; cancelMidCallPreview(): Promise<void>; join(config: sdkTypes.HMSConfig): Promise<void>; leave(): Promise<void>; setScreenShareEnabled(enabled: boolean, config?: HMSScreenShareConfig): Promise<void>; addTrack(track: MediaStreamTrack, type?: HMSTrackSource): Promise<void>; removeTrack(trackId: string): Promise<void>; setLocalAudioEnabled(enabled: boolean): Promise<void>; setLocalVideoEnabled(enabled: boolean): Promise<void>; setEnabledTrack(trackID: string, enabled: boolean): Promise<void>; autoSelectAudioOutput(delay?: number): Promise<void>; setAudioSettings(settings: Partial<sdkTypes.HMSAudioTrackSettings>): Promise<void>; setVideoSettings(settings: Partial<sdkTypes.HMSVideoTrackSettings>): Promise<void>; switchCamera(): Promise<void>; sendMessage(message: string): void; sendBroadcastMessage(message: string, type?: string): Promise<void>; sendGroupMessage(message: string, roles: string[], type?: string): Promise<void>; sendDirectMessage(message: string, peerID: string, type?: string): Promise<void>; private updateMessageInStore; setMessageRead(readStatus: boolean, messageId?: string): void; attachVideo(trackID: string, videoElement: HTMLVideoElement): Promise<void>; detachVideo(trackID: string, videoElement: HTMLVideoElement): Promise<void>; addPluginToVideoTrack(plugin: HMSVideoPlugin, pluginFrameRate?: number): Promise<void>; addPluginsToVideoStream(plugins: HMSMediaStreamPlugin[]): Promise<void>; removePluginsFromVideoStream(plugins: HMSMediaStreamPlugin[]): Promise<void>; addPluginToAudioTrack(plugin: HMSAudioPlugin): Promise<void>; validateVideoPluginSupport(plugin: HMSVideoPlugin): HMSPluginSupportResult; validateAudioPluginSupport(plugin: HMSAudioPlugin): HMSPluginSupportResult; removePluginFromVideoTrack(plugin: HMSVideoPlugin): Promise<void>; removePluginFromAudioTrack(plugin: HMSAudioPlugin): Promise<void>; changeRole(forPeerId: string, toRole: string, force?: boolean): Promise<void>; changeRoleOfPeer(forPeerId: string, toRole: string, force?: boolean): Promise<void>; changeRoleOfPeersWithRoles(roles: HMSRoleName[], toRole: HMSRoleName): Promise<void>; acceptChangeRole(request: HMSRoleChangeRequest): Promise<void>; raiseLocalPeerHand(): Promise<void>; lowerLocalPeerHand(): Promise<void>; raiseRemotePeerHand(peerId: string): Promise<void>; lowerRemotePeerHand(peerId: string): Promise<void>; getPeer(peerId: string): Promise<HMSPeer | undefined>; findPeerByName(options: FindPeerByNameRequestParams): Promise<{ offset: number; eof: boolean | undefined; peers: HMSPeer[]; }>; getPeerListIterator(options?: HMSPeerListIteratorOptions): { hasNext: () => boolean; next: () => Promise<HMSPeer[]>; findPeers: () => Promise<HMSPeer[]>; getTotal: () => number; }; initAppData(appData: Record<string, any>): void; setAppData(key: string, value: any, merge?: boolean): void; /** * @privateRemarks * there is no corresponding sdk method for rejecting change role but as the store also maintains the full * state of current pending requests, this method allows it to clean up when the request is rejected */ rejectChangeRole(request: HMSRoleChangeRequest): void; endRoom(lock: boolean, reason: string): Promise<void>; removePeer(peerID: string, reason: string): Promise<void>; startRTMPOrRecording(params: sdkTypes.RTMPRecordingConfig): Promise<void>; stopRTMPAndRecording(): Promise<void>; startHLSStreaming(params?: sdkTypes.HLSConfig): Promise<void>; stopHLSStreaming(params?: sdkTypes.StopHLSConfig): Promise<void>; startTranscription(params: sdkTypes.TranscriptionConfig): Promise<void>; stopTranscription(params: sdkTypes.TranscriptionConfig): Promise<void>; sendHLSTimedMetadata(metadataList: sdkTypes.HLSTimedMetadata[]): Promise<void>; changeName(name: string): Promise<void>; changeMetadata(metadata: string | any): Promise<void>; setSessionMetadata(metadata: any): Promise<void>; populateSessionMetadata(): Promise<void>; setRemoteTrackEnabled(trackID: HMSTrackID | HMSTrackID[], enabled: boolean): Promise<void>; setRemoteTracksEnabled(params: HMSChangeMultiTrackStateParams): Promise<void>; setLogLevel(level: HMSLogLevel): void; setFrameworkInfo(frameworkInfo: sdkTypes.HMSFrameworkInfo): void; ignoreMessageTypes(msgTypes: string[], replace?: boolean): void; enableBeamSpeakerLabelsLogging(): Promise<void>; initDiagnostics(): Diagnostics; private resetState; getDebugInfo(): import("../schema").DebugInfo | undefined; private sdkJoinWithListeners; private onSFUMigration; private onRemovedFromRoom; private onDeviceChange; private sdkPreviewWithListeners; private onNetworkQuality; private onSessionStoreUpdate; private onPollsUpdate; private onWhiteboardUpdate; private startScreenShare; private stopScreenShare; private attachVideoInternal; /** * This is a very important function as it's responsible for maintaining the source of * truth with maximum efficiency. The efficiency comes from the fact that the only * those portions of the store are updated which have actually changed. * While making a change in this function don't use functions like map, reduce etc. * which return a new copy of the data. Use Object.assign etc. to ensure that if the data * doesn't change reference is also not changed. * The UI and selectors rely on the fact that the store is immutable that is if there is * any change and only if there is a change, they'll get a new copy of the data they're * interested in with a new reference. * @protected */ protected syncRoomState(action: string): void; protected onPreview(sdkRoom: sdkTypes.HMSRoom): void; protected onJoin(sdkRoom: sdkTypes.HMSRoom): void; protected onRoomUpdate(type: sdkTypes.HMSRoomUpdate, room: sdkTypes.HMSRoom): void; protected onPeerUpdate(type: sdkTypes.HMSPeerUpdate, sdkPeer: sdkTypes.HMSPeer | sdkTypes.HMSPeer[]): void; protected onTrackUpdate(type: sdkTypes.HMSTrackUpdate, track: SDKHMSTrack, peer: sdkTypes.HMSPeer): void; protected onMessageReceived(message: MessageNotification): void; protected putMessageInStore(hmsMessage: HMSMessage): void; protected onAudioLevelUpdate(sdkSpeakers: sdkTypes.HMSSpeaker[]): void; /** * The connection quality update is sent for all peers(one needs to know of) every time. */ protected onConnectionQualityUpdate(newQualities: sdkTypes.HMSConnectionQuality[]): void; protected onChangeTrackStateRequest(request: SDKHMSChangeTrackStateRequest): void; protected onChangeMultiTrackStateRequest(request: SDKHMSChangeMultiTrackStateRequest): void; protected onReconnected(): void; protected onReconnecting(sdkError: SDKHMSException): void; protected onError(sdkException: SDKHMSException): void; private handleTrackRemove; private setEnabledSDKTrack; private setSDKLocalVideoTrackSettings; private setSDKLocalAudioTrackSettings; private getMediaSettings; private getPreviewFields; private setTrackVolume; /** * Tells if the trackID is for local peer and video unmute is in process * @private */ private localAndVideoUnmuting; private logPossibleInconsistency; private addRemoveVideoPlugin; private addRemoveMediaStreamVideoPlugins; private addRemoveAudioPlugin; /** * convert new role change requests to store format and save. * keep only one request at a time in store till we figure out how to handle multiple requests at the same time */ private onRoleChangeRequest; private removeRoleChangeRequest; private onRoleUpdate; private getStoreLocalTrackIDfromSDKTrack; private setProgress; private syncPlaylistState; private sendPeerUpdateNotification; private updateMidCallPreviewRoomState; private setSessionStoreValueLocally; private getSDKHMSPeer; /** * setState is separate so any future changes to how state change can be done from one place. * @param fn * @param name */ private setState; /** * @internal * This will be used by beam to check if the recording should continue, it will pass __hms.stats * It will poll at a fixed interval and start an exit timer if the method fails twice consecutively * The exit timer is stopped if the method returns true before that * @param hmsStats */ hasActiveElements(hmsStats: HMSStats): boolean; }