@flashphoner/sfusdk-examples 2.0.132 → 2.0.136
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.
- package/package.json +1 -1
- package/src/commons/js/display.js +106 -30
- package/src/player/player.js +5 -1
- package/src/two-way-streaming/two-way-streaming.js +5 -1
- package/src/webrtc-abr-player/player.css +27 -0
- package/src/webrtc-abr-player/player.html +49 -0
- package/src/webrtc-abr-player/player.js +191 -0
package/package.json
CHANGED
|
@@ -57,11 +57,11 @@ const initLocalDisplay = function(localDisplayElement){
|
|
|
57
57
|
coreDisplay.setAttribute("class","text-center");
|
|
58
58
|
coreDisplay.setAttribute("style","width: auto; height: auto;");
|
|
59
59
|
coreDisplay.id = stream.id;
|
|
60
|
-
const
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
coreDisplay.appendChild(
|
|
60
|
+
const publisherNameDisplay = document.createElement("div");
|
|
61
|
+
publisherNameDisplay.innerHTML = "Name: " + name;
|
|
62
|
+
publisherNameDisplay.setAttribute("class","text-center");
|
|
63
|
+
publisherNameDisplay.setAttribute("style","width: auto; height: auto;");
|
|
64
|
+
coreDisplay.appendChild(publisherNameDisplay);
|
|
65
65
|
|
|
66
66
|
const audioStateDisplay = document.createElement("button");
|
|
67
67
|
audioStateDisplay.innerHTML = audioStateText(stream);
|
|
@@ -102,7 +102,7 @@ const initLocalDisplay = function(localDisplayElement){
|
|
|
102
102
|
});
|
|
103
103
|
});
|
|
104
104
|
video.addEventListener('resize', function (event) {
|
|
105
|
-
|
|
105
|
+
publisherNameDisplay.innerHTML = "Name: " + name + "<br/>Max.resolution: " + video.videoWidth + "x" + video.videoHeight;
|
|
106
106
|
resizeVideo(event.target);
|
|
107
107
|
});
|
|
108
108
|
localDisplays[id] = coreDisplay;
|
|
@@ -133,9 +133,25 @@ const initLocalDisplay = function(localDisplayElement){
|
|
|
133
133
|
}
|
|
134
134
|
}
|
|
135
135
|
|
|
136
|
-
const initRemoteDisplay = function(
|
|
136
|
+
const initRemoteDisplay = function(options) {
|
|
137
137
|
const constants = SFU.constants;
|
|
138
138
|
const remoteParticipants = {};
|
|
139
|
+
// Validate options first
|
|
140
|
+
if (!options.div) {
|
|
141
|
+
throw new Error("Main div to place all the media tag is not defined");
|
|
142
|
+
}
|
|
143
|
+
if (!options.room) {
|
|
144
|
+
throw new Error("Room is not defined");
|
|
145
|
+
}
|
|
146
|
+
if (!options.peerConnection) {
|
|
147
|
+
throw new Error("PeerConnection is not defined");
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
let mainDiv = options.div;
|
|
151
|
+
let room = options.room;
|
|
152
|
+
let peerConnection = options.peerConnection;
|
|
153
|
+
let displayOptions = options.displayOptions || {publisher: true, quality: true};
|
|
154
|
+
|
|
139
155
|
room.on(constants.SFU_ROOM_EVENT.ADD_TRACKS, function(e) {
|
|
140
156
|
console.log("Received ADD_TRACKS");
|
|
141
157
|
let participant = remoteParticipants[e.info.nickName];
|
|
@@ -171,7 +187,7 @@ const initRemoteDisplay = function(mainDiv, room, peerConnection) {
|
|
|
171
187
|
if (!createDisplay) {
|
|
172
188
|
continue;
|
|
173
189
|
}
|
|
174
|
-
let display = createRemoteDisplay(participant.nickName, participant.nickName, mainDiv);
|
|
190
|
+
let display = createRemoteDisplay(participant.nickName, participant.nickName, mainDiv, displayOptions);
|
|
175
191
|
participant.displays.push(display);
|
|
176
192
|
if (pTrack.type === "VIDEO") {
|
|
177
193
|
display.videoMid = pTrack.mid;
|
|
@@ -241,20 +257,31 @@ const initRemoteDisplay = function(mainDiv, room, peerConnection) {
|
|
|
241
257
|
}
|
|
242
258
|
});
|
|
243
259
|
|
|
244
|
-
const createRemoteDisplay = function(id, name, mainDiv) {
|
|
260
|
+
const createRemoteDisplay = function(id, name, mainDiv, displayOptions) {
|
|
245
261
|
const cell = document.createElement("div");
|
|
246
262
|
cell.setAttribute("class", "text-center");
|
|
247
263
|
cell.id = id;
|
|
248
264
|
mainDiv.appendChild(cell);
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
265
|
+
let publisherNameDisplay;
|
|
266
|
+
let currentQualityDisplay;
|
|
267
|
+
if (displayOptions.publisher) {
|
|
268
|
+
publisherNameDisplay = document.createElement("div");
|
|
269
|
+
publisherNameDisplay.innerHTML = "Published by: " + name;
|
|
270
|
+
publisherNameDisplay.setAttribute("style","width:auto; height:30px;");
|
|
271
|
+
publisherNameDisplay.setAttribute("class","text-center");
|
|
272
|
+
cell.appendChild(publisherNameDisplay);
|
|
273
|
+
}
|
|
274
|
+
if (displayOptions.quality) {
|
|
275
|
+
currentQualityDisplay = document.createElement("div");
|
|
276
|
+
currentQualityDisplay.innerHTML = "";
|
|
277
|
+
currentQualityDisplay.setAttribute("style","width:auto; height:30px;");
|
|
278
|
+
currentQualityDisplay.setAttribute("class","text-center");
|
|
279
|
+
cell.appendChild(currentQualityDisplay);
|
|
280
|
+
}
|
|
281
|
+
const qualitySwitchDisplay = document.createElement("div");
|
|
282
|
+
qualitySwitchDisplay.setAttribute("style","width:auto; height:30px;");
|
|
283
|
+
qualitySwitchDisplay.setAttribute("class","text-center");
|
|
284
|
+
cell.appendChild(qualitySwitchDisplay);
|
|
258
285
|
|
|
259
286
|
let qualityDivs = [];
|
|
260
287
|
|
|
@@ -293,11 +320,22 @@ const initRemoteDisplay = function(mainDiv, room, peerConnection) {
|
|
|
293
320
|
audio.controls = "controls";
|
|
294
321
|
audio.muted = true;
|
|
295
322
|
audio.autoplay = true;
|
|
323
|
+
if (Browser().isSafariWebRTC()) {
|
|
324
|
+
audio.setAttribute("playsinline", "");
|
|
325
|
+
audio.setAttribute("webkit-playsinline", "");
|
|
326
|
+
this.setWebkitEventHandlers(audio);
|
|
327
|
+
} else {
|
|
328
|
+
this.setEventHandlers(audio);
|
|
329
|
+
}
|
|
296
330
|
cell.appendChild(audio);
|
|
297
331
|
audio.srcObject = stream;
|
|
298
332
|
audio.onloadedmetadata = function (e) {
|
|
299
333
|
audio.play().then(function() {
|
|
300
|
-
|
|
334
|
+
if (Browser().isSafariWebRTC() && Browser().isiOS()) {
|
|
335
|
+
console.warn("Audio track should be manually unmuted in iOS Safari");
|
|
336
|
+
} else {
|
|
337
|
+
audio.muted = false;
|
|
338
|
+
}
|
|
301
339
|
});
|
|
302
340
|
};
|
|
303
341
|
},
|
|
@@ -319,22 +357,19 @@ const initRemoteDisplay = function(mainDiv, room, peerConnection) {
|
|
|
319
357
|
return;
|
|
320
358
|
}
|
|
321
359
|
video = document.createElement("video");
|
|
360
|
+
video.controls = "controls";
|
|
322
361
|
video.muted = true;
|
|
323
|
-
|
|
362
|
+
video.autoplay = true;
|
|
363
|
+
if (Browser().isSafariWebRTC()) {
|
|
324
364
|
video.setAttribute("playsinline", "");
|
|
325
365
|
video.setAttribute("webkit-playsinline", "");
|
|
366
|
+
this.setWebkitEventHandlers(video);
|
|
367
|
+
} else {
|
|
368
|
+
this.setEventHandlers(video);
|
|
326
369
|
}
|
|
327
370
|
streamDisplay.appendChild(video);
|
|
328
371
|
video.srcObject = stream;
|
|
329
|
-
|
|
330
|
-
video.play().then(function() {
|
|
331
|
-
video.muted = false;
|
|
332
|
-
});
|
|
333
|
-
};
|
|
334
|
-
video.addEventListener("resize", function (event) {
|
|
335
|
-
streamNameDisplay.innerHTML = "Published by: " + name + "<br/>Current resolution: " + video.videoWidth + "x" + video.videoHeight;
|
|
336
|
-
resizeVideo(event.target);
|
|
337
|
-
});
|
|
372
|
+
this.setResizeHandler(video);
|
|
338
373
|
},
|
|
339
374
|
setTrackInfo: function(trackInfo) {
|
|
340
375
|
if (trackInfo && trackInfo.quality) {
|
|
@@ -357,7 +392,7 @@ const initRemoteDisplay = function(mainDiv, room, peerConnection) {
|
|
|
357
392
|
qualityDiv.style.color = "blue";
|
|
358
393
|
room.changeQuality(trackInfo.id, trackInfo.quality[i]);
|
|
359
394
|
});
|
|
360
|
-
|
|
395
|
+
qualitySwitchDisplay.appendChild(qualityDiv);
|
|
361
396
|
}
|
|
362
397
|
}
|
|
363
398
|
},
|
|
@@ -378,6 +413,47 @@ const initRemoteDisplay = function(mainDiv, room, peerConnection) {
|
|
|
378
413
|
hasVideo: function() {
|
|
379
414
|
return video !== null || this.videoMid !== undefined;
|
|
380
415
|
},
|
|
416
|
+
setResizeHandler: function(video) {
|
|
417
|
+
video.addEventListener("resize", function (event) {
|
|
418
|
+
if (displayOptions.publisher) {
|
|
419
|
+
publisherNameDisplay.innerHTML = "Published by: " + name;
|
|
420
|
+
}
|
|
421
|
+
if (displayOptions.quality) {
|
|
422
|
+
currentQualityDisplay.innerHTML = video.videoWidth + "x" + video.videoHeight;
|
|
423
|
+
}
|
|
424
|
+
resizeVideo(event.target);
|
|
425
|
+
});
|
|
426
|
+
},
|
|
427
|
+
setEventHandlers: function(video) {
|
|
428
|
+
// Ignore play/pause button
|
|
429
|
+
video.addEventListener("pause", function () {
|
|
430
|
+
console.log("Media paused by click, continue...");
|
|
431
|
+
video.play();
|
|
432
|
+
});
|
|
433
|
+
},
|
|
434
|
+
setWebkitEventHandlers: function(video) {
|
|
435
|
+
let needRestart = false;
|
|
436
|
+
let isFullscreen = false;
|
|
437
|
+
// Use webkitbeginfullscreen event to detect full screen mode in iOS Safari
|
|
438
|
+
video.addEventListener("webkitbeginfullscreen", function () {
|
|
439
|
+
isFullscreen = true;
|
|
440
|
+
});
|
|
441
|
+
video.addEventListener("pause", function () {
|
|
442
|
+
if (needRestart) {
|
|
443
|
+
console.log("Media paused after fullscreen, continue...");
|
|
444
|
+
video.play();
|
|
445
|
+
needRestart = false;
|
|
446
|
+
} else {
|
|
447
|
+
console.log("Media paused by click, continue...");
|
|
448
|
+
video.play();
|
|
449
|
+
}
|
|
450
|
+
});
|
|
451
|
+
video.addEventListener("webkitendfullscreen", function () {
|
|
452
|
+
video.play();
|
|
453
|
+
needRestart = true;
|
|
454
|
+
isFullscreen = false;
|
|
455
|
+
});
|
|
456
|
+
},
|
|
381
457
|
audioMid: undefined,
|
|
382
458
|
videoMid: undefined
|
|
383
459
|
};
|
package/src/player/player.js
CHANGED
|
@@ -166,7 +166,11 @@ const onStopClick = function(state) {
|
|
|
166
166
|
|
|
167
167
|
const playStreams = function(state) {
|
|
168
168
|
//create remote display item to show remote streams
|
|
169
|
-
remoteDisplay = initRemoteDisplay(
|
|
169
|
+
remoteDisplay = initRemoteDisplay({
|
|
170
|
+
div: document.getElementById("remoteVideo"),
|
|
171
|
+
room: state.room,
|
|
172
|
+
peerConnection: state.pc
|
|
173
|
+
});
|
|
170
174
|
state.room.join(state.pc);
|
|
171
175
|
}
|
|
172
176
|
|
|
@@ -300,7 +300,11 @@ const unPublishStreams = function(state) {
|
|
|
300
300
|
const playStreams = function(state) {
|
|
301
301
|
if (state.isConnected() && state.isActive()) {
|
|
302
302
|
//create remote display item to show remote streams
|
|
303
|
-
remoteDisplay = initRemoteDisplay(
|
|
303
|
+
remoteDisplay = initRemoteDisplay({
|
|
304
|
+
div: document.getElementById("remoteVideo"),
|
|
305
|
+
room: state.room,
|
|
306
|
+
peerConnection: state.pc
|
|
307
|
+
});
|
|
304
308
|
state.room.join(state.pc);
|
|
305
309
|
}
|
|
306
310
|
$("#" + state.buttonId()).prop('disabled', false);
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
.fp-remoteVideo {
|
|
2
|
+
width: 802px;
|
|
3
|
+
text-align: center;
|
|
4
|
+
display: inline-block;
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
.fp-placeholder {
|
|
8
|
+
border: 1px double black;
|
|
9
|
+
width: 802px;
|
|
10
|
+
height: 402px;
|
|
11
|
+
text-align: center;
|
|
12
|
+
background: #c0c0c0;
|
|
13
|
+
display: inline-block;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
video, object {
|
|
17
|
+
width: 100%;
|
|
18
|
+
height: 100%;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
video:-webkit-full-screen {
|
|
22
|
+
border-radius: 1px;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
video::-webkit-media-controls-play-button, video::-webkit-media-controls-pause-button {
|
|
26
|
+
display: none !important;
|
|
27
|
+
}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8">
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
6
|
+
<title>WebRTC ABR Player</title>
|
|
7
|
+
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.0-beta3/dist/css/bootstrap.min.css" rel="stylesheet"
|
|
8
|
+
integrity="sha384-eOJMYsd53ii+scO/bJGFsiCZc+5NDVN2yr8+0RDqr0Ql0h+rP48ckxlpbzKgwra6" crossorigin="anonymous">
|
|
9
|
+
<!-- JavaScript Bundle with Popper -->
|
|
10
|
+
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.0-beta3/dist/js/bootstrap.bundle.min.js"
|
|
11
|
+
integrity="sha384-JEW9xMcG8R+pH31jmWH6WWP0WintQrMb4s7ZOdauHnUtxwoG2vI5DkLtS3qm9Ekf"
|
|
12
|
+
crossorigin="anonymous"></script>
|
|
13
|
+
<script src="https://cdn.jsdelivr.net/npm/jquery@3.6.0/dist/jquery.min.js"></script>
|
|
14
|
+
<link rel="stylesheet" href="player.css">
|
|
15
|
+
<script type="text/javascript" src="../sfu.js"></script>
|
|
16
|
+
<script type="text/javascript" src="../commons/js/util.js"></script>
|
|
17
|
+
<script type="text/javascript" src="../commons/js/config.js"></script>
|
|
18
|
+
<script type="text/javascript" src="../commons/js/display.js"></script>
|
|
19
|
+
<script type="text/javascript" src="player.js"></script>
|
|
20
|
+
</head>
|
|
21
|
+
<body onload="init()">
|
|
22
|
+
<div class="container" id="main">
|
|
23
|
+
<div class="col-sm-12">
|
|
24
|
+
<h2 class="text-center">WebRTC ABR Player</h2>
|
|
25
|
+
|
|
26
|
+
<div class="row col-sm-12 justify-content-center" style="margin-top: 10px">
|
|
27
|
+
<div id="remoteVideo" class="fp-remoteVideo text-center justify-content-center">
|
|
28
|
+
<div id="placeholder" class="fp-placeholder text-center justify-content-center"></div>
|
|
29
|
+
</div>
|
|
30
|
+
</div>
|
|
31
|
+
<div class="row col-sm-12 justify-content-center">
|
|
32
|
+
<div id="connectionForm" class="col-sm-6 text-center form-group">
|
|
33
|
+
<label for="url" class="control-label">Server url</label>
|
|
34
|
+
<input class="form-control" id="url" type="text">
|
|
35
|
+
<label for="streamName" class="control-label">Stream name</label>
|
|
36
|
+
<input class="form-control" id="streamName" type="text">
|
|
37
|
+
<div class="input-group-btn" style="margin-top: 10px">
|
|
38
|
+
<button id="playBtn" type="button" style="height: 30px;; width: auto;">Play</button>
|
|
39
|
+
</div>
|
|
40
|
+
<div class="text-center" style="margin-top: 20px">
|
|
41
|
+
<div id="playStatus"></div>
|
|
42
|
+
<div id="playErrorInfo"></div>
|
|
43
|
+
</div>
|
|
44
|
+
</div>
|
|
45
|
+
</div>
|
|
46
|
+
</div>
|
|
47
|
+
</div>
|
|
48
|
+
</body>
|
|
49
|
+
</html>
|
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
const constants = SFU.constants;
|
|
2
|
+
const sfu = SFU;
|
|
3
|
+
const PRELOADER_URL="../commons/media/silence.mp3"
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Current state object
|
|
7
|
+
*/
|
|
8
|
+
const CurrentState = function() {
|
|
9
|
+
let state = {
|
|
10
|
+
pc: null,
|
|
11
|
+
session: null,
|
|
12
|
+
room: null,
|
|
13
|
+
remoteDisplay: null,
|
|
14
|
+
set: function(pc, session, room) {
|
|
15
|
+
state.pc = pc;
|
|
16
|
+
state.session = session;
|
|
17
|
+
state.room = room;
|
|
18
|
+
},
|
|
19
|
+
clear: function() {
|
|
20
|
+
state.room = null;
|
|
21
|
+
state.session = null;
|
|
22
|
+
state.pc = null;
|
|
23
|
+
},
|
|
24
|
+
setDisplay: function(display) {
|
|
25
|
+
state.remoteDisplay = display;
|
|
26
|
+
},
|
|
27
|
+
disposeDisplay: function() {
|
|
28
|
+
if (state.remoteDisplay) {
|
|
29
|
+
state.remoteDisplay.stop();
|
|
30
|
+
state.remoteDisplay = null;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
};
|
|
34
|
+
return state;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* load config and set default values
|
|
39
|
+
*/
|
|
40
|
+
const init = function() {
|
|
41
|
+
$("#playBtn").prop('disabled', true);
|
|
42
|
+
$("#url").prop('disabled', true);
|
|
43
|
+
$("#streamName").prop('disabled', true);
|
|
44
|
+
onDisconnected(CurrentState());
|
|
45
|
+
$("#url").val(setURL());
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Connect to server
|
|
50
|
+
*/
|
|
51
|
+
const connect = function(state) {
|
|
52
|
+
// Create peer connection
|
|
53
|
+
let pc = new RTCPeerConnection();
|
|
54
|
+
// Create a config to connect to SFU room
|
|
55
|
+
const roomConfig = {
|
|
56
|
+
// Server websocket URL
|
|
57
|
+
url: $("#url").val(),
|
|
58
|
+
// Use stream name as room name to play ABR
|
|
59
|
+
roomName: $("#streamName").val(),
|
|
60
|
+
// Make a random participant name from stream name
|
|
61
|
+
nickname: "Player-" + $("#streamName").val() + "-" + createUUID(4),
|
|
62
|
+
// Set room pin
|
|
63
|
+
pin: 123456
|
|
64
|
+
}
|
|
65
|
+
// Clean state display items
|
|
66
|
+
setStatus("playStatus", "");
|
|
67
|
+
setStatus("playErrorInfo", "");
|
|
68
|
+
// Connect to the server (room should already exist)
|
|
69
|
+
const session = sfu.createRoom(roomConfig);
|
|
70
|
+
session.on(constants.SFU_EVENT.CONNECTED, function() {
|
|
71
|
+
state.set(pc, session, session.room());
|
|
72
|
+
onConnected(state);
|
|
73
|
+
setStatus("playStatus", "CONNECTING...", "black");
|
|
74
|
+
}).on(constants.SFU_EVENT.DISCONNECTED, function() {
|
|
75
|
+
state.clear();
|
|
76
|
+
onDisconnected(state);
|
|
77
|
+
setStatus("playStatus", "DISCONNECTED", "green");
|
|
78
|
+
}).on(constants.SFU_EVENT.FAILED, function(e) {
|
|
79
|
+
state.clear();
|
|
80
|
+
onDisconnected(state);
|
|
81
|
+
setStatus("playStatus", "FAILED", "red");
|
|
82
|
+
setStatus("playErrorInfo", e.status + " " + e.statusText, "red");
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
const onConnected = function(state) {
|
|
87
|
+
$("#playBtn").text("Stop").off('click').click(function () {
|
|
88
|
+
onStopClick(state);
|
|
89
|
+
}).prop('disabled', false);
|
|
90
|
+
$('#url').prop('disabled', true);
|
|
91
|
+
$("#streamName").prop('disabled', true);
|
|
92
|
+
// Add room event handling
|
|
93
|
+
state.room.on(constants.SFU_ROOM_EVENT.PARTICIPANT_LIST, function(e) {
|
|
94
|
+
// If the room is empty, the stream is not published yet
|
|
95
|
+
if(!e.participants || e.participants.length === 0) {
|
|
96
|
+
setStatus("playErrorInfo", "ABR stream is not published", "red");
|
|
97
|
+
onStopClick(state);
|
|
98
|
+
}
|
|
99
|
+
else {
|
|
100
|
+
setStatus("playStatus", "ESTABLISHED", "green");
|
|
101
|
+
$("#placeholder").hide();
|
|
102
|
+
}
|
|
103
|
+
}).on(constants.SFU_ROOM_EVENT.FAILED, function(e) {
|
|
104
|
+
// Display error state
|
|
105
|
+
setStatus("playErrorInfo", e, "red");
|
|
106
|
+
}).on(constants.SFU_ROOM_EVENT.OPERATION_FAILED, function (e) {
|
|
107
|
+
// Display the operation failed
|
|
108
|
+
setStatus("playErrorInfo", e.operation + " failed: " + e.error, "red");
|
|
109
|
+
}).on(constants.SFU_ROOM_EVENT.ENDED, function () {
|
|
110
|
+
// Publishing is stopped, dispose playback and close connection
|
|
111
|
+
setStatus("playErrorInfo", "ABR stream is stopped", "red");
|
|
112
|
+
onStopClick(state);
|
|
113
|
+
});
|
|
114
|
+
playStreams(state);
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
const onDisconnected = function(state) {
|
|
118
|
+
$("#placeholder").show();
|
|
119
|
+
$("#playBtn").text("Play").off('click').click(function () {
|
|
120
|
+
onStartClick(state);
|
|
121
|
+
}).prop('disabled', false);
|
|
122
|
+
$('#url').prop('disabled', false);
|
|
123
|
+
$("#streamName").prop('disabled', false);
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
const onStartClick = function(state) {
|
|
127
|
+
if (validateForm("connectionForm")) {
|
|
128
|
+
$("#playBtn").prop('disabled', true);
|
|
129
|
+
if (Browser().isSafariWebRTC()) {
|
|
130
|
+
playFirstSound(document.getElementById("main"), PRELOADER_URL).then(function () {
|
|
131
|
+
connect(state);
|
|
132
|
+
});
|
|
133
|
+
} else {
|
|
134
|
+
connect(state);
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
const onStopClick = function(state) {
|
|
140
|
+
$("#playBtn").prop('disabled', true);
|
|
141
|
+
stopStreams(state);
|
|
142
|
+
state.session.disconnect();
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
const playStreams = function(state) {
|
|
146
|
+
// Create remote display item to show remote streams
|
|
147
|
+
state.setDisplay(initRemoteDisplay({
|
|
148
|
+
div: document.getElementById("remoteVideo"),
|
|
149
|
+
room: state.room,
|
|
150
|
+
peerConnection: state.pc,
|
|
151
|
+
displayOptions: {
|
|
152
|
+
publisher: false,
|
|
153
|
+
quality: true
|
|
154
|
+
}
|
|
155
|
+
}));
|
|
156
|
+
state.room.join(state.pc);
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
const stopStreams = function(state) {
|
|
160
|
+
state.disposeDisplay();
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
const setStatus = function (status, text, color) {
|
|
164
|
+
color = color || "black";
|
|
165
|
+
const errField = document.getElementById(status);
|
|
166
|
+
errField.style.color = color;
|
|
167
|
+
errField.innerText = text;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
const validateForm = function (formId) {
|
|
171
|
+
var valid = true;
|
|
172
|
+
$('#' + formId + ' :text').each(function () {
|
|
173
|
+
if (!$(this).val()) {
|
|
174
|
+
highlightInput($(this));
|
|
175
|
+
valid = false;
|
|
176
|
+
setStatus("playErrorInfo", "Fields cannot be empty", "red");
|
|
177
|
+
} else {
|
|
178
|
+
removeHighlight($(this));
|
|
179
|
+
setStatus("playErrorInfo", "");
|
|
180
|
+
}
|
|
181
|
+
});
|
|
182
|
+
return valid;
|
|
183
|
+
|
|
184
|
+
function highlightInput(input) {
|
|
185
|
+
input.closest('.form-group').addClass("has-error");
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
function removeHighlight(input) {
|
|
189
|
+
input.closest('.form-group').removeClass("has-error");
|
|
190
|
+
}
|
|
191
|
+
}
|