|
@@ -49,11 +49,10 @@ function init() {
|
49
|
49
|
if (config.useStunTurn) {
|
50
|
50
|
connection.jingle.getStunAndTurnCredentials();
|
51
|
51
|
}
|
52
|
|
- if (RTC.browser === 'firefox') {
|
53
|
|
- getUserMediaWithConstraints(['audio']);
|
54
|
|
- } else {
|
55
|
|
- getUserMediaWithConstraints(['audio', 'video'], config.resolution || '360');
|
56
|
|
- }
|
|
52
|
+ getUserMediaWithConstraints( ['audio'], audioStreamReady,
|
|
53
|
+ function(error){
|
|
54
|
+ console.error('failed to obtain audio stream - stop', error);
|
|
55
|
+ });
|
57
|
56
|
document.getElementById('connect').disabled = true;
|
58
|
57
|
} else {
|
59
|
58
|
console.log('status', status);
|
|
@@ -61,6 +60,31 @@ function init() {
|
61
|
60
|
});
|
62
|
61
|
}
|
63
|
62
|
|
|
63
|
+function audioStreamReady(stream) {
|
|
64
|
+
|
|
65
|
+ change_local_audio(stream);
|
|
66
|
+
|
|
67
|
+ if(RTC.browser !== 'firefox') {
|
|
68
|
+ getUserMediaWithConstraints( ['video'], videoStreamReady, videoStreamFailed, config.resolution || '360' );
|
|
69
|
+ } else {
|
|
70
|
+ doJoin();
|
|
71
|
+ }
|
|
72
|
+}
|
|
73
|
+
|
|
74
|
+function videoStreamReady(stream) {
|
|
75
|
+
|
|
76
|
+ change_local_video(stream);
|
|
77
|
+
|
|
78
|
+ doJoin();
|
|
79
|
+}
|
|
80
|
+
|
|
81
|
+function videoStreamFailed(error) {
|
|
82
|
+
|
|
83
|
+ console.warn("Failed to obtain video stream - continue anyway", error);
|
|
84
|
+
|
|
85
|
+ doJoin();
|
|
86
|
+}
|
|
87
|
+
|
64
|
88
|
function doJoin() {
|
65
|
89
|
var roomnode = null;
|
66
|
90
|
var path = window.location.pathname;
|
|
@@ -104,8 +128,17 @@ function doJoin() {
|
104
|
128
|
connection.emuc.doJoin(roomjid);
|
105
|
129
|
}
|
106
|
130
|
|
107
|
|
-$(document).bind('mediaready.jingle', function (event, stream) {
|
108
|
|
- connection.jingle.localStream = stream;
|
|
131
|
+function change_local_audio(stream) {
|
|
132
|
+
|
|
133
|
+ connection.jingle.localAudio = stream;
|
|
134
|
+ RTC.attachMediaStream($('#localAudio'), stream);
|
|
135
|
+ document.getElementById('localAudio').autoplay = true;
|
|
136
|
+ document.getElementById('localAudio').volume = 0;
|
|
137
|
+}
|
|
138
|
+
|
|
139
|
+function change_local_video(stream) {
|
|
140
|
+
|
|
141
|
+ connection.jingle.localVideo = stream;
|
109
|
142
|
RTC.attachMediaStream($('#localVideo'), stream);
|
110
|
143
|
document.getElementById('localVideo').autoplay = true;
|
111
|
144
|
document.getElementById('localVideo').volume = 0;
|
|
@@ -124,16 +157,14 @@ $(document).bind('mediaready.jingle', function (event, stream) {
|
124
|
157
|
}
|
125
|
158
|
});
|
126
|
159
|
});
|
127
|
|
-
|
128
|
|
- doJoin();
|
129
|
|
-});
|
130
|
|
-
|
131
|
|
-$(document).bind('mediafailure.jingle', function () {
|
132
|
|
- // FIXME
|
133
|
|
-});
|
|
160
|
+}
|
134
|
161
|
|
135
|
162
|
$(document).bind('remotestreamadded.jingle', function (event, data, sid) {
|
136
|
163
|
function waitForRemoteVideo(selector, sid) {
|
|
164
|
+ if(selector.removed) {
|
|
165
|
+ console.warn("media removed before had started", selector);
|
|
166
|
+ return;
|
|
167
|
+ }
|
137
|
168
|
var sess = connection.jingle.sessions[sid];
|
138
|
169
|
if (data.stream.id === 'mixedmslabel') return;
|
139
|
170
|
videoTracks = data.stream.getVideoTracks();
|
|
@@ -188,8 +219,11 @@ $(document).bind('remotestreamadded.jingle', function (event, data, sid) {
|
188
|
219
|
remotes.appendChild(container);
|
189
|
220
|
Util.playSoundNotification('userJoined');
|
190
|
221
|
}
|
191
|
|
- var vid = document.createElement('video');
|
192
|
|
- var id = 'remoteVideo_' + sid + '_' + data.stream.id;
|
|
222
|
+
|
|
223
|
+ var isVideo = data.stream.getVideoTracks().length > 0;
|
|
224
|
+ var vid = isVideo ? document.createElement('video') : document.createElement('audio');
|
|
225
|
+ var id = (isVideo ? 'remoteVideo_' : 'remoteAudio_') + sid + '_' + data.stream.id;
|
|
226
|
+
|
193
|
227
|
vid.id = id;
|
194
|
228
|
vid.autoplay = true;
|
195
|
229
|
vid.oncontextmenu = function () { return false; };
|
|
@@ -203,11 +237,14 @@ $(document).bind('remotestreamadded.jingle', function (event, data, sid) {
|
203
|
237
|
var sel = $('#' + id);
|
204
|
238
|
sel.hide();
|
205
|
239
|
RTC.attachMediaStream(sel, data.stream);
|
206
|
|
- waitForRemoteVideo(sel, sid);
|
|
240
|
+
|
|
241
|
+ if(isVideo) {
|
|
242
|
+ waitForRemoteVideo(sel, sid);
|
|
243
|
+ }
|
|
244
|
+
|
207
|
245
|
data.stream.onended = function () {
|
208
|
246
|
console.log('stream ended', this.id);
|
209
|
|
- var src = $('#' + id).attr('src');
|
210
|
|
- if (src === $('#largeVideo').attr('src')) {
|
|
247
|
+ if (sel.attr('src') === $('#largeVideo').attr('src')) {
|
211
|
248
|
// this is currently displayed as large
|
212
|
249
|
// pick the last visible video in the row
|
213
|
250
|
// if nobody else is left, this picks the local video
|
|
@@ -221,9 +258,21 @@ $(document).bind('remotestreamadded.jingle', function (event, data, sid) {
|
221
|
258
|
updateLargeVideo(pick.src, isLocalVideo, pick.volume);
|
222
|
259
|
}
|
223
|
260
|
}
|
224
|
|
- $('#' + id).parent().remove();
|
225
|
|
- Util.playSoundNotification('userLeft');
|
226
|
|
- resizeThumbnails();
|
|
261
|
+ // Mark video as removed to cancel waiting loop(if video is removed before has started)
|
|
262
|
+ sel.removed = true;
|
|
263
|
+
|
|
264
|
+ var userContainer = sel.parent();
|
|
265
|
+ if(userContainer.children().length === 0) {
|
|
266
|
+ console.log("Remove whole user");
|
|
267
|
+ // Remove whole container
|
|
268
|
+ userContainer.remove();
|
|
269
|
+ Util.playSoundNotification('userLeft');
|
|
270
|
+ resizeThumbnails();
|
|
271
|
+ } else {
|
|
272
|
+ // Remove only stream holder
|
|
273
|
+ sel.remove();
|
|
274
|
+ console.log("Remove stream only", sel);
|
|
275
|
+ }
|
227
|
276
|
};
|
228
|
277
|
sel.click(
|
229
|
278
|
function () {
|
|
@@ -232,9 +281,10 @@ $(document).bind('remotestreamadded.jingle', function (event, data, sid) {
|
232
|
281
|
}
|
233
|
282
|
);
|
234
|
283
|
// an attempt to work around https://github.com/jitsi/jitmeet/issues/32
|
235
|
|
- if (data.peerjid && sess.peerjid === data.peerjid &&
|
236
|
|
- data.stream.getVideoTracks().length === 0 &&
|
237
|
|
- connection.jingle.localStream.getVideoTracks().length > 0) {
|
|
284
|
+ if (isVideo
|
|
285
|
+ && data.peerjid && sess.peerjid === data.peerjid &&
|
|
286
|
+ data.stream.getVideoTracks().length === 0 &&
|
|
287
|
+ connection.jingle.localVideo.getVideoTracks().length > 0) {
|
238
|
288
|
window.setTimeout(function() {
|
239
|
289
|
sendKeyframe(sess.peerconnection);
|
240
|
290
|
}, 3000);
|
|
@@ -379,7 +429,12 @@ $(document).bind('setLocalDescription.jingle', function (event, sid) {
|
379
|
429
|
var ssrc = SDPUtil.find_line(media, 'a=ssrc:').substring(7).split(' ')[0];
|
380
|
430
|
newssrcs[type] = ssrc;
|
381
|
431
|
|
382
|
|
- directions[type] = (SDPUtil.find_line(media, 'a=sendrecv') || SDPUtil.find_line(media, 'a=recvonly') || SDPUtil.find_line('a=sendonly') || SDPUtil.find_line('a=inactive') || 'a=sendrecv').substr(2);
|
|
432
|
+ directions[type] = (
|
|
433
|
+ SDPUtil.find_line(media, 'a=sendrecv')
|
|
434
|
+ || SDPUtil.find_line(media, 'a=recvonly')
|
|
435
|
+ || SDPUtil.find_line('a=sendonly')
|
|
436
|
+ || SDPUtil.find_line('a=inactive')
|
|
437
|
+ || 'a=sendrecv' ).substr(2);
|
383
|
438
|
}
|
384
|
439
|
});
|
385
|
440
|
console.log('new ssrcs', newssrcs);
|
|
@@ -422,7 +477,7 @@ $(document).bind('joined.muc', function (event, jid, info) {
|
422
|
477
|
|
423
|
478
|
$(document).bind('entered.muc', function (event, jid, info, pres) {
|
424
|
479
|
console.log('entered', jid, info);
|
425
|
|
- console.log(focus);
|
|
480
|
+ console.log('is focus?' + focus ? 'true' : 'false');
|
426
|
481
|
|
427
|
482
|
var videoSpanId = 'participant_' + Strophe.getResourceFromJid(jid);
|
428
|
483
|
var container = addRemoteVideoContainer(videoSpanId);
|
|
@@ -712,17 +767,22 @@ function updateLargeVideo(newSrc, localVideo, vol) {
|
712
|
767
|
}
|
713
|
768
|
}
|
714
|
769
|
|
|
770
|
+function getConferenceHandler() {
|
|
771
|
+ return focus ? focus : activecall;
|
|
772
|
+}
|
|
773
|
+
|
715
|
774
|
function toggleVideo() {
|
716
|
|
- if (!(connection && connection.jingle.localStream)) return;
|
|
775
|
+ if (!(connection && connection.jingle.localVideo)) return;
|
717
|
776
|
var ismuted = false;
|
718
|
|
- for (var idx = 0; idx < connection.jingle.localStream.getVideoTracks().length; idx++) {
|
719
|
|
- ismuted = !connection.jingle.localStream.getVideoTracks()[idx].enabled;
|
|
777
|
+ var localVideo = connection.jingle.localVideo;
|
|
778
|
+ for (var idx = 0; idx < localVideo.getVideoTracks().length; idx++) {
|
|
779
|
+ ismuted = !localVideo.getVideoTracks()[idx].enabled;
|
720
|
780
|
}
|
721
|
|
- for (var idx = 0; idx < connection.jingle.localStream.getVideoTracks().length; idx++) {
|
722
|
|
- connection.jingle.localStream.getVideoTracks()[idx].enabled = !connection.jingle.localStream.getVideoTracks()[idx].enabled;
|
|
781
|
+ for (var idx = 0; idx < localVideo.getVideoTracks().length; idx++) {
|
|
782
|
+ localVideo.getVideoTracks()[idx].enabled = !localVideo.getVideoTracks()[idx].enabled;
|
723
|
783
|
}
|
724
|
|
- var sess = focus || activecall;
|
725
|
|
- if (!sess) {
|
|
784
|
+ var sess = getConferenceHandler();
|
|
785
|
+ if (sess) {
|
726
|
786
|
return;
|
727
|
787
|
}
|
728
|
788
|
sess.peerconnection.pendingop = ismuted ? 'unmute' : 'mute';
|
|
@@ -730,9 +790,10 @@ function toggleVideo() {
|
730
|
790
|
}
|
731
|
791
|
|
732
|
792
|
function toggleAudio() {
|
733
|
|
- if (!(connection && connection.jingle.localStream)) return;
|
734
|
|
- for (var idx = 0; idx < connection.jingle.localStream.getAudioTracks().length; idx++) {
|
735
|
|
- connection.jingle.localStream.getAudioTracks()[idx].enabled = !connection.jingle.localStream.getAudioTracks()[idx].enabled;
|
|
793
|
+ if (!(connection && connection.jingle.localAudio)) return;
|
|
794
|
+ var localAudio = connection.jingle.localAudio;
|
|
795
|
+ for (var idx = 0; idx < localAudio.getAudioTracks().length; idx++) {
|
|
796
|
+ localAudio.getAudioTracks()[idx].enabled = !localAudio.getAudioTracks()[idx].enabled;
|
736
|
797
|
}
|
737
|
798
|
}
|
738
|
799
|
|
|
@@ -1170,6 +1231,10 @@ function showFocusIndicator() {
|
1170
|
1231
|
var session = connection.jingle.sessions[Object.keys(connection.jingle.sessions)[0]];
|
1171
|
1232
|
var focusId = 'participant_' + Strophe.getResourceFromJid(session.peerjid);
|
1172
|
1233
|
var focusContainer = document.getElementById(focusId);
|
|
1234
|
+ if(!focusContainer) {
|
|
1235
|
+ console.error("No focus container!");
|
|
1236
|
+ return;
|
|
1237
|
+ }
|
1173
|
1238
|
var indicatorSpan = $('#' + focusId + ' .focusindicator');
|
1174
|
1239
|
|
1175
|
1240
|
if (!indicatorSpan || indicatorSpan.length === 0) {
|