Quellcode durchsuchen

Update libs/app.bundle.js.

j8
George Politis vor 10 Jahren
Ursprung
Commit
777422c87d
2 geänderte Dateien mit 302 neuen und 199 gelöschten Zeilen
  1. 1
    1
      index.html
  2. 301
    198
      libs/app.bundle.js

+ 1
- 1
index.html Datei anzeigen

@@ -19,7 +19,7 @@
19 19
     <script src="libs/popover.js?v=1"></script><!-- bootstrap tooltip lib -->
20 20
     <script src="libs/toastr.js?v=1"></script><!-- notifications lib -->
21 21
     <script src="interface_config.js?v=5"></script>
22
-    <script src="libs/app.bundle.js?v=67"></script>
22
+    <script src="libs/app.bundle.js?v=68"></script>
23 23
     <script src="analytics.js?v=1"></script><!-- google analytics plugin -->
24 24
     <link rel="stylesheet" href="css/font.css?v=7"/>
25 25
     <link rel="stylesheet" href="css/toastr.css?v=1">

+ 301
- 198
libs/app.bundle.js Datei anzeigen

@@ -705,28 +705,26 @@ var eventEmitter = new EventEmitter();
705 705
 function getMediaStreamUsage()
706 706
 {
707 707
     var result = {
708
-        audio: 1,
709
-        video: 1
708
+        audio: true,
709
+        video: true
710 710
     };
711
-    if( config.startAudioMuted === true)
712
-        result.audio = 0;
713
-    if( config.startVideoMuted === true)
714
-        result.video = 0;
715 711
 
716 712
     /** There are some issues with the desktop sharing
717 713
      * when this property is enabled.
714
+     * WARNING: We must change the implementation to start video/audio if we
715
+     * receive from the focus that the peer is not muted.
718 716
 
719
-     if(result.audio > 0 && result.video > 0)
720
-        return result;
721 717
      var isSecureConnection = window.location.protocol == "https:";
722 718
 
723 719
     if(config.disableEarlyMediaPermissionRequests || !isSecureConnection)
724 720
     {
725
-        if(result.audio === 0)
726
-            result.audio = -1;
727
-        if(result.video === 0)
728
-            result.video = -1;
729
-    }**/
721
+        result = {
722
+            audio: false,
723
+            video: false
724
+        };
725
+
726
+    }
727
+    **/
730 728
 
731 729
     return result;
732 730
 }
