@techsee/techsee-media-service 999.15.13-alpha → 999.15.14-alpha

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/MediaSession/SessionOpentok.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,QAAQ,EAAC,MAAM,yBAAyB,CAAC;AAEjD,OAAO,EACH,aAAa,EACb,sBAAsB,EAAE,yBAAyB,EACjD,kBAAkB,EAClB,gBAAgB,EACnB,MAAM,mBAAmB,CAAC;AAE3B,OAAO,EAAC,iBAAiB,EAAoB,MAAM,mBAAmB,CAAC;AAEvE,OAAO,EAAC,iBAAiB,EAAE,gBAAgB,EAAgC,MAAM,oBAAoB,CAAC;AAKtG,OAAO,CAAC,MAAM,CAAC;IACX,UAAU,MAAM;QACZ,EAAE,EAAE,GAAG,CAAC;KACX;CACJ;AAED,UAAU,YAAY;IAClB,YAAY,EAAE,MAAM,CAAC;CACxB;AAED,aAAK,WAAW,GAAG,GAAG,CAAA;AAEtB,aAAK,YAAY,GAAG,GAAG,CAAA;AA+BvB,UAAU,cAAc;IACpB,WAAW,EAAE,GAAG,CAAC;IACjB,WAAW,EAAE,GAAG,CAAC;CACpB;AAED,UAAU,gBAAiB,SAAQ,iBAAiB;IAChD,WAAW,EAAE,QAAQ,CAAC,cAAc,CAAC,CAAC;IACtC,UAAU,EAAE,YAAY,CAAC;IACzB,SAAS,EAAE,QAAQ,CAAC,WAAW,CAAC,CAAC;IACjC,UAAU,EAAE,QAAQ,CAAC,YAAY,CAAC,CAAC;CACtC;AAGD,qBAAa,cAAe,SAAQ,gBAAgB,CAAC,gBAAgB,CAAE,YAAW,aAAa;IAC3F,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAM;IACnC,OAAO,CAAC,iBAAiB,CAAa;IACtC,OAAO,CAAC,QAAQ,CAA8B;IAE9C,IAAI,EAAE,IAAI,MAAM,CAEf;IAED,OAAO,KAAK,SAAS,GAEpB;gBAEW,aAAa,EAAE,kBAAkB,GAAG,yBAAyB,EAAE,aAAa,EAAE,sBAAsB;IAiBhH,iBAAiB,IAAI,IAAI;IAMzB,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAkDxB,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAwB3B,sBAAsB,CAAC,UAAU,EAAE,iBAAiB,GAAG,OAAO,CAAC,IAAI,CAAC;IAYpE,oBAAoB,CAAC,UAAU,EAAE,iBAAiB,EAAE,WAAW,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC;IAK5F,mBAAmB,CAAC,WAAW,EAAE,QAAQ,CAAC,WAAW,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;IAItE,mBAAmB,CAAC,UAAU,EAAE,gBAAgB,GAAG,OAAO,CAAC,gBAAgB,CAAC;IAuB5E,OAAO,CAAC,wBAAwB;IAgFhC,OAAO,CAAC,0BAA0B;IAalC,OAAO,CAAC,oBAAoB;IA2B5B,OAAO,CAAC,sBAAsB;IAuB9B,OAAO,CAAC,qBAAqB;IAU7B,OAAO,CAAC,yBAAyB;IAyBjC,OAAO,CAAC,oBAAoB;IAmC5B,OAAO,CAAC,gCAAgC;IAexC,OAAO,CAAC,qBAAqB;IAmE7B,OAAO,CAAC,iCAAiC;IAsBzC,OAAO,CAAC,kBAAkB;CAK7B","file":"SessionOpentok.d.ts","sourcesContent":["import {Nullable} from '@techsee/techsee-common';\n\nimport {\n IMediaSession,\n ISessionStreamsManager, MediaSessionConfiguration,\n MediaSessionParams,\n RemoteTrackStats\n} from '../MediaContracts';\nimport cloneDeep from 'lodash/cloneDeep';\nimport {SessionClientRole, SessionClientType} from '../MediaConstants';\nimport {throwableGuard} from '@techsee/techsee-common/lib/core/guards';\nimport {IMediaSessionPeer, MediaSessionBase, recordingEvents, streamEvents} from './MediaSessionBase';\nimport {getMediaTracer} from '../MediaUtils/MediaTracer';\n\nconst trace = getMediaTracer('OpentokSession');\n\ndeclare global {\n interface Window {\n OT: any;\n }\n}\n\ninterface OTConnection {\n connectionId: string;\n}\n\ntype OTPublisher = any\n\ntype OTSubscriber = any\n\ninterface IOTSession {\n\n sessionId: string;\n\n connection: Nullable<OTConnection>;\n\n isConnected(): boolean;\n\n connect(token: string, cb: any): void;\n\n disconnect(): void;\n\n publish(publisher: OTPublisher, cb: any): void;\n\n unpublish(publisher: OTPublisher): void;\n\n subscribe(stream: any, container: any, uiProps: any, doneCb: any): OTSubscriber;\n\n unsubscribe(subscriber: OTSubscriber): void;\n\n getSubscribersForStream(stream: any): OTSubscriber[];\n\n off(): void;\n\n on(param: string, cb: any): void;\n\n once(param: string, cb: any): void;\n}\n\ninterface OTStreamSource {\n videoSource: any;\n audioSource: any;\n}\n\ninterface OTPeerConnection extends IMediaSessionPeer {\n localStream: Nullable<OTStreamSource>;\n connection: OTConnection;\n publisher: Nullable<OTPublisher>;\n subscriber: Nullable<OTSubscriber>;\n}\n\n//Currently this version supports subscribing only. Publishing will be implemented as needed.\nexport class OpentokSession extends MediaSessionBase<OTPeerConnection> implements IMediaSession {\n private readonly _credentials: any;\n private _lastStreamEvents: any[] = [];\n private _session: Nullable<IOTSession> = null;\n\n get id(): string {\n return this._session && this._session.sessionId ? this._session.sessionId : '';\n }\n\n private get ownPeerId(): string {\n return this._session && this._session.connection ? this._session.connection.connectionId : '';\n }\n\n constructor(sessionParams: MediaSessionParams & MediaSessionConfiguration, streamFactory: ISessionStreamsManager) {\n super(sessionParams, streamFactory);\n this._credentials = sessionParams.credentials;\n\n this.connect = this.connect.bind(this);\n this.disconnect = this.disconnect.bind(this);\n this.onMediaStreamDestroyed = this.onMediaStreamDestroyed.bind(this);\n this.onMediaStreamRenewed = this.onMediaStreamRenewed.bind(this);\n\n this.createStreamForPublishing = this.createStreamForPublishing.bind(this);\n this.createMediaPublisher = this.createMediaPublisher.bind(this);\n this.connectionCreatedHandler = this.connectionCreatedHandler.bind(this);\n this.connectionDestroyedHandler = this.connectionDestroyedHandler.bind(this);\n this.streamCreatedHandler = this.streamCreatedHandler.bind(this);\n this.streamDestroyedHandler = this.streamDestroyedHandler.bind(this);\n }\n\n sessionDisconnect(): void {\n if (this._session) {\n return this._session.disconnect();\n }\n }\n\n connect(): Promise<void> {\n trace.info('Connect to session', this._credentials);\n\n if (this._session) {\n trace.error('Session already exists');\n\n return Promise.reject('Cannot connect to session while another session is active');\n }\n\n return new Promise((resolve, reject) => {\n const handleError = (error: any): void => {\n this._session && this._session!.off();\n this._session = null;\n trace.error('handleConnect error:', error);\n reject(error);\n };\n\n const {apiKey, sessionId} = this._sessionParams.credentials;\n\n this._session = (window as any).OTSESSION = window.OT.initSession(apiKey, sessionId);\n this._lastStreamEvents = [];\n\n this._session!.on('connectionCreated', this.connectionCreatedHandler);\n this._session!.on('connectionDestroyed', this.connectionDestroyedHandler);\n this._session!.on('streamCreated', this.streamCreatedHandler);\n this._session!.on('streamDestroyed', this.streamDestroyedHandler);\n this._session!.on('archiveStarted', (event: any) => {\n trace.info('archiveStarted event', event);\n this.emitEvent(recordingEvents.RECORD_STARTED, event);\n });\n\n this._session!.on('archiveStopped', (event: any) => {\n trace.info('archiveStopped event', event);\n this.emitEvent(recordingEvents.RECORD_STOPPED, event);\n });\n\n const connectHandler = (error: any): void => {\n if (error) {\n handleError(error);\n\n return;\n }\n\n resolve();\n };\n\n this._session!.connect(this._credentials.token, connectHandler);\n });\n }\n\n disconnect(): Promise<void> {\n return new Promise((resolve) => {\n trace.info('Disconnecting from session');\n const currentSession = this._session;\n\n this._session = null;\n\n this._peerConnections.forEach((peerConnection) => {\n this.destroyPeerConnection(peerConnection);\n });\n\n if (!currentSession) {\n trace.info('No active session - resolving');\n resolve();\n\n return;\n }\n currentSession.off();\n currentSession.disconnect();\n this._lastStreamEvents = [];\n resolve();\n });\n }\n\n onMediaStreamDestroyed(clientRole: SessionClientRole): Promise<void> {\n const promises: Promise<void>[] = [];\n\n this._peerConnections.forEach((peerConnection) => {\n if (peerConnection.peerRole === clientRole) {\n promises.push(this.destroyPublisherOnPeerConnection(peerConnection));\n }\n });\n\n return Promise.all(promises).then(() => undefined);\n }\n\n onMediaStreamRenewed(clientRole: SessionClientRole, mediaStream: MediaStream): Promise<void> {\n //TODO - Alex: need to implement adding new tracks to peer connection and forcing negotiation (in OT API)\n return Promise.resolve();\n }\n\n replaceStreamTracks(mediaStream: Nullable<MediaStream>): Promise<void> {\n return Promise.reject(new Error('Not implemented'));\n }\n\n getRemoteTrackStats(mediaTrack: MediaStreamTrack): Promise<RemoteTrackStats> {\n return new Promise((resolve: any, reject: any) => {\n const peerConnectionOfTrack = this.getPeerConnectionByMediaTrack(mediaTrack);\n\n if (!peerConnectionOfTrack || !peerConnectionOfTrack.subscriber) {\n reject(new Error('Cannot find peer or subscriber for getting stats'));\n }\n\n //https://tokbox.com/developer/sdks/js/reference/Subscriber.html#getStats\n peerConnectionOfTrack!.subscriber.getStats((error: any, stats: any) => {\n if (error) {\n trace.warn('Error getting stats', error);\n resolve({trackId: mediaTrack.id, trackStats: {}});\n\n return;\n }\n resolve({trackId: mediaTrack.id, trackStats: stats});\n });\n });\n }\n\n //#region OpenTok Events Handlers\n\n private connectionCreatedHandler(event: any): void {\n trace.info('connectionCreatedHandler', event);\n const {connection} = event;\n\n if (!this.sessionExistsGuard(false) || !connection) {\n return;\n }\n\n const destinationRole = JSON.parse(connection.data).clientRole;\n\n this.createStreamForPublishing(destinationRole)\n .then((streams: OTStreamSource) => {\n const peerConnection: OTPeerConnection = {\n peerId: connection.connectionId,\n peerRole: destinationRole,\n peerType: this._sessionParams.clientType === SessionClientType.INITIATOR\n ? SessionClientType.GUEST : SessionClientType.INITIATOR,\n connection: connection,\n publisher: null,\n subscriber: null,\n remoteMediaTracks: [],\n localStream: streams,\n connectionTimoutPrt: null\n };\n\n if (connection.connectionId !== this.ownPeerId || (!streams.videoSource && !streams.audioSource)) {\n trace.info('Peer connection without publisher was created', peerConnection);\n\n return peerConnection;\n }\n\n return this.createMediaPublisher(streams)\n .then((publisher: OTPublisher) => {\n peerConnection.publisher = publisher;\n trace.info('Peer connection with publisher was created', peerConnection);\n\n return peerConnection;\n });\n })\n .then((peerConnection: OTPeerConnection) => {\n this._peerConnections.set(peerConnection.peerId, peerConnection);\n\n if (connection.connectionId === this.ownPeerId) {\n trace.info('Before subscribe the event streams');\n\n /*\n When publisher connect after others participants,\n make sure the publisher will not loose their stream to subscribe\n */\n return this._lastStreamEvents.reduce((promiseChain: any, streamEvent: any) => promiseChain\n .then(() => this.streamCreatedHandler(streamEvent)), Promise.resolve())\n .then(() => {\n if (peerConnection.publisher) {\n return new Promise<void>((resolve, reject) => {\n trace.info('Starting publish to peerConnection.publisher');\n this._session!.publish(peerConnection.publisher, (error: any) => {\n if (error) {\n trace.error(`Publish to peerConnection error ${error}`);\n\n return reject(error);\n }\n\n this.emitEvent(streamEvents.PUBLISH_STREAM);\n trace.info('Publish to peerConnection success');\n\n return resolve();\n });\n });\n }\n\n return Promise.resolve();\n });\n }\n })\n .catch((error: any) => {\n //Need to handle fail cases during reliability\n trace.error(`Error handling new peer connection: ${error}`);\n });\n }\n\n private connectionDestroyedHandler(event: any): void {\n trace.info('connectionDestroyedHandler', event);\n const {connection} = event;\n\n if (!this.sessionExistsGuard(false) || !connection) {\n return;\n }\n\n if (this._peerConnections.has(connection.connectionId)) {\n this.destroyPeerConnection(this._peerConnections.get(connection.connectionId)!);\n }\n }\n\n private streamCreatedHandler(event: any): void {\n trace.info('streamCreatedHandler', event.stream);\n const {stream} = event;\n const {connection} = stream || {connection: null};\n\n if (!this.sessionExistsGuard(false) || !stream || connection.connectionId === this.ownPeerId) {\n return;\n }\n\n if (!this._peerConnections.has(connection.connectionId)) {\n trace.warn('Unexpected case, connection should exist on this stage');\n this._lastStreamEvents.push(event);\n\n return;\n }\n\n const peerConnection = this._peerConnections.get(connection.connectionId)!;\n\n trace.info('Subscribing the stream');\n\n this.createMediaSubscriber(stream).then((subscriber: OTSubscriber) => {\n peerConnection.subscriber = subscriber;\n\n this.emitEvent(streamEvents.SUBSCRIBE_STREAM);\n });\n }\n\n private streamDestroyedHandler(event: any): void {\n trace.info('streamDestroyedHandler', event);\n const {stream} = event;\n\n if (!this.sessionExistsGuard(false) || !stream) {\n return;\n }\n\n const peerConnection = this._peerConnections.get(stream.connection.connectionId);\n\n if (!peerConnection) {\n trace.warn('Peer connection for remote stream not found');\n\n return;\n }\n\n this.destroySubscriberOnPeerConnection(peerConnection).catch(() => undefined);\n }\n\n //#endregion\n\n //#region PeerConnection\n\n private destroyPeerConnection(peerConnection: OTPeerConnection): void {\n this._peerConnections.delete(peerConnection.peerId);\n this.destroyPublisherOnPeerConnection(peerConnection).catch(() => undefined);\n this.destroySubscriberOnPeerConnection(peerConnection).catch(() => undefined);\n }\n\n //#endregion\n\n //#region Publisher\n\n private createStreamForPublishing(destinationRole: SessionClientRole): Promise<OTStreamSource> {\n trace.info('createStreamForPublishing');\n\n return this._sessionStreamsManager.getMediaStreamForRole(destinationRole)\n .then((mediaStream: Nullable<MediaStream>) => {\n\n const stream: OTStreamSource = {videoSource: null, audioSource: null};\n\n if (mediaStream) {\n trace.info('Media stream found for publishing', mediaStream);\n mediaStream.getTracks().forEach((track) => {\n if (track.kind === 'video') {\n stream.videoSource = track;\n } else if (track.kind === 'audio') {\n stream.audioSource = track;\n }\n });\n } else if (this._sessionParams.clientRole === SessionClientRole.USER) {\n trace.warn('No local media was found for publishing to destinationRole:', destinationRole);\n }\n\n return stream;\n });\n }\n\n private createMediaPublisher(stream: OTStreamSource): Promise<OTPublisher> {\n const otParams = {\n videoSource: stream.videoSource ? stream.videoSource : false,\n audioSource: stream.audioSource ? stream.audioSource : false,\n publishAudio: !!stream.audioSource,\n publishVideo: !!stream.videoSource,\n showControls: false\n };\n\n return new Promise((resolve, reject) => {\n const otPublisher = window.OT.initPublisher(undefined, otParams, (error: any) => {\n if (error) {\n reject(error);\n\n return;\n }\n otPublisher.on('streamDestroyed', (event: any) => {\n trace.info('Publisher stream destroyed', event);\n //We preventing the default, in order to prevent stop the stream by OT.\n //We managing streams by ourselves and if we allow OT to close the stream, it cannot be reused.\n event.preventDefault();\n });\n otPublisher.on('videoElementCreated', (event: any) => {\n document.getElementById(otPublisher.id)!.style.display = 'none';\n event.element.muted = true;\n });\n otPublisher.on('streamCreated', (event: any) => {\n trace.info('publisher stream created @@@@@@@@@@@@@@@', event);\n trace.info('publisher stream created', otPublisher.stream.hasAudio);\n });\n resolve(otPublisher);\n });\n });\n }\n\n private destroyPublisherOnPeerConnection(peerConnection: OTPeerConnection): Promise<void> {\n if (this.sessionExistsGuard(false) && peerConnection.publisher) {\n this._session!.unpublish(peerConnection.publisher);\n }\n\n peerConnection.publisher = null;\n peerConnection.localStream = null;\n\n return Promise.resolve();\n }\n\n //#endregion\n\n //#region Subscriber\n\n private createMediaSubscriber(remoteStream: any): Promise<OTSubscriber> {\n return new Promise((resolve: any, reject: any) => {\n if (!this.sessionExistsGuard(false)) {\n reject('Session not exists');\n\n return;\n }\n\n const subscriber: OTSubscriber = this._session!.subscribe(remoteStream, null, null, (err: any) => {\n if (err) {\n trace.warn('Error creating subscriber', err);\n reject(err);\n\n return;\n }\n\n subscriber.on('videoElementCreated', (event: any) => {\n document.getElementById(subscriber.id)!.style.display = 'none';\n\n // const allNodes: any = document.querySelectorAll('.OT_video-element').length;\n //\n // for (let i in allNodes) {\n // const x = document.querySelector('.OT_video-element');\n //\n // x.remove();\n // }\n\n const {element} = event;\n\n element.muted = true;\n\n // if (remoteStream.hasAudio) {\n // trace.info('dddddddddddddd');\n // element.playsInline = true;\n // element.play()\n // .then(function () {\n // trace.info('playing opentok')\n // });\n // }\n\n const peerConnection = this._peerConnections.get(remoteStream.connection.connectionId)!;\n const otMediaStream: MediaStream = cloneDeep(element.srcObject);\n\n element.remove();\n console.log(element);\n\n peerConnection.subscriber = subscriber;\n\n if (!otMediaStream) {\n trace.warn('MediaStream not found in OT video element');\n\n return;\n }\n\n trace.info('Registering remote media tracks', peerConnection.subscriber, otMediaStream);\n otMediaStream.getTracks().forEach((mediaTrack: MediaStreamTrack) => {\n this.addRemoteTrackToPeer(peerConnection, cloneDeep(mediaTrack));\n });\n\n this.registerPeersRemoteTracks(peerConnection);\n });\n\n resolve(subscriber);\n });\n });\n }\n\n private destroySubscriberOnPeerConnection(peerConnection: OTPeerConnection): Promise<void> {\n if (this.sessionExistsGuard(false) && peerConnection.subscriber) {\n this._session!.unsubscribe(peerConnection.subscriber);\n }\n\n peerConnection.subscriber = null;\n\n return Promise.resolve();\n\n /**\n REMARK- opentok provide the same media track id for all participates.\n when we unregister the media track we check by the id which is the same for all.\n **/\n // return this.unregisterPeersRemoteMediaTracks(peerConnection)\n // .catch(() => trace.warn('Error removing remote streams from peerConnection'))\n // .then(() => {\n // peerConnection.subscriber = null;\n // });\n }\n\n //#endregion\n\n private sessionExistsGuard(shouldThrow = true): boolean {\n const connected = !!(this._session && this._session.connection && this._session.connection.connectionId);\n\n return throwableGuard(connected, 'There no OpenTok session exists', shouldThrow);\n }\n}\n"]}
1
+ {"version":3,"sources":["../src/MediaSession/SessionOpentok.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,QAAQ,EAAC,MAAM,yBAAyB,CAAC;AAEjD,OAAO,EACH,aAAa,EACb,sBAAsB,EAAE,yBAAyB,EACjD,kBAAkB,EAClB,gBAAgB,EACnB,MAAM,mBAAmB,CAAC;AAE3B,OAAO,EAAC,iBAAiB,EAAoB,MAAM,mBAAmB,CAAC;AAEvE,OAAO,EAAC,iBAAiB,EAAE,gBAAgB,EAAgC,MAAM,oBAAoB,CAAC;AAKtG,OAAO,CAAC,MAAM,CAAC;IACX,UAAU,MAAM;QACZ,EAAE,EAAE,GAAG,CAAC;KACX;CACJ;AAED,UAAU,YAAY;IAClB,YAAY,EAAE,MAAM,CAAC;CACxB;AAED,aAAK,WAAW,GAAG,GAAG,CAAA;AAEtB,aAAK,YAAY,GAAG,GAAG,CAAA;AA+BvB,UAAU,cAAc;IACpB,WAAW,EAAE,GAAG,CAAC;IACjB,WAAW,EAAE,GAAG,CAAC;CACpB;AAED,UAAU,gBAAiB,SAAQ,iBAAiB;IAChD,WAAW,EAAE,QAAQ,CAAC,cAAc,CAAC,CAAC;IACtC,UAAU,EAAE,YAAY,CAAC;IACzB,SAAS,EAAE,QAAQ,CAAC,WAAW,CAAC,CAAC;IACjC,UAAU,EAAE,QAAQ,CAAC,YAAY,CAAC,CAAC;CACtC;AAGD,qBAAa,cAAe,SAAQ,gBAAgB,CAAC,gBAAgB,CAAE,YAAW,aAAa;IAC3F,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAM;IACnC,OAAO,CAAC,iBAAiB,CAAa;IACtC,OAAO,CAAC,QAAQ,CAA8B;IAE9C,IAAI,EAAE,IAAI,MAAM,CAEf;IAED,OAAO,KAAK,SAAS,GAEpB;gBAEW,aAAa,EAAE,kBAAkB,GAAG,yBAAyB,EAAE,aAAa,EAAE,sBAAsB;IAiBhH,iBAAiB,IAAI,IAAI;IAMzB,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAkDxB,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAwB3B,sBAAsB,CAAC,UAAU,EAAE,iBAAiB,GAAG,OAAO,CAAC,IAAI,CAAC;IAYpE,oBAAoB,CAAC,UAAU,EAAE,iBAAiB,EAAE,WAAW,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC;IAK5F,mBAAmB,CAAC,WAAW,EAAE,QAAQ,CAAC,WAAW,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;IAItE,mBAAmB,CAAC,UAAU,EAAE,gBAAgB,GAAG,OAAO,CAAC,gBAAgB,CAAC;IAuB5E,OAAO,CAAC,wBAAwB;IAgFhC,OAAO,CAAC,0BAA0B;IAalC,OAAO,CAAC,oBAAoB;IA2B5B,OAAO,CAAC,sBAAsB;IAuB9B,OAAO,CAAC,qBAAqB;IAU7B,OAAO,CAAC,yBAAyB;IAyBjC,OAAO,CAAC,oBAAoB;IAmC5B,OAAO,CAAC,gCAAgC;IAexC,OAAO,CAAC,qBAAqB;IAiE7B,OAAO,CAAC,iCAAiC;IAsBzC,OAAO,CAAC,kBAAkB;CAK7B","file":"SessionOpentok.d.ts","sourcesContent":["import {Nullable} from '@techsee/techsee-common';\n\nimport {\n IMediaSession,\n ISessionStreamsManager, MediaSessionConfiguration,\n MediaSessionParams,\n RemoteTrackStats\n} from '../MediaContracts';\nimport cloneDeep from 'lodash/cloneDeep';\nimport {SessionClientRole, SessionClientType} from '../MediaConstants';\nimport {throwableGuard} from '@techsee/techsee-common/lib/core/guards';\nimport {IMediaSessionPeer, MediaSessionBase, recordingEvents, streamEvents} from './MediaSessionBase';\nimport {getMediaTracer} from '../MediaUtils/MediaTracer';\n\nconst trace = getMediaTracer('OpentokSession');\n\ndeclare global {\n interface Window {\n OT: any;\n }\n}\n\ninterface OTConnection {\n connectionId: string;\n}\n\ntype OTPublisher = any\n\ntype OTSubscriber = any\n\ninterface IOTSession {\n\n sessionId: string;\n\n connection: Nullable<OTConnection>;\n\n isConnected(): boolean;\n\n connect(token: string, cb: any): void;\n\n disconnect(): void;\n\n publish(publisher: OTPublisher, cb: any): void;\n\n unpublish(publisher: OTPublisher): void;\n\n subscribe(stream: any, container: any, uiProps: any, doneCb: any): OTSubscriber;\n\n unsubscribe(subscriber: OTSubscriber): void;\n\n getSubscribersForStream(stream: any): OTSubscriber[];\n\n off(): void;\n\n on(param: string, cb: any): void;\n\n once(param: string, cb: any): void;\n}\n\ninterface OTStreamSource {\n videoSource: any;\n audioSource: any;\n}\n\ninterface OTPeerConnection extends IMediaSessionPeer {\n localStream: Nullable<OTStreamSource>;\n connection: OTConnection;\n publisher: Nullable<OTPublisher>;\n subscriber: Nullable<OTSubscriber>;\n}\n\n//Currently this version supports subscribing only. Publishing will be implemented as needed.\nexport class OpentokSession extends MediaSessionBase<OTPeerConnection> implements IMediaSession {\n private readonly _credentials: any;\n private _lastStreamEvents: any[] = [];\n private _session: Nullable<IOTSession> = null;\n\n get id(): string {\n return this._session && this._session.sessionId ? this._session.sessionId : '';\n }\n\n private get ownPeerId(): string {\n return this._session && this._session.connection ? this._session.connection.connectionId : '';\n }\n\n constructor(sessionParams: MediaSessionParams & MediaSessionConfiguration, streamFactory: ISessionStreamsManager) {\n super(sessionParams, streamFactory);\n this._credentials = sessionParams.credentials;\n\n this.connect = this.connect.bind(this);\n this.disconnect = this.disconnect.bind(this);\n this.onMediaStreamDestroyed = this.onMediaStreamDestroyed.bind(this);\n this.onMediaStreamRenewed = this.onMediaStreamRenewed.bind(this);\n\n this.createStreamForPublishing = this.createStreamForPublishing.bind(this);\n this.createMediaPublisher = this.createMediaPublisher.bind(this);\n this.connectionCreatedHandler = this.connectionCreatedHandler.bind(this);\n this.connectionDestroyedHandler = this.connectionDestroyedHandler.bind(this);\n this.streamCreatedHandler = this.streamCreatedHandler.bind(this);\n this.streamDestroyedHandler = this.streamDestroyedHandler.bind(this);\n }\n\n sessionDisconnect(): void {\n if (this._session) {\n return this._session.disconnect();\n }\n }\n\n connect(): Promise<void> {\n trace.info('Connect to session', this._credentials);\n\n if (this._session) {\n trace.error('Session already exists');\n\n return Promise.reject('Cannot connect to session while another session is active');\n }\n\n return new Promise((resolve, reject) => {\n const handleError = (error: any): void => {\n this._session && this._session!.off();\n this._session = null;\n trace.error('handleConnect error:', error);\n reject(error);\n };\n\n const {apiKey, sessionId} = this._sessionParams.credentials;\n\n this._session = (window as any).OTSESSION = window.OT.initSession(apiKey, sessionId);\n this._lastStreamEvents = [];\n\n this._session!.on('connectionCreated', this.connectionCreatedHandler);\n this._session!.on('connectionDestroyed', this.connectionDestroyedHandler);\n this._session!.on('streamCreated', this.streamCreatedHandler);\n this._session!.on('streamDestroyed', this.streamDestroyedHandler);\n this._session!.on('archiveStarted', (event: any) => {\n trace.info('archiveStarted event', event);\n this.emitEvent(recordingEvents.RECORD_STARTED, event);\n });\n\n this._session!.on('archiveStopped', (event: any) => {\n trace.info('archiveStopped event', event);\n this.emitEvent(recordingEvents.RECORD_STOPPED, event);\n });\n\n const connectHandler = (error: any): void => {\n if (error) {\n handleError(error);\n\n return;\n }\n\n resolve();\n };\n\n this._session!.connect(this._credentials.token, connectHandler);\n });\n }\n\n disconnect(): Promise<void> {\n return new Promise((resolve) => {\n trace.info('Disconnecting from session');\n const currentSession = this._session;\n\n this._session = null;\n\n this._peerConnections.forEach((peerConnection) => {\n this.destroyPeerConnection(peerConnection);\n });\n\n if (!currentSession) {\n trace.info('No active session - resolving');\n resolve();\n\n return;\n }\n currentSession.off();\n currentSession.disconnect();\n this._lastStreamEvents = [];\n resolve();\n });\n }\n\n onMediaStreamDestroyed(clientRole: SessionClientRole): Promise<void> {\n const promises: Promise<void>[] = [];\n\n this._peerConnections.forEach((peerConnection) => {\n if (peerConnection.peerRole === clientRole) {\n promises.push(this.destroyPublisherOnPeerConnection(peerConnection));\n }\n });\n\n return Promise.all(promises).then(() => undefined);\n }\n\n onMediaStreamRenewed(clientRole: SessionClientRole, mediaStream: MediaStream): Promise<void> {\n //TODO - Alex: need to implement adding new tracks to peer connection and forcing negotiation (in OT API)\n return Promise.resolve();\n }\n\n replaceStreamTracks(mediaStream: Nullable<MediaStream>): Promise<void> {\n return Promise.reject(new Error('Not implemented'));\n }\n\n getRemoteTrackStats(mediaTrack: MediaStreamTrack): Promise<RemoteTrackStats> {\n return new Promise((resolve: any, reject: any) => {\n const peerConnectionOfTrack = this.getPeerConnectionByMediaTrack(mediaTrack);\n\n if (!peerConnectionOfTrack || !peerConnectionOfTrack.subscriber) {\n reject(new Error('Cannot find peer or subscriber for getting stats'));\n }\n\n //https://tokbox.com/developer/sdks/js/reference/Subscriber.html#getStats\n peerConnectionOfTrack!.subscriber.getStats((error: any, stats: any) => {\n if (error) {\n trace.warn('Error getting stats', error);\n resolve({trackId: mediaTrack.id, trackStats: {}});\n\n return;\n }\n resolve({trackId: mediaTrack.id, trackStats: stats});\n });\n });\n }\n\n //#region OpenTok Events Handlers\n\n private connectionCreatedHandler(event: any): void {\n trace.info('connectionCreatedHandler', event);\n const {connection} = event;\n\n if (!this.sessionExistsGuard(false) || !connection) {\n return;\n }\n\n const destinationRole = JSON.parse(connection.data).clientRole;\n\n this.createStreamForPublishing(destinationRole)\n .then((streams: OTStreamSource) => {\n const peerConnection: OTPeerConnection = {\n peerId: connection.connectionId,\n peerRole: destinationRole,\n peerType: this._sessionParams.clientType === SessionClientType.INITIATOR\n ? SessionClientType.GUEST : SessionClientType.INITIATOR,\n connection: connection,\n publisher: null,\n subscriber: null,\n remoteMediaTracks: [],\n localStream: streams,\n connectionTimoutPrt: null\n };\n\n if (connection.connectionId !== this.ownPeerId || (!streams.videoSource && !streams.audioSource)) {\n trace.info('Peer connection without publisher was created', peerConnection);\n\n return peerConnection;\n }\n\n return this.createMediaPublisher(streams)\n .then((publisher: OTPublisher) => {\n peerConnection.publisher = publisher;\n trace.info('Peer connection with publisher was created', peerConnection);\n\n return peerConnection;\n });\n })\n .then((peerConnection: OTPeerConnection) => {\n this._peerConnections.set(peerConnection.peerId, peerConnection);\n\n if (connection.connectionId === this.ownPeerId) {\n trace.info('Before subscribe the event streams');\n\n /*\n When publisher connect after others participants,\n make sure the publisher will not loose their stream to subscribe\n */\n return this._lastStreamEvents.reduce((promiseChain: any, streamEvent: any) => promiseChain\n .then(() => this.streamCreatedHandler(streamEvent)), Promise.resolve())\n .then(() => {\n if (peerConnection.publisher) {\n return new Promise<void>((resolve, reject) => {\n trace.info('Starting publish to peerConnection.publisher');\n this._session!.publish(peerConnection.publisher, (error: any) => {\n if (error) {\n trace.error(`Publish to peerConnection error ${error}`);\n\n return reject(error);\n }\n\n this.emitEvent(streamEvents.PUBLISH_STREAM);\n trace.info('Publish to peerConnection success');\n\n return resolve();\n });\n });\n }\n\n return Promise.resolve();\n });\n }\n })\n .catch((error: any) => {\n //Need to handle fail cases during reliability\n trace.error(`Error handling new peer connection: ${error}`);\n });\n }\n\n private connectionDestroyedHandler(event: any): void {\n trace.info('connectionDestroyedHandler', event);\n const {connection} = event;\n\n if (!this.sessionExistsGuard(false) || !connection) {\n return;\n }\n\n if (this._peerConnections.has(connection.connectionId)) {\n this.destroyPeerConnection(this._peerConnections.get(connection.connectionId)!);\n }\n }\n\n private streamCreatedHandler(event: any): void {\n trace.info('streamCreatedHandler', event.stream);\n const {stream} = event;\n const {connection} = stream || {connection: null};\n\n if (!this.sessionExistsGuard(false) || !stream || connection.connectionId === this.ownPeerId) {\n return;\n }\n\n if (!this._peerConnections.has(connection.connectionId)) {\n trace.warn('Unexpected case, connection should exist on this stage');\n this._lastStreamEvents.push(event);\n\n return;\n }\n\n const peerConnection = this._peerConnections.get(connection.connectionId)!;\n\n trace.info('Subscribing the stream');\n\n this.createMediaSubscriber(stream).then((subscriber: OTSubscriber) => {\n peerConnection.subscriber = subscriber;\n\n this.emitEvent(streamEvents.SUBSCRIBE_STREAM);\n });\n }\n\n private streamDestroyedHandler(event: any): void {\n trace.info('streamDestroyedHandler', event);\n const {stream} = event;\n\n if (!this.sessionExistsGuard(false) || !stream) {\n return;\n }\n\n const peerConnection = this._peerConnections.get(stream.connection.connectionId);\n\n if (!peerConnection) {\n trace.warn('Peer connection for remote stream not found');\n\n return;\n }\n\n this.destroySubscriberOnPeerConnection(peerConnection).catch(() => undefined);\n }\n\n //#endregion\n\n //#region PeerConnection\n\n private destroyPeerConnection(peerConnection: OTPeerConnection): void {\n this._peerConnections.delete(peerConnection.peerId);\n this.destroyPublisherOnPeerConnection(peerConnection).catch(() => undefined);\n this.destroySubscriberOnPeerConnection(peerConnection).catch(() => undefined);\n }\n\n //#endregion\n\n //#region Publisher\n\n private createStreamForPublishing(destinationRole: SessionClientRole): Promise<OTStreamSource> {\n trace.info('createStreamForPublishing');\n\n return this._sessionStreamsManager.getMediaStreamForRole(destinationRole)\n .then((mediaStream: Nullable<MediaStream>) => {\n\n const stream: OTStreamSource = {videoSource: null, audioSource: null};\n\n if (mediaStream) {\n trace.info('Media stream found for publishing', mediaStream);\n mediaStream.getTracks().forEach((track) => {\n if (track.kind === 'video') {\n stream.videoSource = track;\n } else if (track.kind === 'audio') {\n stream.audioSource = track;\n }\n });\n } else if (this._sessionParams.clientRole === SessionClientRole.USER) {\n trace.warn('No local media was found for publishing to destinationRole:', destinationRole);\n }\n\n return stream;\n });\n }\n\n private createMediaPublisher(stream: OTStreamSource): Promise<OTPublisher> {\n const otParams = {\n videoSource: stream.videoSource ? stream.videoSource : false,\n audioSource: stream.audioSource ? stream.audioSource : false,\n publishAudio: !!stream.audioSource,\n publishVideo: !!stream.videoSource,\n showControls: false\n };\n\n return new Promise((resolve, reject) => {\n const otPublisher = window.OT.initPublisher(undefined, otParams, (error: any) => {\n if (error) {\n reject(error);\n\n return;\n }\n otPublisher.on('streamDestroyed', (event: any) => {\n trace.info('Publisher stream destroyed', event);\n //We preventing the default, in order to prevent stop the stream by OT.\n //We managing streams by ourselves and if we allow OT to close the stream, it cannot be reused.\n event.preventDefault();\n });\n otPublisher.on('videoElementCreated', (event: any) => {\n document.getElementById(otPublisher.id)!.style.display = 'none';\n event.element.muted = true;\n });\n otPublisher.on('streamCreated', (event: any) => {\n trace.info('publisher stream created @@@@@@@@@@@@@@@', event);\n trace.info('publisher stream created', otPublisher.stream.hasAudio);\n });\n resolve(otPublisher);\n });\n });\n }\n\n private destroyPublisherOnPeerConnection(peerConnection: OTPeerConnection): Promise<void> {\n if (this.sessionExistsGuard(false) && peerConnection.publisher) {\n this._session!.unpublish(peerConnection.publisher);\n }\n\n peerConnection.publisher = null;\n peerConnection.localStream = null;\n\n return Promise.resolve();\n }\n\n //#endregion\n\n //#region Subscriber\n\n private createMediaSubscriber(remoteStream: any): Promise<OTSubscriber> {\n return new Promise((resolve: any, reject: any) => {\n if (!this.sessionExistsGuard(false)) {\n reject('Session not exists');\n\n return;\n }\n\n const subscriber: OTSubscriber = this._session!.subscribe(remoteStream, null, null, (err: any) => {\n if (err) {\n trace.warn('Error creating subscriber', err);\n reject(err);\n\n return;\n }\n\n subscriber.on('videoElementCreated', (event: any) => {\n document.getElementById(subscriber.id)!.style.display = 'none';\n\n // const allNodes: any = document.querySelectorAll('.OT_video-element').length;\n //\n // for (let i in allNodes) {\n // const x = document.querySelector('.OT_video-element');\n //\n // x.remove();\n // }\n\n const {element} = event;\n\n element.muted = true;\n\n // if (remoteStream.hasAudio) {\n // trace.info('dddddddddddddd');\n subscriber.subscribeToAudio(false);\n // element.playsInline = true;\n // element.play()\n // .then(function () {\n // trace.info('playing opentok')\n // });\n // }\n\n const peerConnection = this._peerConnections.get(remoteStream.connection.connectionId)!;\n const otMediaStream: MediaStream = element.srcObject;\n\n peerConnection.subscriber = subscriber;\n\n if (!otMediaStream) {\n trace.warn('MediaStream not found in OT video element');\n\n return;\n }\n\n trace.info('Registering remote media tracks', peerConnection.subscriber, otMediaStream);\n otMediaStream.getTracks().forEach((mediaTrack: MediaStreamTrack) => {\n this.addRemoteTrackToPeer(peerConnection, mediaTrack);\n });\n\n this.registerPeersRemoteTracks(peerConnection);\n });\n\n resolve(subscriber);\n });\n });\n }\n\n private destroySubscriberOnPeerConnection(peerConnection: OTPeerConnection): Promise<void> {\n if (this.sessionExistsGuard(false) && peerConnection.subscriber) {\n this._session!.unsubscribe(peerConnection.subscriber);\n }\n\n peerConnection.subscriber = null;\n\n return Promise.resolve();\n\n /**\n REMARK- opentok provide the same media track id for all participates.\n when we unregister the media track we check by the id which is the same for all.\n **/\n // return this.unregisterPeersRemoteMediaTracks(peerConnection)\n // .catch(() => trace.warn('Error removing remote streams from peerConnection'))\n // .then(() => {\n // peerConnection.subscriber = null;\n // });\n }\n\n //#endregion\n\n private sessionExistsGuard(shouldThrow = true): boolean {\n const connected = !!(this._session && this._session.connection && this._session.connection.connectionId);\n\n return throwableGuard(connected, 'There no OpenTok session exists', shouldThrow);\n }\n}\n"]}
@@ -19,12 +19,8 @@ var __extends = undefined && undefined.__extends || function () {
19
19
  d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
20
20
  };
21
21
  }();
