|
@@ -9,6 +9,7 @@ var sharedKey = '';
|
9
|
9
|
var roomUrl = null;
|
10
|
10
|
var ssrc2jid = {};
|
11
|
11
|
var localVideoSrc = null;
|
|
12
|
+var flipXLocalVideo = true;
|
12
|
13
|
var preziPlayer = null;
|
13
|
14
|
|
14
|
15
|
/* window.onbeforeunload = closePageWarning; */
|
|
@@ -71,7 +72,7 @@ function audioStreamReady(stream) {
|
71
|
72
|
|
72
|
73
|
function videoStreamReady(stream) {
|
73
|
74
|
|
74
|
|
- change_local_video(stream);
|
|
75
|
+ change_local_video(stream, true);
|
75
|
76
|
|
76
|
77
|
doJoin();
|
77
|
78
|
}
|
|
@@ -134,27 +135,37 @@ function change_local_audio(stream) {
|
134
|
135
|
document.getElementById('localAudio').volume = 0;
|
135
|
136
|
}
|
136
|
137
|
|
137
|
|
-function change_local_video(stream) {
|
|
138
|
+function change_local_video(stream, flipX) {
|
138
|
139
|
|
139
|
140
|
connection.jingle.localVideo = stream;
|
140
|
|
- RTC.attachMediaStream($('#localVideo'), stream);
|
141
|
|
- document.getElementById('localVideo').autoplay = true;
|
142
|
|
- document.getElementById('localVideo').volume = 0;
|
143
|
141
|
|
144
|
|
- localVideoSrc = document.getElementById('localVideo').src;
|
145
|
|
- updateLargeVideo(localVideoSrc, true, 0);
|
146
|
|
-
|
147
|
|
- $('#localVideo').click(function () {
|
148
|
|
- $(document).trigger("video.selected", [false]);
|
149
|
|
- updateLargeVideo($(this).attr('src'), true, 0);
|
|
142
|
+ var localVideo = document.createElement('video');
|
|
143
|
+ localVideo.id = 'localVideo_'+stream.id;
|
|
144
|
+ localVideo.autoplay = true;
|
|
145
|
+ localVideo.volume = 0; // is it required if audio is separated ?
|
|
146
|
+ localVideo.oncontextmenu = function () { return false; };
|
|
147
|
+
|
|
148
|
+ var localVideoContainer = document.getElementById('localVideoContainer');
|
|
149
|
+ localVideoContainer.appendChild(localVideo);
|
|
150
|
+
|
|
151
|
+ var localVideoSelector = $('#' + localVideo.id);
|
|
152
|
+ // Add click handler
|
|
153
|
+ localVideoSelector.click(function () { handleVideoThumbClicked(localVideo.src); } );
|
|
154
|
+ // Add stream ended handler
|
|
155
|
+ stream.onended = function () {
|
|
156
|
+ localVideoContainer.removeChild(localVideo);
|
|
157
|
+ checkChangeLargeVideo(localVideo.src);
|
|
158
|
+ };
|
|
159
|
+ // Flip video x axis if needed
|
|
160
|
+ flipXLocalVideo = flipX;
|
|
161
|
+ if(flipX) {
|
|
162
|
+ localVideoSelector.addClass("flipVideoX");
|
|
163
|
+ }
|
|
164
|
+ // Attach WebRTC stream
|
|
165
|
+ RTC.attachMediaStream(localVideoSelector, stream);
|
150
|
166
|
|
151
|
|
- $('video').each(function (idx, el) {
|
152
|
|
- if (el.id.indexOf('mixedmslabel') !== -1) {
|
153
|
|
- el.volume = 0;
|
154
|
|
- el.volume = 1;
|
155
|
|
- }
|
156
|
|
- });
|
157
|
|
- });
|
|
167
|
+ localVideoSrc = localVideo.src;
|
|
168
|
+ updateLargeVideo(localVideoSrc, 0);
|
158
|
169
|
}
|
159
|
170
|
|
160
|
171
|
$(document).bind('remotestreamadded.jingle', function (event, data, sid) {
|
|
@@ -243,42 +254,27 @@ $(document).bind('remotestreamadded.jingle', function (event, data, sid) {
|
243
|
254
|
|
244
|
255
|
data.stream.onended = function () {
|
245
|
256
|
console.log('stream ended', this.id);
|
246
|
|
- if (sel.attr('src') === $('#largeVideo').attr('src')) {
|
247
|
|
- // this is currently displayed as large
|
248
|
|
- // pick the last visible video in the row
|
249
|
|
- // if nobody else is left, this picks the local video
|
250
|
|
- var pick = $('#remoteVideos>span[id!="mixedstream"]:visible:last>video').get(0);
|
251
|
|
- // mute if localvideo
|
252
|
|
- var isLocalVideo = false;
|
253
|
|
- if (pick) {
|
254
|
|
- if (pick.src === localVideoSrc)
|
255
|
|
- isLocalVideo = true;
|
256
|
|
-
|
257
|
|
- updateLargeVideo(pick.src, isLocalVideo, pick.volume);
|
258
|
|
- }
|
259
|
|
- }
|
|
257
|
+
|
260
|
258
|
// Mark video as removed to cancel waiting loop(if video is removed before has started)
|
261
|
259
|
sel.removed = true;
|
|
260
|
+ sel.remove();
|
262
|
261
|
|
263
|
|
- var userContainer = sel.parent();
|
264
|
|
- if(userContainer.children().length === 0) {
|
|
262
|
+ var audioCount = $('#'+container.id+'>audio').length;
|
|
263
|
+ var videoCount = $('#'+container.id+'>video').length;
|
|
264
|
+ if(!audioCount && !videoCount) {
|
265
|
265
|
console.log("Remove whole user");
|
266
|
266
|
// Remove whole container
|
267
|
|
- userContainer.remove();
|
|
267
|
+ container.remove();
|
268
|
268
|
Util.playSoundNotification('userLeft');
|
269
|
269
|
resizeThumbnails();
|
270
|
|
- } else {
|
271
|
|
- // Remove only stream holder
|
272
|
|
- sel.remove();
|
273
|
|
- console.log("Remove stream only", sel);
|
274
|
270
|
}
|
|
271
|
+
|
|
272
|
+ checkChangeLargeVideo(vid.src);
|
275
|
273
|
};
|
276
|
|
- sel.click(
|
277
|
|
- function () {
|
278
|
|
- $(document).trigger("video.selected", [false]);
|
279
|
|
- updateLargeVideo($(this).attr('src'), false, 1);
|
280
|
|
- }
|
281
|
|
- );
|
|
274
|
+
|
|
275
|
+ // Add click handler
|
|
276
|
+ sel.click(function () { handleVideoThumbClicked(vid.src); });
|
|
277
|
+
|
282
|
278
|
// an attempt to work around https://github.com/jitsi/jitmeet/issues/32
|
283
|
279
|
if (isVideo
|
284
|
280
|
&& data.peerjid && sess.peerjid === data.peerjid &&
|
|
@@ -290,6 +286,46 @@ $(document).bind('remotestreamadded.jingle', function (event, data, sid) {
|
290
|
286
|
}
|
291
|
287
|
});
|
292
|
288
|
|
|
289
|
+function handleVideoThumbClicked(videoSrc) {
|
|
290
|
+
|
|
291
|
+ $(document).trigger("video.selected", [false]);
|
|
292
|
+
|
|
293
|
+ updateLargeVideo(videoSrc, 1);
|
|
294
|
+
|
|
295
|
+ $('audio').each(function (idx, el) {
|
|
296
|
+ // We no longer mix so we check for local audio now
|
|
297
|
+ if(el.id != 'localAudio') {
|
|
298
|
+ el.volume = 0;
|
|
299
|
+ el.volume = 1;
|
|
300
|
+ }
|
|
301
|
+ });
|
|
302
|
+}
|
|
303
|
+
|
|
304
|
+/**
|
|
305
|
+ * Checks if removed video is currently displayed and tries to display another one instead.
|
|
306
|
+ * @param removedVideoSrc src stream identifier of the video.
|
|
307
|
+ */
|
|
308
|
+function checkChangeLargeVideo(removedVideoSrc){
|
|
309
|
+ if (removedVideoSrc === $('#largeVideo').attr('src')) {
|
|
310
|
+ // this is currently displayed as large
|
|
311
|
+ // pick the last visible video in the row
|
|
312
|
+ // if nobody else is left, this picks the local video
|
|
313
|
+ var pick = $('#remoteVideos>span[id!="mixedstream"]:visible:last>video').get(0);
|
|
314
|
+
|
|
315
|
+ if(!pick) {
|
|
316
|
+ console.info("Last visible video no longer exists");
|
|
317
|
+ pick = $('#remoteVideos>span[id!="mixedstream"]>video').get(0);
|
|
318
|
+ }
|
|
319
|
+
|
|
320
|
+ // mute if localvideo
|
|
321
|
+ if (pick) {
|
|
322
|
+ updateLargeVideo(pick.src, pick.volume);
|
|
323
|
+ } else {
|
|
324
|
+ console.warn("Failed to elect large video");
|
|
325
|
+ }
|
|
326
|
+ }
|
|
327
|
+}
|
|
328
|
+
|
293
|
329
|
// an attempt to work around https://github.com/jitsi/jitmeet/issues/32
|
294
|
330
|
function sendKeyframe(pc) {
|
295
|
331
|
console.log('sendkeyframe', pc.iceConnectionState);
|
|
@@ -404,7 +440,7 @@ $(document).bind('callactive.jingle', function (event, videoelem, sid) {
|
404
|
440
|
videoelem.show();
|
405
|
441
|
resizeThumbnails();
|
406
|
442
|
|
407
|
|
- updateLargeVideo(videoelem.attr('src'), false, 1);
|
|
443
|
+ updateLargeVideo(videoelem.attr('src'), 1);
|
408
|
444
|
|
409
|
445
|
showFocusIndicator();
|
410
|
446
|
}
|
|
@@ -566,6 +602,8 @@ $(document).bind('presence.muc', function (event, jid, info, pres) {
|
566
|
602
|
break;
|
567
|
603
|
case 'recvonly':
|
568
|
604
|
el.hide();
|
|
605
|
+ // FIXME: Check if we have to change large video
|
|
606
|
+ //checkChangeLargeVideo(el);
|
569
|
607
|
break;
|
570
|
608
|
}
|
571
|
609
|
}
|
|
@@ -751,23 +789,27 @@ function isPresentationVisible() {
|
751
|
789
|
/**
|
752
|
790
|
* Updates the large video with the given new video source.
|
753
|
791
|
*/
|
754
|
|
-function updateLargeVideo(newSrc, localVideo, vol) {
|
|
792
|
+function updateLargeVideo(newSrc, vol) {
|
755
|
793
|
console.log('hover in', newSrc);
|
756
|
794
|
|
757
|
795
|
setPresentationVisible(false);
|
758
|
796
|
|
759
|
797
|
if ($('#largeVideo').attr('src') !== newSrc) {
|
760
|
798
|
|
761
|
|
- document.getElementById('largeVideo').volume = vol;
|
|
799
|
+ // FIXME: is it still required ? audio is separated
|
|
800
|
+ //document.getElementById('largeVideo').volume = vol;
|
762
|
801
|
|
763
|
802
|
$('#largeVideo').fadeOut(300, function () {
|
764
|
803
|
$(this).attr('src', newSrc);
|
765
|
804
|
|
|
805
|
+ // Screen stream is already rotated
|
|
806
|
+ var flipX = (newSrc === localVideoSrc) && flipXLocalVideo;
|
|
807
|
+
|
766
|
808
|
var videoTransform = document.getElementById('largeVideo').style.webkitTransform;
|
767
|
|
- if (localVideo && videoTransform !== 'scaleX(-1)') {
|
|
809
|
+ if (flipX && videoTransform !== 'scaleX(-1)') {
|
768
|
810
|
document.getElementById('largeVideo').style.webkitTransform = "scaleX(-1)";
|
769
|
811
|
}
|
770
|
|
- else if (!localVideo && videoTransform === 'scaleX(-1)') {
|
|
812
|
+ else if (!flipX && videoTransform === 'scaleX(-1)') {
|
771
|
813
|
document.getElementById('largeVideo').style.webkitTransform = "none";
|
772
|
814
|
}
|
773
|
815
|
|
|
@@ -1203,8 +1245,14 @@ function showToolbar() {
|
1203
|
1245
|
// TODO: Enable settings functionality. Need to uncomment the settings button in index.html.
|
1204
|
1246
|
// $('#settingsButton').css({visibility:"visible"});
|
1205
|
1247
|
}
|
|
1248
|
+ showDesktopSharingButton();
|
|
1249
|
+}
|
|
1250
|
+
|
|
1251
|
+function showDesktopSharingButton() {
|
1206
|
1252
|
if(isDesktopSharingEnabled()) {
|
1207
|
|
- $('#desktopsharing').css({display:"inline"});
|
|
1253
|
+ $('#desktopsharing').css( {display:"inline"} );
|
|
1254
|
+ } else {
|
|
1255
|
+ $('#desktopsharing').css( {display:"none"} );
|
1208
|
1256
|
}
|
1209
|
1257
|
}
|
1210
|
1258
|
|