1 const videoConstraint: {width : any, height: any, facingMode : string} = {
2 width: { ideal: 1280 },
3 height: { ideal: 720 },
6 export class MediaManager {
7 localStream: MediaStream|null = null;
8 remoteVideo: Array<any> = new Array<any>();
9 myCamVideo: HTMLVideoElement;
10 cinemaClose: any = null;
12 microphoneClose: any = null;
13 microphone: any = null;
14 webrtcInAudio: HTMLAudioElement;
15 constraintsMedia : {audio : any, video : any} = {
17 video: videoConstraint
19 updatedLocalStreamCallBack : Function;
21 constructor(updatedLocalStreamCallBack : Function) {
22 this.updatedLocalStreamCallBack = updatedLocalStreamCallBack;
24 this.myCamVideo = this.getElementByIdOrFail<HTMLVideoElement>('myCamVideo');
25 this.webrtcInAudio = this.getElementByIdOrFail<HTMLAudioElement>('audio-webrtc-in');
26 this.webrtcInAudio.volume = 0.2;
28 this.microphoneClose = document.getElementById('microphone-close');
29 this.microphoneClose.style.display = "none";
30 this.microphoneClose.addEventListener('click', (e: any) => {
32 this.enabledMicrophone();
35 this.microphone = document.getElementById('microphone');
36 this.microphone.addEventListener('click', (e: any) => {
38 this.disabledMicrophone();
42 this.cinemaClose = document.getElementById('cinema-close');
43 this.cinemaClose.style.display = "none";
44 this.cinemaClose.addEventListener('click', (e: any) => {
49 this.cinema = document.getElementById('cinema');
50 this.cinema.addEventListener('click', (e: any) => {
52 this.disabledCamera();
58 let webRtc = this.getElementByIdOrFail('webRtc');
59 webRtc.classList.add('active');
63 this.cinemaClose.style.display = "none";
64 this.cinema.style.display = "block";
65 this.constraintsMedia.video = videoConstraint;
66 this.getCamera().then((stream) => {
67 this.updatedLocalStreamCallBack(stream);
72 this.cinemaClose.style.display = "block";
73 this.cinema.style.display = "none";
74 this.constraintsMedia.video = false;
75 this.myCamVideo.srcObject = null;
76 if (this.localStream) {
77 this.localStream.getVideoTracks().forEach((MediaStreamTrack: MediaStreamTrack) => {
78 MediaStreamTrack.stop();
81 this.getCamera().then((stream) => {
82 this.updatedLocalStreamCallBack(stream);
87 this.microphoneClose.style.display = "none";
88 this.microphone.style.display = "block";
89 this.constraintsMedia.audio = true;
90 this.getCamera().then((stream) => {
91 this.updatedLocalStreamCallBack(stream);
95 disabledMicrophone() {
96 this.microphoneClose.style.display = "block";
97 this.microphone.style.display = "none";
98 this.constraintsMedia.audio = false;
99 if(this.localStream) {
100 this.localStream.getAudioTracks().forEach((MediaStreamTrack: MediaStreamTrack) => {
101 MediaStreamTrack.stop();
104 this.getCamera().then((stream) => {
105 this.updatedLocalStreamCallBack(stream);
113 promise = navigator.mediaDevices.getUserMedia(this.constraintsMedia)
114 .then((stream: MediaStream) => {
115 this.localStream = stream;
116 this.myCamVideo.srcObject = this.localStream;
118 //TODO resize remote cam
119 /*console.log(this.localStream.getTracks());
120 let videoMediaStreamTrack = this.localStream.getTracks().find((media : MediaStreamTrack) => media.kind === "video");
121 let {width, height} = videoMediaStreamTrack.getSettings();
122 console.info(`${width}x${height}`); // 6*/
126 console.info(`error get media {video: ${this.constraintsMedia.video}},{audio: ${this.constraintsMedia.audio}}`,err);
127 this.localStream = null;
130 promise = Promise.reject(false);
139 addActiveVideo(userId : string, userName: string = ""){
140 this.webrtcInAudio.play();
141 let elementRemoteVideo = this.getElementByIdOrFail("activeCam");
142 userName = userName.toUpperCase();
143 let color = this.getColorByString(userName);
144 elementRemoteVideo.insertAdjacentHTML('beforeend', `
145 <div id="div-${userId}" class="video-container" style="border-color: ${color};">
146 <div class="connecting-spinner"></div>
147 <div class="rtc-error" style="display: none"></div>
148 <i style="background-color: ${color};">${userName}</i>
149 <img id="microphone-${userId}" src="resources/logos/microphone-close.svg">
150 <video id="${userId}" autoplay></video>
153 this.remoteVideo[(userId as any)] = document.getElementById(userId);
160 disabledMicrophoneByUserId(userId: string){
161 let element = document.getElementById(`microphone-${userId}`);
165 element.classList.add('active')
172 enabledMicrophoneByUserId(userId: string){
173 let element = document.getElementById(`microphone-${userId}`);
177 element.classList.remove('active')
184 disabledVideoByUserId(userId: string) {
185 let element = document.getElementById(`${userId}`);
187 element.style.opacity = "0";
189 element = document.getElementById(`div-${userId}`);
193 element.style.borderStyle = "solid";
200 enabledVideoByUserId(userId: string){
201 let element = document.getElementById(`${userId}`);
203 element.style.opacity = "1";
205 element = document.getElementById(`div-${userId}`);
209 element.style.borderStyle = "none";
217 addStreamRemoteVideo(userId : string, stream : MediaStream){
218 this.remoteVideo[(userId as any)].srcObject = stream;
225 removeActiveVideo(userId : string){
226 let element = document.getElementById(`div-${userId}`);
233 isConnecting(userId : string): void {
234 let connectingSpinnerDiv = this.getSpinner(userId);
235 if (connectingSpinnerDiv === null) {
238 connectingSpinnerDiv.style.display = 'block';
241 isConnected(userId : string): void {
242 let connectingSpinnerDiv = this.getSpinner(userId);
243 if (connectingSpinnerDiv === null) {
246 connectingSpinnerDiv.style.display = 'none';
249 isError(userId : string): void {
250 let element = document.getElementById(`div-${userId}`);
254 let errorDiv = element.getElementsByClassName('rtc-error').item(0) as HTMLDivElement|null;
255 if (errorDiv === null) {
258 errorDiv.style.display = 'block';
261 private getSpinner(userId : string): HTMLDivElement|null {
262 let element = document.getElementById(`div-${userId}`);
266 let connnectingSpinnerDiv = element.getElementsByClassName('connecting-spinner').item(0) as HTMLDivElement|null;
267 return connnectingSpinnerDiv;
274 private getColorByString(str: String) : String|null {
276 if (str.length === 0) return null;
277 for (let i = 0; i < str.length; i++) {
278 hash = str.charCodeAt(i) + ((hash << 5) - hash);
282 for (let i = 0; i < 3; i++) {
283 let value = (hash >> (i * 8)) & 255;
284 color += ('00' + value.toString(16)).substr(-2);
289 private getElementByIdOrFail<T extends HTMLElement>(id: string): T {
290 let elem = document.getElementById(id);
292 throw new Error("Cannot find HTML element with id '"+id+"'");
294 // FIXME: does not check the type of the returned type