22
- var __importDefault = undefined && undefined.__importDefault || function (mod) {
23
- return mod && mod.__esModule ? mod : { "default": mod };
24
- };
25
22
  Object.defineProperty(exports, "__esModule", { value: true });
26
23
  exports.OpentokSession = void 0;
27
- var cloneDeep_1 = __importDefault(require("lodash/cloneDeep"));
28
24
  var MediaConstants_1 = require("../MediaConstants");
29
25
  var guards_1 = require("@techsee/techsee-common/lib/core/guards");
30
26
  var MediaSessionBase_1 = require("./MediaSessionBase");
@@ -378,6 +374,7 @@ var OpentokSession = /** @class */function (_super) {
378
374
  element.muted = true;
379
375
  // if (remoteStream.hasAudio) {
380
376
  // trace.info('dddddddddddddd');
377
+ subscriber.subscribeToAudio(false);
381
378
  // element.playsInline = true;
382
379
  // element.play()
383
380
  // .then(function () {
@@ -385,9 +382,7 @@ var OpentokSession = /** @class */function (_super) {
385
382
  // });
386
383
  // }
387
384
  var peerConnection = _this._peerConnections.get(remoteStream.connection.connectionId);
388
- var otMediaStream = cloneDeep_1.default(element.srcObject);
389
- element.remove();
390
- console.log(element);
385
+ var otMediaStream = element.srcObject;
391
386
  peerConnection.subscriber = subscriber;
392
387
  if (!otMediaStream) {
393
388
  trace.warn('MediaStream not found in OT video element');
@@ -395,7 +390,7 @@ var OpentokSession = /** @class */function (_super) {
395
390
  }
396
391
  trace.info('Registering remote media tracks', peerConnection.subscriber, otMediaStream);
397
392
  otMediaStream.getTracks().forEach(function (mediaTrack) {
398
- _this.addRemoteTrackToPeer(peerConnection, cloneDeep_1.default(mediaTrack));
393
+ _this.addRemoteTrackToPeer(peerConnection, mediaTrack);
399
394
  });
400
395
  _this.registerPeersRemoteTracks(peerConnection);
401
396
  });
@@ -1 +1 @@
1
- {"version":3,"sources":["MediaSession/SessionOpentok.js"],"names":["__extends","extendStatics","d","b","Object","setPrototypeOf","__proto__","Array","p","prototype","hasOwnProperty","call","__","constructor","create","__importDefault","mod","__esModule","defineProperty","exports","value","OpentokSession","cloneDeep_1","require","MediaConstants_1","guards_1","MediaSessionBase_1","MediaTracer_1","trace","getMediaTracer","_super","sessionParams","streamFactory","_this","_lastStreamEvents","_session","_credentials","credentials","connect","bind","disconnect","onMediaStreamDestroyed","onMediaStreamRenewed","createStreamForPublishing","createMediaPublisher","connectionCreatedHandler","connectionDestroyedHandler","streamCreatedHandler","streamDestroyedHandler","get","sessionId","enumerable","configurable","connection","connectionId","sessionDisconnect","info","error","Promise","reject","resolve","handleError","off","_a","_sessionParams","apiKey","window","OTSESSION","OT","initSession","on","event","emitEvent","recordingEvents","RECORD_STARTED","RECORD_STOPPED","connectHandler","token","currentSession","_peerConnections","forEach","peerConnection","destroyPeerConnection","clientRole","promises","peerRole","push","destroyPublisherOnPeerConnection","all","then","undefined","mediaStream","replaceStreamTracks","Error","getRemoteTrackStats","mediaTrack","peerConnectionOfTrack","getPeerConnectionByMediaTrack","subscriber","getStats","stats","warn","trackId","id","trackStats","sessionExistsGuard","destinationRole","JSON","parse","data","streams","peerId","peerType","clientType","SessionClientType","INITIATOR","GUEST","publisher","remoteMediaTracks","localStream","connectionTimoutPrt","ownPeerId","videoSource","audioSource","set","reduce","promiseChain","streamEvent","publish","streamEvents","PUBLISH_STREAM","catch","has","stream","createMediaSubscriber","SUBSCRIBE_STREAM","destroySubscriberOnPeerConnection","delete","_sessionStreamsManager","getMediaStreamForRole","getTracks","track","kind","SessionClientRole","USER","otParams","publishAudio","publishVideo","showControls","otPublisher","initPublisher","preventDefault","document","getElementById","style","display","element","muted","hasAudio","unpublish","remoteStream","subscribe","err","otMediaStream","default","srcObject","remove","console","log","addRemoteTrackToPeer","registerPeersRemoteTracks","unsubscribe","shouldThrow","connected","throwableGuard","MediaSessionBase"],"mappings":"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","file":"SessionOpentok.js","sourcesContent":["\"use strict\";\nvar __extends = (this && this.__extends) || (function () {\n var extendStatics = function (d, b) {\n extendStatics = Object.setPrototypeOf ||\n ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\n function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };\n return extendStatics(d, b);\n };\n return function (d, b) {\n extendStatics(d, b);\n function __() { this.constructor = d; }\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n})();\nvar __importDefault = (this && this.__importDefault) || function (mod) {\n return (mod && mod.__esModule) ? mod : { \"default\": mod };\n};\nObject.defineProperty(exports, \"__esModule\", { value: true });\nexports.OpentokSession = void 0;\nvar cloneDeep_1 = __importDefault(require(\"lodash/cloneDeep\"));\nvar MediaConstants_1 = require(\"../MediaConstants\");\nvar guards_1 = require(\"@techsee/techsee-common/lib/core/guards\");\nvar MediaSessionBase_1 = require(\"./MediaSessionBase\");\nvar MediaTracer_1 = require(\"../MediaUtils/MediaTracer\");\nvar trace = MediaTracer_1.getMediaTracer('OpentokSession');\n//Currently this version supports subscribing only. Publishing will be implemented as needed.\nvar OpentokSession = /** @class */ (function (_super) {\n __extends(OpentokSession, _super);\n function OpentokSession(sessionParams, streamFactory) {\n var _this = _super.call(this, sessionParams, streamFactory) || this;\n _this._lastStreamEvents = [];\n _this._session = null;\n _this._credentials = sessionParams.credentials;\n _this.connect = _this.connect.bind(_this);\n _this.disconnect = _this.disconnect.bind(_this);\n _this.onMediaStreamDestroyed = _this.onMediaStreamDestroyed.bind(_this);\n _this.onMediaStreamRenewed = _this.onMediaStreamRenewed.bind(_this);\n _this.createStreamForPublishing = _this.createStreamForPublishing.bind(_this);\n _this.createMediaPublisher = _this.createMediaPublisher.bind(_this);\n _this.connectionCreatedHandler = _this.connectionCreatedHandler.bind(_this);\n _this.connectionDestroyedHandler = _this.connectionDestroyedHandler.bind(_this);\n _this.streamCreatedHandler = _this.streamCreatedHandler.bind(_this);\n _this.streamDestroyedHandler = _this.streamDestroyedHandler.bind(_this);\n return _this;\n }\n Object.defineProperty(OpentokSession.prototype, \"id\", {\n get: function () {\n return this._session && this._session.sessionId ? this._session.sessionId : '';\n },\n enumerable: false,\n configurable: true\n });\n Object.defineProperty(OpentokSession.prototype, \"ownPeerId\", {\n get: function () {\n return this._session && this._session.connection ? this._session.connection.connectionId : '';\n },\n enumerable: false,\n configurable: true\n });\n OpentokSession.prototype.sessionDisconnect = function () {\n if (this._session) {\n return this._session.disconnect();\n }\n };\n OpentokSession.prototype.connect = function () {\n var _this = this;\n trace.info('Connect to session', this._credentials);\n if (this._session) {\n trace.error('Session already exists');\n return Promise.reject('Cannot connect to session while another session is active');\n }\n return new Promise(function (resolve, reject) {\n var handleError = function (error) {\n _this._session && _this._session.off();\n _this._session = null;\n trace.error('handleConnect error:', error);\n reject(error);\n };\n var _a = _this._sessionParams.credentials, apiKey = _a.apiKey, sessionId = _a.sessionId;\n _this._session = window.OTSESSION = window.OT.initSession(apiKey, sessionId);\n _this._lastStreamEvents = [];\n _this._session.on('connectionCreated', _this.connectionCreatedHandler);\n _this._session.on('connectionDestroyed', _this.connectionDestroyedHandler);\n _this._session.on('streamCreated', _this.streamCreatedHandler);\n _this._session.on('streamDestroyed', _this.streamDestroyedHandler);\n _this._session.on('archiveStarted', function (event) {\n trace.info('archiveStarted event', event);\n _this.emitEvent(MediaSessionBase_1.recordingEvents.RECORD_STARTED, event);\n });\n _this._session.on('archiveStopped', function (event) {\n trace.info('archiveStopped event', event);\n _this.emitEvent(MediaSessionBase_1.recordingEvents.RECORD_STOPPED, event);\n });\n var connectHandler = function (error) {\n if (error) {\n handleError(error);\n return;\n }\n resolve();\n };\n _this._session.connect(_this._credentials.token, connectHandler);\n });\n };\n OpentokSession.prototype.disconnect = function () {\n var _this = this;\n return new Promise(function (resolve) {\n trace.info('Disconnecting from session');\n var currentSession = _this._session;\n _this._session = null;\n _this._peerConnections.forEach(function (peerConnection) {\n _this.destroyPeerConnection(peerConnection);\n });\n if (!currentSession) {\n trace.info('No active session - resolving');\n resolve();\n return;\n }\n currentSession.off();\n currentSession.disconnect();\n _this._lastStreamEvents = [];\n resolve();\n });\n };\n OpentokSession.prototype.onMediaStreamDestroyed = function (clientRole) {\n var _this = this;\n var promises = [];\n this._peerConnections.forEach(function (peerConnection) {\n if (peerConnection.peerRole === clientRole) {\n promises.push(_this.destroyPublisherOnPeerConnection(peerConnection));\n }\n });\n return Promise.all(promises).then(function () { return undefined; });\n };\n OpentokSession.prototype.onMediaStreamRenewed = function (clientRole, mediaStream) {\n //TODO - Alex: need to implement adding new tracks to peer connection and forcing negotiation (in OT API)\n return Promise.resolve();\n };\n OpentokSession.prototype.replaceStreamTracks = function (mediaStream) {\n return Promise.reject(new Error('Not implemented'));\n };\n OpentokSession.prototype.getRemoteTrackStats = function (mediaTrack) {\n var _this = this;\n return new Promise(function (resolve, reject) {\n var peerConnectionOfTrack = _this.getPeerConnectionByMediaTrack(mediaTrack);\n if (!peerConnectionOfTrack || !peerConnectionOfTrack.subscriber) {\n reject(new Error('Cannot find peer or subscriber for getting stats'));\n }\n //https://tokbox.com/developer/sdks/js/reference/Subscriber.html#getStats\n peerConnectionOfTrack.subscriber.getStats(function (error, stats) {\n if (error) {\n trace.warn('Error getting stats', error);\n resolve({ trackId: mediaTrack.id, trackStats: {} });\n return;\n }\n resolve({ trackId: mediaTrack.id, trackStats: stats });\n });\n });\n };\n //#region OpenTok Events Handlers\n OpentokSession.prototype.connectionCreatedHandler = function (event) {\n var _this = this;\n trace.info('connectionCreatedHandler', event);\n var connection = event.connection;\n if (!this.sessionExistsGuard(false) || !connection) {\n return;\n }\n var destinationRole = JSON.parse(connection.data).clientRole;\n this.createStreamForPublishing(destinationRole)\n .then(function (streams) {\n var peerConnection = {\n peerId: connection.connectionId,\n peerRole: destinationRole,\n peerType: _this._sessionParams.clientType === MediaConstants_1.SessionClientType.INITIATOR\n ? MediaConstants_1.SessionClientType.GUEST : MediaConstants_1.SessionClientType.INITIATOR,\n connection: connection,\n publisher: null,\n subscriber: null,\n remoteMediaTracks: [],\n localStream: streams,\n connectionTimoutPrt: null\n };\n if (connection.connectionId !== _this.ownPeerId || (!streams.videoSource && !streams.audioSource)) {\n trace.info('Peer connection without publisher was created', peerConnection);\n return peerConnection;\n }\n return _this.createMediaPublisher(streams)\n .then(function (publisher) {\n peerConnection.publisher = publisher;\n trace.info('Peer connection with publisher was created', peerConnection);\n return peerConnection;\n });\n })\n .then(function (peerConnection) {\n _this._peerConnections.set(peerConnection.peerId, peerConnection);\n if (connection.connectionId === _this.ownPeerId) {\n trace.info('Before subscribe the event streams');\n /*\n When publisher connect after others participants,\n make sure the publisher will not loose their stream to subscribe\n */\n return _this._lastStreamEvents.reduce(function (promiseChain, streamEvent) { return promiseChain\n .then(function () { return _this.streamCreatedHandler(streamEvent); }); }, Promise.resolve())\n .then(function () {\n if (peerConnection.publisher) {\n return new Promise(function (resolve, reject) {\n trace.info('Starting publish to peerConnection.publisher');\n _this._session.publish(peerConnection.publisher, function (error) {\n if (error) {\n trace.error(\"Publish to peerConnection error \" + error);\n return reject(error);\n }\n _this.emitEvent(MediaSessionBase_1.streamEvents.PUBLISH_STREAM);\n trace.info('Publish to peerConnection success');\n return resolve();\n });\n });\n }\n return Promise.resolve();\n });\n }\n })\n .catch(function (error) {\n //Need to handle fail cases during reliability\n trace.error(\"Error handling new peer connection: \" + error);\n });\n };\n OpentokSession.prototype.connectionDestroyedHandler = function (event) {\n trace.info('connectionDestroyedHandler', event);\n var connection = event.connection;\n if (!this.sessionExistsGuard(false) || !connection) {\n return;\n }\n if (this._peerConnections.has(connection.connectionId)) {\n this.destroyPeerConnection(this._peerConnections.get(connection.connectionId));\n }\n };\n OpentokSession.prototype.streamCreatedHandler = function (event) {\n var _this = this;\n trace.info('streamCreatedHandler', event.stream);\n var stream = event.stream;\n var connection = (stream || { connection: null }).connection;\n if (!this.sessionExistsGuard(false) || !stream || connection.connectionId === this.ownPeerId) {\n return;\n }\n if (!this._peerConnections.has(connection.connectionId)) {\n trace.warn('Unexpected case, connection should exist on this stage');\n this._lastStreamEvents.push(event);\n return;\n }\n var peerConnection = this._peerConnections.get(connection.connectionId);\n trace.info('Subscribing the stream');\n this.createMediaSubscriber(stream).then(function (subscriber) {\n peerConnection.subscriber = subscriber;\n _this.emitEvent(MediaSessionBase_1.streamEvents.SUBSCRIBE_STREAM);\n });\n };\n OpentokSession.prototype.streamDestroyedHandler = function (event) {\n trace.info('streamDestroyedHandler', event);\n var stream = event.stream;\n if (!this.sessionExistsGuard(false) || !stream) {\n return;\n }\n var peerConnection = this._peerConnections.get(stream.connection.connectionId);\n if (!peerConnection) {\n trace.warn('Peer connection for remote stream not found');\n return;\n }\n this.destroySubscriberOnPeerConnection(peerConnection).catch(function () { return undefined; });\n };\n //#endregion\n //#region PeerConnection\n OpentokSession.prototype.destroyPeerConnection = function (peerConnection) {\n this._peerConnections.delete(peerConnection.peerId);\n this.destroyPublisherOnPeerConnection(peerConnection).catch(function () { return undefined; });\n this.destroySubscriberOnPeerConnection(peerConnection).catch(function () { return undefined; });\n };\n //#endregion\n //#region Publisher\n OpentokSession.prototype.createStreamForPublishing = function (destinationRole) {\n var _this = this;\n trace.info('createStreamForPublishing');\n return this._sessionStreamsManager.getMediaStreamForRole(destinationRole)\n .then(function (mediaStream) {\n var stream = { videoSource: null, audioSource: null };\n if (mediaStream) {\n trace.info('Media stream found for publishing', mediaStream);\n mediaStream.getTracks().forEach(function (track) {\n if (track.kind === 'video') {\n stream.videoSource = track;\n }\n else if (track.kind === 'audio') {\n stream.audioSource = track;\n }\n });\n }\n else if (_this._sessionParams.clientRole === MediaConstants_1.SessionClientRole.USER) {\n trace.warn('No local media was found for publishing to destinationRole:', destinationRole);\n }\n return stream;\n });\n };\n OpentokSession.prototype.createMediaPublisher = function (stream) {\n var otParams = {\n videoSource: stream.videoSource ? stream.videoSource : false,\n audioSource: stream.audioSource ? stream.audioSource : false,\n publishAudio: !!stream.audioSource,\n publishVideo: !!stream.videoSource,\n showControls: false\n };\n return new Promise(function (resolve, reject) {\n var otPublisher = window.OT.initPublisher(undefined, otParams, function (error) {\n if (error) {\n reject(error);\n return;\n }\n otPublisher.on('streamDestroyed', function (event) {\n trace.info('Publisher stream destroyed', event);\n //We preventing the default, in order to prevent stop the stream by OT.\n //We managing streams by ourselves and if we allow OT to close the stream, it cannot be reused.\n event.preventDefault();\n });\n otPublisher.on('videoElementCreated', function (event) {\n document.getElementById(otPublisher.id).style.display = 'none';\n event.element.muted = true;\n });\n otPublisher.on('streamCreated', function (event) {\n trace.info('publisher stream created @@@@@@@@@@@@@@@', event);\n trace.info('publisher stream created', otPublisher.stream.hasAudio);\n });\n resolve(otPublisher);\n });\n });\n };\n OpentokSession.prototype.destroyPublisherOnPeerConnection = function (peerConnection) {\n if (this.sessionExistsGuard(false) && peerConnection.publisher) {\n this._session.unpublish(peerConnection.publisher);\n }\n peerConnection.publisher = null;\n peerConnection.localStream = null;\n return Promise.resolve();\n };\n //#endregion\n //#region Subscriber\n OpentokSession.prototype.createMediaSubscriber = function (remoteStream) {\n var _this = this;\n return new Promise(function (resolve, reject) {\n if (!_this.sessionExistsGuard(false)) {\n reject('Session not exists');\n return;\n }\n var subscriber = _this._session.subscribe(remoteStream, null, null, function (err) {\n if (err) {\n trace.warn('Error creating subscriber', err);\n reject(err);\n return;\n }\n subscriber.on('videoElementCreated', function (event) {\n document.getElementById(subscriber.id).style.display = 'none';\n // const allNodes: any = document.querySelectorAll('.OT_video-element').length;\n //\n // for (let i in allNodes) {\n // const x = document.querySelector('.OT_video-element');\n //\n // x.remove();\n // }\n var element = event.element;\n element.muted = true;\n // if (remoteStream.hasAudio) {\n // trace.info('dddddddddddddd');\n // element.playsInline = true;\n // element.play()\n // .then(function () {\n // trace.info('playing opentok')\n // });\n // }\n var peerConnection = _this._peerConnections.get(remoteStream.connection.connectionId);\n var otMediaStream = cloneDeep_1.default(element.srcObject);\n element.remove();\n console.log(element);\n peerConnection.subscriber = subscriber;\n if (!otMediaStream) {\n trace.warn('MediaStream not found in OT video element');\n return;\n }\n trace.info('Registering remote media tracks', peerConnection.subscriber, otMediaStream);\n otMediaStream.getTracks().forEach(function (mediaTrack) {\n _this.addRemoteTrackToPeer(peerConnection, cloneDeep_1.default(mediaTrack));\n });\n _this.registerPeersRemoteTracks(peerConnection);\n });\n resolve(subscriber);\n });\n });\n };\n OpentokSession.prototype.destroySubscriberOnPeerConnection = function (peerConnection) {\n if (this.sessionExistsGuard(false) && peerConnection.subscriber) {\n this._session.unsubscribe(peerConnection.subscriber);\n }\n peerConnection.subscriber = null;\n return Promise.resolve();\n /**\n REMARK- opentok provide the same media track id for all participates.\n when we unregister the media track we check by the id which is the same for all.\n **/\n // return this.unregisterPeersRemoteMediaTracks(peerConnection)\n // .catch(() => trace.warn('Error removing remote streams from peerConnection'))\n // .then(() => {\n // peerConnection.subscriber = null;\n // });\n };\n //#endregion\n OpentokSession.prototype.sessionExistsGuard = function (shouldThrow) {\n if (shouldThrow === void 0) { shouldThrow = true; }\n var connected = !!(this._session && this._session.connection && this._session.connection.connectionId);\n return guards_1.throwableGuard(connected, 'There no OpenTok session exists', shouldThrow);\n };\n return OpentokSession;\n}(MediaSessionBase_1.MediaSessionBase));\nexports.OpentokSession = OpentokSession;\n\n//# sourceMappingURL=SessionOpentok.js.map\n"]}
1
+ {"version":3,"sources":["MediaSession/SessionOpentok.js"],"names":["__extends","extendStatics","d","b","Object","setPrototypeOf","__proto__","Array","p","prototype","hasOwnProperty","call","__","constructor","create","defineProperty","exports","value","OpentokSession","MediaConstants_1","require","guards_1","MediaSessionBase_1","MediaTracer_1","trace","getMediaTracer","_super","sessionParams","streamFactory","_this","_lastStreamEvents","_session","_credentials","credentials","connect","bind","disconnect","onMediaStreamDestroyed","onMediaStreamRenewed","createStreamForPublishing","createMediaPublisher","connectionCreatedHandler","connectionDestroyedHandler","streamCreatedHandler","streamDestroyedHandler","get","sessionId","enumerable","configurable","connection","connectionId","sessionDisconnect","info","error","Promise","reject","resolve","handleError","off","_a","_sessionParams","apiKey","window","OTSESSION","OT","initSession","on","event","emitEvent","recordingEvents","RECORD_STARTED","RECORD_STOPPED","connectHandler","token","currentSession","_peerConnections","forEach","peerConnection","destroyPeerConnection","clientRole","promises","peerRole","push","destroyPublisherOnPeerConnection","all","then","undefined","mediaStream","replaceStreamTracks","Error","getRemoteTrackStats","mediaTrack","peerConnectionOfTrack","getPeerConnectionByMediaTrack","subscriber","getStats","stats","warn","trackId","id","trackStats","sessionExistsGuard","destinationRole","JSON","parse","data","streams","peerId","peerType","clientType","SessionClientType","INITIATOR","GUEST","publisher","remoteMediaTracks","localStream","connectionTimoutPrt","ownPeerId","videoSource","audioSource","set","reduce","promiseChain","streamEvent","publish","streamEvents","PUBLISH_STREAM","catch","has","stream","createMediaSubscriber","SUBSCRIBE_STREAM","destroySubscriberOnPeerConnection","delete","_sessionStreamsManager","getMediaStreamForRole","getTracks","track","kind","SessionClientRole","USER","otParams","publishAudio","publishVideo","showControls","otPublisher","initPublisher","preventDefault","document","getElementById","style","display","element","muted","hasAudio","unpublish","remoteStream","subscribe","err","subscribeToAudio","otMediaStream","srcObject","addRemoteTrackToPeer","registerPeersRemoteTracks","unsubscribe","shouldThrow","connected","throwableGuard","MediaSessionBase"],"mappings":"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","file":"SessionOpentok.js","sourcesContent":["\"use strict\";\nvar __extends = (this && this.__extends) || (function () {\n var extendStatics = function (d, b) {\n extendStatics = Object.setPrototypeOf ||\n ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\n function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };\n return extendStatics(d, b);\n };\n return function (d, b) {\n extendStatics(d, b);\n function __() { this.constructor = d; }\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n})();\nObject.defineProperty(exports, \"__esModule\", { value: true });\nexports.OpentokSession = void 0;\nvar MediaConstants_1 = require(\"../MediaConstants\");\nvar guards_1 = require(\"@techsee/techsee-common/lib/core/guards\");\nvar MediaSessionBase_1 = require(\"./MediaSessionBase\");\nvar MediaTracer_1 = require(\"../MediaUtils/MediaTracer\");\nvar trace = MediaTracer_1.getMediaTracer('OpentokSession');\n//Currently this version supports subscribing only. Publishing will be implemented as needed.\nvar OpentokSession = /** @class */ (function (_super) {\n __extends(OpentokSession, _super);\n function OpentokSession(sessionParams, streamFactory) {\n var _this = _super.call(this, sessionParams, streamFactory) || this;\n _this._lastStreamEvents = [];\n _this._session = null;\n _this._credentials = sessionParams.credentials;\n _this.connect = _this.connect.bind(_this);\n _this.disconnect = _this.disconnect.bind(_this);\n _this.onMediaStreamDestroyed = _this.onMediaStreamDestroyed.bind(_this);\n _this.onMediaStreamRenewed = _this.onMediaStreamRenewed.bind(_this);\n _this.createStreamForPublishing = _this.createStreamForPublishing.bind(_this);\n _this.createMediaPublisher = _this.createMediaPublisher.bind(_this);\n _this.connectionCreatedHandler = _this.connectionCreatedHandler.bind(_this);\n _this.connectionDestroyedHandler = _this.connectionDestroyedHandler.bind(_this);\n _this.streamCreatedHandler = _this.streamCreatedHandler.bind(_this);\n _this.streamDestroyedHandler = _this.streamDestroyedHandler.bind(_this);\n return _this;\n }\n Object.defineProperty(OpentokSession.prototype, \"id\", {\n get: function () {\n return this._session && this._session.sessionId ? this._session.sessionId : '';\n },\n enumerable: false,\n configurable: true\n });\n Object.defineProperty(OpentokSession.prototype, \"ownPeerId\", {\n get: function () {\n return this._session && this._session.connection ? this._session.connection.connectionId : '';\n },\n enumerable: false,\n configurable: true\n });\n OpentokSession.prototype.sessionDisconnect = function () {\n if (this._session) {\n return this._session.disconnect();\n }\n };\n OpentokSession.prototype.connect = function () {\n var _this = this;\n trace.info('Connect to session', this._credentials);\n if (this._session) {\n trace.error('Session already exists');\n return Promise.reject('Cannot connect to session while another session is active');\n }\n return new Promise(function (resolve, reject) {\n var handleError = function (error) {\n _this._session && _this._session.off();\n _this._session = null;\n trace.error('handleConnect error:', error);\n reject(error);\n };\n var _a = _this._sessionParams.credentials, apiKey = _a.apiKey, sessionId = _a.sessionId;\n _this._session = window.OTSESSION = window.OT.initSession(apiKey, sessionId);\n _this._lastStreamEvents = [];\n _this._session.on('connectionCreated', _this.connectionCreatedHandler);\n _this._session.on('connectionDestroyed', _this.connectionDestroyedHandler);\n _this._session.on('streamCreated', _this.streamCreatedHandler);\n _this._session.on('streamDestroyed', _this.streamDestroyedHandler);\n _this._session.on('archiveStarted', function (event) {\n trace.info('archiveStarted event', event);\n _this.emitEvent(MediaSessionBase_1.recordingEvents.RECORD_STARTED, event);\n });\n _this._session.on('archiveStopped', function (event) {\n trace.info('archiveStopped event', event);\n _this.emitEvent(MediaSessionBase_1.recordingEvents.RECORD_STOPPED, event);\n });\n var connectHandler = function (error) {\n if (error) {\n handleError(error);\n return;\n }\n resolve();\n };\n _this._session.connect(_this._credentials.token, connectHandler);\n });\n };\n OpentokSession.prototype.disconnect = function () {\n var _this = this;\n return new Promise(function (resolve) {\n trace.info('Disconnecting from session');\n var currentSession = _this._session;\n _this._session = null;\n _this._peerConnections.forEach(function (peerConnection) {\n _this.destroyPeerConnection(peerConnection);\n });\n if (!currentSession) {\n trace.info('No active session - resolving');\n resolve();\n return;\n }\n currentSession.off();\n currentSession.disconnect();\n _this._lastStreamEvents = [];\n resolve();\n });\n };\n OpentokSession.prototype.onMediaStreamDestroyed = function (clientRole) {\n var _this = this;\n var promises = [];\n this._peerConnections.forEach(function (peerConnection) {\n if (peerConnection.peerRole === clientRole) {\n promises.push(_this.destroyPublisherOnPeerConnection(peerConnection));\n }\n });\n return Promise.all(promises).then(function () { return undefined; });\n };\n OpentokSession.prototype.onMediaStreamRenewed = function (clientRole, mediaStream) {\n //TODO - Alex: need to implement adding new tracks to peer connection and forcing negotiation (in OT API)\n return Promise.resolve();\n };\n OpentokSession.prototype.replaceStreamTracks = function (mediaStream) {\n return Promise.reject(new Error('Not implemented'));\n };\n OpentokSession.prototype.getRemoteTrackStats = function (mediaTrack) {\n var _this = this;\n return new Promise(function (resolve, reject) {\n var peerConnectionOfTrack = _this.getPeerConnectionByMediaTrack(mediaTrack);\n if (!peerConnectionOfTrack || !peerConnectionOfTrack.subscriber) {\n reject(new Error('Cannot find peer or subscriber for getting stats'));\n }\n //https://tokbox.com/developer/sdks/js/reference/Subscriber.html#getStats\n peerConnectionOfTrack.subscriber.getStats(function (error, stats) {\n if (error) {\n trace.warn('Error getting stats', error);\n resolve({ trackId: mediaTrack.id, trackStats: {} });\n return;\n }\n resolve({ trackId: mediaTrack.id, trackStats: stats });\n });\n });\n };\n //#region OpenTok Events Handlers\n OpentokSession.prototype.connectionCreatedHandler = function (event) {\n var _this = this;\n trace.info('connectionCreatedHandler', event);\n var connection = event.connection;\n if (!this.sessionExistsGuard(false) || !connection) {\n return;\n }\n var destinationRole = JSON.parse(connection.data).clientRole;\n this.createStreamForPublishing(destinationRole)\n .then(function (streams) {\n var peerConnection = {\n peerId: connection.connectionId,\n peerRole: destinationRole,\n peerType: _this._sessionParams.clientType === MediaConstants_1.SessionClientType.INITIATOR\n ? MediaConstants_1.SessionClientType.GUEST : MediaConstants_1.SessionClientType.INITIATOR,\n connection: connection,\n publisher: null,\n subscriber: null,\n remoteMediaTracks: [],\n localStream: streams,\n connectionTimoutPrt: null\n };\n if (connection.connectionId !== _this.ownPeerId || (!streams.videoSource && !streams.audioSource)) {\n trace.info('Peer connection without publisher was created', peerConnection);\n return peerConnection;\n }\n return _this.createMediaPublisher(streams)\n .then(function (publisher) {\n peerConnection.publisher = publisher;\n trace.info('Peer connection with publisher was created', peerConnection);\n return peerConnection;\n });\n })\n .then(function (peerConnection) {\n _this._peerConnections.set(peerConnection.peerId, peerConnection);\n if (connection.connectionId === _this.ownPeerId) {\n trace.info('Before subscribe the event streams');\n /*\n When publisher connect after others participants,\n make sure the publisher will not loose their stream to subscribe\n */\n return _this._lastStreamEvents.reduce(function (promiseChain, streamEvent) { return promiseChain\n .then(function () { return _this.streamCreatedHandler(streamEvent); }); }, Promise.resolve())\n .then(function () {\n if (peerConnection.publisher) {\n return new Promise(function (resolve, reject) {\n trace.info('Starting publish to peerConnection.publisher');\n _this._session.publish(peerConnection.publisher, function (error) {\n if (error) {\n trace.error(\"Publish to peerConnection error \" + error);\n return reject(error);\n }\n _this.emitEvent(MediaSessionBase_1.streamEvents.PUBLISH_STREAM);\n trace.info('Publish to peerConnection success');\n return resolve();\n });\n });\n }\n return Promise.resolve();\n });\n }\n })\n .catch(function (error) {\n //Need to handle fail cases during reliability\n trace.error(\"Error handling new peer connection: \" + error);\n });\n };\n OpentokSession.prototype.connectionDestroyedHandler = function (event) {\n trace.info('connectionDestroyedHandler', event);\n var connection = event.connection;\n if (!this.sessionExistsGuard(false) || !connection) {\n return;\n }\n if (this._peerConnections.has(connection.connectionId)) {\n this.destroyPeerConnection(this._peerConnections.get(connection.connectionId));\n }\n };\n OpentokSession.prototype.streamCreatedHandler = function (event) {\n var _this = this;\n trace.info('streamCreatedHandler', event.stream);\n var stream = event.stream;\n var connection = (stream || { connection: null }).connection;\n if (!this.sessionExistsGuard(false) || !stream || connection.connectionId === this.ownPeerId) {\n return;\n }\n if (!this._peerConnections.has(connection.connectionId)) {\n trace.warn('Unexpected case, connection should exist on this stage');\n this._lastStreamEvents.push(event);\n return;\n }\n var peerConnection = this._peerConnections.get(connection.connectionId);\n trace.info('Subscribing the stream');\n this.createMediaSubscriber(stream).then(function (subscriber) {\n peerConnection.subscriber = subscriber;\n _this.emitEvent(MediaSessionBase_1.streamEvents.SUBSCRIBE_STREAM);\n });\n };\n OpentokSession.prototype.streamDestroyedHandler = function (event) {\n trace.info('streamDestroyedHandler', event);\n var stream = event.stream;\n if (!this.sessionExistsGuard(false) || !stream) {\n return;\n }\n var peerConnection = this._peerConnections.get(stream.connection.connectionId);\n if (!peerConnection) {\n trace.warn('Peer connection for remote stream not found');\n return;\n }\n this.destroySubscriberOnPeerConnection(peerConnection).catch(function () { return undefined; });\n };\n //#endregion\n //#region PeerConnection\n OpentokSession.prototype.destroyPeerConnection = function (peerConnection) {\n this._peerConnections.delete(peerConnection.peerId);\n this.destroyPublisherOnPeerConnection(peerConnection).catch(function () { return undefined; });\n this.destroySubscriberOnPeerConnection(peerConnection).catch(function () { return undefined; });\n };\n //#endregion\n //#region Publisher\n OpentokSession.prototype.createStreamForPublishing = function (destinationRole) {\n var _this = this;\n trace.info('createStreamForPublishing');\n return this._sessionStreamsManager.getMediaStreamForRole(destinationRole)\n .then(function (mediaStream) {\n var stream = { videoSource: null, audioSource: null };\n if (mediaStream) {\n trace.info('Media stream found for publishing', mediaStream);\n mediaStream.getTracks().forEach(function (track) {\n if (track.kind === 'video') {\n stream.videoSource = track;\n }\n else if (track.kind === 'audio') {\n stream.audioSource = track;\n }\n });\n }\n else if (_this._sessionParams.clientRole === MediaConstants_1.SessionClientRole.USER) {\n trace.warn('No local media was found for publishing to destinationRole:', destinationRole);\n }\n return stream;\n });\n };\n OpentokSession.prototype.createMediaPublisher = function (stream) {\n var otParams = {\n videoSource: stream.videoSource ? stream.videoSource : false,\n audioSource: stream.audioSource ? stream.audioSource : false,\n publishAudio: !!stream.audioSource,\n publishVideo: !!stream.videoSource,\n showControls: false\n };\n return new Promise(function (resolve, reject) {\n var otPublisher = window.OT.initPublisher(undefined, otParams, function (error) {\n if (error) {\n reject(error);\n return;\n }\n otPublisher.on('streamDestroyed', function (event) {\n trace.info('Publisher stream destroyed', event);\n //We preventing the default, in order to prevent stop the stream by OT.\n //We managing streams by ourselves and if we allow OT to close the stream, it cannot be reused.\n event.preventDefault();\n });\n otPublisher.on('videoElementCreated', function (event) {\n document.getElementById(otPublisher.id).style.display = 'none';\n event.element.muted = true;\n });\n otPublisher.on('streamCreated', function (event) {\n trace.info('publisher stream created @@@@@@@@@@@@@@@', event);\n trace.info('publisher stream created', otPublisher.stream.hasAudio);\n });\n resolve(otPublisher);\n });\n });\n };\n OpentokSession.prototype.destroyPublisherOnPeerConnection = function (peerConnection) {\n if (this.sessionExistsGuard(false) && peerConnection.publisher) {\n this._session.unpublish(peerConnection.publisher);\n }\n peerConnection.publisher = null;\n peerConnection.localStream = null;\n return Promise.resolve();\n };\n //#endregion\n //#region Subscriber\n OpentokSession.prototype.createMediaSubscriber = function (remoteStream) {\n var _this = this;\n return new Promise(function (resolve, reject) {\n if (!_this.sessionExistsGuard(false)) {\n reject('Session not exists');\n return;\n }\n var subscriber = _this._session.subscribe(remoteStream, null, null, function (err) {\n if (err) {\n trace.warn('Error creating subscriber', err);\n reject(err);\n return;\n }\n subscriber.on('videoElementCreated', function (event) {\n document.getElementById(subscriber.id).style.display = 'none';\n // const allNodes: any = document.querySelectorAll('.OT_video-element').length;\n //\n // for (let i in allNodes) {\n // const x = document.querySelector('.OT_video-element');\n //\n // x.remove();\n // }\n var element = event.element;\n element.muted = true;\n // if (remoteStream.hasAudio) {\n // trace.info('dddddddddddddd');\n subscriber.subscribeToAudio(false);\n // element.playsInline = true;\n // element.play()\n // .then(function () {\n // trace.info('playing opentok')\n // });\n // }\n var peerConnection = _this._peerConnections.get(remoteStream.connection.connectionId);\n var otMediaStream = element.srcObject;\n peerConnection.subscriber = subscriber;\n if (!otMediaStream) {\n trace.warn('MediaStream not found in OT video element');\n return;\n }\n trace.info('Registering remote media tracks', peerConnection.subscriber, otMediaStream);\n otMediaStream.getTracks().forEach(function (mediaTrack) {\n _this.addRemoteTrackToPeer(peerConnection, mediaTrack);\n });\n _this.registerPeersRemoteTracks(peerConnection);\n });\n resolve(subscriber);\n });\n });\n };\n OpentokSession.prototype.destroySubscriberOnPeerConnection = function (peerConnection) {\n if (this.sessionExistsGuard(false) && peerConnection.subscriber) {\n this._session.unsubscribe(peerConnection.subscriber);\n }\n peerConnection.subscriber = null;\n return Promise.resolve();\n /**\n REMARK- opentok provide the same media track id for all participates.\n when we unregister the media track we check by the id which is the same for all.\n **/\n // return this.unregisterPeersRemoteMediaTracks(peerConnection)\n // .catch(() => trace.warn('Error removing remote streams from peerConnection'))\n // .then(() => {\n // peerConnection.subscriber = null;\n // });\n };\n //#endregion\n OpentokSession.prototype.sessionExistsGuard = function (shouldThrow) {\n if (shouldThrow === void 0) { shouldThrow = true; }\n var connected = !!(this._session && this._session.connection && this._session.connection.connectionId);\n return guards_1.throwableGuard(connected, 'There no OpenTok session exists', shouldThrow);\n };\n return OpentokSession;\n}(MediaSessionBase_1.MediaSessionBase));\nexports.OpentokSession = OpentokSession;\n\n//# sourceMappingURL=SessionOpentok.js.map\n"]}
@@ -14,6 +14,7 @@ export declare class TechseeMediaSubscriber implements IMediaSubscriber {
14
14
  get streamType(): KnownMediaStream;
15
15
  get container(): HTMLDivElement;
16
16
  get isPlaying(): boolean;
17
+ x(): void;
17
18
  get isSoundMuted(): boolean;
18
19
  get hasAudio(): boolean;
19
20
  get hasVideo(): boolean;
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/MediaSubscriber.ts"],"names":[],"mappings":"AACA,OAAO,EAAC,QAAQ,EAAC,MAAM,yBAAyB,CAAC;AACjD,OAAO,EAAC,gBAAgB,EAAE,qBAAqB,EAAC,MAAM,kBAAkB,CAAC;AACzE,OAAO,EAAC,kBAAkB,EAAC,MAAM,sBAAsB,CAAC;AAExD,OAAO,EAAC,gBAAgB,EAAuB,MAAM,kBAAkB,CAAC;AAYxE,qBAAa,sBAAuB,YAAW,gBAAgB;IAC3D,OAAO,CAAC,QAAQ,CAAe;IAC/B,OAAO,CAAC,WAAW,CAAS;IAC5B,OAAO,CAAC,UAAU,CAAS;IAC3B,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,aAAa,CAAoC;IAEzD,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAAwB;gBAE9C,gBAAgB,EAAE,qBAAqB;IAWnD,IAAI,UAAU,IAAI,gBAAgB,CAEjC;IAED,IAAI,SAAS,IAAI,cAAc,CAE9B;IAED,IAAI,SAAS,IAAI,OAAO,CAEvB;IAED,IAAI,YAAY,IAAI,OAAO,CAM1B;IAED,IAAI,QAAQ,IAAI,OAAO,CAEtB;IAED,IAAI,QAAQ,IAAI,OAAO,CAEtB;IAED,IAAI,YAAY,IAAI,QAAQ,CAAC,gBAAgB,CAAC,CAE7C;IAED,IAAI,UAAU,IAAI,MAAM,CAEvB;IAED,IAAI,WAAW,IAAI,MAAM,CAExB;IAED,IAAI,WAAW,IAAI,MAAM,CAExB;IAED,IAAI,YAAY,IAAI,MAAM,CAEzB;IAED,SAAS,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI;IASjC,cAAc,CAAC,QAAQ,EAAE,MAAM,IAAI,GAAG,IAAI;IAK1C,SAAS,CAAC,QAAQ,EAAE,MAAM,IAAI,GAAG,IAAI;IASrC,YAAY,CAAC,MAAM,EAAE,kBAAkB,GAAG,IAAI;IAkB9C,aAAa,IAAI,OAAO,CAAC,IAAI,CAAC;IAI9B,OAAO,IAAI,IAAI;IAgBf,OAAO,CAAC,eAAe;IA4BvB,OAAO,CAAC,kBAAkB;IAK1B,OAAO,CAAC,kBAAkB;IAQ1B,OAAO,CAAC,SAAS;IAMjB,OAAO,CAAC,eAAe;CAK1B","file":"MediaSubscriber.d.ts","sourcesContent":["import {EventEmitter} from 'events';\nimport {Nullable} from '@techsee/techsee-common';\nimport {IMediaSubscriber, MediaSubscriberParams} from './MediaContracts';\nimport {TechseeMediaStream} from './TechseeMediaStream';\nimport {removeVideoElementFromDom, renderMediaStreamToVideoEl} from './MediaUtils/MediaDomUtils';\nimport {KnownMediaStream, KnownMediaStreamKind} from './MediaConstants';\n\nimport {getMediaTracer} from './MediaUtils/MediaTracer';\nimport {onMediaElementResize} from './MediaUtils/Compatibility';\n\nconst trace = getMediaTracer('MediaSubscriber');\n\nenum privateEvents {\n STREAM_STATE_CHANGE = 'STREAM_STATE_CHANGE',\n SUBSCRIBER_DISPOSE = 'SUBSCRIBER_DISPOSE'\n}\n\nexport class TechseeMediaSubscriber implements IMediaSubscriber {\n private _emitter: EventEmitter;\n private _isDisposed = false;\n private _isPlaying = false;\n private _hasVideo = false;\n private _hasAudio = false;\n private _mediaElement: Nullable<HTMLVideoElement> = null;\n\n private readonly _subscriberParams: MediaSubscriberParams;\n\n constructor(subscriberParams: MediaSubscriberParams) {\n trace.info('Subscriber created');\n\n this.videoResizeHandler = this.videoResizeHandler.bind(this);\n\n this._emitter = new EventEmitter();\n this._subscriberParams = subscriberParams;\n }\n\n //#region IMediaSubscriber\n\n get streamType(): KnownMediaStream {\n return this._subscriberParams.streamType;\n }\n\n get container(): HTMLDivElement {\n return this._subscriberParams.container;\n }\n\n get isPlaying(): boolean {\n return this._isPlaying;\n }\n\n get isSoundMuted(): boolean {\n if (!this._mediaElement) {\n return true;\n }\n\n return this._mediaElement.muted;\n }\n\n get hasAudio(): boolean {\n return this._hasAudio;\n }\n\n get hasVideo(): boolean {\n return this._hasVideo;\n }\n\n get mediaElement(): Nullable<HTMLVideoElement> {\n return this._mediaElement;\n }\n\n get videoWidth(): number {\n return this.mediaElement ? this.mediaElement.videoWidth : 0;\n }\n\n get videoHeight(): number {\n return this.mediaElement ? this.mediaElement.videoHeight : 0;\n }\n\n get renderWidth(): number {\n return this.container.offsetWidth;\n }\n\n get renderHeight(): number {\n return this.container.offsetHeight;\n }\n\n muteSound(isMuted: boolean): void {\n this.throwIfDisposed();\n trace.info('Subscriber mute change - isMuted =', isMuted);\n if (this._mediaElement && this._mediaElement.muted !== isMuted) {\n this._mediaElement.muted = isMuted;\n this.emitEvent(privateEvents.STREAM_STATE_CHANGE);\n }\n }\n\n onStateChanged(callback: () => void): void {\n this.throwIfDisposed();\n this._emitter.on(privateEvents.STREAM_STATE_CHANGE, callback);\n }\n\n onDispose(callback: () => void): void {\n this.throwIfDisposed();\n this._emitter.on(privateEvents.SUBSCRIBER_DISPOSE, callback);\n }\n\n //#endregion\n\n //#region Non Interface Methods\n\n renderStream(stream: TechseeMediaStream): void {\n this.throwIfDisposed();\n this.stopRenderInternal().then(() => renderMediaStreamToVideoEl(this.container, stream.mediaStream))\n .then((videoEl) => {\n this._hasAudio = stream.mediaStream.getAudioTracks().length > 0;\n this._hasVideo = stream.mediaStream.getVideoTracks().length > 0;\n\n this.setPlayingState(videoEl, stream.streamKind);\n\n if (this._hasAudio) {\n this.muteSound(false);\n }\n })\n .catch((error) => {\n trace.warn('Error while rendering stream on video element', error);\n });\n }\n\n stopRendering(): Promise<void> {\n return this.stopRenderInternal().then(() => this.setPlayingState());\n }\n\n dispose(): void {\n if (this._isDisposed) {\n return;\n }\n\n this.stopRendering().catch(() => undefined);\n\n\n this._isDisposed = true;\n this._emitter.removeAllListeners();\n trace.info('Subscriber disposed');\n this.emitEvent(privateEvents.SUBSCRIBER_DISPOSE);\n }\n\n //#endregion\n\n private setPlayingState(mediaElement?: HTMLVideoElement, streamKind?: KnownMediaStreamKind): void {\n this._isPlaying = !!mediaElement;\n this._mediaElement = mediaElement || null;\n\n const finalize = (): void => {\n this.emitEvent(privateEvents.STREAM_STATE_CHANGE);\n trace.info(`Video element ${streamKind || ''} ${this.isPlaying ? 'play' : 'stop'} success`);\n };\n\n if (this._mediaElement && streamKind === KnownMediaStreamKind.Video) {\n if (this._mediaElement.videoHeight === 0) {\n let disposeResizeHandler: any = null;\n const resizeHandler = (): void => {\n disposeResizeHandler && disposeResizeHandler();\n onMediaElementResize(this._mediaElement, this.videoResizeHandler);\n finalize();\n };\n\n disposeResizeHandler = onMediaElementResize(this._mediaElement, resizeHandler);\n } else {\n onMediaElementResize(this._mediaElement, this.videoResizeHandler);\n finalize();\n }\n } else {\n finalize();\n }\n }\n\n private videoResizeHandler(): void {\n trace.info(`Video resize, new size = w: ${this.videoWidth} h:${this.videoHeight}`);\n this.emitEvent(privateEvents.STREAM_STATE_CHANGE);\n }\n\n private stopRenderInternal() {\n if (this._mediaElement && document.body.contains(this._mediaElement)) {\n return removeVideoElementFromDom(this._mediaElement);\n }\n\n return Promise.resolve();\n }\n\n private emitEvent(event: string, eventArgs?: any): void {\n setTimeout(() => {\n this._emitter.emit(event, eventArgs);\n });\n }\n\n private throwIfDisposed(): void {\n if (this._isDisposed) {\n throw new Error('Subscriber is already disposed');\n }\n }\n}\n"]}
1
+ {"version":3,"sources":["../src/MediaSubscriber.ts"],"names":[],"mappings":"AACA,OAAO,EAAC,QAAQ,EAAC,MAAM,yBAAyB,CAAC;AACjD,OAAO,EAAC,gBAAgB,EAAE,qBAAqB,EAAC,MAAM,kBAAkB,CAAC;AACzE,OAAO,EAAC,kBAAkB,EAAC,MAAM,sBAAsB,CAAC;AAExD,OAAO,EAAC,gBAAgB,EAAuB,MAAM,kBAAkB,CAAC;AAYxE,qBAAa,sBAAuB,YAAW,gBAAgB;IAC3D,OAAO,CAAC,QAAQ,CAAe;IAC/B,OAAO,CAAC,WAAW,CAAS;IAC5B,OAAO,CAAC,UAAU,CAAS;IAC3B,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,aAAa,CAAoC;IAEzD,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAAwB;gBAE9C,gBAAgB,EAAE,qBAAqB;IAWnD,IAAI,UAAU,IAAI,gBAAgB,CAEjC;IAED,IAAI,SAAS,IAAI,cAAc,CAE9B;IAED,IAAI,SAAS,IAAI,OAAO,CAEvB;IAGD,CAAC;IAQD,IAAI,YAAY,IAAI,OAAO,CAM1B;IAED,IAAI,QAAQ,IAAI,OAAO,CAEtB;IAED,IAAI,QAAQ,IAAI,OAAO,CAEtB;IAED,IAAI,YAAY,IAAI,QAAQ,CAAC,gBAAgB,CAAC,CAE7C;IAED,IAAI,UAAU,IAAI,MAAM,CAEvB;IAED,IAAI,WAAW,IAAI,MAAM,CAExB;IAED,IAAI,WAAW,IAAI,MAAM,CAExB;IAED,IAAI,YAAY,IAAI,MAAM,CAEzB;IAED,SAAS,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI;IASjC,cAAc,CAAC,QAAQ,EAAE,MAAM,IAAI,GAAG,IAAI;IAK1C,SAAS,CAAC,QAAQ,EAAE,MAAM,IAAI,GAAG,IAAI;IASrC,YAAY,CAAC,MAAM,EAAE,kBAAkB,GAAG,IAAI;IAkB9C,aAAa,IAAI,OAAO,CAAC,IAAI,CAAC;IAI9B,OAAO,IAAI,IAAI;IAgBf,OAAO,CAAC,eAAe;IA4BvB,OAAO,CAAC,kBAAkB;IAK1B,OAAO,CAAC,kBAAkB;IAQ1B,OAAO,CAAC,SAAS;IAMjB,OAAO,CAAC,eAAe;CAK1B","file":"MediaSubscriber.d.ts","sourcesContent":["import {EventEmitter} from 'events';\nimport {Nullable} from '@techsee/techsee-common';\nimport {IMediaSubscriber, MediaSubscriberParams} from './MediaContracts';\nimport {TechseeMediaStream} from './TechseeMediaStream';\nimport {removeVideoElementFromDom, renderMediaStreamToVideoEl} from './MediaUtils/MediaDomUtils';\nimport {KnownMediaStream, KnownMediaStreamKind} from './MediaConstants';\n\nimport {getMediaTracer} from './MediaUtils/MediaTracer';\nimport {onMediaElementResize} from './MediaUtils/Compatibility';\n\nconst trace = getMediaTracer('MediaSubscriber');\n\nenum privateEvents {\n STREAM_STATE_CHANGE = 'STREAM_STATE_CHANGE',\n SUBSCRIBER_DISPOSE = 'SUBSCRIBER_DISPOSE'\n}\n\nexport class TechseeMediaSubscriber implements IMediaSubscriber {\n private _emitter: EventEmitter;\n private _isDisposed = false;\n private _isPlaying = false;\n private _hasVideo = false;\n private _hasAudio = false;\n private _mediaElement: Nullable<HTMLVideoElement> = null;\n\n private readonly _subscriberParams: MediaSubscriberParams;\n\n constructor(subscriberParams: MediaSubscriberParams) {\n trace.info('Subscriber created');\n\n this.videoResizeHandler = this.videoResizeHandler.bind(this);\n\n this._emitter = new EventEmitter();\n this._subscriberParams = subscriberParams;\n }\n\n //#region IMediaSubscriber\n\n get streamType(): KnownMediaStream {\n return this._subscriberParams.streamType;\n }\n\n get container(): HTMLDivElement {\n return this._subscriberParams.container;\n }\n\n get isPlaying(): boolean {\n return this._isPlaying;\n }\n\n\n x() {\n if (!this._mediaElement) {\n return;\n }\n\n this._mediaElement.play();\n }\n\n get isSoundMuted(): boolean {\n if (!this._mediaElement) {\n return true;\n }\n\n return this._mediaElement.muted;\n }\n\n get hasAudio(): boolean {\n return this._hasAudio;\n }\n\n get hasVideo(): boolean {\n return this._hasVideo;\n }\n\n get mediaElement(): Nullable<HTMLVideoElement> {\n return this._mediaElement;\n }\n\n get videoWidth(): number {\n return this.mediaElement ? this.mediaElement.videoWidth : 0;\n }\n\n get videoHeight(): number {\n return this.mediaElement ? this.mediaElement.videoHeight : 0;\n }\n\n get renderWidth(): number {\n return this.container.offsetWidth;\n }\n\n get renderHeight(): number {\n return this.container.offsetHeight;\n }\n\n muteSound(isMuted: boolean): void {\n this.throwIfDisposed();\n trace.info('Subscriber mute change - isMuted =', isMuted);\n if (this._mediaElement && this._mediaElement.muted !== isMuted) {\n this._mediaElement.muted = isMuted;\n this.emitEvent(privateEvents.STREAM_STATE_CHANGE);\n }\n }\n\n onStateChanged(callback: () => void): void {\n this.throwIfDisposed();\n this._emitter.on(privateEvents.STREAM_STATE_CHANGE, callback);\n }\n\n onDispose(callback: () => void): void {\n this.throwIfDisposed();\n this._emitter.on(privateEvents.SUBSCRIBER_DISPOSE, callback);\n }\n\n //#endregion\n\n //#region Non Interface Methods\n\n renderStream(stream: TechseeMediaStream): void {\n this.throwIfDisposed();\n this.stopRenderInternal().then(() => renderMediaStreamToVideoEl(this.container, stream.mediaStream))\n .then((videoEl) => {\n this._hasAudio = stream.mediaStream.getAudioTracks().length > 0;\n this._hasVideo = stream.mediaStream.getVideoTracks().length > 0;\n\n this.setPlayingState(videoEl, stream.streamKind);\n\n if (this._hasAudio) {\n this.muteSound(false);\n }\n })\n .catch((error) => {\n trace.warn('Error while rendering stream on video element', error);\n });\n }\n\n stopRendering(): Promise<void> {\n return this.stopRenderInternal().then(() => this.setPlayingState());\n }\n\n dispose(): void {\n if (this._isDisposed) {\n return;\n }\n\n this.stopRendering().catch(() => undefined);\n\n\n this._isDisposed = true;\n this._emitter.removeAllListeners();\n trace.info('Subscriber disposed');\n this.emitEvent(privateEvents.SUBSCRIBER_DISPOSE);\n }\n\n //#endregion\n\n private setPlayingState(mediaElement?: HTMLVideoElement, streamKind?: KnownMediaStreamKind): void {\n this._isPlaying = !!mediaElement;\n this._mediaElement = mediaElement || null;\n\n const finalize = (): void => {\n this.emitEvent(privateEvents.STREAM_STATE_CHANGE);\n trace.info(`Video element ${streamKind || ''} ${this.isPlaying ? 'play' : 'stop'} success`);\n };\n\n if (this._mediaElement && streamKind === KnownMediaStreamKind.Video) {\n if (this._mediaElement.videoHeight === 0) {\n let disposeResizeHandler: any = null;\n const resizeHandler = (): void => {\n disposeResizeHandler && disposeResizeHandler();\n onMediaElementResize(this._mediaElement, this.videoResizeHandler);\n finalize();\n };\n\n disposeResizeHandler = onMediaElementResize(this._mediaElement, resizeHandler);\n } else {\n onMediaElementResize(this._mediaElement, this.videoResizeHandler);\n finalize();\n }\n } else {\n finalize();\n }\n }\n\n private videoResizeHandler(): void {\n trace.info(`Video resize, new size = w: ${this.videoWidth} h:${this.videoHeight}`);\n this.emitEvent(privateEvents.STREAM_STATE_CHANGE);\n }\n\n private stopRenderInternal() {\n if (this._mediaElement && document.body.contains(this._mediaElement)) {\n return removeVideoElementFromDom(this._mediaElement);\n }\n\n return Promise.resolve();\n }\n\n private emitEvent(event: string, eventArgs?: any): void {\n setTimeout(() => {\n this._emitter.emit(event, eventArgs);\n });\n }\n\n private throwIfDisposed(): void {\n if (this._isDisposed) {\n throw new Error('Subscriber is already disposed');\n }\n }\n}\n"]}
@@ -47,6 +47,12 @@ var TechseeMediaSubscriber = /** @class */function () {
47
47
  enumerable: false,
48
48
  configurable: true
49
49
  });
50
+ TechseeMediaSubscriber.prototype.x = function () {
51
+ if (!this._mediaElement) {
52
+ return;
53
+ }
54
+ this._mediaElement.play();
55
+ };
50
56
  Object.defineProperty(TechseeMediaSubscriber.prototype, "isSoundMuted", {
51
57
  get: function get() {
52
58
  if (!this._mediaElement) {
@@ -1 +1 @@
1
- {"version":3,"sources":["MediaSubscriber.js","../src/MediaSubscriber.ts"],"names":["Object","defineProperty","exports","value","TechseeMediaSubscriber","events_1","require","MediaDomUtils_1","MediaConstants_1","MediaTracer_1","Compatibility_1","trace","getMediaTracer","privateEvents","subscriberParams","_isDisposed","_isPlaying","_hasVideo","_hasAudio","_mediaElement","info","videoResizeHandler","bind","_emitter","EventEmitter","_subscriberParams","prototype","get","streamType","enumerable","configurable","container","muted","mediaElement","videoWidth","videoHeight","offsetWidth","offsetHeight","muteSound","isMuted","throwIfDisposed","emitEvent","STREAM_STATE_CHANGE","onStateChanged","callback","on","onDispose","SUBSCRIBER_DISPOSE","renderStream","stream","_this","stopRenderInternal","then","renderMediaStreamToVideoEl","mediaStream","videoEl","getAudioTracks","length","getVideoTracks","setPlayingState","streamKind","catch","error","warn","stopRendering","dispose","undefined","removeAllListeners","finalize","isPlaying","KnownMediaStreamKind","Video","disposeResizeHandler_1","resizeHandler","onMediaElementResize","document","body","contains","removeVideoElementFromDom","Promise","resolve","event","eventArgs","setTimeout","emit","Error"],"mappings":"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","file":"MediaSubscriber.js","sourcesContent":["\"use strict\";\nObject.defineProperty(exports, \"__esModule\", { value: true });\nexports.TechseeMediaSubscriber = void 0;\nvar events_1 = require(\"events\");\nvar MediaDomUtils_1 = require(\"./MediaUtils/MediaDomUtils\");\nvar MediaConstants_1 = require(\"./MediaConstants\");\nvar MediaTracer_1 = require(\"./MediaUtils/MediaTracer\");\nvar Compatibility_1 = require(\"./MediaUtils/Compatibility\");\nvar trace = MediaTracer_1.getMediaTracer('MediaSubscriber');\nvar privateEvents;\n(function (privateEvents) {\n privateEvents[\"STREAM_STATE_CHANGE\"] = \"STREAM_STATE_CHANGE\";\n privateEvents[\"SUBSCRIBER_DISPOSE\"] = \"SUBSCRIBER_DISPOSE\";\n})(privateEvents || (privateEvents = {}));\nvar TechseeMediaSubscriber = /** @class */ (function () {\n function TechseeMediaSubscriber(subscriberParams) {\n this._isDisposed = false;\n this._isPlaying = false;\n this._hasVideo = false;\n this._hasAudio = false;\n this._mediaElement = null;\n trace.info('Subscriber created');\n this.videoResizeHandler = this.videoResizeHandler.bind(this);\n this._emitter = new events_1.EventEmitter();\n this._subscriberParams = subscriberParams;\n }\n Object.defineProperty(TechseeMediaSubscriber.prototype, \"streamType\", {\n //#region IMediaSubscriber\n get: function () {\n return this._subscriberParams.streamType;\n },\n enumerable: false,\n configurable: true\n });\n Object.defineProperty(TechseeMediaSubscriber.prototype, \"container\", {\n get: function () {\n return this._subscriberParams.container;\n },\n enumerable: false,\n configurable: true\n });\n Object.defineProperty(TechseeMediaSubscriber.prototype, \"isPlaying\", {\n get: function () {\n return this._isPlaying;\n },\n enumerable: false,\n configurable: true\n });\n Object.defineProperty(TechseeMediaSubscriber.prototype, \"isSoundMuted\", {\n get: function () {\n if (!this._mediaElement) {\n return true;\n }\n return this._mediaElement.muted;\n },\n enumerable: false,\n configurable: true\n });\n Object.defineProperty(TechseeMediaSubscriber.prototype, \"hasAudio\", {\n get: function () {\n return this._hasAudio;\n },\n enumerable: false,\n configurable: true\n });\n Object.defineProperty(TechseeMediaSubscriber.prototype, \"hasVideo\", {\n get: function () {\n return this._hasVideo;\n },\n enumerable: false,\n configurable: true\n });\n Object.defineProperty(TechseeMediaSubscriber.prototype, \"mediaElement\", {\n get: function () {\n return this._mediaElement;\n },\n enumerable: false,\n configurable: true\n });\n Object.defineProperty(TechseeMediaSubscriber.prototype, \"videoWidth\", {\n get: function () {\n return this.mediaElement ? this.mediaElement.videoWidth : 0;\n },\n enumerable: false,\n configurable: true\n });\n Object.defineProperty(TechseeMediaSubscriber.prototype, \"videoHeight\", {\n get: function () {\n return this.mediaElement ? this.mediaElement.videoHeight : 0;\n },\n enumerable: false,\n configurable: true\n });\n Object.defineProperty(TechseeMediaSubscriber.prototype, \"renderWidth\", {\n get: function () {\n return this.container.offsetWidth;\n },\n enumerable: false,\n configurable: true\n });\n Object.defineProperty(TechseeMediaSubscriber.prototype, \"renderHeight\", {\n get: function () {\n return this.container.offsetHeight;\n },\n enumerable: false,\n configurable: true\n });\n TechseeMediaSubscriber.prototype.muteSound = function (isMuted) {\n this.throwIfDisposed();\n trace.info('Subscriber mute change - isMuted =', isMuted);\n if (this._mediaElement && this._mediaElement.muted !== isMuted) {\n this._mediaElement.muted = isMuted;\n this.emitEvent(privateEvents.STREAM_STATE_CHANGE);\n }\n };\n TechseeMediaSubscriber.prototype.onStateChanged = function (callback) {\n this.throwIfDisposed();\n this._emitter.on(privateEvents.STREAM_STATE_CHANGE, callback);\n };\n TechseeMediaSubscriber.prototype.onDispose = function (callback) {\n this.throwIfDisposed();\n this._emitter.on(privateEvents.SUBSCRIBER_DISPOSE, callback);\n };\n //#endregion\n //#region Non Interface Methods\n TechseeMediaSubscriber.prototype.renderStream = function (stream) {\n var _this = this;\n this.throwIfDisposed();\n this.stopRenderInternal().then(function () { return MediaDomUtils_1.renderMediaStreamToVideoEl(_this.container, stream.mediaStream); })\n .then(function (videoEl) {\n _this._hasAudio = stream.mediaStream.getAudioTracks().length > 0;\n _this._hasVideo = stream.mediaStream.getVideoTracks().length > 0;\n _this.setPlayingState(videoEl, stream.streamKind);\n if (_this._hasAudio) {\n _this.muteSound(false);\n }\n })\n .catch(function (error) {\n trace.warn('Error while rendering stream on video element', error);\n });\n };\n TechseeMediaSubscriber.prototype.stopRendering = function () {\n var _this = this;\n return this.stopRenderInternal().then(function () { return _this.setPlayingState(); });\n };\n TechseeMediaSubscriber.prototype.dispose = function () {\n if (this._isDisposed) {\n return;\n }\n this.stopRendering().catch(function () { return undefined; });\n this._isDisposed = true;\n this._emitter.removeAllListeners();\n trace.info('Subscriber disposed');\n this.emitEvent(privateEvents.SUBSCRIBER_DISPOSE);\n };\n //#endregion\n TechseeMediaSubscriber.prototype.setPlayingState = function (mediaElement, streamKind) {\n var _this = this;\n this._isPlaying = !!mediaElement;\n this._mediaElement = mediaElement || null;\n var finalize = function () {\n _this.emitEvent(privateEvents.STREAM_STATE_CHANGE);\n trace.info(\"Video element \" + (streamKind || '') + \" \" + (_this.isPlaying ? 'play' : 'stop') + \" success\");\n };\n if (this._mediaElement && streamKind === MediaConstants_1.KnownMediaStreamKind.Video) {\n if (this._mediaElement.videoHeight === 0) {\n var disposeResizeHandler_1 = null;\n var resizeHandler = function () {\n disposeResizeHandler_1 && disposeResizeHandler_1();\n Compatibility_1.onMediaElementResize(_this._mediaElement, _this.videoResizeHandler);\n finalize();\n };\n disposeResizeHandler_1 = Compatibility_1.onMediaElementResize(this._mediaElement, resizeHandler);\n }\n else {\n Compatibility_1.onMediaElementResize(this._mediaElement, this.videoResizeHandler);\n finalize();\n }\n }\n else {\n finalize();\n }\n };\n TechseeMediaSubscriber.prototype.videoResizeHandler = function () {\n trace.info(\"Video resize, new size = w: \" + this.videoWidth + \" h:\" + this.videoHeight);\n this.emitEvent(privateEvents.STREAM_STATE_CHANGE);\n };\n TechseeMediaSubscriber.prototype.stopRenderInternal = function () {\n if (this._mediaElement && document.body.contains(this._mediaElement)) {\n return MediaDomUtils_1.removeVideoElementFromDom(this._mediaElement);\n }\n return Promise.resolve();\n };\n TechseeMediaSubscriber.prototype.emitEvent = function (event, eventArgs) {\n var _this = this;\n setTimeout(function () {\n _this._emitter.emit(event, eventArgs);\n });\n };\n TechseeMediaSubscriber.prototype.throwIfDisposed = function () {\n if (this._isDisposed) {\n throw new Error('Subscriber is already disposed');\n }\n };\n return TechseeMediaSubscriber;\n}());\nexports.TechseeMediaSubscriber = TechseeMediaSubscriber;\n\n//# sourceMappingURL=MediaSubscriber.js.map\n","import {EventEmitter} from 'events';\nimport {Nullable} from '@techsee/techsee-common';\nimport {IMediaSubscriber, MediaSubscriberParams} from './MediaContracts';\nimport {TechseeMediaStream} from './TechseeMediaStream';\nimport {removeVideoElementFromDom, renderMediaStreamToVideoEl} from './MediaUtils/MediaDomUtils';\nimport {KnownMediaStream, KnownMediaStreamKind} from './MediaConstants';\n\nimport {getMediaTracer} from './MediaUtils/MediaTracer';\nimport {onMediaElementResize} from './MediaUtils/Compatibility';\n\nconst trace = getMediaTracer('MediaSubscriber');\n\nenum privateEvents {\n STREAM_STATE_CHANGE = 'STREAM_STATE_CHANGE',\n SUBSCRIBER_DISPOSE = 'SUBSCRIBER_DISPOSE'\n}\n\nexport class TechseeMediaSubscriber implements IMediaSubscriber {\n private _emitter: EventEmitter;\n private _isDisposed = false;\n private _isPlaying = false;\n private _hasVideo = false;\n private _hasAudio = false;\n private _mediaElement: Nullable<HTMLVideoElement> = null;\n\n private readonly _subscriberParams: MediaSubscriberParams;\n\n constructor(subscriberParams: MediaSubscriberParams) {\n trace.info('Subscriber created');\n\n this.videoResizeHandler = this.videoResizeHandler.bind(this);\n\n this._emitter = new EventEmitter();\n this._subscriberParams = subscriberParams;\n }\n\n //#region IMediaSubscriber\n\n get streamType(): KnownMediaStream {\n return this._subscriberParams.streamType;\n }\n\n get container(): HTMLDivElement {\n return this._subscriberParams.container;\n }\n\n get isPlaying(): boolean {\n return this._isPlaying;\n }\n\n get isSoundMuted(): boolean {\n if (!this._mediaElement) {\n return true;\n }\n\n return this._mediaElement.muted;\n }\n\n get hasAudio(): boolean {\n return this._hasAudio;\n }\n\n get hasVideo(): boolean {\n return this._hasVideo;\n }\n\n get mediaElement(): Nullable<HTMLVideoElement> {\n return this._mediaElement;\n }\n\n get videoWidth(): number {\n return this.mediaElement ? this.mediaElement.videoWidth : 0;\n }\n\n get videoHeight(): number {\n return this.mediaElement ? this.mediaElement.videoHeight : 0;\n }\n\n get renderWidth(): number {\n return this.container.offsetWidth;\n }\n\n get renderHeight(): number {\n return this.container.offsetHeight;\n }\n\n muteSound(isMuted: boolean): void {\n this.throwIfDisposed();\n trace.info('Subscriber mute change - isMuted =', isMuted);\n if (this._mediaElement && this._mediaElement.muted !== isMuted) {\n this._mediaElement.muted = isMuted;\n this.emitEvent(privateEvents.STREAM_STATE_CHANGE);\n }\n }\n\n onStateChanged(callback: () => void): void {\n this.throwIfDisposed();\n this._emitter.on(privateEvents.STREAM_STATE_CHANGE, callback);\n }\n\n onDispose(callback: () => void): void {\n this.throwIfDisposed();\n this._emitter.on(privateEvents.SUBSCRIBER_DISPOSE, callback);\n }\n\n //#endregion\n\n //#region Non Interface Methods\n\n renderStream(stream: TechseeMediaStream): void {\n this.throwIfDisposed();\n this.stopRenderInternal().then(() => renderMediaStreamToVideoEl(this.container, stream.mediaStream))\n .then((videoEl) => {\n this._hasAudio = stream.mediaStream.getAudioTracks().length > 0;\n this._hasVideo = stream.mediaStream.getVideoTracks().length > 0;\n\n this.setPlayingState(videoEl, stream.streamKind);\n\n if (this._hasAudio) {\n this.muteSound(false);\n }\n })\n .catch((error) => {\n trace.warn('Error while rendering stream on video element', error);\n });\n }\n\n stopRendering(): Promise<void> {\n return this.stopRenderInternal().then(() => this.setPlayingState());\n }\n\n dispose(): void {\n if (this._isDisposed) {\n return;\n }\n\n this.stopRendering().catch(() => undefined);\n\n\n this._isDisposed = true;\n this._emitter.removeAllListeners();\n trace.info('Subscriber disposed');\n this.emitEvent(privateEvents.SUBSCRIBER_DISPOSE);\n }\n\n //#endregion\n\n private setPlayingState(mediaElement?: HTMLVideoElement, streamKind?: KnownMediaStreamKind): void {\n this._isPlaying = !!mediaElement;\n this._mediaElement = mediaElement || null;\n\n const finalize = (): void => {\n this.emitEvent(privateEvents.STREAM_STATE_CHANGE);\n trace.info(`Video element ${streamKind || ''} ${this.isPlaying ? 'play' : 'stop'} success`);\n };\n\n if (this._mediaElement && streamKind === KnownMediaStreamKind.Video) {\n if (this._mediaElement.videoHeight === 0) {\n let disposeResizeHandler: any = null;\n const resizeHandler = (): void => {\n disposeResizeHandler && disposeResizeHandler();\n onMediaElementResize(this._mediaElement, this.videoResizeHandler);\n finalize();\n };\n\n disposeResizeHandler = onMediaElementResize(this._mediaElement, resizeHandler);\n } else {\n onMediaElementResize(this._mediaElement, this.videoResizeHandler);\n finalize();\n }\n } else {\n finalize();\n }\n }\n\n private videoResizeHandler(): void {\n trace.info(`Video resize, new size = w: ${this.videoWidth} h:${this.videoHeight}`);\n this.emitEvent(privateEvents.STREAM_STATE_CHANGE);\n }\n\n private stopRenderInternal() {\n if (this._mediaElement && document.body.contains(this._mediaElement)) {\n return removeVideoElementFromDom(this._mediaElement);\n }\n\n return Promise.resolve();\n }\n\n private emitEvent(event: string, eventArgs?: any): void {\n setTimeout(() => {\n this._emitter.emit(event, eventArgs);\n });\n }\n\n private throwIfDisposed(): void {\n if (this._isDisposed) {\n throw new Error('Subscriber is already disposed');\n }\n }\n}\n"]}
1
+ {"version":3,"sources":["MediaSubscriber.js","../src/MediaSubscriber.ts"],"names":["Object","defineProperty","exports","value","TechseeMediaSubscriber","events_1","require","MediaDomUtils_1","MediaConstants_1","MediaTracer_1","Compatibility_1","trace","getMediaTracer","privateEvents","subscriberParams","_isDisposed","_isPlaying","_hasVideo","_hasAudio","_mediaElement","info","videoResizeHandler","bind","_emitter","EventEmitter","_subscriberParams","prototype","get","streamType","enumerable","configurable","container","x","play","muted","mediaElement","videoWidth","videoHeight","offsetWidth","offsetHeight","muteSound","isMuted","throwIfDisposed","emitEvent","STREAM_STATE_CHANGE","onStateChanged","callback","on","onDispose","SUBSCRIBER_DISPOSE","renderStream","stream","_this","stopRenderInternal","then","renderMediaStreamToVideoEl","mediaStream","videoEl","getAudioTracks","length","getVideoTracks","setPlayingState","streamKind","catch","error","warn","stopRendering","dispose","undefined","removeAllListeners","finalize","isPlaying","KnownMediaStreamKind","Video","disposeResizeHandler_1","resizeHandler","onMediaElementResize","document","body","contains","removeVideoElementFromDom","Promise","resolve","event","eventArgs","setTimeout","emit","Error"],"mappings":"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","file":"MediaSubscriber.js","sourcesContent":["\"use strict\";\nObject.defineProperty(exports, \"__esModule\", { value: true });\nexports.TechseeMediaSubscriber = void 0;\nvar events_1 = require(\"events\");\nvar MediaDomUtils_1 = require(\"./MediaUtils/MediaDomUtils\");\nvar MediaConstants_1 = require(\"./MediaConstants\");\nvar MediaTracer_1 = require(\"./MediaUtils/MediaTracer\");\nvar Compatibility_1 = require(\"./MediaUtils/Compatibility\");\nvar trace = MediaTracer_1.getMediaTracer('MediaSubscriber');\nvar privateEvents;\n(function (privateEvents) {\n privateEvents[\"STREAM_STATE_CHANGE\"] = \"STREAM_STATE_CHANGE\";\n privateEvents[\"SUBSCRIBER_DISPOSE\"] = \"SUBSCRIBER_DISPOSE\";\n})(privateEvents || (privateEvents = {}));\nvar TechseeMediaSubscriber = /** @class */ (function () {\n function TechseeMediaSubscriber(subscriberParams) {\n this._isDisposed = false;\n this._isPlaying = false;\n this._hasVideo = false;\n this._hasAudio = false;\n this._mediaElement = null;\n trace.info('Subscriber created');\n this.videoResizeHandler = this.videoResizeHandler.bind(this);\n this._emitter = new events_1.EventEmitter();\n this._subscriberParams = subscriberParams;\n }\n Object.defineProperty(TechseeMediaSubscriber.prototype, \"streamType\", {\n //#region IMediaSubscriber\n get: function () {\n return this._subscriberParams.streamType;\n },\n enumerable: false,\n configurable: true\n });\n Object.defineProperty(TechseeMediaSubscriber.prototype, \"container\", {\n get: function () {\n return this._subscriberParams.container;\n },\n enumerable: false,\n configurable: true\n });\n Object.defineProperty(TechseeMediaSubscriber.prototype, \"isPlaying\", {\n get: function () {\n return this._isPlaying;\n },\n enumerable: false,\n configurable: true\n });\n TechseeMediaSubscriber.prototype.x = function () {\n if (!this._mediaElement) {\n return;\n }\n this._mediaElement.play();\n };\n Object.defineProperty(TechseeMediaSubscriber.prototype, \"isSoundMuted\", {\n get: function () {\n if (!this._mediaElement) {\n return true;\n }\n return this._mediaElement.muted;\n },\n enumerable: false,\n configurable: true\n });\n Object.defineProperty(TechseeMediaSubscriber.prototype, \"hasAudio\", {\n get: function () {\n return this._hasAudio;\n },\n enumerable: false,\n configurable: true\n });\n Object.defineProperty(TechseeMediaSubscriber.prototype, \"hasVideo\", {\n get: function () {\n return this._hasVideo;\n },\n enumerable: false,\n configurable: true\n });\n Object.defineProperty(TechseeMediaSubscriber.prototype, \"mediaElement\", {\n get: function () {\n return this._mediaElement;\n },\n enumerable: false,\n configurable: true\n });\n Object.defineProperty(TechseeMediaSubscriber.prototype, \"videoWidth\", {\n get: function () {\n return this.mediaElement ? this.mediaElement.videoWidth : 0;\n },\n enumerable: false,\n configurable: true\n });\n Object.defineProperty(TechseeMediaSubscriber.prototype, \"videoHeight\", {\n get: function () {\n return this.mediaElement ? this.mediaElement.videoHeight : 0;\n },\n enumerable: false,\n configurable: true\n });\n Object.defineProperty(TechseeMediaSubscriber.prototype, \"renderWidth\", {\n get: function () {\n return this.container.offsetWidth;\n },\n enumerable: false,\n configurable: true\n });\n Object.defineProperty(TechseeMediaSubscriber.prototype, \"renderHeight\", {\n get: function () {\n return this.container.offsetHeight;\n },\n enumerable: false,\n configurable: true\n });\n TechseeMediaSubscriber.prototype.muteSound = function (isMuted) {\n this.throwIfDisposed();\n trace.info('Subscriber mute change - isMuted =', isMuted);\n if (this._mediaElement && this._mediaElement.muted !== isMuted) {\n this._mediaElement.muted = isMuted;\n this.emitEvent(privateEvents.STREAM_STATE_CHANGE);\n }\n };\n TechseeMediaSubscriber.prototype.onStateChanged = function (callback) {\n this.throwIfDisposed();\n this._emitter.on(privateEvents.STREAM_STATE_CHANGE, callback);\n };\n TechseeMediaSubscriber.prototype.onDispose = function (callback) {\n this.throwIfDisposed();\n this._emitter.on(privateEvents.SUBSCRIBER_DISPOSE, callback);\n };\n //#endregion\n //#region Non Interface Methods\n TechseeMediaSubscriber.prototype.renderStream = function (stream) {\n var _this = this;\n this.throwIfDisposed();\n this.stopRenderInternal().then(function () { return MediaDomUtils_1.renderMediaStreamToVideoEl(_this.container, stream.mediaStream); })\n .then(function (videoEl) {\n _this._hasAudio = stream.mediaStream.getAudioTracks().length > 0;\n _this._hasVideo = stream.mediaStream.getVideoTracks().length > 0;\n _this.setPlayingState(videoEl, stream.streamKind);\n if (_this._hasAudio) {\n _this.muteSound(false);\n }\n })\n .catch(function (error) {\n trace.warn('Error while rendering stream on video element', error);\n });\n };\n TechseeMediaSubscriber.prototype.stopRendering = function () {\n var _this = this;\n return this.stopRenderInternal().then(function () { return _this.setPlayingState(); });\n };\n TechseeMediaSubscriber.prototype.dispose = function () {\n if (this._isDisposed) {\n return;\n }\n this.stopRendering().catch(function () { return undefined; });\n this._isDisposed = true;\n this._emitter.removeAllListeners();\n trace.info('Subscriber disposed');\n this.emitEvent(privateEvents.SUBSCRIBER_DISPOSE);\n };\n //#endregion\n TechseeMediaSubscriber.prototype.setPlayingState = function (mediaElement, streamKind) {\n var _this = this;\n this._isPlaying = !!mediaElement;\n this._mediaElement = mediaElement || null;\n var finalize = function () {\n _this.emitEvent(privateEvents.STREAM_STATE_CHANGE);\n trace.info(\"Video element \" + (streamKind || '') + \" \" + (_this.isPlaying ? 'play' : 'stop') + \" success\");\n };\n if (this._mediaElement && streamKind === MediaConstants_1.KnownMediaStreamKind.Video) {\n if (this._mediaElement.videoHeight === 0) {\n var disposeResizeHandler_1 = null;\n var resizeHandler = function () {\n disposeResizeHandler_1 && disposeResizeHandler_1();\n Compatibility_1.onMediaElementResize(_this._mediaElement, _this.videoResizeHandler);\n finalize();\n };\n disposeResizeHandler_1 = Compatibility_1.onMediaElementResize(this._mediaElement, resizeHandler);\n }\n else {\n Compatibility_1.onMediaElementResize(this._mediaElement, this.videoResizeHandler);\n finalize();\n }\n }\n else {\n finalize();\n }\n };\n TechseeMediaSubscriber.prototype.videoResizeHandler = function () {\n trace.info(\"Video resize, new size = w: \" + this.videoWidth + \" h:\" + this.videoHeight);\n this.emitEvent(privateEvents.STREAM_STATE_CHANGE);\n };\n TechseeMediaSubscriber.prototype.stopRenderInternal = function () {\n if (this._mediaElement && document.body.contains(this._mediaElement)) {\n return MediaDomUtils_1.removeVideoElementFromDom(this._mediaElement);\n }\n return Promise.resolve();\n };\n TechseeMediaSubscriber.prototype.emitEvent = function (event, eventArgs) {\n var _this = this;\n setTimeout(function () {\n _this._emitter.emit(event, eventArgs);\n });\n };\n TechseeMediaSubscriber.prototype.throwIfDisposed = function () {\n if (this._isDisposed) {\n throw new Error('Subscriber is already disposed');\n }\n };\n return TechseeMediaSubscriber;\n}());\nexports.TechseeMediaSubscriber = TechseeMediaSubscriber;\n\n//# sourceMappingURL=MediaSubscriber.js.map\n","import {EventEmitter} from 'events';\nimport {Nullable} from '@techsee/techsee-common';\nimport {IMediaSubscriber, MediaSubscriberParams} from './MediaContracts';\nimport {TechseeMediaStream} from './TechseeMediaStream';\nimport {removeVideoElementFromDom, renderMediaStreamToVideoEl} from './MediaUtils/MediaDomUtils';\nimport {KnownMediaStream, KnownMediaStreamKind} from './MediaConstants';\n\nimport {getMediaTracer} from './MediaUtils/MediaTracer';\nimport {onMediaElementResize} from './MediaUtils/Compatibility';\n\nconst trace = getMediaTracer('MediaSubscriber');\n\nenum privateEvents {\n STREAM_STATE_CHANGE = 'STREAM_STATE_CHANGE',\n SUBSCRIBER_DISPOSE = 'SUBSCRIBER_DISPOSE'\n}\n\nexport class TechseeMediaSubscriber implements IMediaSubscriber {\n private _emitter: EventEmitter;\n private _isDisposed = false;\n private _isPlaying = false;\n private _hasVideo = false;\n private _hasAudio = false;\n private _mediaElement: Nullable<HTMLVideoElement> = null;\n\n private readonly _subscriberParams: MediaSubscriberParams;\n\n constructor(subscriberParams: MediaSubscriberParams) {\n trace.info('Subscriber created');\n\n this.videoResizeHandler = this.videoResizeHandler.bind(this);\n\n this._emitter = new EventEmitter();\n this._subscriberParams = subscriberParams;\n }\n\n //#region IMediaSubscriber\n\n get streamType(): KnownMediaStream {\n return this._subscriberParams.streamType;\n }\n\n get container(): HTMLDivElement {\n return this._subscriberParams.container;\n }\n\n get isPlaying(): boolean {\n return this._isPlaying;\n }\n\n\n x() {\n if (!this._mediaElement) {\n return;\n }\n\n this._mediaElement.play();\n }\n\n get isSoundMuted(): boolean {\n if (!this._mediaElement) {\n return true;\n }\n\n return this._mediaElement.muted;\n }\n\n get hasAudio(): boolean {\n return this._hasAudio;\n }\n\n get hasVideo(): boolean {\n return this._hasVideo;\n }\n\n get mediaElement(): Nullable<HTMLVideoElement> {\n return this._mediaElement;\n }\n\n get videoWidth(): number {\n return this.mediaElement ? this.mediaElement.videoWidth : 0;\n }\n\n get videoHeight(): number {\n return this.mediaElement ? this.mediaElement.videoHeight : 0;\n }\n\n get renderWidth(): number {\n return this.container.offsetWidth;\n }\n\n get renderHeight(): number {\n return this.container.offsetHeight;\n }\n\n muteSound(isMuted: boolean): void {\n this.throwIfDisposed();\n trace.info('Subscriber mute change - isMuted =', isMuted);\n if (this._mediaElement && this._mediaElement.muted !== isMuted) {\n this._mediaElement.muted = isMuted;\n this.emitEvent(privateEvents.STREAM_STATE_CHANGE);\n }\n }\n\n onStateChanged(callback: () => void): void {\n this.throwIfDisposed();\n this._emitter.on(privateEvents.STREAM_STATE_CHANGE, callback);\n }\n\n onDispose(callback: () => void): void {\n this.throwIfDisposed();\n this._emitter.on(privateEvents.SUBSCRIBER_DISPOSE, callback);\n }\n\n //#endregion\n\n //#region Non Interface Methods\n\n renderStream(stream: TechseeMediaStream): void {\n this.throwIfDisposed();\n this.stopRenderInternal().then(() => renderMediaStreamToVideoEl(this.container, stream.mediaStream))\n .then((videoEl) => {\n this._hasAudio = stream.mediaStream.getAudioTracks().length > 0;\n this._hasVideo = stream.mediaStream.getVideoTracks().length > 0;\n\n this.setPlayingState(videoEl, stream.streamKind);\n\n if (this._hasAudio) {\n this.muteSound(false);\n }\n })\n .catch((error) => {\n trace.warn('Error while rendering stream on video element', error);\n });\n }\n\n stopRendering(): Promise<void> {\n return this.stopRenderInternal().then(() => this.setPlayingState());\n }\n\n dispose(): void {\n if (this._isDisposed) {\n return;\n }\n\n this.stopRendering().catch(() => undefined);\n\n\n this._isDisposed = true;\n this._emitter.removeAllListeners();\n trace.info('Subscriber disposed');\n this.emitEvent(privateEvents.SUBSCRIBER_DISPOSE);\n }\n\n //#endregion\n\n private setPlayingState(mediaElement?: HTMLVideoElement, streamKind?: KnownMediaStreamKind): void {\n this._isPlaying = !!mediaElement;\n this._mediaElement = mediaElement || null;\n\n const finalize = (): void => {\n this.emitEvent(privateEvents.STREAM_STATE_CHANGE);\n trace.info(`Video element ${streamKind || ''} ${this.isPlaying ? 'play' : 'stop'} success`);\n };\n\n if (this._mediaElement && streamKind === KnownMediaStreamKind.Video) {\n if (this._mediaElement.videoHeight === 0) {\n let disposeResizeHandler: any = null;\n const resizeHandler = (): void => {\n disposeResizeHandler && disposeResizeHandler();\n onMediaElementResize(this._mediaElement, this.videoResizeHandler);\n finalize();\n };\n\n disposeResizeHandler = onMediaElementResize(this._mediaElement, resizeHandler);\n } else {\n onMediaElementResize(this._mediaElement, this.videoResizeHandler);\n finalize();\n }\n } else {\n finalize();\n }\n }\n\n private videoResizeHandler(): void {\n trace.info(`Video resize, new size = w: ${this.videoWidth} h:${this.videoHeight}`);\n this.emitEvent(privateEvents.STREAM_STATE_CHANGE);\n }\n\n private stopRenderInternal() {\n if (this._mediaElement && document.body.contains(this._mediaElement)) {\n return removeVideoElementFromDom(this._mediaElement);\n }\n\n return Promise.resolve();\n }\n\n private emitEvent(event: string, eventArgs?: any): void {\n setTimeout(() => {\n this._emitter.emit(event, eventArgs);\n });\n }\n\n private throwIfDisposed(): void {\n if (this._isDisposed) {\n throw new Error('Subscriber is already disposed');\n }\n }\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@techsee/techsee-media-service",
3
- "version": "999.15.13-alpha",
3
+ "version": "999.15.14-alpha",
4
4
  "description": "Techsee Media Service Client",
5
5
  "author": "TechSee",
6
6
  "main": "lib/index.js",