浏览代码

Changes the implementation to show availability of video and sound devices.

j8
hristoterezov 10 年前
父节点
当前提交
58cc21d417

+ 25
- 0
css/videolayout_default.css 查看文件

415
     left: 35px;
415
     left: 35px;
416
     border-radius: 200px;
416
     border-radius: 200px;
417
 }
417
 }
418
+
419
+.noMic {
420
+    position: absolute;
421
+    border-radius: 8px;
422
+    z-index: 1;
423
+    width: 100%;
424
+    height: 100%;
425
+    background-image: url("../images/noMic.png");
426
+    background-color: #000;
427
+    background-repeat: no-repeat;
428
+    background-position: center;
429
+}
430
+
431
+.noVideo {
432
+    position: absolute;
433
+    border-radius: 8px;
434
+    z-index: 1;
435
+    width: 100%;
436
+    height: 100%;
437
+    background-image: url("../images/noVideo.png");
438
+    background-color: #000;
439
+    background-repeat: no-repeat;
440
+    background-position: center;
441
+}
442
+

二进制
images/noMic.png 查看文件


二进制
images/noVideo.png 查看文件


+ 2
- 2
index.html 查看文件

19
     <script src="libs/popover.js?v=1"></script><!-- bootstrap tooltip lib -->
19
     <script src="libs/popover.js?v=1"></script><!-- bootstrap tooltip lib -->
20
     <script src="libs/toastr.js?v=1"></script><!-- notifications lib -->
20
     <script src="libs/toastr.js?v=1"></script><!-- notifications lib -->
21
     <script src="interface_config.js?v=5"></script>
21
     <script src="interface_config.js?v=5"></script>
22
-    <script src="libs/app.bundle.js?v=47"></script>
22
+    <script src="libs/app.bundle.js?v=48"></script>
23
     <script src="analytics.js?v=1"></script><!-- google analytics plugin -->
23
     <script src="analytics.js?v=1"></script><!-- google analytics plugin -->
24
     <link rel="stylesheet" href="css/font.css?v=6"/>
24
     <link rel="stylesheet" href="css/font.css?v=6"/>
25
     <link rel="stylesheet" href="css/toastr.css?v=1">
25
     <link rel="stylesheet" href="css/toastr.css?v=1">
26
     <link rel="stylesheet" type="text/css" media="screen" href="css/main.css?v=30"/>
26
     <link rel="stylesheet" type="text/css" media="screen" href="css/main.css?v=30"/>
27
-    <link rel="stylesheet" type="text/css" media="screen" href="css/videolayout_default.css?v=16" id="videolayout_default"/>
27
+    <link rel="stylesheet" type="text/css" media="screen" href="css/videolayout_default.css?v=17" id="videolayout_default"/>
28
     <link href="//netdna.bootstrapcdn.com/font-awesome/4.0.3/css/font-awesome.css" rel="stylesheet">
28
     <link href="//netdna.bootstrapcdn.com/font-awesome/4.0.3/css/font-awesome.css" rel="stylesheet">
29
     <link rel="stylesheet" href="css/jquery-impromptu.css?v=4">
29
     <link rel="stylesheet" href="css/jquery-impromptu.css?v=4">
30
     <link rel="stylesheet" href="css/modaldialog.css?v=3">
30
     <link rel="stylesheet" href="css/modaldialog.css?v=3">

+ 26233
- 26120
libs/app.bundle.js
文件差异内容过多而无法显示
查看文件


+ 11
- 0
modules/RTC/RTC.js 查看文件

7
     = require("../../service/desktopsharing/DesktopSharingEventTypes");
7
     = require("../../service/desktopsharing/DesktopSharingEventTypes");
8
 var MediaStreamType = require("../../service/RTC/MediaStreamTypes");
8
 var MediaStreamType = require("../../service/RTC/MediaStreamTypes");
9
 var StreamEventTypes = require("../../service/RTC/StreamEventTypes.js");
