@flashphoner/websdk 2.0.211 → 2.0.216

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,4 +1,4 @@
1
- Web SDK - 2.0.211
1
+ Web SDK - 2.0.216
2
2
 
3
3
  [Download builds](https://docs.flashphoner.com/display/WEBSDK2EN/Web+SDK+release+notes)
4
4
 
@@ -68,6 +68,8 @@
68
68
  </div>
69
69
  <div class="input-group text-center" style="margin: 5px auto 0 auto;">
70
70
  <button id="participant1Btn" type="button" class="btn btn-default">Play</button>
71
+ <button id="participant1AudioBtn" type="button" class="btn btn-default">Audio</button>
72
+ <div id="participant1AudioState"></div>
71
73
  </div>
72
74
  </div>
73
75
 
@@ -81,6 +83,8 @@
81
83
  </div>
82
84
  <div class="input-group text-center" style="margin: 5px auto 0 auto;">
83
85
  <button id="participant2Btn" type="button" class="btn btn-default">Play</button>
86
+ <button id="participant2AudioBtn" type="button" class="btn btn-default">Audio</button>
87
+ <div id="participant2AudioState"></div>
84
88
  </div>
85
89
  </div>
86
90
 
@@ -5,6 +5,7 @@ var ROOM_EVENT = RoomApi.events;
5
5
  var PRELOADER_URL = "../../dependencies/media/preloader.mp4";
6
6
  var Browser = Flashphoner.Browser;
7
7
  var connection;
8
+ var participantStateList;
8
9
 
9
10
  //initialize interface
10
11
  function init_page() {
@@ -21,6 +22,7 @@ function init_page() {
21
22
  $("#notifyFlash").text("Your browser doesn't support WebRTC technology needed for this example");
22
23
  return;
23
24
  }
25
+ participantStateList = new ParticipantLocalStateList();
24
26
  $("#url").val(setURL());
25
27
  onLeft();
26
28
  }
@@ -47,8 +49,9 @@ function onLeft() {
47
49
  $("[id$=Name]").not(":contains('NONE')").each(function(index,value) {
48
50
  $(value).text('NONE');
49
51
  });
52
+ participantStateList.clean();
50
53
  for (var i = 0; i < _participants; i++) {
51
- $("#participant" + i + "Btn").text("Play").off('click').prop('disabled', true);
54
+ resetParticipantButtons("participant" + i);
52
55
  };
53
56
  $("#joinBtn").text("Join").off('click').click(function(){
54
57
  if (validateForm()) {
@@ -150,88 +153,129 @@ function installParticipant(participant) {
150
153
  if (($("[id$=Name]").not(":contains('NONE')").length + 1) == _participants) {
151
154
  console.warn("More than " + _participants + " participants, ignore participant " + participant.name());
152
155
  } else {
153
- var p = $("[id$=Name]:contains('NONE')")[0].id.replace('Name','');
154
- var pName = '#' + p + 'Name';
156
+ var pBase = $("[id$=Name]:contains('NONE')")[0].id.replace('Name','');
157
+ var pName = '#' + pBase + 'Name';
155
158
  $(pName).text(participant.name());
159
+ participantStateList.add(participant, pBase);
156
160
  playParticipantsStream(participant);
157
161
  }
158
162
  }
159
163
 
160
164
  function removeParticipant(participant) {
161
- $("[id$=Name]").each(function(index,value) {
162
- if ($(value).text() == participant.name()) {
163
- $(value).text('NONE');
164
- var pButtonId = value.id.replace('Name', '') + 'Btn';
165
- $("#" + pButtonId).text("Play").off('click').prop('disabled', true);
166
- }
167
- });
165
+ var participantState = participantStateList.getState(participant);
166
+ if (participantState) {
167
+ participantStateList.remove(participant);
168
+ $(participantState.getName()).text('NONE');
169
+ resetParticipantButtons(participantState.getBaseId());
170
+ } else {
171
+ console.log("Cannot remove " + participant.name() + " from participants list: not found");
172
+ }
168
173
  }
169
174
 
170
175
  function playParticipantsStream(participant) {
171
- if (participant.getStreams().length > 0) {
172
- $("[id$=Name]").each(function (index, value) {
173
- if ($(value).text() == participant.name()) {
174
- var p = value.id.replace('Name', '');
175
- var pDisplay = document.getElementById(p + 'Display');
176
- if (Browser.isSafariWebRTC()) {
177
- Flashphoner.playFirstVideo(pDisplay, false, PRELOADER_URL).then(function() {
178
- playStream(participant, pDisplay);
179
- }).catch(function (error) {
180
- // Low Power Mode detected, user action is needed to start playback in this mode #WCS-2639
181
- console.log("Can't atomatically play participant" + participant.name() + " stream, use Play button");
182
- for (var i = 0; i < pDisplay.children.length; i++) {
183
- if (pDisplay.children[i]) {
184
- console.log("remove cached instance id " + pDisplay.children[i].id);
185
- pDisplay.removeChild(pDisplay.children[i]);
186
- }
187
- }
188
- onParticipantStopped(participant);
189
- });
190
- } else {
191
- playStream(participant, pDisplay);
176
+ var participantState = participantStateList.getState(participant);
177
+ if (participantState && participant.getStreams().length > 0) {
178
+ var pDisplay = participantState.getDisplay();
179
+ if (Browser.isSafariWebRTC()) {
180
+ Flashphoner.playFirstVideo(pDisplay, false, PRELOADER_URL).then(function() {
181
+ playStream(participant, pDisplay);
182
+ }).catch(function (error) {
183
+ // Low Power Mode detected, user action is needed to start playback in this mode #WCS-2639
184
+ console.log("Can't atomatically play participant" + participant.name() + " stream, use Play button");
185
+ for (var i = 0; i < pDisplay.children.length; i++) {
186
+ if (pDisplay.children[i]) {
187
+ console.log("remove cached instance id " + pDisplay.children[i].id);
188
+ pDisplay.removeChild(pDisplay.children[i]);
189
+ }
192
190
  }
193
- }
194
- });
191
+ onParticipantStopped(participant);
192
+ });
193
+ } else {
194
+ playStream(participant, pDisplay);
195
+ }
196
+ } else {
197
+ console.log("Cannot play participant " + participant.name() + " stream: participant not found");
195
198
  }
196
199
  }
197
200
 
198
201
  function playStream(participant, display) {
199
- var button = getParticipantButton(participant);
200
- participant.getStreams()[0].play(display).on(STREAM_STATUS.PLAYING, function (playingStream) {
201
- document.getElementById(playingStream.id()).addEventListener('resize', function (event) {
202
- resizeVideo(event.target);
203
- });
204
- if (button) {
205
- $(button).text("Stop").off('click').click(function(){
206
- $(this).prop('disabled', true);
207
- playingStream.stop();
208
- }).prop('disabled', false);
202
+ var participantState = participantStateList.getState(participant);
203
+ if (participantState) {
204
+ var playBtn = participantState.getPlayButton();
205
+ var audioBtn = participantState.getAudioButton();
206
+ var options = {
207
+ unmutePlayOnStart: true,
208
+ constraints: {
209
+ audio: {
210
+ deviceId: 'default'
211
+ }
212
+ }
213
+ };
214
+ // Leave participant stream muted in Android Edge browser #WCS-3445
215
+ if (Browser.isChromiumEdge() && Browser.isAndroid()) {
216
+ options.unmutePlayOnStart = false;
209
217
  }
210
- }).on(STREAM_STATUS.STOPPED, function () {
211
- onParticipantStopped(participant);
212
- }).on(STREAM_STATUS.FAILED, function () {
213
- onParticipantStopped(participant);
214
- });
218
+ participant.getStreams()[0].play(display, options).on(STREAM_STATUS.PLAYING, function (playingStream) {
219
+ var video = document.getElementById(playingStream.id())
220
+ video.addEventListener('resize', function (event) {
221
+ resizeVideo(event.target);
222
+ });
223
+ // Set up participant Stop/Play button
224
+ if (playBtn) {
225
+ $(playBtn).text("Stop").off('click').click(function() {
226
+ $(this).prop('disabled', true);
227
+ playingStream.stop();
228
+ }).prop('disabled', false);
229
+ }
230
+ // Set up participant audio toggle button #WCS-3445
231
+ if (audioBtn) {
232
+ $(audioBtn).text("Audio").off('click').click(function() {
233
+ if (playingStream.isRemoteAudioMuted()) {
234
+ playingStream.unmuteRemoteAudio();
235
+ } else {
236
+ playingStream.muteRemoteAudio();
237
+ }
238
+ }).prop('disabled', false);
239
+ }
240
+ // Start participant audio state checking timer #WCS-3445
241
+ participantState.startMutedCheck(playingStream);
242
+ }).on(STREAM_STATUS.STOPPED, function () {
243
+ onParticipantStopped(participant);
244
+ }).on(STREAM_STATUS.FAILED, function () {
245
+ onParticipantStopped(participant);
246
+ });
247
+ } else {
248
+ console.log("Cannot play stream: participant " + participant.name() + " not found");
249
+ }
215
250
  }
216
251
 
217
252
  function onParticipantStopped(participant) {
218
- var button = getParticipantButton(participant);
219
- if (button) {
220
- $(button).text("Play").off('click').click(function() {
221
- playParticipantsStream(participant);
222
- }).prop('disabled', false);
253
+ var participantState = participantStateList.getState(participant);
254
+ if (participantState) {
255
+ var playBtn = participantState.getPlayButton();
256
+ var audioBtn = participantState.getAudioButton();
257
+ var audioState = participantState.getAudioState();
258
+ if (playBtn) {
259
+ $(playBtn).text("Play").off('click').click(function() {
260
+ playParticipantsStream(participant);
261
+ }).prop('disabled', false);
262
+ }
263
+ if (audioBtn) {
264
+ $(audioBtn).text("Audio").off('click').prop('disabled', true);
265
+ }
266
+ if (audioState) {
267
+ participantState.stopMutedCheck();
268
+ $(audioState).text("");
269
+ }
270
+ } else {
271
+ console.log("Cannot perfom onStopped actions: " + participant.name() + " not found");
223
272
  }
224
273
  }
225
274
 
226
- function getParticipantButton(participant) {
227
- var button = null;
228
- $("[id$=Name]").each(function (index, value) {
229
- if ($(value).text() == participant.name()) {
230
- button = document.getElementById(value.id.replace('Name', '') + 'Btn');
231
- return(button);
232
- }
233
- });
234
- return(button);
275
+ function resetParticipantButtons(id) {
276
+ $("#" + id + 'Btn').text("Play").off('click').prop('disabled', true);
277
+ $("#" + id + 'AudioBtn').text("Audio").off('click').prop('disabled', true);
278
+ $("#" + id + 'AudioState').text("");
235
279
  }
236
280
 
237
281
  function getRoomName() {
@@ -329,9 +373,9 @@ function publishLocalStream(room) {
329
373
  }
330
374
  onMediaStopped(room);
331
375
  });
332
- return;
376
+ } else {
377
+ publishLocalMedia(room);
333
378
  }
334
- publishLocalMedia(room);
335
379
  }
336
380
 
337
381
  function muteConnectInputs() {
@@ -377,3 +421,100 @@ function setStatus(selector, status) {
377
421
  statusField.attr("class","text-danger");
378
422
  }
379
423
  }
424
+
425
+ // Object to store local state to display participant #WCS-3445
426
+ function ParticipantLocalState(participant, id) {
427
+ var state = {
428
+ participant: participant,
429
+ baseId: id,
430
+ audioTimer: null,
431
+ getBaseId: function() {
432
+ return state.baseId;
433
+ },
434
+ getName: function() {
435
+ return document.getElementById(state.baseId + 'Name');
436
+ },
437
+ getDisplay: function() {
438
+ return document.getElementById(state.baseId + 'Display');
439
+ },
440
+ getPlayButton: function() {
441
+ return document.getElementById(state.baseId + 'Btn');
442
+ },
443
+ getAudioButton: function() {
444
+ return document.getElementById(state.baseId + 'AudioBtn');
445
+ },
446
+ getAudioState: function() {
447
+ return document.getElementById(state.baseId + 'AudioState');
448
+ },
449
+ startMutedCheck: function(stream) {
450
+ var audioState = state.getAudioState();
451
+ state.stopMutedCheck();
452
+ state.audioTimer = setInterval(function () {
453
+ if (stream.isRemoteAudioMuted()) {
454
+ $(audioState).text("Muted");
455
+ } else {
456
+ $(audioState).text("Unmuted");
457
+ }
458
+ }, 500);
459
+ },
460
+ stopMutedCheck: function() {
461
+ if (state.audioTimer) {
462
+ clearInterval(state.audioTimer);
463
+ state.audioTimer = null;
464
+ }
465
+ }
466
+ }
467
+
468
+ return state;
469
+ }
470
+
471
+ // Array object to store local participant states #WCS-3445
472
+ function ParticipantLocalStateList() {
473
+ var stateList = {
474
+ list: [],
475
+ add: function(participant, id) {
476
+ var state = new ParticipantLocalState(participant, id);
477
+ stateList.list.push(state);
478
+ },
479
+ remove: function(participant) {
480
+ for (var i = 0; i < stateList.list.length; i++) {
481
+ if (stateList.list[i].participant && (stateList.list[i].participant.name() === participant.name())) {
482
+ stateList.list[i].stopMutedCheck();
483
+ stateList.list.splice(i, 1);
484
+ }
485
+ }
486
+ },
487
+ clean: function() {
488
+ while (stateList.list.length) {
489
+ var state = stateList.list.pop();
490
+ state.stopMutedCheck();
491
+ }
492
+ },
493
+ getState: function(participant) {
494
+ for (var i = 0; i < stateList.list.length; i++) {
495
+ if (stateList.list[i].participant && (stateList.list[i].participant.name() === participant.name())) {
496
+ return stateList.list[i];
497
+ }
498
+ }
499
+ return null;
500
+ },
501
+ startMutedCheck: function(participant, stream) {
502
+ var item = stateList.getState(participant);
503
+ if (item) {
504
+ item.startMutedCheck(stream);
505
+ } else {
506
+ console.error("Cannot start muted check timer for participant " + participant);
507
+ }
508
+ },
509
+ stopMutedCheck: function(participant) {
510
+ var item = stateList.getState(participant);
511
+ if (item) {
512
+ item.stopMutedCheck();
513
+ } else {
514
+ console.error("Cannot stop muted check timer for participant " + participant);
515
+ }
516
+ }
517
+ }
518
+
519
+ return stateList;
520
+ }
@@ -61,6 +61,11 @@
61
61
  <div class="text-center" style="margin-top: 20px">
62
62
  <div id="participant1Status"></div>
63
63
  </div>
64
+ <div class="input-group text-center" style="margin: 5px auto 0 auto;">
65
+ <button id="participant1Btn" type="button" class="btn btn-default">Play</button>
66
+ <button id="participant1AudioBtn" type="button" class="btn btn-default">Audio</button>
67
+ <div id="participant1AudioState"></div>
68
+ </div>
64
69
  </div>
65
70
 
66
71
  <div class="col-sm-7">