@techsee/techsee-media-service 0.6.1-alpha.1 → 0.6.1-alpha.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (49) hide show
  1. package/lib/LocalStreamManager.d.ts.map +1 -1
  2. package/lib/LocalStreamManager.js +1 -1
  3. package/lib/LocalStreamManager.js.map +1 -1
  4. package/lib/MediaPublisher.d.ts.map +1 -1
  5. package/lib/MediaPublisher.js +1 -1
  6. package/lib/MediaPublisher.js.map +1 -1
  7. package/lib/MediaServiceBase.d.ts.map +1 -1
  8. package/lib/MediaServiceBase.js +5 -5
  9. package/lib/MediaServiceBase.js.map +1 -1
  10. package/lib/MediaSession/SessionOpentok.v3.d.ts.map +1 -0
  11. package/lib/{Session → MediaSession}/SessionOpentok.v3.js +1 -1
  12. package/lib/MediaSession/SessionOpentok.v3.js.map +1 -0
  13. package/lib/MediaSession/SessionTurn.v3.d.ts.map +1 -0
  14. package/lib/{Session → MediaSession}/SessionTurn.v3.js +1 -1
  15. package/lib/MediaSession/SessionTurn.v3.js.map +1 -0
  16. package/lib/MediaSession/TurnConstants.d.ts.map +1 -0
  17. package/lib/MediaSession/TurnConstants.js.map +1 -0
  18. package/lib/MediaSubscriber.d.ts.map +1 -1
  19. package/lib/MediaSubscriber.js +2 -2
  20. package/lib/MediaSubscriber.js.map +1 -1
  21. package/lib/MediaUtils/Compatibility.d.ts.map +1 -0
  22. package/lib/MediaUtils/Compatibility.js.map +1 -0
  23. package/lib/MediaUtils/MediaDomUtils.d.ts.map +1 -0
  24. package/lib/MediaUtils/MediaDomUtils.js.map +1 -0
  25. package/lib/MediaUtils/MediaTracer.d.ts.map +1 -0
  26. package/lib/MediaUtils/MediaTracer.js.map +1 -0
  27. package/package.json +1 -1
  28. package/lib/Session/SessionOpentok.v3.d.ts.map +0 -1
  29. package/lib/Session/SessionOpentok.v3.js.map +0 -1
  30. package/lib/Session/SessionTurn.v3.d.ts.map +0 -1
  31. package/lib/Session/SessionTurn.v3.js.map +0 -1
  32. package/lib/Session/TurnConstants.d.ts.map +0 -1
  33. package/lib/Session/TurnConstants.js.map +0 -1
  34. package/lib/Utils/Compatibility.d.ts.map +0 -1
  35. package/lib/Utils/Compatibility.js.map +0 -1
  36. package/lib/Utils/MediaDomUtils.d.ts.map +0 -1
  37. package/lib/Utils/MediaDomUtils.js.map +0 -1
  38. package/lib/Utils/MediaTracer.d.ts.map +0 -1
  39. package/lib/Utils/MediaTracer.js.map +0 -1
  40. /package/lib/{Session → MediaSession}/SessionOpentok.v3.d.ts +0 -0
  41. /package/lib/{Session → MediaSession}/SessionTurn.v3.d.ts +0 -0
  42. /package/lib/{Session → MediaSession}/TurnConstants.d.ts +0 -0
  43. /package/lib/{Session → MediaSession}/TurnConstants.js +0 -0
  44. /package/lib/{Utils → MediaUtils}/Compatibility.d.ts +0 -0
  45. /package/lib/{Utils → MediaUtils}/Compatibility.js +0 -0
  46. /package/lib/{Utils → MediaUtils}/MediaDomUtils.d.ts +0 -0
  47. /package/lib/{Utils → MediaUtils}/MediaDomUtils.js +0 -0
  48. /package/lib/{Utils → MediaUtils}/MediaTracer.d.ts +0 -0
  49. /package/lib/{Utils → MediaUtils}/MediaTracer.js +0 -0
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/LocalStreamManager.ts"],"names":[],"mappings":"AAGA,OAAO,EAAC,QAAQ,EAAC,MAAM,yBAAyB,CAAC;AAEjD,OAAO,EAEH,qBAAqB,EACrB,2BAA2B,EAE3B,yBAAyB,EACzB,iBAAiB,EACpB,MAAM,kBAAkB,CAAC;AAS1B,OAAO,CAAC,MAAM,CAAC;IACX,UAAU,MAAM;QACZ,qBAAqB,EAAE,QAAQ,CAAC,yBAAyB,CAAC,CAAC;QAC3D,wBAAwB,EAAE,QAAQ,CAAC,yBAAyB,CAAC,CAAC;KACjE;CACJ;AAcD,qBAAa,kBAAkB;IAC3B,OAAO,CAAC,WAAW,CAAoB;gBAE3B,WAAW,EAAE,iBAAiB;IAO1C,kBAAkB,CAAC,WAAW,EAAE,qBAAqB,GAAG,OAAO,CAAC,yBAAyB,CAAC;IAyC1F,qBAAqB,CAAC,WAAW,EAAE,2BAA2B,GAAG,OAAO,CAAC,yBAAyB,CAAC;IA0CnG,sBAAsB,IAAI,OAAO,CAAC,IAAI,CAAC;IAevC,yBAAyB,IAAI,OAAO,CAAC,IAAI,CAAC;IAe1C,eAAe,IAAI,OAAO,CAAC,IAAI,CAAC;IAShC,OAAO,CAAC,0BAA0B;IAqDlC,OAAO,CAAC,mCAAmC;IAsB3C,OAAO,CAAC,oBAAoB;IAsD5B,OAAO,CAAC,wBAAwB;CAoCnC","file":"LocalStreamManager.d.ts","sourcesContent":["import assign from 'lodash/assign';\nimport get from 'lodash/get';\n\nimport {Nullable} from '@techsee/techsee-common';\n\nimport {\n VideoStreamResolution,\n LocalMediaConstraints,\n LocalVideoStreamConstraints,\n MediaRequestFailResult,\n MediaRequestSuccessResult,\n IMediaEnvironment\n} from './MediaContracts';\n\nimport {\n ConstraintType,\n DEFAULT_VIDEO_CONSTRAINT_TYPE,\n DEFAULT_VIDEO_RESOLUTION,\n MediaRequestErrorCode\n} from './MediaConstants';\n\ndeclare global {\n interface Window {\n latestUserMediaStream: Nullable<MediaRequestSuccessResult>;\n latestDesktopMediaStream: Nullable<MediaRequestSuccessResult>;\n }\n}\n\ndeclare const window: Window;\n\nwindow.latestUserMediaStream = null;\nlet userMediaPromise: Nullable<Promise<MediaRequestSuccessResult>> = null;\n\nwindow.latestDesktopMediaStream = null;\nlet desktopMediaPromise: Nullable<Promise<MediaRequestSuccessResult>> = null;\n\nimport {getMediaTracer} from './Utils/MediaTracer';\n\nconst trace = getMediaTracer('LocalStreamManager');\n\nexport class LocalStreamManager {\n private environment: IMediaEnvironment;\n\n constructor(environment: IMediaEnvironment) {\n this.environment = environment;\n\n this.parseMediaErrorThenThrow = this.parseMediaErrorThenThrow.bind(this);\n this.clearAllStreams = this.clearAllStreams.bind(this);\n }\n\n getUserMediaStream(constraints: LocalMediaConstraints): Promise<MediaRequestSuccessResult> {\n trace.info('getUserMediaStream', constraints);\n if (userMediaPromise) {\n return userMediaPromise;\n }\n\n if (window.latestUserMediaStream) {\n const videoTrack = window.latestUserMediaStream.mediaStream.getVideoTracks();\n\n if (videoTrack.length > 0 && videoTrack[0].readyState === 'live') {\n return Promise.resolve({...window.latestUserMediaStream, isNew: false});\n }\n this.destroyUserMediaStream();\n\n }\n\n\n userMediaPromise = new Promise((resolve, reject) => {\n const catchHandler = (err: any): void => {\n userMediaPromise = null;\n window.latestUserMediaStream = null;\n trace.error('getUserMedia error', err);\n reject(err);\n };\n\n try {\n this.getHighestResolutionStream(false, constraints)\n .then((streamResult: MediaRequestSuccessResult) => {\n userMediaPromise = null;\n window.latestUserMediaStream = streamResult;\n resolve({...window.latestUserMediaStream, isNew: true});\n })\n .catch(catchHandler);\n } catch (err) {\n catchHandler(err);\n }\n });\n\n return userMediaPromise;\n }\n\n getDesktopMediaStream(constraints: LocalVideoStreamConstraints): Promise<MediaRequestSuccessResult> {\n if (desktopMediaPromise) {\n return desktopMediaPromise;\n }\n\n if (window.latestDesktopMediaStream) {\n const track = window.latestDesktopMediaStream.mediaStream.getVideoTracks();\n\n if (track.length > 0 && track[0].readyState === 'live') {\n //return Promise.resolve();\n return Promise.resolve({...window.latestDesktopMediaStream, isNew: false});\n }\n this.destroyDesktopMediaStream().catch((error: any) => {\n trace.error('Error destroying desktop media stream', error);\n });\n\n }\n\n desktopMediaPromise = new Promise((resolve, reject) => {\n const mediaCatchHandler = (err: any): void => {\n desktopMediaPromise = null;\n window.latestDesktopMediaStream = null;\n trace.error('getDisplayMedia error', err);\n reject(err);\n };\n\n try {\n this.getHighestResolutionStream(true, {video: constraints, audio: false})\n .then((streamResult: MediaRequestSuccessResult) => {\n desktopMediaPromise = null;\n window.latestDesktopMediaStream = streamResult;\n\n resolve({...window.latestDesktopMediaStream, isNew: true});\n }).catch(mediaCatchHandler);\n } catch (err) {\n mediaCatchHandler(err);\n }\n });\n\n return desktopMediaPromise;\n }\n\n destroyUserMediaStream(): Promise<void> {\n const streamResult = window.latestUserMediaStream;\n\n window.latestUserMediaStream = null;\n userMediaPromise = null;\n\n if (streamResult) {\n streamResult.mediaStream.getTracks().forEach((track: MediaStreamTrack) => {\n track.stop();\n });\n }\n\n return Promise.resolve();\n }\n\n destroyDesktopMediaStream(): Promise<void> {\n const streamResult = window.latestDesktopMediaStream;\n\n window.latestDesktopMediaStream = null;\n desktopMediaPromise = null;\n\n if (streamResult) {\n streamResult.mediaStream.getTracks().forEach((track: MediaStreamTrack) => {\n track.stop();\n });\n }\n\n return Promise.resolve();\n }\n\n clearAllStreams(): Promise<void> {\n trace.info('LocalStreamManager Clearing all streams');\n\n return Promise.all([\n this.destroyDesktopMediaStream(),\n this.destroyUserMediaStream()\n ]).then(() => undefined);\n }\n\n private getHighestResolutionStream(isDesktopMedia: boolean, constraints?: LocalMediaConstraints): Promise<MediaRequestSuccessResult> {\n const constraintsCandidates = this.getParsedConstraints(isDesktopMedia, constraints);\n\n if (constraintsCandidates.length === 0) {\n return Promise.reject(new Error('No constraints to retrieve the stream'));\n }\n\n return new Promise((resolve, reject) => {\n let lastSuccessfulResult: Nullable<MediaRequestSuccessResult> = null;\n let lastFailedResult: Nullable<MediaRequestFailResult> = null;\n let isStreamRequestFulfilled = false;\n\n (Promise as any).reduce(constraintsCandidates, (total: any, candidate: MediaStreamConstraints) => {\n if (isStreamRequestFulfilled) {\n return;\n }\n const constraintType = get(constraints, 'video.videoResolution.constraintType') || get(constraints, 'video.videoResolution[0].constraintType');\n\n return this.getStreamPromiseByParsedConstraints(candidate, isDesktopMedia)\n .then((stream: MediaStream) => {\n lastSuccessfulResult = {\n mediaStream: stream,\n constraint: candidate,\n constraintType,\n isNew: true\n };\n trace.info('getHighestResolutionStream Success', lastSuccessfulResult);\n isStreamRequestFulfilled = true;\n resolve(lastSuccessfulResult);\n })\n .catch((failResult: MediaRequestFailResult) => {\n lastFailedResult = failResult;\n if (lastFailedResult.errorCode === MediaRequestErrorCode.PermissionDenied) {\n isStreamRequestFulfilled = true;\n reject(lastFailedResult);\n }\n });\n }, 0)\n .then(() => {\n if (!isStreamRequestFulfilled) {\n if (!lastFailedResult) {\n lastFailedResult = {\n errorCode: MediaRequestErrorCode.GeneralError,\n message: 'Suitable stream cannot be created'\n };\n }\n reject(lastFailedResult);\n }\n });\n });\n }\n\n //@ts-ignore\n private getStreamPromiseByParsedConstraints(constraints: MediaStreamConstraints, isDesktopMedia: boolean): Promise<MediaStream> {\n let streamPromise = null;\n\n trace.info('getStreamPromiseByParsedConstraints', constraints);\n\n try {\n if (!isDesktopMedia) {\n streamPromise = navigator.mediaDevices.getUserMedia(constraints);\n } else {\n //@ts-ignore\n streamPromise = navigator.mediaDevices.getDisplayMedia\n //@ts-ignore\n ? navigator.mediaDevices.getDisplayMedia(constraints)\n : navigator.getDisplayMedia(constraints);\n }\n\n return streamPromise.catch(this.parseMediaErrorThenThrow);\n } catch (e) {\n this.parseMediaErrorThenThrow(e);\n }\n }\n\n private getParsedConstraints(isDesktopMedia: boolean, streamConstraints?: LocalMediaConstraints): MediaStreamConstraints[] {\n const constraintCandidates: MediaStreamConstraints[] = [];\n\n //TODO - Alex: need to understand which constraints not compatible with screen share\n if (isDesktopMedia) {\n return [{video: true}];\n }\n\n if (!streamConstraints) {\n return constraintCandidates;\n }\n\n const baseConstraints: MediaStreamConstraints = {};\n\n baseConstraints.audio = typeof streamConstraints.audio === 'boolean' ? streamConstraints.audio : undefined;\n\n if (!streamConstraints.video) {\n return [baseConstraints];\n }\n\n baseConstraints.video = {\n facingMode: 'environment',\n frameRate: {ideal: 15, max: 30}\n };\n\n const assignConstraint = (videoResolution: VideoStreamResolution): void => {\n const [width, height] = videoResolution.resolution.split('x');\n const constraintCandidate = assign({}, baseConstraints);\n\n constraintCandidate.video = assign({}, baseConstraints.video, {\n width: _constraintByType(width, videoResolution.constraintType),\n height: _constraintByType(height, videoResolution.constraintType)\n });\n constraintCandidates.push(constraintCandidate);\n };\n\n if ((baseConstraints.video && typeof streamConstraints.video === 'boolean') ||\n !((streamConstraints.video as LocalVideoStreamConstraints).videoResolution instanceof Array)) {\n\n const defaultResolution: VideoStreamResolution = {\n resolution: DEFAULT_VIDEO_RESOLUTION,\n constraintType: DEFAULT_VIDEO_CONSTRAINT_TYPE\n };\n\n assignConstraint(defaultResolution);\n\n return constraintCandidates;\n }\n\n (streamConstraints.video as any).videoResolution.forEach(assignConstraint);\n\n return constraintCandidates;\n }\n\n private parseMediaErrorThenThrow(error: any): MediaRequestFailResult {\n trace.error('Get media stream error.', error);\n const errorName = error && error.name ? error.name : '';\n\n const permissionErrorNames = [\n 'NotAllowedError',\n 'PermissionDismissedError',\n 'PermissionDeniedError'\n\n ];\n\n // const generalError = [\n // 'NotFoundError',\n // 'DevicesNotFoundError',\n // 'NotReadableError',\n // 'TrackStartError'\n // ];\n\n const constraintsErrors = [\n 'OverconstrainedError',\n 'ConstraintNotSatisfiedError'\n\n ];\n\n const isErrorOfType = (errorsArr: string[]) => errorsArr.filter((err: string) => err === errorName).length > 0;\n\n if (isErrorOfType(permissionErrorNames)) {\n throw {errorCode: MediaRequestErrorCode.PermissionDenied, message: errorName};\n }\n\n if (isErrorOfType(constraintsErrors)) {\n throw {errorCode: MediaRequestErrorCode.Overconstrained, message: errorName};\n }\n\n throw {errorCode: MediaRequestErrorCode.GeneralError, message: errorName};\n }\n}\n\nfunction _constraintByType(value: any, type: ConstraintType): any {\n switch (type) {\n case ConstraintType.MIN:\n return {min: value};\n default:\n return {ideal: value};\n }\n}\n"]}
1
+ {"version":3,"sources":["../src/LocalStreamManager.ts"],"names":[],"mappings":"AAGA,OAAO,EAAC,QAAQ,EAAC,MAAM,yBAAyB,CAAC;AAEjD,OAAO,EAEH,qBAAqB,EACrB,2BAA2B,EAE3B,yBAAyB,EACzB,iBAAiB,EACpB,MAAM,kBAAkB,CAAC;AAS1B,OAAO,CAAC,MAAM,CAAC;IACX,UAAU,MAAM;QACZ,qBAAqB,EAAE,QAAQ,CAAC,yBAAyB,CAAC,CAAC;QAC3D,wBAAwB,EAAE,QAAQ,CAAC,yBAAyB,CAAC,CAAC;KACjE;CACJ;AAcD,qBAAa,kBAAkB;IAC3B,OAAO,CAAC,WAAW,CAAoB;gBAE3B,WAAW,EAAE,iBAAiB;IAO1C,kBAAkB,CAAC,WAAW,EAAE,qBAAqB,GAAG,OAAO,CAAC,yBAAyB,CAAC;IAyC1F,qBAAqB,CAAC,WAAW,EAAE,2BAA2B,GAAG,OAAO,CAAC,yBAAyB,CAAC;IA0CnG,sBAAsB,IAAI,OAAO,CAAC,IAAI,CAAC;IAevC,yBAAyB,IAAI,OAAO,CAAC,IAAI,CAAC;IAe1C,eAAe,IAAI,OAAO,CAAC,IAAI,CAAC;IAShC,OAAO,CAAC,0BAA0B;IAqDlC,OAAO,CAAC,mCAAmC;IAsB3C,OAAO,CAAC,oBAAoB;IAsD5B,OAAO,CAAC,wBAAwB;CAoCnC","file":"LocalStreamManager.d.ts","sourcesContent":["import assign from 'lodash/assign';\nimport get from 'lodash/get';\n\nimport {Nullable} from '@techsee/techsee-common';\n\nimport {\n VideoStreamResolution,\n LocalMediaConstraints,\n LocalVideoStreamConstraints,\n MediaRequestFailResult,\n MediaRequestSuccessResult,\n IMediaEnvironment\n} from './MediaContracts';\n\nimport {\n ConstraintType,\n DEFAULT_VIDEO_CONSTRAINT_TYPE,\n DEFAULT_VIDEO_RESOLUTION,\n MediaRequestErrorCode\n} from './MediaConstants';\n\ndeclare global {\n interface Window {\n latestUserMediaStream: Nullable<MediaRequestSuccessResult>;\n latestDesktopMediaStream: Nullable<MediaRequestSuccessResult>;\n }\n}\n\ndeclare const window: Window;\n\nwindow.latestUserMediaStream = null;\nlet userMediaPromise: Nullable<Promise<MediaRequestSuccessResult>> = null;\n\nwindow.latestDesktopMediaStream = null;\nlet desktopMediaPromise: Nullable<Promise<MediaRequestSuccessResult>> = null;\n\nimport {getMediaTracer} from './MediaUtils/MediaTracer';\n\nconst trace = getMediaTracer('LocalStreamManager');\n\nexport class LocalStreamManager {\n private environment: IMediaEnvironment;\n\n constructor(environment: IMediaEnvironment) {\n this.environment = environment;\n\n this.parseMediaErrorThenThrow = this.parseMediaErrorThenThrow.bind(this);\n this.clearAllStreams = this.clearAllStreams.bind(this);\n }\n\n getUserMediaStream(constraints: LocalMediaConstraints): Promise<MediaRequestSuccessResult> {\n trace.info('getUserMediaStream', constraints);\n if (userMediaPromise) {\n return userMediaPromise;\n }\n\n if (window.latestUserMediaStream) {\n const videoTrack = window.latestUserMediaStream.mediaStream.getVideoTracks();\n\n if (videoTrack.length > 0 && videoTrack[0].readyState === 'live') {\n return Promise.resolve({...window.latestUserMediaStream, isNew: false});\n }\n this.destroyUserMediaStream();\n\n }\n\n\n userMediaPromise = new Promise((resolve, reject) => {\n const catchHandler = (err: any): void => {\n userMediaPromise = null;\n window.latestUserMediaStream = null;\n trace.error('getUserMedia error', err);\n reject(err);\n };\n\n try {\n this.getHighestResolutionStream(false, constraints)\n .then((streamResult: MediaRequestSuccessResult) => {\n userMediaPromise = null;\n window.latestUserMediaStream = streamResult;\n resolve({...window.latestUserMediaStream, isNew: true});\n })\n .catch(catchHandler);\n } catch (err) {\n catchHandler(err);\n }\n });\n\n return userMediaPromise;\n }\n\n getDesktopMediaStream(constraints: LocalVideoStreamConstraints): Promise<MediaRequestSuccessResult> {\n if (desktopMediaPromise) {\n return desktopMediaPromise;\n }\n\n if (window.latestDesktopMediaStream) {\n const track = window.latestDesktopMediaStream.mediaStream.getVideoTracks();\n\n if (track.length > 0 && track[0].readyState === 'live') {\n //return Promise.resolve();\n return Promise.resolve({...window.latestDesktopMediaStream, isNew: false});\n }\n this.destroyDesktopMediaStream().catch((error: any) => {\n trace.error('Error destroying desktop media stream', error);\n });\n\n }\n\n desktopMediaPromise = new Promise((resolve, reject) => {\n const mediaCatchHandler = (err: any): void => {\n desktopMediaPromise = null;\n window.latestDesktopMediaStream = null;\n trace.error('getDisplayMedia error', err);\n reject(err);\n };\n\n try {\n this.getHighestResolutionStream(true, {video: constraints, audio: false})\n .then((streamResult: MediaRequestSuccessResult) => {\n desktopMediaPromise = null;\n window.latestDesktopMediaStream = streamResult;\n\n resolve({...window.latestDesktopMediaStream, isNew: true});\n }).catch(mediaCatchHandler);\n } catch (err) {\n mediaCatchHandler(err);\n }\n });\n\n return desktopMediaPromise;\n }\n\n destroyUserMediaStream(): Promise<void> {\n const streamResult = window.latestUserMediaStream;\n\n window.latestUserMediaStream = null;\n userMediaPromise = null;\n\n if (streamResult) {\n streamResult.mediaStream.getTracks().forEach((track: MediaStreamTrack) => {\n track.stop();\n });\n }\n\n return Promise.resolve();\n }\n\n destroyDesktopMediaStream(): Promise<void> {\n const streamResult = window.latestDesktopMediaStream;\n\n window.latestDesktopMediaStream = null;\n desktopMediaPromise = null;\n\n if (streamResult) {\n streamResult.mediaStream.getTracks().forEach((track: MediaStreamTrack) => {\n track.stop();\n });\n }\n\n return Promise.resolve();\n }\n\n clearAllStreams(): Promise<void> {\n trace.info('LocalStreamManager Clearing all streams');\n\n return Promise.all([\n this.destroyDesktopMediaStream(),\n this.destroyUserMediaStream()\n ]).then(() => undefined);\n }\n\n private getHighestResolutionStream(isDesktopMedia: boolean, constraints?: LocalMediaConstraints): Promise<MediaRequestSuccessResult> {\n const constraintsCandidates = this.getParsedConstraints(isDesktopMedia, constraints);\n\n if (constraintsCandidates.length === 0) {\n return Promise.reject(new Error('No constraints to retrieve the stream'));\n }\n\n return new Promise((resolve, reject) => {\n let lastSuccessfulResult: Nullable<MediaRequestSuccessResult> = null;\n let lastFailedResult: Nullable<MediaRequestFailResult> = null;\n let isStreamRequestFulfilled = false;\n\n (Promise as any).reduce(constraintsCandidates, (total: any, candidate: MediaStreamConstraints) => {\n if (isStreamRequestFulfilled) {\n return;\n }\n const constraintType = get(constraints, 'video.videoResolution.constraintType') || get(constraints, 'video.videoResolution[0].constraintType');\n\n return this.getStreamPromiseByParsedConstraints(candidate, isDesktopMedia)\n .then((stream: MediaStream) => {\n lastSuccessfulResult = {\n mediaStream: stream,\n constraint: candidate,\n constraintType,\n isNew: true\n };\n trace.info('getHighestResolutionStream Success', lastSuccessfulResult);\n isStreamRequestFulfilled = true;\n resolve(lastSuccessfulResult);\n })\n .catch((failResult: MediaRequestFailResult) => {\n lastFailedResult = failResult;\n if (lastFailedResult.errorCode === MediaRequestErrorCode.PermissionDenied) {\n isStreamRequestFulfilled = true;\n reject(lastFailedResult);\n }\n });\n }, 0)\n .then(() => {\n if (!isStreamRequestFulfilled) {\n if (!lastFailedResult) {\n lastFailedResult = {\n errorCode: MediaRequestErrorCode.GeneralError,\n message: 'Suitable stream cannot be created'\n };\n }\n reject(lastFailedResult);\n }\n });\n });\n }\n\n //@ts-ignore\n private getStreamPromiseByParsedConstraints(constraints: MediaStreamConstraints, isDesktopMedia: boolean): Promise<MediaStream> {\n let streamPromise = null;\n\n trace.info('getStreamPromiseByParsedConstraints', constraints);\n\n try {\n if (!isDesktopMedia) {\n streamPromise = navigator.mediaDevices.getUserMedia(constraints);\n } else {\n //@ts-ignore\n streamPromise = navigator.mediaDevices.getDisplayMedia\n //@ts-ignore\n ? navigator.mediaDevices.getDisplayMedia(constraints)\n : navigator.getDisplayMedia(constraints);\n }\n\n return streamPromise.catch(this.parseMediaErrorThenThrow);\n } catch (e) {\n this.parseMediaErrorThenThrow(e);\n }\n }\n\n private getParsedConstraints(isDesktopMedia: boolean, streamConstraints?: LocalMediaConstraints): MediaStreamConstraints[] {\n const constraintCandidates: MediaStreamConstraints[] = [];\n\n //TODO - Alex: need to understand which constraints not compatible with screen share\n if (isDesktopMedia) {\n return [{video: true}];\n }\n\n if (!streamConstraints) {\n return constraintCandidates;\n }\n\n const baseConstraints: MediaStreamConstraints = {};\n\n baseConstraints.audio = typeof streamConstraints.audio === 'boolean' ? streamConstraints.audio : undefined;\n\n if (!streamConstraints.video) {\n return [baseConstraints];\n }\n\n baseConstraints.video = {\n facingMode: 'environment',\n frameRate: {ideal: 15, max: 30}\n };\n\n const assignConstraint = (videoResolution: VideoStreamResolution): void => {\n const [width, height] = videoResolution.resolution.split('x');\n const constraintCandidate = assign({}, baseConstraints);\n\n constraintCandidate.video = assign({}, baseConstraints.video, {\n width: _constraintByType(width, videoResolution.constraintType),\n height: _constraintByType(height, videoResolution.constraintType)\n });\n constraintCandidates.push(constraintCandidate);\n };\n\n if ((baseConstraints.video && typeof streamConstraints.video === 'boolean') ||\n !((streamConstraints.video as LocalVideoStreamConstraints).videoResolution instanceof Array)) {\n\n const defaultResolution: VideoStreamResolution = {\n resolution: DEFAULT_VIDEO_RESOLUTION,\n constraintType: DEFAULT_VIDEO_CONSTRAINT_TYPE\n };\n\n assignConstraint(defaultResolution);\n\n return constraintCandidates;\n }\n\n (streamConstraints.video as any).videoResolution.forEach(assignConstraint);\n\n return constraintCandidates;\n }\n\n private parseMediaErrorThenThrow(error: any): MediaRequestFailResult {\n trace.error('Get media stream error.', error);\n const errorName = error && error.name ? error.name : '';\n\n const permissionErrorNames = [\n 'NotAllowedError',\n 'PermissionDismissedError',\n 'PermissionDeniedError'\n\n ];\n\n // const generalError = [\n // 'NotFoundError',\n // 'DevicesNotFoundError',\n // 'NotReadableError',\n // 'TrackStartError'\n // ];\n\n const constraintsErrors = [\n 'OverconstrainedError',\n 'ConstraintNotSatisfiedError'\n\n ];\n\n const isErrorOfType = (errorsArr: string[]) => errorsArr.filter((err: string) => err === errorName).length > 0;\n\n if (isErrorOfType(permissionErrorNames)) {\n throw {errorCode: MediaRequestErrorCode.PermissionDenied, message: errorName};\n }\n\n if (isErrorOfType(constraintsErrors)) {\n throw {errorCode: MediaRequestErrorCode.Overconstrained, message: errorName};\n }\n\n throw {errorCode: MediaRequestErrorCode.GeneralError, message: errorName};\n }\n}\n\nfunction _constraintByType(value: any, type: ConstraintType): any {\n switch (type) {\n case ConstraintType.MIN:\n return {min: value};\n default:\n return {ideal: value};\n }\n}\n"]}
@@ -23,7 +23,7 @@ window.latestUserMediaStream = null;
23
23
  var userMediaPromise = null;
24
24
  window.latestDesktopMediaStream = null;
25
25
  var desktopMediaPromise = null;
26
- var MediaTracer_1 = require("./Utils/MediaTracer");
26
+ var MediaTracer_1 = require("./MediaUtils/MediaTracer");
27
27
  var trace = MediaTracer_1.getMediaTracer('LocalStreamManager');
28
28
  var LocalStreamManager = /** @class */function () {
29
29
  function LocalStreamManager(environment) {
@@ -1 +1 @@
1
- {"version":3,"sources":["LocalStreamManager.js","../src/LocalStreamManager.ts"],"names":["__assign","Object","assign","t","s","i","n","arguments","length","p","prototype","hasOwnProperty","call","apply","__importDefault","mod","__esModule","defineProperty","exports","value","assign_1","require","get_1","MediaConstants_1","window","latestUserMediaStream","userMediaPromise","latestDesktopMediaStream","desktopMediaPromise","MediaTracer_1","trace","getMediaTracer","LocalStreamManager","environment","parseMediaErrorThenThrow","bind","clearAllStreams","getUserMediaStream","constraints","_this","info","videoTrack","mediaStream","getVideoTracks","readyState","Promise","resolve","isNew","destroyUserMediaStream","reject","catchHandler","err","error","getHighestResolutionStream","then","streamResult","catch","getDesktopMediaStream","track","destroyDesktopMediaStream","mediaCatchHandler","video","audio","getTracks","forEach","stop","all","undefined","isDesktopMedia","constraintsCandidates","getParsedConstraints","Error","lastSuccessfulResult","lastFailedResult","isStreamRequestFulfilled","reduce","total","candidate","constraintType","default","getStreamPromiseByParsedConstraints","stream","constraint","failResult","errorCode","MediaRequestErrorCode","PermissionDenied","GeneralError","message","streamPromise","navigator","mediaDevices","getUserMedia","getDisplayMedia","e","streamConstraints","constraintCandidates","baseConstraints","facingMode","frameRate","ideal","max","assignConstraint","videoResolution","_a","resolution","split","width","height","constraintCandidate","_constraintByType","push","Array","defaultResolution","DEFAULT_VIDEO_RESOLUTION","DEFAULT_VIDEO_CONSTRAINT_TYPE","errorName","name","permissionErrorNames","constraintsErrors","isErrorOfType","errorsArr","filter","Overconstrained","type","ConstraintType","MIN","min"],"mappings":"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","file":"LocalStreamManager.js","sourcesContent":["\"use strict\";\nvar __assign = (this && this.__assign) || function () {\n __assign = Object.assign || function(t) {\n for (var s, i = 1, n = arguments.length; i < n; i++) {\n s = arguments[i];\n for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))\n t[p] = s[p];\n }\n return t;\n };\n return __assign.apply(this, arguments);\n};\nvar __importDefault = (this && this.__importDefault) || function (mod) {\n return (mod && mod.__esModule) ? mod : { \"default\": mod };\n};\nObject.defineProperty(exports, \"__esModule\", { value: true });\nvar assign_1 = __importDefault(require(\"lodash/assign\"));\nvar get_1 = __importDefault(require(\"lodash/get\"));\nvar MediaConstants_1 = require(\"./MediaConstants\");\nwindow.latestUserMediaStream = null;\nvar userMediaPromise = null;\nwindow.latestDesktopMediaStream = null;\nvar desktopMediaPromise = null;\nvar MediaTracer_1 = require(\"./Utils/MediaTracer\");\nvar trace = MediaTracer_1.getMediaTracer('LocalStreamManager');\nvar LocalStreamManager = /** @class */ (function () {\n function LocalStreamManager(environment) {\n this.environment = environment;\n this.parseMediaErrorThenThrow = this.parseMediaErrorThenThrow.bind(this);\n this.clearAllStreams = this.clearAllStreams.bind(this);\n }\n LocalStreamManager.prototype.getUserMediaStream = function (constraints) {\n var _this = this;\n trace.info('getUserMediaStream', constraints);\n if (userMediaPromise) {\n return userMediaPromise;\n }\n if (window.latestUserMediaStream) {\n var videoTrack = window.latestUserMediaStream.mediaStream.getVideoTracks();\n if (videoTrack.length > 0 && videoTrack[0].readyState === 'live') {\n return Promise.resolve(__assign({}, window.latestUserMediaStream, { isNew: false }));\n }\n this.destroyUserMediaStream();\n }\n userMediaPromise = new Promise(function (resolve, reject) {\n var catchHandler = function (err) {\n userMediaPromise = null;\n window.latestUserMediaStream = null;\n trace.error('getUserMedia error', err);\n reject(err);\n };\n try {\n _this.getHighestResolutionStream(false, constraints)\n .then(function (streamResult) {\n userMediaPromise = null;\n window.latestUserMediaStream = streamResult;\n resolve(__assign({}, window.latestUserMediaStream, { isNew: true }));\n })\n .catch(catchHandler);\n }\n catch (err) {\n catchHandler(err);\n }\n });\n return userMediaPromise;\n };\n LocalStreamManager.prototype.getDesktopMediaStream = function (constraints) {\n var _this = this;\n if (desktopMediaPromise) {\n return desktopMediaPromise;\n }\n if (window.latestDesktopMediaStream) {\n var track = window.latestDesktopMediaStream.mediaStream.getVideoTracks();\n if (track.length > 0 && track[0].readyState === 'live') {\n //return Promise.resolve();\n return Promise.resolve(__assign({}, window.latestDesktopMediaStream, { isNew: false }));\n }\n this.destroyDesktopMediaStream().catch(function (error) {\n trace.error('Error destroying desktop media stream', error);\n });\n }\n desktopMediaPromise = new Promise(function (resolve, reject) {\n var mediaCatchHandler = function (err) {\n desktopMediaPromise = null;\n window.latestDesktopMediaStream = null;\n trace.error('getDisplayMedia error', err);\n reject(err);\n };\n try {\n _this.getHighestResolutionStream(true, { video: constraints, audio: false })\n .then(function (streamResult) {\n desktopMediaPromise = null;\n window.latestDesktopMediaStream = streamResult;\n resolve(__assign({}, window.latestDesktopMediaStream, { isNew: true }));\n }).catch(mediaCatchHandler);\n }\n catch (err) {\n mediaCatchHandler(err);\n }\n });\n return desktopMediaPromise;\n };\n LocalStreamManager.prototype.destroyUserMediaStream = function () {\n var streamResult = window.latestUserMediaStream;\n window.latestUserMediaStream = null;\n userMediaPromise = null;\n if (streamResult) {\n streamResult.mediaStream.getTracks().forEach(function (track) {\n track.stop();\n });\n }\n return Promise.resolve();\n };\n LocalStreamManager.prototype.destroyDesktopMediaStream = function () {\n var streamResult = window.latestDesktopMediaStream;\n window.latestDesktopMediaStream = null;\n desktopMediaPromise = null;\n if (streamResult) {\n streamResult.mediaStream.getTracks().forEach(function (track) {\n track.stop();\n });\n }\n return Promise.resolve();\n };\n LocalStreamManager.prototype.clearAllStreams = function () {\n trace.info('LocalStreamManager Clearing all streams');\n return Promise.all([\n this.destroyDesktopMediaStream(),\n this.destroyUserMediaStream()\n ]).then(function () { return undefined; });\n };\n LocalStreamManager.prototype.getHighestResolutionStream = function (isDesktopMedia, constraints) {\n var _this = this;\n var constraintsCandidates = this.getParsedConstraints(isDesktopMedia, constraints);\n if (constraintsCandidates.length === 0) {\n return Promise.reject(new Error('No constraints to retrieve the stream'));\n }\n return new Promise(function (resolve, reject) {\n var lastSuccessfulResult = null;\n var lastFailedResult = null;\n var isStreamRequestFulfilled = false;\n Promise.reduce(constraintsCandidates, function (total, candidate) {\n if (isStreamRequestFulfilled) {\n return;\n }\n var constraintType = get_1.default(constraints, 'video.videoResolution.constraintType') || get_1.default(constraints, 'video.videoResolution[0].constraintType');\n return _this.getStreamPromiseByParsedConstraints(candidate, isDesktopMedia)\n .then(function (stream) {\n lastSuccessfulResult = {\n mediaStream: stream,\n constraint: candidate,\n constraintType: constraintType,\n isNew: true\n };\n trace.info('getHighestResolutionStream Success', lastSuccessfulResult);\n isStreamRequestFulfilled = true;\n resolve(lastSuccessfulResult);\n })\n .catch(function (failResult) {\n lastFailedResult = failResult;\n if (lastFailedResult.errorCode === MediaConstants_1.MediaRequestErrorCode.PermissionDenied) {\n isStreamRequestFulfilled = true;\n reject(lastFailedResult);\n }\n });\n }, 0)\n .then(function () {\n if (!isStreamRequestFulfilled) {\n if (!lastFailedResult) {\n lastFailedResult = {\n errorCode: MediaConstants_1.MediaRequestErrorCode.GeneralError,\n message: 'Suitable stream cannot be created'\n };\n }\n reject(lastFailedResult);\n }\n });\n });\n };\n //@ts-ignore\n LocalStreamManager.prototype.getStreamPromiseByParsedConstraints = function (constraints, isDesktopMedia) {\n var streamPromise = null;\n trace.info('getStreamPromiseByParsedConstraints', constraints);\n try {\n if (!isDesktopMedia) {\n streamPromise = navigator.mediaDevices.getUserMedia(constraints);\n }\n else {\n //@ts-ignore\n streamPromise = navigator.mediaDevices.getDisplayMedia\n //@ts-ignore\n ? navigator.mediaDevices.getDisplayMedia(constraints)\n : navigator.getDisplayMedia(constraints);\n }\n return streamPromise.catch(this.parseMediaErrorThenThrow);\n }\n catch (e) {\n this.parseMediaErrorThenThrow(e);\n }\n };\n LocalStreamManager.prototype.getParsedConstraints = function (isDesktopMedia, streamConstraints) {\n var constraintCandidates = [];\n //TODO - Alex: need to understand which constraints not compatible with screen share\n if (isDesktopMedia) {\n return [{ video: true }];\n }\n if (!streamConstraints) {\n return constraintCandidates;\n }\n var baseConstraints = {};\n baseConstraints.audio = typeof streamConstraints.audio === 'boolean' ? streamConstraints.audio : undefined;\n if (!streamConstraints.video) {\n return [baseConstraints];\n }\n baseConstraints.video = {\n facingMode: 'environment',\n frameRate: { ideal: 15, max: 30 }\n };\n var assignConstraint = function (videoResolution) {\n var _a = videoResolution.resolution.split('x'), width = _a[0], height = _a[1];\n var constraintCandidate = assign_1.default({}, baseConstraints);\n constraintCandidate.video = assign_1.default({}, baseConstraints.video, {\n width: _constraintByType(width, videoResolution.constraintType),\n height: _constraintByType(height, videoResolution.constraintType)\n });\n constraintCandidates.push(constraintCandidate);\n };\n if ((baseConstraints.video && typeof streamConstraints.video === 'boolean') ||\n !(streamConstraints.video.videoResolution instanceof Array)) {\n var defaultResolution = {\n resolution: MediaConstants_1.DEFAULT_VIDEO_RESOLUTION,\n constraintType: MediaConstants_1.DEFAULT_VIDEO_CONSTRAINT_TYPE\n };\n assignConstraint(defaultResolution);\n return constraintCandidates;\n }\n streamConstraints.video.videoResolution.forEach(assignConstraint);\n return constraintCandidates;\n };\n LocalStreamManager.prototype.parseMediaErrorThenThrow = function (error) {\n trace.error('Get media stream error.', error);\n var errorName = error && error.name ? error.name : '';\n var permissionErrorNames = [\n 'NotAllowedError',\n 'PermissionDismissedError',\n 'PermissionDeniedError'\n ];\n // const generalError = [\n // 'NotFoundError',\n // 'DevicesNotFoundError',\n // 'NotReadableError',\n // 'TrackStartError'\n // ];\n var constraintsErrors = [\n 'OverconstrainedError',\n 'ConstraintNotSatisfiedError'\n ];\n var isErrorOfType = function (errorsArr) { return errorsArr.filter(function (err) { return err === errorName; }).length > 0; };\n if (isErrorOfType(permissionErrorNames)) {\n throw { errorCode: MediaConstants_1.MediaRequestErrorCode.PermissionDenied, message: errorName };\n }\n if (isErrorOfType(constraintsErrors)) {\n throw { errorCode: MediaConstants_1.MediaRequestErrorCode.Overconstrained, message: errorName };\n }\n throw { errorCode: MediaConstants_1.MediaRequestErrorCode.GeneralError, message: errorName };\n };\n return LocalStreamManager;\n}());\nexports.LocalStreamManager = LocalStreamManager;\nfunction _constraintByType(value, type) {\n switch (type) {\n case MediaConstants_1.ConstraintType.MIN:\n return { min: value };\n default:\n return { ideal: value };\n }\n}\n\n//# sourceMappingURL=LocalStreamManager.js.map\n","import assign from 'lodash/assign';\nimport get from 'lodash/get';\n\nimport {Nullable} from '@techsee/techsee-common';\n\nimport {\n VideoStreamResolution,\n LocalMediaConstraints,\n LocalVideoStreamConstraints,\n MediaRequestFailResult,\n MediaRequestSuccessResult,\n IMediaEnvironment\n} from './MediaContracts';\n\nimport {\n ConstraintType,\n DEFAULT_VIDEO_CONSTRAINT_TYPE,\n DEFAULT_VIDEO_RESOLUTION,\n MediaRequestErrorCode\n} from './MediaConstants';\n\ndeclare global {\n interface Window {\n latestUserMediaStream: Nullable<MediaRequestSuccessResult>;\n latestDesktopMediaStream: Nullable<MediaRequestSuccessResult>;\n }\n}\n\ndeclare const window: Window;\n\nwindow.latestUserMediaStream = null;\nlet userMediaPromise: Nullable<Promise<MediaRequestSuccessResult>> = null;\n\nwindow.latestDesktopMediaStream = null;\nlet desktopMediaPromise: Nullable<Promise<MediaRequestSuccessResult>> = null;\n\nimport {getMediaTracer} from './Utils/MediaTracer';\n\nconst trace = getMediaTracer('LocalStreamManager');\n\nexport class LocalStreamManager {\n private environment: IMediaEnvironment;\n\n constructor(environment: IMediaEnvironment) {\n this.environment = environment;\n\n this.parseMediaErrorThenThrow = this.parseMediaErrorThenThrow.bind(this);\n this.clearAllStreams = this.clearAllStreams.bind(this);\n }\n\n getUserMediaStream(constraints: LocalMediaConstraints): Promise<MediaRequestSuccessResult> {\n trace.info('getUserMediaStream', constraints);\n if (userMediaPromise) {\n return userMediaPromise;\n }\n\n if (window.latestUserMediaStream) {\n const videoTrack = window.latestUserMediaStream.mediaStream.getVideoTracks();\n\n if (videoTrack.length > 0 && videoTrack[0].readyState === 'live') {\n return Promise.resolve({...window.latestUserMediaStream, isNew: false});\n }\n this.destroyUserMediaStream();\n\n }\n\n\n userMediaPromise = new Promise((resolve, reject) => {\n const catchHandler = (err: any): void => {\n userMediaPromise = null;\n window.latestUserMediaStream = null;\n trace.error('getUserMedia error', err);\n reject(err);\n };\n\n try {\n this.getHighestResolutionStream(false, constraints)\n .then((streamResult: MediaRequestSuccessResult) => {\n userMediaPromise = null;\n window.latestUserMediaStream = streamResult;\n resolve({...window.latestUserMediaStream, isNew: true});\n })\n .catch(catchHandler);\n } catch (err) {\n catchHandler(err);\n }\n });\n\n return userMediaPromise;\n }\n\n getDesktopMediaStream(constraints: LocalVideoStreamConstraints): Promise<MediaRequestSuccessResult> {\n if (desktopMediaPromise) {\n return desktopMediaPromise;\n }\n\n if (window.latestDesktopMediaStream) {\n const track = window.latestDesktopMediaStream.mediaStream.getVideoTracks();\n\n if (track.length > 0 && track[0].readyState === 'live') {\n //return Promise.resolve();\n return Promise.resolve({...window.latestDesktopMediaStream, isNew: false});\n }\n this.destroyDesktopMediaStream().catch((error: any) => {\n trace.error('Error destroying desktop media stream', error);\n });\n\n }\n\n desktopMediaPromise = new Promise((resolve, reject) => {\n const mediaCatchHandler = (err: any): void => {\n desktopMediaPromise = null;\n window.latestDesktopMediaStream = null;\n trace.error('getDisplayMedia error', err);\n reject(err);\n };\n\n try {\n this.getHighestResolutionStream(true, {video: constraints, audio: false})\n .then((streamResult: MediaRequestSuccessResult) => {\n desktopMediaPromise = null;\n window.latestDesktopMediaStream = streamResult;\n\n resolve({...window.latestDesktopMediaStream, isNew: true});\n }).catch(mediaCatchHandler);\n } catch (err) {\n mediaCatchHandler(err);\n }\n });\n\n return desktopMediaPromise;\n }\n\n destroyUserMediaStream(): Promise<void> {\n const streamResult = window.latestUserMediaStream;\n\n window.latestUserMediaStream = null;\n userMediaPromise = null;\n\n if (streamResult) {\n streamResult.mediaStream.getTracks().forEach((track: MediaStreamTrack) => {\n track.stop();\n });\n }\n\n return Promise.resolve();\n }\n\n destroyDesktopMediaStream(): Promise<void> {\n const streamResult = window.latestDesktopMediaStream;\n\n window.latestDesktopMediaStream = null;\n desktopMediaPromise = null;\n\n if (streamResult) {\n streamResult.mediaStream.getTracks().forEach((track: MediaStreamTrack) => {\n track.stop();\n });\n }\n\n return Promise.resolve();\n }\n\n clearAllStreams(): Promise<void> {\n trace.info('LocalStreamManager Clearing all streams');\n\n return Promise.all([\n this.destroyDesktopMediaStream(),\n this.destroyUserMediaStream()\n ]).then(() => undefined);\n }\n\n private getHighestResolutionStream(isDesktopMedia: boolean, constraints?: LocalMediaConstraints): Promise<MediaRequestSuccessResult> {\n const constraintsCandidates = this.getParsedConstraints(isDesktopMedia, constraints);\n\n if (constraintsCandidates.length === 0) {\n return Promise.reject(new Error('No constraints to retrieve the stream'));\n }\n\n return new Promise((resolve, reject) => {\n let lastSuccessfulResult: Nullable<MediaRequestSuccessResult> = null;\n let lastFailedResult: Nullable<MediaRequestFailResult> = null;\n let isStreamRequestFulfilled = false;\n\n (Promise as any).reduce(constraintsCandidates, (total: any, candidate: MediaStreamConstraints) => {\n if (isStreamRequestFulfilled) {\n return;\n }\n const constraintType = get(constraints, 'video.videoResolution.constraintType') || get(constraints, 'video.videoResolution[0].constraintType');\n\n return this.getStreamPromiseByParsedConstraints(candidate, isDesktopMedia)\n .then((stream: MediaStream) => {\n lastSuccessfulResult = {\n mediaStream: stream,\n constraint: candidate,\n constraintType,\n isNew: true\n };\n trace.info('getHighestResolutionStream Success', lastSuccessfulResult);\n isStreamRequestFulfilled = true;\n resolve(lastSuccessfulResult);\n })\n .catch((failResult: MediaRequestFailResult) => {\n lastFailedResult = failResult;\n if (lastFailedResult.errorCode === MediaRequestErrorCode.PermissionDenied) {\n isStreamRequestFulfilled = true;\n reject(lastFailedResult);\n }\n });\n }, 0)\n .then(() => {\n if (!isStreamRequestFulfilled) {\n if (!lastFailedResult) {\n lastFailedResult = {\n errorCode: MediaRequestErrorCode.GeneralError,\n message: 'Suitable stream cannot be created'\n };\n }\n reject(lastFailedResult);\n }\n });\n });\n }\n\n //@ts-ignore\n private getStreamPromiseByParsedConstraints(constraints: MediaStreamConstraints, isDesktopMedia: boolean): Promise<MediaStream> {\n let streamPromise = null;\n\n trace.info('getStreamPromiseByParsedConstraints', constraints);\n\n try {\n if (!isDesktopMedia) {\n streamPromise = navigator.mediaDevices.getUserMedia(constraints);\n } else {\n //@ts-ignore\n streamPromise = navigator.mediaDevices.getDisplayMedia\n //@ts-ignore\n ? navigator.mediaDevices.getDisplayMedia(constraints)\n : navigator.getDisplayMedia(constraints);\n }\n\n return streamPromise.catch(this.parseMediaErrorThenThrow);\n } catch (e) {\n this.parseMediaErrorThenThrow(e);\n }\n }\n\n private getParsedConstraints(isDesktopMedia: boolean, streamConstraints?: LocalMediaConstraints): MediaStreamConstraints[] {\n const constraintCandidates: MediaStreamConstraints[] = [];\n\n //TODO - Alex: need to understand which constraints not compatible with screen share\n if (isDesktopMedia) {\n return [{video: true}];\n }\n\n if (!streamConstraints) {\n return constraintCandidates;\n }\n\n const baseConstraints: MediaStreamConstraints = {};\n\n baseConstraints.audio = typeof streamConstraints.audio === 'boolean' ? streamConstraints.audio : undefined;\n\n if (!streamConstraints.video) {\n return [baseConstraints];\n }\n\n baseConstraints.video = {\n facingMode: 'environment',\n frameRate: {ideal: 15, max: 30}\n };\n\n const assignConstraint = (videoResolution: VideoStreamResolution): void => {\n const [width, height] = videoResolution.resolution.split('x');\n const constraintCandidate = assign({}, baseConstraints);\n\n constraintCandidate.video = assign({}, baseConstraints.video, {\n width: _constraintByType(width, videoResolution.constraintType),\n height: _constraintByType(height, videoResolution.constraintType)\n });\n constraintCandidates.push(constraintCandidate);\n };\n\n if ((baseConstraints.video && typeof streamConstraints.video === 'boolean') ||\n !((streamConstraints.video as LocalVideoStreamConstraints).videoResolution instanceof Array)) {\n\n const defaultResolution: VideoStreamResolution = {\n resolution: DEFAULT_VIDEO_RESOLUTION,\n constraintType: DEFAULT_VIDEO_CONSTRAINT_TYPE\n };\n\n assignConstraint(defaultResolution);\n\n return constraintCandidates;\n }\n\n (streamConstraints.video as any).videoResolution.forEach(assignConstraint);\n\n return constraintCandidates;\n }\n\n private parseMediaErrorThenThrow(error: any): MediaRequestFailResult {\n trace.error('Get media stream error.', error);\n const errorName = error && error.name ? error.name : '';\n\n const permissionErrorNames = [\n 'NotAllowedError',\n 'PermissionDismissedError',\n 'PermissionDeniedError'\n\n ];\n\n // const generalError = [\n // 'NotFoundError',\n // 'DevicesNotFoundError',\n // 'NotReadableError',\n // 'TrackStartError'\n // ];\n\n const constraintsErrors = [\n 'OverconstrainedError',\n 'ConstraintNotSatisfiedError'\n\n ];\n\n const isErrorOfType = (errorsArr: string[]) => errorsArr.filter((err: string) => err === errorName).length > 0;\n\n if (isErrorOfType(permissionErrorNames)) {\n throw {errorCode: MediaRequestErrorCode.PermissionDenied, message: errorName};\n }\n\n if (isErrorOfType(constraintsErrors)) {\n throw {errorCode: MediaRequestErrorCode.Overconstrained, message: errorName};\n }\n\n throw {errorCode: MediaRequestErrorCode.GeneralError, message: errorName};\n }\n}\n\nfunction _constraintByType(value: any, type: ConstraintType): any {\n switch (type) {\n case ConstraintType.MIN:\n return {min: value};\n default:\n return {ideal: value};\n }\n}\n"]}
1
+ {"version":3,"sources":["LocalStreamManager.js","../src/LocalStreamManager.ts"],"names":["__assign","Object","assign","t","s","i","n","arguments","length","p","prototype","hasOwnProperty","call","apply","__importDefault","mod","__esModule","defineProperty","exports","value","assign_1","require","get_1","MediaConstants_1","window","latestUserMediaStream","userMediaPromise","latestDesktopMediaStream","desktopMediaPromise","MediaTracer_1","trace","getMediaTracer","LocalStreamManager","environment","parseMediaErrorThenThrow","bind","clearAllStreams","getUserMediaStream","constraints","_this","info","videoTrack","mediaStream","getVideoTracks","readyState","Promise","resolve","isNew","destroyUserMediaStream","reject","catchHandler","err","error","getHighestResolutionStream","then","streamResult","catch","getDesktopMediaStream","track","destroyDesktopMediaStream","mediaCatchHandler","video","audio","getTracks","forEach","stop","all","undefined","isDesktopMedia","constraintsCandidates","getParsedConstraints","Error","lastSuccessfulResult","lastFailedResult","isStreamRequestFulfilled","reduce","total","candidate","constraintType","default","getStreamPromiseByParsedConstraints","stream","constraint","failResult","errorCode","MediaRequestErrorCode","PermissionDenied","GeneralError","message","streamPromise","navigator","mediaDevices","getUserMedia","getDisplayMedia","e","streamConstraints","constraintCandidates","baseConstraints","facingMode","frameRate","ideal","max","assignConstraint","videoResolution","_a","resolution","split","width","height","constraintCandidate","_constraintByType","push","Array","defaultResolution","DEFAULT_VIDEO_RESOLUTION","DEFAULT_VIDEO_CONSTRAINT_TYPE","errorName","name","permissionErrorNames","constraintsErrors","isErrorOfType","errorsArr","filter","Overconstrained","type","ConstraintType","MIN","min"],"mappings":"AAAA;;AACA,IAAIA,WAAY,aAAQ,UAAKA,QAAd,IAA2B,YAAY;AAClDA,eAAWC,OAAOC,MAAP,IAAiB,UAASC,CAAT,EAAY;AACpC,aAAK,IAAIC,CAAJ,EAAOC,IAAI,CAAX,EAAcC,IAAIC,UAAUC,MAAjC,EAAyCH,IAAIC,CAA7C,EAAgDD,GAAhD,EAAqD;AACjDD,gBAAIG,UAAUF,CAAV,CAAJ;AACA,iBAAK,IAAII,CAAT,IAAcL,CAAd;AAAiB,oBAAIH,OAAOS,SAAP,CAAiBC,cAAjB,CAAgCC,IAAhC,CAAqCR,CAArC,EAAwCK,CAAxC,CAAJ,EACbN,EAAEM,CAAF,IAAOL,EAAEK,CAAF,CAAP;AADJ;AAEH;AACD,eAAON,CAAP;AACH,KAPD;AAQA,WAAOH,SAASa,KAAT,CAAe,IAAf,EAAqBN,SAArB,CAAP;AACH,CAVD;AAWA,IAAIO,kBAAmB,aAAQ,UAAKA,eAAd,IAAkC,UAAUC,GAAV,EAAe;AACnE,WAAQA,OAAOA,IAAIC,UAAZ,GAA0BD,GAA1B,GAAgC,EAAE,WAAWA,GAAb,EAAvC;AACH,CAFD;AAGAd,OAAOgB,cAAP,CAAsBC,OAAtB,EAA+B,YAA/B,EAA6C,EAAEC,OAAO,IAAT,EAA7C;ACfA,IAAAC,WAAAN,gBAAAO,QAAA,eAAA,CAAA,CAAA;AACA,IAAAC,QAAAR,gBAAAO,QAAA,YAAA,CAAA,CAAA;AAaA,IAAAE,mBAAAF,QAAA,kBAAA,CAAA;AAgBAG,OAAOC,qBAAP,GAA+B,IAA/B;AACA,IAAIC,mBAAiE,IAArE;AAEAF,OAAOG,wBAAP,GAAkC,IAAlC;AACA,IAAIC,sBAAoE,IAAxE;AAEA,IAAAC,gBAAAR,QAAA,0BAAA,CAAA;AAEA,IAAMS,QAAQD,cAAAE,cAAA,CAAe,oBAAf,CAAd;AAEA,IAAAC,qBAAA,aAAA,YAAA;AAGI,aAAAA,kBAAA,CAAYC,WAAZ,EAA0C;AACtC,aAAKA,WAAL,GAAmBA,WAAnB;AAEA,aAAKC,wBAAL,GAAgC,KAAKA,wBAAL,CAA8BC,IAA9B,CAAmC,IAAnC,CAAhC;AACA,aAAKC,eAAL,GAAuB,KAAKA,eAAL,CAAqBD,IAArB,CAA0B,IAA1B,CAAvB;AACH;AAEDH,uBAAAtB,SAAA,CAAA2B,kBAAA,GAAA,UAAmBC,WAAnB,EAAqD;AAArD,YAAAC,QAAA,IAAA;AACIT,cAAMU,IAAN,CAAW,oBAAX,EAAiCF,WAAjC;AACA,YAAIZ,gBAAJ,EAAsB;AAClB,mBAAOA,gBAAP;AACH;AAED,YAAIF,OAAOC,qBAAX,EAAkC;AAC9B,gBAAMgB,aAAajB,OAAOC,qBAAP,CAA6BiB,WAA7B,CAAyCC,cAAzC,EAAnB;AAEA,gBAAIF,WAAWjC,MAAX,GAAoB,CAApB,IAAyBiC,WAAW,CAAX,EAAcG,UAAd,KAA6B,MAA1D,EAAkE;AAC9D,uBAAOC,QAAQC,OAAR,CAAe9C,SAAA,EAAA,EAAKwB,OAAOC,qBAAZ,EAAiC,EAAEsB,OAAO,KAAT,EAAjC,CAAf,CAAP;AACH;AACD,iBAAKC,sBAAL;AAEH;AAGDtB,2BAAmB,IAAImB,OAAJ,CAAY,UAACC,OAAD,EAAUG,MAAV,EAAgB;AAC3C,gBAAMC,eAAe,SAAfA,YAAe,CAACC,GAAD,EAAS;AAC1BzB,mCAAmB,IAAnB;AACAF,uBAAOC,qBAAP,GAA+B,IAA/B;AACAK,sBAAMsB,KAAN,CAAY,oBAAZ,EAAkCD,GAAlC;AACAF,uBAAOE,GAAP;AACH,aALD;AAOA,gBAAI;AACAZ,sBAAKc,0BAAL,CAAgC,KAAhC,EAAuCf,WAAvC,EACKgB,IADL,CACU,UAACC,YAAD,EAAwC;AAC1C7B,uCAAmB,IAAnB;AACAF,2BAAOC,qBAAP,GAA+B8B,YAA/B;AACAT,4BAAO9C,SAAA,EAAA,EAAKwB,OAAOC,qBAAZ,EAAiC,EAAEsB,OAAO,IAAT,EAAjC,CAAP;AACH,iBALL,EAMKS,KANL,CAMWN,YANX;AAOH,aARD,CAQE,OAAOC,GAAP,EAAY;AACVD,6BAAaC,GAAb;AACH;AACJ,SAnBkB,CAAnB;AAqBA,eAAOzB,gBAAP;AACH,KAvCD;AAyCAM,uBAAAtB,SAAA,CAAA+C,qBAAA,GAAA,UAAsBnB,WAAtB,EAA8D;AAA9D,YAAAC,QAAA,IAAA;AACI,YAAIX,mBAAJ,EAAyB;AACrB,mBAAOA,mBAAP;AACH;AAED,YAAIJ,OAAOG,wBAAX,EAAqC;AACjC,gBAAM+B,QAAQlC,OAAOG,wBAAP,CAAgCe,WAAhC,CAA4CC,cAA5C,EAAd;AAEA,gBAAIe,MAAMlD,MAAN,GAAe,CAAf,IAAoBkD,MAAM,CAAN,EAASd,UAAT,KAAwB,MAAhD,EAAwD;AACpD;AACA,uBAAOC,QAAQC,OAAR,CAAe9C,SAAA,EAAA,EAAKwB,OAAOG,wBAAZ,EAAoC,EAAEoB,OAAO,KAAT,EAApC,CAAf,CAAP;AACH;AACD,iBAAKY,yBAAL,GAAiCH,KAAjC,CAAuC,UAACJ,KAAD,EAAW;AAC9CtB,sBAAMsB,KAAN,CAAY,uCAAZ,EAAqDA,KAArD;AACH,aAFD;AAIH;AAEDxB,8BAAsB,IAAIiB,OAAJ,CAAY,UAACC,OAAD,EAAUG,MAAV,EAAgB;AAC9C,gBAAMW,oBAAoB,SAApBA,iBAAoB,CAACT,GAAD,EAAS;AAC/BvB,sCAAsB,IAAtB;AACAJ,uBAAOG,wBAAP,GAAkC,IAAlC;AACAG,sBAAMsB,KAAN,CAAY,uBAAZ,EAAqCD,GAArC;AACAF,uBAAOE,GAAP;AACH,aALD;AAOA,gBAAI;AACAZ,sBAAKc,0BAAL,CAAgC,IAAhC,EAAsC,EAACQ,OAAOvB,WAAR,EAAqBwB,OAAO,KAA5B,EAAtC,EACKR,IADL,CACU,UAACC,YAAD,EAAwC;AAC1C3B,0CAAsB,IAAtB;AACAJ,2BAAOG,wBAAP,GAAkC4B,YAAlC;AAEAT,4BAAO9C,SAAA,EAAA,EAAKwB,OAAOG,wBAAZ,EAAoC,EAAEoB,OAAO,IAAT,EAApC,CAAP;AACH,iBANL,EAMOS,KANP,CAMaI,iBANb;AAOH,aARD,CAQE,OAAOT,GAAP,EAAY;AACVS,kCAAkBT,GAAlB;AACH;AACJ,SAnBqB,CAAtB;AAqBA,eAAOvB,mBAAP;AACH,KAxCD;AA0CAI,uBAAAtB,SAAA,CAAAsC,sBAAA,GAAA,YAAA;AACI,YAAMO,eAAe/B,OAAOC,qBAA5B;AAEAD,eAAOC,qBAAP,GAA+B,IAA/B;AACAC,2BAAmB,IAAnB;AAEA,YAAI6B,YAAJ,EAAkB;AACdA,yBAAab,WAAb,CAAyBqB,SAAzB,GAAqCC,OAArC,CAA6C,UAACN,KAAD,EAAwB;AACjEA,sBAAMO,IAAN;AACH,aAFD;AAGH;AAED,eAAOpB,QAAQC,OAAR,EAAP;AACH,KAbD;AAeAd,uBAAAtB,SAAA,CAAAiD,yBAAA,GAAA,YAAA;AACI,YAAMJ,eAAe/B,OAAOG,wBAA5B;AAEAH,eAAOG,wBAAP,GAAkC,IAAlC;AACAC,8BAAsB,IAAtB;AAEA,YAAI2B,YAAJ,EAAkB;AACdA,yBAAab,WAAb,CAAyBqB,SAAzB,GAAqCC,OAArC,CAA6C,UAACN,KAAD,EAAwB;AACjEA,sBAAMO,IAAN;AACH,aAFD;AAGH;AAED,eAAOpB,QAAQC,OAAR,EAAP;AACH,KAbD;AAeAd,uBAAAtB,SAAA,CAAA0B,eAAA,GAAA,YAAA;AACIN,cAAMU,IAAN,CAAW,yCAAX;AAEA,eAAOK,QAAQqB,GAAR,CAAY,CACf,KAAKP,yBAAL,EADe,EAEf,KAAKX,sBAAL,EAFe,CAAZ,EAGJM,IAHI,CAGC,YAAA;AAAM,mBAAAa,SAAA;AAAS,SAHhB,CAAP;AAIH,KAPD;AASQnC,uBAAAtB,SAAA,CAAA2C,0BAAA,GAAR,UAAmCe,cAAnC,EAA4D9B,WAA5D,EAA+F;AAA/F,YAAAC,QAAA,IAAA;AACI,YAAM8B,wBAAwB,KAAKC,oBAAL,CAA0BF,cAA1B,EAA0C9B,WAA1C,CAA9B;AAEA,YAAI+B,sBAAsB7D,MAAtB,KAAiC,CAArC,EAAwC;AACpC,mBAAOqC,QAAQI,MAAR,CAAe,IAAIsB,KAAJ,CAAU,uCAAV,CAAf,CAAP;AACH;AAED,eAAO,IAAI1B,OAAJ,CAAY,UAACC,OAAD,EAAUG,MAAV,EAAgB;AAC/B,gBAAIuB,uBAA4D,IAAhE;AACA,gBAAIC,mBAAqD,IAAzD;AACA,gBAAIC,2BAA2B,KAA/B;AAEC7B,oBAAgB8B,MAAhB,CAAuBN,qBAAvB,EAA8C,UAACO,KAAD,EAAaC,SAAb,EAA8C;AACzF,oBAAIH,wBAAJ,EAA8B;AAC1B;AACH;AACD,oBAAMI,iBAAiBxD,MAAAyD,OAAA,CAAIzC,WAAJ,EAAiB,sCAAjB,KAA4DhB,MAAAyD,OAAA,CAAIzC,WAAJ,EAAiB,yCAAjB,CAAnF;AAEA,uBAAOC,MAAKyC,mCAAL,CAAyCH,SAAzC,EAAoDT,cAApD,EACFd,IADE,CACG,UAAC2B,MAAD,EAAoB;AACtBT,2CAAuB;AACnB9B,qCAAauC,MADM;AAEnBC,oCAAYL,SAFO;AAGnBC,wCAAcA,cAHK;AAInB/B,+BAAO;AAJY,qBAAvB;AAMAjB,0BAAMU,IAAN,CAAW,oCAAX,EAAiDgC,oBAAjD;AACAE,+CAA2B,IAA3B;AACA5B,4BAAQ0B,oBAAR;AACH,iBAXE,EAYFhB,KAZE,CAYI,UAAC2B,UAAD,EAAmC;AACtCV,uCAAmBU,UAAnB;AACA,wBAAIV,iBAAiBW,SAAjB,KAA+B7D,iBAAA8D,qBAAA,CAAsBC,gBAAzD,EAA2E;AACvEZ,mDAA2B,IAA3B;AACAzB,+BAAOwB,gBAAP;AACH;AACJ,iBAlBE,CAAP;AAmBH,aAzBA,EAyBE,CAzBF,EA0BInB,IA1BJ,CA0BS,YAAA;AACF,oBAAI,CAACoB,wBAAL,EAA+B;AAC3B,wBAAI,CAACD,gBAAL,EAAuB;AACnBA,2CAAmB;AACfW,uCAAW7D,iBAAA8D,qBAAA,CAAsBE,YADlB;AAEfC,qCAAS;AAFM,yBAAnB;AAIH;AACDvC,2BAAOwB,gBAAP;AACH;AACJ,aApCJ;AAqCJ,SA1CM,CAAP;AA2CH,KAlDO;AAoDR;AACQzC,uBAAAtB,SAAA,CAAAsE,mCAAA,GAAR,UAA4C1C,WAA5C,EAAiF8B,cAAjF,EAAwG;AACpG,YAAIqB,gBAAgB,IAApB;AAEA3D,cAAMU,IAAN,CAAW,qCAAX,EAAkDF,WAAlD;AAEA,YAAI;AACA,gBAAI,CAAC8B,cAAL,EAAqB;AACjBqB,gCAAgBC,UAAUC,YAAV,CAAuBC,YAAvB,CAAoCtD,WAApC,CAAhB;AACH,aAFD,MAEO;AACH;AACAmD,gCAAgBC,UAAUC,YAAV,CAAuBE;AACnC;AADY,kBAEVH,UAAUC,YAAV,CAAuBE,eAAvB,CAAuCvD,WAAvC,CAFU,GAGVoD,UAAUG,eAAV,CAA0BvD,WAA1B,CAHN;AAIH;AAED,mBAAOmD,cAAcjC,KAAd,CAAoB,KAAKtB,wBAAzB,CAAP;AACH,SAZD,CAYE,OAAO4D,CAAP,EAAU;AACR,iBAAK5D,wBAAL,CAA8B4D,CAA9B;AACH;AACJ,KApBO;AAsBA9D,uBAAAtB,SAAA,CAAA4D,oBAAA,GAAR,UAA6BF,cAA7B,EAAsD2B,iBAAtD,EAA+F;AAC3F,YAAMC,uBAAiD,EAAvD;AAEA;AACA,YAAI5B,cAAJ,EAAoB;AAChB,mBAAO,CAAC,EAACP,OAAO,IAAR,EAAD,CAAP;AACH;AAED,YAAI,CAACkC,iBAAL,EAAwB;AACpB,mBAAOC,oBAAP;AACH;AAED,YAAMC,kBAA0C,EAAhD;AAEAA,wBAAgBnC,KAAhB,GAAwB,OAAOiC,kBAAkBjC,KAAzB,KAAmC,SAAnC,GAA+CiC,kBAAkBjC,KAAjE,GAAyEK,SAAjG;AAEA,YAAI,CAAC4B,kBAAkBlC,KAAvB,EAA8B;AAC1B,mBAAO,CAACoC,eAAD,CAAP;AACH;AAEDA,wBAAgBpC,KAAhB,GAAwB;AACpBqC,wBAAY,aADQ;AAEpBC,uBAAW,EAACC,OAAO,EAAR,EAAYC,KAAK,EAAjB;AAFS,SAAxB;AAKA,YAAMC,mBAAmB,SAAnBA,gBAAmB,CAACC,eAAD,EAAuC;AACtD,gBAAAC,KAAAD,gBAAAE,UAAA,CAAAC,KAAA,CAAA,GAAA,CAAA;AAAA,gBAACC,QAAAH,GAAA,CAAA,CAAD;AAAA,gBAAQI,SAAAJ,GAAA,CAAA,CAAR;AACN,gBAAMK,sBAAsBzF,SAAA2D,OAAA,CAAO,EAAP,EAAWkB,eAAX,CAA5B;AAEAY,gCAAoBhD,KAApB,GAA4BzC,SAAA2D,OAAA,CAAO,EAAP,EAAWkB,gBAAgBpC,KAA3B,EAAkC;AAC1D8C,uBAAOG,kBAAkBH,KAAlB,EAAyBJ,gBAAgBzB,cAAzC,CADmD;AAE1D8B,wBAAQE,kBAAkBF,MAAlB,EAA0BL,gBAAgBzB,cAA1C;AAFkD,aAAlC,CAA5B;AAIAkB,iCAAqBe,IAArB,CAA0BF,mBAA1B;AACH,SATD;AAWA,YAAKZ,gBAAgBpC,KAAhB,IAAyB,OAAOkC,kBAAkBlC,KAAzB,KAAmC,SAA7D,IACA,EAAGkC,kBAAkBlC,KAAlB,CAAwD0C,eAAxD,YAAmFS,KAAtF,CADJ,EACkG;AAE9F,gBAAMC,oBAA2C;AAC7CR,4BAAYlF,iBAAA2F,wBADiC;AAE7CpC,gCAAgBvD,iBAAA4F;AAF6B,aAAjD;AAKAb,6BAAiBW,iBAAjB;AAEA,mBAAOjB,oBAAP;AACH;AAEAD,0BAAkBlC,KAAlB,CAAgC0C,eAAhC,CAAgDvC,OAAhD,CAAwDsC,gBAAxD;AAED,eAAON,oBAAP;AACH,KApDO;AAsDAhE,uBAAAtB,SAAA,CAAAwB,wBAAA,GAAR,UAAiCkB,KAAjC,EAA2C;AACvCtB,cAAMsB,KAAN,CAAY,yBAAZ,EAAuCA,KAAvC;AACA,YAAMgE,YAAYhE,SAASA,MAAMiE,IAAf,GAAsBjE,MAAMiE,IAA5B,GAAmC,EAArD;AAEA,YAAMC,uBAAuB,CACzB,iBADyB,EAEzB,0BAFyB,EAGzB,uBAHyB,CAA7B;AAOA;AACA;AACA;AACA;AACA;AACA;AAEA,YAAMC,oBAAoB,CACtB,sBADsB,EAEtB,6BAFsB,CAA1B;AAMA,YAAMC,gBAAgB,SAAhBA,aAAgB,CAACC,SAAD,EAAoB;AAAK,mBAAAA,UAAUC,MAAV,CAAiB,UAACvE,GAAD,EAAY;AAAK,uBAAAA,QAAQiE,SAAR;AAAiB,aAAnD,EAAqD5G,MAArD,GAA8D,CAA9D;AAA+D,SAA9G;AAEA,YAAIgH,cAAcF,oBAAd,CAAJ,EAAyC;AACrC,kBAAM,EAAClC,WAAW7D,iBAAA8D,qBAAA,CAAsBC,gBAAlC,EAAoDE,SAAS4B,SAA7D,EAAN;AACH;AAED,YAAII,cAAcD,iBAAd,CAAJ,EAAsC;AAClC,kBAAM,EAACnC,WAAW7D,iBAAA8D,qBAAA,CAAsBsC,eAAlC,EAAmDnC,SAAS4B,SAA5D,EAAN;AACH;AAED,cAAM,EAAChC,WAAW7D,iBAAA8D,qBAAA,CAAsBE,YAAlC,EAAgDC,SAAS4B,SAAzD,EAAN;AACH,KAnCO;AAoCZ,WAAApF,kBAAA;AAzSA,CAAA,EAAA;AAAad,QAAAc,kBAAA,GAAAA,kBAAA;AA2Sb,SAAS8E,iBAAT,CAA2B3F,KAA3B,EAAuCyG,IAAvC,EAA2D;AACvD,YAAQA,IAAR;AACI,aAAKrG,iBAAAsG,cAAA,CAAeC,GAApB;AACI,mBAAO,EAACC,KAAK5G,KAAN,EAAP;AACJ;AACI,mBAAO,EAACiF,OAAOjF,KAAR,EAAP;AAJR;AAMH;;ADpED","file":"LocalStreamManager.js","sourcesContent":["\"use strict\";\nvar __assign = (this && this.__assign) || function () {\n __assign = Object.assign || function(t) {\n for (var s, i = 1, n = arguments.length; i < n; i++) {\n s = arguments[i];\n for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))\n t[p] = s[p];\n }\n return t;\n };\n return __assign.apply(this, arguments);\n};\nvar __importDefault = (this && this.__importDefault) || function (mod) {\n return (mod && mod.__esModule) ? mod : { \"default\": mod };\n};\nObject.defineProperty(exports, \"__esModule\", { value: true });\nvar assign_1 = __importDefault(require(\"lodash/assign\"));\nvar get_1 = __importDefault(require(\"lodash/get\"));\nvar MediaConstants_1 = require(\"./MediaConstants\");\nwindow.latestUserMediaStream = null;\nvar userMediaPromise = null;\nwindow.latestDesktopMediaStream = null;\nvar desktopMediaPromise = null;\nvar MediaTracer_1 = require(\"./MediaUtils/MediaTracer\");\nvar trace = MediaTracer_1.getMediaTracer('LocalStreamManager');\nvar LocalStreamManager = /** @class */ (function () {\n function LocalStreamManager(environment) {\n this.environment = environment;\n this.parseMediaErrorThenThrow = this.parseMediaErrorThenThrow.bind(this);\n this.clearAllStreams = this.clearAllStreams.bind(this);\n }\n LocalStreamManager.prototype.getUserMediaStream = function (constraints) {\n var _this = this;\n trace.info('getUserMediaStream', constraints);\n if (userMediaPromise) {\n return userMediaPromise;\n }\n if (window.latestUserMediaStream) {\n var videoTrack = window.latestUserMediaStream.mediaStream.getVideoTracks();\n if (videoTrack.length > 0 && videoTrack[0].readyState === 'live') {\n return Promise.resolve(__assign({}, window.latestUserMediaStream, { isNew: false }));\n }\n this.destroyUserMediaStream();\n }\n userMediaPromise = new Promise(function (resolve, reject) {\n var catchHandler = function (err) {\n userMediaPromise = null;\n window.latestUserMediaStream = null;\n trace.error('getUserMedia error', err);\n reject(err);\n };\n try {\n _this.getHighestResolutionStream(false, constraints)\n .then(function (streamResult) {\n userMediaPromise = null;\n window.latestUserMediaStream = streamResult;\n resolve(__assign({}, window.latestUserMediaStream, { isNew: true }));\n })\n .catch(catchHandler);\n }\n catch (err) {\n catchHandler(err);\n }\n });\n return userMediaPromise;\n };\n LocalStreamManager.prototype.getDesktopMediaStream = function (constraints) {\n var _this = this;\n if (desktopMediaPromise) {\n return desktopMediaPromise;\n }\n if (window.latestDesktopMediaStream) {\n var track = window.latestDesktopMediaStream.mediaStream.getVideoTracks();\n if (track.length > 0 && track[0].readyState === 'live') {\n //return Promise.resolve();\n return Promise.resolve(__assign({}, window.latestDesktopMediaStream, { isNew: false }));\n }\n this.destroyDesktopMediaStream().catch(function (error) {\n trace.error('Error destroying desktop media stream', error);\n });\n }\n desktopMediaPromise = new Promise(function (resolve, reject) {\n var mediaCatchHandler = function (err) {\n desktopMediaPromise = null;\n window.latestDesktopMediaStream = null;\n trace.error('getDisplayMedia error', err);\n reject(err);\n };\n try {\n _this.getHighestResolutionStream(true, { video: constraints, audio: false })\n .then(function (streamResult) {\n desktopMediaPromise = null;\n window.latestDesktopMediaStream = streamResult;\n resolve(__assign({}, window.latestDesktopMediaStream, { isNew: true }));\n }).catch(mediaCatchHandler);\n }\n catch (err) {\n mediaCatchHandler(err);\n }\n });\n return desktopMediaPromise;\n };\n LocalStreamManager.prototype.destroyUserMediaStream = function () {\n var streamResult = window.latestUserMediaStream;\n window.latestUserMediaStream = null;\n userMediaPromise = null;\n if (streamResult) {\n streamResult.mediaStream.getTracks().forEach(function (track) {\n track.stop();\n });\n }\n return Promise.resolve();\n };\n LocalStreamManager.prototype.destroyDesktopMediaStream = function () {\n var streamResult = window.latestDesktopMediaStream;\n window.latestDesktopMediaStream = null;\n desktopMediaPromise = null;\n if (streamResult) {\n streamResult.mediaStream.getTracks().forEach(function (track) {\n track.stop();\n });\n }\n return Promise.resolve();\n };\n LocalStreamManager.prototype.clearAllStreams = function () {\n trace.info('LocalStreamManager Clearing all streams');\n return Promise.all([\n this.destroyDesktopMediaStream(),\n this.destroyUserMediaStream()\n ]).then(function () { return undefined; });\n };\n LocalStreamManager.prototype.getHighestResolutionStream = function (isDesktopMedia, constraints) {\n var _this = this;\n var constraintsCandidates = this.getParsedConstraints(isDesktopMedia, constraints);\n if (constraintsCandidates.length === 0) {\n return Promise.reject(new Error('No constraints to retrieve the stream'));\n }\n return new Promise(function (resolve, reject) {\n var lastSuccessfulResult = null;\n var lastFailedResult = null;\n var isStreamRequestFulfilled = false;\n Promise.reduce(constraintsCandidates, function (total, candidate) {\n if (isStreamRequestFulfilled) {\n return;\n }\n var constraintType = get_1.default(constraints, 'video.videoResolution.constraintType') || get_1.default(constraints, 'video.videoResolution[0].constraintType');\n return _this.getStreamPromiseByParsedConstraints(candidate, isDesktopMedia)\n .then(function (stream) {\n lastSuccessfulResult = {\n mediaStream: stream,\n constraint: candidate,\n constraintType: constraintType,\n isNew: true\n };\n trace.info('getHighestResolutionStream Success', lastSuccessfulResult);\n isStreamRequestFulfilled = true;\n resolve(lastSuccessfulResult);\n })\n .catch(function (failResult) {\n lastFailedResult = failResult;\n if (lastFailedResult.errorCode === MediaConstants_1.MediaRequestErrorCode.PermissionDenied) {\n isStreamRequestFulfilled = true;\n reject(lastFailedResult);\n }\n });\n }, 0)\n .then(function () {\n if (!isStreamRequestFulfilled) {\n if (!lastFailedResult) {\n lastFailedResult = {\n errorCode: MediaConstants_1.MediaRequestErrorCode.GeneralError,\n message: 'Suitable stream cannot be created'\n };\n }\n reject(lastFailedResult);\n }\n });\n });\n };\n //@ts-ignore\n LocalStreamManager.prototype.getStreamPromiseByParsedConstraints = function (constraints, isDesktopMedia) {\n var streamPromise = null;\n trace.info('getStreamPromiseByParsedConstraints', constraints);\n try {\n if (!isDesktopMedia) {\n streamPromise = navigator.mediaDevices.getUserMedia(constraints);\n }\n else {\n //@ts-ignore\n streamPromise = navigator.mediaDevices.getDisplayMedia\n //@ts-ignore\n ? navigator.mediaDevices.getDisplayMedia(constraints)\n : navigator.getDisplayMedia(constraints);\n }\n return streamPromise.catch(this.parseMediaErrorThenThrow);\n }\n catch (e) {\n this.parseMediaErrorThenThrow(e);\n }\n };\n LocalStreamManager.prototype.getParsedConstraints = function (isDesktopMedia, streamConstraints) {\n var constraintCandidates = [];\n //TODO - Alex: need to understand which constraints not compatible with screen share\n if (isDesktopMedia) {\n return [{ video: true }];\n }\n if (!streamConstraints) {\n return constraintCandidates;\n }\n var baseConstraints = {};\n baseConstraints.audio = typeof streamConstraints.audio === 'boolean' ? streamConstraints.audio : undefined;\n if (!streamConstraints.video) {\n return [baseConstraints];\n }\n baseConstraints.video = {\n facingMode: 'environment',\n frameRate: { ideal: 15, max: 30 }\n };\n var assignConstraint = function (videoResolution) {\n var _a = videoResolution.resolution.split('x'), width = _a[0], height = _a[1];\n var constraintCandidate = assign_1.default({}, baseConstraints);\n constraintCandidate.video = assign_1.default({}, baseConstraints.video, {\n width: _constraintByType(width, videoResolution.constraintType),\n height: _constraintByType(height, videoResolution.constraintType)\n });\n constraintCandidates.push(constraintCandidate);\n };\n if ((baseConstraints.video && typeof streamConstraints.video === 'boolean') ||\n !(streamConstraints.video.videoResolution instanceof Array)) {\n var defaultResolution = {\n resolution: MediaConstants_1.DEFAULT_VIDEO_RESOLUTION,\n constraintType: MediaConstants_1.DEFAULT_VIDEO_CONSTRAINT_TYPE\n };\n assignConstraint(defaultResolution);\n return constraintCandidates;\n }\n streamConstraints.video.videoResolution.forEach(assignConstraint);\n return constraintCandidates;\n };\n LocalStreamManager.prototype.parseMediaErrorThenThrow = function (error) {\n trace.error('Get media stream error.', error);\n var errorName = error && error.name ? error.name : '';\n var permissionErrorNames = [\n 'NotAllowedError',\n 'PermissionDismissedError',\n 'PermissionDeniedError'\n ];\n // const generalError = [\n // 'NotFoundError',\n // 'DevicesNotFoundError',\n // 'NotReadableError',\n // 'TrackStartError'\n // ];\n var constraintsErrors = [\n 'OverconstrainedError',\n 'ConstraintNotSatisfiedError'\n ];\n var isErrorOfType = function (errorsArr) { return errorsArr.filter(function (err) { return err === errorName; }).length > 0; };\n if (isErrorOfType(permissionErrorNames)) {\n throw { errorCode: MediaConstants_1.MediaRequestErrorCode.PermissionDenied, message: errorName };\n }\n if (isErrorOfType(constraintsErrors)) {\n throw { errorCode: MediaConstants_1.MediaRequestErrorCode.Overconstrained, message: errorName };\n }\n throw { errorCode: MediaConstants_1.MediaRequestErrorCode.GeneralError, message: errorName };\n };\n return LocalStreamManager;\n}());\nexports.LocalStreamManager = LocalStreamManager;\nfunction _constraintByType(value, type) {\n switch (type) {\n case MediaConstants_1.ConstraintType.MIN:\n return { min: value };\n default:\n return { ideal: value };\n }\n}\n\n//# sourceMappingURL=LocalStreamManager.js.map\n","import assign from 'lodash/assign';\nimport get from 'lodash/get';\n\nimport {Nullable} from '@techsee/techsee-common';\n\nimport {\n VideoStreamResolution,\n LocalMediaConstraints,\n LocalVideoStreamConstraints,\n MediaRequestFailResult,\n MediaRequestSuccessResult,\n IMediaEnvironment\n} from './MediaContracts';\n\nimport {\n ConstraintType,\n DEFAULT_VIDEO_CONSTRAINT_TYPE,\n DEFAULT_VIDEO_RESOLUTION,\n MediaRequestErrorCode\n} from './MediaConstants';\n\ndeclare global {\n interface Window {\n latestUserMediaStream: Nullable<MediaRequestSuccessResult>;\n latestDesktopMediaStream: Nullable<MediaRequestSuccessResult>;\n }\n}\n\ndeclare const window: Window;\n\nwindow.latestUserMediaStream = null;\nlet userMediaPromise: Nullable<Promise<MediaRequestSuccessResult>> = null;\n\nwindow.latestDesktopMediaStream = null;\nlet desktopMediaPromise: Nullable<Promise<MediaRequestSuccessResult>> = null;\n\nimport {getMediaTracer} from './MediaUtils/MediaTracer';\n\nconst trace = getMediaTracer('LocalStreamManager');\n\nexport class LocalStreamManager {\n private environment: IMediaEnvironment;\n\n constructor(environment: IMediaEnvironment) {\n this.environment = environment;\n\n this.parseMediaErrorThenThrow = this.parseMediaErrorThenThrow.bind(this);\n this.clearAllStreams = this.clearAllStreams.bind(this);\n }\n\n getUserMediaStream(constraints: LocalMediaConstraints): Promise<MediaRequestSuccessResult> {\n trace.info('getUserMediaStream', constraints);\n if (userMediaPromise) {\n return userMediaPromise;\n }\n\n if (window.latestUserMediaStream) {\n const videoTrack = window.latestUserMediaStream.mediaStream.getVideoTracks();\n\n if (videoTrack.length > 0 && videoTrack[0].readyState === 'live') {\n return Promise.resolve({...window.latestUserMediaStream, isNew: false});\n }\n this.destroyUserMediaStream();\n\n }\n\n\n userMediaPromise = new Promise((resolve, reject) => {\n const catchHandler = (err: any): void => {\n userMediaPromise = null;\n window.latestUserMediaStream = null;\n trace.error('getUserMedia error', err);\n reject(err);\n };\n\n try {\n this.getHighestResolutionStream(false, constraints)\n .then((streamResult: MediaRequestSuccessResult) => {\n userMediaPromise = null;\n window.latestUserMediaStream = streamResult;\n resolve({...window.latestUserMediaStream, isNew: true});\n })\n .catch(catchHandler);\n } catch (err) {\n catchHandler(err);\n }\n });\n\n return userMediaPromise;\n }\n\n getDesktopMediaStream(constraints: LocalVideoStreamConstraints): Promise<MediaRequestSuccessResult> {\n if (desktopMediaPromise) {\n return desktopMediaPromise;\n }\n\n if (window.latestDesktopMediaStream) {\n const track = window.latestDesktopMediaStream.mediaStream.getVideoTracks();\n\n if (track.length > 0 && track[0].readyState === 'live') {\n //return Promise.resolve();\n return Promise.resolve({...window.latestDesktopMediaStream, isNew: false});\n }\n this.destroyDesktopMediaStream().catch((error: any) => {\n trace.error('Error destroying desktop media stream', error);\n });\n\n }\n\n desktopMediaPromise = new Promise((resolve, reject) => {\n const mediaCatchHandler = (err: any): void => {\n desktopMediaPromise = null;\n window.latestDesktopMediaStream = null;\n trace.error('getDisplayMedia error', err);\n reject(err);\n };\n\n try {\n this.getHighestResolutionStream(true, {video: constraints, audio: false})\n .then((streamResult: MediaRequestSuccessResult) => {\n desktopMediaPromise = null;\n window.latestDesktopMediaStream = streamResult;\n\n resolve({...window.latestDesktopMediaStream, isNew: true});\n }).catch(mediaCatchHandler);\n } catch (err) {\n mediaCatchHandler(err);\n }\n });\n\n return desktopMediaPromise;\n }\n\n destroyUserMediaStream(): Promise<void> {\n const streamResult = window.latestUserMediaStream;\n\n window.latestUserMediaStream = null;\n userMediaPromise = null;\n\n if (streamResult) {\n streamResult.mediaStream.getTracks().forEach((track: MediaStreamTrack) => {\n track.stop();\n });\n }\n\n return Promise.resolve();\n }\n\n destroyDesktopMediaStream(): Promise<void> {\n const streamResult = window.latestDesktopMediaStream;\n\n window.latestDesktopMediaStream = null;\n desktopMediaPromise = null;\n\n if (streamResult) {\n streamResult.mediaStream.getTracks().forEach((track: MediaStreamTrack) => {\n track.stop();\n });\n }\n\n return Promise.resolve();\n }\n\n clearAllStreams(): Promise<void> {\n trace.info('LocalStreamManager Clearing all streams');\n\n return Promise.all([\n this.destroyDesktopMediaStream(),\n this.destroyUserMediaStream()\n ]).then(() => undefined);\n }\n\n private getHighestResolutionStream(isDesktopMedia: boolean, constraints?: LocalMediaConstraints): Promise<MediaRequestSuccessResult> {\n const constraintsCandidates = this.getParsedConstraints(isDesktopMedia, constraints);\n\n if (constraintsCandidates.length === 0) {\n return Promise.reject(new Error('No constraints to retrieve the stream'));\n }\n\n return new Promise((resolve, reject) => {\n let lastSuccessfulResult: Nullable<MediaRequestSuccessResult> = null;\n let lastFailedResult: Nullable<MediaRequestFailResult> = null;\n let isStreamRequestFulfilled = false;\n\n (Promise as any).reduce(constraintsCandidates, (total: any, candidate: MediaStreamConstraints) => {\n if (isStreamRequestFulfilled) {\n return;\n }\n const constraintType = get(constraints, 'video.videoResolution.constraintType') || get(constraints, 'video.videoResolution[0].constraintType');\n\n return this.getStreamPromiseByParsedConstraints(candidate, isDesktopMedia)\n .then((stream: MediaStream) => {\n lastSuccessfulResult = {\n mediaStream: stream,\n constraint: candidate,\n constraintType,\n isNew: true\n };\n trace.info('getHighestResolutionStream Success', lastSuccessfulResult);\n isStreamRequestFulfilled = true;\n resolve(lastSuccessfulResult);\n })\n .catch((failResult: MediaRequestFailResult) => {\n lastFailedResult = failResult;\n if (lastFailedResult.errorCode === MediaRequestErrorCode.PermissionDenied) {\n isStreamRequestFulfilled = true;\n reject(lastFailedResult);\n }\n });\n }, 0)\n .then(() => {\n if (!isStreamRequestFulfilled) {\n if (!lastFailedResult) {\n lastFailedResult = {\n errorCode: MediaRequestErrorCode.GeneralError,\n message: 'Suitable stream cannot be created'\n };\n }\n reject(lastFailedResult);\n }\n });\n });\n }\n\n //@ts-ignore\n private getStreamPromiseByParsedConstraints(constraints: MediaStreamConstraints, isDesktopMedia: boolean): Promise<MediaStream> {\n let streamPromise = null;\n\n trace.info('getStreamPromiseByParsedConstraints', constraints);\n\n try {\n if (!isDesktopMedia) {\n streamPromise = navigator.mediaDevices.getUserMedia(constraints);\n } else {\n //@ts-ignore\n streamPromise = navigator.mediaDevices.getDisplayMedia\n //@ts-ignore\n ? navigator.mediaDevices.getDisplayMedia(constraints)\n : navigator.getDisplayMedia(constraints);\n }\n\n return streamPromise.catch(this.parseMediaErrorThenThrow);\n } catch (e) {\n this.parseMediaErrorThenThrow(e);\n }\n }\n\n private getParsedConstraints(isDesktopMedia: boolean, streamConstraints?: LocalMediaConstraints): MediaStreamConstraints[] {\n const constraintCandidates: MediaStreamConstraints[] = [];\n\n //TODO - Alex: need to understand which constraints not compatible with screen share\n if (isDesktopMedia) {\n return [{video: true}];\n }\n\n if (!streamConstraints) {\n return constraintCandidates;\n }\n\n const baseConstraints: MediaStreamConstraints = {};\n\n baseConstraints.audio = typeof streamConstraints.audio === 'boolean' ? streamConstraints.audio : undefined;\n\n if (!streamConstraints.video) {\n return [baseConstraints];\n }\n\n baseConstraints.video = {\n facingMode: 'environment',\n frameRate: {ideal: 15, max: 30}\n };\n\n const assignConstraint = (videoResolution: VideoStreamResolution): void => {\n const [width, height] = videoResolution.resolution.split('x');\n const constraintCandidate = assign({}, baseConstraints);\n\n constraintCandidate.video = assign({}, baseConstraints.video, {\n width: _constraintByType(width, videoResolution.constraintType),\n height: _constraintByType(height, videoResolution.constraintType)\n });\n constraintCandidates.push(constraintCandidate);\n };\n\n if ((baseConstraints.video && typeof streamConstraints.video === 'boolean') ||\n !((streamConstraints.video as LocalVideoStreamConstraints).videoResolution instanceof Array)) {\n\n const defaultResolution: VideoStreamResolution = {\n resolution: DEFAULT_VIDEO_RESOLUTION,\n constraintType: DEFAULT_VIDEO_CONSTRAINT_TYPE\n };\n\n assignConstraint(defaultResolution);\n\n return constraintCandidates;\n }\n\n (streamConstraints.video as any).videoResolution.forEach(assignConstraint);\n\n return constraintCandidates;\n }\n\n private parseMediaErrorThenThrow(error: any): MediaRequestFailResult {\n trace.error('Get media stream error.', error);\n const errorName = error && error.name ? error.name : '';\n\n const permissionErrorNames = [\n 'NotAllowedError',\n 'PermissionDismissedError',\n 'PermissionDeniedError'\n\n ];\n\n // const generalError = [\n // 'NotFoundError',\n // 'DevicesNotFoundError',\n // 'NotReadableError',\n // 'TrackStartError'\n // ];\n\n const constraintsErrors = [\n 'OverconstrainedError',\n 'ConstraintNotSatisfiedError'\n\n ];\n\n const isErrorOfType = (errorsArr: string[]) => errorsArr.filter((err: string) => err === errorName).length > 0;\n\n if (isErrorOfType(permissionErrorNames)) {\n throw {errorCode: MediaRequestErrorCode.PermissionDenied, message: errorName};\n }\n\n if (isErrorOfType(constraintsErrors)) {\n throw {errorCode: MediaRequestErrorCode.Overconstrained, message: errorName};\n }\n\n throw {errorCode: MediaRequestErrorCode.GeneralError, message: errorName};\n }\n}\n\nfunction _constraintByType(value: any, type: ConstraintType): any {\n switch (type) {\n case ConstraintType.MIN:\n return {min: value};\n default:\n return {ideal: value};\n }\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/MediaPublisher.ts"],"names":[],"mappings":"AACA,OAAO,EAAC,oBAAoB,EAAC,MAAM,kBAAkB,CAAC;AAGtD,OAAO,EAAC,gBAAgB,EAAE,iBAAiB,EAAC,MAAM,kBAAkB,CAAC;AAIrE,MAAM,WAAW,eAAe;CAE/B;AAED,qBAAa,qBAAsB,YAAW,eAAe;IACzD,OAAO,CAAC,QAAQ,CAAe;IAC/B,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAuB;IACxD,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAc;gBAE/B,eAAe,EAAE,oBAAoB,EAAE,WAAW,EAAE,gBAAgB,EAAE;aAQ9E,eAAe,EAAI,iBAAiB;aAIpC,WAAW,EAAI,WAAW;aAI1B,WAAW,EAAI,gBAAgB,EAAE;IAIrC,OAAO,IAAI,IAAI;CAGlB","file":"MediaPublisher.d.ts","sourcesContent":["import {EventEmitter} from 'events';\nimport {MediaPublisherParams} from './MediaContracts';\n\nimport {getMediaTracer} from './Utils/MediaTracer';\nimport {KnownMediaStream, SessionClientRole} from './MediaConstants';\n\nconst trace = getMediaTracer('MediaPublisher');\n\nexport interface IMediaPublisher {\n\n}\n\nexport class TechseeMediaPublisher implements IMediaPublisher {\n private _emitter: EventEmitter;\n private readonly _publisherParams: MediaPublisherParams;\n private readonly _mediaStream: MediaStream;\n\n constructor(publisherParams: MediaPublisherParams, mediaTracks: MediaStreamTrack[]) {\n trace.info('Publisher created', publisherParams);\n\n this._emitter = new EventEmitter();\n this._publisherParams = publisherParams;\n this._mediaStream = new MediaStream(mediaTracks);\n }\n\n get destinationRole(): SessionClientRole {\n return this._publisherParams.destinationRole;\n }\n\n get mediaStream(): MediaStream {\n return this._mediaStream;\n }\n\n get streamTypes(): KnownMediaStream[] {\n return this._publisherParams.streamTypes;\n }\n\n dispose(): void {\n trace.info('Publisher disposed');\n }\n}\n"]}
1
+ {"version":3,"sources":["../src/MediaPublisher.ts"],"names":[],"mappings":"AACA,OAAO,EAAC,oBAAoB,EAAC,MAAM,kBAAkB,CAAC;AAGtD,OAAO,EAAC,gBAAgB,EAAE,iBAAiB,EAAC,MAAM,kBAAkB,CAAC;AAIrE,MAAM,WAAW,eAAe;CAE/B;AAED,qBAAa,qBAAsB,YAAW,eAAe;IACzD,OAAO,CAAC,QAAQ,CAAe;IAC/B,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAuB;IACxD,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAc;gBAE/B,eAAe,EAAE,oBAAoB,EAAE,WAAW,EAAE,gBAAgB,EAAE;aAQ9E,eAAe,EAAI,iBAAiB;aAIpC,WAAW,EAAI,WAAW;aAI1B,WAAW,EAAI,gBAAgB,EAAE;IAIrC,OAAO,IAAI,IAAI;CAGlB","file":"MediaPublisher.d.ts","sourcesContent":["import {EventEmitter} from 'events';\nimport {MediaPublisherParams} from './MediaContracts';\n\nimport {getMediaTracer} from './MediaUtils/MediaTracer';\nimport {KnownMediaStream, SessionClientRole} from './MediaConstants';\n\nconst trace = getMediaTracer('MediaPublisher');\n\nexport interface IMediaPublisher {\n\n}\n\nexport class TechseeMediaPublisher implements IMediaPublisher {\n private _emitter: EventEmitter;\n private readonly _publisherParams: MediaPublisherParams;\n private readonly _mediaStream: MediaStream;\n\n constructor(publisherParams: MediaPublisherParams, mediaTracks: MediaStreamTrack[]) {\n trace.info('Publisher created', publisherParams);\n\n this._emitter = new EventEmitter();\n this._publisherParams = publisherParams;\n this._mediaStream = new MediaStream(mediaTracks);\n }\n\n get destinationRole(): SessionClientRole {\n return this._publisherParams.destinationRole;\n }\n\n get mediaStream(): MediaStream {\n return this._mediaStream;\n }\n\n get streamTypes(): KnownMediaStream[] {\n return this._publisherParams.streamTypes;\n }\n\n dispose(): void {\n trace.info('Publisher disposed');\n }\n}\n"]}
@@ -2,7 +2,7 @@
2
2
 
3
3
  Object.defineProperty(exports, "__esModule", { value: true });
4
4
  var events_1 = require("events");
5
- var MediaTracer_1 = require("./Utils/MediaTracer");
5
+ var MediaTracer_1 = require("./MediaUtils/MediaTracer");
6
6
  var trace = MediaTracer_1.getMediaTracer('MediaPublisher');
7
7
  var TechseeMediaPublisher = /** @class */function () {
8
8
  function TechseeMediaPublisher(publisherParams, mediaTracks) {
@@ -1 +1 @@
1
- {"version":3,"sources":["MediaPublisher.js","../src/MediaPublisher.ts"],"names":["Object","defineProperty","exports","value","events_1","require","MediaTracer_1","trace","getMediaTracer","TechseeMediaPublisher","publisherParams","mediaTracks","info","_emitter","EventEmitter","_publisherParams","_mediaStream","MediaStream","prototype","get","destinationRole","enumerable","configurable","streamTypes","dispose"],"mappings":"AAAA;;AACAA,OAAOC,cAAP,CAAsBC,OAAtB,EAA+B,YAA/B,EAA6C,EAAEC,OAAO,IAAT,EAA7C;ACDA,IAAAC,WAAAC,QAAA,QAAA,CAAA;AAGA,IAAAC,gBAAAD,QAAA,qBAAA,CAAA;AAGA,IAAME,QAAQD,cAAAE,cAAA,CAAe,gBAAf,CAAd;AAMA,IAAAC,wBAAA,aAAA,YAAA;AAKI,aAAAA,qBAAA,CAAYC,eAAZ,EAAmDC,WAAnD,EAAkF;AAC9EJ,cAAMK,IAAN,CAAW,mBAAX,EAAgCF,eAAhC;AAEA,aAAKG,QAAL,GAAgB,IAAIT,SAAAU,YAAJ,EAAhB;AACA,aAAKC,gBAAL,GAAwBL,eAAxB;AACA,aAAKM,YAAL,GAAoB,IAAIC,WAAJ,CAAgBN,WAAhB,CAApB;AACH;AAEDX,WAAAC,cAAA,CAAIQ,sBAAAS,SAAJ,EAAI,iBAAJ,EAAmB;ADZfC,aCYJ,eAAA;AACI,mBAAO,KAAKJ,gBAAL,CAAsBK,eAA7B;AACH,SAFkB;ADTfC,oBAAY,ICSG;ADRfC,sBAAc;ACQC,KAAnB;AAIAtB,WAAAC,cAAA,CAAIQ,sBAAAS,SAAJ,EAAI,aAAJ,EAAe;ADTXC,aCSJ,eAAA;AACI,mBAAO,KAAKH,YAAZ;AACH,SAFc;ADNXK,oBAAY,ICMD;ADLXC,sBAAc;ACKH,KAAf;AAIAtB,WAAAC,cAAA,CAAIQ,sBAAAS,SAAJ,EAAI,aAAJ,EAAe;ADNXC,aCMJ,eAAA;AACI,mBAAO,KAAKJ,gBAAL,CAAsBQ,WAA7B;AACH,SAFc;ADHXF,oBAAY,ICGD;ADFXC,sBAAc;ACEH,KAAf;AAIAb,0BAAAS,SAAA,CAAAM,OAAA,GAAA,YAAA;AACIjB,cAAMK,IAAN,CAAW,oBAAX;AACH,KAFD;AAGJ,WAAAH,qBAAA;AA5BA,CAAA,EAAA;AAAaP,QAAAO,qBAAA,GAAAA,qBAAA;;AD4Bb","file":"MediaPublisher.js","sourcesContent":["\"use strict\";\nObject.defineProperty(exports, \"__esModule\", { value: true });\nvar events_1 = require(\"events\");\nvar MediaTracer_1 = require(\"./Utils/MediaTracer\");\nvar trace = MediaTracer_1.getMediaTracer('MediaPublisher');\nvar TechseeMediaPublisher = /** @class */ (function () {\n function TechseeMediaPublisher(publisherParams, mediaTracks) {\n trace.info('Publisher created', publisherParams);\n this._emitter = new events_1.EventEmitter();\n this._publisherParams = publisherParams;\n this._mediaStream = new MediaStream(mediaTracks);\n }\n Object.defineProperty(TechseeMediaPublisher.prototype, \"destinationRole\", {\n get: function () {\n return this._publisherParams.destinationRole;\n },\n enumerable: true,\n configurable: true\n });\n Object.defineProperty(TechseeMediaPublisher.prototype, \"mediaStream\", {\n get: function () {\n return this._mediaStream;\n },\n enumerable: true,\n configurable: true\n });\n Object.defineProperty(TechseeMediaPublisher.prototype, \"streamTypes\", {\n get: function () {\n return this._publisherParams.streamTypes;\n },\n enumerable: true,\n configurable: true\n });\n TechseeMediaPublisher.prototype.dispose = function () {\n trace.info('Publisher disposed');\n };\n return TechseeMediaPublisher;\n}());\nexports.TechseeMediaPublisher = TechseeMediaPublisher;\n\n//# sourceMappingURL=MediaPublisher.js.map\n","import {EventEmitter} from 'events';\nimport {MediaPublisherParams} from './MediaContracts';\n\nimport {getMediaTracer} from './Utils/MediaTracer';\nimport {KnownMediaStream, SessionClientRole} from './MediaConstants';\n\nconst trace = getMediaTracer('MediaPublisher');\n\nexport interface IMediaPublisher {\n\n}\n\nexport class TechseeMediaPublisher implements IMediaPublisher {\n private _emitter: EventEmitter;\n private readonly _publisherParams: MediaPublisherParams;\n private readonly _mediaStream: MediaStream;\n\n constructor(publisherParams: MediaPublisherParams, mediaTracks: MediaStreamTrack[]) {\n trace.info('Publisher created', publisherParams);\n\n this._emitter = new EventEmitter();\n this._publisherParams = publisherParams;\n this._mediaStream = new MediaStream(mediaTracks);\n }\n\n get destinationRole(): SessionClientRole {\n return this._publisherParams.destinationRole;\n }\n\n get mediaStream(): MediaStream {\n return this._mediaStream;\n }\n\n get streamTypes(): KnownMediaStream[] {\n return this._publisherParams.streamTypes;\n }\n\n dispose(): void {\n trace.info('Publisher disposed');\n }\n}\n"]}
1
+ {"version":3,"sources":["MediaPublisher.js","../src/MediaPublisher.ts"],"names":["Object","defineProperty","exports","value","events_1","require","MediaTracer_1","trace","getMediaTracer","TechseeMediaPublisher","publisherParams","mediaTracks","info","_emitter","EventEmitter","_publisherParams","_mediaStream","MediaStream","prototype","get","destinationRole","enumerable","configurable","streamTypes","dispose"],"mappings":"AAAA;;AACAA,OAAOC,cAAP,CAAsBC,OAAtB,EAA+B,YAA/B,EAA6C,EAAEC,OAAO,IAAT,EAA7C;ACDA,IAAAC,WAAAC,QAAA,QAAA,CAAA;AAGA,IAAAC,gBAAAD,QAAA,0BAAA,CAAA;AAGA,IAAME,QAAQD,cAAAE,cAAA,CAAe,gBAAf,CAAd;AAMA,IAAAC,wBAAA,aAAA,YAAA;AAKI,aAAAA,qBAAA,CAAYC,eAAZ,EAAmDC,WAAnD,EAAkF;AAC9EJ,cAAMK,IAAN,CAAW,mBAAX,EAAgCF,eAAhC;AAEA,aAAKG,QAAL,GAAgB,IAAIT,SAAAU,YAAJ,EAAhB;AACA,aAAKC,gBAAL,GAAwBL,eAAxB;AACA,aAAKM,YAAL,GAAoB,IAAIC,WAAJ,CAAgBN,WAAhB,CAApB;AACH;AAEDX,WAAAC,cAAA,CAAIQ,sBAAAS,SAAJ,EAAI,iBAAJ,EAAmB;ADZfC,aCYJ,eAAA;AACI,mBAAO,KAAKJ,gBAAL,CAAsBK,eAA7B;AACH,SAFkB;ADTfC,oBAAY,ICSG;ADRfC,sBAAc;ACQC,KAAnB;AAIAtB,WAAAC,cAAA,CAAIQ,sBAAAS,SAAJ,EAAI,aAAJ,EAAe;ADTXC,aCSJ,eAAA;AACI,mBAAO,KAAKH,YAAZ;AACH,SAFc;ADNXK,oBAAY,ICMD;ADLXC,sBAAc;ACKH,KAAf;AAIAtB,WAAAC,cAAA,CAAIQ,sBAAAS,SAAJ,EAAI,aAAJ,EAAe;ADNXC,aCMJ,eAAA;AACI,mBAAO,KAAKJ,gBAAL,CAAsBQ,WAA7B;AACH,SAFc;ADHXF,oBAAY,ICGD;ADFXC,sBAAc;ACEH,KAAf;AAIAb,0BAAAS,SAAA,CAAAM,OAAA,GAAA,YAAA;AACIjB,cAAMK,IAAN,CAAW,oBAAX;AACH,KAFD;AAGJ,WAAAH,qBAAA;AA5BA,CAAA,EAAA;AAAaP,QAAAO,qBAAA,GAAAA,qBAAA;;AD4Bb","file":"MediaPublisher.js","sourcesContent":["\"use strict\";\nObject.defineProperty(exports, \"__esModule\", { value: true });\nvar events_1 = require(\"events\");\nvar MediaTracer_1 = require(\"./MediaUtils/MediaTracer\");\nvar trace = MediaTracer_1.getMediaTracer('MediaPublisher');\nvar TechseeMediaPublisher = /** @class */ (function () {\n function TechseeMediaPublisher(publisherParams, mediaTracks) {\n trace.info('Publisher created', publisherParams);\n this._emitter = new events_1.EventEmitter();\n this._publisherParams = publisherParams;\n this._mediaStream = new MediaStream(mediaTracks);\n }\n Object.defineProperty(TechseeMediaPublisher.prototype, \"destinationRole\", {\n get: function () {\n return this._publisherParams.destinationRole;\n },\n enumerable: true,\n configurable: true\n });\n Object.defineProperty(TechseeMediaPublisher.prototype, \"mediaStream\", {\n get: function () {\n return this._mediaStream;\n },\n enumerable: true,\n configurable: true\n });\n Object.defineProperty(TechseeMediaPublisher.prototype, \"streamTypes\", {\n get: function () {\n return this._publisherParams.streamTypes;\n },\n enumerable: true,\n configurable: true\n });\n TechseeMediaPublisher.prototype.dispose = function () {\n trace.info('Publisher disposed');\n };\n return TechseeMediaPublisher;\n}());\nexports.TechseeMediaPublisher = TechseeMediaPublisher;\n\n//# sourceMappingURL=MediaPublisher.js.map\n","import {EventEmitter} from 'events';\nimport {MediaPublisherParams} from './MediaContracts';\n\nimport {getMediaTracer} from './MediaUtils/MediaTracer';\nimport {KnownMediaStream, SessionClientRole} from './MediaConstants';\n\nconst trace = getMediaTracer('MediaPublisher');\n\nexport interface IMediaPublisher {\n\n}\n\nexport class TechseeMediaPublisher implements IMediaPublisher {\n private _emitter: EventEmitter;\n private readonly _publisherParams: MediaPublisherParams;\n private readonly _mediaStream: MediaStream;\n\n constructor(publisherParams: MediaPublisherParams, mediaTracks: MediaStreamTrack[]) {\n trace.info('Publisher created', publisherParams);\n\n this._emitter = new EventEmitter();\n this._publisherParams = publisherParams;\n this._mediaStream = new MediaStream(mediaTracks);\n }\n\n get destinationRole(): SessionClientRole {\n return this._publisherParams.destinationRole;\n }\n\n get mediaStream(): MediaStream {\n return this._mediaStream;\n }\n\n get streamTypes(): KnownMediaStream[] {\n return this._publisherParams.streamTypes;\n }\n\n dispose(): void {\n trace.info('Publisher disposed');\n }\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/MediaServiceBase.ts"],"names":[],"mappings":"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","file":"MediaServiceBase.d.ts","sourcesContent":["import filter from 'lodash/filter';\nimport cloneDeep from 'lodash/cloneDeep';\nimport values from 'lodash/values';\nimport debounce from 'lodash/debounce';\nimport {EventEmitter} from 'events';\nimport {Nullable} from '@techsee/techsee-common';\nimport {TechseeMediaSubscriber} from './MediaSubscriber';\nimport {TechseeMediaPublisher} from './MediaPublisher';\nimport {LocalStreamManager} from './LocalStreamManager';\nimport {TechseeMediaStream} from './TechseeMediaStream';\nimport {TurnWebRtcSessionV3} from './Session/SessionTurn.v3';\nimport {getSnapshotFromMediaStream} from './Utils/MediaDomUtils';\nimport {\n ClientWebRtcInfo,\n DeviceSupportInfo,\n IMediaEnvironment,\n IMediaSession,\n IMediaSubscriber,\n ISessionStreamsManager,\n MediaRequestFailResult,\n MediaServiceOptions,\n MediaSessionHandlers,\n MediaSessionIceCredentials,\n MediaSessionParams,\n MediaSubscriberParams,\n RemoteMediaTrack,\n SnapshotOptions,\n SnapshotResult,\n StreamCreatedEventArgs,\n StreamDestroyedEventArgs,\n RemoteTrackStats\n} from './MediaContracts';\nimport {enumerateMediaDevices, isVideoPlaySupportedOnDevice} from './Utils/Compatibility';\nimport {OpentokSessionV3} from './Session/SessionOpentok.v3';\nimport {\n KnownMediaStream,\n KnownMediaStreamKind,\n MediaServiceType,\n MediaSessionDisconnectReason,\n MediaStreamUnregisterReason,\n SessionClientRole\n} from './MediaConstants';\n\nimport {throwableGuard} from '@techsee/techsee-common/lib/core/guards';\n\nimport {getMediaTracer} from './Utils/MediaTracer';\n\nconst trace = getMediaTracer('MediaServiceBase');\nconst traceStatsInfo = debounce(trace.info, 1000 * 5, {leading: true, maxWait: 1000 * 30});\n\nenum privateEvents {\n STREAM_CREATED = 'STREAM_CREATED',\n STREAM_DESTROYED = 'STREAM_DESTROYED'\n}\n\nexport abstract class TechseeMediaServiceBase {\n //This method should not be called. The only place that allowed to use it, is initLocalMediaStreams method.\n //Everyone who need to initialize MediaStream should use initLocalMediaStreams method.\n protected abstract getLocalMediaImplementation(): Promise<void>;\n\n protected abstract createMediaPublisher(destinationRole: SessionClientRole): Promise<Nullable<TechseeMediaPublisher>>;\n\n protected readonly _environment: IMediaEnvironment;\n protected readonly _sessionStreamsManager: ISessionStreamsManager;\n protected readonly _localStreamsManager: LocalStreamManager;\n\n private readonly _deviceSupportFlags: DeviceSupportInfo;\n private readonly _subscribers: Map<HTMLDivElement, TechseeMediaSubscriber> = new Map();\n private readonly _publishers: Map<SessionClientRole, TechseeMediaPublisher> = new Map();\n private readonly _publisherPromises: Map<SessionClientRole, Promise<Nullable<MediaStream>>> = new Map();\n private _serviceOptions: Nullable<MediaServiceOptions> = null;\n\n private readonly _emitter: EventEmitter;\n private _initLocalStreamsPromise: Nullable<Promise<void>> = null;\n private _initServicePromise: Nullable<Promise<void>> = null;\n private _registeredStreams: Map<KnownMediaStream, TechseeMediaStream> = new Map();\n private _isVoipEnabled: boolean = false;\n private _session: Nullable<{\n params: MediaSessionParams;\n connectPromise?: Promise<void>;\n instance?: IMediaSession;\n }> = null;\n\n protected constructor(environment: IMediaEnvironment, webRtcSupportInfo: ClientWebRtcInfo) {\n trace.info('TechseeMediaServiceBase created');\n\n this.bindClassMethods();\n\n this._emitter = new EventEmitter();\n this._environment = environment;\n this._deviceSupportFlags = {\n videoPlayback: false,\n hasCamera: false,\n hasMicrophone: false,\n webRtcSupportInfo: webRtcSupportInfo\n };\n\n this._localStreamsManager = new LocalStreamManager(this._environment);\n\n this._sessionStreamsManager = {\n getMediaStreamForRole: this.getStreamForDestinationRole,\n addRemoteMediaTrack: this.registerRemoteMediaTrack,\n removeMediaTrack: this.unregisterRemoteMediaTrack\n };\n }\n\n get deviceSupportInfo(): DeviceSupportInfo {\n this.serviceInitGuard(false);\n\n return cloneDeep(this._deviceSupportFlags);\n }\n\n get isVoipEnabled(): boolean {\n return this._isVoipEnabled;\n }\n\n get isSessionActive(): boolean {\n return this._session !== null;\n }\n\n get isLocalStreamInitialized(): boolean {\n return this._initLocalStreamsPromise !== null;\n }\n\n /*\n Initializes media service. Before using anything from this service it should be initialized first.\n All of serviceOptions should be retrieved from account settings and by evaluating application state.\n For example, when initializing service, accountSettings is already loaded, and we know if FS session is audio enabled.\n */\n initMediaService(serviceOptions: MediaServiceOptions): Promise<void> {\n trace.info('TechseeMediaServiceBase.initMediaService', serviceOptions);\n const warnMessage = 'Multiple initialization does not supposed to happen. Not rejecting, but check the flow for correctness.';\n\n if (this._initServicePromise || this._serviceOptions) {\n console.warn(warnMessage);\n\n return this._initServicePromise ? this._initServicePromise : Promise.resolve();\n }\n\n this._serviceOptions = cloneDeep(serviceOptions);\n const isOpenTok = this._serviceOptions.mediaServiceType === MediaServiceType.OPENTOK;\n\n this._initServicePromise = Promise.all([\n isVideoPlaySupportedOnDevice(isOpenTok)\n .then((isSupported: boolean) => this._deviceSupportFlags.videoPlayback = isSupported),\n enumerateMediaDevices()\n .catch((error) => {\n trace.warn(error);\n\n return [];\n })\n .then((localDevicesList: MediaDeviceInfo[]) => {\n const groupedDevices = {\n video: filter(localDevicesList, (device) => device.kind.toLowerCase() === 'videoinput'),\n audio: filter(localDevicesList, (device) => device.kind.toLowerCase() === 'audioinput')\n };\n\n this._deviceSupportFlags.hasCamera = groupedDevices.video.length > 0;\n this._deviceSupportFlags.hasMicrophone = groupedDevices.audio.length > 0;\n })\n ]).then(() => undefined);\n\n\n return this._initServicePromise;\n }\n\n //#region Media Streams Management\n\n /*\n The main method to start the initialization of local media streams.\n This method can be executed many times and it will insure all calls are synced and only relevant stream will be created.\n DO NOT USE ANY OTHER METHOD THAT FORCES \"navigator.getUserMedia\" OTHER THAN THIS ONE.\n */\n initLocalMediaStreams(): Promise<void> {\n this.serviceInitGuard();\n\n if (!this._initLocalStreamsPromise) {\n trace.info('initLocalMediaStreams creating media streams');\n this._initLocalStreamsPromise = this.getLocalMediaImplementation()\n .catch((mediaRequestFailResult: MediaRequestFailResult) => {\n trace.error('initLocalMediaStreams failure: ', mediaRequestFailResult);\n throw mediaRequestFailResult;\n });\n } else {\n trace.info('initLocalMediaStreams already done or in progress');\n }\n\n return this._initLocalStreamsPromise;\n }\n\n /*\n Creates an instance of subscriber that will \"listen\" to the requested stream.\n Whenever requested stream is available, subscriber will render it.\n */\n createSubscriber(subscriberParams: MediaSubscriberParams): Promise<IMediaSubscriber> {\n if (this._subscribers.has(subscriberParams.container)) {\n return Promise.reject('Subscriber for provided DIV element already exists');\n }\n\n const subscriber = new TechseeMediaSubscriber(subscriberParams);\n\n this._subscribers.set(subscriberParams.container, subscriber);\n const streamForSubscriber = this.getRegisteredStreamByType(subscriber.streamType);\n\n if (streamForSubscriber) {\n trace.info(`Stream for ${subscriberParams.streamType} is ready.`);\n subscriber.renderStream(streamForSubscriber);\n } else {\n trace.info(`Stream for ${subscriberParams.streamType} not created yet`);\n }\n\n return Promise.resolve(subscriber);\n }\n\n /*\n Destroys the subscriber for provided HTML DIV container\n */\n destroySubscriber(container: HTMLDivElement): Promise<void> {\n if (this._subscribers.has(container)) {\n const subscriber = this._subscribers.get(container);\n\n subscriber!.dispose();\n }\n\n this._subscribers.delete(container);\n\n return Promise.resolve();\n }\n\n onStreamDestroyed(callback: (eventArgs: StreamDestroyedEventArgs) => void): void {\n this.registerEventCallback(privateEvents.STREAM_DESTROYED, callback);\n }\n\n onStreamCreated(callback: (eventArgs: StreamCreatedEventArgs) => void): void {\n this.registerEventCallback(privateEvents.STREAM_CREATED, callback);\n }\n\n //#endregion Media Streams Management\n\n //#region Session Management\n\n /*\n Creates instance of WebRTC session which connects to (signaling server), and begins to listen to WebRTC events.\n */\n connectToSession(sessionParams: MediaSessionParams): Promise<void> {\n this.serviceInitGuard();\n\n if (!this._session) {\n this._session = {params: cloneDeep(sessionParams)};\n this._session.connectPromise = new Promise((resolve, reject) => {\n const doAsyncReject = (error: any): void => {\n\n /*\n Reject with timeout, to change JS 'execution flow'.\n If timeout removed, session is assigned to null, before promise returns, and \"catch\" will not\n work on promise that is returned.\n */\n setTimeout(() => {\n this._session = null;\n reject(error);\n });\n };\n\n const sessionHandlers: MediaSessionHandlers = {\n onDisconnectedHandler: this.onSessionDisconnectHandler\n };\n\n trace.info('connectToSession', sessionParams);\n if (this._serviceOptions!.mediaServiceType === MediaServiceType.TURNSERVER) {\n this._session!.instance = new TurnWebRtcSessionV3(sessionParams, sessionHandlers, this._sessionStreamsManager);\n\n } else if (this._serviceOptions!.mediaServiceType === MediaServiceType.OPENTOK) {\n this._session!.instance = new OpentokSessionV3(sessionParams, this._sessionStreamsManager);\n } else {\n const allowedValues = values(MediaServiceType);\n\n trace.error(`mediaServiceType '${this._serviceOptions!.mediaServiceType}' is not supported.`, {allowedValues});\n doAsyncReject(new Error('mediaServiceType is not supported'));\n }\n\n if (this._session && this._session.instance) {\n this._session!.instance.connect()\n .then(() => {\n trace.info('Session is connected');\n resolve();\n })\n .catch((error: any) => {\n trace.error('Failed to connect to session', error);\n doAsyncReject(error);\n });\n }\n\n });\n } else {\n trace.warn('Session connected already. Disconnect before connect to new session again');\n }\n\n //TODO - Alex: Change a structure of this function to be more safe\n //(when we return, there should not be case when session or promise is null)\n //To fix, need to return promise immediately, then execute process in setTimeout(fn, 0);\n return this._session!.connectPromise!;\n }\n\n /*\n Disconnects from WebRTC session.\n */\n disconnectFromSession(): Promise<void> {\n if (!this._session) {\n return Promise.resolve();\n }\n\n const lastSession = this._session;\n\n this._session = null;\n\n trace.info('Disconnecting from session');\n\n return Promise.all([\n lastSession.instance!.disconnect(),\n this.clearPublishers()\n ]).then(() => undefined);\n }\n\n /*\n Updates a credentials for turn server\n */\n updateSessionCredentials(credentials: MediaSessionIceCredentials): Promise<void> {\n trace.info('updateSessionCredentials');\n if (!this.sessionExistsGuard(false)) {\n return Promise.reject('There no session to update credentials');\n }\n\n this._session!.params.credentials = cloneDeep(credentials);\n\n return Promise.resolve();\n }\n\n enableVoipDuringSession(): void {\n if (!this._isVoipEnabled && this.isLocalStreamInitialized) {\n throw new Error('Voip support cannot be enabled after local stream where initialized');\n }\n\n this._isVoipEnabled = true;\n }\n\n protected getStatsForRemoteTrack(streamType: KnownMediaStream): Promise<RemoteTrackStats> {\n if (!this.sessionExistsGuard(false)) {\n return Promise.reject(new Error('Media session not started'));\n }\n\n const streamForStats = this.getRegisteredStreamByType(streamType);\n\n if (!streamForStats) {\n return Promise.reject(new Error('Stream for requested type was not found'));\n }\n\n return this._session!.instance!.getRemoteTrackStats(streamForStats.mediaTrack)\n .then((trackStats: RemoteTrackStats) => {\n traceStatsInfo(`MediaTrackStats for ${streamType}: ${JSON.stringify(trackStats)}`);\n\n return {\n trackId: streamForStats.mediaTrack.id,\n trackStats: trackStats\n };\n });\n }\n\n private onSessionDisconnectHandler(reason: MediaSessionDisconnectReason): void {\n trace.info('onSessionDisconnectHandler', reason);\n if (reason !== MediaSessionDisconnectReason.ForcedByConsumer) {\n const lastParams = this._session && this._session.params ? this._session.params : null;\n\n this.disconnectFromSession().then(() => {\n if (lastParams && reason === MediaSessionDisconnectReason.UserPeerReconnected) {\n trace.info('Reconnecting to media session, sessionParams:', lastParams);\n this.connectToSession(lastParams)\n .then(() => {\n trace.info('Media session reconnected');\n })\n .catch((error: any) => {\n trace.error('Error while reconnecting to media session');\n });\n }\n });\n } else {\n trace.info('Ignore Session disconnect event');\n }\n }\n\n //#endregion Session Management\n\n //#region Utils\n\n getSnapshotFromKnownStream(sourceStream: KnownMediaStream, snapshotOptions?: SnapshotOptions): Promise<SnapshotResult> {\n return new Promise((resolve, reject) => {\n if (sourceStream !== KnownMediaStream.USER_VIDEO_STREAM &&\n sourceStream !== KnownMediaStream.USER_SCREEN_SHARE_STREAM) {\n trace.error('The requested stream is not video stream, and cannot be used for snapshot');\n reject(new Error('INCOMPATIBLE_STREAM_FOR_SNAPSHOT'));\n\n return;\n }\n\n const snapshotStream = this.getRegisteredStreamByType(sourceStream);\n\n if (!snapshotStream) {\n trace.error('Cannot make snapshot: The requested stream not exists yet.');\n reject(new Error('NO_REQUESTED_STREAM'));\n\n return;\n }\n\n getSnapshotFromMediaStream(snapshotStream.mediaStream, snapshotOptions)\n .then((imageData: any) => {\n const urlComponents = imageData.split(';base64,');\n const mimeType = urlComponents[0].split(':')[1];\n const bytes = atob(urlComponents[1]);\n const buffer = new ArrayBuffer(bytes.length);\n const rawData = new Uint8Array(buffer);\n\n for (let i = 0; i < bytes.length; i++) {\n rawData[i] = bytes.charCodeAt(i);\n }\n\n const blob = new Blob([rawData], {type: mimeType});\n const objectUrl = window.URL.createObjectURL(blob);\n\n trace.info('Snapshot created successfully');\n\n const result: SnapshotResult = {\n base64img: imageData,\n objectUrl: objectUrl,\n imageBlob: blob,\n mimeType: mimeType\n };\n\n resolve(result);\n })\n .catch((error: any) => {\n trace.error('Error creating snapshot', error);\n reject(error);\n });\n });\n }\n\n //Will clean streams, publishers and subscribers, but will not remove event listeners\n clearService(): Promise<void> {\n trace.info('MediaService clearing all resources');\n\n return this.disconnectFromSession()\n .then(this.clearSubscribers)\n .then(this.clearRegisteredStreams)\n .then(this._localStreamsManager.clearAllStreams)\n .then(() => {\n this._initLocalStreamsPromise = null;\n }).then(() => undefined);\n }\n\n //Will clear the service and remove all event listeners\n dispose(): Promise<void> {\n return this.clearService().catch(() => undefined).then(() => {\n this._emitter.removeAllListeners();\n });\n }\n\n //#endregion\n\n //#region Protected Methods\n\n protected get subscribers(): Map<HTMLDivElement, TechseeMediaSubscriber> {\n return this._subscribers;\n }\n\n protected registerLocalMediaStream(tsMediaStream: TechseeMediaStream): Promise<void> {\n trace.info('Registering local stream', tsMediaStream.streamType);\n if (this._registeredStreams.has(tsMediaStream.streamType)) {\n return Promise.reject(new Error(`Stream ${tsMediaStream.streamType} already registered`));\n }\n\n return this.registerStream(tsMediaStream);\n }\n\n protected getRegisteredStreamByType(streamType: KnownMediaStream): Nullable<TechseeMediaStream> {\n return this._registeredStreams.get(streamType) || null;\n }\n\n protected changeEnableForKnownStream(streamType: KnownMediaStream, isPaused: boolean): void {\n const streamToChangeState = this.getRegisteredStreamByType(streamType);\n\n if (!streamToChangeState) {\n trace.warn('There no stream found to change enable state', streamType);\n } else {\n streamToChangeState.mediaTrack.enabled = !isPaused;\n\n if (streamToChangeState.isRemote && streamToChangeState.streamKind === KnownMediaStreamKind.Audio) {\n this.subscribers.forEach((subscriber) => {\n if (subscriber.streamType === streamType) {\n subscriber.muteSound(isPaused);\n }\n });\n }\n\n trace.info('Local stream enable state is changed', {streamType, isPaused});\n }\n }\n\n protected registerEventCallback(event: string, callback: (eventArgs?: any) => void): void {\n this._emitter.on(event, callback);\n }\n\n protected emitEvent(event: string, eventArgs?: any): void {\n setTimeout(() => {\n this._emitter.emit(event, eventArgs);\n });\n }\n\n //#endregion Protected Methods\n\n //#region Private Methods\n\n private registerRemoteMediaTrack(remoteMediaTrack: RemoteMediaTrack): Promise<void> {\n trace.info(`Registering remote ${remoteMediaTrack.trackType} MediaStreamTrack`, remoteMediaTrack.mediaTrack);\n const currentStream = this._registeredStreams.get(remoteMediaTrack.trackType);\n\n if (currentStream && !currentStream.isRemote) {\n return Promise.reject(new Error('Cannot register remote stream with the same type as local stream'));\n }\n\n const newDedicatedStream = new TechseeMediaStream(remoteMediaTrack.mediaTrack, remoteMediaTrack.trackType, true);\n\n return this.registerStream(newDedicatedStream);\n }\n\n private registerStream(mediaStream: TechseeMediaStream): Promise<void> {\n const currentStream = this._registeredStreams.get(mediaStream.streamType);\n\n const registerTrack = (): Promise<void> => {\n mediaStream.mediaTrack.onended = () =>\n this.unregisterTechseeMediaStream(mediaStream, MediaStreamUnregisterReason.NativeEvent);\n\n this._registeredStreams.set(mediaStream.streamType, mediaStream);\n\n trace.info(`TechseeMediaStream registered - ${mediaStream.streamType}`, TechseeMediaStream);\n\n return this.updateSubscribersWithNewStream(mediaStream).then(() => {\n const eventArgs: StreamCreatedEventArgs = {streamType: mediaStream.streamType};\n\n this.emitEvent(privateEvents.STREAM_CREATED, eventArgs);\n });\n };\n\n if (currentStream) {\n return this.unregisterTechseeMediaStream(currentStream, MediaStreamUnregisterReason.ReplacingStream).then(registerTrack);\n }\n\n return registerTrack();\n\n }\n\n private unregisterTechseeMediaStream(streamToUnregister: TechseeMediaStream, reason: MediaStreamUnregisterReason): Promise<void> {\n const traceError = (error: any): void => {\n trace.warn('Unregister TechseeMediaStream error:', error);\n };\n\n const promises: any = [];\n\n trace.info('Unregister TechseeMediaStream: ', streamToUnregister.streamType);\n\n this._subscribers.forEach((subscriber) => {\n if (subscriber.streamType === streamToUnregister.streamType) {\n promises.push(subscriber.stopRendering().catch(traceError));\n }\n });\n\n if (!streamToUnregister.isRemote) {\n this._publishers.forEach((publisher: TechseeMediaPublisher) => {\n if (publisher.streamTypes.find((streamType) => streamType === streamToUnregister.streamType)) {\n if (this._session && this._session!.instance) {\n promises.push(this._session.instance.onMediaStreamDestroyed(publisher.destinationRole).catch(traceError));\n }\n }\n });\n }\n\n return Promise.all(promises)\n .then(() => {\n this._registeredStreams.delete(streamToUnregister.streamType);\n trace.info('Stream deleted', streamToUnregister.streamType);\n\n const eventArgs: StreamDestroyedEventArgs = {streamType: streamToUnregister.streamType, reason: reason};\n\n this.emitEvent(privateEvents.STREAM_DESTROYED, eventArgs);\n });\n }\n\n private unregisterRemoteMediaTrack(mediaTrack: MediaStreamTrack): Promise<void> {\n const promises: any = [];\n\n this._registeredStreams.forEach((registeredStream: TechseeMediaStream) => {\n if (registeredStream.mediaTrack.id === mediaTrack.id) {\n promises.push(this.unregisterTechseeMediaStream(registeredStream, MediaStreamUnregisterReason.ClosedRemotely));\n }\n });\n\n return Promise.all(promises).then(() => undefined);\n }\n\n private removePublisher(publisher: TechseeMediaPublisher): Promise<void> {\n this._publishers.delete(publisher.destinationRole);\n if (this._session && this._session.instance) {\n trace.info('Removing publisher', publisher.destinationRole);\n\n return this._session.instance.onMediaStreamDestroyed(publisher.destinationRole)\n .catch((error: any) => {\n trace.warn('Error while removing publisher', error);\n });\n }\n\n return Promise.resolve();\n }\n\n private getStreamForDestinationRole(destinationRole: SessionClientRole): Promise<Nullable<MediaStream>> {\n this.serviceInitGuard();\n\n if (this._publishers.has(destinationRole)) {\n trace.info(`Publisher for ${destinationRole} already exists`);\n\n return Promise.resolve(this._publishers.get(destinationRole)!.mediaStream);\n }\n\n if (!this._publisherPromises.get(destinationRole)) {\n trace.info(`Creating publisher for ${destinationRole}`);\n const publisherPromise = this.initLocalMediaStreams()\n .then(() => this.createMediaPublisher(destinationRole))\n .then((mediaPublisher: Nullable<TechseeMediaPublisher>) => {\n if (mediaPublisher) {\n this._publishers.set(destinationRole, mediaPublisher);\n }\n\n this._publisherPromises.delete(destinationRole);\n\n return mediaPublisher ? mediaPublisher.mediaStream : null;\n })\n .catch((ex: any) => {\n this._publisherPromises.delete(destinationRole);\n throw ex;\n });\n\n this._publisherPromises.set(destinationRole, publisherPromise);\n } else {\n trace.info(`Create publisher promise for ${destinationRole} already exists`);\n }\n\n return this._publisherPromises.get(destinationRole)!;\n }\n\n private updateSubscribersWithNewStream(registeredStream: TechseeMediaStream): Promise<void> {\n trace.info(`Updating subscribers of ${registeredStream.streamType} with new stream`);\n\n if (this._subscribers.size === 0) {\n trace.warn(`No subscribers exists for the ${registeredStream.streamType}.`);\n } else {\n trace.info(`Total ${this._subscribers.size} subscribers exists, will check if rerender needed.`);\n }\n\n this._subscribers.forEach((subscriber) => {\n if (subscriber.streamType === registeredStream.streamType) {\n trace.info(`${registeredStream.streamType} rendering on subscriber`);\n subscriber.renderStream(registeredStream);\n }\n });\n\n return Promise.resolve();\n }\n\n private bindClassMethods(): void {\n this.updateSessionCredentials = this.updateSessionCredentials.bind(this);\n this.getStreamForDestinationRole = this.getStreamForDestinationRole.bind(this);\n this.registerRemoteMediaTrack = this.registerRemoteMediaTrack.bind(this);\n this.unregisterRemoteMediaTrack = this.unregisterRemoteMediaTrack.bind(this);\n this.createMediaPublisher = this.createMediaPublisher.bind(this);\n this.updateSubscribersWithNewStream = this.updateSubscribersWithNewStream.bind(this);\n this.initLocalMediaStreams = this.initLocalMediaStreams.bind(this);\n this.onSessionDisconnectHandler = this.onSessionDisconnectHandler.bind(this);\n this.clearService = this.clearService.bind(this);\n this.clearRegisteredStreams = this.clearRegisteredStreams.bind(this);\n this.clearPublishers = this.clearPublishers.bind(this);\n this.clearSubscribers = this.clearSubscribers.bind(this);\n }\n\n //region Cleanup\n\n private clearRegisteredStreams(): Promise<void> {\n trace.info('Clearing registered streams');\n const promises: any = [];\n\n this._registeredStreams.forEach((streamToUnregister: TechseeMediaStream) => {\n promises.push(this.unregisterTechseeMediaStream(streamToUnregister, MediaStreamUnregisterReason.ServiceCleanUp));\n });\n\n return Promise.all(promises).then(() => undefined);\n }\n\n private clearSubscribers(): Promise<void> {\n trace.info('Clearing subscribers');\n const promises: any = [];\n\n this._subscribers.forEach((subscriber) => {\n promises.push(this.destroySubscriber(subscriber.container));\n });\n\n return Promise.all(promises).then(() => undefined);\n }\n\n private clearPublishers(): Promise<void> {\n trace.info('Clearing publishers');\n const promises: any = [];\n\n this._publishers.forEach((publisher) => {\n promises.push(this.removePublisher(publisher));\n });\n\n return Promise.all(promises).then(() => undefined);\n }\n\n //#endregion Cleanup\n\n //#region Simple Validation Methods\n\n protected serviceInitGuard(shouldThrow = true): boolean {\n return throwableGuard(!!this._serviceOptions, 'Media service is not initialized', shouldThrow);\n }\n\n protected sessionExistsGuard(shouldThrow = true): boolean {\n return throwableGuard(!!this._session, 'There no active session', shouldThrow);\n }\n\n //#endregion\n\n //#endregion Private Methods\n}\n"]}
1
+ {"version":3,"sources":["../src/MediaServiceBase.ts"],"names":[],"mappings":"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","file":"MediaServiceBase.d.ts","sourcesContent":["import filter from 'lodash/filter';\nimport cloneDeep from 'lodash/cloneDeep';\nimport values from 'lodash/values';\nimport debounce from 'lodash/debounce';\nimport {EventEmitter} from 'events';\nimport {Nullable} from '@techsee/techsee-common';\nimport {TechseeMediaSubscriber} from './MediaSubscriber';\nimport {TechseeMediaPublisher} from './MediaPublisher';\nimport {LocalStreamManager} from './LocalStreamManager';\nimport {TechseeMediaStream} from './TechseeMediaStream';\nimport {TurnWebRtcSessionV3} from './MediaSession/SessionTurn.v3';\nimport {getSnapshotFromMediaStream} from './MediaUtils/MediaDomUtils';\nimport {\n ClientWebRtcInfo,\n DeviceSupportInfo,\n IMediaEnvironment,\n IMediaSession,\n IMediaSubscriber,\n ISessionStreamsManager,\n MediaRequestFailResult,\n MediaServiceOptions,\n MediaSessionHandlers,\n MediaSessionIceCredentials,\n MediaSessionParams,\n MediaSubscriberParams,\n RemoteMediaTrack,\n SnapshotOptions,\n SnapshotResult,\n StreamCreatedEventArgs,\n StreamDestroyedEventArgs,\n RemoteTrackStats\n} from './MediaContracts';\nimport {enumerateMediaDevices, isVideoPlaySupportedOnDevice} from './MediaUtils/Compatibility';\nimport {OpentokSessionV3} from './MediaSession/SessionOpentok.v3';\nimport {\n KnownMediaStream,\n KnownMediaStreamKind,\n MediaServiceType,\n MediaSessionDisconnectReason,\n MediaStreamUnregisterReason,\n SessionClientRole\n} from './MediaConstants';\n\nimport {throwableGuard} from '@techsee/techsee-common/lib/core/guards';\n\nimport {getMediaTracer} from './MediaUtils/MediaTracer';\n\nconst trace = getMediaTracer('MediaServiceBase');\nconst traceStatsInfo = debounce(trace.info, 1000 * 5, {leading: true, maxWait: 1000 * 30});\n\nenum privateEvents {\n STREAM_CREATED = 'STREAM_CREATED',\n STREAM_DESTROYED = 'STREAM_DESTROYED'\n}\n\nexport abstract class TechseeMediaServiceBase {\n //This method should not be called. The only place that allowed to use it, is initLocalMediaStreams method.\n //Everyone who need to initialize MediaStream should use initLocalMediaStreams method.\n protected abstract getLocalMediaImplementation(): Promise<void>;\n\n protected abstract createMediaPublisher(destinationRole: SessionClientRole): Promise<Nullable<TechseeMediaPublisher>>;\n\n protected readonly _environment: IMediaEnvironment;\n protected readonly _sessionStreamsManager: ISessionStreamsManager;\n protected readonly _localStreamsManager: LocalStreamManager;\n\n private readonly _deviceSupportFlags: DeviceSupportInfo;\n private readonly _subscribers: Map<HTMLDivElement, TechseeMediaSubscriber> = new Map();\n private readonly _publishers: Map<SessionClientRole, TechseeMediaPublisher> = new Map();\n private readonly _publisherPromises: Map<SessionClientRole, Promise<Nullable<MediaStream>>> = new Map();\n private _serviceOptions: Nullable<MediaServiceOptions> = null;\n\n private readonly _emitter: EventEmitter;\n private _initLocalStreamsPromise: Nullable<Promise<void>> = null;\n private _initServicePromise: Nullable<Promise<void>> = null;\n private _registeredStreams: Map<KnownMediaStream, TechseeMediaStream> = new Map();\n private _isVoipEnabled: boolean = false;\n private _session: Nullable<{\n params: MediaSessionParams;\n connectPromise?: Promise<void>;\n instance?: IMediaSession;\n }> = null;\n\n protected constructor(environment: IMediaEnvironment, webRtcSupportInfo: ClientWebRtcInfo) {\n trace.info('TechseeMediaServiceBase created');\n\n this.bindClassMethods();\n\n this._emitter = new EventEmitter();\n this._environment = environment;\n this._deviceSupportFlags = {\n videoPlayback: false,\n hasCamera: false,\n hasMicrophone: false,\n webRtcSupportInfo: webRtcSupportInfo\n };\n\n this._localStreamsManager = new LocalStreamManager(this._environment);\n\n this._sessionStreamsManager = {\n getMediaStreamForRole: this.getStreamForDestinationRole,\n addRemoteMediaTrack: this.registerRemoteMediaTrack,\n removeMediaTrack: this.unregisterRemoteMediaTrack\n };\n }\n\n get deviceSupportInfo(): DeviceSupportInfo {\n this.serviceInitGuard(false);\n\n return cloneDeep(this._deviceSupportFlags);\n }\n\n get isVoipEnabled(): boolean {\n return this._isVoipEnabled;\n }\n\n get isSessionActive(): boolean {\n return this._session !== null;\n }\n\n get isLocalStreamInitialized(): boolean {\n return this._initLocalStreamsPromise !== null;\n }\n\n /*\n Initializes media service. Before using anything from this service it should be initialized first.\n All of serviceOptions should be retrieved from account settings and by evaluating application state.\n For example, when initializing service, accountSettings is already loaded, and we know if FS session is audio enabled.\n */\n initMediaService(serviceOptions: MediaServiceOptions): Promise<void> {\n trace.info('TechseeMediaServiceBase.initMediaService', serviceOptions);\n const warnMessage = 'Multiple initialization does not supposed to happen. Not rejecting, but check the flow for correctness.';\n\n if (this._initServicePromise || this._serviceOptions) {\n console.warn(warnMessage);\n\n return this._initServicePromise ? this._initServicePromise : Promise.resolve();\n }\n\n this._serviceOptions = cloneDeep(serviceOptions);\n const isOpenTok = this._serviceOptions.mediaServiceType === MediaServiceType.OPENTOK;\n\n this._initServicePromise = Promise.all([\n isVideoPlaySupportedOnDevice(isOpenTok)\n .then((isSupported: boolean) => this._deviceSupportFlags.videoPlayback = isSupported),\n enumerateMediaDevices()\n .catch((error) => {\n trace.warn(error);\n\n return [];\n })\n .then((localDevicesList: MediaDeviceInfo[]) => {\n const groupedDevices = {\n video: filter(localDevicesList, (device) => device.kind.toLowerCase() === 'videoinput'),\n audio: filter(localDevicesList, (device) => device.kind.toLowerCase() === 'audioinput')\n };\n\n this._deviceSupportFlags.hasCamera = groupedDevices.video.length > 0;\n this._deviceSupportFlags.hasMicrophone = groupedDevices.audio.length > 0;\n })\n ]).then(() => undefined);\n\n\n return this._initServicePromise;\n }\n\n //#region Media Streams Management\n\n /*\n The main method to start the initialization of local media streams.\n This method can be executed many times and it will insure all calls are synced and only relevant stream will be created.\n DO NOT USE ANY OTHER METHOD THAT FORCES \"navigator.getUserMedia\" OTHER THAN THIS ONE.\n */\n initLocalMediaStreams(): Promise<void> {\n this.serviceInitGuard();\n\n if (!this._initLocalStreamsPromise) {\n trace.info('initLocalMediaStreams creating media streams');\n this._initLocalStreamsPromise = this.getLocalMediaImplementation()\n .catch((mediaRequestFailResult: MediaRequestFailResult) => {\n trace.error('initLocalMediaStreams failure: ', mediaRequestFailResult);\n throw mediaRequestFailResult;\n });\n } else {\n trace.info('initLocalMediaStreams already done or in progress');\n }\n\n return this._initLocalStreamsPromise;\n }\n\n /*\n Creates an instance of subscriber that will \"listen\" to the requested stream.\n Whenever requested stream is available, subscriber will render it.\n */\n createSubscriber(subscriberParams: MediaSubscriberParams): Promise<IMediaSubscriber> {\n if (this._subscribers.has(subscriberParams.container)) {\n return Promise.reject('Subscriber for provided DIV element already exists');\n }\n\n const subscriber = new TechseeMediaSubscriber(subscriberParams);\n\n this._subscribers.set(subscriberParams.container, subscriber);\n const streamForSubscriber = this.getRegisteredStreamByType(subscriber.streamType);\n\n if (streamForSubscriber) {\n trace.info(`Stream for ${subscriberParams.streamType} is ready.`);\n subscriber.renderStream(streamForSubscriber);\n } else {\n trace.info(`Stream for ${subscriberParams.streamType} not created yet`);\n }\n\n return Promise.resolve(subscriber);\n }\n\n /*\n Destroys the subscriber for provided HTML DIV container\n */\n destroySubscriber(container: HTMLDivElement): Promise<void> {\n if (this._subscribers.has(container)) {\n const subscriber = this._subscribers.get(container);\n\n subscriber!.dispose();\n }\n\n this._subscribers.delete(container);\n\n return Promise.resolve();\n }\n\n onStreamDestroyed(callback: (eventArgs: StreamDestroyedEventArgs) => void): void {\n this.registerEventCallback(privateEvents.STREAM_DESTROYED, callback);\n }\n\n onStreamCreated(callback: (eventArgs: StreamCreatedEventArgs) => void): void {\n this.registerEventCallback(privateEvents.STREAM_CREATED, callback);\n }\n\n //#endregion Media Streams Management\n\n //#region Session Management\n\n /*\n Creates instance of WebRTC session which connects to (signaling server), and begins to listen to WebRTC events.\n */\n connectToSession(sessionParams: MediaSessionParams): Promise<void> {\n this.serviceInitGuard();\n\n if (!this._session) {\n this._session = {params: cloneDeep(sessionParams)};\n this._session.connectPromise = new Promise((resolve, reject) => {\n const doAsyncReject = (error: any): void => {\n\n /*\n Reject with timeout, to change JS 'execution flow'.\n If timeout removed, session is assigned to null, before promise returns, and \"catch\" will not\n work on promise that is returned.\n */\n setTimeout(() => {\n this._session = null;\n reject(error);\n });\n };\n\n const sessionHandlers: MediaSessionHandlers = {\n onDisconnectedHandler: this.onSessionDisconnectHandler\n };\n\n trace.info('connectToSession', sessionParams);\n if (this._serviceOptions!.mediaServiceType === MediaServiceType.TURNSERVER) {\n this._session!.instance = new TurnWebRtcSessionV3(sessionParams, sessionHandlers, this._sessionStreamsManager);\n\n } else if (this._serviceOptions!.mediaServiceType === MediaServiceType.OPENTOK) {\n this._session!.instance = new OpentokSessionV3(sessionParams, this._sessionStreamsManager);\n } else {\n const allowedValues = values(MediaServiceType);\n\n trace.error(`mediaServiceType '${this._serviceOptions!.mediaServiceType}' is not supported.`, {allowedValues});\n doAsyncReject(new Error('mediaServiceType is not supported'));\n }\n\n if (this._session && this._session.instance) {\n this._session!.instance.connect()\n .then(() => {\n trace.info('Session is connected');\n resolve();\n })\n .catch((error: any) => {\n trace.error('Failed to connect to session', error);\n doAsyncReject(error);\n });\n }\n\n });\n } else {\n trace.warn('Session connected already. Disconnect before connect to new session again');\n }\n\n //TODO - Alex: Change a structure of this function to be more safe\n //(when we return, there should not be case when session or promise is null)\n //To fix, need to return promise immediately, then execute process in setTimeout(fn, 0);\n return this._session!.connectPromise!;\n }\n\n /*\n Disconnects from WebRTC session.\n */\n disconnectFromSession(): Promise<void> {\n if (!this._session) {\n return Promise.resolve();\n }\n\n const lastSession = this._session;\n\n this._session = null;\n\n trace.info('Disconnecting from session');\n\n return Promise.all([\n lastSession.instance!.disconnect(),\n this.clearPublishers()\n ]).then(() => undefined);\n }\n\n /*\n Updates a credentials for turn server\n */\n updateSessionCredentials(credentials: MediaSessionIceCredentials): Promise<void> {\n trace.info('updateSessionCredentials');\n if (!this.sessionExistsGuard(false)) {\n return Promise.reject('There no session to update credentials');\n }\n\n this._session!.params.credentials = cloneDeep(credentials);\n\n return Promise.resolve();\n }\n\n enableVoipDuringSession(): void {\n if (!this._isVoipEnabled && this.isLocalStreamInitialized) {\n throw new Error('Voip support cannot be enabled after local stream where initialized');\n }\n\n this._isVoipEnabled = true;\n }\n\n protected getStatsForRemoteTrack(streamType: KnownMediaStream): Promise<RemoteTrackStats> {\n if (!this.sessionExistsGuard(false)) {\n return Promise.reject(new Error('Media session not started'));\n }\n\n const streamForStats = this.getRegisteredStreamByType(streamType);\n\n if (!streamForStats) {\n return Promise.reject(new Error('Stream for requested type was not found'));\n }\n\n return this._session!.instance!.getRemoteTrackStats(streamForStats.mediaTrack)\n .then((trackStats: RemoteTrackStats) => {\n traceStatsInfo(`MediaTrackStats for ${streamType}: ${JSON.stringify(trackStats)}`);\n\n return {\n trackId: streamForStats.mediaTrack.id,\n trackStats: trackStats\n };\n });\n }\n\n private onSessionDisconnectHandler(reason: MediaSessionDisconnectReason): void {\n trace.info('onSessionDisconnectHandler', reason);\n if (reason !== MediaSessionDisconnectReason.ForcedByConsumer) {\n const lastParams = this._session && this._session.params ? this._session.params : null;\n\n this.disconnectFromSession().then(() => {\n if (lastParams && reason === MediaSessionDisconnectReason.UserPeerReconnected) {\n trace.info('Reconnecting to media session, sessionParams:', lastParams);\n this.connectToSession(lastParams)\n .then(() => {\n trace.info('Media session reconnected');\n })\n .catch((error: any) => {\n trace.error('Error while reconnecting to media session');\n });\n }\n });\n } else {\n trace.info('Ignore Session disconnect event');\n }\n }\n\n //#endregion Session Management\n\n //#region Utils\n\n getSnapshotFromKnownStream(sourceStream: KnownMediaStream, snapshotOptions?: SnapshotOptions): Promise<SnapshotResult> {\n return new Promise((resolve, reject) => {\n if (sourceStream !== KnownMediaStream.USER_VIDEO_STREAM &&\n sourceStream !== KnownMediaStream.USER_SCREEN_SHARE_STREAM) {\n trace.error('The requested stream is not video stream, and cannot be used for snapshot');\n reject(new Error('INCOMPATIBLE_STREAM_FOR_SNAPSHOT'));\n\n return;\n }\n\n const snapshotStream = this.getRegisteredStreamByType(sourceStream);\n\n if (!snapshotStream) {\n trace.error('Cannot make snapshot: The requested stream not exists yet.');\n reject(new Error('NO_REQUESTED_STREAM'));\n\n return;\n }\n\n getSnapshotFromMediaStream(snapshotStream.mediaStream, snapshotOptions)\n .then((imageData: any) => {\n const urlComponents = imageData.split(';base64,');\n const mimeType = urlComponents[0].split(':')[1];\n const bytes = atob(urlComponents[1]);\n const buffer = new ArrayBuffer(bytes.length);\n const rawData = new Uint8Array(buffer);\n\n for (let i = 0; i < bytes.length; i++) {\n rawData[i] = bytes.charCodeAt(i);\n }\n\n const blob = new Blob([rawData], {type: mimeType});\n const objectUrl = window.URL.createObjectURL(blob);\n\n trace.info('Snapshot created successfully');\n\n const result: SnapshotResult = {\n base64img: imageData,\n objectUrl: objectUrl,\n imageBlob: blob,\n mimeType: mimeType\n };\n\n resolve(result);\n })\n .catch((error: any) => {\n trace.error('Error creating snapshot', error);\n reject(error);\n });\n });\n }\n\n //Will clean streams, publishers and subscribers, but will not remove event listeners\n clearService(): Promise<void> {\n trace.info('MediaService clearing all resources');\n\n return this.disconnectFromSession()\n .then(this.clearSubscribers)\n .then(this.clearRegisteredStreams)\n .then(this._localStreamsManager.clearAllStreams)\n .then(() => {\n this._initLocalStreamsPromise = null;\n }).then(() => undefined);\n }\n\n //Will clear the service and remove all event listeners\n dispose(): Promise<void> {\n return this.clearService().catch(() => undefined).then(() => {\n this._emitter.removeAllListeners();\n });\n }\n\n //#endregion\n\n //#region Protected Methods\n\n protected get subscribers(): Map<HTMLDivElement, TechseeMediaSubscriber> {\n return this._subscribers;\n }\n\n protected registerLocalMediaStream(tsMediaStream: TechseeMediaStream): Promise<void> {\n trace.info('Registering local stream', tsMediaStream.streamType);\n if (this._registeredStreams.has(tsMediaStream.streamType)) {\n return Promise.reject(new Error(`Stream ${tsMediaStream.streamType} already registered`));\n }\n\n return this.registerStream(tsMediaStream);\n }\n\n protected getRegisteredStreamByType(streamType: KnownMediaStream): Nullable<TechseeMediaStream> {\n return this._registeredStreams.get(streamType) || null;\n }\n\n protected changeEnableForKnownStream(streamType: KnownMediaStream, isPaused: boolean): void {\n const streamToChangeState = this.getRegisteredStreamByType(streamType);\n\n if (!streamToChangeState) {\n trace.warn('There no stream found to change enable state', streamType);\n } else {\n streamToChangeState.mediaTrack.enabled = !isPaused;\n\n if (streamToChangeState.isRemote && streamToChangeState.streamKind === KnownMediaStreamKind.Audio) {\n this.subscribers.forEach((subscriber) => {\n if (subscriber.streamType === streamType) {\n subscriber.muteSound(isPaused);\n }\n });\n }\n\n trace.info('Local stream enable state is changed', {streamType, isPaused});\n }\n }\n\n protected registerEventCallback(event: string, callback: (eventArgs?: any) => void): void {\n this._emitter.on(event, callback);\n }\n\n protected emitEvent(event: string, eventArgs?: any): void {\n setTimeout(() => {\n this._emitter.emit(event, eventArgs);\n });\n }\n\n //#endregion Protected Methods\n\n //#region Private Methods\n\n private registerRemoteMediaTrack(remoteMediaTrack: RemoteMediaTrack): Promise<void> {\n trace.info(`Registering remote ${remoteMediaTrack.trackType} MediaStreamTrack`, remoteMediaTrack.mediaTrack);\n const currentStream = this._registeredStreams.get(remoteMediaTrack.trackType);\n\n if (currentStream && !currentStream.isRemote) {\n return Promise.reject(new Error('Cannot register remote stream with the same type as local stream'));\n }\n\n const newDedicatedStream = new TechseeMediaStream(remoteMediaTrack.mediaTrack, remoteMediaTrack.trackType, true);\n\n return this.registerStream(newDedicatedStream);\n }\n\n private registerStream(mediaStream: TechseeMediaStream): Promise<void> {\n const currentStream = this._registeredStreams.get(mediaStream.streamType);\n\n const registerTrack = (): Promise<void> => {\n mediaStream.mediaTrack.onended = () =>\n this.unregisterTechseeMediaStream(mediaStream, MediaStreamUnregisterReason.NativeEvent);\n\n this._registeredStreams.set(mediaStream.streamType, mediaStream);\n\n trace.info(`TechseeMediaStream registered - ${mediaStream.streamType}`, TechseeMediaStream);\n\n return this.updateSubscribersWithNewStream(mediaStream).then(() => {\n const eventArgs: StreamCreatedEventArgs = {streamType: mediaStream.streamType};\n\n this.emitEvent(privateEvents.STREAM_CREATED, eventArgs);\n });\n };\n\n if (currentStream) {\n return this.unregisterTechseeMediaStream(currentStream, MediaStreamUnregisterReason.ReplacingStream).then(registerTrack);\n }\n\n return registerTrack();\n\n }\n\n private unregisterTechseeMediaStream(streamToUnregister: TechseeMediaStream, reason: MediaStreamUnregisterReason): Promise<void> {\n const traceError = (error: any): void => {\n trace.warn('Unregister TechseeMediaStream error:', error);\n };\n\n const promises: any = [];\n\n trace.info('Unregister TechseeMediaStream: ', streamToUnregister.streamType);\n\n this._subscribers.forEach((subscriber) => {\n if (subscriber.streamType === streamToUnregister.streamType) {\n promises.push(subscriber.stopRendering().catch(traceError));\n }\n });\n\n if (!streamToUnregister.isRemote) {\n this._publishers.forEach((publisher: TechseeMediaPublisher) => {\n if (publisher.streamTypes.find((streamType) => streamType === streamToUnregister.streamType)) {\n if (this._session && this._session!.instance) {\n promises.push(this._session.instance.onMediaStreamDestroyed(publisher.destinationRole).catch(traceError));\n }\n }\n });\n }\n\n return Promise.all(promises)\n .then(() => {\n this._registeredStreams.delete(streamToUnregister.streamType);\n trace.info('Stream deleted', streamToUnregister.streamType);\n\n const eventArgs: StreamDestroyedEventArgs = {streamType: streamToUnregister.streamType, reason: reason};\n\n this.emitEvent(privateEvents.STREAM_DESTROYED, eventArgs);\n });\n }\n\n private unregisterRemoteMediaTrack(mediaTrack: MediaStreamTrack): Promise<void> {\n const promises: any = [];\n\n this._registeredStreams.forEach((registeredStream: TechseeMediaStream) => {\n if (registeredStream.mediaTrack.id === mediaTrack.id) {\n promises.push(this.unregisterTechseeMediaStream(registeredStream, MediaStreamUnregisterReason.ClosedRemotely));\n }\n });\n\n return Promise.all(promises).then(() => undefined);\n }\n\n private removePublisher(publisher: TechseeMediaPublisher): Promise<void> {\n this._publishers.delete(publisher.destinationRole);\n if (this._session && this._session.instance) {\n trace.info('Removing publisher', publisher.destinationRole);\n\n return this._session.instance.onMediaStreamDestroyed(publisher.destinationRole)\n .catch((error: any) => {\n trace.warn('Error while removing publisher', error);\n });\n }\n\n return Promise.resolve();\n }\n\n private getStreamForDestinationRole(destinationRole: SessionClientRole): Promise<Nullable<MediaStream>> {\n this.serviceInitGuard();\n\n if (this._publishers.has(destinationRole)) {\n trace.info(`Publisher for ${destinationRole} already exists`);\n\n return Promise.resolve(this._publishers.get(destinationRole)!.mediaStream);\n }\n\n if (!this._publisherPromises.get(destinationRole)) {\n trace.info(`Creating publisher for ${destinationRole}`);\n const publisherPromise = this.initLocalMediaStreams()\n .then(() => this.createMediaPublisher(destinationRole))\n .then((mediaPublisher: Nullable<TechseeMediaPublisher>) => {\n if (mediaPublisher) {\n this._publishers.set(destinationRole, mediaPublisher);\n }\n\n this._publisherPromises.delete(destinationRole);\n\n return mediaPublisher ? mediaPublisher.mediaStream : null;\n })\n .catch((ex: any) => {\n this._publisherPromises.delete(destinationRole);\n throw ex;\n });\n\n this._publisherPromises.set(destinationRole, publisherPromise);\n } else {\n trace.info(`Create publisher promise for ${destinationRole} already exists`);\n }\n\n return this._publisherPromises.get(destinationRole)!;\n }\n\n private updateSubscribersWithNewStream(registeredStream: TechseeMediaStream): Promise<void> {\n trace.info(`Updating subscribers of ${registeredStream.streamType} with new stream`);\n\n if (this._subscribers.size === 0) {\n trace.warn(`No subscribers exists for the ${registeredStream.streamType}.`);\n } else {\n trace.info(`Total ${this._subscribers.size} subscribers exists, will check if rerender needed.`);\n }\n\n this._subscribers.forEach((subscriber) => {\n if (subscriber.streamType === registeredStream.streamType) {\n trace.info(`${registeredStream.streamType} rendering on subscriber`);\n subscriber.renderStream(registeredStream);\n }\n });\n\n return Promise.resolve();\n }\n\n private bindClassMethods(): void {\n this.updateSessionCredentials = this.updateSessionCredentials.bind(this);\n this.getStreamForDestinationRole = this.getStreamForDestinationRole.bind(this);\n this.registerRemoteMediaTrack = this.registerRemoteMediaTrack.bind(this);\n this.unregisterRemoteMediaTrack = this.unregisterRemoteMediaTrack.bind(this);\n this.createMediaPublisher = this.createMediaPublisher.bind(this);\n this.updateSubscribersWithNewStream = this.updateSubscribersWithNewStream.bind(this);\n this.initLocalMediaStreams = this.initLocalMediaStreams.bind(this);\n this.onSessionDisconnectHandler = this.onSessionDisconnectHandler.bind(this);\n this.clearService = this.clearService.bind(this);\n this.clearRegisteredStreams = this.clearRegisteredStreams.bind(this);\n this.clearPublishers = this.clearPublishers.bind(this);\n this.clearSubscribers = this.clearSubscribers.bind(this);\n }\n\n //region Cleanup\n\n private clearRegisteredStreams(): Promise<void> {\n trace.info('Clearing registered streams');\n const promises: any = [];\n\n this._registeredStreams.forEach((streamToUnregister: TechseeMediaStream) => {\n promises.push(this.unregisterTechseeMediaStream(streamToUnregister, MediaStreamUnregisterReason.ServiceCleanUp));\n });\n\n return Promise.all(promises).then(() => undefined);\n }\n\n private clearSubscribers(): Promise<void> {\n trace.info('Clearing subscribers');\n const promises: any = [];\n\n this._subscribers.forEach((subscriber) => {\n promises.push(this.destroySubscriber(subscriber.container));\n });\n\n return Promise.all(promises).then(() => undefined);\n }\n\n private clearPublishers(): Promise<void> {\n trace.info('Clearing publishers');\n const promises: any = [];\n\n this._publishers.forEach((publisher) => {\n promises.push(this.removePublisher(publisher));\n });\n\n return Promise.all(promises).then(() => undefined);\n }\n\n //#endregion Cleanup\n\n //#region Simple Validation Methods\n\n protected serviceInitGuard(shouldThrow = true): boolean {\n return throwableGuard(!!this._serviceOptions, 'Media service is not initialized', shouldThrow);\n }\n\n protected sessionExistsGuard(shouldThrow = true): boolean {\n return throwableGuard(!!this._session, 'There no active session', shouldThrow);\n }\n\n //#endregion\n\n //#endregion Private Methods\n}\n"]}
@@ -12,13 +12,13 @@ var events_1 = require("events");
12
12
  var MediaSubscriber_1 = require("./MediaSubscriber");
13
13
  var LocalStreamManager_1 = require("./LocalStreamManager");
14
14
  var TechseeMediaStream_1 = require("./TechseeMediaStream");
15
- var SessionTurn_v3_1 = require("./Session/SessionTurn.v3");
16
- var MediaDomUtils_1 = require("./Utils/MediaDomUtils");
17
- var Compatibility_1 = require("./Utils/Compatibility");
18
- var SessionOpentok_v3_1 = require("./Session/SessionOpentok.v3");
15
+ var SessionTurn_v3_1 = require("./MediaSession/SessionTurn.v3");
16
+ var MediaDomUtils_1 = require("./MediaUtils/MediaDomUtils");
17
+ var Compatibility_1 = require("./MediaUtils/Compatibility");
18
+ var SessionOpentok_v3_1 = require("./MediaSession/SessionOpentok.v3");
19
19
  var MediaConstants_1 = require("./MediaConstants");
20
20
  var guards_1 = require("@techsee/techsee-common/lib/core/guards");
21
- var MediaTracer_1 = require("./Utils/MediaTracer");
21
+ var MediaTracer_1 = require("./MediaUtils/MediaTracer");
22
22
  var trace = MediaTracer_1.getMediaTracer('MediaServiceBase');
23
23
  var traceStatsInfo = debounce_1.default(trace.info, 1000 * 5, { leading: true, maxWait: 1000 * 30 });
24
24
  var privateEvents;