9
 var StreamEventTypes = require("../../service/RTC/StreamEventTypes.js");
10
+var RTCEvents = require("../../service/RTC/RTCEvents.js");
10
 var XMPPEvents = require("../../service/xmpp/XMPPEvents");
11
 var XMPPEvents = require("../../service/xmpp/XMPPEvents");
11
 var UIEvents = require("../../service/UI/UIEvents");
12
 var UIEvents = require("../../service/UI/UIEvents");
12
 
13
 
14
 
15
 
15
 var RTC = {
16
 var RTC = {
16
     rtcUtils: null,
17
     rtcUtils: null,
18
+    devices: {
19
+        audio: false,
20
+        video: false
21
+    },
17
     localStreams: [],
22
     localStreams: [],
18
     remoteStreams: {},
23
     remoteStreams: {},
19
     localAudio: null,
24
     localAudio: null,
37
         if(this.localStreams.length == 0 ||
42
         if(this.localStreams.length == 0 ||
38
             this.localStreams[0].getOriginalStream() != stream)
43
             this.localStreams[0].getOriginalStream() != stream)
39
             this.localStreams.push(localStream);
44
             this.localStreams.push(localStream);
45
+
40
         if(type == "audio")
46
         if(type == "audio")
41
         {
47
         {
42
             this.localAudio = localStream;
48
             this.localAudio = localStream;
224
                 callback,
230
                 callback,
225
                 options);
231
                 options);
226
         }
232
         }
233
+    },
234
+    setDeviceAvailability: function (devices) {
235
+        this.devices.audio = (devices && devices.audio === true);
236
+        this.devices.video = (devices && devices.video === true);
237
+        eventEmitter.emit(RTCEvents.AVAILABLE_DEVICES_CHANGED, this.devices);
227
     }
238
     }
228
 };
239
 };
229
 
240
 

+ 19
- 2
modules/RTC/RTCUtils.js 查看文件

225
 
225
 
226
     var isFF = navigator.userAgent.toLowerCase().indexOf('firefox') > -1;
226
     var isFF = navigator.userAgent.toLowerCase().indexOf('firefox') > -1;
227
 
227
 