@@ -1276,7 +1274,9 @@ RTCUtils.prototype.setAvailableDevices = function (um, available) {
1276 1274
  * We ask for audio and video combined stream in order to get permissions and
1277 1275
  * not to ask twice.
1278 1276
  */
1279
-RTCUtils.prototype.obtainAudioAndVideoPermissions = function(devices, callback, usageOptions) {
1277
+RTCUtils.prototype.obtainAudioAndVideoPermissions =
1278
+    function(devices, callback, usageOptions)
1279
+{
1280 1280
     var self = this;
1281 1281
     // Get AV
1282 1282
 
@@ -1297,7 +1297,7 @@ RTCUtils.prototype.obtainAudioAndVideoPermissions = function(devices, callback,
1297 1297
         for(var i = 0; i < devices.length; i++)
1298 1298
         {
1299 1299
             var device = devices[i];
1300
-            if(usageOptions[device] !== -1)
1300
+            if(usageOptions[device] === true)
1301 1301
                 newDevices.push(device);
1302 1302
         }
1303 1303
     else
@@ -1431,11 +1431,12 @@ RTCUtils.prototype.handleLocalStream = function(stream, usageOptions)
1431 1431
         videoStream = stream.videoStream;
1432 1432
     }
1433 1433
 
1434
-    var audioMuted = (usageOptions && usageOptions.audio != 1),
1435
-        videoMuted = (usageOptions && usageOptions.video != 1);
1434
+    var audioMuted = (usageOptions && usageOptions.audio === false),
1435
+        videoMuted = (usageOptions && usageOptions.video === false);
1436
+
1437
+    var audioGUM = (!usageOptions || usageOptions.audio !== false),
1438
+        videoGUM = (!usageOptions || usageOptions.video !== false);
1436 1439
 
1437
-    var audioGUM = (!usageOptions || usageOptions.audio != -1),
1438
-        videoGUM = (!usageOptions || usageOptions.video != -1);
1439 1440
 
1440 1441
     this.service.createLocalStream(audioStream, "audio", null, null,
1441 1442
         audioMuted, audioGUM);
@@ -1505,10 +1506,8 @@ var roomName = null;
1505 1506
 
1506 1507
 function notifyForInitialMute()
1507 1508
 {
1508
-    if(config.startAudioMuted || config.startVideoMuted)
1509
-    {
1510
-        messageHandler.notify(null, "notify.mutedTitle", "connected", "notify.muted", null, {timeOut: 120000});
1511
-    }
1509
+    messageHandler.notify(null, "notify.mutedTitle", "connected",
1510
+        "notify.muted", null, {timeOut: 120000});
1512 1511
 }
1513 1512
 
1514 1513
 function setupPrezi()
@@ -1725,6 +1724,9 @@ function registerListeners() {
1725 1724
 
1726 1725
     APP.members.addListener(MemberEvents.DTMF_SUPPORT_CHANGED,
1727 1726
                             onDtmfSupportChanged);
1727
+    APP.xmpp.addListener(XMPPEvents.START_MUTED, function (audio, video) {
1728
+        SettingsMenu.setStartMuted(audio, video);
1729
+    });
1728 1730
 }
1729 1731
 
1730 1732
 
@@ -1879,8 +1881,6 @@ UI.start = function (init) {
1879 1881
 
1880 1882
     SettingsMenu.init();
1881 1883
 
1882
-    notifyForInitialMute();
1883
-
1884 1884
 };
1885 1885
 
1886 1886
 function chatAddError(errorMessage, originalText)
@@ -1956,6 +1956,7 @@ function onLocalRoleChanged(jid, info, pres, isModerator)
1956 1956
     console.info("My role changed, new role: " + info.role);
1957 1957
     onModeratorStatusChanged(isModerator);
1958 1958
     VideoLayout.showModeratorIndicator();
1959
+    SettingsMenu.onRoleChanged();
1959 1960
 
1960 1961
     if (isModerator) {
1961 1962
         Authentication.closeAuthenticationWindow();
@@ -2200,6 +2201,12 @@ UI.getRoomName = function () {
2200 2201
     return roomName;
2201 2202
 };
2202 2203
 
2204
+UI.setInitialMuteFromFocus = function (muteAudio, muteVideo) {
2205
+    if(muteAudio || muteVideo) notifyForInitialMute();
2206
+    if(muteAudio) UI.setAudioMuted(true);
2207
+    if(muteVideo) UI.setVideoMute(true);
2208
+}
2209
+
2203 2210
 /**
2204 2211
  * Mutes/unmutes the local video.
2205 2212
  */
@@ -5090,7 +5097,7 @@ function generateLanguagesSelectBox()
5090 5097
 var SettingsMenu = {
5091 5098
 
5092 5099
     init: function () {
5093
-        $("#updateSettings").before(generateLanguagesSelectBox());
5100
+        $("#startMutedOptions").before(generateLanguagesSelectBox());
5094 5101
         APP.translation.translateElement($("#languages_selectbox"));
5095 5102
         $('#settingsmenu>input').keyup(function(event){
5096 5103
             if(event.keyCode === 13) {//enter
@@ -5098,11 +5105,36 @@ var SettingsMenu = {
5098 5105
             }
5099 5106
         });
5100 5107
 
5108
+        if(APP.xmpp.isModerator())
5109
+        {
5110
+            $("#startMutedOptions").css("display", "block");
5111
+        }
5112
+        else
5113
+        {
5114
+            $("#startMutedOptions").css("display", "none");
5115
+        }
5116
+
5101 5117
         $("#updateSettings").click(function () {
5102 5118
             SettingsMenu.update();
5103 5119
         });
5104 5120
     },
5105 5121
 
5122
+    onRoleChanged: function () {
5123
+        if(APP.xmpp.isModerator())
5124
+        {
5125
+            $("#startMutedOptions").css("display", "block");
5126
+        }
5127
+        else
5128
+        {
5129
+            $("#startMutedOptions").css("display", "none");
5130
+        }
5131
+    },
5132
+
5133
+    setStartMuted: function (audio, video) {
5134
+        $("#startAudioMuted").attr("checked", audio);
5135
+        $("#startVideoMuted").attr("checked", video);
5136
+    },
5137
+
5106 5138
     update: function() {
5107 5139
         var newDisplayName = UIUtil.escapeHtml($('#setDisplayName').get(0).value);
5108 5140
         var newEmail = UIUtil.escapeHtml($('#setEmail').get(0).value);
@@ -5119,6 +5151,10 @@ var SettingsMenu = {
5119 5151
         APP.xmpp.addToPresence("email", newEmail);
5120 5152
         var email = Settings.setEmail(newEmail);
5121 5153
 
5154
+        var startAudioMuted = ($("#startAudioMuted").is(":checked"));
5155
+        var startVideoMuted = ($("#startVideoMuted").is(":checked"));
5156
+        APP.xmpp.addToPresence("startMuted",
5157
+            [startAudioMuted, startVideoMuted]);
5122 5158
 
5123 5159
         Avatar.setUserAvatar(APP.xmpp.myJid(), email);
5124 5160
     },
@@ -15638,6 +15674,20 @@ var Moderator = {
15638 15674
                 { name: 'openSctp', value: config.openSctp})
15639 15675
                 .up();
15640 15676
         }
15677
+        if(config.startAudioMuted !== undefined)
15678
+        {
15679
+            elem.c(
15680
+                'property',
15681
+                { name: 'startAudioMuted', value: config.startAudioMuted})
15682
+                .up();
15683
+        }
15684
+        if(config.startVideoMuted !== undefined)
15685
+        {
15686
+            elem.c(
15687
+                'property',
15688
+                { name: 'startVideoMuted', value: config.startVideoMuted})
15689
+                .up();
15690
+        }
15641 15691
         elem.up();
15642 15692
         return elem;
15643 15693
     },
@@ -16187,6 +16237,13 @@ module.exports = function(XMPP, eventEmitter) {
16187 16237
                 $(document).trigger('videomuted.muc', [from, videoMuted.text()]);
16188 16238
             }
16189 16239
 
16240
+            var startMuted = $(pres).find('>startmuted');
16241
+            if (startMuted.length)
16242
+            {
16243
+                eventEmitter.emit(XMPPEvents.START_MUTED,
16244
+                    startMuted.attr("audio") === "true", startMuted.attr("video") === "true");
16245
+            }
16246
+
16190 16247
             var devices = $(pres).find('>devices');
16191 16248
             if(devices.length)
16192 16249
             {
@@ -16541,6 +16598,15 @@ module.exports = function(XMPP, eventEmitter) {
16541 16598
                                     || 'sendrecv' }
16542 16599
                         ).up();
16543 16600
                     }
16601
+                pres.up();
16602
+            }
16603
+
16604
+            if(this.presMap["startMuted"] !== undefined)
16605
+            {
16606
+                pres.c("startmuted", {audio: this.presMap["startMuted"].audio,
16607
+                    video: this.presMap["startMuted"].video,
16608
+                    xmlns: "http://jitsi.org/jitmeet/start-muted"});
16609
+                delete this.presMap["startMuted"];
16544 16610
             }
16545 16611
 
16546 16612
             pres.up();
@@ -16621,6 +16687,9 @@ module.exports = function(XMPP, eventEmitter) {
16621 16687
         addUserIdToPresence: function (userId) {
16622 16688
             this.presMap['userId'] = userId;
16623 16689
         },
16690
+        addStartMutedToPresence: function (audio, video) {
16691
+            this.presMap["startMuted"] = {audio: audio, video: video};
16692
+        },
16624 16693
         isModerator: function () {
16625 16694
             return this.role === 'moderator';
16626 16695
         },
@@ -16808,6 +16877,14 @@ module.exports = function(XMPP, eventEmitter)
16808 16877
             // see http://xmpp.org/extensions/xep-0166.html#concepts-session
16809 16878
             switch (action) {
16810 16879
                 case 'session-initiate':
16880
+                    var startMuted = $(iq).find('jingle>startmuted');
16881
+                    if(startMuted && startMuted.length > 0)
16882
+                    {
16883
+                        var audioMuted = startMuted.attr("audio");
16884
+                        var videoMuted = startMuted.attr("video");
16885
+                        APP.UI.setInitialMuteFromFocus((audioMuted === "true"),
16886
+                            (videoMuted === "true"));
16887
+                    }
16811 16888
                     sess = new JingleSession(
16812 16889
                         $(iq).attr('to'), $(iq).find('jingle').attr('sid'),
16813 16890
                         this.connection, XMPP);
@@ -17450,8 +17527,13 @@ function registerListeners() {
17450 17527
     });
17451 17528
 }
17452 17529
 
17453
-function setupEvents() {
17454
-    $(window).bind('beforeunload', function () {
17530
+var unload = (function () {
17531
+    var unloaded = false;
17532
+
17533
+    return function () {
17534
+        if (unloaded) { return; }
17535
+        unloaded = true;
17536
+
17455 17537
         if (connection && connection.connected) {
17456 17538
             // ensure signout
17457 17539
             $.ajax({
@@ -17460,24 +17542,41 @@ function setupEvents() {
17460 17542
                 async: false,
17461 17543
                 cache: false,
17462 17544
                 contentType: 'application/xml',
17463
-                data: "<body rid='" + (connection.rid || connection._proto.rid)
17464
-                    + "' xmlns='http://jabber.org/protocol/httpbind' sid='"
17465
-                    + (connection.sid || connection._proto.sid)
17466
-                    + "' type='terminate'>" +
17467
-                    "<presence xmlns='jabber:client' type='unavailable'/>" +
17468
-                    "</body>",
17545
+                data: "<body rid='" + (connection.rid || connection._proto.rid) +
17546
+                    "' xmlns='http://jabber.org/protocol/httpbind' sid='" +
17547
+                    (connection.sid || connection._proto.sid)  +
17548
+                    "' type='terminate'>" +
17549
+                "<presence xmlns='jabber:client' type='unavailable'/>" +
17550
+                "</body>",
17469 17551
                 success: function (data) {
17470 17552
                     console.log('signed out');
17471 17553
                     console.log(data);
17472 17554
                 },
17473 17555
                 error: function (XMLHttpRequest, textStatus, errorThrown) {
17474 17556
                     console.log('signout error',
17475
-                            textStatus + ' (' + errorThrown + ')');
17557
+                        textStatus + ' (' + errorThrown + ')');
17476 17558
                 }
17477 17559
             });
17478 17560
         }
17479 17561
         XMPP.disposeConference(true);
17480
-    });
17562
+    };
17563
+})();
17564
+
17565
+function setupEvents() {
17566
+    // In recent versions of FF the 'beforeunload' event is not fired when the
17567
+    // window or the tab is closed. It is only fired when we leave the page
17568
+    // (change URL). If this participant doesn't unload properly, then it
17569
+    // becomes a ghost for the rest of the participants that stay in the
17570
+    // conference. Thankfully handling the 'unload' event in addition to the
17571
+    // 'beforeunload' event seems to garante the execution of the 'unload'
17572
+    // method at least once.
17573
+    //
17574
+    // The 'unload' method can safely be run multiple times, it will actually do
17575
+    // something only the first time that it's run, so we're don't have to worry
17576
+    // about browsers that fire both events.
17577
+
17578
+    $(window).bind('beforeunload', unload);
17579
+    $(window).bind('unload', unload);
17481 17580
 }
17482 17581
 
17483 17582
 var XMPP = {
@@ -17741,6 +17840,12 @@ var XMPP = {
17741 17840
             case "devices":
17742 17841
                 connection.emuc.addDevicesToPresence(value);
17743 17842
                 break;
17843
+            case "startMuted":
17844
+                if(!Moderator.isModerator())
17845
+                    return;
17846
+                connection.emuc.addStartMutedToPresence(value[0],
17847
+                    value[1]);
17848
+                break;
17744 17849
             default :
17745 17850
                 console.log("Unknown tag for presence: " + name);
17746 17851
                 return;
@@ -28054,6 +28159,8 @@ module.exports = function arrayEquals(array) {
28054 28159
 exports.Interop = require('./interop');
28055 28160
 
28056 28161
 },{"./interop":88}],88:[function(require,module,exports){
28162
+"use strict";
28163
+
28057 28164
 var transform = require('./transform');
28058 28165
 var arrayEquals = require('./array-equals');
28059 28166
 
@@ -28122,46 +28229,47 @@ Interop.prototype.toPlanB = function(desc) {
28122 28229
     session.media = [];
28123 28230
 
28124 28231
     // Associative array that maps channel types to channel objects for fast
28125
-    // access to channel objects by their type, e.g. channels['audio']->channel
28232
+    // access to channel objects by their type, e.g. type2bl['audio']->channel
28126 28233
     // obj.
28127
-    var channels = {};
28234
+    var type2bl = {};
28128 28235
 
28129 28236
     // Used to build the group:BUNDLE value after the channels construction
28130 28237
     // loop.
28131 28238
     var types = [];
28132 28239
 
28133
-    // Implode the Unified Plan m-lines/tracks into Plan B "channels".
28134
-    media.forEach(function(mLine) {
28240
+    // Implode the Unified Plan m-lines/tracks into Plan B channels.
28241
+    media.forEach(function(unifiedLine) {
28135 28242
 
28136 28243
         // rtcp-mux is required in the Plan B SDP.
28137
-        if (typeof mLine.rtcpMux !== 'string' ||
28138
-            mLine.rtcpMux !== 'rtcp-mux') {
28244
+        if ((typeof unifiedLine.rtcpMux !== 'string' ||
28245
+            unifiedLine.rtcpMux !== 'rtcp-mux') &&
28246
+            unifiedLine.direction !== 'inactive') {
28139 28247
             throw new Error('Cannot convert to Plan B because m-lines ' +
28140 28248
                 'without the rtcp-mux attribute were found.');
28141 28249
         }
28142 28250
 
28143
-        // If we don't have a channel for this mLine.type, then use this mLine
28251
+        // If we don't have a channel for this unifiedLine.type, then use this unifiedLine
28144 28252
         // as the channel basis.
28145
-        if (typeof channels[mLine.type] === 'undefined') {
28146
-            channels[mLine.type] = mLine;
28253
+        if (typeof type2bl[unifiedLine.type] === 'undefined') {
28254
+            type2bl[unifiedLine.type] = unifiedLine;
28147 28255
         }
28148 28256
 
28149 28257
         // Add sources to the channel and handle a=msid.
28150
-        if (typeof mLine.sources === 'object') {
28151
-            Object.keys(mLine.sources).forEach(function(ssrc) {
28152
-                if (typeof channels[mLine.type].sources !== 'object')
28153
-                    channels[mLine.type].sources = {};
28258
+        if (typeof unifiedLine.sources === 'object') {
28259
+            Object.keys(unifiedLine.sources).forEach(function(ssrc) {
28260
+                if (typeof type2bl[unifiedLine.type].sources !== 'object')
28261
+                    type2bl[unifiedLine.type].sources = {};
28154 28262
 
28155 28263
                 // Assign the sources to the channel.
28156
-                channels[mLine.type].sources[ssrc] = mLine.sources[ssrc];
28264
+                type2bl[unifiedLine.type].sources[ssrc] = unifiedLine.sources[ssrc];
28157 28265
 
28158
-                if (typeof mLine.msid !== 'undefined') {
28266
+                if (typeof unifiedLine.msid !== 'undefined') {
28159 28267
                     // In Plan B the msid is an SSRC attribute. Also, we don't
28160 28268
                     // care about the obsolete label and mslabel attributes.
28161 28269
                     //
28162
-                    // Note that it is not guaranteed that the mLine will have
28270
+                    // Note that it is not guaranteed that the unifiedLine will have
28163 28271
                     // an msid. recvonly channels in particular don't have one.
28164
-                    channels[mLine.type].sources[ssrc].msid = mLine.msid;
28272
+                    type2bl[unifiedLine.type].sources[ssrc].msid = unifiedLine.msid;
28165 28273
                 }
28166 28274
                 // NOTE ssrcs in ssrc groups will share msids, as
28167 28275
                 // draft-uberti-rtcweb-plan-00 mandates.
@@ -28169,39 +28277,39 @@ Interop.prototype.toPlanB = function(desc) {
28169 28277
         }
28170 28278
 
28171 28279
         // Add ssrc groups to the channel.
28172
-        if (typeof mLine.ssrcGroups !== 'undefined' &&
28173
-                Array.isArray(mLine.ssrcGroups)) {
28280
+        if (typeof unifiedLine.ssrcGroups !== 'undefined' &&
28281
+                Array.isArray(unifiedLine.ssrcGroups)) {
28174 28282
 
28175 28283
             // Create the ssrcGroups array, if it's not defined.
28176
-            if (typeof channel.ssrcGroups === 'undefined' ||
28177
-                    !Array.isArray(channel.ssrcGroups)) {
28178
-                channel.ssrcGroups = [];
28284
+            if (typeof type2bl[unifiedLine.type].ssrcGroups === 'undefined' ||
28285
+                    !Array.isArray(type2bl[unifiedLine.type].ssrcGroups)) {
28286
+                type2bl[unifiedLine.type].ssrcGroups = [];
28179 28287
             }
28180 28288
 
28181
-            channel.ssrcGroups = channel.ssrcGroups.concat(mLine.ssrcGroups);
28289
+            type2bl[unifiedLine.type].ssrcGroups = type2bl[unifiedLine.type].ssrcGroups.concat(unifiedLine.ssrcGroups);
28182 28290
         }
28183 28291
 
28184
-        if (channels[mLine.type] === mLine) {
28292
+        if (type2bl[unifiedLine.type] === unifiedLine) {
28185 28293
             // Copy ICE related stuff from the principal media line.
28186
-            mLine.candidates = media[0].candidates;
28187
-            mLine.iceUfrag = media[0].iceUfrag;
28188
-            mLine.icePwd = media[0].icePwd;
28189
-            mLine.fingerprint = media[0].fingerprint;
28294
+            unifiedLine.candidates = media[0].candidates;
28295
+            unifiedLine.iceUfrag = media[0].iceUfrag;
28296
+            unifiedLine.icePwd = media[0].icePwd;
28297
+            unifiedLine.fingerprint = media[0].fingerprint;
28190 28298
 
28191 28299
             // Plan B mids are in ['audio', 'video', 'data']
28192
-            mLine.mid = mLine.type;
28300
+            unifiedLine.mid = unifiedLine.type;
28193 28301
 
28194 28302
             // Plan B doesn't support/need the bundle-only attribute.
28195
-            delete mLine.bundleOnly;
28303
+            delete unifiedLine.bundleOnly;
28196 28304
 
28197 28305
             // In Plan B the msid is an SSRC attribute.
28198
-            delete mLine.msid;
28306
+            delete unifiedLine.msid;
28199 28307
 
28200 28308
             // Used to build the group:BUNDLE value after this loop.
28201
-            types.push(mLine.type);
28309
+            types.push(unifiedLine.type);
28202 28310
 
28203 28311
             // Add the channel to the new media array.
28204
-            session.media.push(mLine);
28312
+            session.media.push(unifiedLine);
28205 28313
         }
28206 28314
     });
28207 28315
 
@@ -28317,34 +28425,35 @@ Interop.prototype.toUnifiedPlan = function(desc) {
28317 28425
 
28318 28426
     // A helper map that sends mids to m-line objects. We use it later to
28319 28427
     // rebuild the Unified Plan style session.media array.
28320
-    var mid2ml = {};
28321
-    session.media.forEach(function(channel) {
28322
-        if (typeof channel.rtcpMux !== 'string' ||
28323
-            channel.rtcpMux !== 'rtcp-mux') {
28428
+    var mid2ul = {};
28429
+    session.media.forEach(function(bLine) {
28430
+        if ((typeof bLine.rtcpMux !== 'string' ||
28431
+            bLine.rtcpMux !== 'rtcp-mux') &&
28432
+            bLine.direction !== 'inactive') {
28324 28433
             throw new Error("Cannot convert to Unified Plan because m-lines " +
28325 28434
                 "without the rtcp-mux attribute were found.");
28326 28435
         }
28327 28436
 
28328 28437
         // With rtcp-mux and bundle all the channels should have the same ICE
28329 28438
         // stuff.
28330
-        var sources = channel.sources;
28331
-        var ssrcGroups = channel.ssrcGroups;
28332
-        var candidates = channel.candidates;
28333
-        var iceUfrag = channel.iceUfrag;
28334
-        var icePwd = channel.icePwd;
28335
-        var fingerprint = channel.fingerprint;
28336
-        var port = channel.port;
28337
-
28338
-        // We'll use the "channel" object as a prototype for each new "mLine"
28439
+        var sources = bLine.sources;
28440
+        var ssrcGroups = bLine.ssrcGroups;
28441
+        var candidates = bLine.candidates;
28442
+        var iceUfrag = bLine.iceUfrag;
28443
+        var icePwd = bLine.icePwd;
28444
+        var fingerprint = bLine.fingerprint;
28445
+        var port = bLine.port;
28446
+
28447
+        // We'll use the "bLine" object as a prototype for each new "mLine"
28339 28448
         // that we create, but first we need to clean it up a bit.
28340
-        delete channel.sources;
28341
-        delete channel.ssrcGroups;
28342
-        delete channel.candidates;
28343
-        delete channel.iceUfrag;
28344
-        delete channel.icePwd;
28345
-        delete channel.fingerprint;
28346
-        delete channel.port;
28347
-        delete channel.mid;
28449
+        delete bLine.sources;
28450
+        delete bLine.ssrcGroups;
28451
+        delete bLine.candidates;
28452
+        delete bLine.iceUfrag;
28453
+        delete bLine.icePwd;
28454
+        delete bLine.fingerprint;
28455
+        delete bLine.port;
28456
+        delete bLine.mid;
28348 28457
 
28349 28458
         // inverted ssrc group map
28350 28459
         var ssrc2group = {};
@@ -28378,11 +28487,11 @@ Interop.prototype.toUnifiedPlan = function(desc) {
28378 28487
             // Explode the Plan B channel sources with one m-line per source.
28379 28488
             Object.keys(sources).forEach(function(ssrc) {
28380 28489
 
28381
-                // The m-line for this SSRC. We either create it from scratch
28382
-                // or, if it's a grouped SSRC, we re-use a related mline. In
28383
-                // other words, if the source is grouped with another source,
28384
-                // put the two together in the same m-line.
28385
-                var mLine;
28490
+                // The (unified) m-line for this SSRC. We either create it from
28491
+                // scratch or, if it's a grouped SSRC, we re-use a related
28492
+                // mline. In other words, if the source is grouped with another
28493
+                // source, put the two together in the same m-line.
28494
+                var unifiedLine;
28386 28495
                 if (typeof ssrc2group[ssrc] !== 'undefined' &&
28387 28496
                     Array.isArray(ssrc2group[ssrc])) {
28388 28497
                     ssrc2group[ssrc].some(function (ssrcGroup) {
@@ -28390,21 +28499,21 @@ Interop.prototype.toUnifiedPlan = function(desc) {
28390 28499
                         // again here.
28391 28500
                         return ssrcGroup.ssrcs.some(function (related) {
28392 28501
                             if (typeof ssrc2ml[related] === 'object') {
28393
-                                mLine = ssrc2ml[related];
28502
+                                unifiedLine = ssrc2ml[related];
28394 28503
                                 return true;
28395 28504
                             }
28396 28505
                         });
28397 28506
                     });
28398 28507
                 }
28399 28508
 
28400
-                if (typeof mLine === 'object') {
28509
+                if (typeof unifiedLine === 'object') {
28401 28510
                     // the m-line already exists. Just add the source.
28402
-                    mLine.sources[ssrc] = sources[ssrc];
28511
+                    unifiedLine.sources[ssrc] = sources[ssrc];
28403 28512
                     delete sources[ssrc].msid;
28404 28513
                 } else {
28405
-                    // Use the "channel" as a prototype for the "mLine".
28406
-                    mLine = Object.create(channel);
28407
-                    ssrc2ml[ssrc] = mLine;
28514
+                    // Use the "bLine" as a prototype for the "unifiedLine".
28515
+                    unifiedLine = Object.create(bLine);
28516
+                    ssrc2ml[ssrc] = unifiedLine;
28408 28517
 
28409 28518
                     if (typeof sources[ssrc].msid !== 'undefined') {
28410 28519
                         // Assign the msid of the source to the m-line. Note
@@ -28412,14 +28521,14 @@ Interop.prototype.toUnifiedPlan = function(desc) {
28412 28521
                         // msid. In particular "recvonly" sources don't have an
28413 28522
                         // msid. Note that "recvonly" is a term only defined
28414 28523
                         // for m-lines.
28415
-                        mLine.msid = sources[ssrc].msid;
28524
+                        unifiedLine.msid = sources[ssrc].msid;
28416 28525
                         delete sources[ssrc].msid;
28417 28526
                     }
28418 28527
 
28419 28528
                     // We assign one SSRC per media line.
28420
-                    mLine.sources = {};
28421
-                    mLine.sources[ssrc] = sources[ssrc];
28422
-                    mLine.ssrcGroups = ssrc2group[ssrc];
28529
+                    unifiedLine.sources = {};
28530
+                    unifiedLine.sources[ssrc] = sources[ssrc];
28531
+                    unifiedLine.ssrcGroups = ssrc2group[ssrc];
28423 28532
 
28424 28533
                     // Use the cached Unified Plan SDP (if it exists) to assign
28425 28534
                     // SSRCs to mids.
@@ -28431,14 +28540,14 @@ Interop.prototype.toUnifiedPlan = function(desc) {
28431 28540
                             if (typeof m.sources === 'object') {
28432 28541
                                 Object.keys(m.sources).forEach(function (s) {
28433 28542
                                     if (s === ssrc) {
28434
-                                        mLine.mid = m.mid;
28543
+                                        unifiedLine.mid = m.mid;
28435 28544
                                     }
28436 28545
                                 });
28437 28546
                             }
28438 28547
                         });
28439 28548
                     }
28440 28549
 
28441
-                    if (typeof mLine.mid === 'undefined') {
28550
+                    if (typeof unifiedLine.mid === 'undefined') {
28442 28551
 
28443 28552
                         // If this is an SSRC that we see for the first time
28444 28553
                         // assign it a new mid. This is typically the case when
@@ -28451,23 +28560,23 @@ Interop.prototype.toUnifiedPlan = function(desc) {
28451 28560
                         //
28452 28561
                         // Because FF generates answers in Unified Plan style,
28453 28562
                         // we MUST already have a cached answer with all the
28454
-                        // local SSRCs mapped to some mLine/mid.
28563
+                        // local SSRCs mapped to some m-line/mid.
28455 28564
 
28456 28565
                         if (desc.type === 'answer') {
28457 28566
                             throw new Error("An unmapped SSRC was found.");
28458 28567
                         }
28459 28568
 
28460
-                        mLine.mid = [channel.type, '-', ssrc].join('');
28569
+                        unifiedLine.mid = [bLine.type, '-', ssrc].join('');
28461 28570
                     }
28462 28571
 
28463 28572
                     // Include the candidates in the 1st media line.
28464
-                    mLine.candidates = candidates;
28465
-                    mLine.iceUfrag = iceUfrag;
28466
-                    mLine.icePwd = icePwd;
28467
-                    mLine.fingerprint = fingerprint;
28468
-                    mLine.port = port;
28573
+                    unifiedLine.candidates = candidates;
28574
+                    unifiedLine.iceUfrag = iceUfrag;
28575
+                    unifiedLine.icePwd = icePwd;
28576
+                    unifiedLine.fingerprint = fingerprint;
28577
+                    unifiedLine.port = port;
28469 28578
 
28470
-                    mid2ml[mLine.mid] = mLine;
28579
+                    mid2ul[unifiedLine.mid] = unifiedLine;
28471 28580
                 }
28472 28581
             });
28473 28582
         }
@@ -28481,71 +28590,57 @@ Interop.prototype.toUnifiedPlan = function(desc) {
28481 28590
     if (desc.type === 'answer') {
28482 28591
 
28483 28592
         // The media lines in the answer must match the media lines in the
28484
-        // offer. The order is important too. Here we use the cached offer to
28485
-        // find the m-lines that are missing (from the converted answer), and
28486
-        // use the cached answer to complete the converted answer.
28487
-
28488
-        if (typeof this.cache['offer'] === 'undefined') {
28489
-            throw new Error("An answer is being processed but we couldn't " +
28490
-                    "find a cached offer.");
28491
-        }
28492
-
28493
-        var cachedOffer = transform.parse(this.cache['offer']);
28494
-
28495
-        if (typeof cachedOffer === 'undefined' ||
28496
-            typeof cachedOffer.media === 'undefined' ||
28497
-            !Array.isArray(cachedOffer.media)) {
28498
-                // FIXME(gp) is this really a problem in the general case?
28499
-                throw new Error("The cached offer has no media.");
28500
-        }
28501
-
28502
-        cachedOffer.media.forEach(function(mo) {
28503
-
28504
-            var mLine;
28505
-            cached.media.some(function(ma) {
28506
-                if (mo.mid == ma.mid) {
28507
-                    if (typeof mid2ml[mo.mid] === 'undefined') {
28508
-
28509
-                        // This is either an m-line containing a remote
28510
-                        // track only, or an m-line containing a remote
28511
-                        // track and a local track that has been removed.
28512
-                        // In either case, it MUST exist in the cached
28513
-                        // answer.
28514
-                        //
28515
-                        // In case this is a removed local track, clean-up
28516
-                        // the m-line and make sure it's 'recvonly'.
28517
-
28518
-                        // TODO sendonly -> inactive makes more sense.
28519
-                        delete ma.msid;
28520
-                        delete ma.sources;
28521
-                        delete ma.ssrcGroups;
28522
-                        if (!ma.direction
28523
-                            || ma.direction === 'sendonly'
28524
-                            || ma.direction === 'sendrecv')
28525
-                            ma.direction = 'recvonly';
28526
-                    } else {
28527
-                        // This is an m-line/channel that contains a local
28528
-                        // track (sendrecv or sendonly channel) or it's a
28529
-                        // recvonly m-line/channel. In either case, since we're
28530
-                        // going from PlanB -> Unified Plan this m-line MUST
28531
-                        // exist in the cached answer.
28532
-                    }
28593
+        // offer. The order is important too. Here we assume that Firefox is the
28594
+        // answerer, so we merely have to use the reconstructed (unified) answer
28595
+        // to update the cached (unified) answer accordingly.
28596
+        //
28597
+        // In the general case, one would have to use the cached (unified) offer
28598
+        // to find the m-lines that are missing from the reconstructed answer,
28599
+        // potentially grabbing them from the cached (unified) answer. One has
28600
+        // to be carefull with this approach because inactive m-lines do not
28601
+        // always have an mid, making it tricky (impossible?) to find where
28602
+        // exactly and which m-lines are missing from the reconstructed answer.
28603
+
28604
+        for (var i = 0; i < cached.media.length; i++) {
28605
+            var unifiedLine = cached.media[i];
28606
+
28607
+            if (typeof mid2ul[unifiedLine.mid] === 'undefined') {
28608
+
28609
+                // The mid isn't in the reconstructed (unified) answer.
28610
+                // This is either a (unified) m-line containing a remote
28611
+                // track only, or a (unified) m-line containing a remote
28612
+                // track and a local track that has been removed.
28613
+                // In either case, it MUST exist in the cached
28614
+                // (unified) answer.
28615
+                //
28616
+                // In case this is a removed local track, clean-up
28617
+                // the (unified) m-line and make sure it's 'recvonly' or
28618
+                // 'inactive'.
28619
+
28620
+                delete unifiedLine.msid;
28621
+                delete unifiedLine.sources;
28622
+                delete unifiedLine.ssrcGroups;
28623
+                if (!unifiedLine.direction
28624
+                    || unifiedLine.direction === 'sendrecv')
28625
+                    unifiedLine.direction = 'recvonly';
28626
+                if (!unifiedLine.direction
28627
+                    || unifiedLine.direction === 'sendonly')
28628
+                    unifiedLine.direction = 'inactive';
28629
+            } else {
28630
+                // This is an (unified) m-line/channel that contains a local
28631
+                // track (sendrecv or sendonly channel) or it's a unified
28632
+                // recvonly m-line/channel. In either case, since we're
28633
+                // going from PlanB -> Unified Plan this m-line MUST
28634
+                // exist in the cached answer.
28635
+            }
28533 28636
 
28534
-                    // assign the found object.
28535
-                    mLine = ma;
28536
-                    return true;
28537
-                }
28538
-            });
28637
+            session.media.push(unifiedLine);
28539 28638
 
28540
-            if (typeof mLine === 'undefined') {
28541
-                throw new Error("The cached offer contains an m-line that " +
28542
-                        "doesn't exist neither in the cached answer nor in " +
28543
-                        "the converted answer.");
28639
+            if (typeof unifiedLine.mid === 'string') {
28640
+                // inactive lines don't/may not have an mid.
28641
+                mids.push(unifiedLine.mid);
28544 28642
             }
28545
-
28546
-            session.media.push(mLine);
28547
-            mids.push(mLine.mid);
28548
-        });
28643
+        }
28549 28644
     } else {
28550 28645
 
28551 28646
         // SDP offer/answer (and the JSEP spec) forbids removing an m-section
@@ -28559,41 +28654,48 @@ Interop.prototype.toUnifiedPlan = function(desc) {
28559 28654
         if (typeof cached !== 'undefined' &&
28560 28655
             typeof cached.media !== 'undefined' &&
28561 28656
             Array.isArray(cached.media)) {
28562
-            cached.media.forEach(function(pm) {
28563
-                mids.push(pm.mid);
28564
-                if (typeof mid2ml[pm.mid] !== 'undefined') {
28565
-                    session.media.push(mid2ml[pm.mid]);
28657
+            cached.media.forEach(function(unifiedLine) {
28658
+                mids.push(unifiedLine.mid);
28659
+                if (typeof mid2ul[unifiedLine.mid] !== 'undefined') {
28660
+                    session.media.push(mid2ul[unifiedLine.mid]);
28566 28661
                 } else {
28567
-                    delete pm.msid;
28568
-                    delete pm.sources;
28569
-                    delete pm.ssrcGroups;
28570
-                    pm.direction = 'recvonly';
28571
-                    session.media.push(pm);
28662
+                    delete unifiedLine.msid;
28663
+                    delete unifiedLine.sources;
28664
+                    delete unifiedLine.ssrcGroups;
28665
+                    if (!unifiedLine.direction
28666
+                        || unifiedLine.direction === 'sendrecv')
28667
+                        unifiedLine.direction = 'recvonly';
28668
+                    if (!unifiedLine.direction
28669
+                        || unifiedLine.direction === 'sendonly')
28670
+                        unifiedLine.direction = 'inactive';
28671
+                    session.media.push(unifiedLine);
28572 28672
                 }
28573 28673
             });
28574 28674
         }
28575 28675
 
28576 28676
         // Add all the remaining (new) m-lines of the transformed SDP.
28577
-        Object.keys(mid2ml).forEach(function(mid) {
28677
+        Object.keys(mid2ul).forEach(function(mid) {
28578 28678
             if (mids.indexOf(mid) === -1) {
28579 28679
                 mids.push(mid);
28580
-                if (typeof mid2ml[mid].msid === 'undefined') {
28680
+                if (typeof mid2ul[mid].direction === 'recvonly') {
28581 28681
                     // This is a remote recvonly channel. Add its SSRC to the
28582
-                    // sendrecv channel.
28583
-                    // TODO(gp) what if there is no sendrecv channel?
28584
-                    session.media.some(function (ml) {
28585
-                        if (ml.direction === 'sendrecv' && ml.type == mid2ml[mid].type) {
28586
-
28587
-                            // this shouldn't have any ssrc-groups
28588
-                            Object.keys(mid2ml[mid].sources).forEach(function (ssrc) {
28589
-                                ml.sources[ssrc] = mid2ml[mid].sources[ssrc];
28682
+                    // appropriate sendrecv or sendonly channel.
28683
+                    // TODO(gp) what if we don't have sendrecv/sendonly channel?
28684
+                    session.media.some(function (unifiedLine) {
28685
+                        if ((unifiedLine.direction === 'sendrecv' ||
28686
+                            unifiedLine.direction === 'sendonly') &&
28687
+                            unifiedLine.type === mid2ul[mid].type) {
28688
+
28689
+                            // mid2ul[mid] shouldn't have any ssrc-groups
28690
+                            Object.keys(mid2ul[mid].sources).forEach(function (ssrc) {
28691
+                                unifiedLine.sources[ssrc] = mid2ul[mid].sources[ssrc];
28590 28692
                             });
28591 28693
 
28592 28694
                             return true;
28593 28695
                         }
28594 28696
                     });
28595 28697
                 } else {
28596
-                    session.media.push(mid2ml[mid]);
28698
+                    session.media.push(mid2ul[mid]);
28597 28699
                 }
28598 28700
             }
28599 28701
         });
@@ -29388,7 +29490,8 @@ var XMPPEvents = {
29388 29490
     AUTHENTICATION_REQUIRED: "xmpp.authentication_required",
29389 29491
     CHAT_ERROR_RECEIVED: "xmpp.chat_error_received",
29390 29492
     ETHERPAD: "xmpp.etherpad",
29391
-    DEVICE_AVAILABLE: "xmpp.device_available"
29493
+    DEVICE_AVAILABLE: "xmpp.device_available",
29494
+    START_MUTED: "xmpp.start_muted"
29392 29495
 };
29393 29496
 module.exports = XMPPEvents;
29394 29497
 },{}],106:[function(require,module,exports){

Laden…
Abbrechen
Speichern