소스 검색

Update libs/app.bundle.js.

j8
George Politis 10 년 전
부모
커밋
777422c87d
2개의 변경된 파일302개의 추가작업 그리고 199개의 파일을 삭제
  1. 1
    1
      index.html
  2. 301
    198
      libs/app.bundle.js

+ 1
- 1
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=67"></script>
22
+    <script src="libs/app.bundle.js?v=68"></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=7"/>
24
     <link rel="stylesheet" href="css/font.css?v=7"/>
25
     <link rel="stylesheet" href="css/toastr.css?v=1">
25
     <link rel="stylesheet" href="css/toastr.css?v=1">

+ 301
- 198
libs/app.bundle.js 파일 보기

705
 function getMediaStreamUsage()
705
 function getMediaStreamUsage()
706
 {
706
 {
707
     var result = {
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
     /** There are some issues with the desktop sharing
712
     /** There are some issues with the desktop sharing
717
      * when this property is enabled.
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
      var isSecureConnection = window.location.protocol == "https:";
717
      var isSecureConnection = window.location.protocol == "https:";
722
 
718
 
723
     if(config.disableEarlyMediaPermissionRequests || !isSecureConnection)
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
     return result;
729
     return result;
732
 }
730
 }
1276
  * We ask for audio and video combined stream in order to get permissions and
1274
  * We ask for audio and video combined stream in order to get permissions and
1277
  * not to ask twice.
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
     var self = this;
1280
     var self = this;
1281
     // Get AV
1281
     // Get AV
1282
 
1282
 
1297
         for(var i = 0; i < devices.length; i++)
1297
         for(var i = 0; i < devices.length; i++)
1298
         {
1298
         {
1299
             var device = devices[i];
1299
             var device = devices[i];
1300
-            if(usageOptions[device] !== -1)
1300
+            if(usageOptions[device] === true)
1301
                 newDevices.push(device);
1301
                 newDevices.push(device);
1302
         }
1302
         }
1303
     else
1303
     else
1431
         videoStream = stream.videoStream;
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
     this.service.createLocalStream(audioStream, "audio", null, null,
1441
     this.service.createLocalStream(audioStream, "audio", null, null,
1441
         audioMuted, audioGUM);
1442
         audioMuted, audioGUM);
1505
 
1506
 
1506
 function notifyForInitialMute()
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
 function setupPrezi()
1513
 function setupPrezi()
1725
 
1724
 
1726
     APP.members.addListener(MemberEvents.DTMF_SUPPORT_CHANGED,
1725
     APP.members.addListener(MemberEvents.DTMF_SUPPORT_CHANGED,
1727
                             onDtmfSupportChanged);
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
 
1881
 
1880
     SettingsMenu.init();
1882
     SettingsMenu.init();
1881
 
1883
 
1882
-    notifyForInitialMute();
1883
-
1884
 };
1884
 };
1885
 
1885
 
1886
 function chatAddError(errorMessage, originalText)
1886
 function chatAddError(errorMessage, originalText)
1956
     console.info("My role changed, new role: " + info.role);
1956
     console.info("My role changed, new role: " + info.role);
1957
     onModeratorStatusChanged(isModerator);
1957
     onModeratorStatusChanged(isModerator);
1958
     VideoLayout.showModeratorIndicator();
1958
     VideoLayout.showModeratorIndicator();
1959
+    SettingsMenu.onRoleChanged();
1959
 
1960
 
1960
     if (isModerator) {
1961
     if (isModerator) {
1961
         Authentication.closeAuthenticationWindow();
1962
         Authentication.closeAuthenticationWindow();
2200
     return roomName;
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
  * Mutes/unmutes the local video.
2211
  * Mutes/unmutes the local video.
2205
  */
2212
  */
5090
 var SettingsMenu = {
5097
 var SettingsMenu = {
5091
 
5098
 
5092
     init: function () {
5099
     init: function () {
5093
-        $("#updateSettings").before(generateLanguagesSelectBox());
5100
+        $("#startMutedOptions").before(generateLanguagesSelectBox());
5094
         APP.translation.translateElement($("#languages_selectbox"));
5101
         APP.translation.translateElement($("#languages_selectbox"));
5095
         $('#settingsmenu>input').keyup(function(event){
5102
         $('#settingsmenu>input').keyup(function(event){
5096
             if(event.keyCode === 13) {//enter
5103
             if(event.keyCode === 13) {//enter
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
         $("#updateSettings").click(function () {
5117
         $("#updateSettings").click(function () {
5102
             SettingsMenu.update();
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
     update: function() {
5138
     update: function() {
5107
         var newDisplayName = UIUtil.escapeHtml($('#setDisplayName').get(0).value);
5139
         var newDisplayName = UIUtil.escapeHtml($('#setDisplayName').get(0).value);
5108
         var newEmail = UIUtil.escapeHtml($('#setEmail').get(0).value);
5140
         var newEmail = UIUtil.escapeHtml($('#setEmail').get(0).value);
5119
         APP.xmpp.addToPresence("email", newEmail);
5151
         APP.xmpp.addToPresence("email", newEmail);
5120
         var email = Settings.setEmail(newEmail);
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
         Avatar.setUserAvatar(APP.xmpp.myJid(), email);
5159
         Avatar.setUserAvatar(APP.xmpp.myJid(), email);
5124
     },
5160
     },
15638
                 { name: 'openSctp', value: config.openSctp})
15674
                 { name: 'openSctp', value: config.openSctp})
15639
                 .up();
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
         elem.up();
15691
         elem.up();
15642
         return elem;
15692
         return elem;
15643
     },
15693
     },
16187
                 $(document).trigger('videomuted.muc', [from, videoMuted.text()]);
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
             var devices = $(pres).find('>devices');
16247
             var devices = $(pres).find('>devices');
16191
             if(devices.length)
16248
             if(devices.length)
16192
             {
16249
             {
16541
                                     || 'sendrecv' }
16598
                                     || 'sendrecv' }
16542
                         ).up();
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
             pres.up();
16612
             pres.up();
16621
         addUserIdToPresence: function (userId) {
16687
         addUserIdToPresence: function (userId) {
16622
             this.presMap['userId'] = userId;
16688
             this.presMap['userId'] = userId;
16623
         },
16689
         },
16690
+        addStartMutedToPresence: function (audio, video) {
16691
+            this.presMap["startMuted"] = {audio: audio, video: video};
16692
+        },
16624
         isModerator: function () {
16693
         isModerator: function () {
16625
             return this.role === 'moderator';
16694
             return this.role === 'moderator';
16626
         },
16695
         },
16808
             // see http://xmpp.org/extensions/xep-0166.html#concepts-session
16877
             // see http://xmpp.org/extensions/xep-0166.html#concepts-session
16809
             switch (action) {
16878
             switch (action) {
16810
                 case 'session-initiate':
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
                     sess = new JingleSession(
16888
                     sess = new JingleSession(
16812
                         $(iq).attr('to'), $(iq).find('jingle').attr('sid'),
16889
                         $(iq).attr('to'), $(iq).find('jingle').attr('sid'),
16813
                         this.connection, XMPP);
16890
                         this.connection, XMPP);
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
         if (connection && connection.connected) {
17537
         if (connection && connection.connected) {
17456
             // ensure signout
17538
             // ensure signout
17457
             $.ajax({
17539
             $.ajax({
17460
                 async: false,
17542
                 async: false,
17461
                 cache: false,
17543
                 cache: false,
17462
                 contentType: 'application/xml',
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
                 success: function (data) {
17551
                 success: function (data) {
17470
                     console.log('signed out');
17552
                     console.log('signed out');
17471
                     console.log(data);
17553
                     console.log(data);
17472
                 },
17554
                 },
17473
                 error: function (XMLHttpRequest, textStatus, errorThrown) {
17555
                 error: function (XMLHttpRequest, textStatus, errorThrown) {
17474
                     console.log('signout error',
17556
                     console.log('signout error',
17475
-                            textStatus + ' (' + errorThrown + ')');
17557
+                        textStatus + ' (' + errorThrown + ')');
17476
                 }
17558
                 }
17477
             });
17559
             });
17478
         }
17560
         }
17479
         XMPP.disposeConference(true);
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
 var XMPP = {
17582
 var XMPP = {
17741
             case "devices":
17840
             case "devices":
17742
                 connection.emuc.addDevicesToPresence(value);
17841
                 connection.emuc.addDevicesToPresence(value);
17743
                 break;
17842
                 break;
17843
+            case "startMuted":
17844
+                if(!Moderator.isModerator())
17845
+                    return;
17846
+                connection.emuc.addStartMutedToPresence(value[0],
17847
+                    value[1]);
17848
+                break;
17744
             default :
17849
             default :
17745
                 console.log("Unknown tag for presence: " + name);
17850
                 console.log("Unknown tag for presence: " + name);
17746
                 return;
17851
                 return;
28054
 exports.Interop = require('./interop');
28159
 exports.Interop = require('./interop');
28055
 
28160
 
28056
 },{"./interop":88}],88:[function(require,module,exports){
28161
 },{"./interop":88}],88:[function(require,module,exports){
28162
+"use strict";
28163
+
28057
 var transform = require('./transform');
28164
 var transform = require('./transform');
28058
 var arrayEquals = require('./array-equals');
28165
 var arrayEquals = require('./array-equals');
28059
 
28166
 
28122
     session.media = [];
28229
     session.media = [];
28123
 
28230
 
28124
     // Associative array that maps channel types to channel objects for fast
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
     // obj.
28233
     // obj.
28127
-    var channels = {};
28234
+    var type2bl = {};
28128
 
28235
 
28129
     // Used to build the group:BUNDLE value after the channels construction
28236
     // Used to build the group:BUNDLE value after the channels construction
28130
     // loop.
28237
     // loop.
28131
     var types = [];
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
         // rtcp-mux is required in the Plan B SDP.
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
             throw new Error('Cannot convert to Plan B because m-lines ' +
28247
             throw new Error('Cannot convert to Plan B because m-lines ' +
28140
                 'without the rtcp-mux attribute were found.');
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
         // as the channel basis.
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
         // Add sources to the channel and handle a=msid.
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
                 // Assign the sources to the channel.
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
                     // In Plan B the msid is an SSRC attribute. Also, we don't
28267
                     // In Plan B the msid is an SSRC attribute. Also, we don't
28160
                     // care about the obsolete label and mslabel attributes.
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
                     // an msid. recvonly channels in particular don't have one.
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
                 // NOTE ssrcs in ssrc groups will share msids, as
28274
                 // NOTE ssrcs in ssrc groups will share msids, as
28167
                 // draft-uberti-rtcweb-plan-00 mandates.
28275
                 // draft-uberti-rtcweb-plan-00 mandates.
28169
         }
28277
         }
28170
 
28278
 
28171
         // Add ssrc groups to the channel.
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
             // Create the ssrcGroups array, if it's not defined.
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
             // Copy ICE related stuff from the principal media line.
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
             // Plan B mids are in ['audio', 'video', 'data']
28299
             // Plan B mids are in ['audio', 'video', 'data']
28192
-            mLine.mid = mLine.type;
28300
+            unifiedLine.mid = unifiedLine.type;
28193
 
28301
 
28194
             // Plan B doesn't support/need the bundle-only attribute.
28302
             // Plan B doesn't support/need the bundle-only attribute.
28195
-            delete mLine.bundleOnly;
28303
+            delete unifiedLine.bundleOnly;
28196
 
28304
 
28197
             // In Plan B the msid is an SSRC attribute.
28305
             // In Plan B the msid is an SSRC attribute.
28198
-            delete mLine.msid;
28306
+            delete unifiedLine.msid;
28199
 
28307
 
28200
             // Used to build the group:BUNDLE value after this loop.
28308
             // Used to build the group:BUNDLE value after this loop.
28201
-            types.push(mLine.type);
28309
+            types.push(unifiedLine.type);
28202
 
28310
 
28203
             // Add the channel to the new media array.
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
 
28425
 
28318
     // A helper map that sends mids to m-line objects. We use it later to
28426
     // A helper map that sends mids to m-line objects. We use it later to
28319
     // rebuild the Unified Plan style session.media array.
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
             throw new Error("Cannot convert to Unified Plan because m-lines " +
28433
             throw new Error("Cannot convert to Unified Plan because m-lines " +
28325
                 "without the rtcp-mux attribute were found.");
28434
                 "without the rtcp-mux attribute were found.");
28326
         }
28435
         }
28327
 
28436
 
28328
         // With rtcp-mux and bundle all the channels should have the same ICE
28437
         // With rtcp-mux and bundle all the channels should have the same ICE
28329
         // stuff.
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
         // that we create, but first we need to clean it up a bit.
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
         // inverted ssrc group map
28458
         // inverted ssrc group map
28350
         var ssrc2group = {};
28459
         var ssrc2group = {};
28378
             // Explode the Plan B channel sources with one m-line per source.
28487
             // Explode the Plan B channel sources with one m-line per source.
28379
             Object.keys(sources).forEach(function(ssrc) {
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
                 if (typeof ssrc2group[ssrc] !== 'undefined' &&
28495
                 if (typeof ssrc2group[ssrc] !== 'undefined' &&
28387
                     Array.isArray(ssrc2group[ssrc])) {
28496
                     Array.isArray(ssrc2group[ssrc])) {
28388
                     ssrc2group[ssrc].some(function (ssrcGroup) {
28497
                     ssrc2group[ssrc].some(function (ssrcGroup) {
28390
                         // again here.
28499
                         // again here.
28391
                         return ssrcGroup.ssrcs.some(function (related) {
28500
                         return ssrcGroup.ssrcs.some(function (related) {
28392
                             if (typeof ssrc2ml[related] === 'object') {
28501
                             if (typeof ssrc2ml[related] === 'object') {
28393
-                                mLine = ssrc2ml[related];
28502
+                                unifiedLine = ssrc2ml[related];
28394
                                 return true;
28503
                                 return true;
28395
                             }
28504
                             }
28396
                         });
28505
                         });
28397
                     });
28506
                     });
28398
                 }
28507
                 }
28399
 
28508
 
28400
-                if (typeof mLine === 'object') {
28509
+                if (typeof unifiedLine === 'object') {
28401
                     // the m-line already exists. Just add the source.
28510
                     // the m-line already exists. Just add the source.
28402
-                    mLine.sources[ssrc] = sources[ssrc];
28511
+                    unifiedLine.sources[ssrc] = sources[ssrc];
28403
                     delete sources[ssrc].msid;
28512
                     delete sources[ssrc].msid;
28404
                 } else {
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
                     if (typeof sources[ssrc].msid !== 'undefined') {
28518
                     if (typeof sources[ssrc].msid !== 'undefined') {
28410
                         // Assign the msid of the source to the m-line. Note
28519
                         // Assign the msid of the source to the m-line. Note
28412
                         // msid. In particular "recvonly" sources don't have an
28521
                         // msid. In particular "recvonly" sources don't have an
28413
                         // msid. Note that "recvonly" is a term only defined
28522
                         // msid. Note that "recvonly" is a term only defined
28414
                         // for m-lines.
28523
                         // for m-lines.
28415
-                        mLine.msid = sources[ssrc].msid;
28524
+                        unifiedLine.msid = sources[ssrc].msid;
28416
                         delete sources[ssrc].msid;
28525
                         delete sources[ssrc].msid;
28417
                     }
28526
                     }
28418
 
28527
 
28419
                     // We assign one SSRC per media line.
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
                     // Use the cached Unified Plan SDP (if it exists) to assign
28533
                     // Use the cached Unified Plan SDP (if it exists) to assign
28425
                     // SSRCs to mids.
28534
                     // SSRCs to mids.
28431
                             if (typeof m.sources === 'object') {
28540
                             if (typeof m.sources === 'object') {
28432
                                 Object.keys(m.sources).forEach(function (s) {
28541
                                 Object.keys(m.sources).forEach(function (s) {
28433
                                     if (s === ssrc) {
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
                         // If this is an SSRC that we see for the first time
28552
                         // If this is an SSRC that we see for the first time
28444
                         // assign it a new mid. This is typically the case when
28553
                         // assign it a new mid. This is typically the case when
28451
                         //
28560
                         //
28452
                         // Because FF generates answers in Unified Plan style,
28561
                         // Because FF generates answers in Unified Plan style,
28453
                         // we MUST already have a cached answer with all the
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
                         if (desc.type === 'answer') {
28565
                         if (desc.type === 'answer') {
28457
                             throw new Error("An unmapped SSRC was found.");
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
                     // Include the candidates in the 1st media line.
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
     if (desc.type === 'answer') {
28590
     if (desc.type === 'answer') {
28482
 
28591
 
28483
         // The media lines in the answer must match the media lines in the
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
     } else {
28644
     } else {
28550
 
28645
 
28551
         // SDP offer/answer (and the JSEP spec) forbids removing an m-section
28646
         // SDP offer/answer (and the JSEP spec) forbids removing an m-section
28559
         if (typeof cached !== 'undefined' &&
28654
         if (typeof cached !== 'undefined' &&
28560
             typeof cached.media !== 'undefined' &&
28655
             typeof cached.media !== 'undefined' &&
28561
             Array.isArray(cached.media)) {
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
                 } else {
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
         // Add all the remaining (new) m-lines of the transformed SDP.
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
             if (mids.indexOf(mid) === -1) {
28678
             if (mids.indexOf(mid) === -1) {
28579
                 mids.push(mid);
28679
                 mids.push(mid);
28580
-                if (typeof mid2ml[mid].msid === 'undefined') {
28680
+                if (typeof mid2ul[mid].direction === 'recvonly') {
28581
                     // This is a remote recvonly channel. Add its SSRC to the
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
                             return true;
28694
                             return true;
28593
                         }
28695
                         }
28594
                     });
28696
                     });
28595
                 } else {
28697
                 } else {
28596
-                    session.media.push(mid2ml[mid]);
28698
+                    session.media.push(mid2ul[mid]);
28597
                 }
28699
                 }
28598
             }
28700
             }
28599
         });
28701
         });
29388
     AUTHENTICATION_REQUIRED: "xmpp.authentication_required",
29490
     AUTHENTICATION_REQUIRED: "xmpp.authentication_required",
29389
     CHAT_ERROR_RECEIVED: "xmpp.chat_error_received",
29491
     CHAT_ERROR_RECEIVED: "xmpp.chat_error_received",
29390
     ETHERPAD: "xmpp.etherpad",
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
 module.exports = XMPPEvents;
29496
 module.exports = XMPPEvents;
29394
 },{}],106:[function(require,module,exports){
29497
 },{}],106:[function(require,module,exports){

Loading…
취소
저장