228
+    var self = this;
229
+
228
     try {
230
     try {
229
         if (config.enableSimulcast
231
         if (config.enableSimulcast
230
             && constraints.video
232
             && constraints.video
236
             && !isFF) {
238
             && !isFF) {
237
             APP.simulcast.getUserMedia(constraints, function (stream) {
239
             APP.simulcast.getUserMedia(constraints, function (stream) {
238
                     console.log('onUserMediaSuccess');
240
                     console.log('onUserMediaSuccess');
241
+                    self.setAvailableDevices(um, true);
239
                     success_callback(stream);
242
                     success_callback(stream);
240
                 },
243
                 },
241
                 function (error) {
244
                 function (error) {
242
                     console.warn('Failed to get access to local media. Error ', error);
245
                     console.warn('Failed to get access to local media. Error ', error);
246
+                    self.setAvailableDevices(um, false);
243
                     if (failure_callback) {
247
                     if (failure_callback) {
244
                         failure_callback(error);
248
                         failure_callback(error);
245
                     }
249
                     }
249
             this.getUserMedia(constraints,
253
             this.getUserMedia(constraints,
250
                 function (stream) {
254
                 function (stream) {
251
                     console.log('onUserMediaSuccess');
255
                     console.log('onUserMediaSuccess');
256
+                    self.setAvailableDevices(um, true);
252
                     success_callback(stream);
257
                     success_callback(stream);
253
                 },
258
                 },
254
                 function (error) {
259
                 function (error) {
260
+                    self.setAvailableDevices(um, false);
255
                     console.warn('Failed to get access to local media. Error ',
261
                     console.warn('Failed to get access to local media. Error ',
256
                         error, constraints);
262
                         error, constraints);
257
                     if (failure_callback) {
263
                     if (failure_callback) {
268
     }
274
     }
269
 };
275
 };
270
 
276
 
277
+RTCUtils.prototype.setAvailableDevices = function (um, available) {
278
+    var devices = {};
279
+    if(um.indexOf("video") != -1)
280
+    {
281
+        devices.video = available;
282
+    }
283
+    if(um.indexOf("audio") != -1)
284
+    {
285
+        devices.audio = available;
286
+    }
287
+    this.service.setDeviceAvailability(devices);
288
+}
289
+
271
 /**
290
 /**
272
  * We ask for audio and video combined stream in order to get permissions and
291
  * We ask for audio and video combined stream in order to get permissions and
273
  * not to ask twice.
292
  * not to ask twice.
328
             function (error) {
347
             function (error) {
329
                 console.error('failed to obtain audio/video stream - stop',
348
                 console.error('failed to obtain audio/video stream - stop',
330
                     error);
349
                     error);
331
-//                APP.UI.messageHandler.showError("dialog.error",
332
-//                    "dialog.failedpermissions");
333
                 return self.successCallback(null);
350
                 return self.successCallback(null);
334
             }
351
             }
335
         );
352
         );

+ 10
- 3
modules/UI/UI.js 查看文件

105
         function (endpointSimulcastLayers) {
105
         function (endpointSimulcastLayers) {
106
             VideoLayout.onSimulcastLayersChanging(endpointSimulcastLayers);
106
             VideoLayout.onSimulcastLayersChanging(endpointSimulcastLayers);
107
         });
107
         });
108
-
108
+    APP.RTC.addListener(RTCEvents.AVAILABLE_DEVICES_CHANGED,
109
+        function (devices) {
110
+            VideoLayout.setDeviceAvailabilityIcons(null, devices);
111
+        })
109
     APP.statistics.addAudioLevelListener(function(jid, audioLevel)
112
     APP.statistics.addAudioLevelListener(function(jid, audioLevel)
110
     {
113
     {
111
         var resourceJid;
114
         var resourceJid;
214
     APP.xmpp.addListener(XMPPEvents.PASSWORD_REQUIRED, onPasswordReqiured);
217
     APP.xmpp.addListener(XMPPEvents.PASSWORD_REQUIRED, onPasswordReqiured);
215
     APP.xmpp.addListener(XMPPEvents.CHAT_ERROR_RECEIVED, chatAddError);
218
     APP.xmpp.addListener(XMPPEvents.CHAT_ERROR_RECEIVED, chatAddError);
216
     APP.xmpp.addListener(XMPPEvents.ETHERPAD, initEtherpad);
219
     APP.xmpp.addListener(XMPPEvents.ETHERPAD, initEtherpad);
217
-    APP.xmpp.addListener(XMPPEvents.AUTHENTICATION_REQUIRED, onAuthenticationRequired);
218
-
220
+    APP.xmpp.addListener(XMPPEvents.AUTHENTICATION_REQUIRED,
221
+        onAuthenticationRequired);
222
+    APP.xmpp.addListener(XMPPEvents.DEVICE_AVAILABLE,
223
+        function (resource, devices) {
224
+            VideoLayout.setDeviceAvailabilityIcons(resource, devices);
225
+        });
219
 
226
 
220
 }
227
 }
221
 
228
 

+ 42
- 0
modules/UI/videolayout/VideoLayout.js 查看文件

639
 
639
 
640
     };
640
     };
641
 
641
 
642
+    /**
643
+     * Adds or removes icons for not available camera and microphone.
644
+     * @param resourceJid the jid of user
645
+     * @param devices available devices
646
+     */
647
+    my.setDeviceAvailabilityIcons = function (resourceJid, devices) {
648
+        if(!devices)
649
+            return;
650
+
651
+        var container = null
652
+        if(!resourceJid)
653
+        {
654
+            container = $("#localVideoContainer")[0];
655
+        }
656
+        else
657
+        {
658
+            container = $("#participant_" + resourceJid)[0];
659
+        }
660
+
661
+        if(!container)
662
+            return;
663
+
664
+        $("#" + container.id + " > .noMic").remove();
665
+        $("#" + container.id + " > .noVideo").remove();
666
+        if(!devices.audio)
667
+        {
668
+            container.appendChild(document.createElement("div")).setAttribute("class","noMic");
669
+        }
670
+
671
+        if(!devices.video)
672
+        {
673
+            container.appendChild(document.createElement("div")).setAttribute("class","noVideo");
674
+        }
675
+
676
+        if(!devices.audio && !devices.video)
677
+        {
678
+            $("#" + container.id + " > .noMic").css("background-position", "75%");
679
+            $("#" + container.id + " > .noVideo").css("background-position", "25%");
680
+            $("#" + container.id + " > .noVideo").css("background-color", "transparent");
681
+        }
682
+    }
683
+
642
     /**
684
     /**
643
      * Checks if removed video is currently displayed and tries to display
685
      * Checks if removed video is currently displayed and tries to display
644
      * another one instead.
686
      * another one instead.

+ 27
- 0
modules/xmpp/strophe.emuc.js 查看文件

143
                 $(document).trigger('videomuted.muc', [from, videoMuted.text()]);
143
                 $(document).trigger('videomuted.muc', [from, videoMuted.text()]);
144
             }
144
             }
145
 
145
 
146
+            var devices = $(pres).find('>devices');
147
+            if(devices.length)
148
+            {
149
+                var audio = devices.find('>audio');
150
+                var video = devices.find('>video');
151
+                var devicesValues = {audio: false, video: false};
152
+                if(audio.length && audio.text() === "true")
153
+                {
154
+                    devicesValues.audio = true;
155
+                }
156
+
157
+                if(video.length && video.text() === "true")
158
+                {
159
+                    devicesValues.video = true;
160
+                }
161
+                eventEmitter.emit(XMPPEvents.DEVICE_AVAILABLE,
162
+                    Strophe.getResourceFromJid(from), devicesValues);
163
+            }
164
+
146
             var stats = $(pres).find('>stats');
165
             var stats = $(pres).find('>stats');
147
             if (stats.length) {
166
             if (stats.length) {
148
                 var statsObj = {};
167
                 var statsObj = {};
422
                     .t(this.presMap['displayName']).up();
441
                     .t(this.presMap['displayName']).up();
423
             }
442
             }
424
 
443
 
444
+            if(this.presMap["devices"])
445
+            {
446
+                pres.c('devices').c('audio').t(this.presMap['devices'].audio).up()
447
+                    .c('video').t(this.presMap['devices'].video).up().up();
448
+            }
425
             if (this.presMap['audions']) {
449
             if (this.presMap['audions']) {
426
                 pres.c('audiomuted', {xmlns: this.presMap['audions']})
450
                 pres.c('audiomuted', {xmlns: this.presMap['audions']})
427
                     .t(this.presMap['audiomuted']).up();
451
                     .t(this.presMap['audiomuted']).up();
485
             this.presMap['source' + sourceNumber + '_ssrc'] = ssrcs;
509
             this.presMap['source' + sourceNumber + '_ssrc'] = ssrcs;
486
             this.presMap['source' + sourceNumber + '_direction'] = direction;
510
             this.presMap['source' + sourceNumber + '_direction'] = direction;
487
         },
511
         },
512
+        addDevicesToPresence: function (devices) {
513
+            this.presMap['devices'] = devices;
514
+        },
488
         clearPresenceMedia: function () {
515
         clearPresenceMedia: function () {
489
             var self = this;
516
             var self = this;
490
             Object.keys(this.presMap).forEach(function (key) {
517
             Object.keys(this.presMap).forEach(function (key) {

+ 7
- 0
modules/xmpp/xmpp.js 查看文件

6
 var Settings = require("../settings/Settings");
6
 var Settings = require("../settings/Settings");
7
 var Pako = require("pako");
7
 var Pako = require("pako");
8
 var StreamEventTypes = require("../../service/RTC/StreamEventTypes");
8
 var StreamEventTypes = require("../../service/RTC/StreamEventTypes");
9
+var RTCEvents = require("../../service/RTC/RTCEvents");
9
 var UIEvents = require("../../service/UI/UIEvents");
10
 var UIEvents = require("../../service/UI/UIEvents");
10
 var XMPPEvents = require("../../service/xmpp/XMPPEvents");
11
 var XMPPEvents = require("../../service/xmpp/XMPPEvents");
11
 
12
 
102
 function registerListeners() {
103
 function registerListeners() {
103
     APP.RTC.addStreamListener(maybeDoJoin,
104
     APP.RTC.addStreamListener(maybeDoJoin,
104
         StreamEventTypes.EVENT_TYPE_LOCAL_CREATED);
105
         StreamEventTypes.EVENT_TYPE_LOCAL_CREATED);
106
+    APP.RTC.addListener(RTCEvents.AVAILABLE_DEVICES_CHANGED, function (devices) {
107
+        XMPP.addToPresence("devices", devices);
108
+    })
105
     APP.UI.addListener(UIEvents.NICKNAME_CHANGED, function (nickname) {
109
     APP.UI.addListener(UIEvents.NICKNAME_CHANGED, function (nickname) {
106
         XMPP.addToPresence("displayName", nickname);
110
         XMPP.addToPresence("displayName", nickname);
107
     });
111
     });
385
             case "email":
389
             case "email":
386
                 connection.emuc.addEmailToPresence(value);
390
                 connection.emuc.addEmailToPresence(value);
387
                 break;
391
                 break;
392
+            case "devices":
393
+                connection.emuc.addDevicesToPresence(value);
394
+                break;
388
             default :
395
             default :
389
                 console.log("Unknown tag for presence: " + name);
396
                 console.log("Unknown tag for presence: " + name);
390
                 return;
397
                 return;

+ 2
- 1
service/RTC/RTCEvents.js 查看文件

5
     SIMULCAST_LAYER_CHANGED: "rtc.simulcast_layer_changed",
5
     SIMULCAST_LAYER_CHANGED: "rtc.simulcast_layer_changed",
6
     SIMULCAST_LAYER_CHANGING: "rtc.simulcast_layer_changing",
6
     SIMULCAST_LAYER_CHANGING: "rtc.simulcast_layer_changing",
7
     SIMULCAST_START: "rtc.simlcast_start",
7
     SIMULCAST_START: "rtc.simlcast_start",
8
-    SIMULCAST_STOP: "rtc.simlcast_stop"
8
+    SIMULCAST_STOP: "rtc.simlcast_stop",
9
+    AVAILABLE_DEVICES_CHANGED: "rtc.available_devices_changed"
9
 };
10
 };
10
 
11
 
11
 module.exports = RTCEvents;
12
 module.exports = RTCEvents;

+ 2
- 1
service/xmpp/XMPPEvents.js 查看文件

24
     PASSWORD_REQUIRED: "xmpp.password_required",
24
     PASSWORD_REQUIRED: "xmpp.password_required",
25
     AUTHENTICATION_REQUIRED: "xmpp.authentication_required",
25
     AUTHENTICATION_REQUIRED: "xmpp.authentication_required",
26
     CHAT_ERROR_RECEIVED: "xmpp.chat_error_received",
26
     CHAT_ERROR_RECEIVED: "xmpp.chat_error_received",
27
-    ETHERPAD: "xmpp.etherpad"
27
+    ETHERPAD: "xmpp.etherpad",
28
+    DEVICE_AVAILABLE: "xmpp.device_available"
28
 };
29
 };
29
 module.exports = XMPPEvents;
30
 module.exports = XMPPEvents;

正在加载...
取消
保存