zdpjs_webrtc
Version:
基于easyrtc二次开发的webrtc框架
5,743 lines • 829 kB
HTML
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>EasyRTC Documentation</title>
<script src="scripts/prettify/prettify.js"> </script>
<script src="scripts/prettify/lang-css.js"> </script>
<!--[if lt IE 9]>
<script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script>
<![endif]-->
<link type="text/css" rel="stylesheet" href="styles/prettify-tomorrow.css">
<link type="text/css" rel="stylesheet" href="styles/jsdoc-default.css">
<link href="../assets/easyrtc-docs-jsdoc-styles-1.css" media="all" rel="stylesheet" />
</head>
<body>
<header class="template">
<div class="wrapper-content">
<a href="../index.html"><img src="../assets/easyrtc-logo.png" alt="EasyRTC Documentation"></a>
<h1 title="EasyRTC Documentation">Documentation</h1>
</div>
</header>
<div class="wrapper-docs">
<nav>
<h2><a href="../index.html">Docs Home</a></h2>
<h3>EasyRTC Guides</h3>
<ul>
<li><a href="../easyrtc_faq.html">FAQ</a></li>
<li><a href="../easyrtc_gettingStarted.html">Getting Started</a></li>
<li><a href="../easyrtc_server_install.html">EasyRTC Server: Installation</a></li>
<li><a href="../easyrtc_client_tutorial.html">EasyRTC Framework Tutorial</a></li>
<li><a href="../easyrtc_rooms.html">Rooms</a></li>
<li><a href="../easyrtc_server_configuration.html">EasyRTC Server: Configuration</a></li>
<li><a href="../easyrtc_server_events.html">EasyRTC Server: Events</a></li>
<li><a href="../easyrtc_server_ice.html">EasyRTC Server: ICE Configuration</a></li>
<li><a href="../easyrtc_with_other_servers.html">Using Alongside Other Servers</a></li>
<li><a href="../easyrtc_server_ssl.html">EasyRTC Server: Using SSL</a></li>
<li><a href="../easyrtc_webrtc_problems.html">WebRTC Problems and Possible Fixes</a></li>
<li><a href="../easyrtc_upcoming_features.html">Upcoming Features</a></li>
<li><a href="../easyrtc_changelog.html">Change Log</a></li>
</ul>
<h3>EasyRTC Client Classes</h3>
<ul>
<li><a href="../client-api/Easyrtc.html">Easyrtc</a></li>
<li><a href="../client-api/Easyrtc_App.html">Easyrtc_App</a></li>
<li><a href="../client-api/Easyrtc_ft.html">Easyrtc_ft</a></li>
<li><a href="../client-api/Easyrtc_IframeCapture.html">Easyrtc_IframeCapture</a></li>
<li><a href="../client-api/Easyrtc_No_IframeCapture.html">Easyrtc_No_IframeCapture</a></li>
<li><a href="../client-api/Easyrtc_Rates.html">Easyrtc_Rates</a></li>
<li><a href="../client-api/Easyrtc_Recorder.html">Easyrtc_Recorder</a></li>
</ul>
<h3>EasyRTC Server Modules</h3>
<ul>
<li><a href="../server-api/module-easyrtc_default_event_listeners.html">easyrtc_default_event_listeners</a></li>
<li><a href="../server-api/module-easyrtc_default_options.html">easyrtc_default_options</a></li>
<li><a href="../server-api/module-easyrtc_private_obj.html">easyrtc_private_obj</a></li>
<li><a href="../server-api/module-easyrtc_public_obj.html">easyrtc_public_obj</a></li>
<li><a href="../server-api/module-easyrtc_util.html">easyrtc_util</a></li>
<li><a href="../server-api/module-general_util.html">general_util</a></li>
</ul>
<h3>EasyRTC Server Classes</h3>
<ul>
<li><a href="../server-api/module-easyrtc_default_event_listeners-eventListener.html">eventListener</a></li>
<li><a href="../server-api/module-easyrtc_public_obj-pub.html">pub</a></li>
<li><a href="../server-api/module-easyrtc_public_obj-pub.events.html">events</a></li>
<li><a href="../server-api/module-easyrtc_public_obj-pub.util.html">util</a></li>
<li><a href="../server-api/module-easyrtc_util-eu.html">eu</a></li>
<li><a href="../server-api/module-general_util-g.html">g</a></li>
<li><a href="../server-api/pub.appObj.html">appObj</a></li>
<li><a href="../server-api/pub.appObj.connectionObj.html">connectionObj</a></li>
<li><a href="../server-api/pub.appObj.connectionObj.connectionRoomObj.html">connectionRoomObj</a></li>
<li><a href="../server-api/pub.appObj.roomObj.html">roomObj</a></li>
<li><a href="../server-api/pub.appObj.sessionObj.html">sessionObj</a></li>
</ul>
</nav>
<div class="easyrtc-docs-content">
<div id="main">
<h1 class="page-title">Source: easyrtc_int.js</h1>
<section>
<article>
<pre class="prettyprint source linenums easyrtc"><code><a name="line1"></a><div class="linenumber">1</div><div style="width:0em;display:inline-block"></div>/* global define, module, require, console, MediaStreamTrack, createIceServer, RTCIceCandidate, RTCPeerConnection, RTCSessionDescription */
<a name="line2"></a><div class="linenumber">2</div><div style="width:0em;display:inline-block"></div>/*!
<a name="line3"></a><div class="linenumber">3</div><div style="width:1em;display:inline-block"></div>Script: easyrtc.js
<a name="line4"></a><div class="linenumber">4</div>
<a name="line5"></a><div class="linenumber">5</div><div style="width:2em;display:inline-block"></div>Provides client side support for the EasyRTC framework.
<a name="line6"></a><div class="linenumber">6</div><div style="width:2em;display:inline-block"></div>See the easyrtc_client_api.md and easyrtc_client_tutorial.md
<a name="line7"></a><div class="linenumber">7</div><div style="width:2em;display:inline-block"></div>for more details.
<a name="line8"></a><div class="linenumber">8</div>
<a name="line9"></a><div class="linenumber">9</div><div style="width:1em;display:inline-block"></div>About: License
<a name="line10"></a><div class="linenumber">10</div>
<a name="line11"></a><div class="linenumber">11</div><div style="width:2em;display:inline-block"></div>Copyright (c) 2016, Priologic Software Inc.
<a name="line12"></a><div class="linenumber">12</div><div style="width:2em;display:inline-block"></div>All rights reserved.
<a name="line13"></a><div class="linenumber">13</div>
<a name="line14"></a><div class="linenumber">14</div><div style="width:2em;display:inline-block"></div>Redistribution and use in source and binary forms, with or without
<a name="line15"></a><div class="linenumber">15</div><div style="width:2em;display:inline-block"></div>modification, are permitted provided that the following conditions are met:
<a name="line16"></a><div class="linenumber">16</div>
<a name="line17"></a><div class="linenumber">17</div><div style="width:4em;display:inline-block"></div>* Redistributions of source code must retain the above copyright notice,
<a name="line18"></a><div class="linenumber">18</div><div style="width:5em;display:inline-block"></div>this list of conditions and the following disclaimer.
<a name="line19"></a><div class="linenumber">19</div><div style="width:4em;display:inline-block"></div>* Redistributions in binary form must reproduce the above copyright
<a name="line20"></a><div class="linenumber">20</div><div style="width:5em;display:inline-block"></div>notice, this list of conditions and the following disclaimer in the
<a name="line21"></a><div class="linenumber">21</div><div style="width:5em;display:inline-block"></div>documentation and/or other materials provided with the distribution.
<a name="line22"></a><div class="linenumber">22</div>
<a name="line23"></a><div class="linenumber">23</div><div style="width:2em;display:inline-block"></div>THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
<a name="line24"></a><div class="linenumber">24</div><div style="width:2em;display:inline-block"></div>AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
<a name="line25"></a><div class="linenumber">25</div><div style="width:2em;display:inline-block"></div>IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
<a name="line26"></a><div class="linenumber">26</div><div style="width:2em;display:inline-block"></div>ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
<a name="line27"></a><div class="linenumber">27</div><div style="width:2em;display:inline-block"></div>LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
<a name="line28"></a><div class="linenumber">28</div><div style="width:2em;display:inline-block"></div>CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
<a name="line29"></a><div class="linenumber">29</div><div style="width:2em;display:inline-block"></div>SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
<a name="line30"></a><div class="linenumber">30</div><div style="width:2em;display:inline-block"></div>INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
<a name="line31"></a><div class="linenumber">31</div><div style="width:2em;display:inline-block"></div>CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
<a name="line32"></a><div class="linenumber">32</div><div style="width:2em;display:inline-block"></div>ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
<a name="line33"></a><div class="linenumber">33</div><div style="width:2em;display:inline-block"></div>POSSIBILITY OF SUCH DAMAGE.
<a name="line34"></a><div class="linenumber">34</div><div style="width:0em;display:inline-block"></div>*/
<a name="line35"></a><div class="linenumber">35</div>
<a name="line36"></a><div class="linenumber">36</div><div style="width:0em;display:inline-block"></div>(function (root, factory) {
<a name="line37"></a><div class="linenumber">37</div><div style="width:2em;display:inline-block"></div>if (typeof define === 'function' && define.amd) {
<a name="line38"></a><div class="linenumber">38</div><div style="width:4em;display:inline-block"></div>//RequireJS (AMD) build system
<a name="line39"></a><div class="linenumber">39</div><div style="width:4em;display:inline-block"></div>define(['easyrtc_lang', 'webrtc-adapter', 'socket.io'], factory);
<a name="line40"></a><div class="linenumber">40</div><div style="width:2em;display:inline-block"></div>} else if (typeof module === 'object' && module.exports) {
<a name="line41"></a><div class="linenumber">41</div><div style="width:4em;display:inline-block"></div>//CommonJS build system
<a name="line42"></a><div class="linenumber">42</div><div style="width:4em;display:inline-block"></div>module.exports = factory(require('easyrtc_lang'), require('webrtc-adapter'), require('socket.io'));
<a name="line43"></a><div class="linenumber">43</div><div style="width:2em;display:inline-block"></div>} else {
<a name="line44"></a><div class="linenumber">44</div><div style="width:4em;display:inline-block"></div>//Vanilla JS, ensure dependencies are loaded correctly
<a name="line45"></a><div class="linenumber">45</div><div style="width:4em;display:inline-block"></div>if (typeof window.io === 'undefined' || !window.io) {
<a name="line46"></a><div class="linenumber">46</div><div style="width:6em;display:inline-block"></div>throw new Error("easyrtc requires socket.io");
<a name="line47"></a><div class="linenumber">47</div><div style="width:4em;display:inline-block"></div>}
<a name="line48"></a><div class="linenumber">48</div><div style="width:4em;display:inline-block"></div>root.easyrtc = factory(window.easyrtc_lang, window.adapter, window.io);
<a name="line49"></a><div class="linenumber">49</div><div style="width:1em;display:inline-block"></div>}
<a name="line50"></a><div class="linenumber">50</div><div style="width:0em;display:inline-block"></div>}(this, function (easyrtc_lang, adapter, io, undefined) {
<a name="line51"></a><div class="linenumber">51</div>
<a name="line52"></a><div class="linenumber">52</div><div style="width:0em;display:inline-block"></div>"use strict";
<a name="line53"></a><div class="linenumber">53</div><div style="width:0em;display:inline-block"></div>/**
<a name="line54"></a><div class="linenumber">54</div><div style="width:0em;display:inline-block"></div>* @class Easyrtc.
<a name="line55"></a><div class="linenumber">55</div><div style="width:0em;display:inline-block"></div>*
<a name="line56"></a><div class="linenumber">56</div><div style="width:0em;display:inline-block"></div>* @returns {Easyrtc} the new easyrtc instance.
<a name="line57"></a><div class="linenumber">57</div><div style="width:0em;display:inline-block"></div>*
<a name="line58"></a><div class="linenumber">58</div><div style="width:0em;display:inline-block"></div>* @constructs Easyrtc
<a name="line59"></a><div class="linenumber">59</div><div style="width:0em;display:inline-block"></div>*/
<a name="line60"></a><div class="linenumber">60</div><div style="width:0em;display:inline-block"></div>var Easyrtc = function() {
<a name="line61"></a><div class="linenumber">61</div>
<a name="line62"></a><div class="linenumber">62</div><div style="width:2em;display:inline-block"></div>var self = this;
<a name="line63"></a><div class="linenumber">63</div>
<a name="line64"></a><div class="linenumber">64</div><div style="width:2em;display:inline-block"></div>function logDebug (message, obj) {
<a name="line65"></a><div class="linenumber">65</div><div style="width:4em;display:inline-block"></div>if (self.debugPrinter) {
<a name="line66"></a><div class="linenumber">66</div><div style="width:6em;display:inline-block"></div>self.debugPrinter(message, obj);
<a name="line67"></a><div class="linenumber">67</div><div style="width:4em;display:inline-block"></div>}
<a name="line68"></a><div class="linenumber">68</div><div style="width:2em;display:inline-block"></div>}
<a name="line69"></a><div class="linenumber">69</div>
<a name="line70"></a><div class="linenumber">70</div><div style="width:2em;display:inline-block"></div>function isEmptyObj(obj) {
<a name="line71"></a><div class="linenumber">71</div><div style="width:4em;display:inline-block"></div>if (obj === null || obj === undefined) {
<a name="line72"></a><div class="linenumber">72</div><div style="width:6em;display:inline-block"></div>return true;
<a name="line73"></a><div class="linenumber">73</div><div style="width:4em;display:inline-block"></div>}
<a name="line74"></a><div class="linenumber">74</div><div style="width:4em;display:inline-block"></div>var key;
<a name="line75"></a><div class="linenumber">75</div><div style="width:4em;display:inline-block"></div>for (key in obj) {
<a name="line76"></a><div class="linenumber">76</div><div style="width:6em;display:inline-block"></div>if (obj.hasOwnProperty(key)) {
<a name="line77"></a><div class="linenumber">77</div><div style="width:8em;display:inline-block"></div>return false;
<a name="line78"></a><div class="linenumber">78</div><div style="width:6em;display:inline-block"></div>}
<a name="line79"></a><div class="linenumber">79</div><div style="width:4em;display:inline-block"></div>}
<a name="line80"></a><div class="linenumber">80</div><div style="width:4em;display:inline-block"></div>return true;
<a name="line81"></a><div class="linenumber">81</div><div style="width:2em;display:inline-block"></div>}
<a name="line82"></a><div class="linenumber">82</div>
<a name="line83"></a><div class="linenumber">83</div><div style="width:2em;display:inline-block"></div>/** @private */
<a name="line84"></a><div class="linenumber">84</div><div style="width:2em;display:inline-block"></div>var autoInitUserMedia = true;
<a name="line85"></a><div class="linenumber">85</div><div style="width:2em;display:inline-block"></div>/** @private */
<a name="line86"></a><div class="linenumber">86</div><div style="width:2em;display:inline-block"></div>var sdpLocalFilter = null;
<a name="line87"></a><div class="linenumber">87</div><div style="width:2em;display:inline-block"></div>/** @private */
<a name="line88"></a><div class="linenumber">88</div><div style="width:2em;display:inline-block"></div>var sdpRemoteFilter = null;
<a name="line89"></a><div class="linenumber">89</div><div style="width:2em;display:inline-block"></div>/** @private */
<a name="line90"></a><div class="linenumber">90</div><div style="width:2em;display:inline-block"></div>var iceCandidateFilter = null;
<a name="line91"></a><div class="linenumber">91</div><div style="width:2em;display:inline-block"></div>/** @private */
<a name="line92"></a><div class="linenumber">92</div><div style="width:2em;display:inline-block"></div>var iceConnectionStateChangeListener = null;
<a name="line93"></a><div class="linenumber">93</div><div style="width:2em;display:inline-block"></div>var signalingStateChangeListener = null;
<a name="line94"></a><div class="linenumber">94</div><div style="width:2em;display:inline-block"></div>/** @private */
<a name="line95"></a><div class="linenumber">95</div><div style="width:2em;display:inline-block"></div>var connectionOptions = {
<a name="line96"></a><div class="linenumber">96</div><div style="width:4em;display:inline-block"></div>'connect timeout': 10000,
<a name="line97"></a><div class="linenumber">97</div><div style="width:4em;display:inline-block"></div>'force new connection': true
<a name="line98"></a><div class="linenumber">98</div><div style="width:2em;display:inline-block"></div>};
<a name="line99"></a><div class="linenumber">99</div>
<a name="line100"></a><div class="linenumber">100</div><div style="width:2em;display:inline-block"></div>/** @private */
<a name="line101"></a><div class="linenumber">101</div><div style="width:2em;display:inline-block"></div>//
<a name="line102"></a><div class="linenumber">102</div><div style="width:2em;display:inline-block"></div>// this function replaces the deprecated MediaStream.stop method
<a name="line103"></a><div class="linenumber">103</div><div style="width:2em;display:inline-block"></div>//
<a name="line104"></a><div class="linenumber">104</div><div style="width:2em;display:inline-block"></div>function stopStream(stream) {
<a name="line105"></a><div class="linenumber">105</div><div style="width:3em;display:inline-block"></div>var i;
<a name="line106"></a><div class="linenumber">106</div><div style="width:3em;display:inline-block"></div>var tracks;
<a name="line107"></a><div class="linenumber">107</div>
<a name="line108"></a><div class="linenumber">108</div><div style="width:3em;display:inline-block"></div>tracks = stream.getAudioTracks();
<a name="line109"></a><div class="linenumber">109</div><div style="width:3em;display:inline-block"></div>for( i = 0; i < tracks.length; i++ ) {
<a name="line110"></a><div class="linenumber">110</div><div style="width:5em;display:inline-block"></div>try {
<a name="line111"></a><div class="linenumber">111</div><div style="width:6em;display:inline-block"></div>tracks[i].stop();
<a name="line112"></a><div class="linenumber">112</div><div style="width:5em;display:inline-block"></div>} catch(err){}
<a name="line113"></a><div class="linenumber">113</div><div style="width:3em;display:inline-block"></div>}
<a name="line114"></a><div class="linenumber">114</div><div style="width:3em;display:inline-block"></div>tracks = stream.getVideoTracks();
<a name="line115"></a><div class="linenumber">115</div><div style="width:3em;display:inline-block"></div>for( i = 0; i < tracks.length; i++ ) {
<a name="line116"></a><div class="linenumber">116</div><div style="width:5em;display:inline-block"></div>try {
<a name="line117"></a><div class="linenumber">117</div><div style="width:6em;display:inline-block"></div>tracks[i].stop();
<a name="line118"></a><div class="linenumber">118</div><div style="width:5em;display:inline-block"></div>} catch(err){}
<a name="line119"></a><div class="linenumber">119</div><div style="width:3em;display:inline-block"></div>}
<a name="line120"></a><div class="linenumber">120</div>
<a name="line121"></a><div class="linenumber">121</div><div style="width:3em;display:inline-block"></div>if (typeof stream.stop === 'function') {
<a name="line122"></a><div class="linenumber">122</div><div style="width:5em;display:inline-block"></div>try {
<a name="line123"></a><div class="linenumber">123</div><div style="width:6em;display:inline-block"></div>stream.stop();
<a name="line124"></a><div class="linenumber">124</div><div style="width:5em;display:inline-block"></div>} catch(err){}
<a name="line125"></a><div class="linenumber">125</div><div style="width:3em;display:inline-block"></div>}
<a name="line126"></a><div class="linenumber">126</div><div style="width:2em;display:inline-block"></div>}
<a name="line127"></a><div class="linenumber">127</div>
<a name="line128"></a><div class="linenumber">128</div><div style="width:2em;display:inline-block"></div>/**
<a name="line129"></a><div class="linenumber">129</div><div style="width:2em;display:inline-block"></div>* Sets functions which filter sdp records before calling setLocalDescription or setRemoteDescription.
<a name="line130"></a><div class="linenumber">130</div><div style="width:2em;display:inline-block"></div>* This is advanced functionality which can break things, easily. See the easyrtc_rates.js file for a
<a name="line131"></a><div class="linenumber">131</div><div style="width:2em;display:inline-block"></div>* filter builder.
<a name="line132"></a><div class="linenumber">132</div><div style="width:2em;display:inline-block"></div>* @param {Function} localFilter a function that takes an sdp string and returns an sdp string.
<a name="line133"></a><div class="linenumber">133</div><div style="width:2em;display:inline-block"></div>* @param {Function} remoteFilter a function that takes an sdp string and returns an sdp string.
<a name="line134"></a><div class="linenumber">134</div><div style="width:2em;display:inline-block"></div>*/
<a name="line135"></a><div class="linenumber">135</div><div style="width:2em;display:inline-block"></div>this.setSdpFilters = function(localFilter, remoteFilter) {
<a name="line136"></a><div class="linenumber">136</div><div style="width:4em;display:inline-block"></div>sdpLocalFilter = localFilter;
<a name="line137"></a><div class="linenumber">137</div><div style="width:4em;display:inline-block"></div>sdpRemoteFilter = remoteFilter;
<a name="line138"></a><div class="linenumber">138</div><div style="width:2em;display:inline-block"></div>};
<a name="line139"></a><div class="linenumber">139</div>
<a name="line140"></a><div class="linenumber">140</div><div style="width:2em;display:inline-block"></div>/**
<a name="line141"></a><div class="linenumber">141</div><div style="width:2em;display:inline-block"></div>* Sets a function to warn about the peer connection closing.
<a name="line142"></a><div class="linenumber">142</div><div style="width:2em;display:inline-block"></div>* @param {Function} handler: a function that gets an easyrtcid as an argument.
<a name="line143"></a><div class="linenumber">143</div><div style="width:2em;display:inline-block"></div>*/
<a name="line144"></a><div class="linenumber">144</div><div style="width:2em;display:inline-block"></div>this.setPeerClosedListener = function( handler ) {
<a name="line145"></a><div class="linenumber">145</div><div style="width:3em;display:inline-block"></div>this.onPeerClosed = handler;
<a name="line146"></a><div class="linenumber">146</div><div style="width:2em;display:inline-block"></div>};
<a name="line147"></a><div class="linenumber">147</div>
<a name="line148"></a><div class="linenumber">148</div><div style="width:2em;display:inline-block"></div>/**
<a name="line149"></a><div class="linenumber">149</div><div style="width:2em;display:inline-block"></div>* Sets a function to warn about the peer connection open.
<a name="line150"></a><div class="linenumber">150</div><div style="width:2em;display:inline-block"></div>* @param {Function} handler: a function that gets an easyrtcid as an argument.
<a name="line151"></a><div class="linenumber">151</div><div style="width:2em;display:inline-block"></div>*/
<a name="line152"></a><div class="linenumber">152</div><div style="width:2em;display:inline-block"></div>this.setPeerOpenListener = function( handler ) {
<a name="line153"></a><div class="linenumber">153</div><div style="width:3em;display:inline-block"></div>this.onPeerOpen = handler;
<a name="line154"></a><div class="linenumber">154</div><div style="width:2em;display:inline-block"></div>};
<a name="line155"></a><div class="linenumber">155</div>
<a name="line156"></a><div class="linenumber">156</div><div style="width:2em;display:inline-block"></div>/**
<a name="line157"></a><div class="linenumber">157</div><div style="width:2em;display:inline-block"></div>* Sets a function to receive warnings about the peer connection
<a name="line158"></a><div class="linenumber">158</div><div style="width:2em;display:inline-block"></div>* failing. The peer connection may recover by itself.
<a name="line159"></a><div class="linenumber">159</div><div style="width:2em;display:inline-block"></div>* @param {Function} failingHandler: a function that gets an easyrtcid as an argument.
<a name="line160"></a><div class="linenumber">160</div><div style="width:2em;display:inline-block"></div>* @param {Function} recoveredHandler: a function that gets an easyrtcid as an argument.
<a name="line161"></a><div class="linenumber">161</div><div style="width:2em;display:inline-block"></div>*/
<a name="line162"></a><div class="linenumber">162</div><div style="width:2em;display:inline-block"></div>this.setPeerFailingListener = function( failingHandler, recoveredHandler ) {
<a name="line163"></a><div class="linenumber">163</div><div style="width:3em;display:inline-block"></div>this.onPeerFailing = failingHandler;
<a name="line164"></a><div class="linenumber">164</div><div style="width:3em;display:inline-block"></div>this.onPeerRecovered = recoveredHandler;
<a name="line165"></a><div class="linenumber">165</div><div style="width:2em;display:inline-block"></div>};
<a name="line166"></a><div class="linenumber">166</div>
<a name="line167"></a><div class="linenumber">167</div><div style="width:2em;display:inline-block"></div>/**
<a name="line168"></a><div class="linenumber">168</div><div style="width:2em;display:inline-block"></div>* Sets a function which filters IceCandidate records being sent or received.
<a name="line169"></a><div class="linenumber">169</div><div style="width:2em;display:inline-block"></div>*
<a name="line170"></a><div class="linenumber">170</div><div style="width:2em;display:inline-block"></div>* Candidate records can be received while they are being generated locally (before being
<a name="line171"></a><div class="linenumber">171</div><div style="width:2em;display:inline-block"></div>* sent to a peer), and after they are received by the peer. The filter receives two arguments, the candidate record and a boolean
<a name="line172"></a><div class="linenumber">172</div><div style="width:2em;display:inline-block"></div>* flag that is true for a candidate being received from another peer,
<a name="line173"></a><div class="linenumber">173</div><div style="width:2em;display:inline-block"></div>* and false for a candidate that was generated locally. The candidate record has the form:
<a name="line174"></a><div class="linenumber">174</div><div style="width:2em;display:inline-block"></div>* {type: 'candidate', label: sdpMLineIndex, id: sdpMid, candidate: candidateString}
<a name="line175"></a><div class="linenumber">175</div><div style="width:2em;display:inline-block"></div>* The function should return one of the following: the input candidate record, a modified candidate record, or null (indicating that the
<a name="line176"></a><div class="linenumber">176</div><div style="width:2em;display:inline-block"></div>* candidate should be discarded).
<a name="line177"></a><div class="linenumber">177</div><div style="width:2em;display:inline-block"></div>* @param {Function} filter
<a name="line178"></a><div class="linenumber">178</div><div style="width:2em;display:inline-block"></div>*/
<a name="line179"></a><div class="linenumber">179</div><div style="width:2em;display:inline-block"></div>this.setIceCandidateFilter = function(filter) {
<a name="line180"></a><div class="linenumber">180</div><div style="width:4em;display:inline-block"></div>iceCandidateFilter = filter;
<a name="line181"></a><div class="linenumber">181</div><div style="width:2em;display:inline-block"></div>};
<a name="line182"></a><div class="linenumber">182</div>
<a name="line183"></a><div class="linenumber">183</div><div style="width:2em;display:inline-block"></div>/**
<a name="line184"></a><div class="linenumber">184</div><div style="width:2em;display:inline-block"></div>* Sets a function that listens on IceConnectionStateChange events.
<a name="line185"></a><div class="linenumber">185</div><div style="width:2em;display:inline-block"></div>*
<a name="line186"></a><div class="linenumber">186</div><div style="width:2em;display:inline-block"></div>* During ICE negotiation the peer connection fires the iceconnectionstatechange event.
<a name="line187"></a><div class="linenumber">187</div><div style="width:2em;display:inline-block"></div>* It is sometimes useful for the application to learn about these changes, especially if the ICE connection fails.
<a name="line188"></a><div class="linenumber">188</div><div style="width:2em;display:inline-block"></div>* The function should accept three parameters: the easyrtc id of the peer, the iceconnectionstatechange event target and the iceconnectionstate.
<a name="line189"></a><div class="linenumber">189</div><div style="width:2em;display:inline-block"></div>* @param {Function} listener
<a name="line190"></a><div class="linenumber">190</div><div style="width:2em;display:inline-block"></div>*/
<a name="line191"></a><div class="linenumber">191</div><div style="width:2em;display:inline-block"></div>this.setIceConnectionStateChangeListener = function(listener) {
<a name="line192"></a><div class="linenumber">192</div><div style="width:3em;display:inline-block"></div>iceConnectionStateChangeListener = listener;
<a name="line193"></a><div class="linenumber">193</div><div style="width:2em;display:inline-block"></div>};
<a name="line194"></a><div class="linenumber">194</div>
<a name="line195"></a><div class="linenumber">195</div><div style="width:2em;display:inline-block"></div>/**
<a name="line196"></a><div class="linenumber">196</div><div style="width:2em;display:inline-block"></div>* Sets a function that listens on SignalingStateChange events.
<a name="line197"></a><div class="linenumber">197</div><div style="width:2em;display:inline-block"></div>*
<a name="line198"></a><div class="linenumber">198</div><div style="width:2em;display:inline-block"></div>* During ICE negotiation the peer connection fires the signalingstatechange event.
<a name="line199"></a><div class="linenumber">199</div><div style="width:2em;display:inline-block"></div>* The function should accept three parameters: the easyrtc id of the peer, the signalingstatechange event target and the signalingstate.
<a name="line200"></a><div class="linenumber">200</div><div style="width:2em;display:inline-block"></div>* @param {Function} listener
<a name="line201"></a><div class="linenumber">201</div><div style="width:2em;display:inline-block"></div>*/
<a name="line202"></a><div class="linenumber">202</div><div style="width:2em;display:inline-block"></div>this.setSignalingStateChangeListener = function(listener) {
<a name="line203"></a><div class="linenumber">203</div><div style="width:3em;display:inline-block"></div>signalingStateChangeListener = listener;
<a name="line204"></a><div class="linenumber">204</div><div style="width:2em;display:inline-block"></div>};
<a name="line205"></a><div class="linenumber">205</div>
<a name="line206"></a><div class="linenumber">206</div><div style="width:2em;display:inline-block"></div>/**
<a name="line207"></a><div class="linenumber">207</div><div style="width:2em;display:inline-block"></div>* Controls whether a default local media stream should be acquired automatically during calls and accepts
<a name="line208"></a><div class="linenumber">208</div><div style="width:2em;display:inline-block"></div>* if a list of streamNames is not supplied. The default is true, which mimics the behaviour of earlier releases
<a name="line209"></a><div class="linenumber">209</div><div style="width:2em;display:inline-block"></div>* that didn't support multiple streams. This function should be called before easyrtc.call or before entering an
<a name="line210"></a><div class="linenumber">210</div><div style="width:2em;display:inline-block"></div>* accept callback.
<a name="line211"></a><div class="linenumber">211</div><div style="width:2em;display:inline-block"></div>* @param {Boolean} flag true to allocate a default local media stream.
<a name="line212"></a><div class="linenumber">212</div><div style="width:2em;display:inline-block"></div>*/
<a name="line213"></a><div class="linenumber">213</div><div style="width:2em;display:inline-block"></div>this.setAutoInitUserMedia = function(flag) {
<a name="line214"></a><div class="linenumber">214</div><div style="width:4em;display:inline-block"></div>autoInitUserMedia = !!flag;
<a name="line215"></a><div class="linenumber">215</div><div style="width:2em;display:inline-block"></div>};
<a name="line216"></a><div class="linenumber">216</div>
<a name="line217"></a><div class="linenumber">217</div><div style="width:2em;display:inline-block"></div>/**
<a name="line218"></a><div class="linenumber">218</div><div style="width:2em;display:inline-block"></div>* This function performs a printf like formatting. It actually takes an unlimited
<a name="line219"></a><div class="linenumber">219</div><div style="width:2em;display:inline-block"></div>* number of arguments, the declared arguments arg1, arg2, arg3 are present just for
<a name="line220"></a><div class="linenumber">220</div><div style="width:2em;display:inline-block"></div>* documentation purposes.
<a name="line221"></a><div class="linenumber">221</div><div style="width:2em;display:inline-block"></div>* @param {String} format A string like "abcd{1}efg{2}hij{1}."
<a name="line222"></a><div class="linenumber">222</div><div style="width:2em;display:inline-block"></div>* @param {String} arg1 The value that replaces {1}
<a name="line223"></a><div class="linenumber">223</div><div style="width:2em;display:inline-block"></div>* @param {String} arg2 The value that replaces {2}
<a name="line224"></a><div class="linenumber">224</div><div style="width:2em;display:inline-block"></div>* @param {String} arg3 The value that replaces {3}
<a name="line225"></a><div class="linenumber">225</div><div style="width:2em;display:inline-block"></div>* @returns {String} the formatted string.
<a name="line226"></a><div class="linenumber">226</div><div style="width:2em;display:inline-block"></div>*/
<a name="line227"></a><div class="linenumber">227</div><div style="width:2em;display:inline-block"></div>this.format = function(format, arg1, arg2, arg3) {
<a name="line228"></a><div class="linenumber">228</div><div style="width:4em;display:inline-block"></div>var formatted = arguments[0];
<a name="line229"></a><div class="linenumber">229</div><div style="width:4em;display:inline-block"></div>for (var i = 1; i < arguments.length; i++) {
<a name="line230"></a><div class="linenumber">230</div><div style="width:6em;display:inline-block"></div>var regexp = new RegExp('\\{' + (i - 1) + '\\}', 'gi');
<a name="line231"></a><div class="linenumber">231</div><div style="width:6em;display:inline-block"></div>formatted = formatted.replace(regexp, arguments[i]);
<a name="line232"></a><div class="linenumber">232</div><div style="width:4em;display:inline-block"></div>}
<a name="line233"></a><div class="linenumber">233</div><div style="width:4em;display:inline-block"></div>return formatted;
<a name="line234"></a><div class="linenumber">234</div><div style="width:2em;display:inline-block"></div>};
<a name="line235"></a><div class="linenumber">235</div>
<a name="line236"></a><div class="linenumber">236</div><div style="width:2em;display:inline-block"></div>/**
<a name="line237"></a><div class="linenumber">237</div><div style="width:2em;display:inline-block"></div>* This function checks if a socket is actually connected.
<a name="line238"></a><div class="linenumber">238</div><div style="width:2em;display:inline-block"></div>* @private
<a name="line239"></a><div class="linenumber">239</div><div style="width:2em;display:inline-block"></div>* @param {Object} socket a socket.io socket.
<a name="line240"></a><div class="linenumber">240</div><div style="width:2em;display:inline-block"></div>* @return true if the socket exists and is connected, false otherwise.
<a name="line241"></a><div class="linenumber">241</div><div style="width:2em;display:inline-block"></div>*/
<a name="line242"></a><div class="linenumber">242</div><div style="width:2em;display:inline-block"></div>function isSocketConnected(socket) {
<a name="line243"></a><div class="linenumber">243</div><div style="width:3em;display:inline-block"></div>return socket && (
<a name="line244"></a><div class="linenumber">244</div><div style="width:6em;display:inline-block"></div>(socket.socket && socket.socket.connected) || socket.connected
<a name="line245"></a><div class="linenumber">245</div><div style="width:4em;display:inline-block"></div>);
<a name="line246"></a><div class="linenumber">246</div><div style="width:2em;display:inline-block"></div>}
<a name="line247"></a><div class="linenumber">247</div>
<a name="line248"></a><div class="linenumber">248</div><div style="width:2em;display:inline-block"></div>/** @private */
<a name="line249"></a><div class="linenumber">249</div><div style="width:2em;display:inline-block"></div>//
<a name="line250"></a><div class="linenumber">250</div><div style="width:2em;display:inline-block"></div>// Maps a key to a language specific string using the easyrtc_lang map.
<a name="line251"></a><div class="linenumber">251</div><div style="width:2em;display:inline-block"></div>// Defaults to the key if the key can not be found, but outputs a warning in that case.
<a name="line252"></a><div class="linenumber">252</div><div style="width:2em;display:inline-block"></div>// This function is only used internally by easyrtc.js
<a name="line253"></a><div class="linenumber">253</div><div style="width:2em;display:inline-block"></div>//
<a name="line254"></a><div class="linenumber">254</div><div style="width:2em;display:inline-block"></div>var haveAudioVideo = {
<a name="line255"></a><div class="linenumber">255</div><div style="width:4em;display:inline-block"></div>audio: false,
<a name="line256"></a><div class="linenumber">256</div><div style="width:4em;display:inline-block"></div>video: false
<a name="line257"></a><div class="linenumber">257</div><div style="width:2em;display:inline-block"></div>};
<a name="line258"></a><div class="linenumber">258</div>
<a name="line259"></a><div class="linenumber">259</div><div style="width:2em;display:inline-block"></div>/**
<a name="line260"></a><div class="linenumber">260</div><div style="width:2em;display:inline-block"></div>* @private
<a name="line261"></a><div class="linenumber">261</div><div style="width:2em;display:inline-block"></div>* @param {String} key
<a name="line262"></a><div class="linenumber">262</div><div style="width:2em;display:inline-block"></div>*/
<a name="line263"></a><div class="linenumber">263</div><div style="width:2em;display:inline-block"></div>this.getConstantString = function(key) {
<a name="line264"></a><div class="linenumber">264</div><div style="width:4em;display:inline-block"></div>if (easyrtc_lang[key]) {
<a name="line265"></a><div class="linenumber">265</div><div style="width:6em;display:inline-block"></div>return easyrtc_lang[key];
<a name="line266"></a><div class="linenumber">266</div><div style="width:4em;display:inline-block"></div>}
<a name="line267"></a><div class="linenumber">267</div><div style="width:4em;display:inline-block"></div>else {
<a name="line268"></a><div class="linenumber">268</div><div style="width:6em;display:inline-block"></div>self.showError(self.errCodes.DEVELOPER_ERR, "Could not find key='" + key + "' in easyrtc_lang");
<a name="line269"></a><div class="linenumber">269</div><div style="width:6em;display:inline-block"></div>return key;
<a name="line270"></a><div class="linenumber">270</div><div style="width:4em;display:inline-block"></div>}
<a name="line271"></a><div class="linenumber">271</div><div style="width:2em;display:inline-block"></div>};
<a name="line272"></a><div class="linenumber">272</div>
<a name="line273"></a><div class="linenumber">273</div><div style="width:2em;display:inline-block"></div>/** @private */
<a name="line274"></a><div class="linenumber">274</div><div style="width:2em;display:inline-block"></div>//
<a name="line275"></a><div class="linenumber">275</div><div style="width:2em;display:inline-block"></div>// this is a list of the events supported by the generalized event listener.
<a name="line276"></a><div class="linenumber">276</div><div style="width:2em;display:inline-block"></div>//
<a name="line277"></a><div class="linenumber">277</div><div style="width:2em;display:inline-block"></div>var allowedEvents = {
<a name="line278"></a><div class="linenumber">278</div><div style="width:4em;display:inline-block"></div>roomOccupant: true, // this receives the list of everybody in any room you belong to
<a name="line279"></a><div class="linenumber">279</div><div style="width:4em;display:inline-block"></div>roomOccupants: true // this receives a {roomName:..., occupants:...} value for a specific room
<a name="line280"></a><div class="linenumber">280</div><div style="width:2em;display:inline-block"></div>};
<a name="line281"></a><div class="linenumber">281</div>
<a name="line282"></a><div class="linenumber">282</div><div style="width:2em;display:inline-block"></div>/** @private */
<a name="line283"></a><div class="linenumber">283</div><div style="width:2em;display:inline-block"></div>//
<a name="line284"></a><div class="linenumber">284</div><div style="width:2em;display:inline-block"></div>// A map of eventListeners. The key is the event type.
<a name="line285"></a><div class="linenumber">285</div><div style="width:2em;display:inline-block"></div>//
<a name="line286"></a><div class="linenumber">286</div><div style="width:2em;display:inline-block"></div>var eventListeners = {};
<a name="line287"></a><div class="linenumber">287</div>
<a name="line288"></a><div class="linenumber">288</div><div style="width:2em;display:inline-block"></div>/**
<a name="line289"></a><div class="linenumber">289</div><div style="width:2em;display:inline-block"></div>* This function checks if an attempt was made to add an event listener or
<a name="line290"></a><div class="linenumber">290</div><div style="width:2em;display:inline-block"></div>* or emit an unlisted event, since such is typically a typo.
<a name="line291"></a><div class="linenumber">291</div><div style="width:2em;display:inline-block"></div>* @private
<a name="line292"></a><div class="linenumber">292</div><div style="width:2em;display:inline-block"></div>* @param {String} eventName
<a name="line293"></a><div class="linenumber">293</div><div style="width:2em;display:inline-block"></div>* @param {String} callingFunction the name of the calling function.
<a name="line294"></a><div class="linenumber">294</div><div style="width:2em;display:inline-block"></div>*/
<a name="line295"></a><div class="linenumber">295</div><div style="width:2em;display:inline-block"></div>function event(eventName, callingFunction) {
<a name="line296"></a><div class="linenumber">296</div><div style="width:4em;display:inline-block"></div>if (typeof eventName !== 'string') {
<a name="line297"></a><div class="linenumber">297</div><div style="width:6em;display:inline-block"></div>self.showError(self.errCodes.DEVELOPER_ERR, callingFunction + " called without a string as the first argument");
<a name="line298"></a><div class="linenumber">298</div><div style="width:6em;display:inline-block"></div>throw "developer error";
<a name="line299"></a><div class="linenumber">299</div><div style="width:4em;display:inline-block"></div>}
<a name="line300"></a><div class="linenumber">300</div><div style="width:4em;display:inline-block"></div>if (!allowedEvents[eventName]) {
<a name="line301"></a><div class="linenumber">301</div><div style="width:6em;display:inline-block"></div>self.showError(self.errCodes.DEVELOPER_ERR, callingFunction + " called with a bad event name = " + eventName);
<a name="line302"></a><div class="linenumber">302</div><div style="width:6em;display:inline-block"></div>throw "developer error";
<a name="line303"></a><div class="linenumber">303</div><div style="width:4em;display:inline-block"></div>}
<a name="line304"></a><div class="linenumber">304</div><div style="width:2em;display:inline-block"></div>}
<a name="line305"></a><div class="linenumber">305</div>
<a name="line306"></a><div class="linenumber">306</div><div style="width:2em;display:inline-block"></div>/**
<a name="line307"></a><div class="linenumber">307</div><div style="width:2em;display:inline-block"></div>* Adds an event listener for a particular type of event.
<a name="line308"></a><div class="linenumber">308</div><div style="width:2em;display:inline-block"></div>* Currently the only eventName supported is "roomOccupant".
<a name="line309"></a><div class="linenumber">309</div><div style="width:2em;display:inline-block"></div>* @param {String} eventName the type of the event
<a name="line310"></a><div class="linenumber">310</div><div style="width:2em;display:inline-block"></div>* @param {Function} eventListener the function that expects the event.
<a name="line311"></a><div class="linenumber">311</div><div style="width:2em;display:inline-block"></div>* The eventListener gets called with the eventName as it's first argument, and the event
<a name="line312"></a><div class="linenumber">312</div><div style="width:2em;display:inline-block"></div>* data as it's second argument.
<a name="line313"></a><div class="linenumber">313</div><div style="width:2em;display:inline-block"></div>* @returns {void}
<a name="line314"></a><div class="linenumber">314</div><div style="width:2em;display:inline-block"></div>*/
<a name="line315"></a><div class="linenumber">315</div><div style="width:2em;display:inline-block"></div>this.addEventListener = function(eventName, eventListener) {
<a name="line316"></a><div class="linenumber">316</div><div style="width:4em;display:inline-block"></div>event(eventName, "addEventListener");
<a name="line317"></a><div class="linenumber">317</div><div style="width:4em;display:inline-block"></div>if (typeof eventListener !== 'function') {
<a name="line318"></a><div class="linenumber">318</div><div style="width:6em;display:inline-block"></div>self.showError(self.errCodes.DEVELOPER_ERR, "addEventListener called with a non-function for second argument");
<a name="line319"></a><div class="linenumber">319</div><div style="width:6em;display:inline-block"></div>throw "developer error";
<a name="line320"></a><div class="linenumber">320</div><div style="width:4em;display:inline-block"></div>}
<a name="line321"></a><div class="linenumber">321</div><div style="width:4em;display:inline-block"></div>//
<a name="line322"></a><div class="linenumber">322</div><div style="width:4em;display:inline-block"></div>// remove the event listener if it's already present so we don't end up with two copies
<a name="line323"></a><div class="linenumber">323</div><div style="width:4em;display:inline-block"></div>//
<a name="line324"></a><div class="linenumber">324</div><div style="width:4em;display:inline-block"></div>self.removeEventListener(eventName, eventListener);
<a name="line325"></a><div class="linenumber">325</div><div style="width:4em;display:inline-block"></div>if (!eventListeners[eventName]) {
<a name="line326"></a><div class="linenumber">326</div><div style="width:6em;display:inline-block"></div>eventListeners[eventName] = [];
<a name="line327"></a><div class="linenumber">327</div><div style="width:4em;display:inline-block"></div>}
<a name="line328"></a><div class="linenumber">328</div><div style="width:4em;display:inline-block"></div>eventListeners[eventName][eventListeners[eventName].length] = eventListener;
<a name="line329"></a><div class="linenumber">329</div><div style="width:2em;display:inline-block"></div>};
<a name="line330"></a><div class="linenumber">330</div>
<a name="line331"></a><div class="linenumber">331</div><div style="width:2em;display:inline-block"></div>/**
<a name="line332"></a><div class="linenumber">332</div><div style="width:2em;display:inline-block"></div>* Removes an event listener.
<a name="line333"></a><div class="linenumber">333</div><div style="width:2em;display:inline-block"></div>* @param {String} eventName
<a name="line334"></a><div class="linenumber">334</div><div style="width:2em;display:inline-block"></div>* @param {Function} eventListener
<a name="line335"></a><div class="linenumber">335</div><div style="width:2em;display:inline-block"></div>*/
<a name="line336"></a><div class="linenumber">336</div><div style="width:2em;display:inline-block"></div>this.removeEventListener = function(eventName, eventListener) {
<a name="line337"></a><div class="linenumber">337</div><div style="width:4em;display:inline-block"></div>event(eventName, "removeEventListener");
<a name="line338"></a><div class="linenumber">338</div><div style="width:4em;display:inline-block"></div>var listeners = eventListeners[eventName];
<a name="line339"></a><div class="linenumber">339</div><div style="width:4em;display:inline-block"></div>var i = 0;
<a name="line340"></a><div class="linenumber">340</div><div style="width:4em;display:inline-block"></div>if (listeners) {
<a name="line341"></a><div class="linenumber">341</div><div style="width:6em;display:inline-block"></div>for (i = 0; i < listeners.length; i++) {
<a name="line342"></a><div class="linenumber">342</div><div style="width:8em;display:inline-block"></div>if (listeners[i] === eventListener) {
<a name="line343"></a><div class="linenumber">343</div><div style="width:10em;display:inline-block"></div>if (i < listeners.length - 1) {
<a name="line344"></a><div class="linenumber">344</div><div style="width:12em;display:inline-block"></div>listeners[i] = listeners[listeners.length - 1];
<a name="line345"></a><div class="linenumber">345</div><div style="width:10em;display:inline-block"></div>}
<a name="line346"></a><div class="linenumber">346</div><div style="width:10em;display:inline-block"></div>listeners.length = listeners.length - 1;
<a name="line347"></a><div class="linenumber">347</div><div style="width:8em;display:inline-block"></div>}
<a name="line348"></a><div class="linenumber">348</div><div style="width:6em;display:inline-block"></div>}
<a name="line349"></a><div class="linenumber">349</div><div style="width:4em;display:inline-block"></div>}
<a name="line350"></a><div class="linenumber">350</div><div style="width:2em;display:inline-block"></div>};
<a name="line351"></a><div class="linenumber">351</div>
<a name="line352"></a><div class="linenumber">352</div><div style="width:2em;display:inline-block"></div>/**
<a name="line353"></a><div class="linenumber">353</div><div style="width:2em;display:inline-block"></div>* Emits an event, or in other words, calls all the eventListeners for a
<a name="line354"></a><div class="linenumber">354</div><div style="width:2em;display:inline-block"></div>* particular event.
<a name="line355"></a><div class="linenumber">355</div><div style="width:2em;display:inline-block"></div>* @param {String} eventName
<a name="line356"></a><div class="linenumber">356</div><div style="width:2em;display:inline-block"></div>* @param {Object} eventData
<a name="line357"></a><div class="linenumber">357</div><div style="width:2em;display:inline-block"></div>*/
<a name="line358"></a><div class="linenumber">358</div><div style="width:2em;display:inline-block"></div>this.emitEvent = function(eventName, eventData) {
<a name="line359"></a><div class="linenumber">359</div><div style="width:4em;display:inline-block"></div>event(eventName, "emitEvent");
<a name="line360"></a><div class="linenumber">360</div><div style="width:4em;display:inline-block"></div>var listeners = eventListeners[eventName];
<a name="line361"></a><div class="linenumber">361</div><div style="width:4em;display:inline-block"></div>var i = 0;
<a name="line362"></a><div class="linenumber">362</div><div style="width:4em;display:inline-block"></div>if (listeners) {
<a name="line363"></a><div class="linenumber">363</div><div style="width:6em;display:inline-block"></div>for (i = 0; i < listeners.length; i++) {
<a name="line364"></a><div class="linenumber">364</div><div style="width:8em;display:inline-block"></div>listeners[i](eventName, eventData);
<a name="line365"></a><div class="linenumber">365</div><div style="width:6em;display:inline-block"></div>}
<a name="line366"></a><div class="linenumber">366</div><div style="width:4em;display:inline-block"></div>}
<a name="line367"></a><div class="linenumber">367</div><div style="width:2em;display:inline-block"></div>};
<a name="line368"></a><div class="linenumber">368</div>
<a name="line369"></a><div class="linenumber">369</div><div style="width:2em;display:inline-block"></div>/**
<a name="line370"></a><div class="linenumber">370</div><div style="width:2em;display:inline-block"></div>* Error codes that the EasyRTC will use in the errorCode field of error object passed
<a name="line371"></a><div class="linenumber">371</div><div style="width:2em;display:inline-block"></div>* to error handler set by easyrtc.setOnError. The error codes are short printable strings.
<a name="line372"></a><div class="linenumber">372</div><div style="width:2em;display:inline-block"></div>* @type Object
<a name="line373"></a><div class="linenumber">373</div><div style="width:2em;display:inline-block"></div>*/
<a name="line374"></a><div class="linenumber">374</div><div style="width:2em;display:inline-block"></div>this.errCodes = {
<a name="line375"></a><div class="linenumber">375</div><div style="width:4em;display:inline-block"></div>BAD_NAME: "BAD_NAME", // a user name wasn't of the desired form
<a name="line376"></a><div class="linenumber">376</div><div style="width:4em;display:inline-block"></div>CALL_ERR: "CALL_ERR", // something went wrong creating the peer connection
<a name="line377"></a><div class="linenumber">377</div><div style="width:4em;display:inline-block"></div>DEVELOPER_ERR: "DEVELOPER_ERR", // the developer using the EasyRTC library made a mistake
<a name="line378"></a><div class="linenumber">378</div><div style="width:4em;display:inline-block"></div>SYSTEM_ERR: "SYSTEM_ERR", // probably an error related to the network
<a name="line379"></a><div class="linenumber">379</div><div style="width:4em;display:inline-block"></div>CONNECT_ERR: "CONNECT_ERR", // error occurred when trying to create a connection
<a name="line380"></a><div class="linenumber">380</div><div style="width:4em;display:inline-block"></div>MEDIA_ERR: "MEDIA_ERR", // unable to get the local media
<a name="line381"></a><div class="linenumber">381</div><div style="width:4em;display:inline-block"></div>MEDIA_WARNING: "MEDIA_WARNING", // didn't get the desired resolution
<a name="line382"></a><div class="linenumber">382</div><div style="width:4em;display:inline-block"></div>INTERNAL_ERR: "INTERNAL_ERR",
<a name="line383"></a><div class="linenumber">383</div><div style="width:4em;display:inline-block"></div>PEER_GONE: "PEER_GONE", // peer doesn't exist
<a name="line384"></a><div class="linenumber">384</div><div style="width:4em;display:inline-block"></div>ALREADY_CONNECTED: "ALREADY_CONNECTED",
<a name="line385"></a><div class="linenumber">385</div><div style="width:4em;display:inline-block"></div>BAD_CREDENTIAL: "BAD_CREDENTIAL",
<a name="line386"></a><div class="linenumber">386</div><div style="width:4em;display:inline-block"></div>ICECANDIDATE_ERR: "ICECANDIDATE_ERR",
<a name="line387"></a><div class="linenumber">387</div><div style="width:4em;display:inline-block"></div>NOVIABLEICE: "NOVIABLEICE",
<a name="line388"></a><div class="linenumber">388</div><div style="width:4em;display:inline-block"></div>SIGNAL_ERR: "SIGNAL_ERR"
<a name="line389"></a><div class="linenumber">389</div><div style="width:2em;display:inline-block"></div>};
<a name="line390"></a><div class="linenumber">390</div>
<a name="line391"></a><div class="linenumber">391</div><div style="width:2em;display:inline-block"></div>this.apiVersion = "1.1.0";
<a name="line392"></a><div class="linenumber">392</div>
<a name="line393"></a><div class="linenumber">393</div><div style="width:2em;display:inline-block"></div>/** Most basic message acknowledgment object */
<a name="line394"></a><div class="linenumber">394</div><div style="width:2em;display:inline-block"></div>this.ackMessage = {msgType: "ack"};
<a name="line395"></a><div class="linenumber">395</div>
<a name="line396"></a><div class="linenumber">396</div><div style="width:2em;display:inline-block"></div>/** Regular expression pattern for user ids. This will need modification to support non US character sets */
<a name="line397"></a><div class="linenumber">397</div><div style="width:2em;display:inline-block"></div>this.usernameRegExp = /^(.){1,64}$/;
<a name="line398"></a><div class="linenumber">398</div>
<a name="line399"></a><div class="linenumber">399</div><div style="width:2em;display:inline-block"></div>/** Default cookieId name */
<a name="line400"></a><div class="linenumber">400</div><div style="width:2em;display:inline-block"></div>this.cookieId = "easyrtcsid";
<a name="line401"></a><div class="linenumber">401</div>
<a name="line402"></a><div class="linenumber">402</div><div style="width:2em;display:inline-block"></div>/** @private */
<a name="line403"></a><div class="linenumber">403</div><div style="width:2em;display:inline-block"></div>var username = null;
<a name="line404"></a><div class="linenumber">404</div>
<a name="line405"></a><div class="linenumber">405</div><div style="width:2em;display:inline-block"></div>/** Flag to indicate that user is currently logging out */
<a name="line406"></a><div class="linenumber">406</div><div style="width:2em;display:inline-block"></div>this.loggingOut = false;
<a name="line407"></a><div class="linenumber">407</div>
<a name="line408"></a><div class="linenumber">408</div><div style="width:2em;display:inline-block"></div>/** @private */
<a name="line409"></a><div class="linenumber">409</div><div style="width:2em;display:inline-block"></div>this.disconnecting = false;
<a name="line410"></a><div class="linenumber">410</div>
<a name="line411"></a><div class="linenumber">411</div><div style="width:2em;display:inline-block"></div>/** @private */
<a name="line412"></a><div class="linenumber">412</div><div style="width:2em;display:inline-block"></div>//
<a name="line413"></a><div class="linenumber">413</div><div style="width:2em;display:inline-block"></div>// A map of ids to local media streams.
<a name="line414"></a><div class="linenumber">414</div><div style="width:2em;display:inline-block"></div>//
<a name="line415"></a><div class="linenumber">415</div><div style="width:2em;display:inline-block"></div>var namedLocalMediaStreams = {};
<a name="line416"></a><div class="linenumber">416</div>
<a name="line417"></a><div class="linenumber">417</div><div style="width:2em;display:inline-block"></div>/** @private */
<a name="line418"></a><div class="linenumber">418</div><div style="width:2em;display:inline-block"></div>var sessionFields = [];
<a name="line419"></a><div class="linenumber">419</div>
<a name="line420"></a><div class="linenumber">420</div><div style="width:2em;display:inline-block"></div>/** @private */
<a name="line421"></a><div class="linenumber">421</div><div style="width:2em;display:inline-block"></div>var receivedMediaConstraints = {};
<a name="line422"></a><div class="linenumber">422</div>
<a name="line423"></a><div class="linenumber">423</div><div style="width:2em;display:inline-block"></div>/**
<a name="line424"></a><div class="linenumber">424</div><div style="width:2em;display:inline-block"></div>* Control whether the client requests audio from a peer during a call.
<a name="line425"></a><div class="linenumber">425</div><div style="width:2em;display:inline-block"></div>* Must be called before the call to have an effect.
<a name="line426"></a><div class="linenumber">426</div><div style="width:2em;display:inline-block"></div>* @param value - true to receive audio, false otherwise. The default is true.
<a name="line427"></a><div class="linenumber">427</div><div style="width:2em;display:inline-block"></div>*/
<a name="line428"></a><div class="linenumber">428</div><div style="width:2em;display:inline-block"></div>this.enableAudioReceive = function(value) {
<a name="line429"></a><div class="linenumber">429</div><div style="width:4em;display:inline-block"></div>if (
<a name="line430"></a><div class="linenumber">430</div><div style="width:6em;display:inline-block"></div>adapter && adapter.browserDetails &&
<a name="line431"></a><div class="linenumber">431</div><div style="width:6em;display:inline-block"></div>(adapter.browserDetails.browser === "firefox" || adapter.browserDetails.browser === "edge")
<a name="line432"></a><div class="linenumber">432</div><div style="width:4em;display:inline-block"></div>) {
<a name="line433"></a><div class="linenumber">433</div><div style="width:6em;display:inline-block"></div>receivedMediaConstraints.offerToReceiveAudio = value;
<a name="line434"></a><div class="linenumber">434</div><div style="width:4em;display:inline-block"></div>}
<a name="line435"></a><div class="linenumber">435</div><div style="width:4em;display:inline-block"></div>else {
<a name="line436"></a><div class="linenumber">436</div><div style="width:6em;display:inline-block"></div>receivedMediaConstraints.mandatory = receivedMediaConstraints.mandatory || {};
<a name="line437"></a><div class="linenumber">437</div><div style="width:6em;display:inline-block"></div>receivedMediaConstraints.mandatory.OfferToReceiveAudio = value;
<a name="line438"></a><div class="linenumber">438</div><div style="width:4em;display:inline-block"></div>}
<a name="line439"></a><div class="linenumber">439</div><div style="width:2em;display:inline-block"></div>};
<a name="line440"></a><div class="linenumber">440</div>
<a name="line441"></a><div class="linenumber">441</div><div style="width:2em;display:inline-block"></div>/**
<a name="line442"></a><div class="linenumber">442</div><div style="width:2em;display:inline-block"></div>* Control whether the client requests video from a peer during a call.
<a name="line443"></a><div class="linenumber">443</div><div style="width:2em;display:inline-block"></div>* Must be called before the call to have an effect.
<a name="line444"></a><div class="linenumber">444</div><div style="width:2em;display:inline-block"></div>* @param value - true to receive video, false otherwise. The default is true.
<a name="line445"></a><div class="linenumber">445</div><div style="width:2em;display:inline-block"></div>*/
<a name="line446"></a><div class="linenumber">446</div><div style="width:2em;display:inline-block"></div>this.enableVideoReceive = function(value) {
<a name="line447"></a><div class="linenumber">447</div><div style="width:4em;display:inline-block"></div>if (
<a name="line448"></a><div class="linenumber">448</div><div style="width:6em;display:inline-block"></div>adapter && adapter.browserDetails &&
<a name="line449"></a><div class="linenumber">449</div><div style="width:6em;display:inline-block"></div>(adapter.browserDetails.browser === "firefox" || adapter.browserDetails.browser === "edge")
<a name="line450"></a><div class="linenumber">450</div><div style="width:4em;display:inline-block"></div>) {
<a name="line451"></a><div class="linenumber">451</div><div style="width:5em;display:inline-block"></div>receivedMediaConstraints.offerToReceiveVideo = value;
<a name="line452"></a><div class="linenumber">452</div><div style="width:4em;display:inline-block"></div>}
<a name="line453"></a><div class="linenumber">453</div><div style="width:4em;display:inline-block"></div>else {
<a name="line454"></a><div class="linenumber">454</div><div style="width:6em;display:inline-block"></div>receivedMediaConstraints.mandatory = receivedMediaConstraints.mandatory || {};
<a name="line455"></a><div class="linenumber">455</div><div style="width:6em;display:inline-block"></div>receivedMediaConstraints.mandatory.OfferToReceiveVideo = value;
<a name="line456"></a><div class="linenumber">456</div><div style="width:4em;display:inline-block"></div>}
<a name="line457"></a><div class="linenumber">457</div><div style="width:2em;display:inline-block"></div>};
<a name="line458"></a><div class="linenumber">458</div>
<a name="line459"></a><div class="linenumber">459</div><div style="width:2em;display:inline-block"></div>// True by default
<a name="line460"></a><div class="linenumber">460</div><div style="width:2em;display:inline-block"></div>// TODO should not be true by default only for legacy
<a name="line461"></a><div class="linenumber">461</div><div style="width:2em;display:inline-block"></div>this.enableAudioReceive(true);
<a name="line462"></a><div class="linenumber">462</div><div style="width:2em;display:inline-block"></div>this.enableVideoReceive(true);
<a name="line463"></a><div class="linenumber">463</div>
<a name="line464"></a><div class="linenumber">464</div><div style="width:2em;display:inline-block"></div>function getSourceList(callback, sourceType) {
<a name="line465"></a><div class="linenumber">465</div><div style="width:4em;display:inline-block"></div>navigator.mediaDevices.enumerateDevices().then(
<a name="line466"></a><div class="linenumber">466</div><div style="width:6em;display:inline-block"></div>function(values) {
<a name="line467"></a><div class="linenumber">467</div><div style="width:8em;display:inline-block"></div>var results = [];
<a name="line468"></a><div class="linenumber">468</div><div style="width:8em;display:inline-block"></div>for (var i = 0; i < values.length; i++) {
<a name="line469"></a><div class="linenumber">469</div><div style="width:10em;display:inline-block"></div>var source = values[i];
<a name="line470"></a><div class="linenumber">470</div><div style="width:10em;display:inline-block"></div>if (source.kind === sourceType) {
<a name="line471"></a><div class="linenumber">471</div><div style="width:12em;display:inline-block"></div>source.id = source.deviceId; //backwards compatibility
<a name="line472"></a><div class="linenumber">472</div><div style="width:12em;display:inline-block"></div>results.push(source);
<a name="line473"></a><div class="linenumber">473</div><div style="width:10em;display:inline-block"></div>}
<a name="line474"></a><div class="linenumber">474</div><div style="width:8em;display:inline-block"></div>}
<a name="line475"></a><div class="linenumber">475</div><div style="width:8em;display:inline-block"></div>callback(results);
<a name="line476"></a><div class="linenumber">476</div><div style="width:6em;display:inline-block"></div>}
<a name="line477"></a><div class="linenumber">477</div><div style="width:5em;display:inline-block"></div>).catch(
<a name="line478"></a><div class="linenumber">478</div><div style="width:6em;display:inline-block"></div>function(reason) {
<a name="line479"></a><div class="linenumber">479</div><div style="width:7em;display:inline-block"></div>logDebug("Unable to enumerate devices (" + reason + ")");
<a name="line480"></a><div class="linenumber">480</div><div style="width:6em;display:inline-block"></div>}
<a name="line481"></a><div class="linenumber">481</div><div style="width:4em;display:inline-block"></div>);
<a name="line482"></a><div class="linenumber">482</div><div style="width:2em;display:inline-block"></div>}
<a name="line483"></a><div class="linenumber">483</div>
<a name="line484"></a><div class="linenumber">484</div><div style="width:2em;display:inline-block"></div>/**
<a name="line485"></a><div class="linenumber">485</div><div style="width:2em;display:inline-block"></div>* Sets the audio output device of a Video object.
<a name="line486"></a><div class="linenumber">486</div><div style="width:2em;display:inline-block"></div>* That is to say, this controls what speakers get the sound.
<a name="line487"></a><div class="linenumber">487</div><div style="width:2em;display:inline-block"></div>* In theory, this works on Chrome but probably doesn't work anywhere else yet.
<a name="line488"></a><div class="linenumber">488</div><div style="width:2em;display:inline-block"></div>* This code was cribbed from https://webrtc.github.io/samples/src/content/devices/multi/.
<a name="line489"></a><div class="linenumber">489</div><div style="width:2em;display:inline-block"></div>* @param {Object} element an HTML5 video element
<a name="line490"></a><div class="linenumber">490</div><div style="width:2em;display:inline-block"></div>* @param {String} sinkId a deviceid from getAudioSinkList
<a name="line491"></a><div class="linenumber">491</div><div style="width:2em;display:inline-block"></div>*/
<a name="line492"></a><div class="linenumber">492</div><div style="width:2em;display:inline-block"></div>this.setAudioOutput = function(element, sinkId) {
<a name="line493"></a><div class="linenumber">493</div><div style="width:3em;display:inline-block"></div>if (typeof element.sinkId !== 'undefined') {
<a name="line494"></a><div class="linenumber">494</div><div style="width:5em;display:inline-block"></div>element.setSinkId(sinkId)
<a name="line495"></a><div class="linenumber">495</div><div style="width:5em;display:inline-block"></div>.then(function() {
<a name="line496"></a><div class="linenumber">496</div><div style="width:6em;display:inline-block"></div>logDebug('Success, audio output device attached: ' + sinkId + ' to ' +
<a name="line497"></a><div class="linenumber">497</div><div style="width:8em;display:inline-block"></div>'element with ' + element.title + ' as source.');
<a name="line498"></a><div class="linenumber">498</div><div style="width:5em;display:inline-block"></div>})
<a name="line499"></a><div class="linenumber">499</div><div style="width:5em;display:inline-block"></div>.catch(function(error) {
<a name="line500"></a><div class="linenumber">500</div><div style="width:6em;display:inline-block"></div>var errorMessage = error;
<a name="line501"></a><div class="linenumber">501</div><div style="width:6em;display:inline-block"></div>if (error.name === 'SecurityError') {
<a name="line502"></a><div class="linenumber">502</div><div style="width:7em;display:inline-block"></div>errorMessage = 'You need to use HTTPS for selecting audio output ' +
<a name="line503"></a><div class="linenumber">503</div><div style="width:9em;display:inline-block"></div>'device: ' + error;
<a name="line504"></a><div class="linenumber">504</div><div style="width:6em;display:inline-block"></div>}
<a name="line505"></a><div class="linenumber">505</div><div style="width:6em;display:inline-block"></div>logDebug(errorMessage);
<a name="line506"></a><div class="linenumber">506</div><div style="width:5em;display:inline-block"></div>});
<a name="line507"></a><div class="linenumber">507</div><div style="width:3em;display:inline-block"></div>} else {
<a name="line508"></a><div class="linenumber">508</div><div style="width:5em;display:inline-block"></div>logDebug('Browser does not support output device selection.');
<a name="line509"></a><div class="linenumber">509</div><div style="width:3em;display:inline-block"></div>}
<a name="line510"></a><div class="linenumber">510</div><div style="width:2em;display:inline-block"></div>};
<a name="line511"></a><div class="linenumber">511</div>
<a name="line512"></a><div class="linenumber">512</div><div style="width:2em;display:inline-block"></div>/**
<a name="line513"></a><div class="linenumber">513</div><div style="width:2em;display:inline-block"></div>* Gets a list of the available audio sinks (ie, speakers)
<a name="line514"></a><div class="linenumber">514</div><div style="width:2em;display:inline-block"></div>* @param {Function} callback receives list of {deviceId:String, groupId:String, label:String, kind:"audio"}
<a name="line515"></a><div class="linenumber">515</div><div style="width:2em;display:inline-block"></div>* @example easyrtc.getAudioSinkList( function(list) {
<a name="line516"></a><div class="linenumber">516</div><div style="width:2em;display:inline-block"></div>* var i;
<a name="line517"></a><div class="linenumber">517</div><div style="width:2em;display:inline-block"></div>* for( i = 0; i < list.length; i++ ) {
<a name="line518"></a><div class="linenumber">518</div><div style="width:2em;display:inline-block"></div>* console.log("label=" + list[i].label + ", id= " + list[i].deviceId);
<a name="line519"></a><div class="linenumber">519</div><div style="width:2em;display:inline-block"></div>* }
<a name="line520"></a><div class="linenumber">520</div><div style="width:2em;display:inline-block"></div>* });
<a name="line521"></a><div class="linenumber">521</div><div style="width:2em;display:inline-block"></div>*/
<a name="line522"></a><div class="linenumber">522</div><div style="width:2em;display:inline-block"></div>this.getAudioSinkList = function(callback){
<a name="line523"></a><div class="linenumber">523</div><div style="width:3em;display:inline-block"></div>getSourceList(callback, "audiooutput");
<a name="line524"></a><div class="linenumber">524</div><div style="width:2em;display:inline-block"></div>};
<a name="line525"></a><div class="linenumber">525</div><div style="width:2em;display:inline-block"></div>/**
<a name="line526"></a><div class="linenumber">526</div><div style="width:2em;display:inline-block"></div>* Gets a list of the available audio sources (ie, microphones)
<a name="line527"></a><div class="linenumber">527</div><div style="width:2em;display:inline-block"></div>* @param {Function} callback receives list of {deviceId:String, groupId:String, label:String, kind:"audio"}
<a name="line528"></a><div class="linenumber">528</div><div style="width:2em;display:inline-block"></div>* @example easyrtc.getAudioSourceList( function(list) {
<a name="line529"></a><div class="linenumber">529</div><div style="width:2em;display:inline-block"></div>* var i;
<a name="line530"></a><div class="linenumber">530</div><div style="width:2em;display:inline-block"></div>* for( i = 0; i < list.length; i++ ) {
<a name="line531"></a><div class="linenumber">531</div><div style="width:2em;display:inline-block"></div>* console.log("label=" + list[i].label + ", id= " + list[i].deviceId);
<a name="line532"></a><div class="linenumber">532</div><div style="width:2em;display:inline-block"></div>* }
<a name="line533"></a><div class="linenumber">533</div><div style="width:2em;display:inline-block"></div>* });
<a name="line534"></a><div class="linenumber">534</div><div style="width:2em;display:inline-block"></div>*/
<a name="line535"></a><div class="linenumber">535</div><div style="width:2em;display:inline-block"></div>this.getAudioSourceList = function(callback){
<a name="line536"></a><div class="linenumber">536</div><div style="width:3em;display:inline-block"></div>getSourceList(callback, "audioinput");
<a name="line537"></a><div class="linenumber">537</div><div style="width:2em;display:inline-block"></div>};
<a name="line538"></a><div class="linenumber">538</div>
<a name="line539"></a><div class="linenumber">539</div><div style="width:2em;display:inline-block"></div>/**
<a name="line540"></a><div class="linenumber">540</div><div style="width:2em;display:inline-block"></div>* Gets a list of the available video sources (ie, cameras)
<a name="line541"></a><div class="linenumber">541</div><div style="width:2em;display:inline-block"></div>* @param {Function} callback receives list of {deviceId:String, groupId:String, label:String, kind:"video"}
<a name="line542"></a><div class="linenumber">542</div><div style="width:2em;display:inline-block"></div>* @example easyrtc.getVideoSourceList( function(list) {
<a name="line543"></a><div class="linenumber">543</div><div style="width:2em;display:inline-block"></div>* var i;
<a name="line544"></a><div class="linenumber">544</div><div style="width:2em;display:inline-block"></div>* for( i = 0; i < list.length; i++ ) {
<a name="line545"></a><div class="linenumber">545</div><div style="width:2em;display:inline-block"></div>* console.log("label=" + list[i].label + ", id= " + list[i].deviceId);
<a name="line546"></a><div class="linenumber">546</div><div style="width:2em;display:inline-block"></div>* }
<a name="line547"></a><div class="linenumber">547</div><div style="width:2em;display:inline-block"></div>* });
<a name="line548"></a><div class="linenumber">548</div><div style="width:2em;display:inline-block"></div>*/
<a name="line549"></a><div class="linenumber">549</div><div style="width:2em;display:inline-block"></div>this.getVideoSourceList = function(callback) {
<a name="line550"></a><div class="linenumber">550</div><div style="width:3em;display:inline-block"></div>getSourceList(callback, "videoinput");
<a name="line551"></a><div class="linenumber">551</div><div style="width:2em;display:inline-block"></div>};
<a name="line552"></a><div class="linenumber">552</div>
<a name="line553"></a><div class="linenumber">553</div>
<a name="line554"></a><div class="linenumber">554</div><div style="width:2em;display:inline-block"></div>/** @private */
<a name="line555"></a><div class="linenumber">555</div><div style="width:2em;display:inline-block"></div>var dataChannelName = "dc";
<a name="line556"></a><div class="linenumber">556</div><div style="width:2em;display:inline-block"></div>/** @private */
<a name="line557"></a><div class="linenumber">557</div><div style="width:2em;display:inline-block"></div>var oldConfig = {};
<a name="line558"></a><div class="linenumber">558</div><div style="width:2em;display:inline-block"></div>/** @private */
<a name="line559"></a><div class="linenumber">559</div><div style="width:2em;display:inline-block"></div>var offersPending = {};
<a name="line560"></a><div class="linenumber">560</div><div style="width:2em;display:inline-block"></div>/** @private */
<a name="line561"></a><div class="linenumber">561</div><div style="width:2em;display:inline-block"></div>var credential = null;
<a name="line562"></a><div class="linenumber">562</div>
<a name="line563"></a><div class="linenumber">563</div><div style="width:2em;display:inline-block"></div>/** @private */
<a name="line564"></a><div class="linenumber">564</div><div style="width:2em;display:inline-block"></div>self.audioEnabled = true;
<a name="line565"></a><div class="linenumber">565</div><div style="width:2em;display:inline-block"></div>/** @private */
<a name="line566"></a><div class="linenumber">566</div><div style="width:2em;display:inline-block"></div>self.videoEnabled = true;
<a name="line567"></a><div class="linenumber">567</div><div style="width:2em;display:inline-block"></div>/** @private */
<a name="line568"></a><div class="linenumber">568</div><div style="width:2em;display:inline-block"></div>this.debugPrinter = null;
<a name="line569"></a><div class="linenumber">569</div><div style="width:2em;display:inline-block"></div>/** Your easyrtcid */
<a name="line570"></a><div class="linenumber">570</div><div style="width:2em;display:inline-block"></div>this.myEasyrtcid = "";
<a name="line571"></a><div class="linenumber">571</div>
<a name="line572"></a><div class="linenumber">572</div><div style="width:2em;display:inline-block"></div>/** The height of the local media stream video in pixels. This field is set an indeterminate period
<a name="line573"></a><div class="linenumber">573</div><div style="width:2em;display:inline-block"></div>* of time after easyrtc.initMediaSource succeeds. Note: in actuality, the dimensions of a video stream
<a name="line574"></a><div class="linenumber">574</div><div style="width:2em;display:inline-block"></div>* change dynamically in response to external factors, you should check the videoWidth and videoHeight attributes
<a name="line575"></a><div class="linenumber">575</div><div style="width:2em;display:inline-block"></div>* of your video objects before you use them for pixel specific operations.
<a name="line576"></a><div class="linenumber">576</div><div style="width:2em;display:inline-block"></div>*/
<a name="line577"></a><div class="linenumber">577</div><div style="width:2em;display:inline-block"></div>this.nativeVideoHeight = 0;
<a name="line578"></a><div class="linenumber">578</div>
<a name="line579"></a><div class="linenumber">579</div><div style="width:2em;display:inline-block"></div>/** This constant determines how long (in bytes) a message can be before being split in chunks of that size.
<a name="line580"></a><div class="linenumber">580</div><div style="width:2em;display:inline-block"></div>* This is because there is a limitation of the length of the message you can send on the
<a name="line581"></a><div class="linenumber">581</div><div style="width:2em;display:inline-block"></div>* data channel between browsers.
<a name="line582"></a><div class="linenumber">582</div><div style="width:2em;display:inline-block"></div>*/
<a name="line583"></a><div class="linenumber">583</div><div style="width:2em;display:inline-block"></div>this.maxP2PMessageLength = 1000;
<a name="line584"></a><div class="linenumber">584</div>
<a name="line585"></a><div class="linenumber">585</div><div style="width:2em;display:inline-block"></div>/** The width of the local media stream video in pixels. This field is set an indeterminate period
<a name="line586"></a><div class="linenumber">586</div><div style="width:2em;display:inline-block"></div>* of time after easyrtc.initMediaSource succeeds. Note: in actuality, the dimensions of a video stream
<a name="line587"></a><div class="linenumber">587</div><div style="width:2em;display:inline-block"></div>* change dynamically in response to external factors, you should check the videoWidth and videoHeight attributes
<a name="line588"></a><div class="linenumber">588</div><div style="width:2em;display:inline-block"></div>* of your video objects before you use them for pixel specific operations.
<a name="line589"></a><div class="linenumber">589</div><div style="width:2em;display:inline-block"></div>*/
<a name="line590"></a><div class="linenumber">590</div><div style="width:2em;display:inline-block"></div>this.nativeVideoWidth = 0;
<a name="line591"></a><div class="linenumber">591</div>
<a name="line592"></a><div class="linenumber">592</div><div style="width:2em;display:inline-block"></div>/** The rooms the user is in. This only applies to room oriented applications and is set at the same
<a name="line593"></a><div class="linenumber">593</div><div style="width:2em;display:inline-block"></div>* time a token is received.
<a name="line594"></a><div class="linenumber">594</div><div style="width:2em;display:inline-block"></div>*/
<a name="line595"></a><div class="linenumber">595</div><div style="width:2em;display:inline-block"></div>this.roomJoin = {};
<a name="line596"></a><div class="linenumber">596</div>
<a name="line597"></a><div class="linenumber">597</div><div style="width:2em;display:inline-block"></div>/** Checks if the supplied string is a valid user name (standard identifier rules)
<a name="line598"></a><div class="linenumber">598</div><div style="width:2em;display:inline-block"></div>* @param {String} name
<a name="line599"></a><div class="linenumber">599</div><div style="width:2em;display:inline-block"></div>* @return {Boolean} true for a valid user name
<a name="line600"></a><div class="linenumber">600</div><div style="width:2em;display:inline-block"></div>* @example
<a name="line601"></a><div class="linenumber">601</div><div style="width:2em;display:inline-block"></div>* var name = document.getElementById('nameField').value;
<a name="line602"></a><div class="linenumber">602</div><div style="width:2em;display:inline-block"></div>* if( !easyrtc.isNameValid(name)){
<a name="line603"></a><div class="linenumber">603</div><div style="width:2em;display:inline-block"></div>* console.error("Bad user name");
<a name="line604"></a><div class="linenumber">604</div><div style="width:2em;display:inline-block"></div>* }
<a name="line605"></a><div class="linenumber">605</div><div style="width:2em;display:inline-block"></div>*/
<a name="line606"></a><div class="linenumber">606</div><div style="width:2em;display:inline-block"></div>this.isNameValid = function(name) {
<a name="line607"></a><div class="linenumber">607</div><div style="width:4em;display:inline-block"></div>return self.usernameRegExp.test(name);
<a name="line608"></a><div class="linenumber">608</div><div style="width:2em;display:inline-block"></div>};
<a name="line609"></a><div class="linenumber">609</div>
<a name="line610"></a><div class="linenumber">610</div><div style="width:2em;display:inline-block"></div>/**
<a name="line611"></a><div class="linenumber">611</div><div style="width:2em;display:inline-block"></div>* This function sets the name of the cookie that client side library will look for
<a name="line612"></a><div class="linenumber">612</div><div style="width:2em;display:inline-block"></div>* and transmit back to the server as it's easyrtcsid in the first message.
<a name="line613"></a><div class="linenumber">613</div><div style="width:2em;display:inline-block"></div>* @param {String} cookieId
<a name="line614"></a><div class="linenumber">614</div><div style="width:2em;display:inline-block"></div>*/
<a name="line615"></a><div class="linenumber">615</div><div style="width:2em;display:inline-block"></div>this.setCookieId = function(cookieId) {
<a name="line616"></a><div class="linenumber">616</div><div style="width:4em;display:inline-block"></div>self.cookieId = cookieId;
<a name="line617"></a><div class="linenumber">617</div><div style="width:2em;display:inline-block"></div>};
<a name="line618"></a><div class="linenumber">618</div>
<a name="line619"></a><div class="linenumber">619</div><div style="width:2em;display:inline-block"></div>/** @private */
<a name="line620"></a><div class="linenumber">620</div><div style="width:2em;display:inline-block"></div>this._desiredVideoProperties = {}; // default camera
<a name="line621"></a><div class="linenumber">621</div>
<a name="line622"></a><div class="linenumber">622</div><div style="width:2em;display:inline-block"></div>/**
<a name="line623"></a><div class="linenumber">623</div><div style="width:2em;display:inline-block"></div>* Specify particular video source. Call this before you call easyrtc.initMediaSource().
<a name="line624"></a><div class="linenumber">624</div><div style="width:2em;display:inline-block"></div>* @param {String} videoSrcId is a id value from one of the entries fetched by getVideoSourceList. null for default.
<a name="line625"></a><div class="linenumber">625</div><div style="width:2em;display:inline-block"></div>* @example easyrtc.setVideoSource( videoSrcId);
<a name="line626"></a><div class="linenumber">626</div><div style="width:2em;display:inline-block"></div>*/
<a name="line627"></a><div class="linenumber">627</div><div style="width:2em;display:inline-block"></div>this.setVideoSource = function(videoSrcId) {
<a name="line628"></a><div class="linenumber">628</div><div style="width:4em;display:inline-block"></div>self._desiredVideoProperties.videoSrcId = videoSrcId;
<a name="line629"></a><div class="linenumber">629</div><div style="width:4em;display:inline-block"></div>delete self._desiredVideoProperties.screenCapture;
<a name="line630"></a><div class="linenumber">630</div><div style="width:2em;display:inline-block"></div>};
<a name="line631"></a><div class="linenumber">631</div>
<a name="line632"></a><div class="linenumber">632</div><div style="width:2em;display:inline-block"></div>/** @private */
<a name="line633"></a><div class="linenumber">633</div><div style="width:2em;display:inline-block"></div>this._desiredAudioProperties = {}; // default camera
<a name="line634"></a><div class="linenumber">634</div>
<a name="line635"></a><div class="linenumber">635</div><div style="width:2em;display:inline-block"></div>/**
<a name="line636"></a><div class="linenumber">636</div><div style="width:2em;display:inline-block"></div>* Specify particular video source. Call this before you call easyrtc.initMediaSource().
<a name="line637"></a><div class="linenumber">637</div><div style="width:2em;display:inline-block"></div>* @param {String} audioSrcId is a id value from one of the entries fetched by getAudioSourceList. null for default.
<a name="line638"></a><div class="linenumber">638</div><div style="width:2em;display:inline-block"></div>* @example easyrtc.setAudioSource( audioSrcId);
<a name="line639"></a><div class="linenumber">639</div><div style="width:2em;display:inline-block"></div>*/
<a name="line640"></a><div class="linenumber">640</div><div style="width:2em;display:inline-block"></div>this.setAudioSource = function(audioSrcId) {
<a name="line641"></a><div class="linenumber">641</div><div style="width:4em;display:inline-block"></div>self._desiredAudioProperties.audioSrcId = audioSrcId;
<a name="line642"></a><div class="linenumber">642</div><div style="width:2em;display:inline-block"></div>};
<a name="line643"></a><div class="linenumber">643</div>
<a name="line644"></a><div class="linenumber">644</div><div style="width:2em;display:inline-block"></div>/** This function is used to set the dimensions of the local camera, usually to get HD.
<a name="line645"></a><div class="linenumber">645</div><div style="width:2em;display:inline-block"></div>* If called, it must be called before calling easyrtc.initMediaSource (explicitly or implicitly).
<a name="line646"></a><div class="linenumber">646</div><div style="width:2em;display:inline-block"></div>* assuming it is supported. If you don't pass any parameters, it will use default camera dimensions.
<a name="line647"></a><div class="linenumber">647</div><div style="width:2em;display:inline-block"></div>* @param {Number} width in pixels
<a name="line648"></a><div class="linenumber">648</div><div style="width:2em;display:inline-block"></div>* @param {Number} height in pixels
<a name="line649"></a><div class="linenumber">649</div><div style="width:2em;display:inline-block"></div>* @param {number} frameRate is optional
<a name="line650"></a><div class="linenumber">650</div><div style="width:2em;display:inline-block"></div>* @example
<a name="line651"></a><div class="linenumber">651</div><div style="width:2em;display:inline-block"></div>* easyrtc.setVideoDims(1280,720);
<a name="line652"></a><div class="linenumber">652</div><div style="width:2em;display:inline-block"></div>* @example
<a name="line653"></a><div class="linenumber">653</div><div style="width:2em;display:inline-block"></div>* easyrtc.setVideoDims();
<a name="line654"></a><div class="linenumber">654</div><div style="width:2em;display:inline-block"></div>*/
<a name="line655"></a><div class="linenumber">655</div><div style="width:2em;display:inline-block"></div>this.setVideoDims = function(width, height, frameRate) {
<a name="line656"></a><div class="linenumber">656</div><div style="width:4em;display:inline-block"></div>self._desiredVideoProperties.width = width;
<a name="line657"></a><div class="linenumber">657</div><div style="width:4em;display:inline-block"></div>self._desiredVideoProperties.height = height;
<a name="line658"></a><div class="linenumber">658</div><div style="width:4em;display:inline-block"></div>if (frameRate !== undefined) {
<a name="line659"></a><div class="linenumber">659</div><div style="width:6em;display:inline-block"></div>self._desiredVideoProperties.frameRate = frameRate;
<a name="line660"></a><div class="linenumber">660</div><div style="width:4em;display:inline-block"></div>}
<a name="line661"></a><div class="linenumber">661</div><div style="width:2em;display:inline-block"></div>};
<a name="line662"></a><div class="linenumber">662</div>
<a name="line663"></a><div class="linenumber">663</div><div style="width:2em;display:inline-block"></div>/** This function requests that screen capturing be used to provide the local media source
<a name="line664"></a><div class="linenumber">664</div><div style="width:2em;display:inline-block"></div>* rather than a webcam. If you have multiple screens, they are composited side by side.
<a name="line665"></a><div class="linenumber">665</div><div style="width:2em;display:inline-block"></div>* Note: this functionality is not supported by Firefox, has to be called before calling initMediaSource (or easyApp), we don't currently supply a way to
<a name="line666"></a><div class="linenumber">666</div><div style="width:2em;display:inline-block"></div>* turn it off (once it's on), only works if the website is hosted SSL (https), and the image quality is rather
<a name="line667"></a><div class="linenumber">667</div><div style="width:2em;display:inline-block"></div>* poor going across a network because it tries to transmit so much data. In short, screen sharing
<a name="line668"></a><div class="linenumber">668</div><div style="width:2em;display:inline-block"></div>* through WebRTC isn't worth using at this point, but it is provided here so people can try it out.
<a name="line669"></a><div class="linenumber">669</div><div style="width:2em;display:inline-block"></div>* @example
<a name="line670"></a><div class="linenumber">670</div><div style="width:2em;display:inline-block"></div>* easyrtc.setScreenCapture();
<a name="line671"></a><div class="linenumber">671</div><div style="width:2em;display:inline-block"></div>* @deprecated: use easyrtc.initScreenCapture (same parameters as easyrtc.initMediaSource.
<a name="line672"></a><div class="linenumber">672</div><div style="width:2em;display:inline-block"></div>*/
<a name="line673"></a><div class="linenumber">673</div><div style="width:2em;display:inline-block"></div>this.setScreenCapture = function(enableScreenCapture) {
<a name="line674"></a><div class="linenumber">674</div><div style="width:4em;display:inline-block"></div>self._desiredVideoProperties.screenCapture = (enableScreenCapture !== false);
<a name="line675"></a><div class="linenumber">675</div><div style="width:2em;display:inline-block"></div>};
<a name="line676"></a><div class="linenumber">676</div>
<a name="line677"></a><div class="linenumber">677</div><div style="width:2em;display:inline-block"></div>/**
<a name="line678"></a><div class="linenumber">678</div><div style="width:2em;display:inline-block"></div>* Builds the constraint object passed to getUserMedia.
<a name="line679"></a><div class="linenumber">679</div><div style="width:2em;display:inline-block"></div>* @returns {Object} mediaConstraints
<a name="line680"></a><div class="linenumber">680</div><div style="width:2em;display:inline-block"></div>*/
<a name="line681"></a><div class="linenumber">681</div><div style="width:2em;display:inline-block"></div>self.getUserMediaConstraints = function() {
<a name="line682"></a><div class="linenumber">682</div><div style="width:4em;display:inline-block"></div>var constraints = {};
<a name="line683"></a><div class="linenumber">683</div><div style="width:4em;display:inline-block"></div>//
<a name="line684"></a><div class="linenumber">684</div><div style="width:4em;display:inline-block"></div>// _presetMediaConstraints allow you to provide your own constraints to be used
<a name="line685"></a><div class="linenumber">685</div><div style="width:4em;display:inline-block"></div>// with initMediaSource.
<a name="line686"></a><div class="linenumber">686</div><div style="width:4em;display:inline-block"></div>//
<a name="line687"></a><div class="linenumber">687</div><div style="width:4em;display:inline-block"></div>if (self._presetMediaConstraints) {
<a name="line688"></a><div class="linenumber">688</div><div style="width:6em;display:inline-block"></div>constraints = self._presetMediaConstraints;
<a name="line689"></a><div class="linenumber">689</div><div style="width:6em;display:inline-block"></div>delete self._presetMediaConstraints;
<a name="line690"></a><div class="linenumber">690</div><div style="width:6em;display:inline-block"></div>return constraints;
<a name="line691"></a><div class="linenumber">691</div><div style="width:4em;display:inline-block"></div>}
<a name="line692"></a><div class="linenumber">692</div><div style="width:4em;display:inline-block"></div>else if (self._desiredVideoProperties.screenCapture) {
<a name="line693"></a><div class="linenumber">693</div><div style="width:6em;display:inline-block"></div>return {
<a name="line694"></a><div class="linenumber">694</div><div style="width:8em;display:inline-block"></div>video: {
<a name="line695"></a><div class="linenumber">695</div><div style="width:10em;display:inline-block"></div>mandatory: {
<a name="line696"></a><div class="linenumber">696</div><div style="width:12em;display:inline-block"></div>chromeMediaSource: 'screen',
<a name="line697"></a><div class="linenumber">697</div><div style="width:12em;display:inline-block"></div>maxWidth: screen.width,
<a name="line698"></a><div class="linenumber">698</div><div style="width:12em;display:inline-block"></div>maxHeight: screen.height,
<a name="line699"></a><div class="linenumber">699</div><div style="width:12em;display:inline-block"></div>minWidth: screen.width,
<a name="line700"></a><div class="linenumber">700</div><div style="width:12em;display:inline-block"></div>minHeight: screen.height,
<a name="line701"></a><div class="linenumber">701</div><div style="width:12em;display:inline-block"></div>minFrameRate: 1,
<a name="line702"></a><div class="linenumber">702</div><div style="width:12em;display:inline-block"></div>maxFrameRate: 5},
<a name="line703"></a><div class="linenumber">703</div><div style="width:10em;display:inline-block"></div>optional: []
<a name="line704"></a><div class="linenumber">704</div><div style="width:8em;display:inline-block"></div>},
<a name="line705"></a><div class="linenumber">705</div><div style="width:8em;display:inline-block"></div>audio: false
<a name="line706"></a><div class="linenumber">706</div><div style="width:6em;display:inline-block"></div>};
<a name="line707"></a><div class="linenumber">707</div><div style="width:4em;display:inline-block"></div>}
<a name="line708"></a><div class="linenumber">708</div><div style="width:4em;display:inline-block"></div>else if (!self.videoEnabled) {
<a name="line709"></a><div class="linenumber">709</div><div style="width:6em;display:inline-block"></div>constraints.video = false;
<a name="line710"></a><div class="linenumber">710</div><div style="width:4em;display:inline-block"></div>}
<a name="line711"></a><div class="linenumber">711</div><div style="width:4em;display:inline-block"></div>else {
<a name="line712"></a><div class="linenumber">712</div>
<a name="line713"></a><div class="linenumber">713</div><div style="width:6em;display:inline-block"></div>// Tested Firefox 49 and MS Edge require minFrameRate and maxFrameRate
<a name="line714"></a><div class="linenumber">714</div><div style="width:6em;display:inline-block"></div>// instead max,min,ideal that cause GetUserMedia failure.
<a name="line715"></a><div class="linenumber">715</div><div style="width:6em;display:inline-block"></div>// Until confirmed both browser support idea,max and min we need this.
<a name="line716"></a><div class="linenumber">716</div><div style="width:6em;display:inline-block"></div>if (
<a name="line717"></a><div class="linenumber">717</div><div style="width:8em;display:inline-block"></div>adapter && adapter.browserDetails &&
<a name="line718"></a><div class="linenumber">718</div><div style="width:10em;display:inline-block"></div>(adapter.browserDetails.browser === "firefox" || adapter.browserDetails.browser === "edge")
<a name="line719"></a><div class="linenumber">719</div><div style="width:6em;display:inline-block"></div>) {
<a name="line720"></a><div class="linenumber">720</div><div style="width:8em;display:inline-block"></div>constraints.video = {};
<a name="line721"></a><div class="linenumber">721</div><div style="width:8em;display:inline-block"></div>if (self._desiredVideoProperties.width) {
<a name="line722"></a><div class="linenumber">722</div><div style="width:10em;display:inline-block"></div>constraints.video.width = self._desiredVideoProperties.width;
<a name="line723"></a><div class="linenumber">723</div><div style="width:8em;display:inline-block"></div>}
<a name="line724"></a><div class="linenumber">724</div><div style="width:8em;display:inline-block"></div>if (self._desiredVideoProperties.height) {
<a name="line725"></a><div class="linenumber">725</div><div style="width:10em;display:inline-block"></div>constraints.video.height = self._desiredVideoProperties.height;
<a name="line726"></a><div class="linenumber">726</div><div style="width:8em;display:inline-block"></div>}
<a name="line727"></a><div class="linenumber">727</div><div style="width:8em;display:inline-block"></div>if (self._desiredVideoProperties.frameRate) {
<a name="line728"></a><div class="linenumber">728</div><div style="width:10em;display:inline-block"></div>constraints.video.frameRate = {
<a name="line729"></a><div class="linenumber">729</div><div style="width:12em;display:inline-block"></div>minFrameRate: self._desiredVideoProperties.frameRate,
<a name="line730"></a><div class="linenumber">730</div><div style="width:12em;display:inline-block"></div>maxFrameRate: self._desiredVideoProperties.frameRate
<a name="line731"></a><div class="linenumber">731</div><div style="width:10em;display:inline-block"></div>};
<a name="line732"></a><div class="linenumber">732</div><div style="width:8em;display:inline-block"></div>}
<a name="line733"></a><div class="linenumber">733</div><div style="width:8em;display:inline-block"></div>if (self._desiredVideoProperties.videoSrcId) {
<a name="line734"></a><div class="linenumber">734</div><div style="width:10em;display:inline-block"></div>constraints.video.deviceId = self._desiredVideoProperties.videoSrcId;
<a name="line735"></a><div class="linenumber">735</div><div style="width:8em;display:inline-block"></div>}
<a name="line736"></a><div class="linenumber">736</div>
<a name="line737"></a><div class="linenumber">737</div><div style="width:6em;display:inline-block"></div>// chrome and opera
<a name="line738"></a><div class="linenumber">738</div><div style="width:6em;display:inline-block"></div>} else {
<a name="line739"></a><div class="linenumber">739</div><div style="width:8em;display:inline-block"></div>constraints.video = {};
<a name="line740"></a><div class="linenumber">740</div><div style="width:8em;display:inline-block"></div>if (self._desiredVideoProperties.width) {
<a name="line741"></a><div class="linenumber">741</div><div style="width:10em;display:inline-block"></div>constraints.video.width = {
<a name="line742"></a><div class="linenumber">742</div><div style="width:12em;display:inline-block"></div>max: self._desiredVideoProperties.width,
<a name="line743"></a><div class="linenumber">743</div><div style="width:12em;display:inline-block"></div>min : self._desiredVideoProperties.width,
<a name="line744"></a><div class="linenumber">744</div><div style="width:12em;display:inline-block"></div>ideal : self._desiredVideoProperties.width
<a name="line745"></a><div class="linenumber">745</div><div style="width:10em;display:inline-block"></div>};
<a name="line746"></a><div class="linenumber">746</div><div style="width:8em;display:inline-block"></div>}
<a name="line747"></a><div class="linenumber">747</div><div style="width:8em;display:inline-block"></div>if (self._desiredVideoProperties.height) {
<a name="line748"></a><div class="linenumber">748</div><div style="width:10em;display:inline-block"></div>constraints.video.height = {
<a name="line749"></a><div class="linenumber">749</div><div style="width:12em;display:inline-block"></div>max: self._desiredVideoProperties.height,
<a name="line750"></a><div class="linenumber">750</div><div style="width:12em;display:inline-block"></div>min: self._desiredVideoProperties.height,
<a name="line751"></a><div class="linenumber">751</div><div style="width:12em;display:inline-block"></div>ideal: self._desiredVideoProperties.height
<a name="line752"></a><div class="linenumber">752</div><div style="width:10em;display:inline-block"></div>};
<a name="line753"></a><div class="linenumber">753</div><div style="width:8em;display:inline-block"></div>}
<a name="line754"></a><div class="linenumber">754</div><div style="width:8em;display:inline-block"></div>if (self._desiredVideoProperties.frameRate) {
<a name="line755"></a><div class="linenumber">755</div><div style="width:10em;display:inline-block"></div>constraints.video.frameRate = {
<a name="line756"></a><div class="linenumber">756</div><div style="width:12em;display:inline-block"></div>max: self._desiredVideoProperties.frameRate,
<a name="line757"></a><div class="linenumber">757</div><div style="width:12em;display:inline-block"></div>ideal: self._desiredVideoProperties.frameRate
<a name="line758"></a><div class="linenumber">758</div><div style="width:10em;display:inline-block"></div>};
<a name="line759"></a><div class="linenumber">759</div><div style="width:8em;display:inline-block"></div>}
<a name="line760"></a><div class="linenumber">760</div><div style="width:8em;display:inline-block"></div>if (self._desiredVideoProperties.videoSrcId) {
<a name="line761"></a><div class="linenumber">761</div><div style="width:10em;display:inline-block"></div>constraints.video.deviceId = self._desiredVideoProperties.videoSrcId;
<a name="line762"></a><div class="linenumber">762</div><div style="width:8em;display:inline-block"></div>}
<a name="line763"></a><div class="linenumber">763</div><div style="width:8em;display:inline-block"></div>// hack for opera
<a name="line764"></a><div class="linenumber">764</div><div style="width:8em;display:inline-block"></div>if (Object.keys(constraints.video).length === 0 ) {
<a name="line765"></a><div class="linenumber">765</div><div style="width:10em;display:inline-block"></div>constraints.video = true;
<a name="line766"></a><div class="linenumber">766</div><div style="width:8em;display:inline-block"></div>}
<a name="line767"></a><div class="linenumber">767</div><div style="width:6em;display:inline-block"></div>}
<a name="line768"></a><div class="linenumber">768</div><div style="width:4em;display:inline-block"></div>}
<a name="line769"></a><div class="linenumber">769</div>
<a name="line770"></a><div class="linenumber">770</div><div style="width:4em;display:inline-block"></div>if (!self.audioEnabled) {
<a name="line771"></a><div class="linenumber">771</div><div style="width:6em;display:inline-block"></div>constraints.audio = false;
<a name="line772"></a><div class="linenumber">772</div><div style="width:4em;display:inline-block"></div>}
<a name="line773"></a><div class="linenumber">773</div><div style="width:4em;display:inline-block"></div>else {
<a name="line774"></a><div class="linenumber">774</div><div style="width:6em;display:inline-block"></div>if (adapter && adapter.browserDetails && adapter.browserDetails.browser === "firefox") {
<a name="line775"></a><div class="linenumber">775</div><div style="width:8em;display:inline-block"></div>constraints.audio = {};
<a name="line776"></a><div class="linenumber">776</div><div style="width:8em;display:inline-block"></div>if (self._desiredAudioProperties.audioSrcId) {
<a name="line777"></a><div class="linenumber">777</div><div style="width:10em;display:inline-block"></div>constraints.audio.deviceId = self._desiredAudioProperties.audioSrcId;
<a name="line778"></a><div class="linenumber">778</div><div style="width:8em;display:inline-block"></div>}
<a name="line779"></a><div class="linenumber">779</div><div style="width:6em;display:inline-block"></div>}
<a name="line780"></a><div class="linenumber">780</div><div style="width:6em;display:inline-block"></div>else { // chrome and opera
<a name="line781"></a><div class="linenumber">781</div><div style="width:8em;display:inline-block"></div>constraints.audio = {mandatory: {}, optional: []};
<a name="line782"></a><div class="linenumber">782</div><div style="width:8em;display:inline-block"></div>if (self._desiredAudioProperties.audioSrcId) {
<a name="line783"></a><div class="linenumber">783</div><div style="width:10em;display:inline-block"></div>constraints.audio.optional = constraints.audio.optional || [];
<a name="line784"></a><div class="linenumber">784</div><div style="width:10em;display:inline-block"></div>constraints.audio.optional.push({deviceId: self._desiredAudioProperties.audioSrcId});
<a name="line785"></a><div class="linenumber">785</div><div style="width:8em;display:inline-block"></div>}
<a name="line786"></a><div class="linenumber">786</div><div style="width:6em;display:inline-block"></div>}
<a name="line787"></a><div class="linenumber">787</div><div style="width:4em;display:inline-block"></div>}
<a name="line788"></a><div class="linenumber">788</div><div style="width:4em;display:inline-block"></div>return constraints;
<a name="line789"></a><div class="linenumber">789</div><div style="width:2em;display:inline-block"></div>};
<a name="line790"></a><div class="linenumber">790</div>
<a name="line791"></a><div class="linenumber">791</div><div style="width:2em;display:inline-block"></div>/** Set the application name. Applications can only communicate with other applications
<a name="line792"></a><div class="linenumber">792</div><div style="width:2em;display:inline-block"></div>* that share the same API Key and application name. There is no predefined set of application
<a name="line793"></a><div class="linenumber">793</div><div style="width:2em;display:inline-block"></div>* names. Maximum length is
<a name="line794"></a><div class="linenumber">794</div><div style="width:2em;display:inline-block"></div>* @param {String} name
<a name="line795"></a><div class="linenumber">795</div><div style="width:2em;display:inline-block"></div>* @example
<a name="line796"></a><div class="linenumber">796</div><div style="width:2em;display:inline-block"></div>* easyrtc.setApplicationName('simpleAudioVideo');
<a name="line797"></a><div class="linenumber">797</div><div style="width:2em;display:inline-block"></div>*/
<a name="line798"></a><div class="linenumber">798</div><div style="width:2em;display:inline-block"></div>this.setApplicationName = function(name) {
<a name="line799"></a><div class="linenumber">799</div><div style="width:4em;display:inline-block"></div>self.applicationName = name;
<a name="line800"></a><div class="linenumber">800</div><div style="width:2em;display:inline-block"></div>};
<a name="line801"></a><div class="linenumber">801</div>
<a name="line802"></a><div class="linenumber">802</div><div style="width:2em;display:inline-block"></div>/** Enable or disable logging to the console.
<a name="line803"></a><div class="linenumber">803</div><div style="width:2em;display:inline-block"></div>* Note: if you want to control the printing of debug messages, override the
<a name="line804"></a><div class="linenumber">804</div><div style="width:2em;display:inline-block"></div>* easyrtc.debugPrinter variable with a function that takes a message string as it's argument.
<a name="line805"></a><div class="linenumber">805</div><div style="width:2em;display:inline-block"></div>* This is exactly what easyrtc.enableDebug does when it's enable argument is true.
<a name="line806"></a><div class="linenumber">806</div><div style="width:2em;display:inline-block"></div>* @param {Boolean} enable - true to turn on debugging, false to turn off debugging. Default is false.
<a name="line807"></a><div class="linenumber">807</div><div style="width:2em;display:inline-block"></div>* @example
<a name="line808"></a><div class="linenumber">808</div><div style="width:2em;display:inline-block"></div>* easyrtc.enableDebug(true);
<a name="line809"></a><div class="linenumber">809</div><div style="width:2em;display:inline-block"></div>*/
<a name="line810"></a><div class="linenumber">810</div><div style="width:2em;display:inline-block"></div>this.enableDebug = function(enable) {
<a name="line811"></a><div class="linenumber">811</div><div style="width:4em;display:inline-block"></div>if (enable) {
<a name="line812"></a><div class="linenumber">812</div><div style="width:6em;display:inline-block"></div>self.debugPrinter = function(message, obj) {
<a name="line813"></a><div class="linenumber">813</div><div style="width:8em;display:inline-block"></div>var now = new Date().toISOString();
<a name="line814"></a><div class="linenumber">814</div><div style="width:8em;display:inline-block"></div>var stackString = new Error().stack;
<a name="line815"></a><div class="linenumber">815</div><div style="width:8em;display:inline-block"></div>var srcLine = "location unknown";
<a name="line816"></a><div class="linenumber">816</div><div style="width:8em;display:inline-block"></div>if (stackString) {
<a name="line817"></a><div class="linenumber">817</div><div style="width:10em;display:inline-block"></div>var stackFrameStrings = stackString.split('\n');
<a name="line818"></a><div class="linenumber">818</div><div style="width:10em;display:inline-block"></div>srcLine = "";
<a name="line819"></a><div class="linenumber">819</div><div style="width:10em;display:inline-block"></div>if (stackFrameStrings.length >= 5) {
<a name="line820"></a><div class="linenumber">820</div><div style="width:12em;display:inline-block"></div>srcLine = stackFrameStrings[4];
<a name="line821"></a><div class="linenumber">821</div><div style="width:10em;display:inline-block"></div>}
<a name="line822"></a><div class="linenumber">822</div><div style="width:8em;display:inline-block"></div>}
<a name="line823"></a><div class="linenumber">823</div>
<a name="line824"></a><div class="linenumber">824</div><div style="width:8em;display:inline-block"></div>console.log("debug " + now + " : " + message + " [" + srcLine + "]");
<a name="line825"></a><div class="linenumber">825</div>
<a name="line826"></a><div class="linenumber">826</div><div style="width:8em;display:inline-block"></div>if (typeof obj !== 'undefined') {
<a name="line827"></a><div class="linenumber">827</div><div style="width:10em;display:inline-block"></div>console.log("debug " + now + " : ", obj);
<a name="line828"></a><div class="linenumber">828</div><div style="width:8em;display:inline-block"></div>}
<a name="line829"></a><div class="linenumber">829</div><div style="width:6em;display:inline-block"></div>};
<a name="line830"></a><div class="linenumber">830</div><div style="width:4em;display:inline-block"></div>}
<a name="line831"></a><div class="linenumber">831</div><div style="width:4em;display:inline-block"></div>else {
<a name="line832"></a><div class="linenumber">832</div><div style="width:6em;display:inline-block"></div>self.debugPrinter = null;
<a name="line833"></a><div class="linenumber">833</div><div style="width:4em;display:inline-block"></div>}
<a name="line834"></a><div class="linenumber">834</div><div style="width:2em;display:inline-block"></div>};
<a name="line835"></a><div class="linenumber">835</div>
<a name="line836"></a><div class="linenumber">836</div><div style="width:2em;display:inline-block"></div>/**
<a name="line837"></a><div class="linenumber">837</div><div style="width:2em;display:inline-block"></div>* Determines if the local browser supports WebRTC GetUserMedia (access to camera and microphone).
<a name="line838"></a><div class="linenumber">838</div><div style="width:2em;display:inline-block"></div>* @returns {Boolean} True getUserMedia is supported.
<a name="line839"></a><div class="linenumber">839</div><div style="width:2em;display:inline-block"></div>*/
<a name="line840"></a><div class="linenumber">840</div><div style="width:2em;display:inline-block"></div>this.supportsGetUserMedia = function() {
<a name="line841"></a><div class="linenumber">841</div><div style="width:4em;display:inline-block"></div>return typeof navigator.getUserMedia !== 'undefined';
<a name="line842"></a><div class="linenumber">842</div><div style="width:2em;display:inline-block"></div>};
<a name="line843"></a><div class="linenumber">843</div>
<a name="line844"></a><div class="linenumber">844</div><div style="width:2em;display:inline-block"></div>/**
<a name="line845"></a><div class="linenumber">845</div><div style="width:2em;display:inline-block"></div>* Determines if the local browser supports WebRTC Peer connections to the extent of being able to do video chats.
<a name="line846"></a><div class="linenumber">846</div><div style="width:2em;display:inline-block"></div>* @returns {Boolean} True if Peer connections are supported.
<a name="line847"></a><div class="linenumber">847</div><div style="width:2em;display:inline-block"></div>*/
<a name="line848"></a><div class="linenumber">848</div><div style="width:2em;display:inline-block"></div>this.supportsPeerConnections = function() {
<a name="line849"></a><div class="linenumber">849</div><div style="width:4em;display:inline-block"></div>return typeof RTCPeerConnection !== 'undefined';
<a name="line850"></a><div class="linenumber">850</div><div style="width:2em;display:inline-block"></div>};
<a name="line851"></a><div class="linenumber">851</div>
<a name="line852"></a><div class="linenumber">852</div><div style="width:2em;display:inline-block"></div>/** Determines whether the current browser supports the new data channels.
<a name="line853"></a><div class="linenumber">853</div><div style="width:2em;display:inline-block"></div>* EasyRTC will not open up connections with the old data channels.
<a name="line854"></a><div class="linenumber">854</div><div style="width:2em;display:inline-block"></div>* @returns {Boolean}
<a name="line855"></a><div class="linenumber">855</div><div style="width:2em;display:inline-block"></div>*/
<a name="line856"></a><div class="linenumber">856</div><div style="width:2em;display:inline-block"></div>this.supportsDataChannels = function() {
<a name="line857"></a><div class="linenumber">857</div>
<a name="line858"></a><div class="linenumber">858</div><div style="width:4em;display:inline-block"></div>var hasCreateDataChannel = false;
<a name="line859"></a><div class="linenumber">859</div>
<a name="line860"></a><div class="linenumber">860</div><div style="width:4em;display:inline-block"></div>if (self.supportsPeerConnections()) {
<a name="line861"></a><div class="linenumber">861</div><div style="width:6em;display:inline-block"></div>try {
<a name="line862"></a><div class="linenumber">862</div><div style="width:8em;display:inline-block"></div>var peer = new RTCPeerConnection({iceServers: []}, {});
<a name="line863"></a><div class="linenumber">863</div><div style="width:8em;display:inline-block"></div>hasCreateDataChannel = typeof peer.createDataChannel !== 'undefined';
<a name="line864"></a><div class="linenumber">864</div><div style="width:8em;display:inline-block"></div>peer.close();
<a name="line865"></a><div class="linenumber">865</div><div style="width:6em;display:inline-block"></div>}
<a name="line866"></a><div class="linenumber">866</div><div style="width:6em;display:inline-block"></div>catch (err) {
<a name="line867"></a><div class="linenumber">867</div><div style="width:8em;display:inline-block"></div>// Ignore possible RTCPeerConnection.close error
<a name="line868"></a><div class="linenumber">868</div><div style="width:8em;display:inline-block"></div>// hasCreateDataChannel should reflect the feature state still.
<a name="line869"></a><div class="linenumber">869</div><div style="width:6em;display:inline-block"></div>}
<a name="line870"></a><div class="linenumber">870</div><div style="width:4em;display:inline-block"></div>}
<a name="line871"></a><div class="linenumber">871</div>
<a name="line872"></a><div class="linenumber">872</div><div style="width:4em;display:inline-block"></div>return hasCreateDataChannel;
<a name="line873"></a><div class="linenumber">873</div><div style="width:2em;display:inline-block"></div>};
<a name="line874"></a><div class="linenumber">874</div>
<a name="line875"></a><div class="linenumber">875</div><div style="width:2em;display:inline-block"></div>/** @private */
<a name="line876"></a><div class="linenumber">876</div><div style="width:2em;display:inline-block"></div>//
<a name="line877"></a><div class="linenumber">877</div><div style="width:2em;display:inline-block"></div>// Experimental function to determine if statistics gathering is supported.
<a name="line878"></a><div class="linenumber">878</div><div style="width:2em;display:inline-block"></div>//
<a name="line879"></a><div class="linenumber">879</div><div style="width:2em;display:inline-block"></div>this.supportsStatistics = function() {
<a name="line880"></a><div class="linenumber">880</div>
<a name="line881"></a><div class="linenumber">881</div><div style="width:4em;display:inline-block"></div>var hasGetStats = false;
<a name="line882"></a><div class="linenumber">882</div>
<a name="line883"></a><div class="linenumber">883</div><div style="width:4em;display:inline-block"></div>if (self.supportsPeerConnections()) {
<a name="line884"></a><div class="linenumber">884</div><div style="width:6em;display:inline-block"></div>try {
<a name="line885"></a><div class="linenumber">885</div><div style="width:8em;display:inline-block"></div>var peer = new RTCPeerConnection({iceServers: []}, {});
<a name="line886"></a><div class="linenumber">886</div><div style="width:8em;display:inline-block"></div>hasGetStats = typeof peer.getStats !== 'undefined';
<a name="line887"></a><div class="linenumber">887</div><div style="width:8em;display:inline-block"></div>peer.close();
<a name="line888"></a><div class="linenumber">888</div><div style="width:6em;display:inline-block"></div>}
<a name="line889"></a><div class="linenumber">889</div><div style="width:6em;display:inline-block"></div>catch (err) {
<a name="line890"></a><div class="linenumber">890</div><div style="width:8em;display:inline-block"></div>// Ingore possible RTCPeerConnection.close error
<a name="line891"></a><div class="linenumber">891</div><div style="width:8em;display:inline-block"></div>// hasCreateDataChannel should reflect the feature state still.
<a name="line892"></a><div class="linenumber">892</div><div style="width:6em;display:inline-block"></div>}
<a name="line893"></a><div class="linenumber">893</div><div style="width:4em;display:inline-block"></div>}
<a name="line894"></a><div class="linenumber">894</div>
<a name="line895"></a><div class="linenumber">895</div><div style="width:4em;display:inline-block"></div>return hasGetStats;
<a name="line896"></a><div class="linenumber">896</div><div style="width:2em;display:inline-block"></div>};
<a name="line897"></a><div class="linenumber">897</div>
<a name="line898"></a><div class="linenumber">898</div><div style="width:2em;display:inline-block"></div>/** @private
<a name="line899"></a><div class="linenumber">899</div><div style="width:2em;display:inline-block"></div>* @param {Array} pc_config ice configuration array
<a name="line900"></a><div class="linenumber">900</div><div style="width:2em;display:inline-block"></div>* @param {Object} optionalStuff peer constraints.
<a name="line901"></a><div class="linenumber">901</div><div style="width:2em;display:inline-block"></div>*/
<a name="line902"></a><div class="linenumber">902</div><div style="width:2em;display:inline-block"></div>this.createRTCPeerConnection = function(pc_config, optionalStuff) {
<a name="line903"></a><div class="linenumber">903</div><div style="width:4em;display:inline-block"></div>if (self.supportsPeerConnections()) {
<a name="line904"></a><div class="linenumber">904</div><div style="width:6em;display:inline-block"></div>return new RTCPeerConnection(pc_config, optionalStuff);
<a name="line905"></a><div class="linenumber">905</div><div style="width:4em;display:inline-block"></div>}
<a name="line906"></a><div class="linenumber">906</div><div style="width:4em;display:inline-block"></div>else {
<a name="line907"></a><div class="linenumber">907</div><div style="width:6em;display:inline-block"></div>throw "Your browser doesn't support webRTC (RTCPeerConnection)";
<a name="line908"></a><div class="linenumber">908</div><div style="width:4em;display:inline-block"></div>}
<a name="line909"></a><div class="linenumber">909</div><div style="width:2em;display:inline-block"></div>};
<a name="line910"></a><div class="linenumber">910</div>
<a name="line911"></a><div class="linenumber">911</div><div style="width:2em;display:inline-block"></div>//
<a name="line912"></a><div class="linenumber">912</div><div style="width:2em;display:inline-block"></div>// this should really be part of adapter.js
<a name="line913"></a><div class="linenumber">913</div><div style="width:2em;display:inline-block"></div>// Versions of chrome < 31 don't support reliable data channels transport.
<a name="line914"></a><div class="linenumber">914</div><div style="width:2em;display:inline-block"></div>// Firefox does.
<a name="line915"></a><div class="linenumber">915</div><div style="width:2em;display:inline-block"></div>//
<a name="line916"></a><div class="linenumber">916</div><div style="width:2em;display:inline-block"></div>this.getDatachannelConstraints = function() {
<a name="line917"></a><div class="linenumber">917</div><div style="width:4em;display:inline-block"></div>return {
<a name="line918"></a><div class="linenumber">918</div><div style="width:6em;display:inline-block"></div>reliable: adapter && adapter.browserDetails &&
<a name="line919"></a><div class="linenumber">919</div><div style="width:8em;display:inline-block"></div>adapter.browserDetails.browser !== "chrome" &&
<a name="line920"></a><div class="linenumber">920</div><div style="width:10em;display:inline-block"></div>adapter.browserDetails.version < 31
<a name="line921"></a><div class="linenumber">921</div><div style="width:4em;display:inline-block"></div>};
<a name="line922"></a><div class="linenumber">922</div><div style="width:2em;display:inline-block"></div>};
<a name="line923"></a><div class="linenumber">923</div>
<a name="line924"></a><div class="linenumber">924</div><div style="width:2em;display:inline-block"></div>/** @private */
<a name="line925"></a><div class="linenumber">925</div><div style="width:2em;display:inline-block"></div>haveAudioVideo = {
<a name="line926"></a><div class="linenumber">926</div><div style="width:4em;display:inline-block"></div>audio: false,
<a name="line927"></a><div class="linenumber">927</div><div style="width:4em;display:inline-block"></div>video: false
<a name="line928"></a><div class="linenumber">928</div><div style="width:2em;display:inline-block"></div>};
<a name="line929"></a><div class="linenumber">929</div><div style="width:2em;display:inline-block"></div>/** @private */
<a name="line930"></a><div class="linenumber">930</div><div style="width:2em;display:inline-block"></div>var dataEnabled = false;
<a name="line931"></a><div class="linenumber">931</div><div style="width:2em;display:inline-block"></div>/** @private */
<a name="line932"></a><div class="linenumber">932</div><div style="width:2em;display:inline-block"></div>var serverPath = null; // this was null, but that was generating an error.
<a name="line933"></a><div class="linenumber">933</div><div style="width:2em;display:inline-block"></div>/** @private */
<a name="line934"></a><div class="linenumber">934</div><div style="width:2em;display:inline-block"></div>var roomOccupantListener = null;
<a name="line935"></a><div class="linenumber">935</div><div style="width:2em;display:inline-block"></div>/** @private */
<a name="line936"></a><div class="linenumber">936</div><div style="width:2em;display:inline-block"></div>var onDataChannelOpen = null;
<a name="line937"></a><div class="linenumber">937</div><div style="width:2em;display:inline-block"></div>/** @private */
<a name="line938"></a><div class="linenumber">938</div><div style="width:2em;display:inline-block"></div>var onDataChannelClose = null;
<a name="line939"></a><div class="linenumber">939</div><div style="width:2em;display:inline-block"></div>/** @private */
<a name="line940"></a><div class="linenumber">940</div><div style="width:2em;display:inline-block"></div>var lastLoggedInList = {};
<a name="line941"></a><div class="linenumber">941</div><div style="width:2em;display:inline-block"></div>/** @private */
<a name="line942"></a><div class="linenumber">942</div><div style="width:2em;display:inline-block"></div>var receivePeer = {msgTypes: {}};
<a name="line943"></a><div class="linenumber">943</div><div style="width:2em;display:inline-block"></div>/** @private */
<a name="line944"></a><div class="linenumber">944</div><div style="width:2em;display:inline-block"></div>var receiveServerCB = null;
<a name="line945"></a><div class="linenumber">945</div><div style="width:2em;display:inline-block"></div>/** @private */
<a name="line946"></a><div class="linenumber">946</div><div style="width:2em;display:inline-block"></div>// dummy placeholder for when we aren't connected
<a name="line947"></a><div class="linenumber">947</div><div style="width:2em;display:inline-block"></div>var updateConfigurationInfo = function() { };
<a name="line948"></a><div class="linenumber">948</div><div style="width:2em;display:inline-block"></div>/** @private */
<a name="line949"></a><div class="linenumber">949</div><div style="width:2em;display:inline-block"></div>//
<a name="line950"></a><div class="linenumber">950</div><div style="width:2em;display:inline-block"></div>//
<a name="line951"></a><div class="linenumber">951</div><div style="width:2em;display:inline-block"></div>// peerConns is a map from caller names to the below object structure
<a name="line952"></a><div class="linenumber">952</div><div style="width:2em;display:inline-block"></div>// { startedAV: boolean, -- true if we have traded audio/video streams
<a name="line953"></a><div class="linenumber">953</div><div style="width:2em;display:inline-block"></div>// dataChannelS: RTPDataChannel for outgoing messages if present
<a name="line954"></a><div class="linenumber">954</div><div style="width:2em;display:inline-block"></div>// dataChannelR: RTPDataChannel for incoming messages if present
<a name="line955"></a><div class="linenumber">955</div><div style="width:2em;display:inline-block"></div>// dataChannelReady: true if the data channel can be used for sending yet
<a name="line956"></a><div class="linenumber">956</div><div style="width:2em;display:inline-block"></div>// connectTime: timestamp when the connection was started
<a name="line957"></a><div class="linenumber">957</div><div style="width:2em;display:inline-block"></div>// sharingAudio: true if audio is being shared
<a name="line958"></a><div class="linenumber">958</div><div style="width:2em;display:inline-block"></div>// sharingVideo: true if video is being shared
<a name="line959"></a><div class="linenumber">959</div><div style="width:2em;display:inline-block"></div>// cancelled: temporarily true if a connection was cancelled by the peer asking to initiate it
<a name="line960"></a><div class="linenumber">960</div><div style="width:2em;display:inline-block"></div>// candidatesToSend: SDP candidates temporarily queued
<a name="line961"></a><div class="linenumber">961</div><div style="width:2em;display:inline-block"></div>// streamsAddedAcks: ack callbacks waiting for stream received messages
<a name="line962"></a><div class="linenumber">962</div><div style="width:2em;display:inline-block"></div>// pc: RTCPeerConnection
<a name="line963"></a><div class="linenumber">963</div><div style="width:2em;display:inline-block"></div>// mediaStream: mediaStream
<a name="line964"></a><div class="linenumber">964</div><div style="width:2em;display:inline-block"></div>// function callSuccessCB(string) - see the easyrtc.call documentation.
<a name="line965"></a><div class="linenumber">965</div><div style="width:2em;display:inline-block"></div>// function callFailureCB(errorCode, string) - see the easyrtc.call documentation.
<a name="line966"></a><div class="linenumber">966</div><div style="width:2em;display:inline-block"></div>// function wasAcceptedCB(boolean,string) - see the easyrtc.call documentation.
<a name="line967"></a><div class="linenumber">967</div><div style="width:2em;display:inline-block"></div>// }
<a name="line968"></a><div class="linenumber">968</div><div style="width:2em;display:inline-block"></div>//
<a name="line969"></a><div class="linenumber">969</div><div style="width:2em;display:inline-block"></div>var peerConns = {};
<a name="line970"></a><div class="linenumber">970</div><div style="width:2em;display:inline-block"></div>/** @private */
<a name="line971"></a><div class="linenumber">971</div><div style="width:2em;display:inline-block"></div>//
<a name="line972"></a><div class="linenumber">972</div><div style="width:2em;display:inline-block"></div>// a map keeping track of whom we've requested a call with so we don't try to
<a name="line973"></a><div class="linenumber">973</div><div style="width:2em;display:inline-block"></div>// call them a second time before they've responded.
<a name="line974"></a><div class="linenumber">974</div><div style="width:2em;display:inline-block"></div>//
<a name="line975"></a><div class="linenumber">975</div><div style="width:2em;display:inline-block"></div>var acceptancePending = {};
<a name="line976"></a><div class="linenumber">976</div>
<a name="line977"></a><div class="linenumber">977</div><div style="width:2em;display:inline-block"></div>/** @private
<a name="line978"></a><div class="linenumber">978</div><div style="width:2em;display:inline-block"></div>* @param {string} caller
<a name="line979"></a><div class="linenumber">979</div><div style="width:2em;display:inline-block"></div>* @param {Function} helper
<a name="line980"></a><div class="linenumber">980</div><div style="width:2em;display:inline-block"></div>*/
<a name="line981"></a><div class="linenumber">981</div><div style="width:2em;display:inline-block"></div>this.acceptCheck = function(caller, helper) {
<a name="line982"></a><div class="linenumber">982</div><div style="width:4em;display:inline-block"></div>helper(true);
<a name="line983"></a><div class="linenumber">983</div><div style="width:2em;display:inline-block"></div>};
<a name="line984"></a><div class="linenumber">984</div>
<a name="line985"></a><div class="linenumber">985</div><div style="width:2em;display:inline-block"></div>/** @private
<a name="line986"></a><div class="linenumber">986</div><div style="width:2em;display:inline-block"></div>* @param {string} easyrtcid
<a name="line987"></a><div class="linenumber">987</div><div style="width:2em;display:inline-block"></div>* @param {HTMLMediaStream} stream
<a name="line988"></a><div class="linenumber">988</div><div style="width:2em;display:inline-block"></div>*/
<a name="line989"></a><div class="linenumber">989</div><div style="width:2em;display:inline-block"></div>this.streamAcceptor = function(easyrtcid, stream) {
<a name="line990"></a><div class="linenumber">990</div><div style="width:2em;display:inline-block"></div>};
<a name="line991"></a><div class="linenumber">991</div>
<a name="line992"></a><div class="linenumber">992</div><div style="width:2em;display:inline-block"></div>/** @private
<a name="line993"></a><div class="linenumber">993</div><div style="width:2em;display:inline-block"></div>* @param {string} easyrtcid
<a name="line994"></a><div class="linenumber">994</div><div style="width:2em;display:inline-block"></div>*/
<a name="line995"></a><div class="linenumber">995</div><div style="width:2em;display:inline-block"></div>this.onStreamClosed = function(easyrtcid) {
<a name="line996"></a><div class="linenumber">996</div><div style="width:2em;display:inline-block"></div>};
<a name="line997"></a><div class="linenumber">997</div>
<a name="line998"></a><div class="linenumber">998</div><div style="width:2em;display:inline-block"></div>/** @private
<a name="line999"></a><div class="linenumber">999</div><div style="width:2em;display:inline-block"></div>* @param {string} easyrtcid
<a name="line1000"></a><div class="linenumber">1000</div><div style="width:2em;display:inline-block"></div>*/
<a name="line1001"></a><div class="linenumber">1001</div><div style="width:2em;display:inline-block"></div>this.callCancelled = function(easyrtcid) {
<a name="line1002"></a><div class="linenumber">1002</div><div style="width:2em;display:inline-block"></div>};
<a name="line1003"></a><div class="linenumber">1003</div>
<a name="line1004"></a><div class="linenumber">1004</div><div style="width:2em;display:inline-block"></div>/**
<a name="line1005"></a><div class="linenumber">1005</div><div style="width:2em;display:inline-block"></div>* This function gets the raw RTCPeerConnection for a given easyrtcid
<a name="line1006"></a><div class="linenumber">1006</div><div style="width:2em;display:inline-block"></div>* @param {String} easyrtcid
<a name="line1007"></a><div class="linenumber">1007</div><div style="width:2em;display:inline-block"></div>* @param {RTCPeerConnection} for that easyrtcid, or null if no connection exists
<a name="line1008"></a><div class="linenumber">1008</div><div style="width:2em;display:inline-block"></div>* Submitted by Fabian Bernhard.
<a name="line1009"></a><div class="linenumber">1009</div><div style="width:2em;display:inline-block"></div>*/
<a name="line1010"></a><div class="linenumber">1010</div><div style="width:2em;display:inline-block"></div>this.getPeerConnectionByUserId = function(userId) {
<a name="line1011"></a><div class="linenumber">1011</div><div style="width:4em;display:inline-block"></div>if (peerConns && peerConns[userId]) {
<a name="line1012"></a><div class="linenumber">1012</div><div style="width:6em;display:inline-block"></div>return peerConns[userId].pc;
<a name="line1013"></a><div class="linenumber">1013</div><div style="width:4em;display:inline-block"></div>}
<a name="line1014"></a><div class="linenumber">1014</div><div style="width:4em;display:inline-block"></div>return null;
<a name="line1015"></a><div class="linenumber">1015</div><div style="width:2em;display:inline-block"></div>};
<a name="line1016"></a><div class="linenumber">1016</div>
<a name="line1017"></a><div class="linenumber">1017</div>
<a name="line1018"></a><div class="linenumber">1018</div><div style="width:2em;display:inline-block"></div>var chromeStatsFilter = [
<a name="line1019"></a><div class="linenumber">1019</div><div style="width:4em;display:inline-block"></div>{
<a name="line1020"></a><div class="linenumber">1020</div><div style="width:6em;display:inline-block"></div>"googTransmitBitrate": "transmitBitRate",
<a name="line1021"></a><div class="linenumber">1021</div><div style="width:6em;display:inline-block"></div>"googActualEncBitrate": "encodeRate",
<a name="line1022"></a><div class="linenumber">1022</div><div style="width:6em;display:inline-block"></div>"googAvailableSendBandwidth": "availableSendRate"
<a name="line1023"></a><div class="linenumber">1023</div><div style="width:4em;display:inline-block"></div>},
<a name="line1024"></a><div class="linenumber">1024</div><div style="width:4em;display:inline-block"></div>{
<a name="line1025"></a><div class="linenumber">1025</div><div style="width:6em;display:inline-block"></div>"googCodecName": "audioCodec",
<a name="line1026"></a><div class="linenumber">1026</div><div style="width:6em;display:inline-block"></div>"googTypingNoiseState": "typingNoise",
<a name="line1027"></a><div class="linenumber">1027</div><div style="width:6em;display:inline-block"></div>"packetsSent": "audioPacketsSent",
<a name="line1028"></a><div class="linenumber">1028</div><div style="width:6em;display:inline-block"></div>"bytesSent": "audioBytesSent"
<a name="line1029"></a><div class="linenumber">1029</div><div style="width:4em;display:inline-block"></div>},
<a name="line1030"></a><div class="linenumber">1030</div><div style="width:4em;display:inline-block"></div>{
<a name="line1031"></a><div class="linenumber">1031</div><div style="width:6em;display:inline-block"></div>"googCodecName": "videoCodec",
<a name="line1032"></a><div class="linenumber">1032</div><div style="width:6em;display:inline-block"></div>"googFrameRateSent": "outFrameRate",
<a name="line1033"></a><div class="linenumber">1033</div><div style="width:6em;display:inline-block"></div>"packetsSent": "videoPacketsSent",
<a name="line1034"></a><div class="linenumber">1034</div><div style="width:6em;display:inline-block"></div>"bytesSent": "videoBytesSent"
<a name="line1035"></a><div class="linenumber">1035</div><div style="width:4em;display:inline-block"></div>},
<a name="line1036"></a><div class="linenumber">1036</div><div style="width:4em;display:inline-block"></div>{
<a name="line1037"></a><div class="linenumber">1037</div><div style="width:6em;display:inline-block"></div>"packetsLost": "videoPacketsLost",
<a name="line1038"></a><div class="linenumber">1038</div><div style="width:6em;display:inline-block"></div>"packetsReceived": "videoPacketsReceived",
<a name="line1039"></a><div class="linenumber">1039</div><div style="width:6em;display:inline-block"></div>"bytesReceived": "videoBytesReceived",
<a name="line1040"></a><div class="linenumber">1040</div><div style="width:6em;display:inline-block"></div>"googFrameRateOutput": "frameRateOut"
<a name="line1041"></a><div class="linenumber">1041</div><div style="width:4em;display:inline-block"></div>},
<a name="line1042"></a><div class="linenumber">1042</div><div style="width:4em;display:inline-block"></div>{
<a name="line1043"></a><div class="linenumber">1043</div><div style="width:6em;display:inline-block"></div>"packetsLost": "audioPacketsLost",
<a name="line1044"></a><div class="linenumber">1044</div><div style="width:6em;display:inline-block"></div>"packetsReceived": "audioPacketsReceived",
<a name="line1045"></a><div class="linenumber">1045</div><div style="width:6em;display:inline-block"></div>"bytesReceived": "audioBytesReceived",
<a name="line1046"></a><div class="linenumber">1046</div><div style="width:6em;display:inline-block"></div>"audioOutputLevel": "audioOutputLevel"
<a name="line1047"></a><div class="linenumber">1047</div><div style="width:4em;display:inline-block"></div>},
<a name="line1048"></a><div class="linenumber">1048</div><div style="width:4em;display:inline-block"></div>{
<a name="line1049"></a><div class="linenumber">1049</div><div style="width:6em;display:inline-block"></div>"googRemoteAddress": "remoteAddress",
<a name="line1050"></a><div class="linenumber">1050</div><div style="width:6em;display:inline-block"></div>"googActiveConnection": "activeConnection"
<a name="line1051"></a><div class="linenumber">1051</div><div style="width:4em;display:inline-block"></div>},
<a name="line1052"></a><div class="linenumber">1052</div><div style="width:4em;display:inline-block"></div>{
<a name="line1053"></a><div class="linenumber">1053</div><div style="width:6em;display:inline-block"></div>"audioInputLevel": "audioInputLevel"
<a name="line1054"></a><div class="linenumber">1054</div><div style="width:4em;display:inline-block"></div>}
<a name="line1055"></a><div class="linenumber">1055</div><div style="width:2em;display:inline-block"></div>];
<a name="line1056"></a><div class="linenumber">1056</div>
<a name="line1057"></a><div class="linenumber">1057</div><div style="width:2em;display:inline-block"></div>var firefoxStatsFilter = {
<a name="line1058"></a><div class="linenumber">1058</div><div style="width:4em;display:inline-block"></div>"outboundrtp_audio.bytesSent": "audioBytesSent",
<a name="line1059"></a><div class="linenumber">1059</div><div style="width:4em;display:inline-block"></div>"outboundrtp_video.bytesSent": "videoBytesSent",
<a name="line1060"></a><div class="linenumber">1060</div><div style="width:4em;display:inline-block"></div>"inboundrtp_video.bytesReceived": "videoBytesReceived",
<a name="line1061"></a><div class="linenumber">1061</div><div style="width:4em;display:inline-block"></div>"inboundrtp_audio.bytesReceived": "audioBytesReceived",
<a name="line1062"></a><div class="linenumber">1062</div><div style="width:4em;display:inline-block"></div>"outboundrtp_audio.packetsSent": "audioPacketsSent",
<a name="line1063"></a><div class="linenumber">1063</div><div style="width:4em;display:inline-block"></div>"outboundrtp_video.packetsSent": "videoPacketsSent",
<a name="line1064"></a><div class="linenumber">1064</div><div style="width:4em;display:inline-block"></div>"inboundrtp_video.packetsReceived": "videoPacketsReceived",
<a name="line1065"></a><div class="linenumber">1065</div><div style="width:4em;display:inline-block"></div>"inboundrtp_audio.packetsReceived": "audioPacketsReceived",
<a name="line1066"></a><div class="linenumber">1066</div><div style="width:4em;display:inline-block"></div>"inboundrtp_video.packetsLost": "videoPacketsLost",
<a name="line1067"></a><div class="linenumber">1067</div><div style="width:4em;display:inline-block"></div>"inboundrtp_audio.packetsLost": "audioPacketsLost",
<a name="line1068"></a><div class="linenumber">1068</div><div style="width:4em;display:inline-block"></div>"firefoxRemoteAddress": "remoteAddress"
<a name="line1069"></a><div class="linenumber">1069</div><div style="width:2em;display:inline-block"></div>};
<a name="line1070"></a><div class="linenumber">1070</div>
<a name="line1071"></a><div class="linenumber">1071</div><div style="width:2em;display:inline-block"></div>var standardStatsFilter = adapter && adapter.browserDetails &&
<a name="line1072"></a><div class="linenumber">1072</div><div style="width:8em;display:inline-block"></div>adapter.browserDetails.browser === "firefox" ? firefoxStatsFilter : chromeStatsFilter;
<a name="line1073"></a><div class="linenumber">1073</div>
<a name="line1074"></a><div class="linenumber">1074</div><div style="width:2em;display:inline-block"></div>function getFirefoxPeerStatistics(peerId, callback, filter) {
<a name="line1075"></a><div class="linenumber">1075</div>
<a name="line1076"></a><div class="linenumber">1076</div>
<a name="line1077"></a><div class="linenumber">1077</div><div style="width:4em;display:inline-block"></div>if (!peerConns[peerId]) {
<a name="line1078"></a><div class="linenumber">1078</div><div style="width:6em;display:inline-block"></div>callback(peerId, {"connected": false});
<a name="line1079"></a><div class="linenumber">1079</div><div style="width:4em;display:inline-block"></div>}
<a name="line1080"></a><div class="linenumber">1080</div><div style="width:4em;display:inline-block"></div>else if (peerConns[peerId].pc.getStats) {
<a name="line1081"></a><div class="linenumber">1081</div><div style="width:6em;display:inline-block"></div>peerConns[peerId].pc.getStats(null, function(stats) {
<a name="line1082"></a><div class="linenumber">1082</div><div style="width:8em;display:inline-block"></div>var items = {};
<a name="line1083"></a><div class="linenumber">1083</div><div style="width:8em;display:inline-block"></div>var candidates = {};
<a name="line1084"></a><div class="linenumber">1084</div><div style="width:8em;display:inline-block"></div>var activeId = null;
<a name="line1085"></a><div class="linenumber">1085</div><div style="width:8em;display:inline-block"></div>var srcKey;
<a name="line1086"></a><div class="linenumber">1086</div><div style="width:8em;display:inline-block"></div>//
<a name="line1087"></a><div class="linenumber">1087</div><div style="width:8em;display:inline-block"></div>// the stats objects has a group of entries. Each entry is either an rtcp, rtp entry
<a name="line1088"></a><div class="linenumber">1088</div><div style="width:8em;display:inline-block"></div>// or a candidate entry.
<a name="line1089"></a><div class="linenumber">1089</div><div style="width:8em;display:inline-block"></div>//
<a name="line1090"></a><div class="linenumber">1090</div><div style="width:8em;display:inline-block"></div>if (stats) {
<a name="line1091"></a><div class="linenumber">1091</div><div style="width:10em;display:inline-block"></div>stats.forEach(function(entry) {
<a name="line1092"></a><div class="linenumber">1092</div><div style="width:12em;display:inline-block"></div>var majorKey;
<a name="line1093"></a><div class="linenumber">1093</div><div style="width:12em;display:inline-block"></div>var subKey;
<a name="line1094"></a><div class="linenumber">1094</div><div style="width:12em;display:inline-block"></div>if (entry.type.match(/boundrtp/)) {
<a name="line1095"></a><div class="linenumber">1095</div><div style="width:14em;display:inline-block"></div>if (entry.id.match(/audio/)) {
<a name="line1096"></a><div class="linenumber">1096</div><div style="width:16em;display:inline-block"></div>majorKey = entry.type + "_audio";
<a name="line1097"></a><div class="linenumber">1097</div><div style="width:14em;display:inline-block"></div>}
<a name="line1098"></a><div class="linenumber">1098</div><div style="width:14em;display:inline-block"></div>else if (entry.id.match(/video/)) {
<a name="line1099"></a><div class="linenumber">1099</div><div style="width:16em;display:inline-block"></div>majorKey = entry.type + "_video";
<a name="line1100"></a><div class="linenumber">1100</div><div style="width:14em;display:inline-block"></div>}
<a name="line1101"></a><div class="linenumber">1101</div><div style="width:14em;display:inline-block"></div>else {
<a name="line1102"></a><div class="linenumber">1102</div><div style="width:16em;display:inline-block"></div>return;
<a name="line1103"></a><div class="linenumber">1103</div><div style="width:14em;display:inline-block"></div>}
<a name="line1104"></a><div class="linenumber">1104</div><div style="width:14em;display:inline-block"></div>for (subKey in entry) {
<a name="line1105"></a><div class="linenumber">1105</div><div style="width:16em;display:inline-block"></div>if (entry.hasOwnProperty(subKey)) {
<a name="line1106"></a><div class="linenumber">1106</div><div style="width:18em;display:inline-block"></div>items[majorKey + "." + subKey] = entry[subKey];
<a name="line1107"></a><div class="linenumber">1107</div><div style="width:16em;display:inline-block"></div>}
<a name="line1108"></a><div class="linenumber">1108</div><div style="width:14em;display:inline-block"></div>}
<a name="line1109"></a><div class="linenumber">1109</div><div style="width:12em;display:inline-block"></div>}
<a name="line1110"></a><div class="linenumber">1110</div><div style="width:12em;display:inline-block"></div>else {
<a name="line1111"></a><div class="linenumber">1111</div><div style="width:14em;display:inline-block"></div>if( entry.hasOwnProperty("ipAddress") && entry.id) {
<a name="line1112"></a><div class="linenumber">1112</div><div style="width:16em;display:inline-block"></div>candidates[entry.id] = entry.ipAddress + ":" +
<a name="line1113"></a><div class="linenumber">1113</div><div style="width:19em;display:inline-block"></div>entry.portNumber;
<a name="line1114"></a><div class="linenumber">1114</div><div style="width:14em;display:inline-block"></div>}
<a name="line1115"></a><div class="linenumber">1115</div><div style="width:14em;display:inline-block"></div>else if( entry.hasOwnProperty("selected") &&
<a name="line1116"></a><div class="linenumber">1116</div><div style="width:18em;display:inline-block"></div>entry.hasOwnProperty("remoteCandidateId") &&
<a name="line1117"></a><div class="linenumber">1117</div><div style="width:18em;display:inline-block"></div>entry.selected ) {
<a name="line1118"></a><div class="linenumber">1118</div><div style="width:16em;display:inline-block"></div>activeId = entry.remoteCandidateId;
<a name="line1119"></a><div class="linenumber">1119</div><div style="width:14em;display:inline-block"></div>}
<a name="line1120"></a><div class="linenumber">1120</div><div style="width:12em;display:inline-block"></div>}
<a name="line1121"></a><div class="linenumber">1121</div><div style="width:10em;display:inline-block"></div>});
<a name="line1122"></a><div class="linenumber">1122</div><div style="width:8em;display:inline-block"></div>}
<a name="line1123"></a><div class="linenumber">1123</div>
<a name="line1124"></a><div class="linenumber">1124</div><div style="width:8em;display:inline-block"></div>if( activeId ) {
<a name="line1125"></a><div class="linenumber">1125</div><div style="width:10em;display:inline-block"></div>items["firefoxRemoteAddress"] = candidates[activeId];
<a name="line1126"></a><div class="linenumber">1126</div><div style="width:8em;display:inline-block"></div>}
<a name="line1127"></a><div class="linenumber">1127</div><div style="width:8em;display:inline-block"></div>if (!filter) {
<a name="line1128"></a><div class="linenumber">1128</div><div style="width:10em;display:inline-block"></div>callback(peerId, items);
<a name="line1129"></a><div class="linenumber">1129</div><div style="width:8em;display:inline-block"></div>}
<a name="line1130"></a><div class="linenumber">1130</div><div style="width:8em;display:inline-block"></div>else {
<a name="line1131"></a><div class="linenumber">1131</div><div style="width:10em;display:inline-block"></div>var filteredItems = {};
<a name="line1132"></a><div class="linenumber">1132</div><div style="width:10em;display:inline-block"></div>for (srcKey in filter) {
<a name="line1133"></a><div class="linenumber">1133</div><div style="width:12em;display:inline-block"></div>if (filter.hasOwnProperty(srcKey) && items.hasOwnProperty(srcKey)) {
<a name="line1134"></a><div class="linenumber">1134</div><div style="width:14em;display:inline-block"></div>filteredItems[ filter[srcKey]] = items[srcKey];
<a name="line1135"></a><div class="linenumber">1135</div><div style="width:12em;display:inline-block"></div>}
<a name="line1136"></a><div class="linenumber">1136</div><div style="width:10em;display:inline-block"></div>}
<a name="line1137"></a><div class="linenumber">1137</div><div style="width:10em;display:inline-block"></div>callback(peerId, filteredItems);
<a name="line1138"></a><div class="linenumber">1138</div><div style="width:8em;display:inline-block"></div>}
<a name="line1139"></a><div class="linenumber">1139</div><div style="width:6em;display:inline-block"></div>},
<a name="line1140"></a><div class="linenumber">1140</div><div style="width:10em;display:inline-block"></div>function(error) {
<a name="line1141"></a><div class="linenumber">1141</div><div style="width:12em;display:inline-block"></div>logDebug("unable to get statistics");
<a name="line1142"></a><div class="linenumber">1142</div><div style="width:10em;display:inline-block"></div>});
<a name="line1143"></a><div class="linenumber">1143</div><div style="width:4em;display:inline-block"></div>}
<a name="line1144"></a><div class="linenumber">1144</div><div style="width:4em;display:inline-block"></div>else {
<a name="line1145"></a><div class="linenumber">1145</div><div style="width:6em;display:inline-block"></div>callback(peerId, {"statistics": self.getConstantString("statsNotSupported")});
<a name="line1146"></a><div class="linenumber">1146</div><div style="width:4em;display:inline-block"></div>}
<a name="line1147"></a><div class="linenumber">1147</div><div style="width:2em;display:inline-block"></div>}
<a name="line1148"></a><div class="linenumber">1148</div>
<a name="line1149"></a><div class="linenumber">1149</div><div style="width:2em;display:inline-block"></div>function getChromePeerStatistics(peerId, callback, filter) {
<a name="line1150"></a><div class="linenumber">1150</div>
<a name="line1151"></a><div class="linenumber">1151</div><div style="width:4em;display:inline-block"></div>if (!peerConns[peerId]) {
<a name="line1152"></a><div class="linenumber">1152</div><div style="width:6em;display:inline-block"></div>callback(peerId, {"connected": false});
<a name="line1153"></a><div class="linenumber">1153</div><div style="width:4em;display:inline-block"></div>}
<a name="line1154"></a><div class="linenumber">1154</div><div style="width:4em;display:inline-block"></div>else if (peerConns[peerId].pc.getStats) {
<a name="line1155"></a><div class="linenumber">1155</div>
<a name="line1156"></a><div class="linenumber">1156</div><div style="width:6em;display:inline-block"></div>peerConns[peerId].pc.getStats(function(stats) {
<a name="line1157"></a><div class="linenumber">1157</div>
<a name="line1158"></a><div class="linenumber">1158</div><div style="width:8em;display:inline-block"></div>var localStats = {};
<a name="line1159"></a><div class="linenumber">1159</div><div style="width:8em;display:inline-block"></div>var part, parts = stats.result();
<a name="line1160"></a><div class="linenumber">1160</div><div style="width:8em;display:inline-block"></div>var i, j;
<a name="line1161"></a><div class="linenumber">1161</div><div style="width:8em;display:inline-block"></div>var itemKeys;
<a name="line1162"></a><div class="linenumber">1162</div><div style="width:8em;display:inline-block"></div>var itemKey;
<a name="line1163"></a><div class="linenumber">1163</div><div style="width:8em;display:inline-block"></div>var names;
<a name="line1164"></a><div class="linenumber">1164</div><div style="width:8em;display:inline-block"></div>var userKey;
<a name="line1165"></a><div class="linenumber">1165</div><div style="width:8em;display:inline-block"></div>var partNames = [];
<a name="line1166"></a><div class="linenumber">1166</div><div style="width:8em;display:inline-block"></div>var partList;
<a name="line1167"></a><div class="linenumber">1167</div><div style="width:8em;display:inline-block"></div>var bestBytes = 0;
<a name="line1168"></a><div class="linenumber">1168</div><div style="width:8em;display:inline-block"></div>var bestI;
<a name="line1169"></a><div class="linenumber">1169</div><div style="width:8em;display:inline-block"></div>var turnAddress = null;
<a name="line1170"></a><div class="linenumber">1170</div><div style="width:8em;display:inline-block"></div>var hasActive, curReceived;
<a name="line1171"></a><div class="linenumber">1171</div><div style="width:8em;display:inline-block"></div>var localAddress, remoteAddress;
<a name="line1172"></a><div class="linenumber">1172</div><div style="width:8em;display:inline-block"></div>if (!filter) {
<a name="line1173"></a><div class="linenumber">1173</div><div style="width:10em;display:inline-block"></div>for (i = 0; i < parts.length; i++) {
<a name="line1174"></a><div class="linenumber">1174</div><div style="width:12em;display:inline-block"></div>names = parts[i].names();
<a name="line1175"></a><div class="linenumber">1175</div><div style="width:12em;display:inline-block"></div>for (j = 0; j < names.length; j++) {
<a name="line1176"></a><div class="linenumber">1176</div><div style="width:14em;display:inline-block"></div>itemKey = names[j];
<a name="line1177"></a><div class="linenumber">1177</div><div style="width:14em;display:inline-block"></div>localStats[parts[i].id + "." + itemKey] = parts[i].stat(itemKey);
<a name="line1178"></a><div class="linenumber">1178</div><div style="width:12em;display:inline-block"></div>}
<a name="line1179"></a><div class="linenumber">1179</div><div style="width:10em;display:inline-block"></div>}
<a name="line1180"></a><div class="linenumber">1180</div><div style="width:8em;display:inline-block"></div>}
<a name="line1181"></a><div class="linenumber">1181</div><div style="width:8em;display:inline-block"></div>else {
<a name="line1182"></a><div class="linenumber">1182</div><div style="width:10em;display:inline-block"></div>for (i = 0; i < parts.length; i++) {
<a name="line1183"></a><div class="linenumber">1183</div><div style="width:12em;display:inline-block"></div>partNames[i] = {};
<a name="line1184"></a><div class="linenumber">1184</div><div style="width:12em;display:inline-block"></div>//
<a name="line1185"></a><div class="linenumber">1185</div><div style="width:12em;display:inline-block"></div>// convert the names into a dictionary
<a name="line1186"></a><div class="linenumber">1186</div><div style="width:12em;display:inline-block"></div>//
<a name="line1187"></a><div class="linenumber">1187</div><div style="width:12em;display:inline-block"></div>names = parts[i].names();
<a name="line1188"></a><div class="linenumber">1188</div><div style="width:12em;display:inline-block"></div>for (j = 0; j < names.length; j++) {
<a name="line1189"></a><div class="linenumber">1189</div><div style="width:14em;display:inline-block"></div>partNames[i][names[j]] = true;
<a name="line1190"></a><div class="linenumber">1190</div><div style="width:12em;display:inline-block"></div>}
<a name="line1191"></a><div class="linenumber">1191</div>
<a name="line1192"></a><div class="linenumber">1192</div><div style="width:12em;display:inline-block"></div>//
<a name="line1193"></a><div class="linenumber">1193</div><div style="width:12em;display:inline-block"></div>// a chrome-firefox connection results in several activeConnections.
<a name="line1194"></a><div class="linenumber">1194</div><div style="width:12em;display:inline-block"></div>// we only want one, so we look for the one with the most data being received on it.
<a name="line1195"></a><div class="linenumber">1195</div><div style="width:12em;display:inline-block"></div>//
<a name="line1196"></a><div class="linenumber">1196</div><div style="width:12em;display:inline-block"></div>if (partNames[i].googRemoteAddress && partNames[i].googActiveConnection) {
<a name="line1197"></a><div class="linenumber">1197</div><div style="width:14em;display:inline-block"></div>hasActive = parts[i].stat("googActiveConnection");
<a name="line1198"></a><div class="linenumber">1198</div><div style="width:14em;display:inline-block"></div>if (hasActive === true || hasActive === "true") {
<a name="line1199"></a><div class="linenumber">1199</div><div style="width:16em;display:inline-block"></div>curReceived = parseInt(parts[i].stat("bytesReceived")) +
<a name="line1200"></a><div class="linenumber">1200</div><div style="width:20em;display:inline-block"></div>parseInt(parts[i].stat("bytesSent"));
<a name="line1201"></a><div class="linenumber">1201</div><div style="width:16em;display:inline-block"></div>if (curReceived > bestBytes) {
<a name="line1202"></a><div class="linenumber">1202</div><div style="width:18em;display:inline-block"></div>bestI = i;
<a name="line1203"></a><div class="linenumber">1203</div><div style="width:18em;display:inline-block"></div>bestBytes = curReceived;
<a name="line1204"></a><div class="linenumber">1204</div><div style="width:16em;display:inline-block"></div>}
<a name="line1205"></a><div class="linenumber">1205</div><div style="width:14em;display:inline-block"></div>}
<a name="line1206"></a><div class="linenumber">1206</div><div style="width:12em;display:inline-block"></div>}
<a name="line1207"></a><div class="linenumber">1207</div><div style="width:10em;display:inline-block"></div>}
<a name="line1208"></a><div class="linenumber">1208</div>
<a name="line1209"></a><div class="linenumber">1209</div><div style="width:10em;display:inline-block"></div>for (i = 0; i < parts.length; i++) {
<a name="line1210"></a><div class="linenumber">1210</div><div style="width:12em;display:inline-block"></div>//
<a name="line1211"></a><div class="linenumber">1211</div><div style="width:12em;display:inline-block"></div>// discard info from any inactive connection.
<a name="line1212"></a><div class="linenumber">1212</div><div style="width:12em;display:inline-block"></div>//
<a name="line1213"></a><div class="linenumber">1213</div><div style="width:12em;display:inline-block"></div>if (partNames[i].googActiveConnection) {
<a name="line1214"></a><div class="linenumber">1214</div><div style="width:14em;display:inline-block"></div>if (i !== bestI) {
<a name="line1215"></a><div class="linenumber">1215</div><div style="width:16em;display:inline-block"></div>partNames[i] = {};
<a name="line1216"></a><div class="linenumber">1216</div><div style="width:14em;display:inline-block"></div>}
<a name="line1217"></a><div class="linenumber">1217</div><div style="width:14em;display:inline-block"></div>else {
<a name="line1218"></a><div class="linenumber">1218</div><div style="width:16em;display:inline-block"></div>localAddress = parts[i].stat("googLocalAddress").split(":")[0];
<a name="line1219"></a><div class="linenumber">1219</div><div style="width:16em;display:inline-block"></div>remoteAddress = parts[i].stat("googRemoteAddress").split(":")[0];
<a name="line1220"></a><div class="linenumber">1220</div><div style="width:16em;display:inline-block"></div>if (self.isTurnServer(localAddress)) {
<a name="line1221"></a><div class="linenumber">1221</div><div style="width:18em;display:inline-block"></div>turnAddress = localAddress;
<a name="line1222"></a><div class="linenumber">1222</div><div style="width:16em;display:inline-block"></div>}
<a name="line1223"></a><div class="linenumber">1223</div><div style="width:16em;display:inline-block"></div>else if (self.isTurnServer(remoteAddress)) {
<a name="line1224"></a><div class="linenumber">1224</div><div style="width:18em;display:inline-block"></div>turnAddress = remoteAddress;
<a name="line1225"></a><div class="linenumber">1225</div><div style="width:16em;display:inline-block"></div>}
<a name="line1226"></a><div class="linenumber">1226</div><div style="width:14em;display:inline-block"></div>}
<a name="line1227"></a><div class="linenumber">1227</div><div style="width:12em;display:inline-block"></div>}
<a name="line1228"></a><div class="linenumber">1228</div><div style="width:10em;display:inline-block"></div>}
<a name="line1229"></a><div class="linenumber">1229</div>
<a name="line1230"></a><div class="linenumber">1230</div><div style="width:10em;display:inline-block"></div>for (i = 0; i < filter.length; i++) {
<a name="line1231"></a><div class="linenumber">1231</div><div style="width:12em;display:inline-block"></div>itemKeys = filter[i];
<a name="line1232"></a><div class="linenumber">1232</div><div style="width:12em;display:inline-block"></div>partList = [];
<a name="line1233"></a><div class="linenumber">1233</div><div style="width:12em;display:inline-block"></div>part = null;
<a name="line1234"></a><div class="linenumber">1234</div><div style="width:12em;display:inline-block"></div>for (j = 0; j < parts.length; j++) {
<a name="line1235"></a><div class="linenumber">1235</div><div style="width:14em;display:inline-block"></div>var fullMatch = true;
<a name="line1236"></a><div class="linenumber">1236</div><div style="width:14em;display:inline-block"></div>for (itemKey in itemKeys) {
<a name="line1237"></a><div class="linenumber">1237</div><div style="width:16em;display:inline-block"></div>if (itemKeys.hasOwnProperty(itemKey) && !partNames[j][itemKey]) {
<a name="line1238"></a><div class="linenumber">1238</div><div style="width:18em;display:inline-block"></div>fullMatch = false;
<a name="line1239"></a><div class="linenumber">1239</div><div style="width:18em;display:inline-block"></div>break;
<a name="line1240"></a><div class="linenumber">1240</div><div style="width:16em;display:inline-block"></div>}
<a name="line1241"></a><div class="linenumber">1241</div><div style="width:14em;display:inline-block"></div>}
<a name="line1242"></a><div class="linenumber">1242</div><div style="width:14em;display:inline-block"></div>if (fullMatch && parts[j]) {
<a name="line1243"></a><div class="linenumber">1243</div><div style="width:16em;display:inline-block"></div>partList.push(parts[j]);
<a name="line1244"></a><div class="linenumber">1244</div><div style="width:14em;display:inline-block"></div>}
<a name="line1245"></a><div class="linenumber">1245</div><div style="width:12em;display:inline-block"></div>}
<a name="line1246"></a><div class="linenumber">1246</div><div style="width:12em;display:inline-block"></div>if (partList.length === 1) {
<a name="line1247"></a><div class="linenumber">1247</div><div style="width:14em;display:inline-block"></div>for (j = 0; j < partList.length; j++) {
<a name="line1248"></a><div class="linenumber">1248</div><div style="width:16em;display:inline-block"></div>part = partList[j];
<a name="line1249"></a><div class="linenumber">1249</div><div style="width:16em;display:inline-block"></div>if (part) {
<a name="line1250"></a><div class="linenumber">1250</div><div style="width:18em;display:inline-block"></div>for (itemKey in itemKeys) {
<a name="line1251"></a><div class="linenumber">1251</div><div style="width:20em;display:inline-block"></div>if (itemKeys.hasOwnProperty(itemKey)) {
<a name="line1252"></a><div class="linenumber">1252</div><div style="width:22em;display:inline-block"></div>userKey = itemKeys[itemKey];
<a name="line1253"></a><div class="linenumber">1253</div><div style="width:22em;display:inline-block"></div>localStats[userKey] = part.stat(itemKey);
<a name="line1254"></a><div class="linenumber">1254</div><div style="width:20em;display:inline-block"></div>}
<a name="line1255"></a><div class="linenumber">1255</div><div style="width:18em;display:inline-block"></div>}
<a name="line1256"></a><div class="linenumber">1256</div><div style="width:16em;display:inline-block"></div>}
<a name="line1257"></a><div class="linenumber">1257</div><div style="width:14em;display:inline-block"></div>}
<a name="line1258"></a><div class="linenumber">1258</div><div style="width:12em;display:inline-block"></div>}
<a name="line1259"></a><div class="linenumber">1259</div><div style="width:12em;display:inline-block"></div>else if (partList.length > 1) {
<a name="line1260"></a><div class="linenumber">1260</div><div style="width:14em;display:inline-block"></div>for (itemKey in itemKeys) {
<a name="line1261"></a><div class="linenumber">1261</div><div style="width:16em;display:inline-block"></div>if (itemKeys.hasOwnProperty(itemKey)) {
<a name="line1262"></a><div class="linenumber">1262</div><div style="width:18em;display:inline-block"></div>localStats[itemKeys[itemKey]] = [];
<a name="line1263"></a><div class="linenumber">1263</div><div style="width:16em;display:inline-block"></div>}
<a name="line1264"></a><div class="linenumber">1264</div><div style="width:14em;display:inline-block"></div>}
<a name="line1265"></a><div class="linenumber">1265</div><div style="width:14em;display:inline-block"></div>for (j = 0; j < partList.length; j++) {
<a name="line1266"></a><div class="linenumber">1266</div><div style="width:16em;display:inline-block"></div>part = partList[j];
<a name="line1267"></a><div class="linenumber">1267</div><div style="width:18em;display:inline-block"></div>for (itemKey in itemKeys) {
<a name="line1268"></a><div class="linenumber">1268</div><div style="width:20em;display:inline-block"></div>if (itemKeys.hasOwnProperty(itemKey)) {
<a name="line1269"></a><div class="linenumber">1269</div><div style="width:22em;display:inline-block"></div>userKey = itemKeys[itemKey];
<a name="line1270"></a><div class="linenumber">1270</div><div style="width:22em;display:inline-block"></div>localStats[userKey].push(part.stat(itemKey));
<a name="line1271"></a><div class="linenumber">1271</div><div style="width:20em;display:inline-block"></div>}
<a name="line1272"></a><div class="linenumber">1272</div><div style="width:18em;display:inline-block"></div>}
<a name="line1273"></a><div class="linenumber">1273</div><div style="width:14em;display:inline-block"></div>}
<a name="line1274"></a><div class="linenumber">1274</div><div style="width:12em;display:inline-block"></div>}
<a name="line1275"></a><div class="linenumber">1275</div><div style="width:10em;display:inline-block"></div>}
<a name="line1276"></a><div class="linenumber">1276</div><div style="width:8em;display:inline-block"></div>}
<a name="line1277"></a><div class="linenumber">1277</div>
<a name="line1278"></a><div class="linenumber">1278</div><div style="width:8em;display:inline-block"></div>if (localStats.remoteAddress && turnAddress) {
<a name="line1279"></a><div class="linenumber">1279</div><div style="width:10em;display:inline-block"></div>localStats.remoteAddress = turnAddress;
<a name="line1280"></a><div class="linenumber">1280</div><div style="width:8em;display:inline-block"></div>}
<a name="line1281"></a><div class="linenumber">1281</div><div style="width:8em;display:inline-block"></div>callback(peerId, localStats);
<a name="line1282"></a><div class="linenumber">1282</div><div style="width:6em;display:inline-block"></div>});
<a name="line1283"></a><div class="linenumber">1283</div><div style="width:4em;display:inline-block"></div>}
<a name="line1284"></a><div class="linenumber">1284</div><div style="width:4em;display:inline-block"></div>else {
<a name="line1285"></a><div class="linenumber">1285</div><div style="width:6em;display:inline-block"></div>callback(peerId, {"statistics": self.getConstantString("statsNotSupported")});
<a name="line1286"></a><div class="linenumber">1286</div><div style="width:4em;display:inline-block"></div>}
<a name="line1287"></a><div class="linenumber">1287</div><div style="width:2em;display:inline-block"></div>}
<a name="line1288"></a><div class="linenumber">1288</div>
<a name="line1289"></a><div class="linenumber">1289</div><div style="width:2em;display:inline-block"></div>/**
<a name="line1290"></a><div class="linenumber">1290</div><div style="width:2em;display:inline-block"></div>* This function gets the statistics for a particular peer connection.
<a name="line1291"></a><div class="linenumber">1291</div><div style="width:2em;display:inline-block"></div>* @param {String} easyrtcid
<a name="line1292"></a><div class="linenumber">1292</div><div style="width:2em;display:inline-block"></div>* @param {Function} callback gets the easyrtcid for the peer and a map of {userDefinedKey: value}. If there is no peer connection to easyrtcid, then the map will
<a name="line1293"></a><div class="linenumber">1293</div><div style="width:2em;display:inline-block"></div>* have a value of {connected:false}.
<a name="line1294"></a><div class="linenumber">1294</div><div style="width:2em;display:inline-block"></div>* @param {Object} filter depends on whether Chrome or Firefox is used. See the default filters for guidance.
<a name="line1295"></a><div class="linenumber">1295</div><div style="width:2em;display:inline-block"></div>* It is still experimental.
<a name="line1296"></a><div class="linenumber">1296</div><div style="width:2em;display:inline-block"></div>*/
<a name="line1297"></a><div class="linenumber">1297</div><div style="width:2em;display:inline-block"></div>this.getPeerStatistics = function(easyrtcid, callback, filter) {
<a name="line1298"></a><div class="linenumber">1298</div><div style="width:4em;display:inline-block"></div>if (
<a name="line1299"></a><div class="linenumber">1299</div><div style="width:6em;display:inline-block"></div>adapter && adapter.browserDetails &&
<a name="line1300"></a><div class="linenumber">1300</div><div style="width:8em;display:inline-block"></div>adapter.browserDetails.browser === "firefox"
<a name="line1301"></a><div class="linenumber">1301</div><div style="width:4em;display:inline-block"></div>) {
<a name="line1302"></a><div class="linenumber">1302</div><div style="width:6em;display:inline-block"></div>getFirefoxPeerStatistics(easyrtcid, callback, filter);
<a name="line1303"></a><div class="linenumber">1303</div><div style="width:4em;display:inline-block"></div>}
<a name="line1304"></a><div class="linenumber">1304</div><div style="width:4em;display:inline-block"></div>else {
<a name="line1305"></a><div class="linenumber">1305</div><div style="width:6em;display:inline-block"></div>getChromePeerStatistics(easyrtcid, callback, filter);
<a name="line1306"></a><div class="linenumber">1306</div><div style="width:4em;display:inline-block"></div>}
<a name="line1307"></a><div class="linenumber">1307</div><div style="width:2em;display:inline-block"></div>};
<a name="line1308"></a><div class="linenumber">1308</div>
<a name="line1309"></a><div class="linenumber">1309</div><div style="width:2em;display:inline-block"></div>/**
<a name="line1310"></a><div class="linenumber">1310</div><div style="width:2em;display:inline-block"></div>* @private
<a name="line1311"></a><div class="linenumber">1311</div><div style="width:2em;display:inline-block"></div>* @param roomName
<a name="line1312"></a><div class="linenumber">1312</div><div style="width:2em;display:inline-block"></div>* @param fields
<a name="line1313"></a><div class="linenumber">1313</div><div style="width:2em;display:inline-block"></div>*/
<a name="line1314"></a><div class="linenumber">1314</div><div style="width:2em;display:inline-block"></div>function sendRoomApiFields(roomName, fields) {
<a name="line1315"></a><div class="linenumber">1315</div><div style="width:4em;display:inline-block"></div>var fieldAsString = JSON.stringify(fields);
<a name="line1316"></a><div class="linenumber">1316</div><div style="width:4em;display:inline-block"></div>JSON.parse(fieldAsString);
<a name="line1317"></a><div class="linenumber">1317</div><div style="width:4em;display:inline-block"></div>var dataToShip = {
<a name="line1318"></a><div class="linenumber">1318</div><div style="width:6em;display:inline-block"></div>msgType: "setRoomApiField",
<a name="line1319"></a><div class="linenumber">1319</div><div style="width:6em;display:inline-block"></div>msgData: {
<a name="line1320"></a><div class="linenumber">1320</div><div style="width:8em;display:inline-block"></div>setRoomApiField: {
<a name="line1321"></a><div class="linenumber">1321</div><div style="width:10em;display:inline-block"></div>roomName: roomName,
<a name="line1322"></a><div class="linenumber">1322</div><div style="width:10em;display:inline-block"></div>field: fields
<a name="line1323"></a><div class="linenumber">1323</div><div style="width:8em;display:inline-block"></div>}
<a name="line1324"></a><div class="linenumber">1324</div><div style="width:6em;display:inline-block"></div>}
<a name="line1325"></a><div class="linenumber">1325</div><div style="width:4em;display:inline-block"></div>};
<a name="line1326"></a><div class="linenumber">1326</div><div style="width:4em;display:inline-block"></div>self.webSocket.json.emit("easyrtcCmd", dataToShip,
<a name="line1327"></a><div class="linenumber">1327</div><div style="width:8em;display:inline-block"></div>function(ackMsg) {
<a name="line1328"></a><div class="linenumber">1328</div><div style="width:10em;display:inline-block"></div>if (ackMsg.msgType === "error") {
<a name="line1329"></a><div class="linenumber">1329</div><div style="width:12em;display:inline-block"></div>self.showError(ackMsg.msgData.errorCode, ackMsg.msgData.errorText);
<a name="line1330"></a><div class="linenumber">1330</div><div style="width:10em;display:inline-block"></div>}
<a name="line1331"></a><div class="linenumber">1331</div><div style="width:8em;display:inline-block"></div>}
<a name="line1332"></a><div class="linenumber">1332</div><div style="width:4em;display:inline-block"></div>);
<a name="line1333"></a><div class="linenumber">1333</div><div style="width:2em;display:inline-block"></div>}
<a name="line1334"></a><div class="linenumber">1334</div>
<a name="line1335"></a><div class="linenumber">1335</div><div style="width:2em;display:inline-block"></div>/** @private */
<a name="line1336"></a><div class="linenumber">1336</div><div style="width:2em;display:inline-block"></div>var roomApiFieldTimer = null;
<a name="line1337"></a><div class="linenumber">1337</div>
<a name="line1338"></a><div class="linenumber">1338</div><div style="width:2em;display:inline-block"></div>/**
<a name="line1339"></a><div class="linenumber">1339</div><div style="width:2em;display:inline-block"></div>* @private
<a name="line1340"></a><div class="linenumber">1340</div><div style="width:2em;display:inline-block"></div>* @param {String} roomName
<a name="line1341"></a><div class="linenumber">1341</div><div style="width:2em;display:inline-block"></div>*/
<a name="line1342"></a><div class="linenumber">1342</div><div style="width:2em;display:inline-block"></div>function enqueueSendRoomApi(roomName) {
<a name="line1343"></a><div class="linenumber">1343</div><div style="width:4em;display:inline-block"></div>//
<a name="line1344"></a><div class="linenumber">1344</div><div style="width:4em;display:inline-block"></div>// Rather than issue the send request immediately, we set a timer so we can accumulate other
<a name="line1345"></a><div class="linenumber">1345</div><div style="width:4em;display:inline-block"></div>// calls
<a name="line1346"></a><div class="linenumber">1346</div><div style="width:4em;display:inline-block"></div>//
<a name="line1347"></a><div class="linenumber">1347</div><div style="width:4em;display:inline-block"></div>if (roomApiFieldTimer) {
<a name="line1348"></a><div class="linenumber">1348</div><div style="width:6em;display:inline-block"></div>clearTimeout(roomApiFieldTimer);
<a name="line1349"></a><div class="linenumber">1349</div><div style="width:4em;display:inline-block"></div>}
<a name="line1350"></a><div class="linenumber">1350</div><div style="width:4em;display:inline-block"></div>roomApiFieldTimer = setTimeout(function() {
<a name="line1351"></a><div class="linenumber">1351</div><div style="width:6em;display:inline-block"></div>sendRoomApiFields(roomName, self._roomApiFields[roomName]);
<a name="line1352"></a><div class="linenumber">1352</div><div style="width:6em;display:inline-block"></div>roomApiFieldTimer = null;
<a name="line1353"></a><div class="linenumber">1353</div><div style="width:4em;display:inline-block"></div>}, 10);
<a name="line1354"></a><div class="linenumber">1354</div><div style="width:2em;display:inline-block"></div>}
<a name="line1355"></a><div class="linenumber">1355</div>
<a name="line1356"></a><div class="linenumber">1356</div><div style="width:2em;display:inline-block"></div>/** Provide a set of application defined fields that will be part of this instances
<a name="line1357"></a><div class="linenumber">1357</div><div style="width:2em;display:inline-block"></div>* configuration information. This data will get sent to other peers via the websocket
<a name="line1358"></a><div class="linenumber">1358</div><div style="width:2em;display:inline-block"></div>* path.
<a name="line1359"></a><div class="linenumber">1359</div><div style="width:2em;display:inline-block"></div>* @param {String} roomName - the room the field is attached to.
<a name="line1360"></a><div class="linenumber">1360</div><div style="width:2em;display:inline-block"></div>* @param {String} fieldName - the name of the field.
<a name="line1361"></a><div class="linenumber">1361</div><div style="width:2em;display:inline-block"></div>* @param {Object} fieldValue - the value of the field.
<a name="line1362"></a><div class="linenumber">1362</div><div style="width:2em;display:inline-block"></div>* @example
<a name="line1363"></a><div class="linenumber">1363</div><div style="width:2em;display:inline-block"></div>* easyrtc.setRoomApiField("trekkieRoom", "favorite_alien", "Mr Spock");
<a name="line1364"></a><div class="linenumber">1364</div><div style="width:2em;display:inline-block"></div>* easyrtc.setRoomOccupantListener( function(roomName, list){
<a name="line1365"></a><div class="linenumber">1365</div><div style="width:2em;display:inline-block"></div>* for( var i in list ){
<a name="line1366"></a><div class="linenumber">1366</div><div style="width:2em;display:inline-block"></div>* console.log("easyrtcid=" + i + " favorite alien is " + list[i].apiFields.favorite_alien);
<a name="line1367"></a><div class="linenumber">1367</div><div style="width:2em;display:inline-block"></div>* }
<a name="line1368"></a><div class="linenumber">1368</div><div style="width:2em;display:inline-block"></div>* });
<a name="line1369"></a><div class="linenumber">1369</div><div style="width:2em;display:inline-block"></div>*/
<a name="line1370"></a><div class="linenumber">1370</div><div style="width:2em;display:inline-block"></div>this.setRoomApiField = function(roomName, fieldName, fieldValue) {
<a name="line1371"></a><div class="linenumber">1371</div><div style="width:4em;display:inline-block"></div>//
<a name="line1372"></a><div class="linenumber">1372</div><div style="width:4em;display:inline-block"></div>// if we're not connected yet, we'll just cache the fields until we are.
<a name="line1373"></a><div class="linenumber">1373</div><div style="width:4em;display:inline-block"></div>//
<a name="line1374"></a><div class="linenumber">1374</div><div style="width:4em;display:inline-block"></div>if (!self._roomApiFields) {
<a name="line1375"></a><div class="linenumber">1375</div><div style="width:6em;display:inline-block"></div>self._roomApiFields = {};
<a name="line1376"></a><div class="linenumber">1376</div><div style="width:4em;display:inline-block"></div>}
<a name="line1377"></a><div class="linenumber">1377</div><div style="width:4em;display:inline-block"></div>if (!fieldName && !fieldValue) {
<a name="line1378"></a><div class="linenumber">1378</div><div style="width:6em;display:inline-block"></div>delete self._roomApiFields[roomName];
<a name="line1379"></a><div class="linenumber">1379</div><div style="width:6em;display:inline-block"></div>return;
<a name="line1380"></a><div class="linenumber">1380</div><div style="width:4em;display:inline-block"></div>}
<a name="line1381"></a><div class="linenumber">1381</div>
<a name="line1382"></a><div class="linenumber">1382</div><div style="width:4em;display:inline-block"></div>if (!self._roomApiFields[roomName]) {
<a name="line1383"></a><div class="linenumber">1383</div><div style="width:6em;display:inline-block"></div>self._roomApiFields[roomName] = {};
<a name="line1384"></a><div class="linenumber">1384</div><div style="width:4em;display:inline-block"></div>}
<a name="line1385"></a><div class="linenumber">1385</div><div style="width:4em;display:inline-block"></div>if (fieldValue !== undefined && fieldValue !== null) {
<a name="line1386"></a><div class="linenumber">1386</div><div style="width:6em;display:inline-block"></div>if (typeof fieldValue === "object") {
<a name="line1387"></a><div class="linenumber">1387</div><div style="width:8em;display:inline-block"></div>try {
<a name="line1388"></a><div class="linenumber">1388</div><div style="width:10em;display:inline-block"></div>JSON.stringify(fieldValue);
<a name="line1389"></a><div class="linenumber">1389</div><div style="width:8em;display:inline-block"></div>}
<a name="line1390"></a><div class="linenumber">1390</div><div style="width:8em;display:inline-block"></div>catch (jsonError) {
<a name="line1391"></a><div class="linenumber">1391</div><div style="width:10em;display:inline-block"></div>self.showError(self.errCodes.DEVELOPER_ERR, "easyrtc.setRoomApiField passed bad object ");
<a name="line1392"></a><div class="linenumber">1392</div><div style="width:10em;display:inline-block"></div>return;
<a name="line1393"></a><div class="linenumber">1393</div><div style="width:8em;display:inline-block"></div>}
<a name="line1394"></a><div class="linenumber">1394</div><div style="width:6em;display:inline-block"></div>}
<a name="line1395"></a><div class="linenumber">1395</div><div style="width:6em;display:inline-block"></div>self._roomApiFields[roomName][fieldName] = {fieldName: fieldName, fieldValue: fieldValue};
<a name="line1396"></a><div class="linenumber">1396</div><div style="width:4em;display:inline-block"></div>}
<a name="line1397"></a><div class="linenumber">1397</div><div style="width:4em;display:inline-block"></div>else {
<a name="line1398"></a><div class="linenumber">1398</div><div style="width:6em;display:inline-block"></div>delete self._roomApiFields[roomName][fieldName];
<a name="line1399"></a><div class="linenumber">1399</div><div style="width:4em;display:inline-block"></div>}
<a name="line1400"></a><div class="linenumber">1400</div><div style="width:4em;display:inline-block"></div>if (self.webSocketConnected) {
<a name="line1401"></a><div class="linenumber">1401</div><div style="width:6em;display:inline-block"></div>enqueueSendRoomApi(roomName);
<a name="line1402"></a><div class="linenumber">1402</div><div style="width:4em;display:inline-block"></div>}
<a name="line1403"></a><div class="linenumber">1403</div><div style="width:2em;display:inline-block"></div>};
<a name="line1404"></a><div class="linenumber">1404</div>
<a name="line1405"></a><div class="linenumber">1405</div><div style="width:2em;display:inline-block"></div>/**
<a name="line1406"></a><div class="linenumber">1406</div><div style="width:2em;display:inline-block"></div>* Default error reporting function. The default implementation displays error messages
<a name="line1407"></a><div class="linenumber">1407</div><div style="width:2em;display:inline-block"></div>* in a programmatically created div with the id easyrtcErrorDialog. The div has title
<a name="line1408"></a><div class="linenumber">1408</div><div style="width:2em;display:inline-block"></div>* component with a class name of easyrtcErrorDialog_title. The error messages get added to a
<a name="line1409"></a><div class="linenumber">1409</div><div style="width:2em;display:inline-block"></div>* container with the id easyrtcErrorDialog_body. Each error message is a text node inside a div
<a name="line1410"></a><div class="linenumber">1410</div><div style="width:2em;display:inline-block"></div>* with a class of easyrtcErrorDialog_element. There is an "okay" button with the className of easyrtcErrorDialog_okayButton.
<a name="line1411"></a><div class="linenumber">1411</div><div style="width:2em;display:inline-block"></div>* @param {String} messageCode An error message code
<a name="line1412"></a><div class="linenumber">1412</div><div style="width:2em;display:inline-block"></div>* @param {String} message the error message text without any markup.
<a name="line1413"></a><div class="linenumber">1413</div><div style="width:2em;display:inline-block"></div>* @example
<a name="line1414"></a><div class="linenumber">1414</div><div style="width:2em;display:inline-block"></div>* easyrtc.showError("BAD_NAME", "Invalid username");
<a name="line1415"></a><div class="linenumber">1415</div><div style="width:2em;display:inline-block"></div>*/
<a name="line1416"></a><div class="linenumber">1416</div><div style="width:2em;display:inline-block"></div>this.showError = function(messageCode, message) {
<a name="line1417"></a><div class="linenumber">1417</div><div style="width:4em;display:inline-block"></div>self.onError({errorCode: messageCode, errorText: message});
<a name="line1418"></a><div class="linenumber">1418</div><div style="width:2em;display:inline-block"></div>};
<a name="line1419"></a><div class="linenumber">1419</div>
<a name="line1420"></a><div class="linenumber">1420</div><div style="width:2em;display:inline-block"></div>/**
<a name="line1421"></a><div class="linenumber">1421</div><div style="width:2em;display:inline-block"></div>* @private
<a name="line1422"></a><div class="linenumber">1422</div><div style="width:2em;display:inline-block"></div>* @param errorObject
<a name="line1423"></a><div class="linenumber">1423</div><div style="width:2em;display:inline-block"></div>*/
<a name="line1424"></a><div class="linenumber">1424</div><div style="width:2em;display:inline-block"></div>this.onError = function(errorObject) {
<a name="line1425"></a><div class="linenumber">1425</div><div style="width:4em;display:inline-block"></div>logDebug("saw error " + errorObject.errorText);
<a name="line1426"></a><div class="linenumber">1426</div>
<a name="line1427"></a><div class="linenumber">1427</div><div style="width:4em;display:inline-block"></div>var errorDiv = document.getElementById('easyrtcErrorDialog');
<a name="line1428"></a><div class="linenumber">1428</div><div style="width:4em;display:inline-block"></div>var errorBody;
<a name="line1429"></a><div class="linenumber">1429</div><div style="width:4em;display:inline-block"></div>if (!errorDiv) {
<a name="line1430"></a><div class="linenumber">1430</div><div style="width:6em;display:inline-block"></div>errorDiv = document.createElement("div");
<a name="line1431"></a><div class="linenumber">1431</div><div style="width:6em;display:inline-block"></div>errorDiv.id = 'easyrtcErrorDialog';
<a name="line1432"></a><div class="linenumber">1432</div><div style="width:6em;display:inline-block"></div>var title = document.createElement("div");
<a name="line1433"></a><div class="linenumber">1433</div><div style="width:6em;display:inline-block"></div>title.innerHTML = "Error messages";
<a name="line1434"></a><div class="linenumber">1434</div><div style="width:6em;display:inline-block"></div>title.className = "easyrtcErrorDialog_title";
<a name="line1435"></a><div class="linenumber">1435</div><div style="width:6em;display:inline-block"></div>errorDiv.appendChild(title);
<a name="line1436"></a><div class="linenumber">1436</div><div style="width:6em;display:inline-block"></div>errorBody = document.createElement("div");
<a name="line1437"></a><div class="linenumber">1437</div><div style="width:6em;display:inline-block"></div>errorBody.id = "easyrtcErrorDialog_body";
<a name="line1438"></a><div class="linenumber">1438</div><div style="width:6em;display:inline-block"></div>errorDiv.appendChild(errorBody);
<a name="line1439"></a><div class="linenumber">1439</div><div style="width:6em;display:inline-block"></div>var clearButton = document.createElement("button");
<a name="line1440"></a><div class="linenumber">1440</div><div style="width:6em;display:inline-block"></div>clearButton.appendChild(document.createTextNode("Okay"));
<a name="line1441"></a><div class="linenumber">1441</div><div style="width:6em;display:inline-block"></div>clearButton.className = "easyrtcErrorDialog_okayButton";
<a name="line1442"></a><div class="linenumber">1442</div><div style="width:6em;display:inline-block"></div>clearButton.onclick = function() {
<a name="line1443"></a><div class="linenumber">1443</div><div style="width:8em;display:inline-block"></div>errorBody.innerHTML = ""; // remove all inner nodes
<a name="line1444"></a><div class="linenumber">1444</div><div style="width:8em;display:inline-block"></div>errorDiv.style.display = "none";
<a name="line1445"></a><div class="linenumber">1445</div><div style="width:6em;display:inline-block"></div>};
<a name="line1446"></a><div class="linenumber">1446</div><div style="width:6em;display:inline-block"></div>errorDiv.appendChild(clearButton);
<a name="line1447"></a><div class="linenumber">1447</div><div style="width:6em;display:inline-block"></div>document.body.appendChild(errorDiv);
<a name="line1448"></a><div class="linenumber">1448</div><div style="width:4em;display:inline-block"></div>}
<a name="line1449"></a><div class="linenumber">1449</div>
<a name="line1450"></a><div class="linenumber">1450</div><div style="width:4em;display:inline-block"></div>errorBody = document.getElementById("easyrtcErrorDialog_body");
<a name="line1451"></a><div class="linenumber">1451</div><div style="width:4em;display:inline-block"></div>var messageNode = document.createElement("div");
<a name="line1452"></a><div class="linenumber">1452</div><div style="width:4em;display:inline-block"></div>messageNode.className = 'easyrtcErrorDialog_element';
<a name="line1453"></a><div class="linenumber">1453</div><div style="width:4em;display:inline-block"></div>messageNode.appendChild(document.createTextNode(errorObject.errorText));
<a name="line1454"></a><div class="linenumber">1454</div><div style="width:4em;display:inline-block"></div>errorBody.appendChild(messageNode);
<a name="line1455"></a><div class="linenumber">1455</div><div style="width:4em;display:inline-block"></div>errorDiv.style.display = "block";
<a name="line1456"></a><div class="linenumber">1456</div><div style="width:2em;display:inline-block"></div>};
<a name="line1457"></a><div class="linenumber">1457</div>
<a name="line1458"></a><div class="linenumber">1458</div><div style="width:2em;display:inline-block"></div>/** @private
<a name="line1459"></a><div class="linenumber">1459</div><div style="width:2em;display:inline-block"></div>* @param mediaStream */
<a name="line1460"></a><div class="linenumber">1460</div><div style="width:2em;display:inline-block"></div>//
<a name="line1461"></a><div class="linenumber">1461</div><div style="width:2em;display:inline-block"></div>// easyrtc.createObjectURL builds a URL from a media stream.
<a name="line1462"></a><div class="linenumber">1462</div><div style="width:2em;display:inline-block"></div>// Arguments:
<a name="line1463"></a><div class="linenumber">1463</div><div style="width:2em;display:inline-block"></div>// mediaStream - a media stream object.
<a name="line1464"></a><div class="linenumber">1464</div><div style="width:2em;display:inline-block"></div>// The video object in Chrome expects a URL.
<a name="line1465"></a><div class="linenumber">1465</div><div style="width:2em;display:inline-block"></div>//
<a name="line1466"></a><div class="linenumber">1466</div><div style="width:2em;display:inline-block"></div>this.createObjectURL = function(mediaStream) {
<a name="line1467"></a><div class="linenumber">1467</div><div style="width:4em;display:inline-block"></div>var errMessage;
<a name="line1468"></a><div class="linenumber">1468</div><div style="width:4em;display:inline-block"></div>if (window.URL && window.URL.createObjectURL) {
<a name="line1469"></a><div class="linenumber">1469</div><div style="width:6em;display:inline-block"></div>return window.URL.createObjectURL(mediaStream);
<a name="line1470"></a><div class="linenumber">1470</div><div style="width:4em;display:inline-block"></div>}
<a name="line1471"></a><div class="linenumber">1471</div><div style="width:4em;display:inline-block"></div>else if (window.webkitURL && window.webkitURL.createObjectURL) {
<a name="line1472"></a><div class="linenumber">1472</div><div style="width:6em;display:inline-block"></div>return window.webkit.createObjectURL(mediaStream);
<a name="line1473"></a><div class="linenumber">1473</div><div style="width:4em;display:inline-block"></div>}
<a name="line1474"></a><div class="linenumber">1474</div><div style="width:4em;display:inline-block"></div>else {
<a name="line1475"></a><div class="linenumber">1475</div><div style="width:6em;display:inline-block"></div>errMessage = "Your browsers does not support URL.createObjectURL.";
<a name="line1476"></a><div class="linenumber">1476</div><div style="width:6em;display:inline-block"></div>logDebug("saw exception " + errMessage);
<a name="line1477"></a><div class="linenumber">1477</div><div style="width:6em;display:inline-block"></div>throw errMessage;
<a name="line1478"></a><div class="linenumber">1478</div><div style="width:4em;display:inline-block"></div>}
<a name="line1479"></a><div class="linenumber">1479</div><div style="width:2em;display:inline-block"></div>};
<a name="line1480"></a><div class="linenumber">1480</div>
<a name="line1481"></a><div class="linenumber">1481</div><div style="width:2em;display:inline-block"></div>/**
<a name="line1482"></a><div class="linenumber">1482</div><div style="width:2em;display:inline-block"></div>* A convenience function to ensure that a string doesn't have symbols that will be interpreted by HTML.
<a name="line1483"></a><div class="linenumber">1483</div><div style="width:2em;display:inline-block"></div>* @param {String} idString
<a name="line1484"></a><div class="linenumber">1484</div><div style="width:2em;display:inline-block"></div>* @return {String} The cleaned string.
<a name="line1485"></a><div class="linenumber">1485</div><div style="width:2em;display:inline-block"></div>* @example
<a name="line1486"></a><div class="linenumber">1486</div><div style="width:2em;display:inline-block"></div>* console.log( easyrtc.cleanId('&hello'));
<a name="line1487"></a><div class="linenumber">1487</div><div style="width:2em;display:inline-block"></div>*/
<a name="line1488"></a><div class="linenumber">1488</div><div style="width:2em;display:inline-block"></div>this.cleanId = function(idString) {
<a name="line1489"></a><div class="linenumber">1489</div><div style="width:4em;display:inline-block"></div>var MAP = {
<a name="line1490"></a><div class="linenumber">1490</div><div style="width:6em;display:inline-block"></div>'&': '&amp;',
<a name="line1491"></a><div class="linenumber">1491</div><div style="width:6em;display:inline-block"></div>'<': '&lt;',
<a name="line1492"></a><div class="linenumber">1492</div><div style="width:6em;display:inline-block"></div>'>': '&gt;'
<a name="line1493"></a><div class="linenumber">1493</div><div style="width:4em;display:inline-block"></div>};
<a name="line1494"></a><div class="linenumber">1494</div><div style="width:4em;display:inline-block"></div>return idString.replace(/[&<>]/g, function(c) {
<a name="line1495"></a><div class="linenumber">1495</div><div style="width:6em;display:inline-block"></div>return MAP[c];
<a name="line1496"></a><div class="linenumber">1496</div><div style="width:4em;display:inline-block"></div>});
<a name="line1497"></a><div class="linenumber">1497</div><div style="width:2em;display:inline-block"></div>};
<a name="line1498"></a><div class="linenumber">1498</div>
<a name="line1499"></a><div class="linenumber">1499</div><div style="width:2em;display:inline-block"></div>/**
<a name="line1500"></a><div class="linenumber">1500</div><div style="width:2em;display:inline-block"></div>* Set a callback that will be invoked when the application enters or leaves a room.
<a name="line1501"></a><div class="linenumber">1501</div><div style="width:2em;display:inline-block"></div>* @param {Function} handler - the first parameter is true for entering a room, false for leaving a room. The second parameter is the room name.
<a name="line1502"></a><div class="linenumber">1502</div><div style="width:2em;display:inline-block"></div>* @example
<a name="line1503"></a><div class="linenumber">1503</div><div style="width:2em;display:inline-block"></div>* easyrtc.setRoomEntryListener(function(entry, roomName){
<a name="line1504"></a><div class="linenumber">1504</div><div style="width:2em;display:inline-block"></div>* if( entry ){
<a name="line1505"></a><div class="linenumber">1505</div><div style="width:2em;display:inline-block"></div>* console.log("entering room " + roomName);
<a name="line1506"></a><div class="linenumber">1506</div><div style="width:2em;display:inline-block"></div>* }
<a name="line1507"></a><div class="linenumber">1507</div><div style="width:2em;display:inline-block"></div>* else{
<a name="line1508"></a><div class="linenumber">1508</div><div style="width:2em;display:inline-block"></div>* console.log("leaving room " + roomName);
<a name="line1509"></a><div class="linenumber">1509</div><div style="width:2em;display:inline-block"></div>* }
<a name="line1510"></a><div class="linenumber">1510</div><div style="width:2em;display:inline-block"></div>* });
<a name="line1511"></a><div class="linenumber">1511</div><div style="width:2em;display:inline-block"></div>*/
<a name="line1512"></a><div class="linenumber">1512</div><div style="width:2em;display:inline-block"></div>self.setRoomEntryListener = function(handler) {
<a name="line1513"></a><div class="linenumber">1513</div><div style="width:4em;display:inline-block"></div>self.roomEntryListener = handler;
<a name="line1514"></a><div class="linenumber">1514</div><div style="width:2em;display:inline-block"></div>};
<a name="line1515"></a><div class="linenumber">1515</div>
<a name="line1516"></a><div class="linenumber">1516</div><div style="width:2em;display:inline-block"></div>/**
<a name="line1517"></a><div class="linenumber">1517</div><div style="width:2em;display:inline-block"></div>* Set the callback that will be invoked when the list of people logged in changes.
<a name="line1518"></a><div class="linenumber">1518</div><div style="width:2em;display:inline-block"></div>* The callback expects to receive a room name argument, and
<a name="line1519"></a><div class="linenumber">1519</div><div style="width:2em;display:inline-block"></div>* a map whose ideas are easyrtcids and whose values are in turn maps
<a name="line1520"></a><div class="linenumber">1520</div><div style="width:2em;display:inline-block"></div>* supplying user specific information. The inner maps have the following keys:
<a name="line1521"></a><div class="linenumber">1521</div><div style="width:2em;display:inline-block"></div>* username, applicationName, browserFamily, browserMajor, osFamily, osMajor, deviceFamily.
<a name="line1522"></a><div class="linenumber">1522</div><div style="width:2em;display:inline-block"></div>* The third argument is the listener is the innerMap for the connections own data (not needed by most applications).
<a name="line1523"></a><div class="linenumber">1523</div><div style="width:2em;display:inline-block"></div>* @param {Function} listener
<a name="line1524"></a><div class="linenumber">1524</div><div style="width:2em;display:inline-block"></div>* @example
<a name="line1525"></a><div class="linenumber">1525</div><div style="width:2em;display:inline-block"></div>* easyrtc.setRoomOccupantListener( function(roomName, list, selfInfo){
<a name="line1526"></a><div class="linenumber">1526</div><div style="width:2em;display:inline-block"></div>* for( var i in list ){
<a name="line1527"></a><div class="linenumber">1527</div><div style="width:2em;display:inline-block"></div>* ("easyrtcid=" + i + " belongs to user " + list[i].username);
<a name="line1528"></a><div class="linenumber">1528</div><div style="width:2em;display:inline-block"></div>* }
<a name="line1529"></a><div class="linenumber">1529</div><div style="width:2em;display:inline-block"></div>* });
<a name="line1530"></a><div class="linenumber">1530</div><div style="width:2em;display:inline-block"></div>*/
<a name="line1531"></a><div class="linenumber">1531</div><div style="width:2em;display:inline-block"></div>self.setRoomOccupantListener = function(listener) {
<a name="line1532"></a><div class="linenumber">1532</div><div style="width:4em;display:inline-block"></div>roomOccupantListener = listener;
<a name="line1533"></a><div class="linenumber">1533</div><div style="width:2em;display:inline-block"></div>};
<a name="line1534"></a><div class="linenumber">1534</div>
<a name="line1535"></a><div class="linenumber">1535</div><div style="width:2em;display:inline-block"></div>/**
<a name="line1536"></a><div class="linenumber">1536</div><div style="width:2em;display:inline-block"></div>* Sets a callback that is called when a data channel is open and ready to send data.
<a name="line1537"></a><div class="linenumber">1537</div><div style="width:2em;display:inline-block"></div>* The callback will be called with an easyrtcid as it's sole argument.
<a name="line1538"></a><div class="linenumber">1538</div><div style="width:2em;display:inline-block"></div>* @param {Function} listener
<a name="line1539"></a><div class="linenumber">1539</div><div style="width:2em;display:inline-block"></div>* @example
<a name="line1540"></a><div class="linenumber">1540</div><div style="width:2em;display:inline-block"></div>* easyrtc.setDataChannelOpenListener( function(easyrtcid){
<a name="line1541"></a><div class="linenumber">1541</div><div style="width:2em;display:inline-block"></div>* easyrtc.sendDataP2P(easyrtcid, "greeting", "hello");
<a name="line1542"></a><div class="linenumber">1542</div><div style="width:2em;display:inline-block"></div>* });
<a name="line1543"></a><div class="linenumber">1543</div><div style="width:2em;display:inline-block"></div>*/
<a name="line1544"></a><div class="linenumber">1544</div><div style="width:2em;display:inline-block"></div>this.setDataChannelOpenListener = function(listener) {
<a name="line1545"></a><div class="linenumber">1545</div><div style="width:4em;display:inline-block"></div>onDataChannelOpen = listener;
<a name="line1546"></a><div class="linenumber">1546</div><div style="width:2em;display:inline-block"></div>};
<a name="line1547"></a><div class="linenumber">1547</div>
<a name="line1548"></a><div class="linenumber">1548</div><div style="width:2em;display:inline-block"></div>/** Sets a callback that is called when a previously open data channel closes.
<a name="line1549"></a><div class="linenumber">1549</div><div style="width:2em;display:inline-block"></div>* The callback will be called with an easyrtcid as it's sole argument.
<a name="line1550"></a><div class="linenumber">1550</div><div style="width:2em;display:inline-block"></div>* @param {Function} listener
<a name="line1551"></a><div class="linenumber">1551</div><div style="width:2em;display:inline-block"></div>* @example
<a name="line1552"></a><div class="linenumber">1552</div><div style="width:2em;display:inline-block"></div>* easyrtc.setDataChannelCloseListener( function(easyrtcid){
<a name="line1553"></a><div class="linenumber">1553</div><div style="width:2em;display:inline-block"></div>* ("No longer connected to " + easyrtc.idToName(easyrtcid));
<a name="line1554"></a><div class="linenumber">1554</div><div style="width:2em;display:inline-block"></div>* });
<a name="line1555"></a><div class="linenumber">1555</div><div style="width:2em;display:inline-block"></div>*/
<a name="line1556"></a><div class="linenumber">1556</div><div style="width:2em;display:inline-block"></div>this.setDataChannelCloseListener = function(listener) {
<a name="line1557"></a><div class="linenumber">1557</div><div style="width:4em;display:inline-block"></div>onDataChannelClose = listener;
<a name="line1558"></a><div class="linenumber">1558</div><div style="width:2em;display:inline-block"></div>};
<a name="line1559"></a><div class="linenumber">1559</div>
<a name="line1560"></a><div class="linenumber">1560</div><div style="width:2em;display:inline-block"></div>/** Returns the number of live peer connections the client has.
<a name="line1561"></a><div class="linenumber">1561</div><div style="width:2em;display:inline-block"></div>* @return {Number}
<a name="line1562"></a><div class="linenumber">1562</div><div style="width:2em;display:inline-block"></div>* @example
<a name="line1563"></a><div class="linenumber">1563</div><div style="width:2em;display:inline-block"></div>* ("You have " + easyrtc.getConnectionCount() + " peer connections");
<a name="line1564"></a><div class="linenumber">1564</div><div style="width:2em;display:inline-block"></div>*/
<a name="line1565"></a><div class="linenumber">1565</div><div style="width:2em;display:inline-block"></div>this.getConnectionCount = function() {
<a name="line1566"></a><div class="linenumber">1566</div><div style="width:4em;display:inline-block"></div>var count = 0;
<a name="line1567"></a><div class="linenumber">1567</div><div style="width:4em;display:inline-block"></div>var i;
<a name="line1568"></a><div class="linenumber">1568</div><div style="width:4em;display:inline-block"></div>for (i in peerConns) {
<a name="line1569"></a><div class="linenumber">1569</div><div style="width:6em;display:inline-block"></div>if (peerConns.hasOwnProperty(i)) {
<a name="line1570"></a><div class="linenumber">1570</div><div style="width:8em;display:inline-block"></div>if (self.getConnectStatus(i) === self.IS_CONNECTED) {
<a name="line1571"></a><div class="linenumber">1571</div><div style="width:10em;display:inline-block"></div>count++;
<a name="line1572"></a><div class="linenumber">1572</div><div style="width:8em;display:inline-block"></div>}
<a name="line1573"></a><div class="linenumber">1573</div><div style="width:6em;display:inline-block"></div>}
<a name="line1574"></a><div class="linenumber">1574</div><div style="width:4em;display:inline-block"></div>}
<a name="line1575"></a><div class="linenumber">1575</div><div style="width:4em;display:inline-block"></div>return count;
<a name="line1576"></a><div class="linenumber">1576</div><div style="width:2em;display:inline-block"></div>};
<a name="line1577"></a><div class="linenumber">1577</div>
<a name="line1578"></a><div class="linenumber">1578</div><div style="width:2em;display:inline-block"></div>/** Sets the maximum length in bytes of P2P messages that can be sent.
<a name="line1579"></a><div class="linenumber">1579</div><div style="width:2em;display:inline-block"></div>* @param {Number} maxLength maximum length to set
<a name="line1580"></a><div class="linenumber">1580</div><div style="width:2em;display:inline-block"></div>* @example
<a name="line1581"></a><div class="linenumber">1581</div><div style="width:2em;display:inline-block"></div>* easyrtc.setMaxP2PMessageLength(10000);
<a name="line1582"></a><div class="linenumber">1582</div><div style="width:2em;display:inline-block"></div>*/
<a name="line1583"></a><div class="linenumber">1583</div><div style="width:2em;display:inline-block"></div>this.setMaxP2PMessageLength = function(maxLength) {
<a name="line1584"></a><div class="linenumber">1584</div><div style="width:4em;display:inline-block"></div>this.maxP2PMessageLength = maxLength;
<a name="line1585"></a><div class="linenumber">1585</div><div style="width:2em;display:inline-block"></div>};
<a name="line1586"></a><div class="linenumber">1586</div>
<a name="line1587"></a><div class="linenumber">1587</div><div style="width:2em;display:inline-block"></div>/** Sets whether audio is transmitted by the local user in any subsequent calls.
<a name="line1588"></a><div class="linenumber">1588</div><div style="width:2em;display:inline-block"></div>* @param {Boolean} enabled true to include audio, false to exclude audio. The default is true.
<a name="line1589"></a><div class="linenumber">1589</div><div style="width:2em;display:inline-block"></div>* @example
<a name="line1590"></a><div class="linenumber">1590</div><div style="width:2em;display:inline-block"></div>* easyrtc.enableAudio(false);
<a name="line1591"></a><div class="linenumber">1591</div><div style="width:2em;display:inline-block"></div>*/
<a name="line1592"></a><div class="linenumber">1592</div><div style="width:2em;display:inline-block"></div>this.enableAudio = function(enabled) {
<a name="line1593"></a><div class="linenumber">1593</div><div style="width:4em;display:inline-block"></div>self.audioEnabled = enabled;
<a name="line1594"></a><div class="linenumber">1594</div><div style="width:2em;display:inline-block"></div>};
<a name="line1595"></a><div class="linenumber">1595</div>
<a name="line1596"></a><div class="linenumber">1596</div><div style="width:2em;display:inline-block"></div>/**
<a name="line1597"></a><div class="linenumber">1597</div><div style="width:2em;display:inline-block"></div>*Sets whether video is transmitted by the local user in any subsequent calls.
<a name="line1598"></a><div class="linenumber">1598</div><div style="width:2em;display:inline-block"></div>* @param {Boolean} enabled - true to include video, false to exclude video. The default is true.
<a name="line1599"></a><div class="linenumber">1599</div><div style="width:2em;display:inline-block"></div>* @example
<a name="line1600"></a><div class="linenumber">1600</div><div style="width:2em;display:inline-block"></div>* easyrtc.enableVideo(false);
<a name="line1601"></a><div class="linenumber">1601</div><div style="width:2em;display:inline-block"></div>*/
<a name="line1602"></a><div class="linenumber">1602</div><div style="width:2em;display:inline-block"></div>this.enableVideo = function(enabled) {
<a name="line1603"></a><div class="linenumber">1603</div><div style="width:4em;display:inline-block"></div>self.videoEnabled = enabled;
<a name="line1604"></a><div class="linenumber">1604</div><div style="width:2em;display:inline-block"></div>};
<a name="line1605"></a><div class="linenumber">1605</div>
<a name="line1606"></a><div class="linenumber">1606</div><div style="width:2em;display:inline-block"></div>/**
<a name="line1607"></a><div class="linenumber">1607</div><div style="width:2em;display:inline-block"></div>* Sets whether WebRTC data channels are used to send inter-client messages.
<a name="line1608"></a><div class="linenumber">1608</div><div style="width:2em;display:inline-block"></div>* This is only the messages that applications explicitly send to other applications, not the WebRTC signaling messages.
<a name="line1609"></a><div class="linenumber">1609</div><div style="width:2em;display:inline-block"></div>* @param {Boolean} enabled true to use data channels, false otherwise. The default is false.
<a name="line1610"></a><div class="linenumber">1610</div><div style="width:2em;display:inline-block"></div>* @example
<a name="line1611"></a><div class="linenumber">1611</div><div style="width:2em;display:inline-block"></div>* easyrtc.enableDataChannels(true);
<a name="line1612"></a><div class="linenumber">1612</div><div style="width:2em;display:inline-block"></div>*/
<a name="line1613"></a><div class="linenumber">1613</div><div style="width:2em;display:inline-block"></div>this.enableDataChannels = function(enabled) {
<a name="line1614"></a><div class="linenumber">1614</div><div style="width:4em;display:inline-block"></div>dataEnabled = enabled;
<a name="line1615"></a><div class="linenumber">1615</div><div style="width:2em;display:inline-block"></div>};
<a name="line1616"></a><div class="linenumber">1616</div>
<a name="line1617"></a><div class="linenumber">1617</div><div style="width:2em;display:inline-block"></div>/**
<a name="line1618"></a><div class="linenumber">1618</div><div style="width:2em;display:inline-block"></div>* @private
<a name="line1619"></a><div class="linenumber">1619</div><div style="width:2em;display:inline-block"></div>* @param {Boolean} enable
<a name="line1620"></a><div class="linenumber">1620</div><div style="width:2em;display:inline-block"></div>* @param {Array} tracks - an array of MediaStreamTrack
<a name="line1621"></a><div class="linenumber">1621</div><div style="width:2em;display:inline-block"></div>*/
<a name="line1622"></a><div class="linenumber">1622</div><div style="width:2em;display:inline-block"></div>function enableMediaTracks(enable, tracks) {
<a name="line1623"></a><div class="linenumber">1623</div><div style="width:4em;display:inline-block"></div>var i;
<a name="line1624"></a><div class="linenumber">1624</div><div style="width:4em;display:inline-block"></div>if (tracks) {
<a name="line1625"></a><div class="linenumber">1625</div><div style="width:6em;display:inline-block"></div>for (i = 0; i < tracks.length; i++) {
<a name="line1626"></a><div class="linenumber">1626</div><div style="width:8em;display:inline-block"></div>var track = tracks[i];
<a name="line1627"></a><div class="linenumber">1627</div><div style="width:8em;display:inline-block"></div>track.enabled = enable;
<a name="line1628"></a><div class="linenumber">1628</div><div style="width:6em;display:inline-block"></div>}
<a name="line1629"></a><div class="linenumber">1629</div><div style="width:4em;display:inline-block"></div>}
<a name="line1630"></a><div class="linenumber">1630</div><div style="width:2em;display:inline-block"></div>}
<a name="line1631"></a><div class="linenumber">1631</div>
<a name="line1632"></a><div class="linenumber">1632</div><div style="width:2em;display:inline-block"></div>/** @private */
<a name="line1633"></a><div class="linenumber">1633</div><div style="width:2em;display:inline-block"></div>//
<a name="line1634"></a><div class="linenumber">1634</div><div style="width:2em;display:inline-block"></div>// fetches a stream by name. Treat a null/undefined streamName as "default".
<a name="line1635"></a><div class="linenumber">1635</div><div style="width:2em;display:inline-block"></div>//
<a name="line1636"></a><div class="linenumber">1636</div><div style="width:2em;display:inline-block"></div>function getLocalMediaStreamByName(streamName) {
<a name="line1637"></a><div class="linenumber">1637</div><div style="width:4em;display:inline-block"></div>if (!streamName) {
<a name="line1638"></a><div class="linenumber">1638</div><div style="width:6em;display:inline-block"></div>streamName = "default";
<a name="line1639"></a><div class="linenumber">1639</div><div style="width:4em;display:inline-block"></div>}
<a name="line1640"></a><div class="linenumber">1640</div><div style="width:4em;display:inline-block"></div>if (namedLocalMediaStreams.hasOwnProperty(streamName)) {
<a name="line1641"></a><div class="linenumber">1641</div><div style="width:6em;display:inline-block"></div>return namedLocalMediaStreams[streamName];
<a name="line1642"></a><div class="linenumber">1642</div><div style="width:4em;display:inline-block"></div>}
<a name="line1643"></a><div class="linenumber">1643</div><div style="width:4em;display:inline-block"></div>else {
<a name="line1644"></a><div class="linenumber">1644</div><div style="width:6em;display:inline-block"></div>return null;
<a name="line1645"></a><div class="linenumber">1645</div><div style="width:4em;display:inline-block"></div>}
<a name="line1646"></a><div class="linenumber">1646</div><div style="width:2em;display:inline-block"></div>}
<a name="line1647"></a><div class="linenumber">1647</div>
<a name="line1648"></a><div class="linenumber">1648</div><div style="width:2em;display:inline-block"></div>/**
<a name="line1649"></a><div class="linenumber">1649</div><div style="width:2em;display:inline-block"></div>* Returns the user assigned id's of currently active local media streams.
<a name="line1650"></a><div class="linenumber">1650</div><div style="width:2em;display:inline-block"></div>* @return {Array}
<a name="line1651"></a><div class="linenumber">1651</div><div style="width:2em;display:inline-block"></div>*/
<a name="line1652"></a><div class="linenumber">1652</div><div style="width:2em;display:inline-block"></div>this.getLocalMediaIds = function() {
<a name="line1653"></a><div class="linenumber">1653</div><div style="width:4em;display:inline-block"></div>return Object.keys(namedLocalMediaStreams);
<a name="line1654"></a><div class="linenumber">1654</div><div style="width:2em;display:inline-block"></div>};
<a name="line1655"></a><div class="linenumber">1655</div>
<a name="line1656"></a><div class="linenumber">1656</div><div style="width:2em;display:inline-block"></div>/** @private */
<a name="line1657"></a><div class="linenumber">1657</div><div style="width:2em;display:inline-block"></div>function buildMediaIds() {
<a name="line1658"></a><div class="linenumber">1658</div><div style="width:4em;display:inline-block"></div>var mediaMap = {};
<a name="line1659"></a><div class="linenumber">1659</div><div style="width:4em;display:inline-block"></div>var streamName;
<a name="line1660"></a><div class="linenumber">1660</div><div style="width:4em;display:inline-block"></div>for (streamName in namedLocalMediaStreams) {
<a name="line1661"></a><div class="linenumber">1661</div><div style="width:6em;display:inline-block"></div>if (namedLocalMediaStreams.hasOwnProperty(streamName)) {
<a name="line1662"></a><div class="linenumber">1662</div><div style="width:8em;display:inline-block"></div>mediaMap[streamName] = namedLocalMediaStreams[streamName].id || "default";
<a name="line1663"></a><div class="linenumber">1663</div><div style="width:6em;display:inline-block"></div>}
<a name="line1664"></a><div class="linenumber">1664</div><div style="width:4em;display:inline-block"></div>}
<a name="line1665"></a><div class="linenumber">1665</div><div style="width:4em;display:inline-block"></div>return mediaMap;
<a name="line1666"></a><div class="linenumber">1666</div><div style="width:2em;display:inline-block"></div>}
<a name="line1667"></a><div class="linenumber">1667</div>
<a name="line1668"></a><div class="linenumber">1668</div><div style="width:2em;display:inline-block"></div>/** @private */
<a name="line1669"></a><div class="linenumber">1669</div><div style="width:2em;display:inline-block"></div>function registerLocalMediaStreamByName(stream, streamName) {
<a name="line1670"></a><div class="linenumber">1670</div><div style="width:4em;display:inline-block"></div>var roomName;
<a name="line1671"></a><div class="linenumber">1671</div><div style="width:4em;display:inline-block"></div>if (!streamName) {
<a name="line1672"></a><div class="linenumber">1672</div><div style="width:6em;display:inline-block"></div>streamName = "default";
<a name="line1673"></a><div class="linenumber">1673</div><div style="width:4em;display:inline-block"></div>}
<a name="line1674"></a><div class="linenumber">1674</div><div style="width:4em;display:inline-block"></div>stream.streamName = streamName;
<a name="line1675"></a><div class="linenumber">1675</div><div style="width:4em;display:inline-block"></div>namedLocalMediaStreams[streamName] = stream;
<a name="line1676"></a><div class="linenumber">1676</div><div style="width:4em;display:inline-block"></div>if (streamName !== "default") {
<a name="line1677"></a><div class="linenumber">1677</div><div style="width:6em;display:inline-block"></div>var mediaIds = buildMediaIds(),
<a name="line1678"></a><div class="linenumber">1678</div><div style="width:8em;display:inline-block"></div>roomData = self.roomData;
<a name="line1679"></a><div class="linenumber">1679</div><div style="width:6em;display:inline-block"></div>for (roomName in roomData) {
<a name="line1680"></a><div class="linenumber">1680</div><div style="width:8em;display:inline-block"></div>if (roomData.hasOwnProperty(roomName)) {
<a name="line1681"></a><div class="linenumber">1681</div><div style="width:10em;display:inline-block"></div>self.setRoomApiField(roomName, "mediaIds", mediaIds);
<a name="line1682"></a><div class="linenumber">1682</div><div style="width:8em;display:inline-block"></div>}
<a name="line1683"></a><div class="linenumber">1683</div><div style="width:6em;display:inline-block"></div>}
<a name="line1684"></a><div class="linenumber">1684</div><div style="width:4em;display:inline-block"></div>}
<a name="line1685"></a><div class="linenumber">1685</div><div style="width:2em;display:inline-block"></div>}
<a name="line1686"></a><div class="linenumber">1686</div>
<a name="line1687"></a><div class="linenumber">1687</div><div style="width:2em;display:inline-block"></div>/**
<a name="line1688"></a><div class="linenumber">1688</div><div style="width:2em;display:inline-block"></div>* Allow an externally created mediastream (ie, created by another
<a name="line1689"></a><div class="linenumber">1689</div><div style="width:2em;display:inline-block"></div>* library) to be used within easyrtc. Tracking when it closes
<a name="line1690"></a><div class="linenumber">1690</div><div style="width:2em;display:inline-block"></div>* must be done by the supplying party.
<a name="line1691"></a><div class="linenumber">1691</div><div style="width:2em;display:inline-block"></div>*/
<a name="line1692"></a><div class="linenumber">1692</div><div style="width:2em;display:inline-block"></div>this.register3rdPartyLocalMediaStream = function(stream, streamName) {
<a name="line1693"></a><div class="linenumber">1693</div><div style="width:3em;display:inline-block"></div>return registerLocalMediaStreamByName(stream, streamName);
<a name="line1694"></a><div class="linenumber">1694</div><div style="width:2em;display:inline-block"></div>};
<a name="line1695"></a><div class="linenumber">1695</div>
<a name="line1696"></a><div class="linenumber">1696</div><div style="width:2em;display:inline-block"></div>/** @private */
<a name="line1697"></a><div class="linenumber">1697</div><div style="width:2em;display:inline-block"></div>//
<a name="line1698"></a><div class="linenumber">1698</div><div style="width:2em;display:inline-block"></div>// look up a stream's name from the stream.id
<a name="line1699"></a><div class="linenumber">1699</div><div style="width:2em;display:inline-block"></div>//
<a name="line1700"></a><div class="linenumber">1700</div><div style="width:2em;display:inline-block"></div>function getNameOfRemoteStream(easyrtcId, webrtcStreamId) {
<a name="line1701"></a><div class="linenumber">1701</div><div style="width:4em;display:inline-block"></div>var roomName;
<a name="line1702"></a><div class="linenumber">1702</div><div style="width:4em;display:inline-block"></div>var mediaIds;
<a name="line1703"></a><div class="linenumber">1703</div><div style="width:4em;display:inline-block"></div>var streamName;
<a name="line1704"></a><div class="linenumber">1704</div><div style="width:4em;display:inline-block"></div>if (!webrtcStreamId) {
<a name="line1705"></a><div class="linenumber">1705</div><div style="width:6em;display:inline-block"></div>webrtcStreamId = "default";
<a name="line1706"></a><div class="linenumber">1706</div><div style="width:4em;display:inline-block"></div>}
<a name="line1707"></a><div class="linenumber">1707</div><div style="width:4em;display:inline-block"></div>if (peerConns[easyrtcId]) {
<a name="line1708"></a><div class="linenumber">1708</div><div style="width:6em;display:inline-block"></div>streamName = peerConns[easyrtcId].remoteStreamIdToName[webrtcStreamId];
<a name="line1709"></a><div class="linenumber">1709</div><div style="width:6em;display:inline-block"></div>if (streamName) {
<a name="line1710"></a><div class="linenumber">1710</div><div style="width:8em;display:inline-block"></div>return streamName;
<a name="line1711"></a><div class="linenumber">1711</div><div style="width:6em;display:inline-block"></div>}
<a name="line1712"></a><div class="linenumber">1712</div><div style="width:4em;display:inline-block"></div>}
<a name="line1713"></a><div class="linenumber">1713</div>
<a name="line1714"></a><div class="linenumber">1714</div><div style="width:4em;display:inline-block"></div>for (roomName in self.roomData) {
<a name="line1715"></a><div class="linenumber">1715</div><div style="width:6em;display:inline-block"></div>if (self.roomData.hasOwnProperty(roomName)) {
<a name="line1716"></a><div class="linenumber">1716</div><div style="width:8em;display:inline-block"></div>mediaIds = self.getRoomApiField(roomName, easyrtcId, "mediaIds");
<a name="line1717"></a><div class="linenumber">1717</div><div style="width:8em;display:inline-block"></div>if (!mediaIds) {
<a name="line1718"></a><div class="linenumber">1718</div><div style="width:10em;display:inline-block"></div>continue;
<a name="line1719"></a><div class="linenumber">1719</div><div style="width:8em;display:inline-block"></div>}
<a name="line1720"></a><div class="linenumber">1720</div><div style="width:8em;display:inline-block"></div>for (streamName in mediaIds) {
<a name="line1721"></a><div class="linenumber">1721</div><div style="width:10em;display:inline-block"></div>if (mediaIds.hasOwnProperty(streamName) &&
<a name="line1722"></a><div class="linenumber">1722</div><div style="width:14em;display:inline-block"></div>mediaIds[streamName] === webrtcStreamId) {
<a name="line1723"></a><div class="linenumber">1723</div><div style="width:12em;display:inline-block"></div>return streamName;
<a name="line1724"></a><div class="linenumber">1724</div><div style="width:10em;display:inline-block"></div>}
<a name="line1725"></a><div class="linenumber">1725</div><div style="width:8em;display:inline-block"></div>}
<a name="line1726"></a><div class="linenumber">1726</div><div style="width:8em;display:inline-block"></div>//
<a name="line1727"></a><div class="linenumber">1727</div><div style="width:8em;display:inline-block"></div>// a stream from chrome to firefox will be missing it's id/label.
<a name="line1728"></a><div class="linenumber">1728</div><div style="width:8em;display:inline-block"></div>// there is no correct solution.
<a name="line1729"></a><div class="linenumber">1729</div><div style="width:8em;display:inline-block"></div>//
<a name="line1730"></a><div class="linenumber">1730</div><div style="width:8em;display:inline-block"></div>if (
<a name="line1731"></a><div class="linenumber">1731</div><div style="width:10em;display:inline-block"></div>adapter && adapter.browserDetails &&
<a name="line1732"></a><div class="linenumber">1732</div><div style="width:12em;display:inline-block"></div>adapter.browserDetails.browser === "firefox"
<a name="line1733"></a><div class="linenumber">1733</div><div style="width:8em;display:inline-block"></div>) {
<a name="line1734"></a><div class="linenumber">1734</div>
<a name="line1735"></a><div class="linenumber">1735</div><div style="width:9em;display:inline-block"></div>// if there is a stream called default, return it in preference
<a name="line1736"></a><div class="linenumber">1736</div><div style="width:9em;display:inline-block"></div>if (mediaIds["default"]) {
<a name="line1737"></a><div class="linenumber">1737</div><div style="width:11em;display:inline-block"></div>return "default";
<a name="line1738"></a><div class="linenumber">1738</div><div style="width:9em;display:inline-block"></div>}
<a name="line1739"></a><div class="linenumber">1739</div>
<a name="line1740"></a><div class="linenumber">1740</div><div style="width:9em;display:inline-block"></div>//
<a name="line1741"></a><div class="linenumber">1741</div><div style="width:9em;display:inline-block"></div>// otherwise return the first name we find. If there is more than
<a name="line1742"></a><div class="linenumber">1742</div><div style="width:9em;display:inline-block"></div>// one, complain to Mozilla.
<a name="line1743"></a><div class="linenumber">1743</div><div style="width:9em;display:inline-block"></div>//
<a name="line1744"></a><div class="linenumber">1744</div><div style="width:9em;display:inline-block"></div>for(var anyName in mediaIds) {
<a name="line1745"></a><div class="linenumber">1745</div><div style="width:12em;display:inline-block"></div>if (mediaIds.hasOwnProperty(anyName)) {
<a name="line1746"></a><div class="linenumber">1746</div><div style="width:14em;display:inline-block"></div>return anyName;
<a name="line1747"></a><div class="linenumber">1747</div><div style="width:12em;display:inline-block"></div>}
<a name="line1748"></a><div class="linenumber">1748</div><div style="width:9em;display:inline-block"></div>}
<a name="line1749"></a><div class="linenumber">1749</div><div style="width:8em;display:inline-block"></div>}
<a name="line1750"></a><div class="linenumber">1750</div><div style="width:6em;display:inline-block"></div>}
<a name="line1751"></a><div class="linenumber">1751</div><div style="width:4em;display:inline-block"></div>}
<a name="line1752"></a><div class="linenumber">1752</div>
<a name="line1753"></a><div class="linenumber">1753</div><div style="width:4em;display:inline-block"></div>return undefined;
<a name="line1754"></a><div class="linenumber">1754</div><div style="width:2em;display:inline-block"></div>}
<a name="line1755"></a><div class="linenumber">1755</div>
<a name="line1756"></a><div class="linenumber">1756</div><div style="width:2em;display:inline-block"></div>this.getNameOfRemoteStream = function(easyrtcId, webrtcStream){
<a name="line1757"></a><div class="linenumber">1757</div><div style="width:4em;display:inline-block"></div>if(typeof webrtcStream === "string") {
<a name="line1758"></a><div class="linenumber">1758</div><div style="width:6em;display:inline-block"></div>return getNameOfRemoteStream(easyrtcId, webrtcStream);
<a name="line1759"></a><div class="linenumber">1759</div><div style="width:4em;display:inline-block"></div>}
<a name="line1760"></a><div class="linenumber">1760</div><div style="width:4em;display:inline-block"></div>else if( webrtcStream.id) {
<a name="line1761"></a><div class="linenumber">1761</div><div style="width:6em;display:inline-block"></div>return getNameOfRemoteStream(easyrtcId, webrtcStream.id);
<a name="line1762"></a><div class="linenumber">1762</div><div style="width:4em;display:inline-block"></div>}
<a name="line1763"></a><div class="linenumber">1763</div><div style="width:2em;display:inline-block"></div>};
<a name="line1764"></a><div class="linenumber">1764</div>
<a name="line1765"></a><div class="linenumber">1765</div><div style="width:2em;display:inline-block"></div>/** @private */
<a name="line1766"></a><div class="linenumber">1766</div><div style="width:2em;display:inline-block"></div>function closeLocalMediaStreamByName(streamName) {
<a name="line1767"></a><div class="linenumber">1767</div><div style="width:4em;display:inline-block"></div>if (!streamName) {
<a name="line1768"></a><div class="linenumber">1768</div><div style="width:6em;display:inline-block"></div>streamName = "default";
<a name="line1769"></a><div class="linenumber">1769</div><div style="width:4em;display:inline-block"></div>}
<a name="line1770"></a><div class="linenumber">1770</div><div style="width:4em;display:inline-block"></div>var stream = self.getLocalStream(streamName);
<a name="line1771"></a><div class="linenumber">1771</div><div style="width:4em;display:inline-block"></div>if (!stream) {
<a name="line1772"></a><div class="linenumber">1772</div><div style="width:6em;display:inline-block"></div>return;
<a name="line1773"></a><div class="linenumber">1773</div><div style="width:4em;display:inline-block"></div>}
<a name="line1774"></a><div class="linenumber">1774</div><div style="width:4em;display:inline-block"></div>var streamId = stream.id || "default";
<a name="line1775"></a><div class="linenumber">1775</div><div style="width:4em;display:inline-block"></div>var id;
<a name="line1776"></a><div class="linenumber">1776</div><div style="width:4em;display:inline-block"></div>var roomName;
<a name="line1777"></a><div class="linenumber">1777</div><div style="width:4em;display:inline-block"></div>if (namedLocalMediaStreams[streamName]) {
<a name="line1778"></a><div class="linenumber">1778</div>
<a name="line1779"></a><div class="linenumber">1779</div><div style="width:6em;display:inline-block"></div>for (id in peerConns) {
<a name="line1780"></a><div class="linenumber">1780</div><div style="width:8em;display:inline-block"></div>if (peerConns.hasOwnProperty(id)) {
<a name="line1781"></a><div class="linenumber">1781</div><div style="width:10em;display:inline-block"></div>try {
<a name="line1782"></a><div class="linenumber">1782</div><div style="width:12em;display:inline-block"></div>peerConns[id].pc.removeStream(stream);
<a name="line1783"></a><div class="linenumber">1783</div><div style="width:10em;display:inline-block"></div>} catch (err) {
<a name="line1784"></a><div class="linenumber">1784</div><div style="width:10em;display:inline-block"></div>}
<a name="line1785"></a><div class="linenumber">1785</div><div style="width:10em;display:inline-block"></div>self.sendPeerMessage(id, "__closingMediaStream", {streamId: streamId, streamName: streamName});
<a name="line1786"></a><div class="linenumber">1786</div><div style="width:8em;display:inline-block"></div>}
<a name="line1787"></a><div class="linenumber">1787</div><div style="width:6em;display:inline-block"></div>}
<a name="line1788"></a><div class="linenumber">1788</div>
<a name="line1789"></a><div class="linenumber">1789</div><div style="width:6em;display:inline-block"></div>stopStream(namedLocalMediaStreams[streamName]);
<a name="line1790"></a><div class="linenumber">1790</div><div style="width:6em;display:inline-block"></div>delete namedLocalMediaStreams[streamName];
<a name="line1791"></a><div class="linenumber">1791</div>
<a name="line1792"></a><div class="linenumber">1792</div><div style="width:6em;display:inline-block"></div>if (streamName !== "default") {
<a name="line1793"></a><div class="linenumber">1793</div><div style="width:8em;display:inline-block"></div>var mediaIds = buildMediaIds();
<a name="line1794"></a><div class="linenumber">1794</div><div style="width:8em;display:inline-block"></div>for (roomName in self.roomData) {
<a name="line1795"></a><div class="linenumber">1795</div><div style="width:10em;display:inline-block"></div>if (self.roomData.hasOwnProperty(roomName)) {
<a name="line1796"></a><div class="linenumber">1796</div><div style="width:12em;display:inline-block"></div>self.setRoomApiField(roomName, "mediaIds", mediaIds);
<a name="line1797"></a><div class="linenumber">1797</div><div style="width:10em;display:inline-block"></div>}
<a name="line1798"></a><div class="linenumber">1798</div><div style="width:8em;display:inline-block"></div>}
<a name="line1799"></a><div class="linenumber">1799</div><div style="width:6em;display:inline-block"></div>}
<a name="line1800"></a><div class="linenumber">1800</div><div style="width:4em;display:inline-block"></div>}
<a name="line1801"></a><div class="linenumber">1801</div><div style="width:2em;display:inline-block"></div>}
<a name="line1802"></a><div class="linenumber">1802</div>
<a name="line1803"></a><div class="linenumber">1803</div><div style="width:2em;display:inline-block"></div>/**
<a name="line1804"></a><div class="linenumber">1804</div><div style="width:2em;display:inline-block"></div>* Close the local media stream. You usually need to close the existing media stream
<a name="line1805"></a><div class="linenumber">1805</div><div style="width:2em;display:inline-block"></div>* of a camera before reacquiring it at a different resolution.
<a name="line1806"></a><div class="linenumber">1806</div><div style="width:2em;display:inline-block"></div>* @param {String} streamName - an option stream name.
<a name="line1807"></a><div class="linenumber">1807</div><div style="width:2em;display:inline-block"></div>*/
<a name="line1808"></a><div class="linenumber">1808</div><div style="width:2em;display:inline-block"></div>this.closeLocalMediaStream = function(streamName) {
<a name="line1809"></a><div class="linenumber">1809</div><div style="width:4em;display:inline-block"></div>return closeLocalMediaStreamByName(streamName);
<a name="line1810"></a><div class="linenumber">1810</div><div style="width:2em;display:inline-block"></div>};
<a name="line1811"></a><div class="linenumber">1811</div>
<a name="line1812"></a><div class="linenumber">1812</div><div style="width:2em;display:inline-block"></div>/**
<a name="line1813"></a><div class="linenumber">1813</div><div style="width:2em;display:inline-block"></div>* Alias for closeLocalMediaStream
<a name="line1814"></a><div class="linenumber">1814</div><div style="width:2em;display:inline-block"></div>*/
<a name="line1815"></a><div class="linenumber">1815</div><div style="width:2em;display:inline-block"></div>this.closeLocalStream = this.closeLocalMediaStream;
<a name="line1816"></a><div class="linenumber">1816</div>
<a name="line1817"></a><div class="linenumber">1817</div><div style="width:2em;display:inline-block"></div>/**
<a name="line1818"></a><div class="linenumber">1818</div><div style="width:2em;display:inline-block"></div>* This function is used to enable and disable the local camera. If you disable the
<a name="line1819"></a><div class="linenumber">1819</div><div style="width:2em;display:inline-block"></div>* camera, video objects display it will "freeze" until the camera is re-enabled. *
<a name="line1820"></a><div class="linenumber">1820</div><div style="width:2em;display:inline-block"></div>* By default, a camera is enabled.
<a name="line1821"></a><div class="linenumber">1821</div><div style="width:2em;display:inline-block"></div>* @param {Boolean} enable - true to enable the camera, false to disable it.
<a name="line1822"></a><div class="linenumber">1822</div><div style="width:2em;display:inline-block"></div>* @param {String} streamName - the name of the stream, optional.
<a name="line1823"></a><div class="linenumber">1823</div><div style="width:2em;display:inline-block"></div>*/
<a name="line1824"></a><div class="linenumber">1824</div><div style="width:2em;display:inline-block"></div>this.enableCamera = function(enable, streamName) {
<a name="line1825"></a><div class="linenumber">1825</div><div style="width:4em;display:inline-block"></div>var stream = getLocalMediaStreamByName(streamName);
<a name="line1826"></a><div class="linenumber">1826</div><div style="width:4em;display:inline-block"></div>if (stream && stream.getVideoTracks) {
<a name="line1827"></a><div class="linenumber">1827</div><div style="width:6em;display:inline-block"></div>enableMediaTracks(enable, stream.getVideoTracks());
<a name="line1828"></a><div class="linenumber">1828</div><div style="width:4em;display:inline-block"></div>}
<a name="line1829"></a><div class="linenumber">1829</div><div style="width:2em;display:inline-block"></div>};
<a name="line1830"></a><div class="linenumber">1830</div>
<a name="line1831"></a><div class="linenumber">1831</div><div style="width:2em;display:inline-block"></div>/**
<a name="line1832"></a><div class="linenumber">1832</div><div style="width:2em;display:inline-block"></div>* This function is used to enable and disable the local microphone. If you disable
<a name="line1833"></a><div class="linenumber">1833</div><div style="width:2em;display:inline-block"></div>* the microphone, sounds stops being transmitted to your peers. By default, the microphone
<a name="line1834"></a><div class="linenumber">1834</div><div style="width:2em;display:inline-block"></div>* is enabled.
<a name="line1835"></a><div class="linenumber">1835</div><div style="width:2em;display:inline-block"></div>* @param {Boolean} enable - true to enable the microphone, false to disable it.
<a name="line1836"></a><div class="linenumber">1836</div><div style="width:2em;display:inline-block"></div>* @param {String} streamName - an optional streamName
<a name="line1837"></a><div class="linenumber">1837</div><div style="width:2em;display:inline-block"></div>*/
<a name="line1838"></a><div class="linenumber">1838</div><div style="width:2em;display:inline-block"></div>this.enableMicrophone = function(enable, streamName) {
<a name="line1839"></a><div class="linenumber">1839</div><div style="width:4em;display:inline-block"></div>var stream = getLocalMediaStreamByName(streamName);
<a name="line1840"></a><div class="linenumber">1840</div><div style="width:4em;display:inline-block"></div>if (stream && stream.getAudioTracks) {
<a name="line1841"></a><div class="linenumber">1841</div><div style="width:6em;display:inline-block"></div>enableMediaTracks(enable, stream.getAudioTracks());
<a name="line1842"></a><div class="linenumber">1842</div><div style="width:4em;display:inline-block"></div>}
<a name="line1843"></a><div class="linenumber">1843</div><div style="width:2em;display:inline-block"></div>};
<a name="line1844"></a><div class="linenumber">1844</div>
<a name="line1845"></a><div class="linenumber">1845</div><div style="width:2em;display:inline-block"></div>/**
<a name="line1846"></a><div class="linenumber">1846</div><div style="width:2em;display:inline-block"></div>* Mute a video object.
<a name="line1847"></a><div class="linenumber">1847</div><div style="width:2em;display:inline-block"></div>* @param {String} videoObjectName - A DOMObject or the id of the DOMObject.
<a name="line1848"></a><div class="linenumber">1848</div><div style="width:2em;display:inline-block"></div>* @param {Boolean} mute - true to mute the video object, false to unmute it.
<a name="line1849"></a><div class="linenumber">1849</div><div style="width:2em;display:inline-block"></div>*/
<a name="line1850"></a><div class="linenumber">1850</div><div style="width:2em;display:inline-block"></div>this.muteVideoObject = function(videoObjectName, mute) {
<a name="line1851"></a><div class="linenumber">1851</div><div style="width:4em;display:inline-block"></div>var videoObject;
<a name="line1852"></a><div class="linenumber">1852</div><div style="width:4em;display:inline-block"></div>if (typeof (videoObjectName) === 'string') {
<a name="line1853"></a><div class="linenumber">1853</div><div style="width:6em;display:inline-block"></div>videoObject = document.getElementById(videoObjectName);
<a name="line1854"></a><div class="linenumber">1854</div><div style="width:6em;display:inline-block"></div>if (!videoObject) {
<a name="line1855"></a><div class="linenumber">1855</div><div style="width:8em;display:inline-block"></div>throw "Unknown video object " + videoObjectName;
<a name="line1856"></a><div class="linenumber">1856</div><div style="width:6em;display:inline-block"></div>}
<a name="line1857"></a><div class="linenumber">1857</div><div style="width:4em;display:inline-block"></div>}
<a name="line1858"></a><div class="linenumber">1858</div><div style="width:4em;display:inline-block"></div>else if (!videoObjectName) {
<a name="line1859"></a><div class="linenumber">1859</div><div style="width:6em;display:inline-block"></div>throw "muteVideoObject passed a null";
<a name="line1860"></a><div class="linenumber">1860</div><div style="width:4em;display:inline-block"></div>}
<a name="line1861"></a><div class="linenumber">1861</div><div style="width:4em;display:inline-block"></div>else {
<a name="line1862"></a><div class="linenumber">1862</div><div style="width:6em;display:inline-block"></div>videoObject = videoObjectName;
<a name="line1863"></a><div class="linenumber">1863</div><div style="width:4em;display:inline-block"></div>}
<a name="line1864"></a><div class="linenumber">1864</div><div style="width:4em;display:inline-block"></div>videoObject.muted = !!mute;
<a name="line1865"></a><div class="linenumber">1865</div><div style="width:2em;display:inline-block"></div>};
<a name="line1866"></a><div class="linenumber">1866</div>
<a name="line1867"></a><div class="linenumber">1867</div><div style="width:2em;display:inline-block"></div>/**
<a name="line1868"></a><div class="linenumber">1868</div><div style="width:2em;display:inline-block"></div>* Returns a URL for your local camera and microphone.
<a name="line1869"></a><div class="linenumber">1869</div><div style="width:2em;display:inline-block"></div>* It can be called only after easyrtc.initMediaSource has succeeded.
<a name="line1870"></a><div class="linenumber">1870</div><div style="width:2em;display:inline-block"></div>* It returns a url that can be used as a source by the Chrome video element or the &lt;canvas&gt; element.
<a name="line1871"></a><div class="linenumber">1871</div><div style="width:2em;display:inline-block"></div>* @param {String} streamName - an option stream name.
<a name="line1872"></a><div class="linenumber">1872</div><div style="width:2em;display:inline-block"></div>* @return {URL}
<a name="line1873"></a><div class="linenumber">1873</div><div style="width:2em;display:inline-block"></div>* @example
<a name="line1874"></a><div class="linenumber">1874</div><div style="width:2em;display:inline-block"></div>* document.getElementById("myVideo").src = easyrtc.getLocalStreamAsUrl();
<a name="line1875"></a><div class="linenumber">1875</div><div style="width:2em;display:inline-block"></div>*/
<a name="line1876"></a><div class="linenumber">1876</div><div style="width:2em;display:inline-block"></div>self.getLocalStreamAsUrl = function(streamName) {
<a name="line1877"></a><div class="linenumber">1877</div><div style="width:4em;display:inline-block"></div>var stream = getLocalMediaStreamByName(streamName);
<a name="line1878"></a><div class="linenumber">1878</div><div style="width:4em;display:inline-block"></div>if (stream === null) {
<a name="line1879"></a><div class="linenumber">1879</div><div style="width:6em;display:inline-block"></div>throw "Developer error: attempt to get a MediaStream without invoking easyrtc.initMediaSource successfully";
<a name="line1880"></a><div class="linenumber">1880</div><div style="width:4em;display:inline-block"></div>}
<a name="line1881"></a><div class="linenumber">1881</div><div style="width:4em;display:inline-block"></div>return self.createObjectURL(stream);
<a name="line1882"></a><div class="linenumber">1882</div><div style="width:2em;display:inline-block"></div>};
<a name="line1883"></a><div class="linenumber">1883</div>
<a name="line1884"></a><div class="linenumber">1884</div><div style="width:2em;display:inline-block"></div>/**
<a name="line1885"></a><div class="linenumber">1885</div><div style="width:2em;display:inline-block"></div>* Returns a media stream for your local camera and microphone.
<a name="line1886"></a><div class="linenumber">1886</div><div style="width:2em;display:inline-block"></div>* It can be called only after easyrtc.initMediaSource has succeeded.
<a name="line1887"></a><div class="linenumber">1887</div><div style="width:2em;display:inline-block"></div>* It returns a stream that can be used as an argument to easyrtc.setVideoObjectSrc.
<a name="line1888"></a><div class="linenumber">1888</div><div style="width:2em;display:inline-block"></div>* Returns null if there is no local media stream acquired yet.
<a name="line1889"></a><div class="linenumber">1889</div><div style="width:2em;display:inline-block"></div>* @return {?MediaStream}
<a name="line1890"></a><div class="linenumber">1890</div><div style="width:2em;display:inline-block"></div>* @example
<a name="line1891"></a><div class="linenumber">1891</div><div style="width:2em;display:inline-block"></div>* easyrtc.setVideoObjectSrc( document.getElementById("myVideo"), easyrtc.getLocalStream());
<a name="line1892"></a><div class="linenumber">1892</div><div style="width:2em;display:inline-block"></div>*/
<a name="line1893"></a><div class="linenumber">1893</div><div style="width:2em;display:inline-block"></div>this.getLocalStream = function(streamName) {
<a name="line1894"></a><div class="linenumber">1894</div><div style="width:4em;display:inline-block"></div>return getLocalMediaStreamByName(streamName) || null;
<a name="line1895"></a><div class="linenumber">1895</div><div style="width:2em;display:inline-block"></div>};
<a name="line1896"></a><div class="linenumber">1896</div>
<a name="line1897"></a><div class="linenumber">1897</div><div style="width:2em;display:inline-block"></div>/** Clears the media stream on a video object.
<a name="line1898"></a><div class="linenumber">1898</div><div style="width:2em;display:inline-block"></div>*
<a name="line1899"></a><div class="linenumber">1899</div><div style="width:2em;display:inline-block"></div>* @param {Object} element the video object.
<a name="line1900"></a><div class="linenumber">1900</div><div style="width:2em;display:inline-block"></div>* @example
<a name="line1901"></a><div class="linenumber">1901</div><div style="width:2em;display:inline-block"></div>* easyrtc.clearMediaStream( document.getElementById('selfVideo'));
<a name="line1902"></a><div class="linenumber">1902</div><div style="width:2em;display:inline-block"></div>*
<a name="line1903"></a><div class="linenumber">1903</div><div style="width:2em;display:inline-block"></div>*/
<a name="line1904"></a><div class="linenumber">1904</div><div style="width:2em;display:inline-block"></div>this.clearMediaStream = function(element) {
<a name="line1905"></a><div class="linenumber">1905</div><div style="width:4em;display:inline-block"></div>if (typeof element.src !== 'undefined') {
<a name="line1906"></a><div class="linenumber">1906</div><div style="width:6em;display:inline-block"></div>//noinspection JSUndefinedPropertyAssignment
<a name="line1907"></a><div class="linenumber">1907</div><div style="width:6em;display:inline-block"></div>element.src = "";
<a name="line1908"></a><div class="linenumber">1908</div><div style="width:4em;display:inline-block"></div>} else if (typeof element.srcObject !== 'undefined') {
<a name="line1909"></a><div class="linenumber">1909</div><div style="width:6em;display:inline-block"></div>element.srcObject = "";
<a name="line1910"></a><div class="linenumber">1910</div><div style="width:4em;display:inline-block"></div>} else if (typeof element.mozSrcObject !== 'undefined') {
<a name="line1911"></a><div class="linenumber">1911</div><div style="width:6em;display:inline-block"></div>element.mozSrcObject = null;
<a name="line1912"></a><div class="linenumber">1912</div><div style="width:4em;display:inline-block"></div>}
<a name="line1913"></a><div class="linenumber">1913</div><div style="width:2em;display:inline-block"></div>};
<a name="line1914"></a><div class="linenumber">1914</div>
<a name="line1915"></a><div class="linenumber">1915</div><div style="width:2em;display:inline-block"></div>/**
<a name="line1916"></a><div class="linenumber">1916</div><div style="width:2em;display:inline-block"></div>* Sets a video or audio object from a media stream.
<a name="line1917"></a><div class="linenumber">1917</div><div style="width:2em;display:inline-block"></div>* Chrome uses the src attribute and expects a URL, while firefox
<a name="line1918"></a><div class="linenumber">1918</div><div style="width:2em;display:inline-block"></div>* uses the mozSrcObject and expects a stream. This procedure hides
<a name="line1919"></a><div class="linenumber">1919</div><div style="width:2em;display:inline-block"></div>* that from you.
<a name="line1920"></a><div class="linenumber">1920</div><div style="width:2em;display:inline-block"></div>* If the media stream is from a local webcam, you may want to add the
<a name="line1921"></a><div class="linenumber">1921</div><div style="width:2em;display:inline-block"></div>* easyrtcMirror class to the video object so it looks like a proper mirror.
<a name="line1922"></a><div class="linenumber">1922</div><div style="width:2em;display:inline-block"></div>* The easyrtcMirror class is defined in this.css.
<a name="line1923"></a><div class="linenumber">1923</div><div style="width:2em;display:inline-block"></div>* Which is could be added using the same path of easyrtc.js file to an HTML file
<a name="line1924"></a><div class="linenumber">1924</div><div style="width:2em;display:inline-block"></div>* @param {Object} element an HTML5 video element
<a name="line1925"></a><div class="linenumber">1925</div><div style="width:2em;display:inline-block"></div>* @param {MediaStream|String} stream a media stream as returned by easyrtc.getLocalStream or your stream acceptor.
<a name="line1926"></a><div class="linenumber">1926</div><div style="width:2em;display:inline-block"></div>* @example
<a name="line1927"></a><div class="linenumber">1927</div><div style="width:2em;display:inline-block"></div>* easyrtc.setVideoObjectSrc( document.getElementById("myVideo"), easyrtc.getLocalStream());
<a name="line1928"></a><div class="linenumber">1928</div><div style="width:2em;display:inline-block"></div>*
<a name="line1929"></a><div class="linenumber">1929</div><div style="width:2em;display:inline-block"></div>*/
<a name="line1930"></a><div class="linenumber">1930</div><div style="width:2em;display:inline-block"></div>this.setVideoObjectSrc = function(element, stream) {
<a name="line1931"></a><div class="linenumber">1931</div><div style="width:4em;display:inline-block"></div>if (stream && stream !== "") {
<a name="line1932"></a><div class="linenumber">1932</div><div style="width:6em;display:inline-block"></div>element.autoplay = true;
<a name="line1933"></a><div class="linenumber">1933</div>
<a name="line1934"></a><div class="linenumber">1934</div><div style="width:6em;display:inline-block"></div>if (typeof element.src !== 'undefined') {
<a name="line1935"></a><div class="linenumber">1935</div><div style="width:8em;display:inline-block"></div>element.src = self.createObjectURL(stream);
<a name="line1936"></a><div class="linenumber">1936</div><div style="width:6em;display:inline-block"></div>} else if (typeof element.srcObject !== 'undefined') {
<a name="line1937"></a><div class="linenumber">1937</div><div style="width:8em;display:inline-block"></div>element.srcObject = stream;
<a name="line1938"></a><div class="linenumber">1938</div><div style="width:6em;display:inline-block"></div>} else if (typeof element.mozSrcObject !== 'undefined') {
<a name="line1939"></a><div class="linenumber">1939</div><div style="width:8em;display:inline-block"></div>element.mozSrcObject = self.createObjectURL(stream);
<a name="line1940"></a><div class="linenumber">1940</div><div style="width:6em;display:inline-block"></div>}
<a name="line1941"></a><div class="linenumber">1941</div><div style="width:6em;display:inline-block"></div>element.play();
<a name="line1942"></a><div class="linenumber">1942</div><div style="width:4em;display:inline-block"></div>}
<a name="line1943"></a><div class="linenumber">1943</div><div style="width:4em;display:inline-block"></div>else {
<a name="line1944"></a><div class="linenumber">1944</div><div style="width:6em;display:inline-block"></div>self.clearMediaStream(element);
<a name="line1945"></a><div class="linenumber">1945</div><div style="width:4em;display:inline-block"></div>}
<a name="line1946"></a><div class="linenumber">1946</div><div style="width:2em;display:inline-block"></div>};
<a name="line1947"></a><div class="linenumber">1947</div>
<a name="line1948"></a><div class="linenumber">1948</div><div style="width:2em;display:inline-block"></div>/**
<a name="line1949"></a><div class="linenumber">1949</div><div style="width:2em;display:inline-block"></div>* This function builds a new named local media stream from a set of existing audio and video tracks from other media streams.
<a name="line1950"></a><div class="linenumber">1950</div><div style="width:2em;display:inline-block"></div>* @param {String} streamName is the name of the new media stream.
<a name="line1951"></a><div class="linenumber">1951</div><div style="width:2em;display:inline-block"></div>* @param {Array} audioTracks is an array of MediaStreamTracks
<a name="line1952"></a><div class="linenumber">1952</div><div style="width:2em;display:inline-block"></div>* @param {Array} videoTracks is an array of MediaStreamTracks
<a name="line1953"></a><div class="linenumber">1953</div><div style="width:2em;display:inline-block"></div>* @returns {?MediaStream} the track created.
<a name="line1954"></a><div class="linenumber">1954</div><div style="width:2em;display:inline-block"></div>* @example
<a name="line1955"></a><div class="linenumber">1955</div><div style="width:2em;display:inline-block"></div>* easyrtc.buildLocalMediaStream("myComposedStream",
<a name="line1956"></a><div class="linenumber">1956</div><div style="width:2em;display:inline-block"></div>* easyrtc.getLocalStream("camera1").getVideoTracks(),
<a name="line1957"></a><div class="linenumber">1957</div><div style="width:2em;display:inline-block"></div>* easyrtc.getLocalStream("camera2").getAudioTracks());
<a name="line1958"></a><div class="linenumber">1958</div><div style="width:2em;display:inline-block"></div>*/
<a name="line1959"></a><div class="linenumber">1959</div><div style="width:2em;display:inline-block"></div>this.buildLocalMediaStream = function(streamName, audioTracks, videoTracks) {
<a name="line1960"></a><div class="linenumber">1960</div><div style="width:4em;display:inline-block"></div>var i;
<a name="line1961"></a><div class="linenumber">1961</div><div style="width:4em;display:inline-block"></div>if (typeof streamName !== 'string') {
<a name="line1962"></a><div class="linenumber">1962</div><div style="width:6em;display:inline-block"></div>self.showError(self.errCodes.DEVELOPER_ERR,
<a name="line1963"></a><div class="linenumber">1963</div><div style="width:7em;display:inline-block"></div>"easyrtc.buildLocalMediaStream not supplied a stream name");
<a name="line1964"></a><div class="linenumber">1964</div><div style="width:6em;display:inline-block"></div>return null;
<a name="line1965"></a><div class="linenumber">1965</div><div style="width:4em;display:inline-block"></div>}
<a name="line1966"></a><div class="linenumber">1966</div>
<a name="line1967"></a><div class="linenumber">1967</div><div style="width:4em;display:inline-block"></div>var streamToClone = null;
<a name="line1968"></a><div class="linenumber">1968</div><div style="width:4em;display:inline-block"></div>for(var key in namedLocalMediaStreams ) {
<a name="line1969"></a><div class="linenumber">1969</div><div style="width:6em;display:inline-block"></div>if( namedLocalMediaStreams.hasOwnProperty(key)) {
<a name="line1970"></a><div class="linenumber">1970</div><div style="width:7em;display:inline-block"></div>streamToClone = namedLocalMediaStreams[key];
<a name="line1971"></a><div class="linenumber">1971</div><div style="width:7em;display:inline-block"></div>if(streamToClone) {
<a name="line1972"></a><div class="linenumber">1972</div><div style="width:8em;display:inline-block"></div>break;
<a name="line1973"></a><div class="linenumber">1973</div><div style="width:7em;display:inline-block"></div>}
<a name="line1974"></a><div class="linenumber">1974</div><div style="width:6em;display:inline-block"></div>}
<a name="line1975"></a><div class="linenumber">1975</div><div style="width:4em;display:inline-block"></div>}
<a name="line1976"></a><div class="linenumber">1976</div><div style="width:4em;display:inline-block"></div>if( !streamToClone ) {
<a name="line1977"></a><div class="linenumber">1977</div><div style="width:6em;display:inline-block"></div>for(key in peerConns) {
<a name="line1978"></a><div class="linenumber">1978</div><div style="width:8em;display:inline-block"></div>if (peerConns.hasOwnProperty(key)) {
<a name="line1979"></a><div class="linenumber">1979</div><div style="width:10em;display:inline-block"></div>var remoteStreams = peerConns[key].pc.getRemoteStreams();
<a name="line1980"></a><div class="linenumber">1980</div><div style="width:10em;display:inline-block"></div>if( remoteStreams && remoteStreams.length > 0 ) {
<a name="line1981"></a><div class="linenumber">1981</div><div style="width:12em;display:inline-block"></div>streamToClone = remoteStreams[0];
<a name="line1982"></a><div class="linenumber">1982</div><div style="width:10em;display:inline-block"></div>}
<a name="line1983"></a><div class="linenumber">1983</div><div style="width:8em;display:inline-block"></div>}
<a name="line1984"></a><div class="linenumber">1984</div><div style="width:6em;display:inline-block"></div>}
<a name="line1985"></a><div class="linenumber">1985</div><div style="width:4em;display:inline-block"></div>}
<a name="line1986"></a><div class="linenumber">1986</div><div style="width:4em;display:inline-block"></div>if( !streamToClone ){
<a name="line1987"></a><div class="linenumber">1987</div><div style="width:6em;display:inline-block"></div>self.showError(self.errCodes.DEVELOPER_ERR,
<a name="line1988"></a><div class="linenumber">1988</div><div style="width:6em;display:inline-block"></div>"Attempt to create a mediastream without one to clone from");
<a name="line1989"></a><div class="linenumber">1989</div><div style="width:6em;display:inline-block"></div>return null;
<a name="line1990"></a><div class="linenumber">1990</div><div style="width:4em;display:inline-block"></div>}
<a name="line1991"></a><div class="linenumber">1991</div>
<a name="line1992"></a><div class="linenumber">1992</div><div style="width:4em;display:inline-block"></div>//
<a name="line1993"></a><div class="linenumber">1993</div><div style="width:4em;display:inline-block"></div>// clone whatever mediastream we found, and remove any of it's
<a name="line1994"></a><div class="linenumber">1994</div><div style="width:4em;display:inline-block"></div>// tracks.
<a name="line1995"></a><div class="linenumber">1995</div><div style="width:4em;display:inline-block"></div>//
<a name="line1996"></a><div class="linenumber">1996</div><div style="width:4em;display:inline-block"></div>var mediaClone = streamToClone.clone();
<a name="line1997"></a><div class="linenumber">1997</div><div style="width:4em;display:inline-block"></div>var oldTracks = mediaClone.getTracks();
<a name="line1998"></a><div class="linenumber">1998</div>
<a name="line1999"></a><div class="linenumber">1999</div><div style="width:4em;display:inline-block"></div>if (audioTracks) {
<a name="line2000"></a><div class="linenumber">2000</div><div style="width:6em;display:inline-block"></div>for (i = 0; i < audioTracks.length; i++) {
<a name="line2001"></a><div class="linenumber">2001</div><div style="width:8em;display:inline-block"></div>mediaClone.addTrack(audioTracks[i].clone());
<a name="line2002"></a><div class="linenumber">2002</div><div style="width:6em;display:inline-block"></div>}
<a name="line2003"></a><div class="linenumber">2003</div><div style="width:4em;display:inline-block"></div>}
<a name="line2004"></a><div class="linenumber">2004</div>
<a name="line2005"></a><div class="linenumber">2005</div><div style="width:4em;display:inline-block"></div>if (videoTracks) {
<a name="line2006"></a><div class="linenumber">2006</div><div style="width:6em;display:inline-block"></div>for (i = 0; i < videoTracks.length; i++) {
<a name="line2007"></a><div class="linenumber">2007</div><div style="width:8em;display:inline-block"></div>mediaClone.addTrack(videoTracks[i].clone());
<a name="line2008"></a><div class="linenumber">2008</div><div style="width:6em;display:inline-block"></div>}
<a name="line2009"></a><div class="linenumber">2009</div><div style="width:4em;display:inline-block"></div>}
<a name="line2010"></a><div class="linenumber">2010</div>
<a name="line2011"></a><div class="linenumber">2011</div><div style="width:4em;display:inline-block"></div>for( i = 0; i < oldTracks.length; i++ ) {
<a name="line2012"></a><div class="linenumber">2012</div><div style="width:6em;display:inline-block"></div>mediaClone.removeTrack(oldTracks[i]);
<a name="line2013"></a><div class="linenumber">2013</div><div style="width:4em;display:inline-block"></div>}
<a name="line2014"></a><div class="linenumber">2014</div>
<a name="line2015"></a><div class="linenumber">2015</div><div style="width:4em;display:inline-block"></div>registerLocalMediaStreamByName(mediaClone, streamName);
<a name="line2016"></a><div class="linenumber">2016</div><div style="width:4em;display:inline-block"></div>return mediaClone;
<a name="line2017"></a><div class="linenumber">2017</div><div style="width:2em;display:inline-block"></div>};
<a name="line2018"></a><div class="linenumber">2018</div>
<a name="line2019"></a><div class="linenumber">2019</div><div style="width:2em;display:inline-block"></div>/* @private*/
<a name="line2020"></a><div class="linenumber">2020</div><div style="width:2em;display:inline-block"></div>/** Load Easyrtc Stylesheet.
<a name="line2021"></a><div class="linenumber">2021</div><div style="width:2em;display:inline-block"></div>* Easyrtc Stylesheet define easyrtcMirror class and some basic css class for using easyrtc.js.
<a name="line2022"></a><div class="linenumber">2022</div><div style="width:2em;display:inline-block"></div>* That way, developers can override it or use it's own css file minified css or package.
<a name="line2023"></a><div class="linenumber">2023</div><div style="width:2em;display:inline-block"></div>* @example
<a name="line2024"></a><div class="linenumber">2024</div><div style="width:2em;display:inline-block"></div>* easyrtc.loadStylesheet();
<a name="line2025"></a><div class="linenumber">2025</div><div style="width:2em;display:inline-block"></div>*
<a name="line2026"></a><div class="linenumber">2026</div><div style="width:2em;display:inline-block"></div>*/
<a name="line2027"></a><div class="linenumber">2027</div><div style="width:2em;display:inline-block"></div>this.loadStylesheet = function() {
<a name="line2028"></a><div class="linenumber">2028</div>
<a name="line2029"></a><div class="linenumber">2029</div><div style="width:4em;display:inline-block"></div>//
<a name="line2030"></a><div class="linenumber">2030</div><div style="width:4em;display:inline-block"></div>// check to see if we already have an easyrtc.css file loaded
<a name="line2031"></a><div class="linenumber">2031</div><div style="width:4em;display:inline-block"></div>// if we do, we can exit immediately.
<a name="line2032"></a><div class="linenumber">2032</div><div style="width:4em;display:inline-block"></div>//
<a name="line2033"></a><div class="linenumber">2033</div><div style="width:4em;display:inline-block"></div>var links = document.getElementsByTagName("link");
<a name="line2034"></a><div class="linenumber">2034</div><div style="width:4em;display:inline-block"></div>var cssIndex, css;
<a name="line2035"></a><div class="linenumber">2035</div><div style="width:4em;display:inline-block"></div>for (cssIndex in links) {
<a name="line2036"></a><div class="linenumber">2036</div><div style="width:6em;display:inline-block"></div>if (links.hasOwnProperty(cssIndex)) {
<a name="line2037"></a><div class="linenumber">2037</div><div style="width:8em;display:inline-block"></div>css = links[cssIndex];
<a name="line2038"></a><div class="linenumber">2038</div><div style="width:8em;display:inline-block"></div>if (css.href && (css.href.match(/\/easyrtc.css/))) {
<a name="line2039"></a><div class="linenumber">2039</div><div style="width:10em;display:inline-block"></div>return;
<a name="line2040"></a><div class="linenumber">2040</div><div style="width:8em;display:inline-block"></div>}
<a name="line2041"></a><div class="linenumber">2041</div><div style="width:6em;display:inline-block"></div>}
<a name="line2042"></a><div class="linenumber">2042</div><div style="width:4em;display:inline-block"></div>}
<a name="line2043"></a><div class="linenumber">2043</div><div style="width:4em;display:inline-block"></div>//
<a name="line2044"></a><div class="linenumber">2044</div><div style="width:4em;display:inline-block"></div>// add the easyrtc.css file since it isn't present
<a name="line2045"></a><div class="linenumber">2045</div><div style="width:4em;display:inline-block"></div>//
<a name="line2046"></a><div class="linenumber">2046</div><div style="width:4em;display:inline-block"></div>var easySheet = document.createElement("link");
<a name="line2047"></a><div class="linenumber">2047</div><div style="width:4em;display:inline-block"></div>easySheet.setAttribute("rel", "stylesheet");
<a name="line2048"></a><div class="linenumber">2048</div><div style="width:4em;display:inline-block"></div>easySheet.setAttribute("type", "text/css");
<a name="line2049"></a><div class="linenumber">2049</div><div style="width:4em;display:inline-block"></div>easySheet.setAttribute("href", "/easyrtc/easyrtc.css");
<a name="line2050"></a><div class="linenumber">2050</div><div style="width:4em;display:inline-block"></div>var headSection = document.getElementsByTagName("head")[0];
<a name="line2051"></a><div class="linenumber">2051</div><div style="width:4em;display:inline-block"></div>var firstHead = headSection.childNodes[0];
<a name="line2052"></a><div class="linenumber">2052</div><div style="width:4em;display:inline-block"></div>headSection.insertBefore(easySheet, firstHead);
<a name="line2053"></a><div class="linenumber">2053</div><div style="width:2em;display:inline-block"></div>};
<a name="line2054"></a><div class="linenumber">2054</div>
<a name="line2055"></a><div class="linenumber">2055</div><div style="width:2em;display:inline-block"></div>/**
<a name="line2056"></a><div class="linenumber">2056</div><div style="width:2em;display:inline-block"></div>* @private
<a name="line2057"></a><div class="linenumber">2057</div><div style="width:2em;display:inline-block"></div>* @param {String} x
<a name="line2058"></a><div class="linenumber">2058</div><div style="width:2em;display:inline-block"></div>*/
<a name="line2059"></a><div class="linenumber">2059</div><div style="width:2em;display:inline-block"></div>this.formatError = function(x) {
<a name="line2060"></a><div class="linenumber">2060</div><div style="width:4em;display:inline-block"></div>var name, result;
<a name="line2061"></a><div class="linenumber">2061</div><div style="width:4em;display:inline-block"></div>if (x === null || typeof x === 'undefined') {
<a name="line2062"></a><div class="linenumber">2062</div><div style="width:6em;display:inline-block"></div>return "null";
<a name="line2063"></a><div class="linenumber">2063</div><div style="width:4em;display:inline-block"></div>}
<a name="line2064"></a><div class="linenumber">2064</div><div style="width:4em;display:inline-block"></div>if (typeof x === 'string') {
<a name="line2065"></a><div class="linenumber">2065</div><div style="width:6em;display:inline-block"></div>return x;
<a name="line2066"></a><div class="linenumber">2066</div><div style="width:4em;display:inline-block"></div>}
<a name="line2067"></a><div class="linenumber">2067</div><div style="width:4em;display:inline-block"></div>else if (x.type && x.description) {
<a name="line2068"></a><div class="linenumber">2068</div><div style="width:6em;display:inline-block"></div>return x.type + " : " + x.description;
<a name="line2069"></a><div class="linenumber">2069</div><div style="width:4em;display:inline-block"></div>}
<a name="line2070"></a><div class="linenumber">2070</div><div style="width:4em;display:inline-block"></div>else if (typeof x === 'object') {
<a name="line2071"></a><div class="linenumber">2071</div><div style="width:6em;display:inline-block"></div>try {
<a name="line2072"></a><div class="linenumber">2072</div><div style="width:8em;display:inline-block"></div>return JSON.stringify(x);
<a name="line2073"></a><div class="linenumber">2073</div><div style="width:6em;display:inline-block"></div>}
<a name="line2074"></a><div class="linenumber">2074</div><div style="width:6em;display:inline-block"></div>catch (oops) {
<a name="line2075"></a><div class="linenumber">2075</div><div style="width:8em;display:inline-block"></div>result = "{";
<a name="line2076"></a><div class="linenumber">2076</div><div style="width:8em;display:inline-block"></div>for (name in x) {
<a name="line2077"></a><div class="linenumber">2077</div><div style="width:10em;display:inline-block"></div>if (x.hasOwnProperty(name)) {
<a name="line2078"></a><div class="linenumber">2078</div><div style="width:12em;display:inline-block"></div>if (typeof x[name] === 'string') {
<a name="line2079"></a><div class="linenumber">2079</div><div style="width:14em;display:inline-block"></div>result = result + name + "='" + x[name] + "' ";
<a name="line2080"></a><div class="linenumber">2080</div><div style="width:12em;display:inline-block"></div>}
<a name="line2081"></a><div class="linenumber">2081</div><div style="width:10em;display:inline-block"></div>}
<a name="line2082"></a><div class="linenumber">2082</div><div style="width:8em;display:inline-block"></div>}
<a name="line2083"></a><div class="linenumber">2083</div><div style="width:8em;display:inline-block"></div>result = result + "}";
<a name="line2084"></a><div class="linenumber">2084</div><div style="width:8em;display:inline-block"></div>return result;
<a name="line2085"></a><div class="linenumber">2085</div><div style="width:6em;display:inline-block"></div>}
<a name="line2086"></a><div class="linenumber">2086</div><div style="width:4em;display:inline-block"></div>}
<a name="line2087"></a><div class="linenumber">2087</div><div style="width:4em;display:inline-block"></div>else {
<a name="line2088"></a><div class="linenumber">2088</div><div style="width:6em;display:inline-block"></div>return "Strange case";
<a name="line2089"></a><div class="linenumber">2089</div><div style="width:4em;display:inline-block"></div>}
<a name="line2090"></a><div class="linenumber">2090</div><div style="width:2em;display:inline-block"></div>};
<a name="line2091"></a><div class="linenumber">2091</div>
<a name="line2092"></a><div class="linenumber">2092</div><div style="width:2em;display:inline-block"></div>/**
<a name="line2093"></a><div class="linenumber">2093</div><div style="width:2em;display:inline-block"></div>* Initializes your access to a local camera and microphone.
<a name="line2094"></a><div class="linenumber">2094</div><div style="width:2em;display:inline-block"></div>* Failure could be caused a browser that didn't support WebRTC, or by the user not granting permission.
<a name="line2095"></a><div class="linenumber">2095</div><div style="width:2em;display:inline-block"></div>* If you are going to call easyrtc.enableAudio or easyrtc.enableVideo, you need to do it before
<a name="line2096"></a><div class="linenumber">2096</div><div style="width:2em;display:inline-block"></div>* calling easyrtc.initMediaSource.
<a name="line2097"></a><div class="linenumber">2097</div><div style="width:2em;display:inline-block"></div>* @param {function(Object)} successCallback - will be called with localmedia stream on success.
<a name="line2098"></a><div class="linenumber">2098</div><div style="width:2em;display:inline-block"></div>* @param {function(String,String)} errorCallback - is called with an error code and error description.
<a name="line2099"></a><div class="linenumber">2099</div><div style="width:2em;display:inline-block"></div>* @param {String} streamName - an optional name for the media source so you can use multiple cameras and
<a name="line2100"></a><div class="linenumber">2100</div><div style="width:2em;display:inline-block"></div>* screen share simultaneously.
<a name="line2101"></a><div class="linenumber">2101</div><div style="width:2em;display:inline-block"></div>* @example
<a name="line2102"></a><div class="linenumber">2102</div><div style="width:2em;display:inline-block"></div>* easyrtc.initMediaSource(
<a name="line2103"></a><div class="linenumber">2103</div><div style="width:2em;display:inline-block"></div>* function(mediastream){
<a name="line2104"></a><div class="linenumber">2104</div><div style="width:2em;display:inline-block"></div>* easyrtc.setVideoObjectSrc( document.getElementById("mirrorVideo"), mediastream);
<a name="line2105"></a><div class="linenumber">2105</div><div style="width:2em;display:inline-block"></div>* },
<a name="line2106"></a><div class="linenumber">2106</div><div style="width:2em;display:inline-block"></div>* function(errorCode, errorText){
<a name="line2107"></a><div class="linenumber">2107</div><div style="width:2em;display:inline-block"></div>* easyrtc.showError(errorCode, errorText);
<a name="line2108"></a><div class="linenumber">2108</div><div style="width:2em;display:inline-block"></div>* });
<a name="line2109"></a><div class="linenumber">2109</div><div style="width:2em;display:inline-block"></div>*/
<a name="line2110"></a><div class="linenumber">2110</div><div style="width:2em;display:inline-block"></div>this.initMediaSource = function(successCallback, errorCallback, streamName) {
<a name="line2111"></a><div class="linenumber">2111</div>
<a name="line2112"></a><div class="linenumber">2112</div><div style="width:4em;display:inline-block"></div>logDebug("about to request local media");
<a name="line2113"></a><div class="linenumber">2113</div>
<a name="line2114"></a><div class="linenumber">2114</div><div style="width:4em;display:inline-block"></div>if (!streamName) {
<a name="line2115"></a><div class="linenumber">2115</div><div style="width:6em;display:inline-block"></div>streamName = "default";
<a name="line2116"></a><div class="linenumber">2116</div><div style="width:4em;display:inline-block"></div>}
<a name="line2117"></a><div class="linenumber">2117</div>
<a name="line2118"></a><div class="linenumber">2118</div><div style="width:4em;display:inline-block"></div>haveAudioVideo = {
<a name="line2119"></a><div class="linenumber">2119</div><div style="width:6em;display:inline-block"></div>audio: self.audioEnabled,
<a name="line2120"></a><div class="linenumber">2120</div><div style="width:6em;display:inline-block"></div>video: self.videoEnabled
<a name="line2121"></a><div class="linenumber">2121</div><div style="width:4em;display:inline-block"></div>};
<a name="line2122"></a><div class="linenumber">2122</div>
<a name="line2123"></a><div class="linenumber">2123</div><div style="width:4em;display:inline-block"></div>if (!errorCallback) {
<a name="line2124"></a><div class="linenumber">2124</div><div style="width:6em;display:inline-block"></div>errorCallback = function(errorCode, errorText) {
<a name="line2125"></a><div class="linenumber">2125</div><div style="width:8em;display:inline-block"></div>var message = "easyrtc.initMediaSource: " + self.formatError(errorText);
<a name="line2126"></a><div class="linenumber">2126</div><div style="width:8em;display:inline-block"></div>logDebug(message);
<a name="line2127"></a><div class="linenumber">2127</div><div style="width:8em;display:inline-block"></div>self.showError(self.errCodes.MEDIA_ERR, message);
<a name="line2128"></a><div class="linenumber">2128</div><div style="width:6em;display:inline-block"></div>};
<a name="line2129"></a><div class="linenumber">2129</div><div style="width:4em;display:inline-block"></div>}
<a name="line2130"></a><div class="linenumber">2130</div>
<a name="line2131"></a><div class="linenumber">2131</div><div style="width:4em;display:inline-block"></div>if (!self.supportsGetUserMedia()) {
<a name="line2132"></a><div class="linenumber">2132</div><div style="width:6em;display:inline-block"></div>errorCallback(self.errCodes.MEDIA_ERR, self.getConstantString("noWebrtcSupport"));
<a name="line2133"></a><div class="linenumber">2133</div><div style="width:6em;display:inline-block"></div>return;
<a name="line2134"></a><div class="linenumber">2134</div><div style="width:4em;display:inline-block"></div>}
<a name="line2135"></a><div class="linenumber">2135</div>
<a name="line2136"></a><div class="linenumber">2136</div><div style="width:4em;display:inline-block"></div>if (!successCallback) {
<a name="line2137"></a><div class="linenumber">2137</div><div style="width:6em;display:inline-block"></div>self.showError(self.errCodes.DEVELOPER_ERR,
<a name="line2138"></a><div class="linenumber">2138</div><div style="width:10em;display:inline-block"></div>"easyrtc.initMediaSource not supplied a successCallback");
<a name="line2139"></a><div class="linenumber">2139</div><div style="width:6em;display:inline-block"></div>return;
<a name="line2140"></a><div class="linenumber">2140</div><div style="width:4em;display:inline-block"></div>}
<a name="line2141"></a><div class="linenumber">2141</div>
<a name="line2142"></a><div class="linenumber">2142</div><div style="width:4em;display:inline-block"></div>var mode = self.getUserMediaConstraints();
<a name="line2143"></a><div class="linenumber">2143</div><div style="width:4em;display:inline-block"></div>/** @private
<a name="line2144"></a><div class="linenumber">2144</div><div style="width:4em;display:inline-block"></div>* @param {Object} stream - A mediaStream object.
<a name="line2145"></a><div class="linenumber">2145</div><div style="width:4em;display:inline-block"></div>* */
<a name="line2146"></a><div class="linenumber">2146</div><div style="width:4em;display:inline-block"></div>var onUserMediaSuccess = function(stream) {
<a name="line2147"></a><div class="linenumber">2147</div><div style="width:6em;display:inline-block"></div>logDebug("getUserMedia success callback entered");
<a name="line2148"></a><div class="linenumber">2148</div><div style="width:6em;display:inline-block"></div>logDebug("successfully got local media");
<a name="line2149"></a><div class="linenumber">2149</div>
<a name="line2150"></a><div class="linenumber">2150</div><div style="width:6em;display:inline-block"></div>stream.streamName = streamName;
<a name="line2151"></a><div class="linenumber">2151</div><div style="width:6em;display:inline-block"></div>registerLocalMediaStreamByName(stream, streamName);
<a name="line2152"></a><div class="linenumber">2152</div><div style="width:6em;display:inline-block"></div>var videoObj, triesLeft, tryToGetSize, ele;
<a name="line2153"></a><div class="linenumber">2153</div><div style="width:6em;display:inline-block"></div>if (haveAudioVideo.video) {
<a name="line2154"></a><div class="linenumber">2154</div><div style="width:8em;display:inline-block"></div>videoObj = document.createElement('video');
<a name="line2155"></a><div class="linenumber">2155</div><div style="width:8em;display:inline-block"></div>videoObj.muted = true;
<a name="line2156"></a><div class="linenumber">2156</div><div style="width:8em;display:inline-block"></div>triesLeft = 30;
<a name="line2157"></a><div class="linenumber">2157</div><div style="width:8em;display:inline-block"></div>tryToGetSize = function() {
<a name="line2158"></a><div class="linenumber">2158</div><div style="width:10em;display:inline-block"></div>if (videoObj.videoWidth > 0 || triesLeft < 0) {
<a name="line2159"></a><div class="linenumber">2159</div><div style="width:12em;display:inline-block"></div>self.nativeVideoWidth = videoObj.videoWidth;
<a name="line2160"></a><div class="linenumber">2160</div><div style="width:12em;display:inline-block"></div>self.nativeVideoHeight = videoObj.videoHeight;
<a name="line2161"></a><div class="linenumber">2161</div><div style="width:12em;display:inline-block"></div>if (self._desiredVideoProperties.height &&
<a name="line2162"></a><div class="linenumber">2162</div><div style="width:16em;display:inline-block"></div>(self.nativeVideoHeight !== self._desiredVideoProperties.height ||
<a name="line2163"></a><div class="linenumber">2163</div><div style="width:20em;display:inline-block"></div>self.nativeVideoWidth !== self._desiredVideoProperties.width)) {
<a name="line2164"></a><div class="linenumber">2164</div><div style="width:14em;display:inline-block"></div>self.showError(self.errCodes.MEDIA_WARNING,
<a name="line2165"></a><div class="linenumber">2165</div><div style="width:18em;display:inline-block"></div>self.format(self.getConstantString("resolutionWarning"),
<a name="line2166"></a><div class="linenumber">2166</div><div style="width:18em;display:inline-block"></div>self._desiredVideoProperties.width, self._desiredVideoProperties.height,
<a name="line2167"></a><div class="linenumber">2167</div><div style="width:18em;display:inline-block"></div>self.nativeVideoWidth, self.nativeVideoHeight));
<a name="line2168"></a><div class="linenumber">2168</div><div style="width:12em;display:inline-block"></div>}
<a name="line2169"></a><div class="linenumber">2169</div><div style="width:12em;display:inline-block"></div>self.setVideoObjectSrc(videoObj, null);
<a name="line2170"></a><div class="linenumber">2170</div><div style="width:12em;display:inline-block"></div>if (videoObj.removeNode) {
<a name="line2171"></a><div class="linenumber">2171</div><div style="width:14em;display:inline-block"></div>videoObj.removeNode(true);
<a name="line2172"></a><div class="linenumber">2172</div><div style="width:12em;display:inline-block"></div>}
<a name="line2173"></a><div class="linenumber">2173</div><div style="width:12em;display:inline-block"></div>else {
<a name="line2174"></a><div class="linenumber">2174</div><div style="width:14em;display:inline-block"></div>ele = document.createElement('div');
<a name="line2175"></a><div class="linenumber">2175</div><div style="width:14em;display:inline-block"></div>ele.appendChild(videoObj);
<a name="line2176"></a><div class="linenumber">2176</div><div style="width:14em;display:inline-block"></div>ele.removeChild(videoObj);
<a name="line2177"></a><div class="linenumber">2177</div><div style="width:12em;display:inline-block"></div>}
<a name="line2178"></a><div class="linenumber">2178</div>
<a name="line2179"></a><div class="linenumber">2179</div><div style="width:12em;display:inline-block"></div>updateConfigurationInfo();
<a name="line2180"></a><div class="linenumber">2180</div><div style="width:12em;display:inline-block"></div>if (successCallback) {
<a name="line2181"></a><div class="linenumber">2181</div><div style="width:14em;display:inline-block"></div>successCallback(stream);
<a name="line2182"></a><div class="linenumber">2182</div><div style="width:12em;display:inline-block"></div>}
<a name="line2183"></a><div class="linenumber">2183</div><div style="width:10em;display:inline-block"></div>}
<a name="line2184"></a><div class="linenumber">2184</div><div style="width:10em;display:inline-block"></div>else {
<a name="line2185"></a><div class="linenumber">2185</div><div style="width:12em;display:inline-block"></div>triesLeft -= 1;
<a name="line2186"></a><div class="linenumber">2186</div><div style="width:12em;display:inline-block"></div>setTimeout(tryToGetSize, 300);
<a name="line2187"></a><div class="linenumber">2187</div><div style="width:10em;display:inline-block"></div>}
<a name="line2188"></a><div class="linenumber">2188</div><div style="width:8em;display:inline-block"></div>};
<a name="line2189"></a><div class="linenumber">2189</div><div style="width:8em;display:inline-block"></div>self.setVideoObjectSrc(videoObj, stream);
<a name="line2190"></a><div class="linenumber">2190</div><div style="width:8em;display:inline-block"></div>tryToGetSize();
<a name="line2191"></a><div class="linenumber">2191</div><div style="width:6em;display:inline-block"></div>}
<a name="line2192"></a><div class="linenumber">2192</div><div style="width:6em;display:inline-block"></div>else {
<a name="line2193"></a><div class="linenumber">2193</div><div style="width:8em;display:inline-block"></div>updateConfigurationInfo();
<a name="line2194"></a><div class="linenumber">2194</div><div style="width:8em;display:inline-block"></div>if (successCallback) {
<a name="line2195"></a><div class="linenumber">2195</div><div style="width:10em;display:inline-block"></div>successCallback(stream);
<a name="line2196"></a><div class="linenumber">2196</div><div style="width:8em;display:inline-block"></div>}
<a name="line2197"></a><div class="linenumber">2197</div><div style="width:6em;display:inline-block"></div>}
<a name="line2198"></a><div class="linenumber">2198</div><div style="width:4em;display:inline-block"></div>};
<a name="line2199"></a><div class="linenumber">2199</div>
<a name="line2200"></a><div class="linenumber">2200</div><div style="width:4em;display:inline-block"></div>/**
<a name="line2201"></a><div class="linenumber">2201</div><div style="width:4em;display:inline-block"></div>* @private
<a name="line2202"></a><div class="linenumber">2202</div><div style="width:4em;display:inline-block"></div>* @param {String} error
<a name="line2203"></a><div class="linenumber">2203</div><div style="width:4em;display:inline-block"></div>*/
<a name="line2204"></a><div class="linenumber">2204</div><div style="width:4em;display:inline-block"></div>var onUserMediaError = function(error) {
<a name="line2205"></a><div class="linenumber">2205</div><div style="width:6em;display:inline-block"></div>logDebug("getusermedia failed");
<a name="line2206"></a><div class="linenumber">2206</div><div style="width:6em;display:inline-block"></div>logDebug("failed to get local media");
<a name="line2207"></a><div class="linenumber">2207</div><div style="width:6em;display:inline-block"></div>var errText;
<a name="line2208"></a><div class="linenumber">2208</div><div style="width:6em;display:inline-block"></div>if (typeof error === 'string') {
<a name="line2209"></a><div class="linenumber">2209</div><div style="width:8em;display:inline-block"></div>errText = error;
<a name="line2210"></a><div class="linenumber">2210</div><div style="width:6em;display:inline-block"></div>}
<a name="line2211"></a><div class="linenumber">2211</div><div style="width:6em;display:inline-block"></div>else if (error.name) {
<a name="line2212"></a><div class="linenumber">2212</div><div style="width:8em;display:inline-block"></div>errText = error.name;
<a name="line2213"></a><div class="linenumber">2213</div><div style="width:6em;display:inline-block"></div>}
<a name="line2214"></a><div class="linenumber">2214</div><div style="width:6em;display:inline-block"></div>else {
<a name="line2215"></a><div class="linenumber">2215</div><div style="width:8em;display:inline-block"></div>errText = "Unknown";
<a name="line2216"></a><div class="linenumber">2216</div><div style="width:6em;display:inline-block"></div>}
<a name="line2217"></a><div class="linenumber">2217</div><div style="width:6em;display:inline-block"></div>if (errorCallback) {
<a name="line2218"></a><div class="linenumber">2218</div><div style="width:8em;display:inline-block"></div>logDebug("invoking error callback", errText);
<a name="line2219"></a><div class="linenumber">2219</div><div style="width:8em;display:inline-block"></div>errorCallback(self.errCodes.MEDIA_ERR, self.format(self.getConstantString("gumFailed"), errText));
<a name="line2220"></a><div class="linenumber">2220</div><div style="width:6em;display:inline-block"></div>}
<a name="line2221"></a><div class="linenumber">2221</div><div style="width:6em;display:inline-block"></div>closeLocalMediaStreamByName(streamName);
<a name="line2222"></a><div class="linenumber">2222</div><div style="width:6em;display:inline-block"></div>haveAudioVideo = {
<a name="line2223"></a><div class="linenumber">2223</div><div style="width:8em;display:inline-block"></div>audio: false,
<a name="line2224"></a><div class="linenumber">2224</div><div style="width:8em;display:inline-block"></div>video: false
<a name="line2225"></a><div class="linenumber">2225</div><div style="width:6em;display:inline-block"></div>};
<a name="line2226"></a><div class="linenumber">2226</div><div style="width:6em;display:inline-block"></div>updateConfigurationInfo();
<a name="line2227"></a><div class="linenumber">2227</div><div style="width:4em;display:inline-block"></div>};
<a name="line2228"></a><div class="linenumber">2228</div>
<a name="line2229"></a><div class="linenumber">2229</div><div style="width:4em;display:inline-block"></div>if (!self.audioEnabled && !self.videoEnabled) {
<a name="line2230"></a><div class="linenumber">2230</div><div style="width:6em;display:inline-block"></div>onUserMediaError(self.getConstantString("requireAudioOrVideo"));
<a name="line2231"></a><div class="linenumber">2231</div><div style="width:6em;display:inline-block"></div>return;
<a name="line2232"></a><div class="linenumber">2232</div><div style="width:4em;display:inline-block"></div>}
<a name="line2233"></a><div class="linenumber">2233</div>
<a name="line2234"></a><div class="linenumber">2234</div><div style="width:4em;display:inline-block"></div>function getCurrentTime() {
<a name="line2235"></a><div class="linenumber">2235</div><div style="width:6em;display:inline-block"></div>return (new Date()).getTime();
<a name="line2236"></a><div class="linenumber">2236</div><div style="width:4em;display:inline-block"></div>}
<a name="line2237"></a><div class="linenumber">2237</div>
<a name="line2238"></a><div class="linenumber">2238</div><div style="width:4em;display:inline-block"></div>var firstCallTime;
<a name="line2239"></a><div class="linenumber">2239</div><div style="width:4em;display:inline-block"></div>function tryAgain(err) {
<a name="line2240"></a><div class="linenumber">2240</div><div style="width:6em;display:inline-block"></div>var currentTime = getCurrentTime();
<a name="line2241"></a><div class="linenumber">2241</div><div style="width:6em;display:inline-block"></div>if (currentTime < firstCallTime + 1000) {
<a name="line2242"></a><div class="linenumber">2242</div><div style="width:8em;display:inline-block"></div>logDebug("Trying getUserMedia a second time");
<a name="line2243"></a><div class="linenumber">2243</div><div style="width:8em;display:inline-block"></div>try {
<a name="line2244"></a><div class="linenumber">2244</div><div style="width:10em;display:inline-block"></div>navigator.getUserMedia(mode, onUserMediaSuccess, onUserMediaError);
<a name="line2245"></a><div class="linenumber">2245</div><div style="width:8em;display:inline-block"></div>} catch (e) {
<a name="line2246"></a><div class="linenumber">2246</div><div style="width:10em;display:inline-block"></div>onUserMediaError(err);
<a name="line2247"></a><div class="linenumber">2247</div><div style="width:8em;display:inline-block"></div>}
<a name="line2248"></a><div class="linenumber">2248</div><div style="width:6em;display:inline-block"></div>}
<a name="line2249"></a><div class="linenumber">2249</div><div style="width:6em;display:inline-block"></div>else {
<a name="line2250"></a><div class="linenumber">2250</div><div style="width:8em;display:inline-block"></div>onUserMediaError(err);
<a name="line2251"></a><div class="linenumber">2251</div><div style="width:6em;display:inline-block"></div>}
<a name="line2252"></a><div class="linenumber">2252</div><div style="width:4em;display:inline-block"></div>}
<a name="line2253"></a><div class="linenumber">2253</div>
<a name="line2254"></a><div class="linenumber">2254</div><div style="width:4em;display:inline-block"></div>//
<a name="line2255"></a><div class="linenumber">2255</div><div style="width:4em;display:inline-block"></div>// getUserMedia sometimes fails the first time I call it. I suspect it's a page loading
<a name="line2256"></a><div class="linenumber">2256</div><div style="width:4em;display:inline-block"></div>// issue. So I'm going to try adding a 1 second delay to allow things to settle down first.
<a name="line2257"></a><div class="linenumber">2257</div><div style="width:4em;display:inline-block"></div>// In addition, I'm going to try again after 3 seconds.
<a name="line2258"></a><div class="linenumber">2258</div><div style="width:4em;display:inline-block"></div>//
<a name="line2259"></a><div class="linenumber">2259</div><div style="width:4em;display:inline-block"></div>try {
<a name="line2260"></a><div class="linenumber">2260</div><div style="width:6em;display:inline-block"></div>firstCallTime = getCurrentTime();
<a name="line2261"></a><div class="linenumber">2261</div><div style="width:6em;display:inline-block"></div>navigator.getUserMedia(mode, onUserMediaSuccess, tryAgain);
<a name="line2262"></a><div class="linenumber">2262</div><div style="width:4em;display:inline-block"></div>} catch (err) {
<a name="line2263"></a><div class="linenumber">2263</div><div style="width:6em;display:inline-block"></div>tryAgain(err);
<a name="line2264"></a><div class="linenumber">2264</div><div style="width:4em;display:inline-block"></div>}
<a name="line2265"></a><div class="linenumber">2265</div><div style="width:2em;display:inline-block"></div>};
<a name="line2266"></a><div class="linenumber">2266</div>
<a name="line2267"></a><div class="linenumber">2267</div><div style="width:2em;display:inline-block"></div>/**
<a name="line2268"></a><div class="linenumber">2268</div><div style="width:2em;display:inline-block"></div>* Sets the callback used to decide whether to accept or reject an incoming call.
<a name="line2269"></a><div class="linenumber">2269</div><div style="width:2em;display:inline-block"></div>* @param {Function} acceptCheck takes the arguments (callerEasyrtcid, acceptor).
<a name="line2270"></a><div class="linenumber">2270</div><div style="width:2em;display:inline-block"></div>* The acceptCheck callback is passed an easyrtcid and an acceptor function. The acceptor function should be called with either
<a name="line2271"></a><div class="linenumber">2271</div><div style="width:2em;display:inline-block"></div>* a true value (accept the call) or false value( reject the call) as it's first argument, and optionally,
<a name="line2272"></a><div class="linenumber">2272</div><div style="width:2em;display:inline-block"></div>* an array of local media streamNames as a second argument.
<a name="line2273"></a><div class="linenumber">2273</div><div style="width:2em;display:inline-block"></div>* @example
<a name="line2274"></a><div class="linenumber">2274</div><div style="width:2em;display:inline-block"></div>* easyrtc.setAcceptChecker( function(easyrtcid, acceptor){
<a name="line2275"></a><div class="linenumber">2275</div><div style="width:2em;display:inline-block"></div>* if( easyrtc.idToName(easyrtcid) === 'Fred' ){
<a name="line2276"></a><div class="linenumber">2276</div><div style="width:2em;display:inline-block"></div>* acceptor(true);
<a name="line2277"></a><div class="linenumber">2277</div><div style="width:2em;display:inline-block"></div>* }
<a name="line2278"></a><div class="linenumber">2278</div><div style="width:2em;display:inline-block"></div>* else if( easyrtc.idToName(easyrtcid) === 'Barney' ){
<a name="line2279"></a><div class="linenumber">2279</div><div style="width:2em;display:inline-block"></div>* setTimeout( function(){
<a name="line2280"></a><div class="linenumber">2280</div><div style="width:2em;display:inline-block"></div>acceptor(true, ['myOtherCam']); // myOtherCam presumed to a streamName
<a name="line2281"></a><div class="linenumber">2281</div><div style="width:2em;display:inline-block"></div>}, 10000);
<a name="line2282"></a><div class="linenumber">2282</div><div style="width:2em;display:inline-block"></div>* }
<a name="line2283"></a><div class="linenumber">2283</div><div style="width:2em;display:inline-block"></div>* else{
<a name="line2284"></a><div class="linenumber">2284</div><div style="width:2em;display:inline-block"></div>* acceptor(false);
<a name="line2285"></a><div class="linenumber">2285</div><div style="width:2em;display:inline-block"></div>* }
<a name="line2286"></a><div class="linenumber">2286</div><div style="width:2em;display:inline-block"></div>* });
<a name="line2287"></a><div class="linenumber">2287</div><div style="width:2em;display:inline-block"></div>*/
<a name="line2288"></a><div class="linenumber">2288</div><div style="width:2em;display:inline-block"></div>this.setAcceptChecker = function(acceptCheck) {
<a name="line2289"></a><div class="linenumber">2289</div><div style="width:4em;display:inline-block"></div>self.acceptCheck = acceptCheck;
<a name="line2290"></a><div class="linenumber">2290</div><div style="width:2em;display:inline-block"></div>};
<a name="line2291"></a><div class="linenumber">2291</div>
<a name="line2292"></a><div class="linenumber">2292</div><div style="width:2em;display:inline-block"></div>/**
<a name="line2293"></a><div class="linenumber">2293</div><div style="width:2em;display:inline-block"></div>* easyrtc.setStreamAcceptor sets a callback to receive media streams from other peers, independent
<a name="line2294"></a><div class="linenumber">2294</div><div style="width:2em;display:inline-block"></div>* of where the call was initiated (caller or callee).
<a name="line2295"></a><div class="linenumber">2295</div><div style="width:2em;display:inline-block"></div>* @param {Function} acceptor takes arguments (caller, mediaStream, mediaStreamName)
<a name="line2296"></a><div class="linenumber">2296</div><div style="width:2em;display:inline-block"></div>* @example
<a name="line2297"></a><div class="linenumber">2297</div><div style="width:2em;display:inline-block"></div>* easyrtc.setStreamAcceptor(function(easyrtcid, stream, streamName){
<a name="line2298"></a><div class="linenumber">2298</div><div style="width:2em;display:inline-block"></div>* document.getElementById('callerName').innerHTML = easyrtc.idToName(easyrtcid);
<a name="line2299"></a><div class="linenumber">2299</div><div style="width:2em;display:inline-block"></div>* easyrtc.setVideoObjectSrc( document.getElementById("callerVideo"), stream);
<a name="line2300"></a><div class="linenumber">2300</div><div style="width:2em;display:inline-block"></div>* });
<a name="line2301"></a><div class="linenumber">2301</div><div style="width:2em;display:inline-block"></div>*/
<a name="line2302"></a><div class="linenumber">2302</div><div style="width:2em;display:inline-block"></div>this.setStreamAcceptor = function(acceptor) {
<a name="line2303"></a><div class="linenumber">2303</div><div style="width:4em;display:inline-block"></div>self.streamAcceptor = acceptor;
<a name="line2304"></a><div class="linenumber">2304</div><div style="width:2em;display:inline-block"></div>};
<a name="line2305"></a><div class="linenumber">2305</div>
<a name="line2306"></a><div class="linenumber">2306</div><div style="width:2em;display:inline-block"></div>/** Sets the easyrtc.onError field to a user specified function.
<a name="line2307"></a><div class="linenumber">2307</div><div style="width:2em;display:inline-block"></div>* @param {Function} errListener takes an object of the form {errorCode: String, errorText: String}
<a name="line2308"></a><div class="linenumber">2308</div><div style="width:2em;display:inline-block"></div>* @example
<a name="line2309"></a><div class="linenumber">2309</div><div style="width:2em;display:inline-block"></div>* easyrtc.setOnError( function(errorObject){
<a name="line2310"></a><div class="linenumber">2310</div><div style="width:2em;display:inline-block"></div>* document.getElementById("errMessageDiv").innerHTML += errorObject.errorText;
<a name="line2311"></a><div class="linenumber">2311</div><div style="width:2em;display:inline-block"></div>* });
<a name="line2312"></a><div class="linenumber">2312</div><div style="width:2em;display:inline-block"></div>*/
<a name="line2313"></a><div class="linenumber">2313</div><div style="width:2em;display:inline-block"></div>self.setOnError = function(errListener) {
<a name="line2314"></a><div class="linenumber">2314</div><div style="width:4em;display:inline-block"></div>self.onError = errListener;
<a name="line2315"></a><div class="linenumber">2315</div><div style="width:2em;display:inline-block"></div>};
<a name="line2316"></a><div class="linenumber">2316</div>
<a name="line2317"></a><div class="linenumber">2317</div><div style="width:2em;display:inline-block"></div>/**
<a name="line2318"></a><div class="linenumber">2318</div><div style="width:2em;display:inline-block"></div>* Sets the callCancelled callback. This will be called when a remote user
<a name="line2319"></a><div class="linenumber">2319</div><div style="width:2em;display:inline-block"></div>* initiates a call to you, but does a "hangup" before you have a chance to get his video stream.
<a name="line2320"></a><div class="linenumber">2320</div><div style="width:2em;display:inline-block"></div>* @param {Function} callCancelled takes an easyrtcid as an argument and a boolean that indicates whether
<a name="line2321"></a><div class="linenumber">2321</div><div style="width:2em;display:inline-block"></div>* the call was explicitly cancelled remotely (true), or actually accepted by the user attempting a call to
<a name="line2322"></a><div class="linenumber">2322</div><div style="width:2em;display:inline-block"></div>* the same party.
<a name="line2323"></a><div class="linenumber">2323</div><div style="width:2em;display:inline-block"></div>* @example
<a name="line2324"></a><div class="linenumber">2324</div><div style="width:2em;display:inline-block"></div>* easyrtc.setCallCancelled( function(easyrtcid, explicitlyCancelled){
<a name="line2325"></a><div class="linenumber">2325</div><div style="width:2em;display:inline-block"></div>* if( explicitlyCancelled ){
<a name="line2326"></a><div class="linenumber">2326</div><div style="width:2em;display:inline-block"></div>* console.log(easyrtc.idToName(easyrtcid) + " stopped trying to reach you");
<a name="line2327"></a><div class="linenumber">2327</div><div style="width:2em;display:inline-block"></div>* }
<a name="line2328"></a><div class="linenumber">2328</div><div style="width:2em;display:inline-block"></div>* else{
<a name="line2329"></a><div class="linenumber">2329</div><div style="width:2em;display:inline-block"></div>* console.log("Implicitly called " + easyrtc.idToName(easyrtcid));
<a name="line2330"></a><div class="linenumber">2330</div><div style="width:2em;display:inline-block"></div>* }
<a name="line2331"></a><div class="linenumber">2331</div><div style="width:2em;display:inline-block"></div>* });
<a name="line2332"></a><div class="linenumber">2332</div><div style="width:2em;display:inline-block"></div>*/
<a name="line2333"></a><div class="linenumber">2333</div><div style="width:2em;display:inline-block"></div>this.setCallCancelled = function(callCancelled) {
<a name="line2334"></a><div class="linenumber">2334</div><div style="width:4em;display:inline-block"></div>self.callCancelled = callCancelled;
<a name="line2335"></a><div class="linenumber">2335</div><div style="width:2em;display:inline-block"></div>};
<a name="line2336"></a><div class="linenumber">2336</div>
<a name="line2337"></a><div class="linenumber">2337</div><div style="width:2em;display:inline-block"></div>/** Sets a callback to receive notification of a media stream closing. The usual
<a name="line2338"></a><div class="linenumber">2338</div><div style="width:2em;display:inline-block"></div>* use of this is to clear the source of your video object so you aren't left with
<a name="line2339"></a><div class="linenumber">2339</div><div style="width:2em;display:inline-block"></div>* the last frame of the video displayed on it.
<a name="line2340"></a><div class="linenumber">2340</div><div style="width:2em;display:inline-block"></div>* @param {Function} onStreamClosed takes an easyrtcid as it's first parameter, the stream as it's second argument, and name of the video stream as it's third.
<a name="line2341"></a><div class="linenumber">2341</div><div style="width:2em;display:inline-block"></div>* @example
<a name="line2342"></a><div class="linenumber">2342</div><div style="width:2em;display:inline-block"></div>* easyrtc.setOnStreamClosed( function(easyrtcid, stream, streamName){
<a name="line2343"></a><div class="linenumber">2343</div><div style="width:2em;display:inline-block"></div>* easyrtc.setVideoObjectSrc( document.getElementById("callerVideo"), "");
<a name="line2344"></a><div class="linenumber">2344</div><div style="width:2em;display:inline-block"></div>* ( easyrtc.idToName(easyrtcid) + " closed stream " + stream.id + " " + streamName);
<a name="line2345"></a><div class="linenumber">2345</div><div style="width:2em;display:inline-block"></div>* });
<a name="line2346"></a><div class="linenumber">2346</div><div style="width:2em;display:inline-block"></div>*/
<a name="line2347"></a><div class="linenumber">2347</div><div style="width:2em;display:inline-block"></div>this.setOnStreamClosed = function(onStreamClosed) {
<a name="line2348"></a><div class="linenumber">2348</div><div style="width:4em;display:inline-block"></div>self.onStreamClosed = onStreamClosed;
<a name="line2349"></a><div class="linenumber">2349</div><div style="width:2em;display:inline-block"></div>};
<a name="line2350"></a><div class="linenumber">2350</div>
<a name="line2351"></a><div class="linenumber">2351</div><div style="width:2em;display:inline-block"></div>/**
<a name="line2352"></a><div class="linenumber">2352</div><div style="width:2em;display:inline-block"></div>* Sets a listener for data sent from another client (either peer to peer or via websockets).
<a name="line2353"></a><div class="linenumber">2353</div><div style="width:2em;display:inline-block"></div>* If no msgType or source is provided, the listener applies to all events that aren't otherwise handled.
<a name="line2354"></a><div class="linenumber">2354</div><div style="width:2em;display:inline-block"></div>* If a msgType but no source is provided, the listener applies to all messages of that msgType that aren't otherwise handled.
<a name="line2355"></a><div class="linenumber">2355</div><div style="width:2em;display:inline-block"></div>* If a msgType and a source is provided, the listener applies to only message of the specified type coming from the specified peer.
<a name="line2356"></a><div class="linenumber">2356</div><div style="width:2em;display:inline-block"></div>* The most specific case takes priority over the more general.
<a name="line2357"></a><div class="linenumber">2357</div><div style="width:2em;display:inline-block"></div>* @param {Function} listener has the signature (easyrtcid, msgType, msgData, targeting).
<a name="line2358"></a><div class="linenumber">2358</div><div style="width:2em;display:inline-block"></div>* msgType is a string. targeting is null if the message was received using WebRTC data channels, otherwise it
<a name="line2359"></a><div class="linenumber">2359</div><div style="width:2em;display:inline-block"></div>* is an object that contains one or more of the following string valued elements {targetEasyrtcid, targetGroup, targetRoom}.
<a name="line2360"></a><div class="linenumber">2360</div><div style="width:2em;display:inline-block"></div>* @param {String} msgType - a string, optional.
<a name="line2361"></a><div class="linenumber">2361</div><div style="width:2em;display:inline-block"></div>* @param {String} source - the sender's easyrtcid, optional.
<a name="line2362"></a><div class="linenumber">2362</div><div style="width:2em;display:inline-block"></div>* @example
<a name="line2363"></a><div class="linenumber">2363</div><div style="width:2em;display:inline-block"></div>* easyrtc.setPeerListener( function(easyrtcid, msgType, msgData, targeting){
<a name="line2364"></a><div class="linenumber">2364</div><div style="width:2em;display:inline-block"></div>* console.log("From " + easyrtc.idToName(easyrtcid) +
<a name="line2365"></a><div class="linenumber">2365</div><div style="width:2em;display:inline-block"></div>* " sent the following data " + JSON.stringify(msgData));
<a name="line2366"></a><div class="linenumber">2366</div><div style="width:2em;display:inline-block"></div>* });
<a name="line2367"></a><div class="linenumber">2367</div><div style="width:2em;display:inline-block"></div>* easyrtc.setPeerListener( function(easyrtcid, msgType, msgData, targeting){
<a name="line2368"></a><div class="linenumber">2368</div><div style="width:2em;display:inline-block"></div>* console.log("From " + easyrtc.idToName(easyrtcid) +
<a name="line2369"></a><div class="linenumber">2369</div><div style="width:2em;display:inline-block"></div>* " sent the following data " + JSON.stringify(msgData));
<a name="line2370"></a><div class="linenumber">2370</div><div style="width:2em;display:inline-block"></div>* }, 'food', 'dkdjdekj44--');
<a name="line2371"></a><div class="linenumber">2371</div><div style="width:2em;display:inline-block"></div>* easyrtc.setPeerListener( function(easyrtcid, msgType, msgData, targeting){
<a name="line2372"></a><div class="linenumber">2372</div><div style="width:2em;display:inline-block"></div>* console.log("From " + easyrtcid +
<a name="line2373"></a><div class="linenumber">2373</div><div style="width:2em;display:inline-block"></div>* " sent the following data " + JSON.stringify(msgData));
<a name="line2374"></a><div class="linenumber">2374</div><div style="width:2em;display:inline-block"></div>* }, 'drink');
<a name="line2375"></a><div class="linenumber">2375</div><div style="width:2em;display:inline-block"></div>*
<a name="line2376"></a><div class="linenumber">2376</div><div style="width:2em;display:inline-block"></div>*
<a name="line2377"></a><div class="linenumber">2377</div><div style="width:2em;display:inline-block"></div>*/
<a name="line2378"></a><div class="linenumber">2378</div><div style="width:2em;display:inline-block"></div>this.setPeerListener = function(listener, msgType, source) {
<a name="line2379"></a><div class="linenumber">2379</div><div style="width:4em;display:inline-block"></div>if (!msgType) {
<a name="line2380"></a><div class="linenumber">2380</div><div style="width:6em;display:inline-block"></div>receivePeer.cb = listener;
<a name="line2381"></a><div class="linenumber">2381</div><div style="width:4em;display:inline-block"></div>}
<a name="line2382"></a><div class="linenumber">2382</div><div style="width:4em;display:inline-block"></div>else {
<a name="line2383"></a><div class="linenumber">2383</div><div style="width:6em;display:inline-block"></div>if (!receivePeer.msgTypes[msgType]) {
<a name="line2384"></a><div class="linenumber">2384</div><div style="width:8em;display:inline-block"></div>receivePeer.msgTypes[msgType] = {sources: {}};
<a name="line2385"></a><div class="linenumber">2385</div><div style="width:6em;display:inline-block"></div>}
<a name="line2386"></a><div class="linenumber">2386</div><div style="width:6em;display:inline-block"></div>if (!source) {
<a name="line2387"></a><div class="linenumber">2387</div><div style="width:8em;display:inline-block"></div>receivePeer.msgTypes[msgType].cb = listener;
<a name="line2388"></a><div class="linenumber">2388</div><div style="width:6em;display:inline-block"></div>}
<a name="line2389"></a><div class="linenumber">2389</div><div style="width:6em;display:inline-block"></div>else {
<a name="line2390"></a><div class="linenumber">2390</div><div style="width:8em;display:inline-block"></div>receivePeer.msgTypes[msgType].sources[source] = {cb: listener};
<a name="line2391"></a><div class="linenumber">2391</div><div style="width:6em;display:inline-block"></div>}
<a name="line2392"></a><div class="linenumber">2392</div><div style="width:4em;display:inline-block"></div>}
<a name="line2393"></a><div class="linenumber">2393</div><div style="width:2em;display:inline-block"></div>};
<a name="line2394"></a><div class="linenumber">2394</div><div style="width:2em;display:inline-block"></div>/* This function serves to distribute peer messages to the various peer listeners */
<a name="line2395"></a><div class="linenumber">2395</div><div style="width:2em;display:inline-block"></div>/** @private
<a name="line2396"></a><div class="linenumber">2396</div><div style="width:2em;display:inline-block"></div>* @param {String} easyrtcid
<a name="line2397"></a><div class="linenumber">2397</div><div style="width:2em;display:inline-block"></div>* @param {Object} msg - needs to contain a msgType and a msgData field.
<a name="line2398"></a><div class="linenumber">2398</div><div style="width:2em;display:inline-block"></div>* @param {Object} targeting
<a name="line2399"></a><div class="linenumber">2399</div><div style="width:2em;display:inline-block"></div>*/
<a name="line2400"></a><div class="linenumber">2400</div><div style="width:2em;display:inline-block"></div>this.receivePeerDistribute = function(easyrtcid, msg, targeting) {
<a name="line2401"></a><div class="linenumber">2401</div><div style="width:4em;display:inline-block"></div>var msgType = msg.msgType;
<a name="line2402"></a><div class="linenumber">2402</div><div style="width:4em;display:inline-block"></div>var msgData = msg.msgData;
<a name="line2403"></a><div class="linenumber">2403</div><div style="width:4em;display:inline-block"></div>if (!msgType) {
<a name="line2404"></a><div class="linenumber">2404</div><div style="width:6em;display:inline-block"></div>logDebug("received peer message without msgType", msg);
<a name="line2405"></a><div class="linenumber">2405</div><div style="width:6em;display:inline-block"></div>return;
<a name="line2406"></a><div class="linenumber">2406</div><div style="width:4em;display:inline-block"></div>}
<a name="line2407"></a><div class="linenumber">2407</div>
<a name="line2408"></a><div class="linenumber">2408</div><div style="width:4em;display:inline-block"></div>if (receivePeer.msgTypes[msgType]) {
<a name="line2409"></a><div class="linenumber">2409</div><div style="width:6em;display:inline-block"></div>if (receivePeer.msgTypes[msgType].sources[easyrtcid] &&
<a name="line2410"></a><div class="linenumber">2410</div><div style="width:10em;display:inline-block"></div>receivePeer.msgTypes[msgType].sources[easyrtcid].cb) {
<a name="line2411"></a><div class="linenumber">2411</div><div style="width:8em;display:inline-block"></div>receivePeer.msgTypes[msgType].sources[easyrtcid].cb(easyrtcid, msgType, msgData, targeting);
<a name="line2412"></a><div class="linenumber">2412</div><div style="width:8em;display:inline-block"></div>return;
<a name="line2413"></a><div class="linenumber">2413</div><div style="width:6em;display:inline-block"></div>}
<a name="line2414"></a><div class="linenumber">2414</div><div style="width:6em;display:inline-block"></div>if (receivePeer.msgTypes[msgType].cb) {
<a name="line2415"></a><div class="linenumber">2415</div><div style="width:8em;display:inline-block"></div>receivePeer.msgTypes[msgType].cb(easyrtcid, msgType, msgData, targeting);
<a name="line2416"></a><div class="linenumber">2416</div><div style="width:8em;display:inline-block"></div>return;
<a name="line2417"></a><div class="linenumber">2417</div><div style="width:6em;display:inline-block"></div>}
<a name="line2418"></a><div class="linenumber">2418</div><div style="width:4em;display:inline-block"></div>}
<a name="line2419"></a><div class="linenumber">2419</div><div style="width:4em;display:inline-block"></div>if (receivePeer.cb) {
<a name="line2420"></a><div class="linenumber">2420</div><div style="width:6em;display:inline-block"></div>receivePeer.cb(easyrtcid, msgType, msgData, targeting);
<a name="line2421"></a><div class="linenumber">2421</div><div style="width:4em;display:inline-block"></div>}
<a name="line2422"></a><div class="linenumber">2422</div><div style="width:2em;display:inline-block"></div>};
<a name="line2423"></a><div class="linenumber">2423</div>
<a name="line2424"></a><div class="linenumber">2424</div><div style="width:2em;display:inline-block"></div>/**
<a name="line2425"></a><div class="linenumber">2425</div><div style="width:2em;display:inline-block"></div>* Sets a listener for messages from the server.
<a name="line2426"></a><div class="linenumber">2426</div><div style="width:2em;display:inline-block"></div>* @param {Function} listener has the signature (msgType, msgData, targeting)
<a name="line2427"></a><div class="linenumber">2427</div><div style="width:2em;display:inline-block"></div>* @example
<a name="line2428"></a><div class="linenumber">2428</div><div style="width:2em;display:inline-block"></div>* easyrtc.setServerListener( function(msgType, msgData, targeting){
<a name="line2429"></a><div class="linenumber">2429</div><div style="width:2em;display:inline-block"></div>* ("The Server sent the following message " + JSON.stringify(msgData));
<a name="line2430"></a><div class="linenumber">2430</div><div style="width:2em;display:inline-block"></div>* });
<a name="line2431"></a><div class="linenumber">2431</div><div style="width:2em;display:inline-block"></div>*/
<a name="line2432"></a><div class="linenumber">2432</div><div style="width:2em;display:inline-block"></div>this.setServerListener = function(listener) {
<a name="line2433"></a><div class="linenumber">2433</div><div style="width:4em;display:inline-block"></div>receiveServerCB = listener;
<a name="line2434"></a><div class="linenumber">2434</div><div style="width:2em;display:inline-block"></div>};
<a name="line2435"></a><div class="linenumber">2435</div>
<a name="line2436"></a><div class="linenumber">2436</div><div style="width:2em;display:inline-block"></div>/**
<a name="line2437"></a><div class="linenumber">2437</div><div style="width:2em;display:inline-block"></div>* Sets the url of the Socket server.
<a name="line2438"></a><div class="linenumber">2438</div><div style="width:2em;display:inline-block"></div>* The node.js server is great as a socket server, but it doesn't have
<a name="line2439"></a><div class="linenumber">2439</div><div style="width:2em;display:inline-block"></div>* all the hooks you'd like in a general web server, like PHP or Python
<a name="line2440"></a><div class="linenumber">2440</div><div style="width:2em;display:inline-block"></div>* plug-ins. By setting the serverPath your application can get it's regular
<a name="line2441"></a><div class="linenumber">2441</div><div style="width:2em;display:inline-block"></div>* pages from a regular web server, but the EasyRTC library can still reach the
<a name="line2442"></a><div class="linenumber">2442</div><div style="width:2em;display:inline-block"></div>* socket server.
<a name="line2443"></a><div class="linenumber">2443</div><div style="width:2em;display:inline-block"></div>* @param {String} socketUrl
<a name="line2444"></a><div class="linenumber">2444</div><div style="width:2em;display:inline-block"></div>* @param {Object} options an optional dictionary of options for socket.io's connect method.
<a name="line2445"></a><div class="linenumber">2445</div><div style="width:2em;display:inline-block"></div>* The default is {'connect timeout': 10000,'force new connection': true }
<a name="line2446"></a><div class="linenumber">2446</div><div style="width:2em;display:inline-block"></div>* @example
<a name="line2447"></a><div class="linenumber">2447</div><div style="width:2em;display:inline-block"></div>* easyrtc.setSocketUrl(":8080", options);
<a name="line2448"></a><div class="linenumber">2448</div><div style="width:2em;display:inline-block"></div>*/
<a name="line2449"></a><div class="linenumber">2449</div><div style="width:2em;display:inline-block"></div>this.setSocketUrl = function(socketUrl, options) {
<a name="line2450"></a><div class="linenumber">2450</div><div style="width:4em;display:inline-block"></div>logDebug("WebRTC signaling server URL set to " + socketUrl);
<a name="line2451"></a><div class="linenumber">2451</div><div style="width:4em;display:inline-block"></div>serverPath = socketUrl;
<a name="line2452"></a><div class="linenumber">2452</div><div style="width:4em;display:inline-block"></div>if( options ) {
<a name="line2453"></a><div class="linenumber">2453</div><div style="width:6em;display:inline-block"></div>connectionOptions = options;
<a name="line2454"></a><div class="linenumber">2454</div><div style="width:4em;display:inline-block"></div>}
<a name="line2455"></a><div class="linenumber">2455</div><div style="width:2em;display:inline-block"></div>};
<a name="line2456"></a><div class="linenumber">2456</div>
<a name="line2457"></a><div class="linenumber">2457</div><div style="width:2em;display:inline-block"></div>/**
<a name="line2458"></a><div class="linenumber">2458</div><div style="width:2em;display:inline-block"></div>* Sets the user name associated with the connection.
<a name="line2459"></a><div class="linenumber">2459</div><div style="width:2em;display:inline-block"></div>* @param {String} username must obey standard identifier conventions.
<a name="line2460"></a><div class="linenumber">2460</div><div style="width:2em;display:inline-block"></div>* @returns {Boolean} true if the call succeeded, false if the username was invalid.
<a name="line2461"></a><div class="linenumber">2461</div><div style="width:2em;display:inline-block"></div>* @example
<a name="line2462"></a><div class="linenumber">2462</div><div style="width:2em;display:inline-block"></div>* if( !easyrtc.setUsername("JohnSmith") ){
<a name="line2463"></a><div class="linenumber">2463</div><div style="width:2em;display:inline-block"></div>* console.error("bad user name);
<a name="line2464"></a><div class="linenumber">2464</div><div style="width:2em;display:inline-block"></div>* }
<a name="line2465"></a><div class="linenumber">2465</div><div style="width:2em;display:inline-block"></div>*
<a name="line2466"></a><div class="linenumber">2466</div><div style="width:2em;display:inline-block"></div>*/
<a name="line2467"></a><div class="linenumber">2467</div><div style="width:2em;display:inline-block"></div>this.setUsername = function(username) {
<a name="line2468"></a><div class="linenumber">2468</div><div style="width:4em;display:inline-block"></div>if( self.myEasyrtcid ) {
<a name="line2469"></a><div class="linenumber">2469</div><div style="width:6em;display:inline-block"></div>self.showError(self.errCodes.DEVELOPER_ERR, "easyrtc.setUsername called after authentication");
<a name="line2470"></a><div class="linenumber">2470</div><div style="width:6em;display:inline-block"></div>return false;
<a name="line2471"></a><div class="linenumber">2471</div><div style="width:4em;display:inline-block"></div>}
<a name="line2472"></a><div class="linenumber">2472</div><div style="width:4em;display:inline-block"></div>else if (self.isNameValid(username)) {
<a name="line2473"></a><div class="linenumber">2473</div><div style="width:6em;display:inline-block"></div>self.username = username;
<a name="line2474"></a><div class="linenumber">2474</div><div style="width:6em;display:inline-block"></div>return true;
<a name="line2475"></a><div class="linenumber">2475</div><div style="width:4em;display:inline-block"></div>}
<a name="line2476"></a><div class="linenumber">2476</div><div style="width:4em;display:inline-block"></div>else {
<a name="line2477"></a><div class="linenumber">2477</div><div style="width:6em;display:inline-block"></div>self.showError(self.errCodes.BAD_NAME, self.format(self.getConstantString("badUserName"), username));
<a name="line2478"></a><div class="linenumber">2478</div><div style="width:6em;display:inline-block"></div>return false;
<a name="line2479"></a><div class="linenumber">2479</div><div style="width:4em;display:inline-block"></div>}
<a name="line2480"></a><div class="linenumber">2480</div><div style="width:2em;display:inline-block"></div>};
<a name="line2481"></a><div class="linenumber">2481</div>
<a name="line2482"></a><div class="linenumber">2482</div><div style="width:2em;display:inline-block"></div>/**
<a name="line2483"></a><div class="linenumber">2483</div><div style="width:2em;display:inline-block"></div>* Get an array of easyrtcids that are using a particular username
<a name="line2484"></a><div class="linenumber">2484</div><div style="width:2em;display:inline-block"></div>* @param {String} username - the username of interest.
<a name="line2485"></a><div class="linenumber">2485</div><div style="width:2em;display:inline-block"></div>* @param {String} room - an optional room name argument limiting results to a particular room.
<a name="line2486"></a><div class="linenumber">2486</div><div style="width:2em;display:inline-block"></div>* @returns {Array} an array of {easyrtcid:id, roomName: roomName}.
<a name="line2487"></a><div class="linenumber">2487</div><div style="width:2em;display:inline-block"></div>*/
<a name="line2488"></a><div class="linenumber">2488</div><div style="width:2em;display:inline-block"></div>this.usernameToIds = function(username, room) {
<a name="line2489"></a><div class="linenumber">2489</div><div style="width:4em;display:inline-block"></div>var results = [];
<a name="line2490"></a><div class="linenumber">2490</div><div style="width:4em;display:inline-block"></div>var id, roomName;
<a name="line2491"></a><div class="linenumber">2491</div><div style="width:4em;display:inline-block"></div>for (roomName in lastLoggedInList) {
<a name="line2492"></a><div class="linenumber">2492</div><div style="width:6em;display:inline-block"></div>if (!lastLoggedInList.hasOwnProperty(roomName)) {
<a name="line2493"></a><div class="linenumber">2493</div><div style="width:8em;display:inline-block"></div>continue;
<a name="line2494"></a><div class="linenumber">2494</div><div style="width:6em;display:inline-block"></div>}
<a name="line2495"></a><div class="linenumber">2495</div><div style="width:6em;display:inline-block"></div>if (room && roomName !== room) {
<a name="line2496"></a><div class="linenumber">2496</div><div style="width:8em;display:inline-block"></div>continue;
<a name="line2497"></a><div class="linenumber">2497</div><div style="width:6em;display:inline-block"></div>}
<a name="line2498"></a><div class="linenumber">2498</div><div style="width:6em;display:inline-block"></div>for (id in lastLoggedInList[roomName]) {
<a name="line2499"></a><div class="linenumber">2499</div><div style="width:8em;display:inline-block"></div>if (!lastLoggedInList[roomName].hasOwnProperty(id)) {
<a name="line2500"></a><div class="linenumber">2500</div><div style="width:10em;display:inline-block"></div>continue;
<a name="line2501"></a><div class="linenumber">2501</div><div style="width:8em;display:inline-block"></div>}
<a name="line2502"></a><div class="linenumber">2502</div><div style="width:8em;display:inline-block"></div>if (lastLoggedInList[roomName][id].username === username) {
<a name="line2503"></a><div class="linenumber">2503</div><div style="width:10em;display:inline-block"></div>results.push({
<a name="line2504"></a><div class="linenumber">2504</div><div style="width:12em;display:inline-block"></div>easyrtcid: id,
<a name="line2505"></a><div class="linenumber">2505</div><div style="width:12em;display:inline-block"></div>roomName: roomName
<a name="line2506"></a><div class="linenumber">2506</div><div style="width:10em;display:inline-block"></div>});
<a name="line2507"></a><div class="linenumber">2507</div><div style="width:8em;display:inline-block"></div>}
<a name="line2508"></a><div class="linenumber">2508</div><div style="width:6em;display:inline-block"></div>}
<a name="line2509"></a><div class="linenumber">2509</div><div style="width:4em;display:inline-block"></div>}
<a name="line2510"></a><div class="linenumber">2510</div><div style="width:4em;display:inline-block"></div>return results;
<a name="line2511"></a><div class="linenumber">2511</div><div style="width:2em;display:inline-block"></div>};
<a name="line2512"></a><div class="linenumber">2512</div>
<a name="line2513"></a><div class="linenumber">2513</div><div style="width:2em;display:inline-block"></div>/**
<a name="line2514"></a><div class="linenumber">2514</div><div style="width:2em;display:inline-block"></div>* Returns another peers API field, if it exists.
<a name="line2515"></a><div class="linenumber">2515</div><div style="width:2em;display:inline-block"></div>* @param {type} roomName
<a name="line2516"></a><div class="linenumber">2516</div><div style="width:2em;display:inline-block"></div>* @param {type} easyrtcid
<a name="line2517"></a><div class="linenumber">2517</div><div style="width:2em;display:inline-block"></div>* @param {type} fieldName
<a name="line2518"></a><div class="linenumber">2518</div><div style="width:2em;display:inline-block"></div>* @returns {Object} Undefined if the attribute does not exist, its value otherwise.
<a name="line2519"></a><div class="linenumber">2519</div><div style="width:2em;display:inline-block"></div>*/
<a name="line2520"></a><div class="linenumber">2520</div><div style="width:2em;display:inline-block"></div>this.getRoomApiField = function(roomName, easyrtcid, fieldName) {
<a name="line2521"></a><div class="linenumber">2521</div><div style="width:4em;display:inline-block"></div>if (lastLoggedInList[roomName] &&
<a name="line2522"></a><div class="linenumber">2522</div><div style="width:8em;display:inline-block"></div>lastLoggedInList[roomName][easyrtcid] &&
<a name="line2523"></a><div class="linenumber">2523</div><div style="width:8em;display:inline-block"></div>lastLoggedInList[roomName][easyrtcid].apiField &&
<a name="line2524"></a><div class="linenumber">2524</div><div style="width:8em;display:inline-block"></div>lastLoggedInList[roomName][easyrtcid].apiField[fieldName]) {
<a name="line2525"></a><div class="linenumber">2525</div><div style="width:6em;display:inline-block"></div>return lastLoggedInList[roomName][easyrtcid].apiField[fieldName].fieldValue;
<a name="line2526"></a><div class="linenumber">2526</div><div style="width:4em;display:inline-block"></div>}
<a name="line2527"></a><div class="linenumber">2527</div><div style="width:4em;display:inline-block"></div>else {
<a name="line2528"></a><div class="linenumber">2528</div><div style="width:6em;display:inline-block"></div>return undefined;
<a name="line2529"></a><div class="linenumber">2529</div><div style="width:4em;display:inline-block"></div>}
<a name="line2530"></a><div class="linenumber">2530</div><div style="width:2em;display:inline-block"></div>};
<a name="line2531"></a><div class="linenumber">2531</div>
<a name="line2532"></a><div class="linenumber">2532</div><div style="width:2em;display:inline-block"></div>/**
<a name="line2533"></a><div class="linenumber">2533</div><div style="width:2em;display:inline-block"></div>* Set the authentication credential if needed.
<a name="line2534"></a><div class="linenumber">2534</div><div style="width:2em;display:inline-block"></div>* @param {Object} credentialParm - a JSONable object.
<a name="line2535"></a><div class="linenumber">2535</div><div style="width:2em;display:inline-block"></div>*/
<a name="line2536"></a><div class="linenumber">2536</div><div style="width:2em;display:inline-block"></div>this.setCredential = function(credentialParm) {
<a name="line2537"></a><div class="linenumber">2537</div><div style="width:4em;display:inline-block"></div>try {
<a name="line2538"></a><div class="linenumber">2538</div><div style="width:6em;display:inline-block"></div>JSON.stringify(credentialParm);
<a name="line2539"></a><div class="linenumber">2539</div><div style="width:6em;display:inline-block"></div>credential = credentialParm;
<a name="line2540"></a><div class="linenumber">2540</div><div style="width:6em;display:inline-block"></div>return true;
<a name="line2541"></a><div class="linenumber">2541</div><div style="width:4em;display:inline-block"></div>}
<a name="line2542"></a><div class="linenumber">2542</div><div style="width:4em;display:inline-block"></div>catch (oops) {
<a name="line2543"></a><div class="linenumber">2543</div><div style="width:6em;display:inline-block"></div>self.showError(self.errCodes.BAD_CREDENTIAL, "easyrtc.setCredential passed a non-JSON-able object");
<a name="line2544"></a><div class="linenumber">2544</div><div style="width:6em;display:inline-block"></div>throw "easyrtc.setCredential passed a non-JSON-able object";
<a name="line2545"></a><div class="linenumber">2545</div><div style="width:4em;display:inline-block"></div>}
<a name="line2546"></a><div class="linenumber">2546</div><div style="width:2em;display:inline-block"></div>};
<a name="line2547"></a><div class="linenumber">2547</div>
<a name="line2548"></a><div class="linenumber">2548</div><div style="width:2em;display:inline-block"></div>/**
<a name="line2549"></a><div class="linenumber">2549</div><div style="width:2em;display:inline-block"></div>* Sets the listener for socket disconnection by external (to the API) reasons.
<a name="line2550"></a><div class="linenumber">2550</div><div style="width:2em;display:inline-block"></div>* @param {Function} disconnectListener takes no arguments and is not called as a result of calling easyrtc.disconnect.
<a name="line2551"></a><div class="linenumber">2551</div><div style="width:2em;display:inline-block"></div>* @example
<a name="line2552"></a><div class="linenumber">2552</div><div style="width:2em;display:inline-block"></div>* easyrtc.setDisconnectListener(function(){
<a name="line2553"></a><div class="linenumber">2553</div><div style="width:2em;display:inline-block"></div>* easyrtc.showError("SYSTEM-ERROR", "Lost our connection to the socket server");
<a name="line2554"></a><div class="linenumber">2554</div><div style="width:2em;display:inline-block"></div>* });
<a name="line2555"></a><div class="linenumber">2555</div><div style="width:2em;display:inline-block"></div>*/
<a name="line2556"></a><div class="linenumber">2556</div><div style="width:2em;display:inline-block"></div>this.setDisconnectListener = function(disconnectListener) {
<a name="line2557"></a><div class="linenumber">2557</div><div style="width:4em;display:inline-block"></div>self.disconnectListener = disconnectListener;
<a name="line2558"></a><div class="linenumber">2558</div><div style="width:2em;display:inline-block"></div>};
<a name="line2559"></a><div class="linenumber">2559</div>
<a name="line2560"></a><div class="linenumber">2560</div><div style="width:2em;display:inline-block"></div>/**
<a name="line2561"></a><div class="linenumber">2561</div><div style="width:2em;display:inline-block"></div>* Convert an easyrtcid to a user name. This is useful for labeling buttons and messages
<a name="line2562"></a><div class="linenumber">2562</div><div style="width:2em;display:inline-block"></div>* regarding peers.
<a name="line2563"></a><div class="linenumber">2563</div><div style="width:2em;display:inline-block"></div>* @param {String} easyrtcid
<a name="line2564"></a><div class="linenumber">2564</div><div style="width:2em;display:inline-block"></div>* @return {String} the username associated with the easyrtcid, or the easyrtcid if there is
<a name="line2565"></a><div class="linenumber">2565</div><div style="width:2em;display:inline-block"></div>* no associated username.
<a name="line2566"></a><div class="linenumber">2566</div><div style="width:2em;display:inline-block"></div>* @example
<a name="line2567"></a><div class="linenumber">2567</div><div style="width:2em;display:inline-block"></div>* console.log(easyrtcid + " is actually " + easyrtc.idToName(easyrtcid));
<a name="line2568"></a><div class="linenumber">2568</div><div style="width:2em;display:inline-block"></div>*/
<a name="line2569"></a><div class="linenumber">2569</div><div style="width:2em;display:inline-block"></div>this.idToName = function(easyrtcid) {
<a name="line2570"></a><div class="linenumber">2570</div><div style="width:4em;display:inline-block"></div>var roomName;
<a name="line2571"></a><div class="linenumber">2571</div><div style="width:4em;display:inline-block"></div>for (roomName in lastLoggedInList) {
<a name="line2572"></a><div class="linenumber">2572</div><div style="width:6em;display:inline-block"></div>if (!lastLoggedInList.hasOwnProperty(roomName)) {
<a name="line2573"></a><div class="linenumber">2573</div><div style="width:8em;display:inline-block"></div>continue;
<a name="line2574"></a><div class="linenumber">2574</div><div style="width:6em;display:inline-block"></div>}
<a name="line2575"></a><div class="linenumber">2575</div><div style="width:6em;display:inline-block"></div>if (lastLoggedInList[roomName][easyrtcid]) {
<a name="line2576"></a><div class="linenumber">2576</div><div style="width:8em;display:inline-block"></div>if (lastLoggedInList[roomName][easyrtcid].username) {
<a name="line2577"></a><div class="linenumber">2577</div><div style="width:10em;display:inline-block"></div>return lastLoggedInList[roomName][easyrtcid].username;
<a name="line2578"></a><div class="linenumber">2578</div><div style="width:8em;display:inline-block"></div>}
<a name="line2579"></a><div class="linenumber">2579</div><div style="width:6em;display:inline-block"></div>}
<a name="line2580"></a><div class="linenumber">2580</div><div style="width:4em;display:inline-block"></div>}
<a name="line2581"></a><div class="linenumber">2581</div><div style="width:4em;display:inline-block"></div>return easyrtcid;
<a name="line2582"></a><div class="linenumber">2582</div><div style="width:2em;display:inline-block"></div>};
<a name="line2583"></a><div class="linenumber">2583</div>
<a name="line2584"></a><div class="linenumber">2584</div><div style="width:2em;display:inline-block"></div>/* used in easyrtc.connect */
<a name="line2585"></a><div class="linenumber">2585</div><div style="width:2em;display:inline-block"></div>/** @private */
<a name="line2586"></a><div class="linenumber">2586</div><div style="width:2em;display:inline-block"></div>this.webSocket = null;
<a name="line2587"></a><div class="linenumber">2587</div><div style="width:2em;display:inline-block"></div>/** @private */
<a name="line2588"></a><div class="linenumber">2588</div><div style="width:2em;display:inline-block"></div>var pc_config = {};
<a name="line2589"></a><div class="linenumber">2589</div><div style="width:2em;display:inline-block"></div>/** @private */
<a name="line2590"></a><div class="linenumber">2590</div><div style="width:2em;display:inline-block"></div>var pc_config_to_use = null;
<a name="line2591"></a><div class="linenumber">2591</div><div style="width:2em;display:inline-block"></div>/** @private */
<a name="line2592"></a><div class="linenumber">2592</div><div style="width:2em;display:inline-block"></div>var use_fresh_ice_each_peer = false;
<a name="line2593"></a><div class="linenumber">2593</div>
<a name="line2594"></a><div class="linenumber">2594</div><div style="width:2em;display:inline-block"></div>/**
<a name="line2595"></a><div class="linenumber">2595</div><div style="width:2em;display:inline-block"></div>* Determines whether fresh ice server configuration should be requested from the server for each peer connection.
<a name="line2596"></a><div class="linenumber">2596</div><div style="width:2em;display:inline-block"></div>* @param {Boolean} value the default is false.
<a name="line2597"></a><div class="linenumber">2597</div><div style="width:2em;display:inline-block"></div>*/
<a name="line2598"></a><div class="linenumber">2598</div><div style="width:2em;display:inline-block"></div>this.setUseFreshIceEachPeerConnection = function(value) {
<a name="line2599"></a><div class="linenumber">2599</div><div style="width:4em;display:inline-block"></div>use_fresh_ice_each_peer = value;
<a name="line2600"></a><div class="linenumber">2600</div><div style="width:2em;display:inline-block"></div>};
<a name="line2601"></a><div class="linenumber">2601</div>
<a name="line2602"></a><div class="linenumber">2602</div><div style="width:2em;display:inline-block"></div>/**
<a name="line2603"></a><div class="linenumber">2603</div><div style="width:2em;display:inline-block"></div>* Returns the last ice config supplied by the EasyRTC server. This function is not normally used, it is provided
<a name="line2604"></a><div class="linenumber">2604</div><div style="width:2em;display:inline-block"></div>* for people who want to try filtering ice server configuration on the client.
<a name="line2605"></a><div class="linenumber">2605</div><div style="width:2em;display:inline-block"></div>* @return {Object} which has the form {iceServers:[ice_server_entry, ice_server_entry, ...]}
<a name="line2606"></a><div class="linenumber">2606</div><div style="width:2em;display:inline-block"></div>*/
<a name="line2607"></a><div class="linenumber">2607</div><div style="width:2em;display:inline-block"></div>this.getServerIce = function() {
<a name="line2608"></a><div class="linenumber">2608</div><div style="width:4em;display:inline-block"></div>return pc_config;
<a name="line2609"></a><div class="linenumber">2609</div><div style="width:2em;display:inline-block"></div>};
<a name="line2610"></a><div class="linenumber">2610</div>
<a name="line2611"></a><div class="linenumber">2611</div><div style="width:2em;display:inline-block"></div>/**
<a name="line2612"></a><div class="linenumber">2612</div><div style="width:2em;display:inline-block"></div>* Sets the ice server configuration that will be used in subsequent calls. You only need this function if you are filtering
<a name="line2613"></a><div class="linenumber">2613</div><div style="width:2em;display:inline-block"></div>* the ice server configuration on the client or if you are using TURN certificates that have a very short lifespan.
<a name="line2614"></a><div class="linenumber">2614</div><div style="width:2em;display:inline-block"></div>* @param {Object} ice An object with iceServers element containing an array of ice server entries.
<a name="line2615"></a><div class="linenumber">2615</div><div style="width:2em;display:inline-block"></div>* @example
<a name="line2616"></a><div class="linenumber">2616</div><div style="width:2em;display:inline-block"></div>* easyrtc.setIceUsedInCalls( {"iceServers": [
<a name="line2617"></a><div class="linenumber">2617</div><div style="width:2em;display:inline-block"></div>* {
<a name="line2618"></a><div class="linenumber">2618</div><div style="width:2em;display:inline-block"></div>* "url": "stun:stun.sipgate.net"
<a name="line2619"></a><div class="linenumber">2619</div><div style="width:2em;display:inline-block"></div>* },
<a name="line2620"></a><div class="linenumber">2620</div><div style="width:2em;display:inline-block"></div>* {
<a name="line2621"></a><div class="linenumber">2621</div><div style="width:2em;display:inline-block"></div>* "url": "stun:217.10.68.152"
<a name="line2622"></a><div class="linenumber">2622</div><div style="width:2em;display:inline-block"></div>* },
<a name="line2623"></a><div class="linenumber">2623</div><div style="width:2em;display:inline-block"></div>* {
<a name="line2624"></a><div class="linenumber">2624</div><div style="width:2em;display:inline-block"></div>* "url": "stun:stun.sipgate.net:10000"
<a name="line2625"></a><div class="linenumber">2625</div><div style="width:2em;display:inline-block"></div>* }
<a name="line2626"></a><div class="linenumber">2626</div><div style="width:2em;display:inline-block"></div>* ]});
<a name="line2627"></a><div class="linenumber">2627</div><div style="width:2em;display:inline-block"></div>* easyrtc.call(...);
<a name="line2628"></a><div class="linenumber">2628</div><div style="width:2em;display:inline-block"></div>*/
<a name="line2629"></a><div class="linenumber">2629</div><div style="width:2em;display:inline-block"></div>this.setIceUsedInCalls = function(ice) {
<a name="line2630"></a><div class="linenumber">2630</div><div style="width:4em;display:inline-block"></div>if (!ice.iceServers) {
<a name="line2631"></a><div class="linenumber">2631</div><div style="width:6em;display:inline-block"></div>self.showError(self.errCodes.DEVELOPER_ERR, "Bad ice configuration passed to easyrtc.setIceUsedInCalls");
<a name="line2632"></a><div class="linenumber">2632</div><div style="width:4em;display:inline-block"></div>}
<a name="line2633"></a><div class="linenumber">2633</div><div style="width:4em;display:inline-block"></div>else {
<a name="line2634"></a><div class="linenumber">2634</div><div style="width:6em;display:inline-block"></div>pc_config_to_use = ice;
<a name="line2635"></a><div class="linenumber">2635</div><div style="width:4em;display:inline-block"></div>}
<a name="line2636"></a><div class="linenumber">2636</div><div style="width:2em;display:inline-block"></div>};
<a name="line2637"></a><div class="linenumber">2637</div>
<a name="line2638"></a><div class="linenumber">2638</div><div style="width:2em;display:inline-block"></div>/** @private */
<a name="line2639"></a><div class="linenumber">2639</div><div style="width:2em;display:inline-block"></div>function getRemoteStreamByName(peerConn, otherUser, streamName) {
<a name="line2640"></a><div class="linenumber">2640</div>
<a name="line2641"></a><div class="linenumber">2641</div><div style="width:4em;display:inline-block"></div>var keyToMatch = null;
<a name="line2642"></a><div class="linenumber">2642</div><div style="width:4em;display:inline-block"></div>var remoteStreams = peerConn.pc.getRemoteStreams();
<a name="line2643"></a><div class="linenumber">2643</div>
<a name="line2644"></a><div class="linenumber">2644</div><div style="width:4em;display:inline-block"></div>// No streamName lead to default
<a name="line2645"></a><div class="linenumber">2645</div><div style="width:4em;display:inline-block"></div>if (!streamName) {
<a name="line2646"></a><div class="linenumber">2646</div><div style="width:6em;display:inline-block"></div>streamName = "default";
<a name="line2647"></a><div class="linenumber">2647</div><div style="width:4em;display:inline-block"></div>}
<a name="line2648"></a><div class="linenumber">2648</div>
<a name="line2649"></a><div class="linenumber">2649</div><div style="width:4em;display:inline-block"></div>// default lead to first if available
<a name="line2650"></a><div class="linenumber">2650</div><div style="width:4em;display:inline-block"></div>if (streamName === "default") {
<a name="line2651"></a><div class="linenumber">2651</div><div style="width:6em;display:inline-block"></div>if (remoteStreams.length > 0) {
<a name="line2652"></a><div class="linenumber">2652</div><div style="width:8em;display:inline-block"></div>return remoteStreams[0];
<a name="line2653"></a><div class="linenumber">2653</div><div style="width:6em;display:inline-block"></div>}
<a name="line2654"></a><div class="linenumber">2654</div><div style="width:6em;display:inline-block"></div>else {
<a name="line2655"></a><div class="linenumber">2655</div><div style="width:8em;display:inline-block"></div>return null;
<a name="line2656"></a><div class="linenumber">2656</div><div style="width:6em;display:inline-block"></div>}
<a name="line2657"></a><div class="linenumber">2657</div><div style="width:4em;display:inline-block"></div>}
<a name="line2658"></a><div class="linenumber">2658</div>
<a name="line2659"></a><div class="linenumber">2659</div><div style="width:4em;display:inline-block"></div>// Get mediaIds from user roomData
<a name="line2660"></a><div class="linenumber">2660</div><div style="width:4em;display:inline-block"></div>for (var roomName in self.roomData) {
<a name="line2661"></a><div class="linenumber">2661</div><div style="width:6em;display:inline-block"></div>if (self.roomData.hasOwnProperty(roomName)) {
<a name="line2662"></a><div class="linenumber">2662</div><div style="width:8em;display:inline-block"></div>var mediaIds = self.getRoomApiField(roomName, otherUser, "mediaIds");
<a name="line2663"></a><div class="linenumber">2663</div><div style="width:8em;display:inline-block"></div>keyToMatch = mediaIds ? mediaIds[streamName] : null;
<a name="line2664"></a><div class="linenumber">2664</div><div style="width:8em;display:inline-block"></div>if (keyToMatch) {
<a name="line2665"></a><div class="linenumber">2665</div><div style="width:10em;display:inline-block"></div>break;
<a name="line2666"></a><div class="linenumber">2666</div><div style="width:8em;display:inline-block"></div>}
<a name="line2667"></a><div class="linenumber">2667</div><div style="width:6em;display:inline-block"></div>}
<a name="line2668"></a><div class="linenumber">2668</div><div style="width:4em;display:inline-block"></div>}
<a name="line2669"></a><div class="linenumber">2669</div>
<a name="line2670"></a><div class="linenumber">2670</div><div style="width:4em;display:inline-block"></div>//
<a name="line2671"></a><div class="linenumber">2671</div><div style="width:4em;display:inline-block"></div>if (!keyToMatch) {
<a name="line2672"></a><div class="linenumber">2672</div><div style="width:6em;display:inline-block"></div>self.showError(self.errCodes.DEVELOPER_ERR, "remote peer does not have media stream called " + streamName);
<a name="line2673"></a><div class="linenumber">2673</div><div style="width:4em;display:inline-block"></div>}
<a name="line2674"></a><div class="linenumber">2674</div>
<a name="line2675"></a><div class="linenumber">2675</div><div style="width:4em;display:inline-block"></div>//
<a name="line2676"></a><div class="linenumber">2676</div><div style="width:4em;display:inline-block"></div>for (var i = 0; i < remoteStreams.length; i++) {
<a name="line2677"></a><div class="linenumber">2677</div><div style="width:6em;display:inline-block"></div>var remoteId;
<a name="line2678"></a><div class="linenumber">2678</div><div style="width:6em;display:inline-block"></div>if (remoteStreams[i].id) {
<a name="line2679"></a><div class="linenumber">2679</div><div style="width:8em;display:inline-block"></div>remoteId = remoteStreams[i].id;
<a name="line2680"></a><div class="linenumber">2680</div><div style="width:6em;display:inline-block"></div>} else {
<a name="line2681"></a><div class="linenumber">2681</div><div style="width:8em;display:inline-block"></div>remoteId = "default";
<a name="line2682"></a><div class="linenumber">2682</div><div style="width:6em;display:inline-block"></div>}
<a name="line2683"></a><div class="linenumber">2683</div>
<a name="line2684"></a><div class="linenumber">2684</div><div style="width:6em;display:inline-block"></div>if (
<a name="line2685"></a><div class="linenumber">2685</div><div style="width:8em;display:inline-block"></div>!keyToMatch || // No match
<a name="line2686"></a><div class="linenumber">2686</div><div style="width:10em;display:inline-block"></div>remoteId === keyToMatch || // Full match
<a name="line2687"></a><div class="linenumber">2687</div><div style="width:12em;display:inline-block"></div>remoteId.indexOf(keyToMatch) === 0 // Partial match
<a name="line2688"></a><div class="linenumber">2688</div><div style="width:6em;display:inline-block"></div>) {
<a name="line2689"></a><div class="linenumber">2689</div><div style="width:8em;display:inline-block"></div>return remoteStreams[i];
<a name="line2690"></a><div class="linenumber">2690</div><div style="width:6em;display:inline-block"></div>}
<a name="line2691"></a><div class="linenumber">2691</div>
<a name="line2692"></a><div class="linenumber">2692</div><div style="width:4em;display:inline-block"></div>}
<a name="line2693"></a><div class="linenumber">2693</div>
<a name="line2694"></a><div class="linenumber">2694</div><div style="width:4em;display:inline-block"></div>return null;
<a name="line2695"></a><div class="linenumber">2695</div><div style="width:2em;display:inline-block"></div>}
<a name="line2696"></a><div class="linenumber">2696</div>
<a name="line2697"></a><div class="linenumber">2697</div><div style="width:2em;display:inline-block"></div>/**
<a name="line2698"></a><div class="linenumber">2698</div><div style="width:2em;display:inline-block"></div>* @private
<a name="line2699"></a><div class="linenumber">2699</div><div style="width:2em;display:inline-block"></div>* @param {string} easyrtcid
<a name="line2700"></a><div class="linenumber">2700</div><div style="width:2em;display:inline-block"></div>* @param {boolean} checkAudio
<a name="line2701"></a><div class="linenumber">2701</div><div style="width:2em;display:inline-block"></div>* @param {string} streamName
<a name="line2702"></a><div class="linenumber">2702</div><div style="width:2em;display:inline-block"></div>*/
<a name="line2703"></a><div class="linenumber">2703</div><div style="width:2em;display:inline-block"></div>function _haveTracks(easyrtcid, checkAudio, streamName) {
<a name="line2704"></a><div class="linenumber">2704</div><div style="width:4em;display:inline-block"></div>var stream, peerConnObj;
<a name="line2705"></a><div class="linenumber">2705</div><div style="width:4em;display:inline-block"></div>if (!easyrtcid) {
<a name="line2706"></a><div class="linenumber">2706</div><div style="width:6em;display:inline-block"></div>stream = getLocalMediaStreamByName(streamName);
<a name="line2707"></a><div class="linenumber">2707</div><div style="width:4em;display:inline-block"></div>}
<a name="line2708"></a><div class="linenumber">2708</div><div style="width:4em;display:inline-block"></div>else {
<a name="line2709"></a><div class="linenumber">2709</div><div style="width:6em;display:inline-block"></div>peerConnObj = peerConns[easyrtcid];
<a name="line2710"></a><div class="linenumber">2710</div><div style="width:6em;display:inline-block"></div>if (!peerConnObj) {
<a name="line2711"></a><div class="linenumber">2711</div><div style="width:8em;display:inline-block"></div>self.showError(self.errCodes.DEVELOPER_ERR, "haveTracks called about a peer you don't have a connection to");
<a name="line2712"></a><div class="linenumber">2712</div><div style="width:8em;display:inline-block"></div>return false;
<a name="line2713"></a><div class="linenumber">2713</div><div style="width:6em;display:inline-block"></div>}
<a name="line2714"></a><div class="linenumber">2714</div><div style="width:6em;display:inline-block"></div>stream = getRemoteStreamByName(peerConns[easyrtcid], easyrtcid, streamName);
<a name="line2715"></a><div class="linenumber">2715</div><div style="width:4em;display:inline-block"></div>}
<a name="line2716"></a><div class="linenumber">2716</div><div style="width:4em;display:inline-block"></div>if (!stream) {
<a name="line2717"></a><div class="linenumber">2717</div><div style="width:6em;display:inline-block"></div>return false;
<a name="line2718"></a><div class="linenumber">2718</div><div style="width:4em;display:inline-block"></div>}
<a name="line2719"></a><div class="linenumber">2719</div>
<a name="line2720"></a><div class="linenumber">2720</div><div style="width:4em;display:inline-block"></div>var tracks;
<a name="line2721"></a><div class="linenumber">2721</div><div style="width:4em;display:inline-block"></div>try {
<a name="line2722"></a><div class="linenumber">2722</div>
<a name="line2723"></a><div class="linenumber">2723</div><div style="width:6em;display:inline-block"></div>if (checkAudio) {
<a name="line2724"></a><div class="linenumber">2724</div><div style="width:8em;display:inline-block"></div>tracks = stream.getAudioTracks();
<a name="line2725"></a><div class="linenumber">2725</div><div style="width:6em;display:inline-block"></div>}
<a name="line2726"></a><div class="linenumber">2726</div><div style="width:6em;display:inline-block"></div>else {
<a name="line2727"></a><div class="linenumber">2727</div><div style="width:8em;display:inline-block"></div>tracks = stream.getVideoTracks();
<a name="line2728"></a><div class="linenumber">2728</div><div style="width:6em;display:inline-block"></div>}
<a name="line2729"></a><div class="linenumber">2729</div>
<a name="line2730"></a><div class="linenumber">2730</div><div style="width:4em;display:inline-block"></div>} catch (oops) {
<a name="line2731"></a><div class="linenumber">2731</div><div style="width:6em;display:inline-block"></div>// TODO why do we return true here ?
<a name="line2732"></a><div class="linenumber">2732</div><div style="width:6em;display:inline-block"></div>return true;
<a name="line2733"></a><div class="linenumber">2733</div><div style="width:4em;display:inline-block"></div>}
<a name="line2734"></a><div class="linenumber">2734</div>
<a name="line2735"></a><div class="linenumber">2735</div><div style="width:4em;display:inline-block"></div>if (!tracks) {
<a name="line2736"></a><div class="linenumber">2736</div><div style="width:6em;display:inline-block"></div>return false;
<a name="line2737"></a><div class="linenumber">2737</div><div style="width:4em;display:inline-block"></div>}
<a name="line2738"></a><div class="linenumber">2738</div>
<a name="line2739"></a><div class="linenumber">2739</div><div style="width:4em;display:inline-block"></div>return tracks.length > 0;
<a name="line2740"></a><div class="linenumber">2740</div><div style="width:2em;display:inline-block"></div>}
<a name="line2741"></a><div class="linenumber">2741</div>
<a name="line2742"></a><div class="linenumber">2742</div><div style="width:2em;display:inline-block"></div>/** Determines if a particular peer2peer connection has an audio track.
<a name="line2743"></a><div class="linenumber">2743</div><div style="width:2em;display:inline-block"></div>* @param {String} easyrtcid - the id of the other caller in the connection. If easyrtcid is not supplied, checks the local media.
<a name="line2744"></a><div class="linenumber">2744</div><div style="width:2em;display:inline-block"></div>* @param {String} streamName - an optional stream id.
<a name="line2745"></a><div class="linenumber">2745</div><div style="width:2em;display:inline-block"></div>* @return {Boolean} true if there is an audio track or the browser can't tell us.
<a name="line2746"></a><div class="linenumber">2746</div><div style="width:2em;display:inline-block"></div>*/
<a name="line2747"></a><div class="linenumber">2747</div><div style="width:2em;display:inline-block"></div>this.haveAudioTrack = function(easyrtcid, streamName) {
<a name="line2748"></a><div class="linenumber">2748</div><div style="width:4em;display:inline-block"></div>return _haveTracks(easyrtcid, true, streamName);
<a name="line2749"></a><div class="linenumber">2749</div><div style="width:2em;display:inline-block"></div>};
<a name="line2750"></a><div class="linenumber">2750</div>
<a name="line2751"></a><div class="linenumber">2751</div><div style="width:2em;display:inline-block"></div>/** Determines if a particular peer2peer connection has a video track.
<a name="line2752"></a><div class="linenumber">2752</div><div style="width:2em;display:inline-block"></div>* @param {String} easyrtcid - the id of the other caller in the connection. If easyrtcid is not supplied, checks the local media.
<a name="line2753"></a><div class="linenumber">2753</div><div style="width:2em;display:inline-block"></div>* @param {String} streamName - an optional stream id. *
<a name="line2754"></a><div class="linenumber">2754</div><div style="width:2em;display:inline-block"></div>* @return {Boolean} true if there is an video track or the browser can't tell us.
<a name="line2755"></a><div class="linenumber">2755</div><div style="width:2em;display:inline-block"></div>*/
<a name="line2756"></a><div class="linenumber">2756</div><div style="width:2em;display:inline-block"></div>this.haveVideoTrack = function(easyrtcid, streamName) {
<a name="line2757"></a><div class="linenumber">2757</div><div style="width:4em;display:inline-block"></div>return _haveTracks(easyrtcid, false, streamName);
<a name="line2758"></a><div class="linenumber">2758</div><div style="width:2em;display:inline-block"></div>};
<a name="line2759"></a><div class="linenumber">2759</div>
<a name="line2760"></a><div class="linenumber">2760</div><div style="width:2em;display:inline-block"></div>/**
<a name="line2761"></a><div class="linenumber">2761</div><div style="width:2em;display:inline-block"></div>* Gets a data field associated with a room.
<a name="line2762"></a><div class="linenumber">2762</div><div style="width:2em;display:inline-block"></div>* @param {String} roomName - the name of the room.
<a name="line2763"></a><div class="linenumber">2763</div><div style="width:2em;display:inline-block"></div>* @param {String} fieldName - the name of the field.
<a name="line2764"></a><div class="linenumber">2764</div><div style="width:2em;display:inline-block"></div>* @return {Object} dataValue - the value of the field if present, undefined if not present.
<a name="line2765"></a><div class="linenumber">2765</div><div style="width:2em;display:inline-block"></div>*/
<a name="line2766"></a><div class="linenumber">2766</div><div style="width:2em;display:inline-block"></div>this.getRoomField = function(roomName, fieldName) {
<a name="line2767"></a><div class="linenumber">2767</div><div style="width:4em;display:inline-block"></div>var fields = self.getRoomFields(roomName);
<a name="line2768"></a><div class="linenumber">2768</div><div style="width:4em;display:inline-block"></div>return (!fields || !fields[fieldName]) ? undefined : fields[fieldName].fieldValue;
<a name="line2769"></a><div class="linenumber">2769</div><div style="width:2em;display:inline-block"></div>};
<a name="line2770"></a><div class="linenumber">2770</div>
<a name="line2771"></a><div class="linenumber">2771</div><div style="width:2em;display:inline-block"></div>/** @private */
<a name="line2772"></a><div class="linenumber">2772</div><div style="width:2em;display:inline-block"></div>var fields = null;
<a name="line2773"></a><div class="linenumber">2773</div>
<a name="line2774"></a><div class="linenumber">2774</div><div style="width:2em;display:inline-block"></div>/** @private */
<a name="line2775"></a><div class="linenumber">2775</div><div style="width:2em;display:inline-block"></div>var preallocatedSocketIo = null;
<a name="line2776"></a><div class="linenumber">2776</div>
<a name="line2777"></a><div class="linenumber">2777</div><div style="width:2em;display:inline-block"></div>/** @private */
<a name="line2778"></a><div class="linenumber">2778</div><div style="width:2em;display:inline-block"></div>var closedChannel = null;
<a name="line2779"></a><div class="linenumber">2779</div>
<a name="line2780"></a><div class="linenumber">2780</div><div style="width:2em;display:inline-block"></div>//
<a name="line2781"></a><div class="linenumber">2781</div><div style="width:2em;display:inline-block"></div>// easyrtc.disconnect performs a clean disconnection of the client from the server.
<a name="line2782"></a><div class="linenumber">2782</div><div style="width:2em;display:inline-block"></div>//
<a name="line2783"></a><div class="linenumber">2783</div><div style="width:2em;display:inline-block"></div>function disconnectBody() {
<a name="line2784"></a><div class="linenumber">2784</div><div style="width:4em;display:inline-block"></div>var key;
<a name="line2785"></a><div class="linenumber">2785</div><div style="width:4em;display:inline-block"></div>self.loggingOut = true;
<a name="line2786"></a><div class="linenumber">2786</div><div style="width:4em;display:inline-block"></div>offersPending = {};
<a name="line2787"></a><div class="linenumber">2787</div><div style="width:4em;display:inline-block"></div>acceptancePending = {};
<a name="line2788"></a><div class="linenumber">2788</div><div style="width:4em;display:inline-block"></div>self.disconnecting = true;
<a name="line2789"></a><div class="linenumber">2789</div><div style="width:4em;display:inline-block"></div>closedChannel = self.webSocket;
<a name="line2790"></a><div class="linenumber">2790</div><div style="width:4em;display:inline-block"></div>if (self.webSocketConnected) {
<a name="line2791"></a><div class="linenumber">2791</div><div style="width:6em;display:inline-block"></div>if (!preallocatedSocketIo) {
<a name="line2792"></a><div class="linenumber">2792</div><div style="width:8em;display:inline-block"></div>self.webSocket.close();
<a name="line2793"></a><div class="linenumber">2793</div><div style="width:6em;display:inline-block"></div>}
<a name="line2794"></a><div class="linenumber">2794</div><div style="width:6em;display:inline-block"></div>self.webSocketConnected = false;
<a name="line2795"></a><div class="linenumber">2795</div><div style="width:4em;display:inline-block"></div>}
<a name="line2796"></a><div class="linenumber">2796</div><div style="width:4em;display:inline-block"></div>self.hangupAll();
<a name="line2797"></a><div class="linenumber">2797</div><div style="width:4em;display:inline-block"></div>if (roomOccupantListener) {
<a name="line2798"></a><div class="linenumber">2798</div><div style="width:6em;display:inline-block"></div>for (key in lastLoggedInList) {
<a name="line2799"></a><div class="linenumber">2799</div><div style="width:8em;display:inline-block"></div>if (lastLoggedInList.hasOwnProperty(key)) {
<a name="line2800"></a><div class="linenumber">2800</div><div style="width:10em;display:inline-block"></div>roomOccupantListener(key, {}, false);
<a name="line2801"></a><div class="linenumber">2801</div><div style="width:8em;display:inline-block"></div>}
<a name="line2802"></a><div class="linenumber">2802</div><div style="width:6em;display:inline-block"></div>}
<a name="line2803"></a><div class="linenumber">2803</div><div style="width:4em;display:inline-block"></div>}
<a name="line2804"></a><div class="linenumber">2804</div><div style="width:4em;display:inline-block"></div>lastLoggedInList = {};
<a name="line2805"></a><div class="linenumber">2805</div><div style="width:4em;display:inline-block"></div>self.emitEvent("roomOccupant", {});
<a name="line2806"></a><div class="linenumber">2806</div><div style="width:4em;display:inline-block"></div>self.roomData = {};
<a name="line2807"></a><div class="linenumber">2807</div><div style="width:4em;display:inline-block"></div>self.roomJoin = {};
<a name="line2808"></a><div class="linenumber">2808</div><div style="width:4em;display:inline-block"></div>self.loggingOut = false;
<a name="line2809"></a><div class="linenumber">2809</div><div style="width:4em;display:inline-block"></div>self.myEasyrtcid = null;
<a name="line2810"></a><div class="linenumber">2810</div><div style="width:4em;display:inline-block"></div>self.disconnecting = false;
<a name="line2811"></a><div class="linenumber">2811</div><div style="width:4em;display:inline-block"></div>oldConfig = {};
<a name="line2812"></a><div class="linenumber">2812</div><div style="width:2em;display:inline-block"></div>}
<a name="line2813"></a><div class="linenumber">2813</div>
<a name="line2814"></a><div class="linenumber">2814</div><div style="width:2em;display:inline-block"></div>/**
<a name="line2815"></a><div class="linenumber">2815</div><div style="width:2em;display:inline-block"></div>* Disconnect from the EasyRTC server.
<a name="line2816"></a><div class="linenumber">2816</div><div style="width:2em;display:inline-block"></div>* @example
<a name="line2817"></a><div class="linenumber">2817</div><div style="width:2em;display:inline-block"></div>* easyrtc.disconnect();
<a name="line2818"></a><div class="linenumber">2818</div><div style="width:2em;display:inline-block"></div>*/
<a name="line2819"></a><div class="linenumber">2819</div><div style="width:2em;display:inline-block"></div>this.disconnect = function() {
<a name="line2820"></a><div class="linenumber">2820</div>
<a name="line2821"></a><div class="linenumber">2821</div><div style="width:4em;display:inline-block"></div>logDebug("attempt to disconnect from WebRTC signalling server");
<a name="line2822"></a><div class="linenumber">2822</div>
<a name="line2823"></a><div class="linenumber">2823</div><div style="width:4em;display:inline-block"></div>self.disconnecting = true;
<a name="line2824"></a><div class="linenumber">2824</div><div style="width:4em;display:inline-block"></div>self.hangupAll();
<a name="line2825"></a><div class="linenumber">2825</div><div style="width:4em;display:inline-block"></div>self.loggingOut = true;
<a name="line2826"></a><div class="linenumber">2826</div><div style="width:4em;display:inline-block"></div>//
<a name="line2827"></a><div class="linenumber">2827</div><div style="width:4em;display:inline-block"></div>// The hangupAll may try to send configuration information back to the server.
<a name="line2828"></a><div class="linenumber">2828</div><div style="width:4em;display:inline-block"></div>// Collecting that information is asynchronous, we don't actually close the
<a name="line2829"></a><div class="linenumber">2829</div><div style="width:4em;display:inline-block"></div>// connection until it's had a chance to be sent. We allocate 100ms for collecting
<a name="line2830"></a><div class="linenumber">2830</div><div style="width:4em;display:inline-block"></div>// the info, so 250ms should be sufficient for the disconnecting.
<a name="line2831"></a><div class="linenumber">2831</div><div style="width:4em;display:inline-block"></div>//
<a name="line2832"></a><div class="linenumber">2832</div><div style="width:4em;display:inline-block"></div>setTimeout(function() {
<a name="line2833"></a><div class="linenumber">2833</div><div style="width:6em;display:inline-block"></div>if (self.webSocket) {
<a name="line2834"></a><div class="linenumber">2834</div><div style="width:8em;display:inline-block"></div>try {
<a name="line2835"></a><div class="linenumber">2835</div><div style="width:10em;display:inline-block"></div>self.webSocket.disconnect();
<a name="line2836"></a><div class="linenumber">2836</div><div style="width:8em;display:inline-block"></div>} catch (e) {
<a name="line2837"></a><div class="linenumber">2837</div><div style="width:10em;display:inline-block"></div>// we don't really care if this fails.
<a name="line2838"></a><div class="linenumber">2838</div><div style="width:8em;display:inline-block"></div>}
<a name="line2839"></a><div class="linenumber">2839</div>
<a name="line2840"></a><div class="linenumber">2840</div><div style="width:8em;display:inline-block"></div>closedChannel = self.webSocket;
<a name="line2841"></a><div class="linenumber">2841</div><div style="width:8em;display:inline-block"></div>self.webSocket = 0;
<a name="line2842"></a><div class="linenumber">2842</div><div style="width:6em;display:inline-block"></div>}
<a name="line2843"></a><div class="linenumber">2843</div><div style="width:6em;display:inline-block"></div>self.loggingOut = false;
<a name="line2844"></a><div class="linenumber">2844</div><div style="width:6em;display:inline-block"></div>self.disconnecting = false;
<a name="line2845"></a><div class="linenumber">2845</div><div style="width:6em;display:inline-block"></div>if (roomOccupantListener) {
<a name="line2846"></a><div class="linenumber">2846</div><div style="width:8em;display:inline-block"></div>roomOccupantListener(null, {}, false);
<a name="line2847"></a><div class="linenumber">2847</div><div style="width:6em;display:inline-block"></div>}
<a name="line2848"></a><div class="linenumber">2848</div><div style="width:6em;display:inline-block"></div>self.emitEvent("roomOccupant", {});
<a name="line2849"></a><div class="linenumber">2849</div><div style="width:6em;display:inline-block"></div>oldConfig = {};
<a name="line2850"></a><div class="linenumber">2850</div><div style="width:4em;display:inline-block"></div>}, 250);
<a name="line2851"></a><div class="linenumber">2851</div><div style="width:2em;display:inline-block"></div>};
<a name="line2852"></a><div class="linenumber">2852</div>
<a name="line2853"></a><div class="linenumber">2853</div><div style="width:2em;display:inline-block"></div>/** @private */
<a name="line2854"></a><div class="linenumber">2854</div><div style="width:2em;display:inline-block"></div>//
<a name="line2855"></a><div class="linenumber">2855</div><div style="width:2em;display:inline-block"></div>// This function is used to send WebRTC signaling messages to another client. These messages all the form:
<a name="line2856"></a><div class="linenumber">2856</div><div style="width:2em;display:inline-block"></div>// destUser: some id or null
<a name="line2857"></a><div class="linenumber">2857</div><div style="width:2em;display:inline-block"></div>// msgType: one of ["offer"/"answer"/"candidate","reject","hangup", "getRoomList"]
<a name="line2858"></a><div class="linenumber">2858</div><div style="width:2em;display:inline-block"></div>// msgData: either null or an SDP record
<a name="line2859"></a><div class="linenumber">2859</div><div style="width:2em;display:inline-block"></div>// successCallback: a function with the signature function(msgType, wholeMsg);
<a name="line2860"></a><div class="linenumber">2860</div><div style="width:2em;display:inline-block"></div>// errorCallback: a function with signature function(errorCode, errorText)
<a name="line2861"></a><div class="linenumber">2861</div><div style="width:2em;display:inline-block"></div>//
<a name="line2862"></a><div class="linenumber">2862</div><div style="width:2em;display:inline-block"></div>function sendSignalling(destUser, msgType, msgData, successCallback, errorCallback) {
<a name="line2863"></a><div class="linenumber">2863</div><div style="width:4em;display:inline-block"></div>if (!self.webSocket) {
<a name="line2864"></a><div class="linenumber">2864</div><div style="width:6em;display:inline-block"></div>throw "Attempt to send message without a valid connection to the server.";
<a name="line2865"></a><div class="linenumber">2865</div><div style="width:4em;display:inline-block"></div>}
<a name="line2866"></a><div class="linenumber">2866</div><div style="width:4em;display:inline-block"></div>else {
<a name="line2867"></a><div class="linenumber">2867</div><div style="width:6em;display:inline-block"></div>var dataToShip = {
<a name="line2868"></a><div class="linenumber">2868</div><div style="width:8em;display:inline-block"></div>msgType: msgType
<a name="line2869"></a><div class="linenumber">2869</div><div style="width:6em;display:inline-block"></div>};
<a name="line2870"></a><div class="linenumber">2870</div><div style="width:6em;display:inline-block"></div>if (destUser) {
<a name="line2871"></a><div class="linenumber">2871</div><div style="width:8em;display:inline-block"></div>dataToShip.targetEasyrtcid = destUser;
<a name="line2872"></a><div class="linenumber">2872</div><div style="width:6em;display:inline-block"></div>}
<a name="line2873"></a><div class="linenumber">2873</div><div style="width:6em;display:inline-block"></div>if (msgData) {
<a name="line2874"></a><div class="linenumber">2874</div><div style="width:8em;display:inline-block"></div>dataToShip.msgData = msgData;
<a name="line2875"></a><div class="linenumber">2875</div><div style="width:6em;display:inline-block"></div>}
<a name="line2876"></a><div class="linenumber">2876</div>
<a name="line2877"></a><div class="linenumber">2877</div><div style="width:6em;display:inline-block"></div>logDebug("sending socket message " + JSON.stringify(dataToShip));
<a name="line2878"></a><div class="linenumber">2878</div>
<a name="line2879"></a><div class="linenumber">2879</div><div style="width:6em;display:inline-block"></div>self.webSocket.json.emit("easyrtcCmd", dataToShip,
<a name="line2880"></a><div class="linenumber">2880</div><div style="width:10em;display:inline-block"></div>function(ackMsg) {
<a name="line2881"></a><div class="linenumber">2881</div><div style="width:12em;display:inline-block"></div>if (ackMsg.msgType !== "error") {
<a name="line2882"></a><div class="linenumber">2882</div><div style="width:14em;display:inline-block"></div>if (!ackMsg.hasOwnProperty("msgData")) {
<a name="line2883"></a><div class="linenumber">2883</div><div style="width:16em;display:inline-block"></div>ackMsg.msgData = null;
<a name="line2884"></a><div class="linenumber">2884</div><div style="width:14em;display:inline-block"></div>}
<a name="line2885"></a><div class="linenumber">2885</div><div style="width:14em;display:inline-block"></div>if (successCallback) {
<a name="line2886"></a><div class="linenumber">2886</div><div style="width:16em;display:inline-block"></div>successCallback(ackMsg.msgType, ackMsg.msgData);
<a name="line2887"></a><div class="linenumber">2887</div><div style="width:14em;display:inline-block"></div>}
<a name="line2888"></a><div class="linenumber">2888</div><div style="width:12em;display:inline-block"></div>}
<a name="line2889"></a><div class="linenumber">2889</div><div style="width:12em;display:inline-block"></div>else {
<a name="line2890"></a><div class="linenumber">2890</div><div style="width:14em;display:inline-block"></div>if (errorCallback) {
<a name="line2891"></a><div class="linenumber">2891</div><div style="width:16em;display:inline-block"></div>errorCallback(ackMsg.msgData.errorCode, ackMsg.msgData.errorText);
<a name="line2892"></a><div class="linenumber">2892</div><div style="width:14em;display:inline-block"></div>}
<a name="line2893"></a><div class="linenumber">2893</div><div style="width:14em;display:inline-block"></div>else {
<a name="line2894"></a><div class="linenumber">2894</div><div style="width:16em;display:inline-block"></div>self.showError(ackMsg.msgData.errorCode, ackMsg.msgData.errorText);
<a name="line2895"></a><div class="linenumber">2895</div><div style="width:14em;display:inline-block"></div>}
<a name="line2896"></a><div class="linenumber">2896</div><div style="width:12em;display:inline-block"></div>}
<a name="line2897"></a><div class="linenumber">2897</div><div style="width:10em;display:inline-block"></div>}
<a name="line2898"></a><div class="linenumber">2898</div><div style="width:6em;display:inline-block"></div>);
<a name="line2899"></a><div class="linenumber">2899</div><div style="width:4em;display:inline-block"></div>}
<a name="line2900"></a><div class="linenumber">2900</div><div style="width:2em;display:inline-block"></div>}
<a name="line2901"></a><div class="linenumber">2901</div>
<a name="line2902"></a><div class="linenumber">2902</div><div style="width:2em;display:inline-block"></div>/** @private */
<a name="line2903"></a><div class="linenumber">2903</div><div style="width:2em;display:inline-block"></div>//
<a name="line2904"></a><div class="linenumber">2904</div><div style="width:2em;display:inline-block"></div>// This function is used to send large messages. it sends messages that have a transfer field
<a name="line2905"></a><div class="linenumber">2905</div><div style="width:2em;display:inline-block"></div>// so that the receiver knows it's a transfer message. To differentiate the transfers, a
<a name="line2906"></a><div class="linenumber">2906</div><div style="width:2em;display:inline-block"></div>// transferId is generated and passed for each message.
<a name="line2907"></a><div class="linenumber">2907</div><div style="width:2em;display:inline-block"></div>//
<a name="line2908"></a><div class="linenumber">2908</div><div style="width:2em;display:inline-block"></div>var sendByChunkUidCounter = 0;
<a name="line2909"></a><div class="linenumber">2909</div><div style="width:2em;display:inline-block"></div>/** @private */
<a name="line2910"></a><div class="linenumber">2910</div><div style="width:2em;display:inline-block"></div>function sendByChunkHelper(destUser, msgData) {
<a name="line2911"></a><div class="linenumber">2911</div><div style="width:4em;display:inline-block"></div>var transferId = destUser + '-' + sendByChunkUidCounter++;
<a name="line2912"></a><div class="linenumber">2912</div>
<a name="line2913"></a><div class="linenumber">2913</div><div style="width:4em;display:inline-block"></div>var pos, len, startMessage, message, endMessage;
<a name="line2914"></a><div class="linenumber">2914</div><div style="width:4em;display:inline-block"></div>var numberOfChunks = Math.ceil(msgData.length / self.maxP2PMessageLength);
<a name="line2915"></a><div class="linenumber">2915</div><div style="width:4em;display:inline-block"></div>startMessage = {
<a name="line2916"></a><div class="linenumber">2916</div><div style="width:6em;display:inline-block"></div>transfer: 'start',
<a name="line2917"></a><div class="linenumber">2917</div><div style="width:6em;display:inline-block"></div>transferId: transferId,
<a name="line2918"></a><div class="linenumber">2918</div><div style="width:6em;display:inline-block"></div>parts: numberOfChunks
<a name="line2919"></a><div class="linenumber">2919</div><div style="width:4em;display:inline-block"></div>};
<a name="line2920"></a><div class="linenumber">2920</div>
<a name="line2921"></a><div class="linenumber">2921</div><div style="width:4em;display:inline-block"></div>endMessage = {
<a name="line2922"></a><div class="linenumber">2922</div><div style="width:6em;display:inline-block"></div>transfer: 'end',
<a name="line2923"></a><div class="linenumber">2923</div><div style="width:6em;display:inline-block"></div>transferId: transferId
<a name="line2924"></a><div class="linenumber">2924</div><div style="width:4em;display:inline-block"></div>};
<a name="line2925"></a><div class="linenumber">2925</div>
<a name="line2926"></a><div class="linenumber">2926</div><div style="width:4em;display:inline-block"></div>peerConns[destUser].dataChannelS.send(JSON.stringify(startMessage));
<a name="line2927"></a><div class="linenumber">2927</div>
<a name="line2928"></a><div class="linenumber">2928</div><div style="width:4em;display:inline-block"></div>for (pos = 0, len = msgData.length; pos < len; pos += self.maxP2PMessageLength) {
<a name="line2929"></a><div class="linenumber">2929</div><div style="width:6em;display:inline-block"></div>message = {
<a name="line2930"></a><div class="linenumber">2930</div><div style="width:8em;display:inline-block"></div>transferId: transferId,
<a name="line2931"></a><div class="linenumber">2931</div><div style="width:8em;display:inline-block"></div>data: msgData.substr(pos, self.maxP2PMessageLength),
<a name="line2932"></a><div class="linenumber">2932</div><div style="width:8em;display:inline-block"></div>transfer: 'chunk'
<a name="line2933"></a><div class="linenumber">2933</div><div style="width:6em;display:inline-block"></div>};
<a name="line2934"></a><div class="linenumber">2934</div><div style="width:6em;display:inline-block"></div>peerConns[destUser].dataChannelS.send(JSON.stringify(message));
<a name="line2935"></a><div class="linenumber">2935</div><div style="width:4em;display:inline-block"></div>}
<a name="line2936"></a><div class="linenumber">2936</div>
<a name="line2937"></a><div class="linenumber">2937</div><div style="width:4em;display:inline-block"></div>peerConns[destUser].dataChannelS.send(JSON.stringify(endMessage));
<a name="line2938"></a><div class="linenumber">2938</div><div style="width:2em;display:inline-block"></div>}
<a name="line2939"></a><div class="linenumber">2939</div>
<a name="line2940"></a><div class="linenumber">2940</div><div style="width:2em;display:inline-block"></div>/**
<a name="line2941"></a><div class="linenumber">2941</div><div style="width:2em;display:inline-block"></div>*Sends data to another user using previously established data channel. This method will
<a name="line2942"></a><div class="linenumber">2942</div><div style="width:2em;display:inline-block"></div>* fail if no data channel has been established yet. Unlike the easyrtc.sendWS method,
<a name="line2943"></a><div class="linenumber">2943</div><div style="width:2em;display:inline-block"></div>* you can't send a dictionary, convert dictionaries to strings using JSON.stringify first.
<a name="line2944"></a><div class="linenumber">2944</div><div style="width:2em;display:inline-block"></div>* What data types you can send, and how large a data type depends on your browser.
<a name="line2945"></a><div class="linenumber">2945</div><div style="width:2em;display:inline-block"></div>* @param {String} destUser (an easyrtcid)
<a name="line2946"></a><div class="linenumber">2946</div><div style="width:2em;display:inline-block"></div>* @param {String} msgType - the type of message being sent (application specific).
<a name="line2947"></a><div class="linenumber">2947</div><div style="width:2em;display:inline-block"></div>* @param {Object} msgData - a JSONable object.
<a name="line2948"></a><div class="linenumber">2948</div><div style="width:2em;display:inline-block"></div>* @example
<a name="line2949"></a><div class="linenumber">2949</div><div style="width:2em;display:inline-block"></div>* easyrtc.sendDataP2P(someEasyrtcid, "roomData", {room:499, bldgNum:'asd'});
<a name="line2950"></a><div class="linenumber">2950</div><div style="width:2em;display:inline-block"></div>*/
<a name="line2951"></a><div class="linenumber">2951</div><div style="width:2em;display:inline-block"></div>this.sendDataP2P = function(destUser, msgType, msgData) {
<a name="line2952"></a><div class="linenumber">2952</div>
<a name="line2953"></a><div class="linenumber">2953</div><div style="width:4em;display:inline-block"></div>var flattenedData = JSON.stringify({msgType: msgType, msgData: msgData});
<a name="line2954"></a><div class="linenumber">2954</div><div style="width:4em;display:inline-block"></div>logDebug("sending p2p message to " + destUser + " with data=" + JSON.stringify(flattenedData));
<a name="line2955"></a><div class="linenumber">2955</div>
<a name="line2956"></a><div class="linenumber">2956</div><div style="width:4em;display:inline-block"></div>if (!peerConns[destUser]) {
<a name="line2957"></a><div class="linenumber">2957</div><div style="width:6em;display:inline-block"></div>self.showError(self.errCodes.DEVELOPER_ERR, "Attempt to send data peer to peer without a connection to " + destUser + ' first.');
<a name="line2958"></a><div class="linenumber">2958</div><div style="width:4em;display:inline-block"></div>}
<a name="line2959"></a><div class="linenumber">2959</div><div style="width:4em;display:inline-block"></div>else if (!peerConns[destUser].dataChannelS) {
<a name="line2960"></a><div class="linenumber">2960</div><div style="width:6em;display:inline-block"></div>self.showError(self.errCodes.DEVELOPER_ERR, "Attempt to send data peer to peer without establishing a data channel to " + destUser + ' first.');
<a name="line2961"></a><div class="linenumber">2961</div><div style="width:4em;display:inline-block"></div>}
<a name="line2962"></a><div class="linenumber">2962</div><div style="width:4em;display:inline-block"></div>else if (!peerConns[destUser].dataChannelReady) {
<a name="line2963"></a><div class="linenumber">2963</div><div style="width:6em;display:inline-block"></div>self.showError(self.errCodes.DEVELOPER_ERR, "Attempt to use data channel to " + destUser + " before it's ready to send.");
<a name="line2964"></a><div class="linenumber">2964</div><div style="width:4em;display:inline-block"></div>}
<a name="line2965"></a><div class="linenumber">2965</div><div style="width:4em;display:inline-block"></div>else {
<a name="line2966"></a><div class="linenumber">2966</div><div style="width:6em;display:inline-block"></div>try {
<a name="line2967"></a><div class="linenumber">2967</div><div style="width:8em;display:inline-block"></div>if (flattenedData.length > self.maxP2PMessageLength) {
<a name="line2968"></a><div class="linenumber">2968</div><div style="width:10em;display:inline-block"></div>sendByChunkHelper(destUser, flattenedData);
<a name="line2969"></a><div class="linenumber">2969</div><div style="width:8em;display:inline-block"></div>} else {
<a name="line2970"></a><div class="linenumber">2970</div><div style="width:10em;display:inline-block"></div>peerConns[destUser].dataChannelS.send(flattenedData);
<a name="line2971"></a><div class="linenumber">2971</div><div style="width:8em;display:inline-block"></div>}
<a name="line2972"></a><div class="linenumber">2972</div><div style="width:6em;display:inline-block"></div>} catch (sendDataErr) {
<a name="line2973"></a><div class="linenumber">2973</div><div style="width:8em;display:inline-block"></div>logDebug("sendDataP2P error: ", sendDataErr);
<a name="line2974"></a><div class="linenumber">2974</div><div style="width:8em;display:inline-block"></div>throw sendDataErr;
<a name="line2975"></a><div class="linenumber">2975</div><div style="width:6em;display:inline-block"></div>}
<a name="line2976"></a><div class="linenumber">2976</div><div style="width:4em;display:inline-block"></div>}
<a name="line2977"></a><div class="linenumber">2977</div><div style="width:2em;display:inline-block"></div>};
<a name="line2978"></a><div class="linenumber">2978</div>
<a name="line2979"></a><div class="linenumber">2979</div><div style="width:2em;display:inline-block"></div>/** Sends data to another user using websockets. The easyrtc.sendServerMessage or easyrtc.sendPeerMessage methods
<a name="line2980"></a><div class="linenumber">2980</div><div style="width:2em;display:inline-block"></div>* are wrappers for this method; application code should use them instead.
<a name="line2981"></a><div class="linenumber">2981</div><div style="width:2em;display:inline-block"></div>* @param {String} destination - either a string containing the easyrtcId of the other user, or an object containing some subset of the following fields: targetEasyrtcid, targetGroup, targetRoom.
<a name="line2982"></a><div class="linenumber">2982</div><div style="width:2em;display:inline-block"></div>* Specifying multiple fields restricts the scope of the destination (operates as a logical AND, not a logical OR).
<a name="line2983"></a><div class="linenumber">2983</div><div style="width:2em;display:inline-block"></div>* @param {String} msgType -the type of message being sent (application specific).
<a name="line2984"></a><div class="linenumber">2984</div><div style="width:2em;display:inline-block"></div>* @param {Object} msgData - a JSONable object.
<a name="line2985"></a><div class="linenumber">2985</div><div style="width:2em;display:inline-block"></div>* @param {Function} ackhandler - by default, the ackhandler handles acknowledgments from the server that your message was delivered to it's destination.
<a name="line2986"></a><div class="linenumber">2986</div><div style="width:2em;display:inline-block"></div>* However, application logic in the server can over-ride this. If you leave this null, a stub ackHandler will be used. The ackHandler
<a name="line2987"></a><div class="linenumber">2987</div><div style="width:2em;display:inline-block"></div>* gets passed a message with the same msgType as your outgoing message, or a message type of "error" in which case
<a name="line2988"></a><div class="linenumber">2988</div><div style="width:2em;display:inline-block"></div>* msgData will contain a errorCode and errorText fields.
<a name="line2989"></a><div class="linenumber">2989</div><div style="width:2em;display:inline-block"></div>* @example
<a name="line2990"></a><div class="linenumber">2990</div><div style="width:2em;display:inline-block"></div>* easyrtc.sendDataWS(someEasyrtcid, "setPostalAddress", {room:499, bldgNum:'asd'},
<a name="line2991"></a><div class="linenumber">2991</div><div style="width:2em;display:inline-block"></div>* function(ackMsg){
<a name="line2992"></a><div class="linenumber">2992</div><div style="width:2em;display:inline-block"></div>* console.log("saw the following acknowledgment " + JSON.stringify(ackMsg));
<a name="line2993"></a><div class="linenumber">2993</div><div style="width:2em;display:inline-block"></div>* }
<a name="line2994"></a><div class="linenumber">2994</div><div style="width:2em;display:inline-block"></div>* );
<a name="line2995"></a><div class="linenumber">2995</div><div style="width:2em;display:inline-block"></div>*/
<a name="line2996"></a><div class="linenumber">2996</div><div style="width:2em;display:inline-block"></div>this.sendDataWS = function(destination, msgType, msgData, ackhandler) {
<a name="line2997"></a><div class="linenumber">2997</div><div style="width:4em;display:inline-block"></div>logDebug("sending client message via websockets to " + destination + " with data=" + JSON.stringify(msgData));
<a name="line2998"></a><div class="linenumber">2998</div>
<a name="line2999"></a><div class="linenumber">2999</div><div style="width:4em;display:inline-block"></div>if (!ackhandler) {
<a name="line3000"></a><div class="linenumber">3000</div><div style="width:6em;display:inline-block"></div>ackhandler = function(msg) {
<a name="line3001"></a><div class="linenumber">3001</div><div style="width:8em;display:inline-block"></div>if (msg.msgType === "error") {
<a name="line3002"></a><div class="linenumber">3002</div><div style="width:10em;display:inline-block"></div>self.showError(msg.msgData.errorCode, msg.msgData.errorText);
<a name="line3003"></a><div class="linenumber">3003</div><div style="width:8em;display:inline-block"></div>}
<a name="line3004"></a><div class="linenumber">3004</div><div style="width:6em;display:inline-block"></div>};
<a name="line3005"></a><div class="linenumber">3005</div><div style="width:4em;display:inline-block"></div>}
<a name="line3006"></a><div class="linenumber">3006</div>
<a name="line3007"></a><div class="linenumber">3007</div><div style="width:4em;display:inline-block"></div>var outgoingMessage = {
<a name="line3008"></a><div class="linenumber">3008</div><div style="width:6em;display:inline-block"></div>msgType: msgType,
<a name="line3009"></a><div class="linenumber">3009</div><div style="width:6em;display:inline-block"></div>msgData: msgData
<a name="line3010"></a><div class="linenumber">3010</div><div style="width:4em;display:inline-block"></div>};
<a name="line3011"></a><div class="linenumber">3011</div>
<a name="line3012"></a><div class="linenumber">3012</div><div style="width:4em;display:inline-block"></div>if (destination) {
<a name="line3013"></a><div class="linenumber">3013</div><div style="width:6em;display:inline-block"></div>if (typeof destination === 'string') {
<a name="line3014"></a><div class="linenumber">3014</div><div style="width:8em;display:inline-block"></div>outgoingMessage.targetEasyrtcid = destination;
<a name="line3015"></a><div class="linenumber">3015</div><div style="width:6em;display:inline-block"></div>}
<a name="line3016"></a><div class="linenumber">3016</div><div style="width:6em;display:inline-block"></div>else if (typeof destination === 'object') {
<a name="line3017"></a><div class="linenumber">3017</div><div style="width:8em;display:inline-block"></div>if (destination.targetEasyrtcid) {
<a name="line3018"></a><div class="linenumber">3018</div><div style="width:10em;display:inline-block"></div>outgoingMessage.targetEasyrtcid = destination.targetEasyrtcid;
<a name="line3019"></a><div class="linenumber">3019</div><div style="width:8em;display:inline-block"></div>}
<a name="line3020"></a><div class="linenumber">3020</div><div style="width:8em;display:inline-block"></div>if (destination.targetRoom) {
<a name="line3021"></a><div class="linenumber">3021</div><div style="width:10em;display:inline-block"></div>outgoingMessage.targetRoom = destination.targetRoom;
<a name="line3022"></a><div class="linenumber">3022</div><div style="width:8em;display:inline-block"></div>}
<a name="line3023"></a><div class="linenumber">3023</div><div style="width:8em;display:inline-block"></div>if (destination.targetGroup) {
<a name="line3024"></a><div class="linenumber">3024</div><div style="width:10em;display:inline-block"></div>outgoingMessage.targetGroup = destination.targetGroup;
<a name="line3025"></a><div class="linenumber">3025</div><div style="width:8em;display:inline-block"></div>}
<a name="line3026"></a><div class="linenumber">3026</div><div style="width:6em;display:inline-block"></div>}
<a name="line3027"></a><div class="linenumber">3027</div><div style="width:4em;display:inline-block"></div>}
<a name="line3028"></a><div class="linenumber">3028</div>
<a name="line3029"></a><div class="linenumber">3029</div><div style="width:4em;display:inline-block"></div>if (self.webSocket) {
<a name="line3030"></a><div class="linenumber">3030</div><div style="width:6em;display:inline-block"></div>self.webSocket.json.emit("easyrtcMsg", outgoingMessage, ackhandler);
<a name="line3031"></a><div class="linenumber">3031</div><div style="width:4em;display:inline-block"></div>}
<a name="line3032"></a><div class="linenumber">3032</div><div style="width:4em;display:inline-block"></div>else {
<a name="line3033"></a><div class="linenumber">3033</div><div style="width:6em;display:inline-block"></div>logDebug("websocket failed because no connection to server");
<a name="line3034"></a><div class="linenumber">3034</div>
<a name="line3035"></a><div class="linenumber">3035</div><div style="width:6em;display:inline-block"></div>throw "Attempt to send message without a valid connection to the server.";
<a name="line3036"></a><div class="linenumber">3036</div><div style="width:4em;display:inline-block"></div>}
<a name="line3037"></a><div class="linenumber">3037</div><div style="width:2em;display:inline-block"></div>};
<a name="line3038"></a><div class="linenumber">3038</div>
<a name="line3039"></a><div class="linenumber">3039</div><div style="width:2em;display:inline-block"></div>/** Sends data to another user. This method uses data channels if one has been set up, or websockets otherwise.
<a name="line3040"></a><div class="linenumber">3040</div><div style="width:2em;display:inline-block"></div>* @param {String} destUser - a string containing the easyrtcId of the other user.
<a name="line3041"></a><div class="linenumber">3041</div><div style="width:2em;display:inline-block"></div>* Specifying multiple fields restricts the scope of the destination (operates as a logical AND, not a logical OR).
<a name="line3042"></a><div class="linenumber">3042</div><div style="width:2em;display:inline-block"></div>* @param {String} msgType -the type of message being sent (application specific).
<a name="line3043"></a><div class="linenumber">3043</div><div style="width:2em;display:inline-block"></div>* @param {Object} msgData - a JSONable object.
<a name="line3044"></a><div class="linenumber">3044</div><div style="width:2em;display:inline-block"></div>* @param {Function} ackHandler - a function which receives acknowledgments. May only be invoked in
<a name="line3045"></a><div class="linenumber">3045</div><div style="width:2em;display:inline-block"></div>* the websocket case.
<a name="line3046"></a><div class="linenumber">3046</div><div style="width:2em;display:inline-block"></div>* @example
<a name="line3047"></a><div class="linenumber">3047</div><div style="width:2em;display:inline-block"></div>* easyrtc.sendData(someEasyrtcid, "roomData", {room:499, bldgNum:'asd'},
<a name="line3048"></a><div class="linenumber">3048</div><div style="width:2em;display:inline-block"></div>* function ackHandler(msgType, msgData);
<a name="line3049"></a><div class="linenumber">3049</div><div style="width:2em;display:inline-block"></div>* );
<a name="line3050"></a><div class="linenumber">3050</div><div style="width:2em;display:inline-block"></div>*/
<a name="line3051"></a><div class="linenumber">3051</div><div style="width:2em;display:inline-block"></div>this.sendData = function(destUser, msgType, msgData, ackHandler) {
<a name="line3052"></a><div class="linenumber">3052</div><div style="width:4em;display:inline-block"></div>if (peerConns[destUser] && peerConns[destUser].dataChannelReady) {
<a name="line3053"></a><div class="linenumber">3053</div><div style="width:6em;display:inline-block"></div>self.sendDataP2P(destUser, msgType, msgData);
<a name="line3054"></a><div class="linenumber">3054</div><div style="width:4em;display:inline-block"></div>}
<a name="line3055"></a><div class="linenumber">3055</div><div style="width:4em;display:inline-block"></div>else {
<a name="line3056"></a><div class="linenumber">3056</div><div style="width:6em;display:inline-block"></div>self.sendDataWS(destUser, msgType, msgData, ackHandler);
<a name="line3057"></a><div class="linenumber">3057</div><div style="width:4em;display:inline-block"></div>}
<a name="line3058"></a><div class="linenumber">3058</div><div style="width:2em;display:inline-block"></div>};
<a name="line3059"></a><div class="linenumber">3059</div>
<a name="line3060"></a><div class="linenumber">3060</div><div style="width:2em;display:inline-block"></div>/**
<a name="line3061"></a><div class="linenumber">3061</div><div style="width:2em;display:inline-block"></div>* Sends a message to another peer on the easyrtcMsg channel.
<a name="line3062"></a><div class="linenumber">3062</div><div style="width:2em;display:inline-block"></div>* @param {String} destination - either a string containing the easyrtcId of the other user, or an object containing some subset of the following fields: targetEasyrtcid, targetGroup, targetRoom.
<a name="line3063"></a><div class="linenumber">3063</div><div style="width:2em;display:inline-block"></div>* Specifying multiple fields restricts the scope of the destination (operates as a logical AND, not a logical OR).
<a name="line3064"></a><div class="linenumber">3064</div><div style="width:2em;display:inline-block"></div>* @param {String} msgType - the type of message being sent (application specific).
<a name="line3065"></a><div class="linenumber">3065</div><div style="width:2em;display:inline-block"></div>* @param {Object} msgData - a JSONable object with the message contents.
<a name="line3066"></a><div class="linenumber">3066</div><div style="width:2em;display:inline-block"></div>* @param {function(String, Object)} successCB - a callback function with results from the server.
<a name="line3067"></a><div class="linenumber">3067</div><div style="width:2em;display:inline-block"></div>* @param {function(String, String)} failureCB - a callback function to handle errors.
<a name="line3068"></a><div class="linenumber">3068</div><div style="width:2em;display:inline-block"></div>* @example
<a name="line3069"></a><div class="linenumber">3069</div><div style="width:2em;display:inline-block"></div>* easyrtc.sendPeerMessage(otherUser, 'offer_candy', {candy_name:'mars'},
<a name="line3070"></a><div class="linenumber">3070</div><div style="width:2em;display:inline-block"></div>* function(msgType, msgBody ){
<a name="line3071"></a><div class="linenumber">3071</div><div style="width:2em;display:inline-block"></div>* console.log("message was sent");
<a name="line3072"></a><div class="linenumber">3072</div><div style="width:2em;display:inline-block"></div>* },
<a name="line3073"></a><div class="linenumber">3073</div><div style="width:2em;display:inline-block"></div>* function(errorCode, errorText){
<a name="line3074"></a><div class="linenumber">3074</div><div style="width:2em;display:inline-block"></div>* console.log("error was " + errorText);
<a name="line3075"></a><div class="linenumber">3075</div><div style="width:2em;display:inline-block"></div>* });
<a name="line3076"></a><div class="linenumber">3076</div><div style="width:2em;display:inline-block"></div>*/
<a name="line3077"></a><div class="linenumber">3077</div><div style="width:2em;display:inline-block"></div>this.sendPeerMessage = function(destination, msgType, msgData, successCB, failureCB) {
<a name="line3078"></a><div class="linenumber">3078</div><div style="width:4em;display:inline-block"></div>if (!destination) {
<a name="line3079"></a><div class="linenumber">3079</div><div style="width:6em;display:inline-block"></div>self.showError(self.errCodes.DEVELOPER_ERR, "destination was null in sendPeerMessage");
<a name="line3080"></a><div class="linenumber">3080</div><div style="width:4em;display:inline-block"></div>}
<a name="line3081"></a><div class="linenumber">3081</div>
<a name="line3082"></a><div class="linenumber">3082</div><div style="width:4em;display:inline-block"></div>logDebug("sending peer message " + JSON.stringify(msgData));
<a name="line3083"></a><div class="linenumber">3083</div>
<a name="line3084"></a><div class="linenumber">3084</div><div style="width:4em;display:inline-block"></div>function ackHandler(response) {
<a name="line3085"></a><div class="linenumber">3085</div><div style="width:6em;display:inline-block"></div>if (response.msgType === "error") {
<a name="line3086"></a><div class="linenumber">3086</div><div style="width:8em;display:inline-block"></div>if (failureCB) {
<a name="line3087"></a><div class="linenumber">3087</div><div style="width:10em;display:inline-block"></div>failureCB(response.msgData.errorCode, response.msgData.errorText);
<a name="line3088"></a><div class="linenumber">3088</div><div style="width:8em;display:inline-block"></div>}
<a name="line3089"></a><div class="linenumber">3089</div><div style="width:6em;display:inline-block"></div>}
<a name="line3090"></a><div class="linenumber">3090</div><div style="width:6em;display:inline-block"></div>else {
<a name="line3091"></a><div class="linenumber">3091</div><div style="width:8em;display:inline-block"></div>if (successCB) {
<a name="line3092"></a><div class="linenumber">3092</div><div style="width:10em;display:inline-block"></div>// firefox complains if you pass an undefined as an parameter.
<a name="line3093"></a><div class="linenumber">3093</div><div style="width:10em;display:inline-block"></div>successCB(response.msgType, response.msgData ? response.msgData : null);
<a name="line3094"></a><div class="linenumber">3094</div><div style="width:8em;display:inline-block"></div>}
<a name="line3095"></a><div class="linenumber">3095</div><div style="width:6em;display:inline-block"></div>}
<a name="line3096"></a><div class="linenumber">3096</div><div style="width:4em;display:inline-block"></div>}
<a name="line3097"></a><div class="linenumber">3097</div>
<a name="line3098"></a><div class="linenumber">3098</div><div style="width:4em;display:inline-block"></div>self.sendDataWS(destination, msgType, msgData, ackHandler);
<a name="line3099"></a><div class="linenumber">3099</div><div style="width:2em;display:inline-block"></div>};
<a name="line3100"></a><div class="linenumber">3100</div>
<a name="line3101"></a><div class="linenumber">3101</div><div style="width:2em;display:inline-block"></div>/**
<a name="line3102"></a><div class="linenumber">3102</div><div style="width:2em;display:inline-block"></div>* Sends a message to the application code in the server (ie, on the easyrtcMsg channel).
<a name="line3103"></a><div class="linenumber">3103</div><div style="width:2em;display:inline-block"></div>* @param {String} msgType - the type of message being sent (application specific).
<a name="line3104"></a><div class="linenumber">3104</div><div style="width:2em;display:inline-block"></div>* @param {Object} msgData - a JSONable object with the message contents.
<a name="line3105"></a><div class="linenumber">3105</div><div style="width:2em;display:inline-block"></div>* @param {function(String, Object)} successCB - a callback function with results from the server.
<a name="line3106"></a><div class="linenumber">3106</div><div style="width:2em;display:inline-block"></div>* @param {function(String, String)} failureCB - a callback function to handle errors.
<a name="line3107"></a><div class="linenumber">3107</div><div style="width:2em;display:inline-block"></div>* @example
<a name="line3108"></a><div class="linenumber">3108</div><div style="width:2em;display:inline-block"></div>* easyrtc.sendServerMessage('get_candy', {candy_name:'mars'},
<a name="line3109"></a><div class="linenumber">3109</div><div style="width:2em;display:inline-block"></div>* function(msgType, msgData ){
<a name="line3110"></a><div class="linenumber">3110</div><div style="width:2em;display:inline-block"></div>* console.log("got candy count of " + msgData.barCount);
<a name="line3111"></a><div class="linenumber">3111</div><div style="width:2em;display:inline-block"></div>* },
<a name="line3112"></a><div class="linenumber">3112</div><div style="width:2em;display:inline-block"></div>* function(errorCode, errorText){
<a name="line3113"></a><div class="linenumber">3113</div><div style="width:2em;display:inline-block"></div>* console.log("error was " + errorText);
<a name="line3114"></a><div class="linenumber">3114</div><div style="width:2em;display:inline-block"></div>* });
<a name="line3115"></a><div class="linenumber">3115</div><div style="width:2em;display:inline-block"></div>*/
<a name="line3116"></a><div class="linenumber">3116</div><div style="width:2em;display:inline-block"></div>this.sendServerMessage = function(msgType, msgData, successCB, failureCB) {
<a name="line3117"></a><div class="linenumber">3117</div>
<a name="line3118"></a><div class="linenumber">3118</div><div style="width:4em;display:inline-block"></div>var dataToShip = {msgType: msgType, msgData: msgData};
<a name="line3119"></a><div class="linenumber">3119</div><div style="width:4em;display:inline-block"></div>logDebug("sending server message " + JSON.stringify(dataToShip));
<a name="line3120"></a><div class="linenumber">3120</div>
<a name="line3121"></a><div class="linenumber">3121</div><div style="width:4em;display:inline-block"></div>function ackhandler(response) {
<a name="line3122"></a><div class="linenumber">3122</div><div style="width:6em;display:inline-block"></div>if (response.msgType === "error") {
<a name="line3123"></a><div class="linenumber">3123</div><div style="width:8em;display:inline-block"></div>if (failureCB) {
<a name="line3124"></a><div class="linenumber">3124</div><div style="width:10em;display:inline-block"></div>failureCB(response.msgData.errorCode, response.msgData.errorText);
<a name="line3125"></a><div class="linenumber">3125</div><div style="width:8em;display:inline-block"></div>}
<a name="line3126"></a><div class="linenumber">3126</div><div style="width:6em;display:inline-block"></div>}
<a name="line3127"></a><div class="linenumber">3127</div><div style="width:6em;display:inline-block"></div>else {
<a name="line3128"></a><div class="linenumber">3128</div><div style="width:8em;display:inline-block"></div>if (successCB) {
<a name="line3129"></a><div class="linenumber">3129</div><div style="width:10em;display:inline-block"></div>successCB(response.msgType, response.msgData ? response.msgData : null);
<a name="line3130"></a><div class="linenumber">3130</div><div style="width:8em;display:inline-block"></div>}
<a name="line3131"></a><div class="linenumber">3131</div><div style="width:6em;display:inline-block"></div>}
<a name="line3132"></a><div class="linenumber">3132</div><div style="width:4em;display:inline-block"></div>}
<a name="line3133"></a><div class="linenumber">3133</div>
<a name="line3134"></a><div class="linenumber">3134</div><div style="width:4em;display:inline-block"></div>self.sendDataWS(null, msgType, msgData, ackhandler);
<a name="line3135"></a><div class="linenumber">3135</div><div style="width:2em;display:inline-block"></div>};
<a name="line3136"></a><div class="linenumber">3136</div>
<a name="line3137"></a><div class="linenumber">3137</div><div style="width:2em;display:inline-block"></div>/** Sends the server a request for the list of rooms the user can see.
<a name="line3138"></a><div class="linenumber">3138</div><div style="width:2em;display:inline-block"></div>* You must have already be connected to use this function.
<a name="line3139"></a><div class="linenumber">3139</div><div style="width:2em;display:inline-block"></div>* @param {function(Object)} callback - on success, this function is called with a map of the form { roomName:{"roomName":String, "numberClients": Number}}.
<a name="line3140"></a><div class="linenumber">3140</div><div style="width:2em;display:inline-block"></div>* The roomName appears as both the key to the map, and as the value of the "roomName" field.
<a name="line3141"></a><div class="linenumber">3141</div><div style="width:2em;display:inline-block"></div>* @param {function(String, String)} errorCallback is called on failure. It gets an errorCode and errorText as it's too arguments.
<a name="line3142"></a><div class="linenumber">3142</div><div style="width:2em;display:inline-block"></div>* @example
<a name="line3143"></a><div class="linenumber">3143</div><div style="width:2em;display:inline-block"></div>* easyrtc.getRoomList(
<a name="line3144"></a><div class="linenumber">3144</div><div style="width:2em;display:inline-block"></div>* function(roomList){
<a name="line3145"></a><div class="linenumber">3145</div><div style="width:2em;display:inline-block"></div>* for(roomName in roomList){
<a name="line3146"></a><div class="linenumber">3146</div><div style="width:2em;display:inline-block"></div>* console.log("saw room " + roomName);
<a name="line3147"></a><div class="linenumber">3147</div><div style="width:2em;display:inline-block"></div>* }
<a name="line3148"></a><div class="linenumber">3148</div><div style="width:2em;display:inline-block"></div>* },
<a name="line3149"></a><div class="linenumber">3149</div><div style="width:2em;display:inline-block"></div>* function(errorCode, errorText){
<a name="line3150"></a><div class="linenumber">3150</div><div style="width:2em;display:inline-block"></div>* easyrtc.showError(errorCode, errorText);
<a name="line3151"></a><div class="linenumber">3151</div><div style="width:2em;display:inline-block"></div>* }
<a name="line3152"></a><div class="linenumber">3152</div><div style="width:2em;display:inline-block"></div>* );
<a name="line3153"></a><div class="linenumber">3153</div><div style="width:2em;display:inline-block"></div>*/
<a name="line3154"></a><div class="linenumber">3154</div><div style="width:2em;display:inline-block"></div>this.getRoomList = function(callback, errorCallback) {
<a name="line3155"></a><div class="linenumber">3155</div><div style="width:4em;display:inline-block"></div>sendSignalling(null, "getRoomList", null,
<a name="line3156"></a><div class="linenumber">3156</div><div style="width:8em;display:inline-block"></div>function(msgType, msgData) {
<a name="line3157"></a><div class="linenumber">3157</div><div style="width:10em;display:inline-block"></div>callback(msgData.roomList);
<a name="line3158"></a><div class="linenumber">3158</div><div style="width:8em;display:inline-block"></div>},
<a name="line3159"></a><div class="linenumber">3159</div><div style="width:8em;display:inline-block"></div>function(errorCode, errorText) {
<a name="line3160"></a><div class="linenumber">3160</div><div style="width:10em;display:inline-block"></div>if (errorCallback) {
<a name="line3161"></a><div class="linenumber">3161</div><div style="width:12em;display:inline-block"></div>errorCallback(errorCode, errorText);
<a name="line3162"></a><div class="linenumber">3162</div><div style="width:10em;display:inline-block"></div>}
<a name="line3163"></a><div class="linenumber">3163</div><div style="width:10em;display:inline-block"></div>else {
<a name="line3164"></a><div class="linenumber">3164</div><div style="width:12em;display:inline-block"></div>self.showError(errorCode, errorText);
<a name="line3165"></a><div class="linenumber">3165</div><div style="width:10em;display:inline-block"></div>}
<a name="line3166"></a><div class="linenumber">3166</div><div style="width:8em;display:inline-block"></div>}
<a name="line3167"></a><div class="linenumber">3167</div><div style="width:4em;display:inline-block"></div>);
<a name="line3168"></a><div class="linenumber">3168</div><div style="width:2em;display:inline-block"></div>};
<a name="line3169"></a><div class="linenumber">3169</div>
<a name="line3170"></a><div class="linenumber">3170</div><div style="width:2em;display:inline-block"></div>/** Value returned by easyrtc.getConnectStatus if the other user isn't connected to us. */
<a name="line3171"></a><div class="linenumber">3171</div><div style="width:2em;display:inline-block"></div>this.NOT_CONNECTED = "not connected";
<a name="line3172"></a><div class="linenumber">3172</div>
<a name="line3173"></a><div class="linenumber">3173</div><div style="width:2em;display:inline-block"></div>/** Value returned by easyrtc.getConnectStatus if the other user is in the process of getting connected */
<a name="line3174"></a><div class="linenumber">3174</div><div style="width:2em;display:inline-block"></div>this.BECOMING_CONNECTED = "connection in progress to us.";
<a name="line3175"></a><div class="linenumber">3175</div>
<a name="line3176"></a><div class="linenumber">3176</div><div style="width:2em;display:inline-block"></div>/** Value returned by easyrtc.getConnectStatus if the other user is connected to us. */
<a name="line3177"></a><div class="linenumber">3177</div><div style="width:2em;display:inline-block"></div>this.IS_CONNECTED = "is connected";
<a name="line3178"></a><div class="linenumber">3178</div>
<a name="line3179"></a><div class="linenumber">3179</div><div style="width:2em;display:inline-block"></div>/**
<a name="line3180"></a><div class="linenumber">3180</div><div style="width:2em;display:inline-block"></div>* Check if the client has a peer-2-peer connection to another user.
<a name="line3181"></a><div class="linenumber">3181</div><div style="width:2em;display:inline-block"></div>* The return values are text strings so you can use them in debugging output.
<a name="line3182"></a><div class="linenumber">3182</div><div style="width:2em;display:inline-block"></div>* @param {String} otherUser - the easyrtcid of the other user.
<a name="line3183"></a><div class="linenumber">3183</div><div style="width:2em;display:inline-block"></div>* @return {String} one of the following values: easyrtc.NOT_CONNECTED, easyrtc.BECOMING_CONNECTED, easyrtc.IS_CONNECTED
<a name="line3184"></a><div class="linenumber">3184</div><div style="width:2em;display:inline-block"></div>* @example
<a name="line3185"></a><div class="linenumber">3185</div><div style="width:2em;display:inline-block"></div>* if( easyrtc.getConnectStatus(otherEasyrtcid) == easyrtc.NOT_CONNECTED ){
<a name="line3186"></a><div class="linenumber">3186</div><div style="width:2em;display:inline-block"></div>* easyrtc.call(otherEasyrtcid,
<a name="line3187"></a><div class="linenumber">3187</div><div style="width:2em;display:inline-block"></div>* function(){ console.log("success"); },
<a name="line3188"></a><div class="linenumber">3188</div><div style="width:2em;display:inline-block"></div>* function(){ console.log("failure"); });
<a name="line3189"></a><div class="linenumber">3189</div><div style="width:2em;display:inline-block"></div>* }
<a name="line3190"></a><div class="linenumber">3190</div><div style="width:2em;display:inline-block"></div>*/
<a name="line3191"></a><div class="linenumber">3191</div><div style="width:2em;display:inline-block"></div>this.getConnectStatus = function(otherUser) {
<a name="line3192"></a><div class="linenumber">3192</div><div style="width:4em;display:inline-block"></div>if (!peerConns.hasOwnProperty(otherUser)) {
<a name="line3193"></a><div class="linenumber">3193</div><div style="width:6em;display:inline-block"></div>return self.NOT_CONNECTED;
<a name="line3194"></a><div class="linenumber">3194</div><div style="width:4em;display:inline-block"></div>}
<a name="line3195"></a><div class="linenumber">3195</div><div style="width:4em;display:inline-block"></div>var peer = peerConns[otherUser];
<a name="line3196"></a><div class="linenumber">3196</div><div style="width:4em;display:inline-block"></div>if ((peer.sharingAudio || peer.sharingVideo) && !peer.startedAV) {
<a name="line3197"></a><div class="linenumber">3197</div><div style="width:6em;display:inline-block"></div>return self.BECOMING_CONNECTED;
<a name="line3198"></a><div class="linenumber">3198</div><div style="width:4em;display:inline-block"></div>}
<a name="line3199"></a><div class="linenumber">3199</div><div style="width:4em;display:inline-block"></div>else if (peer.sharingData && !peer.dataChannelReady) {
<a name="line3200"></a><div class="linenumber">3200</div><div style="width:6em;display:inline-block"></div>return self.BECOMING_CONNECTED;
<a name="line3201"></a><div class="linenumber">3201</div><div style="width:4em;display:inline-block"></div>}
<a name="line3202"></a><div class="linenumber">3202</div><div style="width:4em;display:inline-block"></div>else {
<a name="line3203"></a><div class="linenumber">3203</div><div style="width:6em;display:inline-block"></div>return self.IS_CONNECTED;
<a name="line3204"></a><div class="linenumber">3204</div><div style="width:4em;display:inline-block"></div>}
<a name="line3205"></a><div class="linenumber">3205</div><div style="width:2em;display:inline-block"></div>};
<a name="line3206"></a><div class="linenumber">3206</div>
<a name="line3207"></a><div class="linenumber">3207</div><div style="width:2em;display:inline-block"></div>/**
<a name="line3208"></a><div class="linenumber">3208</div><div style="width:2em;display:inline-block"></div>* @private
<a name="line3209"></a><div class="linenumber">3209</div><div style="width:2em;display:inline-block"></div>*/
<a name="line3210"></a><div class="linenumber">3210</div><div style="width:2em;display:inline-block"></div>function buildPeerConstraints() {
<a name="line3211"></a><div class="linenumber">3211</div><div style="width:4em;display:inline-block"></div>var options = [];
<a name="line3212"></a><div class="linenumber">3212</div><div style="width:4em;display:inline-block"></div>options.push({'DtlsSrtpKeyAgreement': 'true'}); // for interoperability
<a name="line3213"></a><div class="linenumber">3213</div><div style="width:4em;display:inline-block"></div>return {optional: options};
<a name="line3214"></a><div class="linenumber">3214</div><div style="width:2em;display:inline-block"></div>}
<a name="line3215"></a><div class="linenumber">3215</div>
<a name="line3216"></a><div class="linenumber">3216</div><div style="width:2em;display:inline-block"></div>/** @private */
<a name="line3217"></a><div class="linenumber">3217</div><div style="width:2em;display:inline-block"></div>function sendQueuedCandidates(peer, onSignalSuccess, onSignalFailure) {
<a name="line3218"></a><div class="linenumber">3218</div><div style="width:4em;display:inline-block"></div>var i;
<a name="line3219"></a><div class="linenumber">3219</div><div style="width:4em;display:inline-block"></div>for (i = 0; i < peerConns[peer].candidatesToSend.length; i++) {
<a name="line3220"></a><div class="linenumber">3220</div><div style="width:6em;display:inline-block"></div>sendSignalling(
<a name="line3221"></a><div class="linenumber">3221</div><div style="width:10em;display:inline-block"></div>peer,
<a name="line3222"></a><div class="linenumber">3222</div><div style="width:10em;display:inline-block"></div>"candidate",
<a name="line3223"></a><div class="linenumber">3223</div><div style="width:10em;display:inline-block"></div>peerConns[peer].candidatesToSend[i],
<a name="line3224"></a><div class="linenumber">3224</div><div style="width:10em;display:inline-block"></div>onSignalSuccess,
<a name="line3225"></a><div class="linenumber">3225</div><div style="width:10em;display:inline-block"></div>onSignalFailure
<a name="line3226"></a><div class="linenumber">3226</div><div style="width:10em;display:inline-block"></div>);
<a name="line3227"></a><div class="linenumber">3227</div><div style="width:4em;display:inline-block"></div>}
<a name="line3228"></a><div class="linenumber">3228</div><div style="width:2em;display:inline-block"></div>}
<a name="line3229"></a><div class="linenumber">3229</div>
<a name="line3230"></a><div class="linenumber">3230</div><div style="width:2em;display:inline-block"></div>/** @private */
<a name="line3231"></a><div class="linenumber">3231</div><div style="width:2em;display:inline-block"></div>//
<a name="line3232"></a><div class="linenumber">3232</div><div style="width:2em;display:inline-block"></div>// This function calls the users onStreamClosed handler, passing it the easyrtcid of the peer, the stream itself,
<a name="line3233"></a><div class="linenumber">3233</div><div style="width:2em;display:inline-block"></div>// and the name of the stream.
<a name="line3234"></a><div class="linenumber">3234</div><div style="width:2em;display:inline-block"></div>//
<a name="line3235"></a><div class="linenumber">3235</div><div style="width:2em;display:inline-block"></div>function emitOnStreamClosed(easyrtcid, stream) {
<a name="line3236"></a><div class="linenumber">3236</div><div style="width:4em;display:inline-block"></div>if (!peerConns[easyrtcid]) {
<a name="line3237"></a><div class="linenumber">3237</div><div style="width:6em;display:inline-block"></div>return;
<a name="line3238"></a><div class="linenumber">3238</div><div style="width:4em;display:inline-block"></div>}
<a name="line3239"></a><div class="linenumber">3239</div><div style="width:4em;display:inline-block"></div>var streamName;
<a name="line3240"></a><div class="linenumber">3240</div><div style="width:4em;display:inline-block"></div>var id;
<a name="line3241"></a><div class="linenumber">3241</div><div style="width:4em;display:inline-block"></div>if (stream.id) {
<a name="line3242"></a><div class="linenumber">3242</div><div style="width:6em;display:inline-block"></div>id = stream.id;
<a name="line3243"></a><div class="linenumber">3243</div><div style="width:4em;display:inline-block"></div>}
<a name="line3244"></a><div class="linenumber">3244</div><div style="width:4em;display:inline-block"></div>else {
<a name="line3245"></a><div class="linenumber">3245</div><div style="width:6em;display:inline-block"></div>id = "default";
<a name="line3246"></a><div class="linenumber">3246</div><div style="width:4em;display:inline-block"></div>}
<a name="line3247"></a><div class="linenumber">3247</div><div style="width:4em;display:inline-block"></div>streamName = peerConns[easyrtcid].remoteStreamIdToName[id] || "default";
<a name="line3248"></a><div class="linenumber">3248</div><div style="width:4em;display:inline-block"></div>if (peerConns[easyrtcid].liveRemoteStreams[streamName] &&
<a name="line3249"></a><div class="linenumber">3249</div><div style="width:6em;display:inline-block"></div>self.onStreamClosed) {
<a name="line3250"></a><div class="linenumber">3250</div><div style="width:6em;display:inline-block"></div>delete peerConns[easyrtcid].liveRemoteStreams[streamName];
<a name="line3251"></a><div class="linenumber">3251</div><div style="width:6em;display:inline-block"></div>self.onStreamClosed(easyrtcid, stream, streamName);
<a name="line3252"></a><div class="linenumber">3252</div><div style="width:4em;display:inline-block"></div>}
<a name="line3253"></a><div class="linenumber">3253</div><div style="width:4em;display:inline-block"></div>delete peerConns[easyrtcid].remoteStreamIdToName[id];
<a name="line3254"></a><div class="linenumber">3254</div><div style="width:2em;display:inline-block"></div>}
<a name="line3255"></a><div class="linenumber">3255</div>
<a name="line3256"></a><div class="linenumber">3256</div><div style="width:2em;display:inline-block"></div>/** @private */
<a name="line3257"></a><div class="linenumber">3257</div><div style="width:2em;display:inline-block"></div>function onRemoveStreamHelper(easyrtcid, stream) {
<a name="line3258"></a><div class="linenumber">3258</div><div style="width:4em;display:inline-block"></div>if (peerConns[easyrtcid]) {
<a name="line3259"></a><div class="linenumber">3259</div><div style="width:6em;display:inline-block"></div>emitOnStreamClosed(easyrtcid, stream);
<a name="line3260"></a><div class="linenumber">3260</div><div style="width:6em;display:inline-block"></div>updateConfigurationInfo();
<a name="line3261"></a><div class="linenumber">3261</div><div style="width:6em;display:inline-block"></div>if (peerConns[easyrtcid].pc) {
<a name="line3262"></a><div class="linenumber">3262</div><div style="width:8em;display:inline-block"></div>try {
<a name="line3263"></a><div class="linenumber">3263</div><div style="width:10em;display:inline-block"></div>peerConns[easyrtcid].pc.removeStream(stream);
<a name="line3264"></a><div class="linenumber">3264</div><div style="width:8em;display:inline-block"></div>} catch( err) {}
<a name="line3265"></a><div class="linenumber">3265</div><div style="width:6em;display:inline-block"></div>}
<a name="line3266"></a><div class="linenumber">3266</div><div style="width:4em;display:inline-block"></div>}
<a name="line3267"></a><div class="linenumber">3267</div><div style="width:2em;display:inline-block"></div>}
<a name="line3268"></a><div class="linenumber">3268</div>
<a name="line3269"></a><div class="linenumber">3269</div><div style="width:2em;display:inline-block"></div>/** @private */
<a name="line3270"></a><div class="linenumber">3270</div><div style="width:2em;display:inline-block"></div>function buildDeltaRecord(added, deleted) {
<a name="line3271"></a><div class="linenumber">3271</div><div style="width:4em;display:inline-block"></div>function objectNotEmpty(obj) {
<a name="line3272"></a><div class="linenumber">3272</div><div style="width:6em;display:inline-block"></div>var i;
<a name="line3273"></a><div class="linenumber">3273</div><div style="width:6em;display:inline-block"></div>for (i in obj) {
<a name="line3274"></a><div class="linenumber">3274</div><div style="width:8em;display:inline-block"></div>if (obj.hasOwnProperty(i)) {
<a name="line3275"></a><div class="linenumber">3275</div><div style="width:10em;display:inline-block"></div>return true;
<a name="line3276"></a><div class="linenumber">3276</div><div style="width:8em;display:inline-block"></div>}
<a name="line3277"></a><div class="linenumber">3277</div><div style="width:6em;display:inline-block"></div>}
<a name="line3278"></a><div class="linenumber">3278</div><div style="width:6em;display:inline-block"></div>return false;
<a name="line3279"></a><div class="linenumber">3279</div><div style="width:4em;display:inline-block"></div>}
<a name="line3280"></a><div class="linenumber">3280</div>
<a name="line3281"></a><div class="linenumber">3281</div><div style="width:4em;display:inline-block"></div>var result = {};
<a name="line3282"></a><div class="linenumber">3282</div><div style="width:4em;display:inline-block"></div>if (objectNotEmpty(added)) {
<a name="line3283"></a><div class="linenumber">3283</div><div style="width:6em;display:inline-block"></div>result.added = added;
<a name="line3284"></a><div class="linenumber">3284</div><div style="width:4em;display:inline-block"></div>}
<a name="line3285"></a><div class="linenumber">3285</div>
<a name="line3286"></a><div class="linenumber">3286</div><div style="width:4em;display:inline-block"></div>if (objectNotEmpty(deleted)) {
<a name="line3287"></a><div class="linenumber">3287</div><div style="width:6em;display:inline-block"></div>result.deleted = deleted;
<a name="line3288"></a><div class="linenumber">3288</div><div style="width:4em;display:inline-block"></div>}
<a name="line3289"></a><div class="linenumber">3289</div>
<a name="line3290"></a><div class="linenumber">3290</div><div style="width:4em;display:inline-block"></div>if (objectNotEmpty(result)) {
<a name="line3291"></a><div class="linenumber">3291</div><div style="width:6em;display:inline-block"></div>return result;
<a name="line3292"></a><div class="linenumber">3292</div><div style="width:4em;display:inline-block"></div>}
<a name="line3293"></a><div class="linenumber">3293</div><div style="width:4em;display:inline-block"></div>else {
<a name="line3294"></a><div class="linenumber">3294</div><div style="width:6em;display:inline-block"></div>return null;
<a name="line3295"></a><div class="linenumber">3295</div><div style="width:4em;display:inline-block"></div>}
<a name="line3296"></a><div class="linenumber">3296</div><div style="width:2em;display:inline-block"></div>}
<a name="line3297"></a><div class="linenumber">3297</div>
<a name="line3298"></a><div class="linenumber">3298</div><div style="width:2em;display:inline-block"></div>/** @private */
<a name="line3299"></a><div class="linenumber">3299</div><div style="width:2em;display:inline-block"></div>function findDeltas(oldVersion, newVersion) {
<a name="line3300"></a><div class="linenumber">3300</div><div style="width:4em;display:inline-block"></div>var i;
<a name="line3301"></a><div class="linenumber">3301</div><div style="width:4em;display:inline-block"></div>var added = {}, deleted = {};
<a name="line3302"></a><div class="linenumber">3302</div><div style="width:4em;display:inline-block"></div>var subPart;
<a name="line3303"></a><div class="linenumber">3303</div><div style="width:4em;display:inline-block"></div>for (i in newVersion) {
<a name="line3304"></a><div class="linenumber">3304</div><div style="width:6em;display:inline-block"></div>if (newVersion.hasOwnProperty(i)) {
<a name="line3305"></a><div class="linenumber">3305</div><div style="width:8em;display:inline-block"></div>if (oldVersion === null || typeof oldVersion[i] === 'undefined') {
<a name="line3306"></a><div class="linenumber">3306</div><div style="width:10em;display:inline-block"></div>added[i] = newVersion[i];
<a name="line3307"></a><div class="linenumber">3307</div><div style="width:8em;display:inline-block"></div>}
<a name="line3308"></a><div class="linenumber">3308</div><div style="width:8em;display:inline-block"></div>else if (typeof newVersion[i] === 'object') {
<a name="line3309"></a><div class="linenumber">3309</div><div style="width:10em;display:inline-block"></div>subPart = findDeltas(oldVersion[i], newVersion[i]);
<a name="line3310"></a><div class="linenumber">3310</div><div style="width:10em;display:inline-block"></div>if (subPart !== null) {
<a name="line3311"></a><div class="linenumber">3311</div><div style="width:12em;display:inline-block"></div>added[i] = newVersion[i];
<a name="line3312"></a><div class="linenumber">3312</div><div style="width:10em;display:inline-block"></div>}
<a name="line3313"></a><div class="linenumber">3313</div><div style="width:8em;display:inline-block"></div>}
<a name="line3314"></a><div class="linenumber">3314</div><div style="width:8em;display:inline-block"></div>else if (newVersion[i] !== oldVersion[i]) {
<a name="line3315"></a><div class="linenumber">3315</div><div style="width:10em;display:inline-block"></div>added[i] = newVersion[i];
<a name="line3316"></a><div class="linenumber">3316</div><div style="width:8em;display:inline-block"></div>}
<a name="line3317"></a><div class="linenumber">3317</div><div style="width:6em;display:inline-block"></div>}
<a name="line3318"></a><div class="linenumber">3318</div><div style="width:4em;display:inline-block"></div>}
<a name="line3319"></a><div class="linenumber">3319</div><div style="width:4em;display:inline-block"></div>for (i in oldVersion) {
<a name="line3320"></a><div class="linenumber">3320</div><div style="width:6em;display:inline-block"></div>if (newVersion.hasOwnProperty(i)) {
<a name="line3321"></a><div class="linenumber">3321</div><div style="width:8em;display:inline-block"></div>if (typeof newVersion[i] === 'undefined') {
<a name="line3322"></a><div class="linenumber">3322</div><div style="width:10em;display:inline-block"></div>deleted[i] = oldVersion[i];
<a name="line3323"></a><div class="linenumber">3323</div><div style="width:8em;display:inline-block"></div>}
<a name="line3324"></a><div class="linenumber">3324</div><div style="width:6em;display:inline-block"></div>}
<a name="line3325"></a><div class="linenumber">3325</div><div style="width:4em;display:inline-block"></div>}
<a name="line3326"></a><div class="linenumber">3326</div>
<a name="line3327"></a><div class="linenumber">3327</div><div style="width:4em;display:inline-block"></div>return buildDeltaRecord(added, deleted);
<a name="line3328"></a><div class="linenumber">3328</div><div style="width:2em;display:inline-block"></div>}
<a name="line3329"></a><div class="linenumber">3329</div>
<a name="line3330"></a><div class="linenumber">3330</div><div style="width:2em;display:inline-block"></div>/** @private */
<a name="line3331"></a><div class="linenumber">3331</div><div style="width:2em;display:inline-block"></div>//
<a name="line3332"></a><div class="linenumber">3332</div><div style="width:2em;display:inline-block"></div>// this function collects configuration info that will be sent to the server.
<a name="line3333"></a><div class="linenumber">3333</div><div style="width:2em;display:inline-block"></div>// It returns that information, leaving it the responsibility of the caller to
<a name="line3334"></a><div class="linenumber">3334</div><div style="width:2em;display:inline-block"></div>// do the actual sending.
<a name="line3335"></a><div class="linenumber">3335</div><div style="width:2em;display:inline-block"></div>//
<a name="line3336"></a><div class="linenumber">3336</div><div style="width:2em;display:inline-block"></div>function collectConfigurationInfo(/* forAuthentication */) {
<a name="line3337"></a><div class="linenumber">3337</div><div style="width:4em;display:inline-block"></div>var p2pList = {};
<a name="line3338"></a><div class="linenumber">3338</div><div style="width:4em;display:inline-block"></div>var i;
<a name="line3339"></a><div class="linenumber">3339</div><div style="width:4em;display:inline-block"></div>for (i in peerConns) {
<a name="line3340"></a><div class="linenumber">3340</div><div style="width:6em;display:inline-block"></div>if (!peerConns.hasOwnProperty(i)) {
<a name="line3341"></a><div class="linenumber">3341</div><div style="width:8em;display:inline-block"></div>continue;
<a name="line3342"></a><div class="linenumber">3342</div><div style="width:6em;display:inline-block"></div>}
<a name="line3343"></a><div class="linenumber">3343</div><div style="width:6em;display:inline-block"></div>p2pList[i] = {
<a name="line3344"></a><div class="linenumber">3344</div><div style="width:8em;display:inline-block"></div>connectTime: peerConns[i].connectTime,
<a name="line3345"></a><div class="linenumber">3345</div><div style="width:8em;display:inline-block"></div>isInitiator: !!peerConns[i].isInitiator
<a name="line3346"></a><div class="linenumber">3346</div><div style="width:6em;display:inline-block"></div>};
<a name="line3347"></a><div class="linenumber">3347</div><div style="width:4em;display:inline-block"></div>}
<a name="line3348"></a><div class="linenumber">3348</div>
<a name="line3349"></a><div class="linenumber">3349</div><div style="width:4em;display:inline-block"></div>var newConfig = {
<a name="line3350"></a><div class="linenumber">3350</div><div style="width:6em;display:inline-block"></div>userSettings: {
<a name="line3351"></a><div class="linenumber">3351</div><div style="width:8em;display:inline-block"></div>sharingAudio: !!haveAudioVideo.audio,
<a name="line3352"></a><div class="linenumber">3352</div><div style="width:8em;display:inline-block"></div>sharingVideo: !!haveAudioVideo.video,
<a name="line3353"></a><div class="linenumber">3353</div><div style="width:8em;display:inline-block"></div>sharingData: !!dataEnabled,
<a name="line3354"></a><div class="linenumber">3354</div><div style="width:8em;display:inline-block"></div>nativeVideoWidth: self.nativeVideoWidth,
<a name="line3355"></a><div class="linenumber">3355</div><div style="width:8em;display:inline-block"></div>nativeVideoHeight: self.nativeVideoHeight,
<a name="line3356"></a><div class="linenumber">3356</div><div style="width:8em;display:inline-block"></div>windowWidth: window.innerWidth,
<a name="line3357"></a><div class="linenumber">3357</div><div style="width:8em;display:inline-block"></div>windowHeight: window.innerHeight,
<a name="line3358"></a><div class="linenumber">3358</div><div style="width:8em;display:inline-block"></div>screenWidth: window.screen.width,
<a name="line3359"></a><div class="linenumber">3359</div><div style="width:8em;display:inline-block"></div>screenHeight: window.screen.height,
<a name="line3360"></a><div class="linenumber">3360</div><div style="width:8em;display:inline-block"></div>cookieEnabled: navigator.cookieEnabled,
<a name="line3361"></a><div class="linenumber">3361</div><div style="width:8em;display:inline-block"></div>os: navigator.oscpu,
<a name="line3362"></a><div class="linenumber">3362</div><div style="width:8em;display:inline-block"></div>language: navigator.language
<a name="line3363"></a><div class="linenumber">3363</div><div style="width:6em;display:inline-block"></div>}
<a name="line3364"></a><div class="linenumber">3364</div><div style="width:4em;display:inline-block"></div>};
<a name="line3365"></a><div class="linenumber">3365</div>
<a name="line3366"></a><div class="linenumber">3366</div><div style="width:4em;display:inline-block"></div>if (!isEmptyObj(p2pList)) {
<a name="line3367"></a><div class="linenumber">3367</div><div style="width:6em;display:inline-block"></div>newConfig.p2pList = p2pList;
<a name="line3368"></a><div class="linenumber">3368</div><div style="width:4em;display:inline-block"></div>}
<a name="line3369"></a><div class="linenumber">3369</div>
<a name="line3370"></a><div class="linenumber">3370</div><div style="width:4em;display:inline-block"></div>return newConfig;
<a name="line3371"></a><div class="linenumber">3371</div><div style="width:2em;display:inline-block"></div>}
<a name="line3372"></a><div class="linenumber">3372</div>
<a name="line3373"></a><div class="linenumber">3373</div><div style="width:2em;display:inline-block"></div>/** @private */
<a name="line3374"></a><div class="linenumber">3374</div><div style="width:2em;display:inline-block"></div>function updateConfiguration() {
<a name="line3375"></a><div class="linenumber">3375</div>
<a name="line3376"></a><div class="linenumber">3376</div><div style="width:4em;display:inline-block"></div>var newConfig = collectConfigurationInfo(false);
<a name="line3377"></a><div class="linenumber">3377</div><div style="width:4em;display:inline-block"></div>//
<a name="line3378"></a><div class="linenumber">3378</div><div style="width:4em;display:inline-block"></div>// we need to give the getStats calls a chance to fish out the data.
<a name="line3379"></a><div class="linenumber">3379</div><div style="width:4em;display:inline-block"></div>// The longest I've seen it take is 5 milliseconds so 100 should be overkill.
<a name="line3380"></a><div class="linenumber">3380</div><div style="width:4em;display:inline-block"></div>//
<a name="line3381"></a><div class="linenumber">3381</div><div style="width:4em;display:inline-block"></div>var sendDeltas = function() {
<a name="line3382"></a><div class="linenumber">3382</div><div style="width:6em;display:inline-block"></div>var alteredData = findDeltas(oldConfig, newConfig);
<a name="line3383"></a><div class="linenumber">3383</div><div style="width:6em;display:inline-block"></div>//
<a name="line3384"></a><div class="linenumber">3384</div><div style="width:6em;display:inline-block"></div>// send all the configuration information that changes during the session
<a name="line3385"></a><div class="linenumber">3385</div><div style="width:6em;display:inline-block"></div>//
<a name="line3386"></a><div class="linenumber">3386</div><div style="width:6em;display:inline-block"></div>if (alteredData) {
<a name="line3387"></a><div class="linenumber">3387</div><div style="width:8em;display:inline-block"></div>logDebug("cfg=" + JSON.stringify(alteredData.added));
<a name="line3388"></a><div class="linenumber">3388</div>
<a name="line3389"></a><div class="linenumber">3389</div><div style="width:8em;display:inline-block"></div>if (self.webSocket) {
<a name="line3390"></a><div class="linenumber">3390</div><div style="width:10em;display:inline-block"></div>sendSignalling(null, "setUserCfg", {setUserCfg: alteredData.added}, null, null);
<a name="line3391"></a><div class="linenumber">3391</div><div style="width:8em;display:inline-block"></div>}
<a name="line3392"></a><div class="linenumber">3392</div><div style="width:6em;display:inline-block"></div>}
<a name="line3393"></a><div class="linenumber">3393</div><div style="width:6em;display:inline-block"></div>oldConfig = newConfig;
<a name="line3394"></a><div class="linenumber">3394</div><div style="width:4em;display:inline-block"></div>};
<a name="line3395"></a><div class="linenumber">3395</div><div style="width:4em;display:inline-block"></div>if (oldConfig === {}) {
<a name="line3396"></a><div class="linenumber">3396</div><div style="width:6em;display:inline-block"></div>sendDeltas();
<a name="line3397"></a><div class="linenumber">3397</div><div style="width:4em;display:inline-block"></div>}
<a name="line3398"></a><div class="linenumber">3398</div><div style="width:4em;display:inline-block"></div>else {
<a name="line3399"></a><div class="linenumber">3399</div><div style="width:6em;display:inline-block"></div>setTimeout(sendDeltas, 100);
<a name="line3400"></a><div class="linenumber">3400</div><div style="width:4em;display:inline-block"></div>}
<a name="line3401"></a><div class="linenumber">3401</div><div style="width:2em;display:inline-block"></div>}
<a name="line3402"></a><div class="linenumber">3402</div>
<a name="line3403"></a><div class="linenumber">3403</div><div style="width:2em;display:inline-block"></div>// Parse the uint32 PRIORITY field into its constituent parts from RFC 5245,
<a name="line3404"></a><div class="linenumber">3404</div><div style="width:2em;display:inline-block"></div>// type preference, local preference, and (256 - component ID).
<a name="line3405"></a><div class="linenumber">3405</div><div style="width:2em;display:inline-block"></div>// ex: 126 | 32252 | 255 (126 is host preference, 255 is component ID 1)
<a name="line3406"></a><div class="linenumber">3406</div><div style="width:2em;display:inline-block"></div>function formatPriority(priority) {
<a name="line3407"></a><div class="linenumber">3407</div><div style="width:4em;display:inline-block"></div>var s = '';
<a name="line3408"></a><div class="linenumber">3408</div><div style="width:4em;display:inline-block"></div>s += (priority >> 24);
<a name="line3409"></a><div class="linenumber">3409</div><div style="width:4em;display:inline-block"></div>s += ' | ';
<a name="line3410"></a><div class="linenumber">3410</div><div style="width:4em;display:inline-block"></div>s += (priority >> 8) & 0xFFFF;
<a name="line3411"></a><div class="linenumber">3411</div><div style="width:4em;display:inline-block"></div>s += ' | ';
<a name="line3412"></a><div class="linenumber">3412</div><div style="width:4em;display:inline-block"></div>s += priority & 0xFF;
<a name="line3413"></a><div class="linenumber">3413</div><div style="width:4em;display:inline-block"></div>return s;
<a name="line3414"></a><div class="linenumber">3414</div><div style="width:2em;display:inline-block"></div>}
<a name="line3415"></a><div class="linenumber">3415</div>
<a name="line3416"></a><div class="linenumber">3416</div><div style="width:2em;display:inline-block"></div>// Parse a candidate:foo string into an object, for easier use by other methods.
<a name="line3417"></a><div class="linenumber">3417</div><div style="width:2em;display:inline-block"></div>/** @private */
<a name="line3418"></a><div class="linenumber">3418</div><div style="width:2em;display:inline-block"></div>function parseCandidate(text) {
<a name="line3419"></a><div class="linenumber">3419</div><div style="width:4em;display:inline-block"></div>var candidateStr = 'candidate:';
<a name="line3420"></a><div class="linenumber">3420</div><div style="width:4em;display:inline-block"></div>var pos = text.indexOf(candidateStr) + candidateStr.length;
<a name="line3421"></a><div class="linenumber">3421</div><div style="width:4em;display:inline-block"></div>var fields = text.substr(pos).split(' ');
<a name="line3422"></a><div class="linenumber">3422</div><div style="width:4em;display:inline-block"></div>return {
<a name="line3423"></a><div class="linenumber">3423</div><div style="width:6em;display:inline-block"></div>'component': fields[1],
<a name="line3424"></a><div class="linenumber">3424</div><div style="width:6em;display:inline-block"></div>'type': fields[7],
<a name="line3425"></a><div class="linenumber">3425</div><div style="width:6em;display:inline-block"></div>'foundation': fields[0],
<a name="line3426"></a><div class="linenumber">3426</div><div style="width:6em;display:inline-block"></div>'protocol': fields[2],
<a name="line3427"></a><div class="linenumber">3427</div><div style="width:6em;display:inline-block"></div>'address': fields[4],
<a name="line3428"></a><div class="linenumber">3428</div><div style="width:6em;display:inline-block"></div>'port': fields[5],
<a name="line3429"></a><div class="linenumber">3429</div><div style="width:6em;display:inline-block"></div>'priority': formatPriority(fields[3])
<a name="line3430"></a><div class="linenumber">3430</div><div style="width:4em;display:inline-block"></div>};
<a name="line3431"></a><div class="linenumber">3431</div><div style="width:2em;display:inline-block"></div>}
<a name="line3432"></a><div class="linenumber">3432</div>
<a name="line3433"></a><div class="linenumber">3433</div><div style="width:2em;display:inline-block"></div>/** @private */
<a name="line3434"></a><div class="linenumber">3434</div><div style="width:2em;display:inline-block"></div>function processCandicate(candicate) {
<a name="line3435"></a><div class="linenumber">3435</div><div style="width:4em;display:inline-block"></div>self._candicates = self._candicates || [];
<a name="line3436"></a><div class="linenumber">3436</div><div style="width:4em;display:inline-block"></div>self._candicates.push(parseCandidate(candicate));
<a name="line3437"></a><div class="linenumber">3437</div><div style="width:2em;display:inline-block"></div>}
<a name="line3438"></a><div class="linenumber">3438</div>
<a name="line3439"></a><div class="linenumber">3439</div><div style="width:2em;display:inline-block"></div>function processAddedStream(otherUser, theStream) {
<a name="line3440"></a><div class="linenumber">3440</div><div style="width:4em;display:inline-block"></div>if (!peerConns[otherUser] || peerConns[otherUser].cancelled) {
<a name="line3441"></a><div class="linenumber">3441</div><div style="width:6em;display:inline-block"></div>return;
<a name="line3442"></a><div class="linenumber">3442</div><div style="width:4em;display:inline-block"></div>}
<a name="line3443"></a><div class="linenumber">3443</div>
<a name="line3444"></a><div class="linenumber">3444</div><div style="width:4em;display:inline-block"></div>var peerConn = peerConns[otherUser];
<a name="line3445"></a><div class="linenumber">3445</div>
<a name="line3446"></a><div class="linenumber">3446</div><div style="width:4em;display:inline-block"></div>if (!peerConn.startedAV) {
<a name="line3447"></a><div class="linenumber">3447</div><div style="width:6em;display:inline-block"></div>peerConn.startedAV = true;
<a name="line3448"></a><div class="linenumber">3448</div><div style="width:6em;display:inline-block"></div>peerConn.sharingAudio = haveAudioVideo.audio;
<a name="line3449"></a><div class="linenumber">3449</div><div style="width:6em;display:inline-block"></div>peerConn.sharingVideo = haveAudioVideo.video;
<a name="line3450"></a><div class="linenumber">3450</div><div style="width:6em;display:inline-block"></div>peerConn.connectTime = new Date().getTime();
<a name="line3451"></a><div class="linenumber">3451</div><div style="width:6em;display:inline-block"></div>if (peerConn.callSuccessCB) {
<a name="line3452"></a><div class="linenumber">3452</div><div style="width:8em;display:inline-block"></div>if (peerConn.sharingAudio || peerConn.sharingVideo) {
<a name="line3453"></a><div class="linenumber">3453</div><div style="width:10em;display:inline-block"></div>peerConn.callSuccessCB(otherUser, "audiovideo");
<a name="line3454"></a><div class="linenumber">3454</div><div style="width:8em;display:inline-block"></div>}
<a name="line3455"></a><div class="linenumber">3455</div><div style="width:6em;display:inline-block"></div>}
<a name="line3456"></a><div class="linenumber">3456</div><div style="width:6em;display:inline-block"></div>if (self.audioEnabled || self.videoEnabled) {
<a name="line3457"></a><div class="linenumber">3457</div><div style="width:8em;display:inline-block"></div>updateConfiguration();
<a name="line3458"></a><div class="linenumber">3458</div><div style="width:6em;display:inline-block"></div>}
<a name="line3459"></a><div class="linenumber">3459</div><div style="width:4em;display:inline-block"></div>}
<a name="line3460"></a><div class="linenumber">3460</div>
<a name="line3461"></a><div class="linenumber">3461</div><div style="width:4em;display:inline-block"></div>var remoteName = getNameOfRemoteStream(otherUser, theStream.id || "default");
<a name="line3462"></a><div class="linenumber">3462</div><div style="width:4em;display:inline-block"></div>if (!remoteName) {
<a name="line3463"></a><div class="linenumber">3463</div><div style="width:6em;display:inline-block"></div>remoteName = "default";
<a name="line3464"></a><div class="linenumber">3464</div><div style="width:4em;display:inline-block"></div>}
<a name="line3465"></a><div class="linenumber">3465</div><div style="width:4em;display:inline-block"></div>peerConn.remoteStreamIdToName[theStream.id || "default"] = remoteName;
<a name="line3466"></a><div class="linenumber">3466</div><div style="width:4em;display:inline-block"></div>peerConn.liveRemoteStreams[remoteName] = true;
<a name="line3467"></a><div class="linenumber">3467</div><div style="width:4em;display:inline-block"></div>theStream.streamName = remoteName;
<a name="line3468"></a><div class="linenumber">3468</div><div style="width:4em;display:inline-block"></div>if (self.streamAcceptor) {
<a name="line3469"></a><div class="linenumber">3469</div><div style="width:6em;display:inline-block"></div>self.streamAcceptor(otherUser, theStream, remoteName);
<a name="line3470"></a><div class="linenumber">3470</div><div style="width:6em;display:inline-block"></div>//
<a name="line3471"></a><div class="linenumber">3471</div><div style="width:6em;display:inline-block"></div>// Inform the other user that the stream they provided has been received.
<a name="line3472"></a><div class="linenumber">3472</div><div style="width:6em;display:inline-block"></div>// This should be moved into signalling at some point
<a name="line3473"></a><div class="linenumber">3473</div><div style="width:6em;display:inline-block"></div>//
<a name="line3474"></a><div class="linenumber">3474</div><div style="width:6em;display:inline-block"></div>self.sendDataWS(otherUser, "easyrtc_streamReceived", {streamName:remoteName},function(){});
<a name="line3475"></a><div class="linenumber">3475</div><div style="width:4em;display:inline-block"></div>}
<a name="line3476"></a><div class="linenumber">3476</div><div style="width:2em;display:inline-block"></div>}
<a name="line3477"></a><div class="linenumber">3477</div>
<a name="line3478"></a><div class="linenumber">3478</div><div style="width:2em;display:inline-block"></div>function processAddedTrack(otherUser, peerStreams) {
<a name="line3479"></a><div class="linenumber">3479</div>
<a name="line3480"></a><div class="linenumber">3480</div><div style="width:4em;display:inline-block"></div>if (!peerConns[otherUser] || peerConns[otherUser].cancelled) {
<a name="line3481"></a><div class="linenumber">3481</div><div style="width:6em;display:inline-block"></div>return;
<a name="line3482"></a><div class="linenumber">3482</div><div style="width:4em;display:inline-block"></div>}
<a name="line3483"></a><div class="linenumber">3483</div>
<a name="line3484"></a><div class="linenumber">3484</div><div style="width:4em;display:inline-block"></div>var peerConn = peerConns[otherUser];
<a name="line3485"></a><div class="linenumber">3485</div><div style="width:4em;display:inline-block"></div>peerConn.trackTimers = peerConn.trackTimers || {};
<a name="line3486"></a><div class="linenumber">3486</div>
<a name="line3487"></a><div class="linenumber">3487</div><div style="width:4em;display:inline-block"></div>// easyrtc thinks in terms of streams, not tracks.
<a name="line3488"></a><div class="linenumber">3488</div><div style="width:4em;display:inline-block"></div>// so we'll add a timeout when the first track event
<a name="line3489"></a><div class="linenumber">3489</div><div style="width:4em;display:inline-block"></div>// fires. Firefox produces two events (one of type "video",
<a name="line3490"></a><div class="linenumber">3490</div><div style="width:4em;display:inline-block"></div>// and one of type "audio".
<a name="line3491"></a><div class="linenumber">3491</div>
<a name="line3492"></a><div class="linenumber">3492</div><div style="width:4em;display:inline-block"></div>for (var i = 0, l = peerStreams.length; i < l; i++) {
<a name="line3493"></a><div class="linenumber">3493</div><div style="width:6em;display:inline-block"></div>var peerStream = peerStreams[i],
<a name="line3494"></a><div class="linenumber">3494</div><div style="width:8em;display:inline-block"></div>streamId = peerStream.id || "default";
<a name="line3495"></a><div class="linenumber">3495</div><div style="width:6em;display:inline-block"></div>clearTimeout(peerConn.trackTimers[streamId]);
<a name="line3496"></a><div class="linenumber">3496</div><div style="width:6em;display:inline-block"></div>peerConn.trackTimers[streamId] = setTimeout(function(peerStream) {
<a name="line3497"></a><div class="linenumber">3497</div><div style="width:7em;display:inline-block"></div>processAddedStream(peerConn, otherUser, peerStream);
<a name="line3498"></a><div class="linenumber">3498</div><div style="width:6em;display:inline-block"></div>}.bind(peerStream), 100); // Bind peerStream
<a name="line3499"></a><div class="linenumber">3499</div><div style="width:4em;display:inline-block"></div>}
<a name="line3500"></a><div class="linenumber">3500</div><div style="width:2em;display:inline-block"></div>}
<a name="line3501"></a><div class="linenumber">3501</div>
<a name="line3502"></a><div class="linenumber">3502</div><div style="width:2em;display:inline-block"></div>/** @private */
<a name="line3503"></a><div class="linenumber">3503</div><div style="width:2em;display:inline-block"></div>// TODO split buildPeerConnection it more thant 500 lines
<a name="line3504"></a><div class="linenumber">3504</div><div style="width:2em;display:inline-block"></div>function buildPeerConnection(otherUser, isInitiator, failureCB, streamNames) {
<a name="line3505"></a><div class="linenumber">3505</div><div style="width:4em;display:inline-block"></div>var pc;
<a name="line3506"></a><div class="linenumber">3506</div><div style="width:4em;display:inline-block"></div>var message;
<a name="line3507"></a><div class="linenumber">3507</div><div style="width:4em;display:inline-block"></div>var newPeerConn;
<a name="line3508"></a><div class="linenumber">3508</div><div style="width:4em;display:inline-block"></div>var iceConfig = pc_config_to_use ? pc_config_to_use : pc_config;
<a name="line3509"></a><div class="linenumber">3509</div>
<a name="line3510"></a><div class="linenumber">3510</div><div style="width:4em;display:inline-block"></div>logDebug("building peer connection to " + otherUser);
<a name="line3511"></a><div class="linenumber">3511</div>
<a name="line3512"></a><div class="linenumber">3512</div><div style="width:4em;display:inline-block"></div>//
<a name="line3513"></a><div class="linenumber">3513</div><div style="width:4em;display:inline-block"></div>// we don't support data channels on chrome versions < 31
<a name="line3514"></a><div class="linenumber">3514</div><div style="width:4em;display:inline-block"></div>//
<a name="line3515"></a><div class="linenumber">3515</div>
<a name="line3516"></a><div class="linenumber">3516</div><div style="width:4em;display:inline-block"></div>try {
<a name="line3517"></a><div class="linenumber">3517</div>
<a name="line3518"></a><div class="linenumber">3518</div><div style="width:6em;display:inline-block"></div>pc = self.createRTCPeerConnection(iceConfig, buildPeerConstraints());
<a name="line3519"></a><div class="linenumber">3519</div>
<a name="line3520"></a><div class="linenumber">3520</div><div style="width:6em;display:inline-block"></div>if (!pc) {
<a name="line3521"></a><div class="linenumber">3521</div><div style="width:8em;display:inline-block"></div>message = "Unable to create PeerConnection object, check your ice configuration(" + JSON.stringify(iceConfig) + ")";
<a name="line3522"></a><div class="linenumber">3522</div><div style="width:8em;display:inline-block"></div>logDebug(message);
<a name="line3523"></a><div class="linenumber">3523</div><div style="width:8em;display:inline-block"></div>throw Error(message);
<a name="line3524"></a><div class="linenumber">3524</div><div style="width:6em;display:inline-block"></div>}
<a name="line3525"></a><div class="linenumber">3525</div>
<a name="line3526"></a><div class="linenumber">3526</div><div style="width:6em;display:inline-block"></div>//
<a name="line3527"></a><div class="linenumber">3527</div><div style="width:6em;display:inline-block"></div>// turn off data channel support if the browser doesn't support it.
<a name="line3528"></a><div class="linenumber">3528</div><div style="width:6em;display:inline-block"></div>//
<a name="line3529"></a><div class="linenumber">3529</div>
<a name="line3530"></a><div class="linenumber">3530</div><div style="width:6em;display:inline-block"></div>if (dataEnabled && typeof pc.createDataChannel === 'undefined') {
<a name="line3531"></a><div class="linenumber">3531</div><div style="width:8em;display:inline-block"></div>dataEnabled = false;
<a name="line3532"></a><div class="linenumber">3532</div><div style="width:6em;display:inline-block"></div>}
<a name="line3533"></a><div class="linenumber">3533</div>
<a name="line3534"></a><div class="linenumber">3534</div><div style="width:6em;display:inline-block"></div>pc.onnegotiationneeded = function(event) {
<a name="line3535"></a><div class="linenumber">3535</div><div style="width:8em;display:inline-block"></div>if (
<a name="line3536"></a><div class="linenumber">3536</div><div style="width:10em;display:inline-block"></div>peerConns[otherUser] &&
<a name="line3537"></a><div class="linenumber">3537</div><div style="width:12em;display:inline-block"></div>(peerConns[otherUser].enableNegotiateListener)
<a name="line3538"></a><div class="linenumber">3538</div><div style="width:8em;display:inline-block"></div>) {
<a name="line3539"></a><div class="linenumber">3539</div><div style="width:10em;display:inline-block"></div>pc.createOffer(function(sdp) {
<a name="line3540"></a><div class="linenumber">3540</div><div style="width:12em;display:inline-block"></div>if (sdpLocalFilter) {
<a name="line3541"></a><div class="linenumber">3541</div><div style="width:14em;display:inline-block"></div>sdp.sdp = sdpLocalFilter(sdp.sdp);
<a name="line3542"></a><div class="linenumber">3542</div><div style="width:12em;display:inline-block"></div>}
<a name="line3543"></a><div class="linenumber">3543</div><div style="width:12em;display:inline-block"></div>pc.setLocalDescription(sdp, function() {
<a name="line3544"></a><div class="linenumber">3544</div><div style="width:14em;display:inline-block"></div>self.sendPeerMessage(otherUser, "__addedMediaStream", {
<a name="line3545"></a><div class="linenumber">3545</div><div style="width:16em;display:inline-block"></div>sdp: sdp
<a name="line3546"></a><div class="linenumber">3546</div><div style="width:14em;display:inline-block"></div>});
<a name="line3547"></a><div class="linenumber">3547</div>
<a name="line3548"></a><div class="linenumber">3548</div><div style="width:12em;display:inline-block"></div>}, function() {
<a name="line3549"></a><div class="linenumber">3549</div><div style="width:12em;display:inline-block"></div>});
<a name="line3550"></a><div class="linenumber">3550</div><div style="width:10em;display:inline-block"></div>}, function(error) {
<a name="line3551"></a><div class="linenumber">3551</div><div style="width:12em;display:inline-block"></div>logDebug("unexpected error in creating offer");
<a name="line3552"></a><div class="linenumber">3552</div><div style="width:10em;display:inline-block"></div>});
<a name="line3553"></a><div class="linenumber">3553</div><div style="width:8em;display:inline-block"></div>}
<a name="line3554"></a><div class="linenumber">3554</div><div style="width:6em;display:inline-block"></div>};
<a name="line3555"></a><div class="linenumber">3555</div>
<a name="line3556"></a><div class="linenumber">3556</div><div style="width:6em;display:inline-block"></div>pc.onsignalingstatechange = function () {
<a name="line3557"></a><div class="linenumber">3557</div>
<a name="line3558"></a><div class="linenumber">3558</div><div style="width:8em;display:inline-block"></div>var eventTarget = event.currentTarget || event.target || pc,
<a name="line3559"></a><div class="linenumber">3559</div><div style="width:10em;display:inline-block"></div>signalingState = eventTarget.signalingState || 'unknown';
<a name="line3560"></a><div class="linenumber">3560</div>
<a name="line3561"></a><div class="linenumber">3561</div><div style="width:8em;display:inline-block"></div>if (signalingStateChangeListener) {
<a name="line3562"></a><div class="linenumber">3562</div><div style="width:9em;display:inline-block"></div>signalingStateChangeListener(otherUser, eventTarget, signalingState);
<a name="line3563"></a><div class="linenumber">3563</div><div style="width:8em;display:inline-block"></div>}
<a name="line3564"></a><div class="linenumber">3564</div><div style="width:6em;display:inline-block"></div>};
<a name="line3565"></a><div class="linenumber">3565</div>
<a name="line3566"></a><div class="linenumber">3566</div><div style="width:6em;display:inline-block"></div>pc.oniceconnectionstatechange = function(event) {
<a name="line3567"></a><div class="linenumber">3567</div>
<a name="line3568"></a><div class="linenumber">3568</div><div style="width:8em;display:inline-block"></div>var eventTarget = event.currentTarget || event.target || pc,
<a name="line3569"></a><div class="linenumber">3569</div><div style="width:10em;display:inline-block"></div>connState = eventTarget.iceConnectionState || 'unknown';
<a name="line3570"></a><div class="linenumber">3570</div>
<a name="line3571"></a><div class="linenumber">3571</div><div style="width:8em;display:inline-block"></div>if (iceConnectionStateChangeListener) {
<a name="line3572"></a><div class="linenumber">3572</div><div style="width:9em;display:inline-block"></div>iceConnectionStateChangeListener(otherUser, eventTarget, connState);
<a name="line3573"></a><div class="linenumber">3573</div><div style="width:8em;display:inline-block"></div>}
<a name="line3574"></a><div class="linenumber">3574</div>
<a name="line3575"></a><div class="linenumber">3575</div><div style="width:8em;display:inline-block"></div>switch (connState) {
<a name="line3576"></a><div class="linenumber">3576</div><div style="width:10em;display:inline-block"></div>case "connected":
<a name="line3577"></a><div class="linenumber">3577</div><div style="width:12em;display:inline-block"></div>if (self.onPeerOpen ) {
<a name="line3578"></a><div class="linenumber">3578</div><div style="width:14em;display:inline-block"></div>self.onPeerOpen(otherUser);
<a name="line3579"></a><div class="linenumber">3579</div><div style="width:12em;display:inline-block"></div>}
<a name="line3580"></a><div class="linenumber">3580</div><div style="width:12em;display:inline-block"></div>if (peerConns[otherUser] && peerConns[otherUser].callSuccessCB) {
<a name="line3581"></a><div class="linenumber">3581</div><div style="width:14em;display:inline-block"></div>peerConns[otherUser].callSuccessCB(otherUser, "connection");
<a name="line3582"></a><div class="linenumber">3582</div><div style="width:12em;display:inline-block"></div>}
<a name="line3583"></a><div class="linenumber">3583</div><div style="width:12em;display:inline-block"></div>break;
<a name="line3584"></a><div class="linenumber">3584</div><div style="width:10em;display:inline-block"></div>case "failed":
<a name="line3585"></a><div class="linenumber">3585</div><div style="width:12em;display:inline-block"></div>if (failureCB) {
<a name="line3586"></a><div class="linenumber">3586</div><div style="width:14em;display:inline-block"></div>failureCB(self.errCodes.NOVIABLEICE, "No usable STUN/TURN path");
<a name="line3587"></a><div class="linenumber">3587</div><div style="width:12em;display:inline-block"></div>}
<a name="line3588"></a><div class="linenumber">3588</div><div style="width:12em;display:inline-block"></div>delete peerConns[otherUser];
<a name="line3589"></a><div class="linenumber">3589</div><div style="width:12em;display:inline-block"></div>break;
<a name="line3590"></a><div class="linenumber">3590</div><div style="width:10em;display:inline-block"></div>case "disconnected":
<a name="line3591"></a><div class="linenumber">3591</div><div style="width:12em;display:inline-block"></div>if (self.onPeerFailing) {
<a name="line3592"></a><div class="linenumber">3592</div><div style="width:14em;display:inline-block"></div>self.onPeerFailing(otherUser);
<a name="line3593"></a><div class="linenumber">3593</div><div style="width:12em;display:inline-block"></div>}
<a name="line3594"></a><div class="linenumber">3594</div><div style="width:12em;display:inline-block"></div>if (peerConns[otherUser]) {
<a name="line3595"></a><div class="linenumber">3595</div><div style="width:14em;display:inline-block"></div>peerConns[otherUser].failing = Date.now();
<a name="line3596"></a><div class="linenumber">3596</div><div style="width:12em;display:inline-block"></div>}
<a name="line3597"></a><div class="linenumber">3597</div><div style="width:12em;display:inline-block"></div>break;
<a name="line3598"></a><div class="linenumber">3598</div>
<a name="line3599"></a><div class="linenumber">3599</div><div style="width:10em;display:inline-block"></div>case "closed":
<a name="line3600"></a><div class="linenumber">3600</div><div style="width:12em;display:inline-block"></div>if (self.onPeerClosed) {
<a name="line3601"></a><div class="linenumber">3601</div><div style="width:14em;display:inline-block"></div>self.onPeerClosed(otherUser);
<a name="line3602"></a><div class="linenumber">3602</div><div style="width:12em;display:inline-block"></div>}
<a name="line3603"></a><div class="linenumber">3603</div><div style="width:12em;display:inline-block"></div>break;
<a name="line3604"></a><div class="linenumber">3604</div><div style="width:10em;display:inline-block"></div>case "completed":
<a name="line3605"></a><div class="linenumber">3605</div><div style="width:12em;display:inline-block"></div>if (peerConns[otherUser]) {
<a name="line3606"></a><div class="linenumber">3606</div><div style="width:14em;display:inline-block"></div>if (peerConns[otherUser].failing && self.onPeerRecovered) {
<a name="line3607"></a><div class="linenumber">3607</div><div style="width:16em;display:inline-block"></div>self.onPeerRecovered(otherUser, peerConns[otherUser].failing, Date.now());
<a name="line3608"></a><div class="linenumber">3608</div><div style="width:14em;display:inline-block"></div>}
<a name="line3609"></a><div class="linenumber">3609</div><div style="width:14em;display:inline-block"></div>delete peerConns[otherUser].failing;
<a name="line3610"></a><div class="linenumber">3610</div><div style="width:12em;display:inline-block"></div>}
<a name="line3611"></a><div class="linenumber">3611</div><div style="width:12em;display:inline-block"></div>break;
<a name="line3612"></a><div class="linenumber">3612</div><div style="width:8em;display:inline-block"></div>}
<a name="line3613"></a><div class="linenumber">3613</div><div style="width:6em;display:inline-block"></div>};
<a name="line3614"></a><div class="linenumber">3614</div>
<a name="line3615"></a><div class="linenumber">3615</div><div style="width:6em;display:inline-block"></div>pc.onconnection = function() {
<a name="line3616"></a><div class="linenumber">3616</div><div style="width:8em;display:inline-block"></div>logDebug("onconnection called prematurely");
<a name="line3617"></a><div class="linenumber">3617</div><div style="width:6em;display:inline-block"></div>};
<a name="line3618"></a><div class="linenumber">3618</div>
<a name="line3619"></a><div class="linenumber">3619</div><div style="width:6em;display:inline-block"></div>newPeerConn = {
<a name="line3620"></a><div class="linenumber">3620</div><div style="width:8em;display:inline-block"></div>pc: pc,
<a name="line3621"></a><div class="linenumber">3621</div><div style="width:8em;display:inline-block"></div>candidatesToSend: [],
<a name="line3622"></a><div class="linenumber">3622</div><div style="width:8em;display:inline-block"></div>startedAV: false,
<a name="line3623"></a><div class="linenumber">3623</div><div style="width:8em;display:inline-block"></div>connectionAccepted: false,
<a name="line3624"></a><div class="linenumber">3624</div><div style="width:8em;display:inline-block"></div>isInitiator: isInitiator,
<a name="line3625"></a><div class="linenumber">3625</div><div style="width:8em;display:inline-block"></div>remoteStreamIdToName: {},
<a name="line3626"></a><div class="linenumber">3626</div><div style="width:8em;display:inline-block"></div>streamsAddedAcks: {},
<a name="line3627"></a><div class="linenumber">3627</div><div style="width:8em;display:inline-block"></div>liveRemoteStreams: {}
<a name="line3628"></a><div class="linenumber">3628</div><div style="width:6em;display:inline-block"></div>};
<a name="line3629"></a><div class="linenumber">3629</div>
<a name="line3630"></a><div class="linenumber">3630</div><div style="width:6em;display:inline-block"></div>pc.onicecandidate = function(event) {
<a name="line3631"></a><div class="linenumber">3631</div><div style="width:8em;display:inline-block"></div>if (peerConns[otherUser] && peerConns[otherUser].cancelled) {
<a name="line3632"></a><div class="linenumber">3632</div><div style="width:10em;display:inline-block"></div>return;
<a name="line3633"></a><div class="linenumber">3633</div><div style="width:8em;display:inline-block"></div>}
<a name="line3634"></a><div class="linenumber">3634</div><div style="width:8em;display:inline-block"></div>var candidateData;
<a name="line3635"></a><div class="linenumber">3635</div><div style="width:8em;display:inline-block"></div>if (event.candidate && peerConns[otherUser]) {
<a name="line3636"></a><div class="linenumber">3636</div><div style="width:10em;display:inline-block"></div>candidateData = {
<a name="line3637"></a><div class="linenumber">3637</div><div style="width:12em;display:inline-block"></div>type: 'candidate',
<a name="line3638"></a><div class="linenumber">3638</div><div style="width:12em;display:inline-block"></div>label: event.candidate.sdpMLineIndex,
<a name="line3639"></a><div class="linenumber">3639</div><div style="width:12em;display:inline-block"></div>id: event.candidate.sdpMid,
<a name="line3640"></a><div class="linenumber">3640</div><div style="width:12em;display:inline-block"></div>candidate: event.candidate.candidate
<a name="line3641"></a><div class="linenumber">3641</div><div style="width:10em;display:inline-block"></div>};
<a name="line3642"></a><div class="linenumber">3642</div>
<a name="line3643"></a><div class="linenumber">3643</div><div style="width:10em;display:inline-block"></div>if (iceCandidateFilter ) {
<a name="line3644"></a><div class="linenumber">3644</div><div style="width:11em;display:inline-block"></div>candidateData = iceCandidateFilter(candidateData, false);
<a name="line3645"></a><div class="linenumber">3645</div><div style="width:11em;display:inline-block"></div>if( !candidateData ) {
<a name="line3646"></a><div class="linenumber">3646</div><div style="width:13em;display:inline-block"></div>return;
<a name="line3647"></a><div class="linenumber">3647</div><div style="width:11em;display:inline-block"></div>}
<a name="line3648"></a><div class="linenumber">3648</div><div style="width:10em;display:inline-block"></div>}
<a name="line3649"></a><div class="linenumber">3649</div><div style="width:10em;display:inline-block"></div>//
<a name="line3650"></a><div class="linenumber">3650</div><div style="width:10em;display:inline-block"></div>// some candidates include ip addresses of turn servers. we'll want those
<a name="line3651"></a><div class="linenumber">3651</div><div style="width:10em;display:inline-block"></div>// later so we can see if our actual connection uses a turn server.
<a name="line3652"></a><div class="linenumber">3652</div><div style="width:10em;display:inline-block"></div>// The keyword "relay" in the candidate identifies it as referencing a
<a name="line3653"></a><div class="linenumber">3653</div><div style="width:10em;display:inline-block"></div>// turn server. The \d symbol in the regular expression matches a number.
<a name="line3654"></a><div class="linenumber">3654</div><div style="width:10em;display:inline-block"></div>//
<a name="line3655"></a><div class="linenumber">3655</div><div style="width:10em;display:inline-block"></div>processCandicate(event.candidate.candidate);
<a name="line3656"></a><div class="linenumber">3656</div>
<a name="line3657"></a><div class="linenumber">3657</div><div style="width:10em;display:inline-block"></div>if (peerConns[otherUser].connectionAccepted) {
<a name="line3658"></a><div class="linenumber">3658</div><div style="width:12em;display:inline-block"></div>sendSignalling(otherUser, "candidate", candidateData, null, function() {
<a name="line3659"></a><div class="linenumber">3659</div><div style="width:14em;display:inline-block"></div>failureCB(self.errCodes.PEER_GONE, "Candidate disappeared");
<a name="line3660"></a><div class="linenumber">3660</div><div style="width:12em;display:inline-block"></div>});
<a name="line3661"></a><div class="linenumber">3661</div><div style="width:10em;display:inline-block"></div>}
<a name="line3662"></a><div class="linenumber">3662</div><div style="width:10em;display:inline-block"></div>else {
<a name="line3663"></a><div class="linenumber">3663</div><div style="width:12em;display:inline-block"></div>peerConns[otherUser].candidatesToSend.push(candidateData);
<a name="line3664"></a><div class="linenumber">3664</div><div style="width:10em;display:inline-block"></div>}
<a name="line3665"></a><div class="linenumber">3665</div><div style="width:8em;display:inline-block"></div>}
<a name="line3666"></a><div class="linenumber">3666</div><div style="width:6em;display:inline-block"></div>};
<a name="line3667"></a><div class="linenumber">3667</div>
<a name="line3668"></a><div class="linenumber">3668</div><div style="width:6em;display:inline-block"></div>pc.ontrack = function(event) {
<a name="line3669"></a><div class="linenumber">3669</div><div style="width:8em;display:inline-block"></div>logDebug("empty ontrack method invoked, which is expected");
<a name="line3670"></a><div class="linenumber">3670</div><div style="width:8em;display:inline-block"></div>processAddedTrack(otherUser, event.streams);
<a name="line3671"></a><div class="linenumber">3671</div><div style="width:6em;display:inline-block"></div>};
<a name="line3672"></a><div class="linenumber">3672</div>
<a name="line3673"></a><div class="linenumber">3673</div><div style="width:6em;display:inline-block"></div>pc.onaddstream = function(event) {
<a name="line3674"></a><div class="linenumber">3674</div><div style="width:8em;display:inline-block"></div>logDebug("empty onaddstream method invoked, which is expected");
<a name="line3675"></a><div class="linenumber">3675</div><div style="width:8em;display:inline-block"></div>processAddedStream(otherUser, event.stream);
<a name="line3676"></a><div class="linenumber">3676</div><div style="width:6em;display:inline-block"></div>};
<a name="line3677"></a><div class="linenumber">3677</div>
<a name="line3678"></a><div class="linenumber">3678</div><div style="width:6em;display:inline-block"></div>pc.onremovestream = function(event) {
<a name="line3679"></a><div class="linenumber">3679</div><div style="width:8em;display:inline-block"></div>logDebug("saw remove on remote media stream");
<a name="line3680"></a><div class="linenumber">3680</div><div style="width:8em;display:inline-block"></div>onRemoveStreamHelper(otherUser, event.stream);
<a name="line3681"></a><div class="linenumber">3681</div><div style="width:6em;display:inline-block"></div>};
<a name="line3682"></a><div class="linenumber">3682</div>
<a name="line3683"></a><div class="linenumber">3683</div><div style="width:6em;display:inline-block"></div>// Register PeerConn
<a name="line3684"></a><div class="linenumber">3684</div><div style="width:6em;display:inline-block"></div>peerConns[otherUser] = newPeerConn;
<a name="line3685"></a><div class="linenumber">3685</div>
<a name="line3686"></a><div class="linenumber">3686</div><div style="width:4em;display:inline-block"></div>} catch (error) {
<a name="line3687"></a><div class="linenumber">3687</div><div style="width:6em;display:inline-block"></div>logDebug('buildPeerConnection error', error);
<a name="line3688"></a><div class="linenumber">3688</div><div style="width:6em;display:inline-block"></div>failureCB(self.errCodes.SYSTEM_ERR, error.message);
<a name="line3689"></a><div class="linenumber">3689</div><div style="width:6em;display:inline-block"></div>return null;
<a name="line3690"></a><div class="linenumber">3690</div><div style="width:4em;display:inline-block"></div>}
<a name="line3691"></a><div class="linenumber">3691</div>
<a name="line3692"></a><div class="linenumber">3692</div><div style="width:4em;display:inline-block"></div>var i, stream;
<a name="line3693"></a><div class="linenumber">3693</div><div style="width:4em;display:inline-block"></div>if (streamNames) {
<a name="line3694"></a><div class="linenumber">3694</div><div style="width:6em;display:inline-block"></div>for (i = 0; i < streamNames.length; i++) {
<a name="line3695"></a><div class="linenumber">3695</div><div style="width:8em;display:inline-block"></div>stream = getLocalMediaStreamByName(streamNames[i]);
<a name="line3696"></a><div class="linenumber">3696</div><div style="width:8em;display:inline-block"></div>if (stream) {
<a name="line3697"></a><div class="linenumber">3697</div><div style="width:10em;display:inline-block"></div>pc.addStream(stream);
<a name="line3698"></a><div class="linenumber">3698</div><div style="width:8em;display:inline-block"></div>}
<a name="line3699"></a><div class="linenumber">3699</div><div style="width:8em;display:inline-block"></div>else {
<a name="line3700"></a><div class="linenumber">3700</div><div style="width:10em;display:inline-block"></div>logDebug("Developer error, attempt to access unknown local media stream " + streamNames[i]);
<a name="line3701"></a><div class="linenumber">3701</div><div style="width:8em;display:inline-block"></div>}
<a name="line3702"></a><div class="linenumber">3702</div><div style="width:6em;display:inline-block"></div>}
<a name="line3703"></a><div class="linenumber">3703</div><div style="width:4em;display:inline-block"></div>}
<a name="line3704"></a><div class="linenumber">3704</div><div style="width:4em;display:inline-block"></div>else if (autoInitUserMedia && (self.videoEnabled || self.audioEnabled)) {
<a name="line3705"></a><div class="linenumber">3705</div><div style="width:6em;display:inline-block"></div>stream = self.getLocalStream();
<a name="line3706"></a><div class="linenumber">3706</div><div style="width:6em;display:inline-block"></div>pc.addStream(stream);
<a name="line3707"></a><div class="linenumber">3707</div><div style="width:4em;display:inline-block"></div>}
<a name="line3708"></a><div class="linenumber">3708</div>
<a name="line3709"></a><div class="linenumber">3709</div><div style="width:4em;display:inline-block"></div>//
<a name="line3710"></a><div class="linenumber">3710</div><div style="width:4em;display:inline-block"></div>// This function handles data channel message events.
<a name="line3711"></a><div class="linenumber">3711</div><div style="width:4em;display:inline-block"></div>//
<a name="line3712"></a><div class="linenumber">3712</div><div style="width:4em;display:inline-block"></div>var pendingTransfer = {};
<a name="line3713"></a><div class="linenumber">3713</div><div style="width:4em;display:inline-block"></div>function dataChannelMessageHandler(event) {
<a name="line3714"></a><div class="linenumber">3714</div><div style="width:6em;display:inline-block"></div>logDebug("saw dataChannel.onmessage event: ", event.data);
<a name="line3715"></a><div class="linenumber">3715</div>
<a name="line3716"></a><div class="linenumber">3716</div><div style="width:6em;display:inline-block"></div>if (event.data === "dataChannelPrimed") {
<a name="line3717"></a><div class="linenumber">3717</div><div style="width:8em;display:inline-block"></div>self.sendDataWS(otherUser, "dataChannelPrimed", "");
<a name="line3718"></a><div class="linenumber">3718</div><div style="width:6em;display:inline-block"></div>}
<a name="line3719"></a><div class="linenumber">3719</div><div style="width:6em;display:inline-block"></div>else {
<a name="line3720"></a><div class="linenumber">3720</div><div style="width:8em;display:inline-block"></div>//
<a name="line3721"></a><div class="linenumber">3721</div><div style="width:8em;display:inline-block"></div>// Chrome and Firefox Interop is passing a event with a strange data="", perhaps
<a name="line3722"></a><div class="linenumber">3722</div><div style="width:8em;display:inline-block"></div>// as it's own form of priming message. Comparing the data against "" doesn't
<a name="line3723"></a><div class="linenumber">3723</div><div style="width:8em;display:inline-block"></div>// work, so I'm going with parsing and trapping the parse error.
<a name="line3724"></a><div class="linenumber">3724</div><div style="width:8em;display:inline-block"></div>//
<a name="line3725"></a><div class="linenumber">3725</div><div style="width:8em;display:inline-block"></div>var msg;
<a name="line3726"></a><div class="linenumber">3726</div>
<a name="line3727"></a><div class="linenumber">3727</div><div style="width:8em;display:inline-block"></div>try {
<a name="line3728"></a><div class="linenumber">3728</div><div style="width:10em;display:inline-block"></div>msg = JSON.parse(event.data);
<a name="line3729"></a><div class="linenumber">3729</div><div style="width:8em;display:inline-block"></div>} catch (err) {
<a name="line3730"></a><div class="linenumber">3730</div><div style="width:10em;display:inline-block"></div>logDebug('Developer error, unable to parse event data');
<a name="line3731"></a><div class="linenumber">3731</div><div style="width:8em;display:inline-block"></div>}
<a name="line3732"></a><div class="linenumber">3732</div>
<a name="line3733"></a><div class="linenumber">3733</div><div style="width:8em;display:inline-block"></div>if (msg) {
<a name="line3734"></a><div class="linenumber">3734</div><div style="width:10em;display:inline-block"></div>if (msg.transfer && msg.transferId) {
<a name="line3735"></a><div class="linenumber">3735</div><div style="width:12em;display:inline-block"></div>if (msg.transfer === 'start') {
<a name="line3736"></a><div class="linenumber">3736</div><div style="width:14em;display:inline-block"></div>logDebug('start transfer #' + msg.transferId);
<a name="line3737"></a><div class="linenumber">3737</div>
<a name="line3738"></a><div class="linenumber">3738</div><div style="width:14em;display:inline-block"></div>var parts = parseInt(msg.parts);
<a name="line3739"></a><div class="linenumber">3739</div><div style="width:14em;display:inline-block"></div>pendingTransfer = {
<a name="line3740"></a><div class="linenumber">3740</div><div style="width:16em;display:inline-block"></div>chunks: [],
<a name="line3741"></a><div class="linenumber">3741</div><div style="width:16em;display:inline-block"></div>parts: parts,
<a name="line3742"></a><div class="linenumber">3742</div><div style="width:16em;display:inline-block"></div>transferId: msg.transferId
<a name="line3743"></a><div class="linenumber">3743</div><div style="width:14em;display:inline-block"></div>};
<a name="line3744"></a><div class="linenumber">3744</div>
<a name="line3745"></a><div class="linenumber">3745</div><div style="width:12em;display:inline-block"></div>} else if (msg.transfer === 'chunk') {
<a name="line3746"></a><div class="linenumber">3746</div><div style="width:14em;display:inline-block"></div>logDebug('got chunk for transfer #' + msg.transferId);
<a name="line3747"></a><div class="linenumber">3747</div>
<a name="line3748"></a><div class="linenumber">3748</div><div style="width:14em;display:inline-block"></div>// check data is valid
<a name="line3749"></a><div class="linenumber">3749</div><div style="width:14em;display:inline-block"></div>if (!(typeof msg.data === 'string' && msg.data.length <= self.maxP2PMessageLength)) {
<a name="line3750"></a><div class="linenumber">3750</div><div style="width:16em;display:inline-block"></div>logDebug('Developer error, invalid data');
<a name="line3751"></a><div class="linenumber">3751</div>
<a name="line3752"></a><div class="linenumber">3752</div><div style="width:16em;display:inline-block"></div>// check there's a pending transfer
<a name="line3753"></a><div class="linenumber">3753</div><div style="width:14em;display:inline-block"></div>} else if (!pendingTransfer) {
<a name="line3754"></a><div class="linenumber">3754</div><div style="width:16em;display:inline-block"></div>logDebug('Developer error, unexpected chunk');
<a name="line3755"></a><div class="linenumber">3755</div>
<a name="line3756"></a><div class="linenumber">3756</div><div style="width:14em;display:inline-block"></div>// check that transferId is valid
<a name="line3757"></a><div class="linenumber">3757</div><div style="width:14em;display:inline-block"></div>} else if (msg.transferId !== pendingTransfer.transferId) {
<a name="line3758"></a><div class="linenumber">3758</div><div style="width:16em;display:inline-block"></div>logDebug('Developer error, invalid transfer id');
<a name="line3759"></a><div class="linenumber">3759</div>
<a name="line3760"></a><div class="linenumber">3760</div><div style="width:14em;display:inline-block"></div>// check that the max length of transfer is not reached
<a name="line3761"></a><div class="linenumber">3761</div><div style="width:14em;display:inline-block"></div>} else if (pendingTransfer.chunks.length + 1 > pendingTransfer.parts) {
<a name="line3762"></a><div class="linenumber">3762</div><div style="width:16em;display:inline-block"></div>logDebug('Developer error, received too many chunks');
<a name="line3763"></a><div class="linenumber">3763</div>
<a name="line3764"></a><div class="linenumber">3764</div><div style="width:14em;display:inline-block"></div>} else {
<a name="line3765"></a><div class="linenumber">3765</div><div style="width:16em;display:inline-block"></div>pendingTransfer.chunks.push(msg.data);
<a name="line3766"></a><div class="linenumber">3766</div><div style="width:14em;display:inline-block"></div>}
<a name="line3767"></a><div class="linenumber">3767</div>
<a name="line3768"></a><div class="linenumber">3768</div><div style="width:12em;display:inline-block"></div>} else if (msg.transfer === 'end') {
<a name="line3769"></a><div class="linenumber">3769</div><div style="width:14em;display:inline-block"></div>logDebug('end of transfer #' + msg.transferId);
<a name="line3770"></a><div class="linenumber">3770</div>
<a name="line3771"></a><div class="linenumber">3771</div><div style="width:14em;display:inline-block"></div>// check there's a pending transfer
<a name="line3772"></a><div class="linenumber">3772</div><div style="width:14em;display:inline-block"></div>if (!pendingTransfer) {
<a name="line3773"></a><div class="linenumber">3773</div><div style="width:16em;display:inline-block"></div>logDebug('Developer error, unexpected end of transfer');
<a name="line3774"></a><div class="linenumber">3774</div>
<a name="line3775"></a><div class="linenumber">3775</div><div style="width:14em;display:inline-block"></div>// check that transferId is valid
<a name="line3776"></a><div class="linenumber">3776</div><div style="width:14em;display:inline-block"></div>} else if (msg.transferId !== pendingTransfer.transferId) {
<a name="line3777"></a><div class="linenumber">3777</div><div style="width:16em;display:inline-block"></div>logDebug('Developer error, invalid transfer id');
<a name="line3778"></a><div class="linenumber">3778</div>
<a name="line3779"></a><div class="linenumber">3779</div><div style="width:14em;display:inline-block"></div>// check that all the chunks were received
<a name="line3780"></a><div class="linenumber">3780</div><div style="width:14em;display:inline-block"></div>} else if (pendingTransfer.chunks.length !== pendingTransfer.parts) {
<a name="line3781"></a><div class="linenumber">3781</div><div style="width:16em;display:inline-block"></div>logDebug('Developer error, received wrong number of chunks');
<a name="line3782"></a><div class="linenumber">3782</div>
<a name="line3783"></a><div class="linenumber">3783</div><div style="width:14em;display:inline-block"></div>} else {
<a name="line3784"></a><div class="linenumber">3784</div><div style="width:16em;display:inline-block"></div>var chunkedMsg;
<a name="line3785"></a><div class="linenumber">3785</div><div style="width:16em;display:inline-block"></div>try {
<a name="line3786"></a><div class="linenumber">3786</div><div style="width:18em;display:inline-block"></div>chunkedMsg = JSON.parse(pendingTransfer.chunks.join(''));
<a name="line3787"></a><div class="linenumber">3787</div><div style="width:16em;display:inline-block"></div>} catch (err) {
<a name="line3788"></a><div class="linenumber">3788</div><div style="width:18em;display:inline-block"></div>logDebug('Developer error, unable to parse message');
<a name="line3789"></a><div class="linenumber">3789</div><div style="width:16em;display:inline-block"></div>}
<a name="line3790"></a><div class="linenumber">3790</div>
<a name="line3791"></a><div class="linenumber">3791</div><div style="width:16em;display:inline-block"></div>if (chunkedMsg) {
<a name="line3792"></a><div class="linenumber">3792</div><div style="width:18em;display:inline-block"></div>self.receivePeerDistribute(otherUser, chunkedMsg, null);
<a name="line3793"></a><div class="linenumber">3793</div><div style="width:16em;display:inline-block"></div>}
<a name="line3794"></a><div class="linenumber">3794</div><div style="width:14em;display:inline-block"></div>}
<a name="line3795"></a><div class="linenumber">3795</div><div style="width:14em;display:inline-block"></div>pendingTransfer = { };
<a name="line3796"></a><div class="linenumber">3796</div>
<a name="line3797"></a><div class="linenumber">3797</div><div style="width:12em;display:inline-block"></div>} else {
<a name="line3798"></a><div class="linenumber">3798</div><div style="width:14em;display:inline-block"></div>logDebug('Developer error, got an unknown transfer message' + msg.transfer);
<a name="line3799"></a><div class="linenumber">3799</div><div style="width:12em;display:inline-block"></div>}
<a name="line3800"></a><div class="linenumber">3800</div><div style="width:10em;display:inline-block"></div>} else {
<a name="line3801"></a><div class="linenumber">3801</div><div style="width:12em;display:inline-block"></div>self.receivePeerDistribute(otherUser, msg, null);
<a name="line3802"></a><div class="linenumber">3802</div><div style="width:10em;display:inline-block"></div>}
<a name="line3803"></a><div class="linenumber">3803</div><div style="width:8em;display:inline-block"></div>}
<a name="line3804"></a><div class="linenumber">3804</div><div style="width:6em;display:inline-block"></div>}
<a name="line3805"></a><div class="linenumber">3805</div><div style="width:4em;display:inline-block"></div>}
<a name="line3806"></a><div class="linenumber">3806</div>
<a name="line3807"></a><div class="linenumber">3807</div><div style="width:4em;display:inline-block"></div>function initOutGoingChannel(otherUser) {
<a name="line3808"></a><div class="linenumber">3808</div><div style="width:6em;display:inline-block"></div>logDebug("saw initOutgoingChannel call");
<a name="line3809"></a><div class="linenumber">3809</div>
<a name="line3810"></a><div class="linenumber">3810</div><div style="width:6em;display:inline-block"></div>var dataChannel = pc.createDataChannel(dataChannelName, self.getDatachannelConstraints());
<a name="line3811"></a><div class="linenumber">3811</div><div style="width:6em;display:inline-block"></div>peerConns[otherUser].dataChannelS = dataChannel;
<a name="line3812"></a><div class="linenumber">3812</div><div style="width:6em;display:inline-block"></div>peerConns[otherUser].dataChannelR = dataChannel;
<a name="line3813"></a><div class="linenumber">3813</div><div style="width:6em;display:inline-block"></div>dataChannel.onmessage = dataChannelMessageHandler;
<a name="line3814"></a><div class="linenumber">3814</div><div style="width:6em;display:inline-block"></div>dataChannel.onopen = function(event) {
<a name="line3815"></a><div class="linenumber">3815</div><div style="width:8em;display:inline-block"></div>logDebug("saw dataChannel.onopen event");
<a name="line3816"></a><div class="linenumber">3816</div>
<a name="line3817"></a><div class="linenumber">3817</div><div style="width:8em;display:inline-block"></div>if (peerConns[otherUser]) {
<a name="line3818"></a><div class="linenumber">3818</div><div style="width:10em;display:inline-block"></div>dataChannel.send("dataChannelPrimed");
<a name="line3819"></a><div class="linenumber">3819</div><div style="width:8em;display:inline-block"></div>}
<a name="line3820"></a><div class="linenumber">3820</div><div style="width:6em;display:inline-block"></div>};
<a name="line3821"></a><div class="linenumber">3821</div><div style="width:6em;display:inline-block"></div>dataChannel.onclose = function(event) {
<a name="line3822"></a><div class="linenumber">3822</div><div style="width:8em;display:inline-block"></div>logDebug("saw dataChannelS.onclose event");
<a name="line3823"></a><div class="linenumber">3823</div>
<a name="line3824"></a><div class="linenumber">3824</div><div style="width:8em;display:inline-block"></div>if (peerConns[otherUser]) {
<a name="line3825"></a><div class="linenumber">3825</div><div style="width:10em;display:inline-block"></div>peerConns[otherUser].dataChannelReady = false;
<a name="line3826"></a><div class="linenumber">3826</div><div style="width:10em;display:inline-block"></div>delete peerConns[otherUser].dataChannelS;
<a name="line3827"></a><div class="linenumber">3827</div><div style="width:8em;display:inline-block"></div>}
<a name="line3828"></a><div class="linenumber">3828</div><div style="width:8em;display:inline-block"></div>if (onDataChannelClose) {
<a name="line3829"></a><div class="linenumber">3829</div><div style="width:10em;display:inline-block"></div>onDataChannelClose(otherUser);
<a name="line3830"></a><div class="linenumber">3830</div><div style="width:8em;display:inline-block"></div>}
<a name="line3831"></a><div class="linenumber">3831</div>
<a name="line3832"></a><div class="linenumber">3832</div><div style="width:8em;display:inline-block"></div>updateConfigurationInfo();
<a name="line3833"></a><div class="linenumber">3833</div><div style="width:6em;display:inline-block"></div>};
<a name="line3834"></a><div class="linenumber">3834</div><div style="width:4em;display:inline-block"></div>}
<a name="line3835"></a><div class="linenumber">3835</div>
<a name="line3836"></a><div class="linenumber">3836</div><div style="width:4em;display:inline-block"></div>function initIncomingChannel(otherUser) {
<a name="line3837"></a><div class="linenumber">3837</div><div style="width:6em;display:inline-block"></div>logDebug("initializing incoming channel handler for " + otherUser);
<a name="line3838"></a><div class="linenumber">3838</div>
<a name="line3839"></a><div class="linenumber">3839</div><div style="width:6em;display:inline-block"></div>peerConns[otherUser].pc.ondatachannel = function(event) {
<a name="line3840"></a><div class="linenumber">3840</div>
<a name="line3841"></a><div class="linenumber">3841</div><div style="width:8em;display:inline-block"></div>logDebug("saw incoming data channel");
<a name="line3842"></a><div class="linenumber">3842</div>
<a name="line3843"></a><div class="linenumber">3843</div><div style="width:8em;display:inline-block"></div>var dataChannel = event.channel;
<a name="line3844"></a><div class="linenumber">3844</div><div style="width:8em;display:inline-block"></div>peerConns[otherUser].dataChannelR = dataChannel;
<a name="line3845"></a><div class="linenumber">3845</div><div style="width:8em;display:inline-block"></div>peerConns[otherUser].dataChannelS = dataChannel;
<a name="line3846"></a><div class="linenumber">3846</div><div style="width:8em;display:inline-block"></div>peerConns[otherUser].dataChannelReady = true;
<a name="line3847"></a><div class="linenumber">3847</div><div style="width:8em;display:inline-block"></div>dataChannel.onmessage = dataChannelMessageHandler;
<a name="line3848"></a><div class="linenumber">3848</div><div style="width:8em;display:inline-block"></div>dataChannel.onclose = function(event) {
<a name="line3849"></a><div class="linenumber">3849</div><div style="width:10em;display:inline-block"></div>logDebug("saw dataChannelR.onclose event");
<a name="line3850"></a><div class="linenumber">3850</div>
<a name="line3851"></a><div class="linenumber">3851</div><div style="width:10em;display:inline-block"></div>if (peerConns[otherUser]) {
<a name="line3852"></a><div class="linenumber">3852</div><div style="width:12em;display:inline-block"></div>peerConns[otherUser].dataChannelReady = false;
<a name="line3853"></a><div class="linenumber">3853</div><div style="width:12em;display:inline-block"></div>delete peerConns[otherUser].dataChannelR;
<a name="line3854"></a><div class="linenumber">3854</div><div style="width:10em;display:inline-block"></div>}
<a name="line3855"></a><div class="linenumber">3855</div><div style="width:10em;display:inline-block"></div>if (onDataChannelClose) {
<a name="line3856"></a><div class="linenumber">3856</div><div style="width:12em;display:inline-block"></div>onDataChannelClose(otherUser);
<a name="line3857"></a><div class="linenumber">3857</div><div style="width:10em;display:inline-block"></div>}
<a name="line3858"></a><div class="linenumber">3858</div>
<a name="line3859"></a><div class="linenumber">3859</div><div style="width:10em;display:inline-block"></div>updateConfigurationInfo();
<a name="line3860"></a><div class="linenumber">3860</div><div style="width:8em;display:inline-block"></div>};
<a name="line3861"></a><div class="linenumber">3861</div><div style="width:8em;display:inline-block"></div>dataChannel.onopen = function(event) {
<a name="line3862"></a><div class="linenumber">3862</div><div style="width:10em;display:inline-block"></div>logDebug("saw dataChannel.onopen event");
<a name="line3863"></a><div class="linenumber">3863</div>
<a name="line3864"></a><div class="linenumber">3864</div><div style="width:10em;display:inline-block"></div>if (peerConns[otherUser]) {
<a name="line3865"></a><div class="linenumber">3865</div><div style="width:12em;display:inline-block"></div>dataChannel.send("dataChannelPrimed");
<a name="line3866"></a><div class="linenumber">3866</div><div style="width:10em;display:inline-block"></div>}
<a name="line3867"></a><div class="linenumber">3867</div><div style="width:8em;display:inline-block"></div>};
<a name="line3868"></a><div class="linenumber">3868</div><div style="width:6em;display:inline-block"></div>};
<a name="line3869"></a><div class="linenumber">3869</div><div style="width:4em;display:inline-block"></div>}
<a name="line3870"></a><div class="linenumber">3870</div>
<a name="line3871"></a><div class="linenumber">3871</div><div style="width:4em;display:inline-block"></div>//
<a name="line3872"></a><div class="linenumber">3872</div><div style="width:4em;display:inline-block"></div>// added for interoperability
<a name="line3873"></a><div class="linenumber">3873</div><div style="width:4em;display:inline-block"></div>//
<a name="line3874"></a><div class="linenumber">3874</div><div style="width:4em;display:inline-block"></div>// TODO check if both sides have the same browser and versions
<a name="line3875"></a><div class="linenumber">3875</div><div style="width:4em;display:inline-block"></div>if (dataEnabled) {
<a name="line3876"></a><div class="linenumber">3876</div><div style="width:6em;display:inline-block"></div>self.setPeerListener(function() {
<a name="line3877"></a><div class="linenumber">3877</div><div style="width:8em;display:inline-block"></div>if (peerConns[otherUser]) {
<a name="line3878"></a><div class="linenumber">3878</div><div style="width:10em;display:inline-block"></div>peerConns[otherUser].dataChannelReady = true;
<a name="line3879"></a><div class="linenumber">3879</div><div style="width:10em;display:inline-block"></div>if (peerConns[otherUser].callSuccessCB) {
<a name="line3880"></a><div class="linenumber">3880</div><div style="width:12em;display:inline-block"></div>peerConns[otherUser].callSuccessCB(otherUser, "datachannel");
<a name="line3881"></a><div class="linenumber">3881</div><div style="width:10em;display:inline-block"></div>}
<a name="line3882"></a><div class="linenumber">3882</div><div style="width:10em;display:inline-block"></div>if (onDataChannelOpen) {
<a name="line3883"></a><div class="linenumber">3883</div><div style="width:12em;display:inline-block"></div>onDataChannelOpen(otherUser, true);
<a name="line3884"></a><div class="linenumber">3884</div><div style="width:10em;display:inline-block"></div>}
<a name="line3885"></a><div class="linenumber">3885</div><div style="width:10em;display:inline-block"></div>updateConfigurationInfo();
<a name="line3886"></a><div class="linenumber">3886</div><div style="width:8em;display:inline-block"></div>} else {
<a name="line3887"></a><div class="linenumber">3887</div><div style="width:10em;display:inline-block"></div>logDebug("failed to setup outgoing channel listener");
<a name="line3888"></a><div class="linenumber">3888</div><div style="width:8em;display:inline-block"></div>}
<a name="line3889"></a><div class="linenumber">3889</div><div style="width:6em;display:inline-block"></div>}, "dataChannelPrimed", otherUser);
<a name="line3890"></a><div class="linenumber">3890</div>
<a name="line3891"></a><div class="linenumber">3891</div><div style="width:6em;display:inline-block"></div>if (isInitiator) {
<a name="line3892"></a><div class="linenumber">3892</div><div style="width:8em;display:inline-block"></div>try {
<a name="line3893"></a><div class="linenumber">3893</div>
<a name="line3894"></a><div class="linenumber">3894</div><div style="width:10em;display:inline-block"></div>initOutGoingChannel(otherUser);
<a name="line3895"></a><div class="linenumber">3895</div><div style="width:8em;display:inline-block"></div>} catch (channelErrorEvent) {
<a name="line3896"></a><div class="linenumber">3896</div><div style="width:10em;display:inline-block"></div>logDebug("failed to init outgoing channel");
<a name="line3897"></a><div class="linenumber">3897</div><div style="width:10em;display:inline-block"></div>failureCB(self.errCodes.SYSTEM_ERR,
<a name="line3898"></a><div class="linenumber">3898</div><div style="width:14em;display:inline-block"></div>self.formatError(channelErrorEvent));
<a name="line3899"></a><div class="linenumber">3899</div><div style="width:8em;display:inline-block"></div>}
<a name="line3900"></a><div class="linenumber">3900</div><div style="width:6em;display:inline-block"></div>}
<a name="line3901"></a><div class="linenumber">3901</div><div style="width:6em;display:inline-block"></div>if (!isInitiator) {
<a name="line3902"></a><div class="linenumber">3902</div><div style="width:8em;display:inline-block"></div>initIncomingChannel(otherUser);
<a name="line3903"></a><div class="linenumber">3903</div><div style="width:6em;display:inline-block"></div>}
<a name="line3904"></a><div class="linenumber">3904</div><div style="width:4em;display:inline-block"></div>}
<a name="line3905"></a><div class="linenumber">3905</div>
<a name="line3906"></a><div class="linenumber">3906</div><div style="width:4em;display:inline-block"></div>pc.onconnection = function() {
<a name="line3907"></a><div class="linenumber">3907</div><div style="width:6em;display:inline-block"></div>logDebug("setup pc.onconnection ");
<a name="line3908"></a><div class="linenumber">3908</div><div style="width:4em;display:inline-block"></div>};
<a name="line3909"></a><div class="linenumber">3909</div>
<a name="line3910"></a><div class="linenumber">3910</div><div style="width:4em;display:inline-block"></div>//
<a name="line3911"></a><div class="linenumber">3911</div><div style="width:4em;display:inline-block"></div>// Temporary support for responding to acknowledgements of about streams being added.
<a name="line3912"></a><div class="linenumber">3912</div><div style="width:4em;display:inline-block"></div>//
<a name="line3913"></a><div class="linenumber">3913</div><div style="width:4em;display:inline-block"></div>self.setPeerListener(function(easyrtcid, msgType, msgData, targeting){
<a name="line3914"></a><div class="linenumber">3914</div><div style="width:6em;display:inline-block"></div>if( newPeerConn.streamsAddedAcks[msgData.streamName]) {
<a name="line3915"></a><div class="linenumber">3915</div><div style="width:8em;display:inline-block"></div>(newPeerConn.streamsAddedAcks[msgData.streamName])(easyrtcid, msgData.streamName);
<a name="line3916"></a><div class="linenumber">3916</div><div style="width:8em;display:inline-block"></div>delete newPeerConn.streamsAddedAcks[msgData.streamName];
<a name="line3917"></a><div class="linenumber">3917</div><div style="width:6em;display:inline-block"></div>}
<a name="line3918"></a><div class="linenumber">3918</div><div style="width:4em;display:inline-block"></div>}, "easyrtc_streamReceived", otherUser);
<a name="line3919"></a><div class="linenumber">3919</div><div style="width:4em;display:inline-block"></div>return pc;
<a name="line3920"></a><div class="linenumber">3920</div><div style="width:2em;display:inline-block"></div>}
<a name="line3921"></a><div class="linenumber">3921</div>
<a name="line3922"></a><div class="linenumber">3922</div><div style="width:2em;display:inline-block"></div>/** @private */
<a name="line3923"></a><div class="linenumber">3923</div><div style="width:2em;display:inline-block"></div>function doAnswerBody(caller, msgData, streamNames) {
<a name="line3924"></a><div class="linenumber">3924</div><div style="width:4em;display:inline-block"></div>var pc = buildPeerConnection(caller, false, function(message) {
<a name="line3925"></a><div class="linenumber">3925</div><div style="width:6em;display:inline-block"></div>self.showError(self.errCodes.SYSTEM_ERR, message);
<a name="line3926"></a><div class="linenumber">3926</div><div style="width:4em;display:inline-block"></div>}, streamNames);
<a name="line3927"></a><div class="linenumber">3927</div><div style="width:4em;display:inline-block"></div>var newPeerConn = peerConns[caller];
<a name="line3928"></a><div class="linenumber">3928</div><div style="width:4em;display:inline-block"></div>if (!pc) {
<a name="line3929"></a><div class="linenumber">3929</div><div style="width:6em;display:inline-block"></div>logDebug("buildPeerConnection failed. Call not answered");
<a name="line3930"></a><div class="linenumber">3930</div><div style="width:6em;display:inline-block"></div>return;
<a name="line3931"></a><div class="linenumber">3931</div><div style="width:4em;display:inline-block"></div>}
<a name="line3932"></a><div class="linenumber">3932</div><div style="width:4em;display:inline-block"></div>var setLocalAndSendMessage1 = function(sessionDescription) {
<a name="line3933"></a><div class="linenumber">3933</div>
<a name="line3934"></a><div class="linenumber">3934</div><div style="width:6em;display:inline-block"></div>if (newPeerConn.cancelled) {
<a name="line3935"></a><div class="linenumber">3935</div><div style="width:8em;display:inline-block"></div>return;
<a name="line3936"></a><div class="linenumber">3936</div><div style="width:6em;display:inline-block"></div>}
<a name="line3937"></a><div class="linenumber">3937</div>
<a name="line3938"></a><div class="linenumber">3938</div><div style="width:6em;display:inline-block"></div>var sendAnswer = function() {
<a name="line3939"></a><div class="linenumber">3939</div><div style="width:8em;display:inline-block"></div>logDebug("sending answer");
<a name="line3940"></a><div class="linenumber">3940</div>
<a name="line3941"></a><div class="linenumber">3941</div><div style="width:8em;display:inline-block"></div>function onSignalSuccess() {
<a name="line3942"></a><div class="linenumber">3942</div><div style="width:10em;display:inline-block"></div>logDebug("sending success");
<a name="line3943"></a><div class="linenumber">3943</div><div style="width:8em;display:inline-block"></div>}
<a name="line3944"></a><div class="linenumber">3944</div>
<a name="line3945"></a><div class="linenumber">3945</div><div style="width:8em;display:inline-block"></div>function onSignalFailure(errorCode, errorText) {
<a name="line3946"></a><div class="linenumber">3946</div><div style="width:10em;display:inline-block"></div>logDebug("sending error");
<a name="line3947"></a><div class="linenumber">3947</div><div style="width:10em;display:inline-block"></div>delete peerConns[caller];
<a name="line3948"></a><div class="linenumber">3948</div><div style="width:10em;display:inline-block"></div>self.showError(errorCode, errorText);
<a name="line3949"></a><div class="linenumber">3949</div><div style="width:8em;display:inline-block"></div>}
<a name="line3950"></a><div class="linenumber">3950</div>
<a name="line3951"></a><div class="linenumber">3951</div><div style="width:8em;display:inline-block"></div>sendSignalling(caller, "answer", sessionDescription, onSignalSuccess, onSignalFailure);
<a name="line3952"></a><div class="linenumber">3952</div><div style="width:8em;display:inline-block"></div>peerConns[caller].connectionAccepted = true;
<a name="line3953"></a><div class="linenumber">3953</div><div style="width:8em;display:inline-block"></div>sendQueuedCandidates(caller, onSignalSuccess, onSignalFailure);
<a name="line3954"></a><div class="linenumber">3954</div>
<a name="line3955"></a><div class="linenumber">3955</div><div style="width:8em;display:inline-block"></div>if (pc.connectDataConnection) {
<a name="line3956"></a><div class="linenumber">3956</div><div style="width:10em;display:inline-block"></div>logDebug("calling connectDataConnection(5002,5001)");
<a name="line3957"></a><div class="linenumber">3957</div><div style="width:10em;display:inline-block"></div>pc.connectDataConnection(5002, 5001);
<a name="line3958"></a><div class="linenumber">3958</div><div style="width:8em;display:inline-block"></div>}
<a name="line3959"></a><div class="linenumber">3959</div><div style="width:6em;display:inline-block"></div>};
<a name="line3960"></a><div class="linenumber">3960</div><div style="width:6em;display:inline-block"></div>if (sdpLocalFilter) {
<a name="line3961"></a><div class="linenumber">3961</div><div style="width:8em;display:inline-block"></div>sessionDescription.sdp = sdpLocalFilter(sessionDescription.sdp);
<a name="line3962"></a><div class="linenumber">3962</div><div style="width:6em;display:inline-block"></div>}
<a name="line3963"></a><div class="linenumber">3963</div><div style="width:6em;display:inline-block"></div>pc.setLocalDescription(sessionDescription, sendAnswer, function(message) {
<a name="line3964"></a><div class="linenumber">3964</div><div style="width:8em;display:inline-block"></div>self.showError(self.errCodes.INTERNAL_ERR, "setLocalDescription: " + message);
<a name="line3965"></a><div class="linenumber">3965</div><div style="width:6em;display:inline-block"></div>});
<a name="line3966"></a><div class="linenumber">3966</div><div style="width:4em;display:inline-block"></div>};
<a name="line3967"></a><div class="linenumber">3967</div><div style="width:4em;display:inline-block"></div>var sd = new RTCSessionDescription(msgData);
<a name="line3968"></a><div class="linenumber">3968</div>
<a name="line3969"></a><div class="linenumber">3969</div><div style="width:4em;display:inline-block"></div>if (!sd) {
<a name="line3970"></a><div class="linenumber">3970</div><div style="width:6em;display:inline-block"></div>throw "Could not create the RTCSessionDescription";
<a name="line3971"></a><div class="linenumber">3971</div><div style="width:4em;display:inline-block"></div>}
<a name="line3972"></a><div class="linenumber">3972</div>
<a name="line3973"></a><div class="linenumber">3973</div><div style="width:4em;display:inline-block"></div>logDebug("sdp || " + JSON.stringify(sd));
<a name="line3974"></a><div class="linenumber">3974</div>
<a name="line3975"></a><div class="linenumber">3975</div><div style="width:4em;display:inline-block"></div>var invokeCreateAnswer = function() {
<a name="line3976"></a><div class="linenumber">3976</div><div style="width:6em;display:inline-block"></div>if (newPeerConn.cancelled) {
<a name="line3977"></a><div class="linenumber">3977</div><div style="width:8em;display:inline-block"></div>return;
<a name="line3978"></a><div class="linenumber">3978</div><div style="width:6em;display:inline-block"></div>}
<a name="line3979"></a><div class="linenumber">3979</div><div style="width:6em;display:inline-block"></div>pc.createAnswer(setLocalAndSendMessage1,
<a name="line3980"></a><div class="linenumber">3980</div><div style="width:8em;display:inline-block"></div>function(message) {
<a name="line3981"></a><div class="linenumber">3981</div><div style="width:10em;display:inline-block"></div>self.showError(self.errCodes.INTERNAL_ERR, "create-answer: " + message);
<a name="line3982"></a><div class="linenumber">3982</div><div style="width:8em;display:inline-block"></div>},
<a name="line3983"></a><div class="linenumber">3983</div><div style="width:8em;display:inline-block"></div>receivedMediaConstraints);
<a name="line3984"></a><div class="linenumber">3984</div><div style="width:4em;display:inline-block"></div>};
<a name="line3985"></a><div class="linenumber">3985</div>
<a name="line3986"></a><div class="linenumber">3986</div><div style="width:4em;display:inline-block"></div>logDebug("about to call setRemoteDescription in doAnswer");
<a name="line3987"></a><div class="linenumber">3987</div>
<a name="line3988"></a><div class="linenumber">3988</div><div style="width:4em;display:inline-block"></div>try {
<a name="line3989"></a><div class="linenumber">3989</div>
<a name="line3990"></a><div class="linenumber">3990</div><div style="width:6em;display:inline-block"></div>if (sdpRemoteFilter) {
<a name="line3991"></a><div class="linenumber">3991</div><div style="width:8em;display:inline-block"></div>sd.sdp = sdpRemoteFilter(sd.sdp);
<a name="line3992"></a><div class="linenumber">3992</div><div style="width:6em;display:inline-block"></div>}
<a name="line3993"></a><div class="linenumber">3993</div><div style="width:6em;display:inline-block"></div>pc.setRemoteDescription(sd, invokeCreateAnswer, function(message) {
<a name="line3994"></a><div class="linenumber">3994</div><div style="width:8em;display:inline-block"></div>self.showError(self.errCodes.INTERNAL_ERR, "set-remote-description: " + message);
<a name="line3995"></a><div class="linenumber">3995</div><div style="width:6em;display:inline-block"></div>});
<a name="line3996"></a><div class="linenumber">3996</div><div style="width:4em;display:inline-block"></div>} catch (srdError) {
<a name="line3997"></a><div class="linenumber">3997</div><div style="width:6em;display:inline-block"></div>logDebug("set remote description failed");
<a name="line3998"></a><div class="linenumber">3998</div><div style="width:6em;display:inline-block"></div>self.showError(self.errCodes.INTERNAL_ERR, "setRemoteDescription failed: " + srdError.message);
<a name="line3999"></a><div class="linenumber">3999</div><div style="width:4em;display:inline-block"></div>}
<a name="line4000"></a><div class="linenumber">4000</div><div style="width:2em;display:inline-block"></div>}
<a name="line4001"></a><div class="linenumber">4001</div>
<a name="line4002"></a><div class="linenumber">4002</div><div style="width:2em;display:inline-block"></div>/** @private */
<a name="line4003"></a><div class="linenumber">4003</div><div style="width:2em;display:inline-block"></div>function doAnswer(caller, msgData, streamNames) {
<a name="line4004"></a><div class="linenumber">4004</div><div style="width:4em;display:inline-block"></div>if (!streamNames && autoInitUserMedia) {
<a name="line4005"></a><div class="linenumber">4005</div><div style="width:6em;display:inline-block"></div>var localStream = self.getLocalStream();
<a name="line4006"></a><div class="linenumber">4006</div><div style="width:6em;display:inline-block"></div>if (!localStream && (self.videoEnabled || self.audioEnabled)) {
<a name="line4007"></a><div class="linenumber">4007</div><div style="width:8em;display:inline-block"></div>self.initMediaSource(
<a name="line4008"></a><div class="linenumber">4008</div><div style="width:12em;display:inline-block"></div>function() {
<a name="line4009"></a><div class="linenumber">4009</div><div style="width:14em;display:inline-block"></div>doAnswer(caller, msgData);
<a name="line4010"></a><div class="linenumber">4010</div><div style="width:12em;display:inline-block"></div>},
<a name="line4011"></a><div class="linenumber">4011</div><div style="width:12em;display:inline-block"></div>function(errorCode, error) {
<a name="line4012"></a><div class="linenumber">4012</div><div style="width:14em;display:inline-block"></div>self.showError(self.errCodes.MEDIA_ERR, self.format(self.getConstantString("localMediaError")));
<a name="line4013"></a><div class="linenumber">4013</div><div style="width:12em;display:inline-block"></div>});
<a name="line4014"></a><div class="linenumber">4014</div><div style="width:8em;display:inline-block"></div>return;
<a name="line4015"></a><div class="linenumber">4015</div><div style="width:6em;display:inline-block"></div>}
<a name="line4016"></a><div class="linenumber">4016</div><div style="width:4em;display:inline-block"></div>}
<a name="line4017"></a><div class="linenumber">4017</div><div style="width:4em;display:inline-block"></div>if (use_fresh_ice_each_peer) {
<a name="line4018"></a><div class="linenumber">4018</div><div style="width:6em;display:inline-block"></div>self.getFreshIceConfig(function(succeeded) {
<a name="line4019"></a><div class="linenumber">4019</div><div style="width:8em;display:inline-block"></div>if (succeeded) {
<a name="line4020"></a><div class="linenumber">4020</div><div style="width:10em;display:inline-block"></div>doAnswerBody(caller, msgData, streamNames);
<a name="line4021"></a><div class="linenumber">4021</div><div style="width:8em;display:inline-block"></div>}
<a name="line4022"></a><div class="linenumber">4022</div><div style="width:8em;display:inline-block"></div>else {
<a name="line4023"></a><div class="linenumber">4023</div><div style="width:10em;display:inline-block"></div>self.showError(self.errCodes.CALL_ERR, "Failed to get fresh ice config");
<a name="line4024"></a><div class="linenumber">4024</div><div style="width:8em;display:inline-block"></div>}
<a name="line4025"></a><div class="linenumber">4025</div><div style="width:6em;display:inline-block"></div>});
<a name="line4026"></a><div class="linenumber">4026</div><div style="width:4em;display:inline-block"></div>}
<a name="line4027"></a><div class="linenumber">4027</div><div style="width:4em;display:inline-block"></div>else {
<a name="line4028"></a><div class="linenumber">4028</div><div style="width:6em;display:inline-block"></div>doAnswerBody(caller, msgData, streamNames);
<a name="line4029"></a><div class="linenumber">4029</div><div style="width:4em;display:inline-block"></div>}
<a name="line4030"></a><div class="linenumber">4030</div><div style="width:2em;display:inline-block"></div>}
<a name="line4031"></a><div class="linenumber">4031</div>
<a name="line4032"></a><div class="linenumber">4032</div>
<a name="line4033"></a><div class="linenumber">4033</div><div style="width:2em;display:inline-block"></div>/** @private */
<a name="line4034"></a><div class="linenumber">4034</div><div style="width:2em;display:inline-block"></div>function callBody(otherUser, callSuccessCB, callFailureCB, wasAcceptedCB, streamNames) {
<a name="line4035"></a><div class="linenumber">4035</div><div style="width:4em;display:inline-block"></div>acceptancePending[otherUser] = true;
<a name="line4036"></a><div class="linenumber">4036</div><div style="width:4em;display:inline-block"></div>var pc = buildPeerConnection(otherUser, true, callFailureCB, streamNames);
<a name="line4037"></a><div class="linenumber">4037</div><div style="width:4em;display:inline-block"></div>var message;
<a name="line4038"></a><div class="linenumber">4038</div><div style="width:4em;display:inline-block"></div>if (!pc) {
<a name="line4039"></a><div class="linenumber">4039</div><div style="width:6em;display:inline-block"></div>message = "buildPeerConnection failed, call not completed";
<a name="line4040"></a><div class="linenumber">4040</div><div style="width:6em;display:inline-block"></div>logDebug(message);
<a name="line4041"></a><div class="linenumber">4041</div><div style="width:6em;display:inline-block"></div>throw message;
<a name="line4042"></a><div class="linenumber">4042</div><div style="width:4em;display:inline-block"></div>}
<a name="line4043"></a><div class="linenumber">4043</div>
<a name="line4044"></a><div class="linenumber">4044</div><div style="width:4em;display:inline-block"></div>peerConns[otherUser].callSuccessCB = callSuccessCB;
<a name="line4045"></a><div class="linenumber">4045</div><div style="width:4em;display:inline-block"></div>peerConns[otherUser].callFailureCB = callFailureCB;
<a name="line4046"></a><div class="linenumber">4046</div><div style="width:4em;display:inline-block"></div>peerConns[otherUser].wasAcceptedCB = wasAcceptedCB;
<a name="line4047"></a><div class="linenumber">4047</div><div style="width:4em;display:inline-block"></div>var peerConnObj = peerConns[otherUser];
<a name="line4048"></a><div class="linenumber">4048</div><div style="width:4em;display:inline-block"></div>var setLocalAndSendMessage0 = function(sessionDescription) {
<a name="line4049"></a><div class="linenumber">4049</div><div style="width:6em;display:inline-block"></div>if (peerConnObj.cancelled) {
<a name="line4050"></a><div class="linenumber">4050</div><div style="width:8em;display:inline-block"></div>return;
<a name="line4051"></a><div class="linenumber">4051</div><div style="width:6em;display:inline-block"></div>}
<a name="line4052"></a><div class="linenumber">4052</div><div style="width:6em;display:inline-block"></div>var sendOffer = function() {
<a name="line4053"></a><div class="linenumber">4053</div>
<a name="line4054"></a><div class="linenumber">4054</div><div style="width:8em;display:inline-block"></div>sendSignalling(otherUser, "offer", sessionDescription, null, callFailureCB);
<a name="line4055"></a><div class="linenumber">4055</div><div style="width:6em;display:inline-block"></div>};
<a name="line4056"></a><div class="linenumber">4056</div><div style="width:6em;display:inline-block"></div>if (sdpLocalFilter) {
<a name="line4057"></a><div class="linenumber">4057</div><div style="width:8em;display:inline-block"></div>sessionDescription.sdp = sdpLocalFilter(sessionDescription.sdp);
<a name="line4058"></a><div class="linenumber">4058</div><div style="width:6em;display:inline-block"></div>}
<a name="line4059"></a><div class="linenumber">4059</div><div style="width:6em;display:inline-block"></div>pc.setLocalDescription(sessionDescription, sendOffer,
<a name="line4060"></a><div class="linenumber">4060</div><div style="width:10em;display:inline-block"></div>function(errorText) {
<a name="line4061"></a><div class="linenumber">4061</div><div style="width:12em;display:inline-block"></div>callFailureCB(self.errCodes.CALL_ERR, errorText);
<a name="line4062"></a><div class="linenumber">4062</div><div style="width:10em;display:inline-block"></div>});
<a name="line4063"></a><div class="linenumber">4063</div><div style="width:4em;display:inline-block"></div>};
<a name="line4064"></a><div class="linenumber">4064</div><div style="width:4em;display:inline-block"></div>setTimeout(function() {
<a name="line4065"></a><div class="linenumber">4065</div><div style="width:6em;display:inline-block"></div>//
<a name="line4066"></a><div class="linenumber">4066</div><div style="width:6em;display:inline-block"></div>// if the call was cancelled, we don't want to continue getting the offer.
<a name="line4067"></a><div class="linenumber">4067</div><div style="width:6em;display:inline-block"></div>// we can tell the call was cancelled because there won't be a peerConn object
<a name="line4068"></a><div class="linenumber">4068</div><div style="width:6em;display:inline-block"></div>// for it.
<a name="line4069"></a><div class="linenumber">4069</div><div style="width:6em;display:inline-block"></div>//
<a name="line4070"></a><div class="linenumber">4070</div><div style="width:6em;display:inline-block"></div>if( !peerConns[otherUser]) {
<a name="line4071"></a><div class="linenumber">4071</div><div style="width:8em;display:inline-block"></div>return;
<a name="line4072"></a><div class="linenumber">4072</div><div style="width:6em;display:inline-block"></div>}
<a name="line4073"></a><div class="linenumber">4073</div><div style="width:6em;display:inline-block"></div>pc.createOffer(setLocalAndSendMessage0, function(errorObj) {
<a name="line4074"></a><div class="linenumber">4074</div><div style="width:8em;display:inline-block"></div>callFailureCB(self.errCodes.CALL_ERR, JSON.stringify(errorObj));
<a name="line4075"></a><div class="linenumber">4075</div><div style="width:6em;display:inline-block"></div>},
<a name="line4076"></a><div class="linenumber">4076</div><div style="width:10em;display:inline-block"></div>receivedMediaConstraints);
<a name="line4077"></a><div class="linenumber">4077</div><div style="width:4em;display:inline-block"></div>}, 100);
<a name="line4078"></a><div class="linenumber">4078</div><div style="width:2em;display:inline-block"></div>}
<a name="line4079"></a><div class="linenumber">4079</div>
<a name="line4080"></a><div class="linenumber">4080</div><div style="width:2em;display:inline-block"></div>/**
<a name="line4081"></a><div class="linenumber">4081</div><div style="width:2em;display:inline-block"></div>* Initiates a call to another user. If it succeeds, the streamAcceptor callback will be called.
<a name="line4082"></a><div class="linenumber">4082</div><div style="width:2em;display:inline-block"></div>* @param {String} otherUser - the easyrtcid of the peer being called.
<a name="line4083"></a><div class="linenumber">4083</div><div style="width:2em;display:inline-block"></div>* @param {Function} callSuccessCB (otherCaller, mediaType) - is called when the datachannel is established or the MediaStream is established. mediaType will have a value of "audiovideo" or "datachannel"
<a name="line4084"></a><div class="linenumber">4084</div><div style="width:2em;display:inline-block"></div>* @param {Function} callFailureCB (errorCode, errMessage) - is called if there was a system error interfering with the call.
<a name="line4085"></a><div class="linenumber">4085</div><div style="width:2em;display:inline-block"></div>* @param {Function} wasAcceptedCB (wasAccepted:boolean,otherUser:string) - is called when a call is accepted or rejected by another party. It can be left null.
<a name="line4086"></a><div class="linenumber">4086</div><div style="width:2em;display:inline-block"></div>* @param {Array} streamNames - optional array of streamNames.
<a name="line4087"></a><div class="linenumber">4087</div><div style="width:2em;display:inline-block"></div>* @example
<a name="line4088"></a><div class="linenumber">4088</div><div style="width:2em;display:inline-block"></div>* easyrtc.call( otherEasyrtcid,
<a name="line4089"></a><div class="linenumber">4089</div><div style="width:2em;display:inline-block"></div>* function(easyrtcid, mediaType){
<a name="line4090"></a><div class="linenumber">4090</div><div style="width:2em;display:inline-block"></div>* console.log("Got mediaType " + mediaType + " from " + easyrtc.idToName(easyrtcid));
<a name="line4091"></a><div class="linenumber">4091</div><div style="width:2em;display:inline-block"></div>* },
<a name="line4092"></a><div class="linenumber">4092</div><div style="width:2em;display:inline-block"></div>* function(errorCode, errMessage){
<a name="line4093"></a><div class="linenumber">4093</div><div style="width:2em;display:inline-block"></div>* console.log("call to " + easyrtc.idToName(otherEasyrtcid) + " failed:" + errMessage);
<a name="line4094"></a><div class="linenumber">4094</div><div style="width:2em;display:inline-block"></div>* },
<a name="line4095"></a><div class="linenumber">4095</div><div style="width:2em;display:inline-block"></div>* function(wasAccepted, easyrtcid){
<a name="line4096"></a><div class="linenumber">4096</div><div style="width:2em;display:inline-block"></div>* if( wasAccepted ){
<a name="line4097"></a><div class="linenumber">4097</div><div style="width:2em;display:inline-block"></div>* console.log("call accepted by " + easyrtc.idToName(easyrtcid));
<a name="line4098"></a><div class="linenumber">4098</div><div style="width:2em;display:inline-block"></div>* }
<a name="line4099"></a><div class="linenumber">4099</div><div style="width:2em;display:inline-block"></div>* else{
<a name="line4100"></a><div class="linenumber">4100</div><div style="width:2em;display:inline-block"></div>* console.log("call rejected" + easyrtc.idToName(easyrtcid));
<a name="line4101"></a><div class="linenumber">4101</div><div style="width:2em;display:inline-block"></div>* }
<a name="line4102"></a><div class="linenumber">4102</div><div style="width:2em;display:inline-block"></div>* });
<a name="line4103"></a><div class="linenumber">4103</div><div style="width:2em;display:inline-block"></div>*/
<a name="line4104"></a><div class="linenumber">4104</div><div style="width:2em;display:inline-block"></div>this.call = function(otherUser, callSuccessCB, callFailureCB, wasAcceptedCB, streamNames) {
<a name="line4105"></a><div class="linenumber">4105</div>
<a name="line4106"></a><div class="linenumber">4106</div><div style="width:4em;display:inline-block"></div>if (streamNames) {
<a name="line4107"></a><div class="linenumber">4107</div><div style="width:6em;display:inline-block"></div>if (typeof streamNames === "string") { // accept a string argument if passed.
<a name="line4108"></a><div class="linenumber">4108</div><div style="width:8em;display:inline-block"></div>streamNames = [streamNames];
<a name="line4109"></a><div class="linenumber">4109</div><div style="width:6em;display:inline-block"></div>}
<a name="line4110"></a><div class="linenumber">4110</div><div style="width:6em;display:inline-block"></div>else if (typeof streamNames.length === "undefined") {
<a name="line4111"></a><div class="linenumber">4111</div><div style="width:8em;display:inline-block"></div>self.showError(self.errCodes.DEVELOPER_ERR, "easyrtc.call passed bad streamNames");
<a name="line4112"></a><div class="linenumber">4112</div><div style="width:8em;display:inline-block"></div>return;
<a name="line4113"></a><div class="linenumber">4113</div><div style="width:6em;display:inline-block"></div>}
<a name="line4114"></a><div class="linenumber">4114</div><div style="width:4em;display:inline-block"></div>}
<a name="line4115"></a><div class="linenumber">4115</div>
<a name="line4116"></a><div class="linenumber">4116</div><div style="width:4em;display:inline-block"></div>logDebug("initiating peer to peer call to " + otherUser +
<a name="line4117"></a><div class="linenumber">4117</div><div style="width:10em;display:inline-block"></div>" audio=" + self.audioEnabled +
<a name="line4118"></a><div class="linenumber">4118</div><div style="width:10em;display:inline-block"></div>" video=" + self.videoEnabled +
<a name="line4119"></a><div class="linenumber">4119</div><div style="width:10em;display:inline-block"></div>" data=" + dataEnabled);
<a name="line4120"></a><div class="linenumber">4120</div>
<a name="line4121"></a><div class="linenumber">4121</div>
<a name="line4122"></a><div class="linenumber">4122</div><div style="width:4em;display:inline-block"></div>if (!self.supportsPeerConnections()) {
<a name="line4123"></a><div class="linenumber">4123</div><div style="width:6em;display:inline-block"></div>callFailureCB(self.errCodes.CALL_ERR, self.getConstantString("noWebrtcSupport"));
<a name="line4124"></a><div class="linenumber">4124</div><div style="width:6em;display:inline-block"></div>return;
<a name="line4125"></a><div class="linenumber">4125</div><div style="width:4em;display:inline-block"></div>}
<a name="line4126"></a><div class="linenumber">4126</div>
<a name="line4127"></a><div class="linenumber">4127</div><div style="width:4em;display:inline-block"></div>var message;
<a name="line4128"></a><div class="linenumber">4128</div><div style="width:4em;display:inline-block"></div>//
<a name="line4129"></a><div class="linenumber">4129</div><div style="width:4em;display:inline-block"></div>// If we are sharing audio/video and we haven't allocated the local media stream yet,
<a name="line4130"></a><div class="linenumber">4130</div><div style="width:4em;display:inline-block"></div>// we'll do so, recalling our self on success.
<a name="line4131"></a><div class="linenumber">4131</div><div style="width:4em;display:inline-block"></div>//
<a name="line4132"></a><div class="linenumber">4132</div><div style="width:4em;display:inline-block"></div>if (!streamNames && autoInitUserMedia) {
<a name="line4133"></a><div class="linenumber">4133</div><div style="width:6em;display:inline-block"></div>var stream = self.getLocalStream();
<a name="line4134"></a><div class="linenumber">4134</div><div style="width:6em;display:inline-block"></div>if (!stream && (self.audioEnabled || self.videoEnabled)) {
<a name="line4135"></a><div class="linenumber">4135</div><div style="width:8em;display:inline-block"></div>self.initMediaSource(function() {
<a name="line4136"></a><div class="linenumber">4136</div><div style="width:10em;display:inline-block"></div>self.call(otherUser, callSuccessCB, callFailureCB, wasAcceptedCB);
<a name="line4137"></a><div class="linenumber">4137</div><div style="width:8em;display:inline-block"></div>}, callFailureCB);
<a name="line4138"></a><div class="linenumber">4138</div><div style="width:8em;display:inline-block"></div>return;
<a name="line4139"></a><div class="linenumber">4139</div><div style="width:6em;display:inline-block"></div>}
<a name="line4140"></a><div class="linenumber">4140</div><div style="width:4em;display:inline-block"></div>}
<a name="line4141"></a><div class="linenumber">4141</div>
<a name="line4142"></a><div class="linenumber">4142</div><div style="width:4em;display:inline-block"></div>if (!self.webSocket) {
<a name="line4143"></a><div class="linenumber">4143</div><div style="width:6em;display:inline-block"></div>message = "Attempt to make a call prior to connecting to service";
<a name="line4144"></a><div class="linenumber">4144</div><div style="width:6em;display:inline-block"></div>logDebug(message);
<a name="line4145"></a><div class="linenumber">4145</div><div style="width:6em;display:inline-block"></div>throw message;
<a name="line4146"></a><div class="linenumber">4146</div><div style="width:4em;display:inline-block"></div>}
<a name="line4147"></a><div class="linenumber">4147</div>
<a name="line4148"></a><div class="linenumber">4148</div><div style="width:4em;display:inline-block"></div>//
<a name="line4149"></a><div class="linenumber">4149</div><div style="width:4em;display:inline-block"></div>// If B calls A, and then A calls B before accepting, then A should treat the attempt to
<a name="line4150"></a><div class="linenumber">4150</div><div style="width:4em;display:inline-block"></div>// call B as a positive offer to B's offer.
<a name="line4151"></a><div class="linenumber">4151</div><div style="width:4em;display:inline-block"></div>//
<a name="line4152"></a><div class="linenumber">4152</div><div style="width:4em;display:inline-block"></div>if (offersPending[otherUser]) {
<a name="line4153"></a><div class="linenumber">4153</div><div style="width:6em;display:inline-block"></div>wasAcceptedCB(true, otherUser);
<a name="line4154"></a><div class="linenumber">4154</div><div style="width:6em;display:inline-block"></div>doAnswer(otherUser, offersPending[otherUser], streamNames);
<a name="line4155"></a><div class="linenumber">4155</div><div style="width:6em;display:inline-block"></div>delete offersPending[otherUser];
<a name="line4156"></a><div class="linenumber">4156</div><div style="width:6em;display:inline-block"></div>self.callCancelled(otherUser, false);
<a name="line4157"></a><div class="linenumber">4157</div><div style="width:6em;display:inline-block"></div>return;
<a name="line4158"></a><div class="linenumber">4158</div><div style="width:4em;display:inline-block"></div>}
<a name="line4159"></a><div class="linenumber">4159</div>
<a name="line4160"></a><div class="linenumber">4160</div><div style="width:4em;display:inline-block"></div>// do we already have a pending call?
<a name="line4161"></a><div class="linenumber">4161</div><div style="width:4em;display:inline-block"></div>if (typeof acceptancePending[otherUser] !== 'undefined') {
<a name="line4162"></a><div class="linenumber">4162</div><div style="width:6em;display:inline-block"></div>message = "Call already pending acceptance";
<a name="line4163"></a><div class="linenumber">4163</div><div style="width:6em;display:inline-block"></div>logDebug(message);
<a name="line4164"></a><div class="linenumber">4164</div><div style="width:6em;display:inline-block"></div>callFailureCB(self.errCodes.ALREADY_CONNECTED, message);
<a name="line4165"></a><div class="linenumber">4165</div><div style="width:6em;display:inline-block"></div>return;
<a name="line4166"></a><div class="linenumber">4166</div><div style="width:4em;display:inline-block"></div>}
<a name="line4167"></a><div class="linenumber">4167</div>
<a name="line4168"></a><div class="linenumber">4168</div><div style="width:4em;display:inline-block"></div>if (use_fresh_ice_each_peer) {
<a name="line4169"></a><div class="linenumber">4169</div><div style="width:6em;display:inline-block"></div>self.getFreshIceConfig(function(succeeded) {
<a name="line4170"></a><div class="linenumber">4170</div><div style="width:8em;display:inline-block"></div>if (succeeded) {
<a name="line4171"></a><div class="linenumber">4171</div><div style="width:10em;display:inline-block"></div>callBody(otherUser, callSuccessCB, callFailureCB, wasAcceptedCB, streamNames);
<a name="line4172"></a><div class="linenumber">4172</div><div style="width:8em;display:inline-block"></div>}
<a name="line4173"></a><div class="linenumber">4173</div><div style="width:8em;display:inline-block"></div>else {
<a name="line4174"></a><div class="linenumber">4174</div><div style="width:10em;display:inline-block"></div>callFailureCB(self.errCodes.CALL_ERR, "Attempt to get fresh ice configuration failed");
<a name="line4175"></a><div class="linenumber">4175</div><div style="width:8em;display:inline-block"></div>}
<a name="line4176"></a><div class="linenumber">4176</div><div style="width:6em;display:inline-block"></div>});
<a name="line4177"></a><div class="linenumber">4177</div><div style="width:4em;display:inline-block"></div>}
<a name="line4178"></a><div class="linenumber">4178</div><div style="width:4em;display:inline-block"></div>else {
<a name="line4179"></a><div class="linenumber">4179</div><div style="width:6em;display:inline-block"></div>callBody(otherUser, callSuccessCB, callFailureCB, wasAcceptedCB, streamNames);
<a name="line4180"></a><div class="linenumber">4180</div><div style="width:4em;display:inline-block"></div>}
<a name="line4181"></a><div class="linenumber">4181</div><div style="width:2em;display:inline-block"></div>};
<a name="line4182"></a><div class="linenumber">4182</div>
<a name="line4183"></a><div class="linenumber">4183</div><div style="width:2em;display:inline-block"></div>/** @private */
<a name="line4184"></a><div class="linenumber">4184</div><div style="width:2em;display:inline-block"></div>//
<a name="line4185"></a><div class="linenumber">4185</div><div style="width:2em;display:inline-block"></div>// this function check the deprecated MediaStream.ended attribute
<a name="line4186"></a><div class="linenumber">4186</div><div style="width:2em;display:inline-block"></div>// and new .active. Also fallback .enable on track for Firefox.
<a name="line4187"></a><div class="linenumber">4187</div><div style="width:2em;display:inline-block"></div>//
<a name="line4188"></a><div class="linenumber">4188</div><div style="width:2em;display:inline-block"></div>function isStreamActive(stream) {
<a name="line4189"></a><div class="linenumber">4189</div>
<a name="line4190"></a><div class="linenumber">4190</div><div style="width:4em;display:inline-block"></div>var isActive;
<a name="line4191"></a><div class="linenumber">4191</div>
<a name="line4192"></a><div class="linenumber">4192</div><div style="width:4em;display:inline-block"></div>if (stream.active === true || stream.ended === false) {
<a name="line4193"></a><div class="linenumber">4193</div><div style="width:6em;display:inline-block"></div>isActive = true;
<a name="line4194"></a><div class="linenumber">4194</div><div style="width:4em;display:inline-block"></div>} else {
<a name="line4195"></a><div class="linenumber">4195</div><div style="width:6em;display:inline-block"></div>isActive = stream.getTracks().reduce(function (track) {
<a name="line4196"></a><div class="linenumber">4196</div><div style="width:8em;display:inline-block"></div>return track.enabled;
<a name="line4197"></a><div class="linenumber">4197</div><div style="width:6em;display:inline-block"></div>});
<a name="line4198"></a><div class="linenumber">4198</div><div style="width:4em;display:inline-block"></div>}
<a name="line4199"></a><div class="linenumber">4199</div>
<a name="line4200"></a><div class="linenumber">4200</div><div style="width:4em;display:inline-block"></div>return isActive;
<a name="line4201"></a><div class="linenumber">4201</div><div style="width:2em;display:inline-block"></div>}
<a name="line4202"></a><div class="linenumber">4202</div>
<a name="line4203"></a><div class="linenumber">4203</div><div style="width:2em;display:inline-block"></div>/** @private */
<a name="line4204"></a><div class="linenumber">4204</div><div style="width:2em;display:inline-block"></div>var queuedMessages = {};
<a name="line4205"></a><div class="linenumber">4205</div>
<a name="line4206"></a><div class="linenumber">4206</div><div style="width:2em;display:inline-block"></div>/** @private */
<a name="line4207"></a><div class="linenumber">4207</div><div style="width:2em;display:inline-block"></div>function clearQueuedMessages(caller) {
<a name="line4208"></a><div class="linenumber">4208</div><div style="width:4em;display:inline-block"></div>queuedMessages[caller] = {
<a name="line4209"></a><div class="linenumber">4209</div><div style="width:6em;display:inline-block"></div>candidates: []
<a name="line4210"></a><div class="linenumber">4210</div><div style="width:4em;display:inline-block"></div>};
<a name="line4211"></a><div class="linenumber">4211</div><div style="width:2em;display:inline-block"></div>}
<a name="line4212"></a><div class="linenumber">4212</div>
<a name="line4213"></a><div class="linenumber">4213</div><div style="width:2em;display:inline-block"></div>/** @private */
<a name="line4214"></a><div class="linenumber">4214</div><div style="width:2em;display:inline-block"></div>function closePeer(otherUser) {
<a name="line4215"></a><div class="linenumber">4215</div>
<a name="line4216"></a><div class="linenumber">4216</div><div style="width:4em;display:inline-block"></div>if (acceptancePending[otherUser]) {
<a name="line4217"></a><div class="linenumber">4217</div><div style="width:6em;display:inline-block"></div>delete acceptancePending[otherUser];
<a name="line4218"></a><div class="linenumber">4218</div><div style="width:4em;display:inline-block"></div>}
<a name="line4219"></a><div class="linenumber">4219</div><div style="width:4em;display:inline-block"></div>if (offersPending[otherUser]) {
<a name="line4220"></a><div class="linenumber">4220</div><div style="width:6em;display:inline-block"></div>delete offersPending[otherUser];
<a name="line4221"></a><div class="linenumber">4221</div><div style="width:4em;display:inline-block"></div>}
<a name="line4222"></a><div class="linenumber">4222</div>
<a name="line4223"></a><div class="linenumber">4223</div><div style="width:4em;display:inline-block"></div>if (
<a name="line4224"></a><div class="linenumber">4224</div><div style="width:5em;display:inline-block"></div>!peerConns[otherUser].cancelled &&
<a name="line4225"></a><div class="linenumber">4225</div><div style="width:7em;display:inline-block"></div>peerConns[otherUser].pc
<a name="line4226"></a><div class="linenumber">4226</div><div style="width:4em;display:inline-block"></div>) {
<a name="line4227"></a><div class="linenumber">4227</div><div style="width:6em;display:inline-block"></div>try {
<a name="line4228"></a><div class="linenumber">4228</div><div style="width:8em;display:inline-block"></div>var remoteStreams = peerConns[otherUser].pc.getRemoteStreams();
<a name="line4229"></a><div class="linenumber">4229</div><div style="width:8em;display:inline-block"></div>for (var i = 0; i < remoteStreams.length; i++) {
<a name="line4230"></a><div class="linenumber">4230</div><div style="width:10em;display:inline-block"></div>if (isStreamActive(remoteStreams[i])) {
<a name="line4231"></a><div class="linenumber">4231</div><div style="width:12em;display:inline-block"></div>emitOnStreamClosed(otherUser, remoteStreams[i]);
<a name="line4232"></a><div class="linenumber">4232</div><div style="width:12em;display:inline-block"></div>stopStream(remoteStreams[i]);
<a name="line4233"></a><div class="linenumber">4233</div><div style="width:10em;display:inline-block"></div>}
<a name="line4234"></a><div class="linenumber">4234</div><div style="width:8em;display:inline-block"></div>}
<a name="line4235"></a><div class="linenumber">4235</div>
<a name="line4236"></a><div class="linenumber">4236</div><div style="width:8em;display:inline-block"></div>peerConns[otherUser].pc.close();
<a name="line4237"></a><div class="linenumber">4237</div><div style="width:8em;display:inline-block"></div>peerConns[otherUser].cancelled = true;
<a name="line4238"></a><div class="linenumber">4238</div><div style="width:8em;display:inline-block"></div>logDebug("peer closed");
<a name="line4239"></a><div class="linenumber">4239</div><div style="width:6em;display:inline-block"></div>} catch (err) {
<a name="line4240"></a><div class="linenumber">4240</div><div style="width:8em;display:inline-block"></div>logDebug("peer " + otherUser + " close failed:" + err);
<a name="line4241"></a><div class="linenumber">4241</div><div style="width:6em;display:inline-block"></div>} finally {
<a name="line4242"></a><div class="linenumber">4242</div><div style="width:8em;display:inline-block"></div>if (self.onPeerClosed) {
<a name="line4243"></a><div class="linenumber">4243</div><div style="width:10em;display:inline-block"></div>self.onPeerClosed(otherUser);
<a name="line4244"></a><div class="linenumber">4244</div><div style="width:8em;display:inline-block"></div>}
<a name="line4245"></a><div class="linenumber">4245</div><div style="width:6em;display:inline-block"></div>}
<a name="line4246"></a><div class="linenumber">4246</div><div style="width:4em;display:inline-block"></div>}
<a name="line4247"></a><div class="linenumber">4247</div><div style="width:2em;display:inline-block"></div>}
<a name="line4248"></a><div class="linenumber">4248</div>
<a name="line4249"></a><div class="linenumber">4249</div><div style="width:2em;display:inline-block"></div>/** @private */
<a name="line4250"></a><div class="linenumber">4250</div><div style="width:2em;display:inline-block"></div>function hangupBody(otherUser) {
<a name="line4251"></a><div class="linenumber">4251</div>
<a name="line4252"></a><div class="linenumber">4252</div><div style="width:4em;display:inline-block"></div>logDebug("Hanging up on " + otherUser);
<a name="line4253"></a><div class="linenumber">4253</div><div style="width:4em;display:inline-block"></div>clearQueuedMessages(otherUser);
<a name="line4254"></a><div class="linenumber">4254</div>
<a name="line4255"></a><div class="linenumber">4255</div><div style="width:4em;display:inline-block"></div>if (peerConns[otherUser]) {
<a name="line4256"></a><div class="linenumber">4256</div>
<a name="line4257"></a><div class="linenumber">4257</div><div style="width:6em;display:inline-block"></div>if (peerConns[otherUser].pc) {
<a name="line4258"></a><div class="linenumber">4258</div><div style="width:8em;display:inline-block"></div>closePeer(otherUser);
<a name="line4259"></a><div class="linenumber">4259</div><div style="width:6em;display:inline-block"></div>}
<a name="line4260"></a><div class="linenumber">4260</div>
<a name="line4261"></a><div class="linenumber">4261</div><div style="width:6em;display:inline-block"></div>if (peerConns[otherUser]) {
<a name="line4262"></a><div class="linenumber">4262</div><div style="width:8em;display:inline-block"></div>delete peerConns[otherUser];
<a name="line4263"></a><div class="linenumber">4263</div><div style="width:6em;display:inline-block"></div>}
<a name="line4264"></a><div class="linenumber">4264</div>
<a name="line4265"></a><div class="linenumber">4265</div><div style="width:6em;display:inline-block"></div>updateConfigurationInfo();
<a name="line4266"></a><div class="linenumber">4266</div>
<a name="line4267"></a><div class="linenumber">4267</div><div style="width:6em;display:inline-block"></div>if (self.webSocket) {
<a name="line4268"></a><div class="linenumber">4268</div><div style="width:8em;display:inline-block"></div>sendSignalling(otherUser, "hangup", null, function() {
<a name="line4269"></a><div class="linenumber">4269</div><div style="width:10em;display:inline-block"></div>logDebug("hangup succeeds");
<a name="line4270"></a><div class="linenumber">4270</div><div style="width:8em;display:inline-block"></div>}, function(errorCode, errorText) {
<a name="line4271"></a><div class="linenumber">4271</div><div style="width:10em;display:inline-block"></div>logDebug("hangup failed:" + errorText);
<a name="line4272"></a><div class="linenumber">4272</div><div style="width:10em;display:inline-block"></div>self.showError(errorCode, errorText);
<a name="line4273"></a><div class="linenumber">4273</div><div style="width:8em;display:inline-block"></div>});
<a name="line4274"></a><div class="linenumber">4274</div><div style="width:6em;display:inline-block"></div>}
<a name="line4275"></a><div class="linenumber">4275</div><div style="width:4em;display:inline-block"></div>}
<a name="line4276"></a><div class="linenumber">4276</div><div style="width:2em;display:inline-block"></div>}
<a name="line4277"></a><div class="linenumber">4277</div>
<a name="line4278"></a><div class="linenumber">4278</div>
<a name="line4279"></a><div class="linenumber">4279</div>
<a name="line4280"></a><div class="linenumber">4280</div><div style="width:2em;display:inline-block"></div>/**
<a name="line4281"></a><div class="linenumber">4281</div><div style="width:2em;display:inline-block"></div>* Hang up on a particular user or all users.
<a name="line4282"></a><div class="linenumber">4282</div><div style="width:2em;display:inline-block"></div>* @param {String} otherUser - the easyrtcid of the person to hang up on.
<a name="line4283"></a><div class="linenumber">4283</div><div style="width:2em;display:inline-block"></div>* @example
<a name="line4284"></a><div class="linenumber">4284</div><div style="width:2em;display:inline-block"></div>* easyrtc.hangup(someEasyrtcid);
<a name="line4285"></a><div class="linenumber">4285</div><div style="width:2em;display:inline-block"></div>*/
<a name="line4286"></a><div class="linenumber">4286</div><div style="width:2em;display:inline-block"></div>this.hangup = function(otherUser) {
<a name="line4287"></a><div class="linenumber">4287</div><div style="width:4em;display:inline-block"></div>hangupBody(otherUser);
<a name="line4288"></a><div class="linenumber">4288</div><div style="width:4em;display:inline-block"></div>updateConfigurationInfo();
<a name="line4289"></a><div class="linenumber">4289</div><div style="width:2em;display:inline-block"></div>};
<a name="line4290"></a><div class="linenumber">4290</div>
<a name="line4291"></a><div class="linenumber">4291</div><div style="width:2em;display:inline-block"></div>/**
<a name="line4292"></a><div class="linenumber">4292</div><div style="width:2em;display:inline-block"></div>* Hangs up on all current connections.
<a name="line4293"></a><div class="linenumber">4293</div><div style="width:2em;display:inline-block"></div>* @example
<a name="line4294"></a><div class="linenumber">4294</div><div style="width:2em;display:inline-block"></div>* easyrtc.hangupAll();
<a name="line4295"></a><div class="linenumber">4295</div><div style="width:2em;display:inline-block"></div>*/
<a name="line4296"></a><div class="linenumber">4296</div><div style="width:2em;display:inline-block"></div>this.hangupAll = function() {
<a name="line4297"></a><div class="linenumber">4297</div>
<a name="line4298"></a><div class="linenumber">4298</div><div style="width:4em;display:inline-block"></div>var sawAConnection = false;
<a name="line4299"></a><div class="linenumber">4299</div><div style="width:4em;display:inline-block"></div>for (var otherUser in peerConns) {
<a name="line4300"></a><div class="linenumber">4300</div><div style="width:6em;display:inline-block"></div>if (!peerConns.hasOwnProperty(otherUser)) {
<a name="line4301"></a><div class="linenumber">4301</div><div style="width:8em;display:inline-block"></div>continue;
<a name="line4302"></a><div class="linenumber">4302</div><div style="width:6em;display:inline-block"></div>}
<a name="line4303"></a><div class="linenumber">4303</div><div style="width:6em;display:inline-block"></div>sawAConnection = true;
<a name="line4304"></a><div class="linenumber">4304</div><div style="width:6em;display:inline-block"></div>hangupBody(otherUser);
<a name="line4305"></a><div class="linenumber">4305</div><div style="width:4em;display:inline-block"></div>}
<a name="line4306"></a><div class="linenumber">4306</div>
<a name="line4307"></a><div class="linenumber">4307</div><div style="width:4em;display:inline-block"></div>if (sawAConnection) {
<a name="line4308"></a><div class="linenumber">4308</div><div style="width:6em;display:inline-block"></div>updateConfigurationInfo();
<a name="line4309"></a><div class="linenumber">4309</div><div style="width:4em;display:inline-block"></div>}
<a name="line4310"></a><div class="linenumber">4310</div><div style="width:2em;display:inline-block"></div>};
<a name="line4311"></a><div class="linenumber">4311</div>
<a name="line4312"></a><div class="linenumber">4312</div><div style="width:2em;display:inline-block"></div>/**
<a name="line4313"></a><div class="linenumber">4313</div><div style="width:2em;display:inline-block"></div>* Checks to see if data channels work between two peers.
<a name="line4314"></a><div class="linenumber">4314</div><div style="width:2em;display:inline-block"></div>* @param {String} otherUser - the other peer.
<a name="line4315"></a><div class="linenumber">4315</div><div style="width:2em;display:inline-block"></div>* @returns {Boolean} true if data channels work and are ready to be used
<a name="line4316"></a><div class="linenumber">4316</div><div style="width:2em;display:inline-block"></div>* between the two peers.
<a name="line4317"></a><div class="linenumber">4317</div><div style="width:2em;display:inline-block"></div>*/
<a name="line4318"></a><div class="linenumber">4318</div><div style="width:2em;display:inline-block"></div>this.doesDataChannelWork = function(otherUser) {
<a name="line4319"></a><div class="linenumber">4319</div><div style="width:4em;display:inline-block"></div>if (!peerConns[otherUser]) {
<a name="line4320"></a><div class="linenumber">4320</div><div style="width:6em;display:inline-block"></div>return false;
<a name="line4321"></a><div class="linenumber">4321</div><div style="width:4em;display:inline-block"></div>}
<a name="line4322"></a><div class="linenumber">4322</div><div style="width:4em;display:inline-block"></div>return !!peerConns[otherUser].dataChannelReady;
<a name="line4323"></a><div class="linenumber">4323</div><div style="width:2em;display:inline-block"></div>};
<a name="line4324"></a><div class="linenumber">4324</div>
<a name="line4325"></a><div class="linenumber">4325</div><div style="width:2em;display:inline-block"></div>/**
<a name="line4326"></a><div class="linenumber">4326</div><div style="width:2em;display:inline-block"></div>* Return the media stream shared by a particular peer. This is needed when you
<a name="line4327"></a><div class="linenumber">4327</div><div style="width:2em;display:inline-block"></div>* add a stream in the middle of a call.
<a name="line4328"></a><div class="linenumber">4328</div><div style="width:2em;display:inline-block"></div>* @param {String} easyrtcid the peer.
<a name="line4329"></a><div class="linenumber">4329</div><div style="width:2em;display:inline-block"></div>* @param {String} remoteStreamName an optional argument supplying the streamName.
<a name="line4330"></a><div class="linenumber">4330</div><div style="width:2em;display:inline-block"></div>* @returns {Object} A mediaStream.
<a name="line4331"></a><div class="linenumber">4331</div><div style="width:2em;display:inline-block"></div>*/
<a name="line4332"></a><div class="linenumber">4332</div><div style="width:2em;display:inline-block"></div>this.getRemoteStream = function(easyrtcid, remoteStreamName) {
<a name="line4333"></a><div class="linenumber">4333</div><div style="width:4em;display:inline-block"></div>if (!peerConns[easyrtcid]) {
<a name="line4334"></a><div class="linenumber">4334</div><div style="width:6em;display:inline-block"></div>self.showError(self.errCodes.DEVELOPER_ERR, "attempt to get stream of uncalled party");
<a name="line4335"></a><div class="linenumber">4335</div><div style="width:6em;display:inline-block"></div>throw "Developer err: no such stream";
<a name="line4336"></a><div class="linenumber">4336</div><div style="width:4em;display:inline-block"></div>}
<a name="line4337"></a><div class="linenumber">4337</div><div style="width:4em;display:inline-block"></div>else {
<a name="line4338"></a><div class="linenumber">4338</div><div style="width:6em;display:inline-block"></div>return getRemoteStreamByName(peerConns[easyrtcid], easyrtcid, remoteStreamName);
<a name="line4339"></a><div class="linenumber">4339</div><div style="width:4em;display:inline-block"></div>}
<a name="line4340"></a><div class="linenumber">4340</div><div style="width:2em;display:inline-block"></div>};
<a name="line4341"></a><div class="linenumber">4341</div>
<a name="line4342"></a><div class="linenumber">4342</div><div style="width:2em;display:inline-block"></div>/**
<a name="line4343"></a><div class="linenumber">4343</div><div style="width:2em;display:inline-block"></div>* Assign a local streamName to a remote stream so that it can be forwarded to other callers.
<a name="line4344"></a><div class="linenumber">4344</div><div style="width:2em;display:inline-block"></div>* @param {String} easyrtcid the peer supplying the remote stream
<a name="line4345"></a><div class="linenumber">4345</div><div style="width:2em;display:inline-block"></div>* @param {String} remoteStreamName the streamName supplied by the peer.
<a name="line4346"></a><div class="linenumber">4346</div><div style="width:2em;display:inline-block"></div>* @param {String} localStreamName streamName used when passing the stream to other peers.
<a name="line4347"></a><div class="linenumber">4347</div><div style="width:2em;display:inline-block"></div>* @example
<a name="line4348"></a><div class="linenumber">4348</div><div style="width:2em;display:inline-block"></div>* easyrtc.makeLocalStreamFromRemoteStream(sourcePeer, "default", "forwardedStream");
<a name="line4349"></a><div class="linenumber">4349</div><div style="width:2em;display:inline-block"></div>* easyrtc.call(nextPeer, callSuccessCB, callFailureCB, wasAcceptedCB, ["forwardedStream"]);
<a name="line4350"></a><div class="linenumber">4350</div><div style="width:2em;display:inline-block"></div>*/
<a name="line4351"></a><div class="linenumber">4351</div><div style="width:2em;display:inline-block"></div>this.makeLocalStreamFromRemoteStream = function(easyrtcid, remoteStreamName, localStreamName) {
<a name="line4352"></a><div class="linenumber">4352</div><div style="width:4em;display:inline-block"></div>var remoteStream;
<a name="line4353"></a><div class="linenumber">4353</div><div style="width:4em;display:inline-block"></div>if (peerConns[easyrtcid].pc) {
<a name="line4354"></a><div class="linenumber">4354</div><div style="width:6em;display:inline-block"></div>remoteStream = getRemoteStreamByName(peerConns[easyrtcid], easyrtcid, remoteStreamName);
<a name="line4355"></a><div class="linenumber">4355</div><div style="width:6em;display:inline-block"></div>if (remoteStream) {
<a name="line4356"></a><div class="linenumber">4356</div><div style="width:8em;display:inline-block"></div>registerLocalMediaStreamByName(remoteStream, localStreamName);
<a name="line4357"></a><div class="linenumber">4357</div><div style="width:6em;display:inline-block"></div>}
<a name="line4358"></a><div class="linenumber">4358</div><div style="width:6em;display:inline-block"></div>else {
<a name="line4359"></a><div class="linenumber">4359</div><div style="width:8em;display:inline-block"></div>throw "Developer err: no such stream";
<a name="line4360"></a><div class="linenumber">4360</div><div style="width:6em;display:inline-block"></div>}
<a name="line4361"></a><div class="linenumber">4361</div><div style="width:4em;display:inline-block"></div>}
<a name="line4362"></a><div class="linenumber">4362</div><div style="width:4em;display:inline-block"></div>else {
<a name="line4363"></a><div class="linenumber">4363</div><div style="width:6em;display:inline-block"></div>throw "Developer err: no such peer ";
<a name="line4364"></a><div class="linenumber">4364</div><div style="width:4em;display:inline-block"></div>}
<a name="line4365"></a><div class="linenumber">4365</div><div style="width:2em;display:inline-block"></div>};
<a name="line4366"></a><div class="linenumber">4366</div>
<a name="line4367"></a><div class="linenumber">4367</div><div style="width:2em;display:inline-block"></div>/**
<a name="line4368"></a><div class="linenumber">4368</div><div style="width:2em;display:inline-block"></div>* Add a named local stream to a call.
<a name="line4369"></a><div class="linenumber">4369</div><div style="width:2em;display:inline-block"></div>* @param {String} easyrtcId The id of client receiving the stream.
<a name="line4370"></a><div class="linenumber">4370</div><div style="width:2em;display:inline-block"></div>* @param {String} streamName The name of the stream.
<a name="line4371"></a><div class="linenumber">4371</div><div style="width:2em;display:inline-block"></div>* @param {Function} receiptHandler is a function that gets called when the other side sends a message
<a name="line4372"></a><div class="linenumber">4372</div><div style="width:2em;display:inline-block"></div>* that the stream has been received. The receiptHandler gets called with an easyrtcid and a stream name. This
<a name="line4373"></a><div class="linenumber">4373</div><div style="width:2em;display:inline-block"></div>* argument is optional.
<a name="line4374"></a><div class="linenumber">4374</div><div style="width:2em;display:inline-block"></div>*/
<a name="line4375"></a><div class="linenumber">4375</div><div style="width:2em;display:inline-block"></div>this.addStreamToCall = function(easyrtcId, streamName, receiptHandler) {
<a name="line4376"></a><div class="linenumber">4376</div><div style="width:4em;display:inline-block"></div>if( !streamName) {
<a name="line4377"></a><div class="linenumber">4377</div><div style="width:6em;display:inline-block"></div>streamName = "default";
<a name="line4378"></a><div class="linenumber">4378</div><div style="width:4em;display:inline-block"></div>}
<a name="line4379"></a><div class="linenumber">4379</div><div style="width:4em;display:inline-block"></div>var stream = getLocalMediaStreamByName(streamName);
<a name="line4380"></a><div class="linenumber">4380</div><div style="width:4em;display:inline-block"></div>if (!stream) {
<a name="line4381"></a><div class="linenumber">4381</div><div style="width:6em;display:inline-block"></div>logDebug("attempt to add nonexistent stream " + streamName);
<a name="line4382"></a><div class="linenumber">4382</div><div style="width:4em;display:inline-block"></div>}
<a name="line4383"></a><div class="linenumber">4383</div><div style="width:4em;display:inline-block"></div>else if (!peerConns[easyrtcId] || !peerConns[easyrtcId].pc) {
<a name="line4384"></a><div class="linenumber">4384</div><div style="width:6em;display:inline-block"></div>logDebug("Can't add stream before a call has started.");
<a name="line4385"></a><div class="linenumber">4385</div><div style="width:4em;display:inline-block"></div>}
<a name="line4386"></a><div class="linenumber">4386</div><div style="width:4em;display:inline-block"></div>else {
<a name="line4387"></a><div class="linenumber">4387</div><div style="width:6em;display:inline-block"></div>var pc = peerConns[easyrtcId].pc;
<a name="line4388"></a><div class="linenumber">4388</div><div style="width:6em;display:inline-block"></div>peerConns[easyrtcId].enableNegotiateListener = true;
<a name="line4389"></a><div class="linenumber">4389</div><div style="width:6em;display:inline-block"></div>pc.addStream(stream);
<a name="line4390"></a><div class="linenumber">4390</div><div style="width:6em;display:inline-block"></div>if (receiptHandler) {
<a name="line4391"></a><div class="linenumber">4391</div><div style="width:8em;display:inline-block"></div>peerConns[easyrtcId].streamsAddedAcks[streamName] = receiptHandler;
<a name="line4392"></a><div class="linenumber">4392</div><div style="width:6em;display:inline-block"></div>}
<a name="line4393"></a><div class="linenumber">4393</div><div style="width:4em;display:inline-block"></div>}
<a name="line4394"></a><div class="linenumber">4394</div><div style="width:2em;display:inline-block"></div>};
<a name="line4395"></a><div class="linenumber">4395</div>
<a name="line4396"></a><div class="linenumber">4396</div><div style="width:2em;display:inline-block"></div>//
<a name="line4397"></a><div class="linenumber">4397</div><div style="width:2em;display:inline-block"></div>// these three listeners support the ability to add/remove additional media streams on the fly.
<a name="line4398"></a><div class="linenumber">4398</div><div style="width:2em;display:inline-block"></div>//
<a name="line4399"></a><div class="linenumber">4399</div><div style="width:2em;display:inline-block"></div>this.setPeerListener(function(easyrtcid, msgType, msgData) {
<a name="line4400"></a><div class="linenumber">4400</div><div style="width:4em;display:inline-block"></div>if (!peerConns[easyrtcid] || !peerConns[easyrtcid].pc) {
<a name="line4401"></a><div class="linenumber">4401</div><div style="width:6em;display:inline-block"></div>self.showError(self.errCodes.DEVELOPER_ERR,
<a name="line4402"></a><div class="linenumber">4402</div><div style="width:9em;display:inline-block"></div>"Attempt to add additional stream before establishing the base call.");
<a name="line4403"></a><div class="linenumber">4403</div><div style="width:4em;display:inline-block"></div>}
<a name="line4404"></a><div class="linenumber">4404</div><div style="width:4em;display:inline-block"></div>else {
<a name="line4405"></a><div class="linenumber">4405</div><div style="width:6em;display:inline-block"></div>var sdp = msgData.sdp;
<a name="line4406"></a><div class="linenumber">4406</div><div style="width:6em;display:inline-block"></div>var pc = peerConns[easyrtcid].pc;
<a name="line4407"></a><div class="linenumber">4407</div>
<a name="line4408"></a><div class="linenumber">4408</div><div style="width:6em;display:inline-block"></div>var setLocalAndSendMessage1 = function(sessionDescription) {
<a name="line4409"></a><div class="linenumber">4409</div><div style="width:8em;display:inline-block"></div>var sendAnswer = function() {
<a name="line4410"></a><div class="linenumber">4410</div><div style="width:9em;display:inline-block"></div>logDebug("sending answer");
<a name="line4411"></a><div class="linenumber">4411</div>
<a name="line4412"></a><div class="linenumber">4412</div><div style="width:9em;display:inline-block"></div>function onSignalSuccess() {
<a name="line4413"></a><div class="linenumber">4413</div><div style="width:12em;display:inline-block"></div>logDebug("sending answer succeeded");
<a name="line4414"></a><div class="linenumber">4414</div>
<a name="line4415"></a><div class="linenumber">4415</div><div style="width:9em;display:inline-block"></div>}
<a name="line4416"></a><div class="linenumber">4416</div>
<a name="line4417"></a><div class="linenumber">4417</div><div style="width:9em;display:inline-block"></div>function onSignalFailure(errorCode, errorText) {
<a name="line4418"></a><div class="linenumber">4418</div><div style="width:12em;display:inline-block"></div>logDebug("sending answer failed");
<a name="line4419"></a><div class="linenumber">4419</div>
<a name="line4420"></a><div class="linenumber">4420</div><div style="width:11em;display:inline-block"></div>delete peerConns[easyrtcid];
<a name="line4421"></a><div class="linenumber">4421</div><div style="width:11em;display:inline-block"></div>self.showError(errorCode, errorText);
<a name="line4422"></a><div class="linenumber">4422</div><div style="width:9em;display:inline-block"></div>}
<a name="line4423"></a><div class="linenumber">4423</div>
<a name="line4424"></a><div class="linenumber">4424</div><div style="width:9em;display:inline-block"></div>sendSignalling(easyrtcid, "answer", sessionDescription,
<a name="line4425"></a><div class="linenumber">4425</div><div style="width:13em;display:inline-block"></div>onSignalSuccess, onSignalFailure);
<a name="line4426"></a><div class="linenumber">4426</div><div style="width:9em;display:inline-block"></div>peerConns[easyrtcid].connectionAccepted = true;
<a name="line4427"></a><div class="linenumber">4427</div><div style="width:9em;display:inline-block"></div>sendQueuedCandidates(easyrtcid, onSignalSuccess, onSignalFailure);
<a name="line4428"></a><div class="linenumber">4428</div><div style="width:7em;display:inline-block"></div>};
<a name="line4429"></a><div class="linenumber">4429</div>
<a name="line4430"></a><div class="linenumber">4430</div><div style="width:7em;display:inline-block"></div>if (sdpLocalFilter) {
<a name="line4431"></a><div class="linenumber">4431</div><div style="width:9em;display:inline-block"></div>sessionDescription.sdp = sdpLocalFilter(sessionDescription.sdp);
<a name="line4432"></a><div class="linenumber">4432</div><div style="width:7em;display:inline-block"></div>}
<a name="line4433"></a><div class="linenumber">4433</div><div style="width:7em;display:inline-block"></div>pc.setLocalDescription(sessionDescription, sendAnswer, function(message) {
<a name="line4434"></a><div class="linenumber">4434</div><div style="width:9em;display:inline-block"></div>self.showError(self.errCodes.INTERNAL_ERR, "setLocalDescription: " + msgData);
<a name="line4435"></a><div class="linenumber">4435</div><div style="width:7em;display:inline-block"></div>});
<a name="line4436"></a><div class="linenumber">4436</div><div style="width:6em;display:inline-block"></div>};
<a name="line4437"></a><div class="linenumber">4437</div>
<a name="line4438"></a><div class="linenumber">4438</div><div style="width:6em;display:inline-block"></div>var invokeCreateAnswer = function() {
<a name="line4439"></a><div class="linenumber">4439</div><div style="width:7em;display:inline-block"></div>pc.createAnswer(setLocalAndSendMessage1,
<a name="line4440"></a><div class="linenumber">4440</div><div style="width:10em;display:inline-block"></div>function(message) {
<a name="line4441"></a><div class="linenumber">4441</div><div style="width:12em;display:inline-block"></div>self.showError(self.errCodes.INTERNAL_ERR, "create-answer: " + message);
<a name="line4442"></a><div class="linenumber">4442</div><div style="width:10em;display:inline-block"></div>},
<a name="line4443"></a><div class="linenumber">4443</div><div style="width:10em;display:inline-block"></div>receivedMediaConstraints);
<a name="line4444"></a><div class="linenumber">4444</div><div style="width:7em;display:inline-block"></div>self.sendPeerMessage(easyrtcid, "__gotAddedMediaStream", {sdp: sdp});
<a name="line4445"></a><div class="linenumber">4445</div><div style="width:6em;display:inline-block"></div>};
<a name="line4446"></a><div class="linenumber">4446</div>
<a name="line4447"></a><div class="linenumber">4447</div><div style="width:6em;display:inline-block"></div>logDebug("about to call setRemoteDescription in doAnswer");
<a name="line4448"></a><div class="linenumber">4448</div>
<a name="line4449"></a><div class="linenumber">4449</div><div style="width:6em;display:inline-block"></div>try {
<a name="line4450"></a><div class="linenumber">4450</div>
<a name="line4451"></a><div class="linenumber">4451</div><div style="width:8em;display:inline-block"></div>if (sdpRemoteFilter) {
<a name="line4452"></a><div class="linenumber">4452</div><div style="width:10em;display:inline-block"></div>sdp.sdp = sdpRemoteFilter(sdp.sdp);
<a name="line4453"></a><div class="linenumber">4453</div><div style="width:8em;display:inline-block"></div>}
<a name="line4454"></a><div class="linenumber">4454</div><div style="width:8em;display:inline-block"></div>pc.setRemoteDescription(new RTCSessionDescription(sdp),
<a name="line4455"></a><div class="linenumber">4455</div><div style="width:9em;display:inline-block"></div>invokeCreateAnswer, function(message) {
<a name="line4456"></a><div class="linenumber">4456</div><div style="width:10em;display:inline-block"></div>self.showError(self.errCodes.INTERNAL_ERR, "set-remote-description: " + message);
<a name="line4457"></a><div class="linenumber">4457</div><div style="width:8em;display:inline-block"></div>});
<a name="line4458"></a><div class="linenumber">4458</div><div style="width:6em;display:inline-block"></div>} catch (srdError) {
<a name="line4459"></a><div class="linenumber">4459</div><div style="width:8em;display:inline-block"></div>logDebug("saw exception in setRemoteDescription", srdError);
<a name="line4460"></a><div class="linenumber">4460</div><div style="width:8em;display:inline-block"></div>self.showError(self.errCodes.INTERNAL_ERR, "setRemoteDescription failed: " + srdError.message);
<a name="line4461"></a><div class="linenumber">4461</div><div style="width:6em;display:inline-block"></div>}
<a name="line4462"></a><div class="linenumber">4462</div><div style="width:4em;display:inline-block"></div>}
<a name="line4463"></a><div class="linenumber">4463</div><div style="width:2em;display:inline-block"></div>}, "__addedMediaStream");
<a name="line4464"></a><div class="linenumber">4464</div>
<a name="line4465"></a><div class="linenumber">4465</div><div style="width:2em;display:inline-block"></div>this.setPeerListener(function(easyrtcid, msgType, msgData) {
<a name="line4466"></a><div class="linenumber">4466</div><div style="width:4em;display:inline-block"></div>if (!peerConns[easyrtcid] || !peerConns[easyrtcid].pc) {
<a name="line4467"></a><div class="linenumber">4467</div><div style="width:6em;display:inline-block"></div>logDebug("setPeerListener failed: __gotAddedMediaStream Unknow easyrtcid " + easyrtcid);
<a name="line4468"></a><div class="linenumber">4468</div><div style="width:4em;display:inline-block"></div>}
<a name="line4469"></a><div class="linenumber">4469</div><div style="width:4em;display:inline-block"></div>else {
<a name="line4470"></a><div class="linenumber">4470</div><div style="width:6em;display:inline-block"></div>var sdp = msgData.sdp;
<a name="line4471"></a><div class="linenumber">4471</div><div style="width:6em;display:inline-block"></div>if (sdpRemoteFilter) {
<a name="line4472"></a><div class="linenumber">4472</div><div style="width:8em;display:inline-block"></div>sdp.sdp = sdpRemoteFilter(sdp.sdp);
<a name="line4473"></a><div class="linenumber">4473</div><div style="width:6em;display:inline-block"></div>}
<a name="line4474"></a><div class="linenumber">4474</div><div style="width:6em;display:inline-block"></div>var pc = peerConns[easyrtcid].pc;
<a name="line4475"></a><div class="linenumber">4475</div><div style="width:6em;display:inline-block"></div>pc.setRemoteDescription(new RTCSessionDescription(sdp), function(){},
<a name="line4476"></a><div class="linenumber">4476</div><div style="width:10em;display:inline-block"></div>function(message) {
<a name="line4477"></a><div class="linenumber">4477</div><div style="width:11em;display:inline-block"></div>self.showError(self.errCodes.INTERNAL_ERR, "set-remote-description: " + message);
<a name="line4478"></a><div class="linenumber">4478</div><div style="width:10em;display:inline-block"></div>});
<a name="line4479"></a><div class="linenumber">4479</div><div style="width:4em;display:inline-block"></div>}
<a name="line4480"></a><div class="linenumber">4480</div>
<a name="line4481"></a><div class="linenumber">4481</div><div style="width:2em;display:inline-block"></div>}, "__gotAddedMediaStream");
<a name="line4482"></a><div class="linenumber">4482</div>
<a name="line4483"></a><div class="linenumber">4483</div><div style="width:2em;display:inline-block"></div>this.setPeerListener(function(easyrtcid, msgType, msgData) {
<a name="line4484"></a><div class="linenumber">4484</div><div style="width:4em;display:inline-block"></div>if (!peerConns[easyrtcid] || !peerConns[easyrtcid].pc) {
<a name="line4485"></a><div class="linenumber">4485</div><div style="width:6em;display:inline-block"></div>logDebug("setPeerListener failed: __closingMediaStream Unknow easyrtcid " + easyrtcid);
<a name="line4486"></a><div class="linenumber">4486</div><div style="width:4em;display:inline-block"></div>}
<a name="line4487"></a><div class="linenumber">4487</div><div style="width:4em;display:inline-block"></div>else {
<a name="line4488"></a><div class="linenumber">4488</div><div style="width:6em;display:inline-block"></div>var stream = getRemoteStreamByName(peerConns[easyrtcid], easyrtcid, msgData.streamName);
<a name="line4489"></a><div class="linenumber">4489</div><div style="width:6em;display:inline-block"></div>if (stream) {
<a name="line4490"></a><div class="linenumber">4490</div><div style="width:8em;display:inline-block"></div>onRemoveStreamHelper(easyrtcid, stream);
<a name="line4491"></a><div class="linenumber">4491</div><div style="width:8em;display:inline-block"></div>stopStream(stream);
<a name="line4492"></a><div class="linenumber">4492</div><div style="width:6em;display:inline-block"></div>}
<a name="line4493"></a><div class="linenumber">4493</div><div style="width:4em;display:inline-block"></div>}
<a name="line4494"></a><div class="linenumber">4494</div>
<a name="line4495"></a><div class="linenumber">4495</div><div style="width:2em;display:inline-block"></div>}, "__closingMediaStream");
<a name="line4496"></a><div class="linenumber">4496</div>
<a name="line4497"></a><div class="linenumber">4497</div><div style="width:2em;display:inline-block"></div>/** @private */
<a name="line4498"></a><div class="linenumber">4498</div><div style="width:2em;display:inline-block"></div>this.dumpPeerConnectionInfo = function() {
<a name="line4499"></a><div class="linenumber">4499</div><div style="width:4em;display:inline-block"></div>var i;
<a name="line4500"></a><div class="linenumber">4500</div><div style="width:4em;display:inline-block"></div>for (var peer in peerConns) {
<a name="line4501"></a><div class="linenumber">4501</div><div style="width:6em;display:inline-block"></div>if (peerConns.hasOwnProperty(peer)) {
<a name="line4502"></a><div class="linenumber">4502</div><div style="width:8em;display:inline-block"></div>var pc = peerConns[peer].pc;
<a name="line4503"></a><div class="linenumber">4503</div><div style="width:8em;display:inline-block"></div>var remotes = pc.getRemoteStreams();
<a name="line4504"></a><div class="linenumber">4504</div><div style="width:8em;display:inline-block"></div>var remoteIds = [];
<a name="line4505"></a><div class="linenumber">4505</div><div style="width:8em;display:inline-block"></div>for (i = 0; i < remotes.length; i++) {
<a name="line4506"></a><div class="linenumber">4506</div><div style="width:10em;display:inline-block"></div>remoteIds.push(remotes[i].id);
<a name="line4507"></a><div class="linenumber">4507</div><div style="width:8em;display:inline-block"></div>}
<a name="line4508"></a><div class="linenumber">4508</div><div style="width:8em;display:inline-block"></div>var locals = pc.getLocalStreams();
<a name="line4509"></a><div class="linenumber">4509</div><div style="width:8em;display:inline-block"></div>var localIds = [];
<a name="line4510"></a><div class="linenumber">4510</div><div style="width:8em;display:inline-block"></div>for (i = 0; i < locals.length; i++) {
<a name="line4511"></a><div class="linenumber">4511</div><div style="width:10em;display:inline-block"></div>localIds.push(locals[i].id);
<a name="line4512"></a><div class="linenumber">4512</div><div style="width:8em;display:inline-block"></div>}
<a name="line4513"></a><div class="linenumber">4513</div>
<a name="line4514"></a><div class="linenumber">4514</div><div style="width:8em;display:inline-block"></div>logDebug("For peer " + peer);
<a name="line4515"></a><div class="linenumber">4515</div><div style="width:8em;display:inline-block"></div>logDebug(" " + JSON.stringify({local: localIds, remote: remoteIds}));
<a name="line4516"></a><div class="linenumber">4516</div><div style="width:6em;display:inline-block"></div>}
<a name="line4517"></a><div class="linenumber">4517</div><div style="width:4em;display:inline-block"></div>}
<a name="line4518"></a><div class="linenumber">4518</div><div style="width:2em;display:inline-block"></div>};
<a name="line4519"></a><div class="linenumber">4519</div>
<a name="line4520"></a><div class="linenumber">4520</div><div style="width:2em;display:inline-block"></div>/** @private */
<a name="line4521"></a><div class="linenumber">4521</div><div style="width:2em;display:inline-block"></div>function onRemoteHangup(otherUser) {
<a name="line4522"></a><div class="linenumber">4522</div>
<a name="line4523"></a><div class="linenumber">4523</div><div style="width:4em;display:inline-block"></div>logDebug("Saw onRemote hangup event");
<a name="line4524"></a><div class="linenumber">4524</div><div style="width:4em;display:inline-block"></div>clearQueuedMessages(otherUser);
<a name="line4525"></a><div class="linenumber">4525</div>
<a name="line4526"></a><div class="linenumber">4526</div><div style="width:4em;display:inline-block"></div>if (peerConns[otherUser]) {
<a name="line4527"></a><div class="linenumber">4527</div>
<a name="line4528"></a><div class="linenumber">4528</div><div style="width:6em;display:inline-block"></div>if (peerConns[otherUser].pc) {
<a name="line4529"></a><div class="linenumber">4529</div><div style="width:8em;display:inline-block"></div>closePeer(otherUser);
<a name="line4530"></a><div class="linenumber">4530</div><div style="width:6em;display:inline-block"></div>}
<a name="line4531"></a><div class="linenumber">4531</div><div style="width:6em;display:inline-block"></div>else {
<a name="line4532"></a><div class="linenumber">4532</div><div style="width:8em;display:inline-block"></div>if (self.callCancelled) {
<a name="line4533"></a><div class="linenumber">4533</div><div style="width:10em;display:inline-block"></div>self.callCancelled(otherUser, true);
<a name="line4534"></a><div class="linenumber">4534</div><div style="width:8em;display:inline-block"></div>}
<a name="line4535"></a><div class="linenumber">4535</div><div style="width:6em;display:inline-block"></div>}
<a name="line4536"></a><div class="linenumber">4536</div>
<a name="line4537"></a><div class="linenumber">4537</div><div style="width:6em;display:inline-block"></div>if (peerConns[otherUser]) {
<a name="line4538"></a><div class="linenumber">4538</div><div style="width:8em;display:inline-block"></div>delete peerConns[otherUser];
<a name="line4539"></a><div class="linenumber">4539</div><div style="width:6em;display:inline-block"></div>}
<a name="line4540"></a><div class="linenumber">4540</div><div style="width:4em;display:inline-block"></div>}
<a name="line4541"></a><div class="linenumber">4541</div><div style="width:4em;display:inline-block"></div>else {
<a name="line4542"></a><div class="linenumber">4542</div><div style="width:6em;display:inline-block"></div>if (self.callCancelled) {
<a name="line4543"></a><div class="linenumber">4543</div><div style="width:8em;display:inline-block"></div>self.callCancelled(otherUser, true);
<a name="line4544"></a><div class="linenumber">4544</div><div style="width:6em;display:inline-block"></div>}
<a name="line4545"></a><div class="linenumber">4545</div><div style="width:4em;display:inline-block"></div>}
<a name="line4546"></a><div class="linenumber">4546</div><div style="width:2em;display:inline-block"></div>}
<a name="line4547"></a><div class="linenumber">4547</div>
<a name="line4548"></a><div class="linenumber">4548</div><div style="width:2em;display:inline-block"></div>/** @private */
<a name="line4549"></a><div class="linenumber">4549</div><div style="width:2em;display:inline-block"></div>//
<a name="line4550"></a><div class="linenumber">4550</div><div style="width:2em;display:inline-block"></div>// checks to see if a particular peer is in any room at all.
<a name="line4551"></a><div class="linenumber">4551</div><div style="width:2em;display:inline-block"></div>//
<a name="line4552"></a><div class="linenumber">4552</div><div style="width:2em;display:inline-block"></div>function isPeerInAnyRoom(id) {
<a name="line4553"></a><div class="linenumber">4553</div><div style="width:4em;display:inline-block"></div>var roomName;
<a name="line4554"></a><div class="linenumber">4554</div><div style="width:4em;display:inline-block"></div>for (roomName in lastLoggedInList) {
<a name="line4555"></a><div class="linenumber">4555</div><div style="width:6em;display:inline-block"></div>if (!lastLoggedInList.hasOwnProperty(roomName)) {
<a name="line4556"></a><div class="linenumber">4556</div><div style="width:8em;display:inline-block"></div>continue;
<a name="line4557"></a><div class="linenumber">4557</div><div style="width:6em;display:inline-block"></div>}
<a name="line4558"></a><div class="linenumber">4558</div><div style="width:6em;display:inline-block"></div>if (lastLoggedInList[roomName][id]) {
<a name="line4559"></a><div class="linenumber">4559</div><div style="width:8em;display:inline-block"></div>return true;
<a name="line4560"></a><div class="linenumber">4560</div><div style="width:6em;display:inline-block"></div>}
<a name="line4561"></a><div class="linenumber">4561</div><div style="width:4em;display:inline-block"></div>}
<a name="line4562"></a><div class="linenumber">4562</div><div style="width:4em;display:inline-block"></div>return false;
<a name="line4563"></a><div class="linenumber">4563</div><div style="width:2em;display:inline-block"></div>}
<a name="line4564"></a><div class="linenumber">4564</div>
<a name="line4565"></a><div class="linenumber">4565</div><div style="width:2em;display:inline-block"></div>/**
<a name="line4566"></a><div class="linenumber">4566</div><div style="width:2em;display:inline-block"></div>* Checks to see if a particular peer is present in any room.
<a name="line4567"></a><div class="linenumber">4567</div><div style="width:2em;display:inline-block"></div>* If it isn't, we assume it's logged out.
<a name="line4568"></a><div class="linenumber">4568</div><div style="width:2em;display:inline-block"></div>* @param {string} easyrtcid the easyrtcId of the peer.
<a name="line4569"></a><div class="linenumber">4569</div><div style="width:2em;display:inline-block"></div>*/
<a name="line4570"></a><div class="linenumber">4570</div><div style="width:2em;display:inline-block"></div>this.isPeerInAnyRoom = function(easyrtcid) {
<a name="line4571"></a><div class="linenumber">4571</div><div style="width:4em;display:inline-block"></div>return isPeerInAnyRoom(easyrtcid);
<a name="line4572"></a><div class="linenumber">4572</div><div style="width:2em;display:inline-block"></div>};
<a name="line4573"></a><div class="linenumber">4573</div>
<a name="line4574"></a><div class="linenumber">4574</div><div style="width:2em;display:inline-block"></div>/** @private */
<a name="line4575"></a><div class="linenumber">4575</div><div style="width:2em;display:inline-block"></div>function processLostPeers(peersInRoom) {
<a name="line4576"></a><div class="linenumber">4576</div><div style="width:4em;display:inline-block"></div>var id;
<a name="line4577"></a><div class="linenumber">4577</div><div style="width:4em;display:inline-block"></div>//
<a name="line4578"></a><div class="linenumber">4578</div><div style="width:4em;display:inline-block"></div>// check to see the person is still in at least one room. If not, we'll hangup
<a name="line4579"></a><div class="linenumber">4579</div><div style="width:4em;display:inline-block"></div>// on them. This isn't the correct behavior, but it's the best we can do without
<a name="line4580"></a><div class="linenumber">4580</div><div style="width:4em;display:inline-block"></div>// changes to the server.
<a name="line4581"></a><div class="linenumber">4581</div><div style="width:4em;display:inline-block"></div>//
<a name="line4582"></a><div class="linenumber">4582</div><div style="width:4em;display:inline-block"></div>for (id in peerConns) {
<a name="line4583"></a><div class="linenumber">4583</div><div style="width:6em;display:inline-block"></div>if (peerConns.hasOwnProperty(id) &&
<a name="line4584"></a><div class="linenumber">4584</div><div style="width:10em;display:inline-block"></div>typeof peersInRoom[id] === 'undefined') {
<a name="line4585"></a><div class="linenumber">4585</div><div style="width:8em;display:inline-block"></div>if (!isPeerInAnyRoom(id)) {
<a name="line4586"></a><div class="linenumber">4586</div><div style="width:10em;display:inline-block"></div>if (peerConns[id].pc || peerConns[id].isInitiator) {
<a name="line4587"></a><div class="linenumber">4587</div><div style="width:12em;display:inline-block"></div>onRemoteHangup(id);
<a name="line4588"></a><div class="linenumber">4588</div><div style="width:10em;display:inline-block"></div>}
<a name="line4589"></a><div class="linenumber">4589</div><div style="width:10em;display:inline-block"></div>delete offersPending[id];
<a name="line4590"></a><div class="linenumber">4590</div><div style="width:10em;display:inline-block"></div>delete acceptancePending[id];
<a name="line4591"></a><div class="linenumber">4591</div><div style="width:10em;display:inline-block"></div>clearQueuedMessages(id);
<a name="line4592"></a><div class="linenumber">4592</div><div style="width:8em;display:inline-block"></div>}
<a name="line4593"></a><div class="linenumber">4593</div><div style="width:6em;display:inline-block"></div>}
<a name="line4594"></a><div class="linenumber">4594</div><div style="width:4em;display:inline-block"></div>}
<a name="line4595"></a><div class="linenumber">4595</div>
<a name="line4596"></a><div class="linenumber">4596</div><div style="width:4em;display:inline-block"></div>for (id in offersPending) {
<a name="line4597"></a><div class="linenumber">4597</div><div style="width:6em;display:inline-block"></div>if (offersPending.hasOwnProperty(id) && !isPeerInAnyRoom(id)) {
<a name="line4598"></a><div class="linenumber">4598</div><div style="width:8em;display:inline-block"></div>onRemoteHangup(id);
<a name="line4599"></a><div class="linenumber">4599</div><div style="width:8em;display:inline-block"></div>clearQueuedMessages(id);
<a name="line4600"></a><div class="linenumber">4600</div><div style="width:8em;display:inline-block"></div>delete offersPending[id];
<a name="line4601"></a><div class="linenumber">4601</div><div style="width:8em;display:inline-block"></div>delete acceptancePending[id];
<a name="line4602"></a><div class="linenumber">4602</div><div style="width:6em;display:inline-block"></div>}
<a name="line4603"></a><div class="linenumber">4603</div><div style="width:4em;display:inline-block"></div>}
<a name="line4604"></a><div class="linenumber">4604</div>
<a name="line4605"></a><div class="linenumber">4605</div><div style="width:4em;display:inline-block"></div>for (id in acceptancePending) {
<a name="line4606"></a><div class="linenumber">4606</div><div style="width:6em;display:inline-block"></div>if (acceptancePending.hasOwnProperty(id) && !isPeerInAnyRoom(id)) {
<a name="line4607"></a><div class="linenumber">4607</div><div style="width:8em;display:inline-block"></div>onRemoteHangup(id);
<a name="line4608"></a><div class="linenumber">4608</div><div style="width:8em;display:inline-block"></div>clearQueuedMessages(id);
<a name="line4609"></a><div class="linenumber">4609</div><div style="width:8em;display:inline-block"></div>delete acceptancePending[id];
<a name="line4610"></a><div class="linenumber">4610</div><div style="width:6em;display:inline-block"></div>}
<a name="line4611"></a><div class="linenumber">4611</div><div style="width:4em;display:inline-block"></div>}
<a name="line4612"></a><div class="linenumber">4612</div><div style="width:2em;display:inline-block"></div>}
<a name="line4613"></a><div class="linenumber">4613</div>
<a name="line4614"></a><div class="linenumber">4614</div><div style="width:2em;display:inline-block"></div>/**
<a name="line4615"></a><div class="linenumber">4615</div><div style="width:2em;display:inline-block"></div>* The idea of aggregating timers is that there are events that convey state and these can fire more frequently
<a name="line4616"></a><div class="linenumber">4616</div><div style="width:2em;display:inline-block"></div>* than desired. Aggregating timers allow a bunch of events to be collapsed into one by only firing the last
<a name="line4617"></a><div class="linenumber">4617</div><div style="width:2em;display:inline-block"></div>* event.
<a name="line4618"></a><div class="linenumber">4618</div><div style="width:2em;display:inline-block"></div>* @private
<a name="line4619"></a><div class="linenumber">4619</div><div style="width:2em;display:inline-block"></div>*/
<a name="line4620"></a><div class="linenumber">4620</div><div style="width:2em;display:inline-block"></div>var aggregatingTimers = {};
<a name="line4621"></a><div class="linenumber">4621</div>
<a name="line4622"></a><div class="linenumber">4622</div><div style="width:2em;display:inline-block"></div>/**
<a name="line4623"></a><div class="linenumber">4623</div><div style="width:2em;display:inline-block"></div>* This function sets a timeout for a function to be called with the feature that if another
<a name="line4624"></a><div class="linenumber">4624</div><div style="width:2em;display:inline-block"></div>* invocation comes along within a particular interval (with the same key), the second invocation
<a name="line4625"></a><div class="linenumber">4625</div><div style="width:2em;display:inline-block"></div>* replaces the first. To prevent a continuous stream of events from preventing a callback from ever
<a name="line4626"></a><div class="linenumber">4626</div><div style="width:2em;display:inline-block"></div>* firing, we'll collapse no more than 20 events.
<a name="line4627"></a><div class="linenumber">4627</div><div style="width:2em;display:inline-block"></div>* @param {String} key A key used to identify callbacks that should be aggregated.
<a name="line4628"></a><div class="linenumber">4628</div><div style="width:2em;display:inline-block"></div>* @param {Function} callback The callback to invoke.
<a name="line4629"></a><div class="linenumber">4629</div><div style="width:2em;display:inline-block"></div>* @param {Number} period The aggregating period in milliseconds.
<a name="line4630"></a><div class="linenumber">4630</div><div style="width:2em;display:inline-block"></div>* @private
<a name="line4631"></a><div class="linenumber">4631</div><div style="width:2em;display:inline-block"></div>*/
<a name="line4632"></a><div class="linenumber">4632</div><div style="width:2em;display:inline-block"></div>function addAggregatingTimer(key, callback, period) {
<a name="line4633"></a><div class="linenumber">4633</div><div style="width:4em;display:inline-block"></div>if( !period) {
<a name="line4634"></a><div class="linenumber">4634</div><div style="width:6em;display:inline-block"></div>period = 100; // 0.1 second
<a name="line4635"></a><div class="linenumber">4635</div><div style="width:4em;display:inline-block"></div>}
<a name="line4636"></a><div class="linenumber">4636</div><div style="width:4em;display:inline-block"></div>var counter = 0;
<a name="line4637"></a><div class="linenumber">4637</div><div style="width:4em;display:inline-block"></div>if( aggregatingTimers[key]) {
<a name="line4638"></a><div class="linenumber">4638</div><div style="width:6em;display:inline-block"></div>clearTimeout(aggregatingTimers[key].timer);
<a name="line4639"></a><div class="linenumber">4639</div><div style="width:6em;display:inline-block"></div>counter = aggregatingTimers[key].counter;
<a name="line4640"></a><div class="linenumber">4640</div><div style="width:4em;display:inline-block"></div>}
<a name="line4641"></a><div class="linenumber">4641</div><div style="width:4em;display:inline-block"></div>if( counter > 20) {
<a name="line4642"></a><div class="linenumber">4642</div><div style="width:6em;display:inline-block"></div>delete aggregatingTimers[key];
<a name="line4643"></a><div class="linenumber">4643</div><div style="width:6em;display:inline-block"></div>callback();
<a name="line4644"></a><div class="linenumber">4644</div><div style="width:4em;display:inline-block"></div>}
<a name="line4645"></a><div class="linenumber">4645</div><div style="width:4em;display:inline-block"></div>else {
<a name="line4646"></a><div class="linenumber">4646</div><div style="width:6em;display:inline-block"></div>aggregatingTimers[key] = {counter: counter +1};
<a name="line4647"></a><div class="linenumber">4647</div><div style="width:6em;display:inline-block"></div>aggregatingTimers[key].timer = setTimeout(function () {
<a name="line4648"></a><div class="linenumber">4648</div><div style="width:8em;display:inline-block"></div>delete aggregatingTimers[key];
<a name="line4649"></a><div class="linenumber">4649</div><div style="width:8em;display:inline-block"></div>callback();
<a name="line4650"></a><div class="linenumber">4650</div><div style="width:6em;display:inline-block"></div>}, period);
<a name="line4651"></a><div class="linenumber">4651</div><div style="width:4em;display:inline-block"></div>}
<a name="line4652"></a><div class="linenumber">4652</div><div style="width:2em;display:inline-block"></div>}
<a name="line4653"></a><div class="linenumber">4653</div>
<a name="line4654"></a><div class="linenumber">4654</div><div style="width:2em;display:inline-block"></div>/** @private */
<a name="line4655"></a><div class="linenumber">4655</div><div style="width:2em;display:inline-block"></div>//
<a name="line4656"></a><div class="linenumber">4656</div><div style="width:2em;display:inline-block"></div>// this function gets called for each room when there is a room update.
<a name="line4657"></a><div class="linenumber">4657</div><div style="width:2em;display:inline-block"></div>//
<a name="line4658"></a><div class="linenumber">4658</div><div style="width:2em;display:inline-block"></div>function processOccupantList(roomName, occupantList) {
<a name="line4659"></a><div class="linenumber">4659</div><div style="width:4em;display:inline-block"></div>var myInfo = null;
<a name="line4660"></a><div class="linenumber">4660</div><div style="width:4em;display:inline-block"></div>var reducedList = {};
<a name="line4661"></a><div class="linenumber">4661</div>
<a name="line4662"></a><div class="linenumber">4662</div><div style="width:4em;display:inline-block"></div>var id;
<a name="line4663"></a><div class="linenumber">4663</div><div style="width:4em;display:inline-block"></div>for (id in occupantList) {
<a name="line4664"></a><div class="linenumber">4664</div><div style="width:6em;display:inline-block"></div>if (occupantList.hasOwnProperty(id)) {
<a name="line4665"></a><div class="linenumber">4665</div><div style="width:8em;display:inline-block"></div>if (id === self.myEasyrtcid) {
<a name="line4666"></a><div class="linenumber">4666</div><div style="width:10em;display:inline-block"></div>myInfo = occupantList[id];
<a name="line4667"></a><div class="linenumber">4667</div><div style="width:8em;display:inline-block"></div>}
<a name="line4668"></a><div class="linenumber">4668</div><div style="width:8em;display:inline-block"></div>else {
<a name="line4669"></a><div class="linenumber">4669</div><div style="width:10em;display:inline-block"></div>reducedList[id] = occupantList[id];
<a name="line4670"></a><div class="linenumber">4670</div><div style="width:8em;display:inline-block"></div>}
<a name="line4671"></a><div class="linenumber">4671</div><div style="width:6em;display:inline-block"></div>}
<a name="line4672"></a><div class="linenumber">4672</div><div style="width:4em;display:inline-block"></div>}
<a name="line4673"></a><div class="linenumber">4673</div><div style="width:4em;display:inline-block"></div>//
<a name="line4674"></a><div class="linenumber">4674</div><div style="width:4em;display:inline-block"></div>// processLostPeers detects peers that have gone away and performs
<a name="line4675"></a><div class="linenumber">4675</div><div style="width:4em;display:inline-block"></div>// house keeping accordingly.
<a name="line4676"></a><div class="linenumber">4676</div><div style="width:4em;display:inline-block"></div>//
<a name="line4677"></a><div class="linenumber">4677</div><div style="width:4em;display:inline-block"></div>processLostPeers(reducedList);
<a name="line4678"></a><div class="linenumber">4678</div><div style="width:4em;display:inline-block"></div>//
<a name="line4679"></a><div class="linenumber">4679</div><div style="width:4em;display:inline-block"></div>//
<a name="line4680"></a><div class="linenumber">4680</div><div style="width:4em;display:inline-block"></div>//
<a name="line4681"></a><div class="linenumber">4681</div><div style="width:4em;display:inline-block"></div>addAggregatingTimer("roomOccupants&" + roomName, function(){
<a name="line4682"></a><div class="linenumber">4682</div><div style="width:6em;display:inline-block"></div>if (roomOccupantListener) {
<a name="line4683"></a><div class="linenumber">4683</div><div style="width:8em;display:inline-block"></div>roomOccupantListener(roomName, reducedList, myInfo);
<a name="line4684"></a><div class="linenumber">4684</div><div style="width:6em;display:inline-block"></div>}
<a name="line4685"></a><div class="linenumber">4685</div><div style="width:6em;display:inline-block"></div>self.emitEvent("roomOccupants", {roomName:roomName, occupants:lastLoggedInList});
<a name="line4686"></a><div class="linenumber">4686</div><div style="width:4em;display:inline-block"></div>}, 100);
<a name="line4687"></a><div class="linenumber">4687</div><div style="width:2em;display:inline-block"></div>}
<a name="line4688"></a><div class="linenumber">4688</div>
<a name="line4689"></a><div class="linenumber">4689</div><div style="width:2em;display:inline-block"></div>/** @private */
<a name="line4690"></a><div class="linenumber">4690</div><div style="width:2em;display:inline-block"></div>function onChannelMsg(msg, ackAcceptorFunc) {
<a name="line4691"></a><div class="linenumber">4691</div>
<a name="line4692"></a><div class="linenumber">4692</div><div style="width:4em;display:inline-block"></div>var targeting = {};
<a name="line4693"></a><div class="linenumber">4693</div><div style="width:4em;display:inline-block"></div>if (ackAcceptorFunc) {
<a name="line4694"></a><div class="linenumber">4694</div><div style="width:6em;display:inline-block"></div>ackAcceptorFunc(self.ackMessage);
<a name="line4695"></a><div class="linenumber">4695</div><div style="width:4em;display:inline-block"></div>}
<a name="line4696"></a><div class="linenumber">4696</div><div style="width:4em;display:inline-block"></div>if (msg.targetEasyrtcid) {
<a name="line4697"></a><div class="linenumber">4697</div><div style="width:6em;display:inline-block"></div>targeting.targetEasyrtcid = msg.targetEasyrtcid;
<a name="line4698"></a><div class="linenumber">4698</div><div style="width:4em;display:inline-block"></div>}
<a name="line4699"></a><div class="linenumber">4699</div><div style="width:4em;display:inline-block"></div>if (msg.targetRoom) {
<a name="line4700"></a><div class="linenumber">4700</div><div style="width:6em;display:inline-block"></div>targeting.targetRoom = msg.targetRoom;
<a name="line4701"></a><div class="linenumber">4701</div><div style="width:4em;display:inline-block"></div>}
<a name="line4702"></a><div class="linenumber">4702</div><div style="width:4em;display:inline-block"></div>if (msg.targetGroup) {
<a name="line4703"></a><div class="linenumber">4703</div><div style="width:6em;display:inline-block"></div>targeting.targetGroup = msg.targetGroup;
<a name="line4704"></a><div class="linenumber">4704</div><div style="width:4em;display:inline-block"></div>}
<a name="line4705"></a><div class="linenumber">4705</div><div style="width:4em;display:inline-block"></div>if (msg.senderEasyrtcid) {
<a name="line4706"></a><div class="linenumber">4706</div><div style="width:6em;display:inline-block"></div>self.receivePeerDistribute(msg.senderEasyrtcid, msg, targeting);
<a name="line4707"></a><div class="linenumber">4707</div><div style="width:4em;display:inline-block"></div>}
<a name="line4708"></a><div class="linenumber">4708</div><div style="width:4em;display:inline-block"></div>else {
<a name="line4709"></a><div class="linenumber">4709</div><div style="width:6em;display:inline-block"></div>if (receiveServerCB) {
<a name="line4710"></a><div class="linenumber">4710</div><div style="width:8em;display:inline-block"></div>receiveServerCB(msg.msgType, msg.msgData, targeting);
<a name="line4711"></a><div class="linenumber">4711</div><div style="width:6em;display:inline-block"></div>}
<a name="line4712"></a><div class="linenumber">4712</div><div style="width:6em;display:inline-block"></div>else {
<a name="line4713"></a><div class="linenumber">4713</div><div style="width:8em;display:inline-block"></div>logDebug("Unhandled server message " + JSON.stringify(msg));
<a name="line4714"></a><div class="linenumber">4714</div><div style="width:6em;display:inline-block"></div>}
<a name="line4715"></a><div class="linenumber">4715</div><div style="width:4em;display:inline-block"></div>}
<a name="line4716"></a><div class="linenumber">4716</div><div style="width:2em;display:inline-block"></div>}
<a name="line4717"></a><div class="linenumber">4717</div>
<a name="line4718"></a><div class="linenumber">4718</div><div style="width:2em;display:inline-block"></div>/** @private */
<a name="line4719"></a><div class="linenumber">4719</div><div style="width:2em;display:inline-block"></div>function processUrl(url) {
<a name="line4720"></a><div class="linenumber">4720</div><div style="width:4em;display:inline-block"></div>var ipAddress;
<a name="line4721"></a><div class="linenumber">4721</div><div style="width:4em;display:inline-block"></div>if (url.indexOf('turn:') === 0 || url.indexOf('turns:') === 0) {
<a name="line4722"></a><div class="linenumber">4722</div><div style="width:6em;display:inline-block"></div>ipAddress = url.split(/[@:&]/g)[1];
<a name="line4723"></a><div class="linenumber">4723</div><div style="width:6em;display:inline-block"></div>self._turnServers[ipAddress] = true;
<a name="line4724"></a><div class="linenumber">4724</div><div style="width:4em;display:inline-block"></div>} else if (url.indexOf('stun:') === 0 || url.indexOf('stuns:') === 0) {
<a name="line4725"></a><div class="linenumber">4725</div><div style="width:6em;display:inline-block"></div>ipAddress = url.split(/[@:&]/g)[1];
<a name="line4726"></a><div class="linenumber">4726</div><div style="width:6em;display:inline-block"></div>self._stunServers[ipAddress] = true;
<a name="line4727"></a><div class="linenumber">4727</div><div style="width:4em;display:inline-block"></div>}
<a name="line4728"></a><div class="linenumber">4728</div><div style="width:2em;display:inline-block"></div>}
<a name="line4729"></a><div class="linenumber">4729</div>
<a name="line4730"></a><div class="linenumber">4730</div><div style="width:2em;display:inline-block"></div>/** @private */
<a name="line4731"></a><div class="linenumber">4731</div><div style="width:2em;display:inline-block"></div>function processIceConfig(iceConfig) {
<a name="line4732"></a><div class="linenumber">4732</div>
<a name="line4733"></a><div class="linenumber">4733</div><div style="width:4em;display:inline-block"></div>var i, j, item;
<a name="line4734"></a><div class="linenumber">4734</div>
<a name="line4735"></a><div class="linenumber">4735</div><div style="width:4em;display:inline-block"></div>pc_config = {
<a name="line4736"></a><div class="linenumber">4736</div><div style="width:6em;display:inline-block"></div>iceServers: []
<a name="line4737"></a><div class="linenumber">4737</div><div style="width:4em;display:inline-block"></div>};
<a name="line4738"></a><div class="linenumber">4738</div>
<a name="line4739"></a><div class="linenumber">4739</div><div style="width:4em;display:inline-block"></div>self._turnServers = {};
<a name="line4740"></a><div class="linenumber">4740</div><div style="width:4em;display:inline-block"></div>self._stunServers = {};
<a name="line4741"></a><div class="linenumber">4741</div>
<a name="line4742"></a><div class="linenumber">4742</div><div style="width:4em;display:inline-block"></div>if (
<a name="line4743"></a><div class="linenumber">4743</div><div style="width:6em;display:inline-block"></div>!iceConfig ||
<a name="line4744"></a><div class="linenumber">4744</div><div style="width:8em;display:inline-block"></div>!iceConfig.iceServers ||
<a name="line4745"></a><div class="linenumber">4745</div><div style="width:10em;display:inline-block"></div>typeof iceConfig.iceServers.length === "undefined"
<a name="line4746"></a><div class="linenumber">4746</div><div style="width:4em;display:inline-block"></div>) {
<a name="line4747"></a><div class="linenumber">4747</div><div style="width:6em;display:inline-block"></div>self.showError(
<a name="line4748"></a><div class="linenumber">4748</div><div style="width:8em;display:inline-block"></div>self.errCodes.DEVELOPER_ERR,
<a name="line4749"></a><div class="linenumber">4749</div><div style="width:8em;display:inline-block"></div>"iceConfig received from server didn't have an array called iceServers, ignoring it"
<a name="line4750"></a><div class="linenumber">4750</div><div style="width:6em;display:inline-block"></div>);
<a name="line4751"></a><div class="linenumber">4751</div><div style="width:4em;display:inline-block"></div>} else {
<a name="line4752"></a><div class="linenumber">4752</div><div style="width:6em;display:inline-block"></div>pc_config = {
<a name="line4753"></a><div class="linenumber">4753</div><div style="width:8em;display:inline-block"></div>iceServers: iceConfig.iceServers
<a name="line4754"></a><div class="linenumber">4754</div><div style="width:6em;display:inline-block"></div>};
<a name="line4755"></a><div class="linenumber">4755</div><div style="width:4em;display:inline-block"></div>}
<a name="line4756"></a><div class="linenumber">4756</div>
<a name="line4757"></a><div class="linenumber">4757</div><div style="width:4em;display:inline-block"></div>for (i = 0; i < iceConfig.iceServers.length; i++) {
<a name="line4758"></a><div class="linenumber">4758</div><div style="width:6em;display:inline-block"></div>item = iceConfig.iceServers[i];
<a name="line4759"></a><div class="linenumber">4759</div><div style="width:6em;display:inline-block"></div>if( item.urls && item.urls.length ) {
<a name="line4760"></a><div class="linenumber">4760</div><div style="width:7em;display:inline-block"></div>for( j = 0; j < item.urls.length; j++ ) {
<a name="line4761"></a><div class="linenumber">4761</div><div style="width:9em;display:inline-block"></div>processUrl(item.urls[j]);
<a name="line4762"></a><div class="linenumber">4762</div><div style="width:7em;display:inline-block"></div>}
<a name="line4763"></a><div class="linenumber">4763</div><div style="width:6em;display:inline-block"></div>}
<a name="line4764"></a><div class="linenumber">4764</div><div style="width:6em;display:inline-block"></div>else if( item.url ) {
<a name="line4765"></a><div class="linenumber">4765</div><div style="width:7em;display:inline-block"></div>processUrl(item.url);
<a name="line4766"></a><div class="linenumber">4766</div><div style="width:6em;display:inline-block"></div>}
<a name="line4767"></a><div class="linenumber">4767</div><div style="width:4em;display:inline-block"></div>}
<a name="line4768"></a><div class="linenumber">4768</div><div style="width:2em;display:inline-block"></div>}
<a name="line4769"></a><div class="linenumber">4769</div>
<a name="line4770"></a><div class="linenumber">4770</div><div style="width:2em;display:inline-block"></div>/** @private */
<a name="line4771"></a><div class="linenumber">4771</div><div style="width:2em;display:inline-block"></div>function processSessionData(sessionData) {
<a name="line4772"></a><div class="linenumber">4772</div><div style="width:4em;display:inline-block"></div>if (sessionData) {
<a name="line4773"></a><div class="linenumber">4773</div><div style="width:6em;display:inline-block"></div>if (sessionData.easyrtcsid) {
<a name="line4774"></a><div class="linenumber">4774</div><div style="width:8em;display:inline-block"></div>self.easyrtcsid = sessionData.easyrtcsid;
<a name="line4775"></a><div class="linenumber">4775</div><div style="width:6em;display:inline-block"></div>}
<a name="line4776"></a><div class="linenumber">4776</div><div style="width:6em;display:inline-block"></div>if (sessionData.field) {
<a name="line4777"></a><div class="linenumber">4777</div><div style="width:8em;display:inline-block"></div>sessionFields = sessionData.field;
<a name="line4778"></a><div class="linenumber">4778</div><div style="width:6em;display:inline-block"></div>}
<a name="line4779"></a><div class="linenumber">4779</div><div style="width:4em;display:inline-block"></div>}
<a name="line4780"></a><div class="linenumber">4780</div><div style="width:2em;display:inline-block"></div>}
<a name="line4781"></a><div class="linenumber">4781</div>
<a name="line4782"></a><div class="linenumber">4782</div><div style="width:2em;display:inline-block"></div>/** @private */
<a name="line4783"></a><div class="linenumber">4783</div><div style="width:2em;display:inline-block"></div>function processRoomData(roomData) {
<a name="line4784"></a><div class="linenumber">4784</div><div style="width:4em;display:inline-block"></div>self.roomData = roomData;
<a name="line4785"></a><div class="linenumber">4785</div>
<a name="line4786"></a><div class="linenumber">4786</div><div style="width:4em;display:inline-block"></div>var k, roomName,
<a name="line4787"></a><div class="linenumber">4787</div><div style="width:6em;display:inline-block"></div>stuffToRemove, stuffToAdd,
<a name="line4788"></a><div class="linenumber">4788</div><div style="width:6em;display:inline-block"></div>id, removeId;
<a name="line4789"></a><div class="linenumber">4789</div>
<a name="line4790"></a><div class="linenumber">4790</div><div style="width:4em;display:inline-block"></div>for (roomName in self.roomData) {
<a name="line4791"></a><div class="linenumber">4791</div><div style="width:6em;display:inline-block"></div>if (!self.roomData.hasOwnProperty(roomName)) {
<a name="line4792"></a><div class="linenumber">4792</div><div style="width:8em;display:inline-block"></div>continue;
<a name="line4793"></a><div class="linenumber">4793</div><div style="width:6em;display:inline-block"></div>}
<a name="line4794"></a><div class="linenumber">4794</div><div style="width:6em;display:inline-block"></div>if (roomData[roomName].roomStatus === "join") {
<a name="line4795"></a><div class="linenumber">4795</div><div style="width:8em;display:inline-block"></div>if (!(self.roomJoin[roomName])) {
<a name="line4796"></a><div class="linenumber">4796</div><div style="width:10em;display:inline-block"></div>self.roomJoin[roomName] = roomData[roomName];
<a name="line4797"></a><div class="linenumber">4797</div><div style="width:8em;display:inline-block"></div>}
<a name="line4798"></a><div class="linenumber">4798</div><div style="width:8em;display:inline-block"></div>var mediaIds = buildMediaIds();
<a name="line4799"></a><div class="linenumber">4799</div><div style="width:8em;display:inline-block"></div>if (mediaIds !== {}) {
<a name="line4800"></a><div class="linenumber">4800</div><div style="width:10em;display:inline-block"></div>self.setRoomApiField(roomName, "mediaIds", mediaIds);
<a name="line4801"></a><div class="linenumber">4801</div><div style="width:8em;display:inline-block"></div>}
<a name="line4802"></a><div class="linenumber">4802</div><div style="width:6em;display:inline-block"></div>}
<a name="line4803"></a><div class="linenumber">4803</div><div style="width:6em;display:inline-block"></div>else if (roomData[roomName].roomStatus === "leave") {
<a name="line4804"></a><div class="linenumber">4804</div><div style="width:8em;display:inline-block"></div>if (self.roomEntryListener) {
<a name="line4805"></a><div class="linenumber">4805</div><div style="width:10em;display:inline-block"></div>self.roomEntryListener(false, roomName);
<a name="line4806"></a><div class="linenumber">4806</div><div style="width:8em;display:inline-block"></div>}
<a name="line4807"></a><div class="linenumber">4807</div><div style="width:8em;display:inline-block"></div>delete self.roomJoin[roomName];
<a name="line4808"></a><div class="linenumber">4808</div><div style="width:8em;display:inline-block"></div>delete lastLoggedInList[roomName];
<a name="line4809"></a><div class="linenumber">4809</div><div style="width:8em;display:inline-block"></div>continue;
<a name="line4810"></a><div class="linenumber">4810</div><div style="width:6em;display:inline-block"></div>}
<a name="line4811"></a><div class="linenumber">4811</div>
<a name="line4812"></a><div class="linenumber">4812</div><div style="width:6em;display:inline-block"></div>if (roomData[roomName].clientList) {
<a name="line4813"></a><div class="linenumber">4813</div><div style="width:8em;display:inline-block"></div>lastLoggedInList[roomName] = roomData[roomName].clientList;
<a name="line4814"></a><div class="linenumber">4814</div><div style="width:6em;display:inline-block"></div>}
<a name="line4815"></a><div class="linenumber">4815</div><div style="width:6em;display:inline-block"></div>else if (roomData[roomName].clientListDelta) {
<a name="line4816"></a><div class="linenumber">4816</div><div style="width:8em;display:inline-block"></div>stuffToAdd = roomData[roomName].clientListDelta.updateClient;
<a name="line4817"></a><div class="linenumber">4817</div><div style="width:8em;display:inline-block"></div>if (stuffToAdd) {
<a name="line4818"></a><div class="linenumber">4818</div><div style="width:10em;display:inline-block"></div>for (id in stuffToAdd) {
<a name="line4819"></a><div class="linenumber">4819</div><div style="width:12em;display:inline-block"></div>if (!stuffToAdd.hasOwnProperty(id)) {
<a name="line4820"></a><div class="linenumber">4820</div><div style="width:14em;display:inline-block"></div>continue;
<a name="line4821"></a><div class="linenumber">4821</div><div style="width:12em;display:inline-block"></div>}
<a name="line4822"></a><div class="linenumber">4822</div><div style="width:12em;display:inline-block"></div>if (!lastLoggedInList[roomName]) {
<a name="line4823"></a><div class="linenumber">4823</div><div style="width:14em;display:inline-block"></div>lastLoggedInList[roomName] = [];
<a name="line4824"></a><div class="linenumber">4824</div><div style="width:12em;display:inline-block"></div>}
<a name="line4825"></a><div class="linenumber">4825</div><div style="width:12em;display:inline-block"></div>if( !lastLoggedInList[roomName][id] ) {
<a name="line4826"></a><div class="linenumber">4826</div><div style="width:13em;display:inline-block"></div>lastLoggedInList[roomName][id] = stuffToAdd[id];
<a name="line4827"></a><div class="linenumber">4827</div><div style="width:12em;display:inline-block"></div>}
<a name="line4828"></a><div class="linenumber">4828</div><div style="width:12em;display:inline-block"></div>for( k in stuffToAdd[id] ) {
<a name="line4829"></a><div class="linenumber">4829</div><div style="width:13em;display:inline-block"></div>if( k === "apiField" || k === "presence") {
<a name="line4830"></a><div class="linenumber">4830</div><div style="width:15em;display:inline-block"></div>lastLoggedInList[roomName][id][k] = stuffToAdd[id][k];
<a name="line4831"></a><div class="linenumber">4831</div><div style="width:13em;display:inline-block"></div>}
<a name="line4832"></a><div class="linenumber">4832</div><div style="width:12em;display:inline-block"></div>}
<a name="line4833"></a><div class="linenumber">4833</div><div style="width:10em;display:inline-block"></div>}
<a name="line4834"></a><div class="linenumber">4834</div><div style="width:8em;display:inline-block"></div>}
<a name="line4835"></a><div class="linenumber">4835</div><div style="width:8em;display:inline-block"></div>stuffToRemove = roomData[roomName].clientListDelta.removeClient;
<a name="line4836"></a><div class="linenumber">4836</div><div style="width:8em;display:inline-block"></div>if (stuffToRemove && lastLoggedInList[roomName]) {
<a name="line4837"></a><div class="linenumber">4837</div><div style="width:10em;display:inline-block"></div>for (removeId in stuffToRemove) {
<a name="line4838"></a><div class="linenumber">4838</div><div style="width:12em;display:inline-block"></div>if (stuffToRemove.hasOwnProperty(removeId)) {
<a name="line4839"></a><div class="linenumber">4839</div><div style="width:14em;display:inline-block"></div>delete lastLoggedInList[roomName][removeId];
<a name="line4840"></a><div class="linenumber">4840</div><div style="width:12em;display:inline-block"></div>}
<a name="line4841"></a><div class="linenumber">4841</div><div style="width:10em;display:inline-block"></div>}
<a name="line4842"></a><div class="linenumber">4842</div><div style="width:8em;display:inline-block"></div>}
<a name="line4843"></a><div class="linenumber">4843</div><div style="width:6em;display:inline-block"></div>}
<a name="line4844"></a><div class="linenumber">4844</div><div style="width:6em;display:inline-block"></div>if (self.roomJoin[roomName] && roomData[roomName].field) {
<a name="line4845"></a><div class="linenumber">4845</div><div style="width:8em;display:inline-block"></div>fields.rooms[roomName] = roomData[roomName].field;
<a name="line4846"></a><div class="linenumber">4846</div><div style="width:6em;display:inline-block"></div>}
<a name="line4847"></a><div class="linenumber">4847</div><div style="width:6em;display:inline-block"></div>if (roomData[roomName].roomStatus === "join") {
<a name="line4848"></a><div class="linenumber">4848</div><div style="width:8em;display:inline-block"></div>if (self.roomEntryListener) {
<a name="line4849"></a><div class="linenumber">4849</div><div style="width:10em;display:inline-block"></div>self.roomEntryListener(true, roomName);
<a name="line4850"></a><div class="linenumber">4850</div><div style="width:8em;display:inline-block"></div>}
<a name="line4851"></a><div class="linenumber">4851</div><div style="width:6em;display:inline-block"></div>}
<a name="line4852"></a><div class="linenumber">4852</div><div style="width:6em;display:inline-block"></div>processOccupantList(roomName, lastLoggedInList[roomName]);
<a name="line4853"></a><div class="linenumber">4853</div><div style="width:4em;display:inline-block"></div>}
<a name="line4854"></a><div class="linenumber">4854</div><div style="width:4em;display:inline-block"></div>self.emitEvent("roomOccupant", lastLoggedInList);
<a name="line4855"></a><div class="linenumber">4855</div><div style="width:2em;display:inline-block"></div>}
<a name="line4856"></a><div class="linenumber">4856</div>
<a name="line4857"></a><div class="linenumber">4857</div><div style="width:2em;display:inline-block"></div>/** @private */
<a name="line4858"></a><div class="linenumber">4858</div><div style="width:2em;display:inline-block"></div>function onChannelCmd(msg, ackAcceptorFn) {
<a name="line4859"></a><div class="linenumber">4859</div>
<a name="line4860"></a><div class="linenumber">4860</div><div style="width:4em;display:inline-block"></div>var caller = msg.senderEasyrtcid;
<a name="line4861"></a><div class="linenumber">4861</div><div style="width:4em;display:inline-block"></div>var msgType = msg.msgType;
<a name="line4862"></a><div class="linenumber">4862</div><div style="width:4em;display:inline-block"></div>var msgData = msg.msgData;
<a name="line4863"></a><div class="linenumber">4863</div><div style="width:4em;display:inline-block"></div>var pc;
<a name="line4864"></a><div class="linenumber">4864</div>
<a name="line4865"></a><div class="linenumber">4865</div><div style="width:4em;display:inline-block"></div>logDebug('received message of type ' + msgType);
<a name="line4866"></a><div class="linenumber">4866</div>
<a name="line4867"></a><div class="linenumber">4867</div>
<a name="line4868"></a><div class="linenumber">4868</div><div style="width:4em;display:inline-block"></div>if (typeof queuedMessages[caller] === "undefined") {
<a name="line4869"></a><div class="linenumber">4869</div><div style="width:6em;display:inline-block"></div>clearQueuedMessages(caller);
<a name="line4870"></a><div class="linenumber">4870</div><div style="width:4em;display:inline-block"></div>}
<a name="line4871"></a><div class="linenumber">4871</div>
<a name="line4872"></a><div class="linenumber">4872</div><div style="width:4em;display:inline-block"></div>var processCandidateBody = function(caller, msgData) {
<a name="line4873"></a><div class="linenumber">4873</div><div style="width:6em;display:inline-block"></div>var candidate = null;
<a name="line4874"></a><div class="linenumber">4874</div>
<a name="line4875"></a><div class="linenumber">4875</div><div style="width:6em;display:inline-block"></div>if( iceCandidateFilter ) {
<a name="line4876"></a><div class="linenumber">4876</div><div style="width:7em;display:inline-block"></div>msgData = iceCandidateFilter(msgData, true);
<a name="line4877"></a><div class="linenumber">4877</div><div style="width:7em;display:inline-block"></div>if( !msgData ) {
<a name="line4878"></a><div class="linenumber">4878</div><div style="width:9em;display:inline-block"></div>return;
<a name="line4879"></a><div class="linenumber">4879</div><div style="width:7em;display:inline-block"></div>}
<a name="line4880"></a><div class="linenumber">4880</div><div style="width:6em;display:inline-block"></div>}
<a name="line4881"></a><div class="linenumber">4881</div>
<a name="line4882"></a><div class="linenumber">4882</div><div style="width:6em;display:inline-block"></div>candidate = new RTCIceCandidate({
<a name="line4883"></a><div class="linenumber">4883</div><div style="width:8em;display:inline-block"></div>sdpMLineIndex: msgData.label,
<a name="line4884"></a><div class="linenumber">4884</div><div style="width:8em;display:inline-block"></div>candidate: msgData.candidate
<a name="line4885"></a><div class="linenumber">4885</div><div style="width:6em;display:inline-block"></div>});
<a name="line4886"></a><div class="linenumber">4886</div><div style="width:6em;display:inline-block"></div>pc = peerConns[caller].pc;
<a name="line4887"></a><div class="linenumber">4887</div>
<a name="line4888"></a><div class="linenumber">4888</div><div style="width:6em;display:inline-block"></div>function iceAddSuccess() {
<a name="line4889"></a><div class="linenumber">4889</div><div style="width:8em;display:inline-block"></div>logDebug("iceAddSuccess: " +
<a name="line4890"></a><div class="linenumber">4890</div><div style="width:10em;display:inline-block"></div>JSON.stringify(candidate));
<a name="line4891"></a><div class="linenumber">4891</div><div style="width:8em;display:inline-block"></div>processCandicate(msgData.candidate);
<a name="line4892"></a><div class="linenumber">4892</div><div style="width:6em;display:inline-block"></div>}
<a name="line4893"></a><div class="linenumber">4893</div>
<a name="line4894"></a><div class="linenumber">4894</div><div style="width:6em;display:inline-block"></div>function iceAddFailure(domError) {
<a name="line4895"></a><div class="linenumber">4895</div><div style="width:8em;display:inline-block"></div>self.showError(self.errCodes.ICECANDIDATE_ERR, "bad ice candidate (" + domError.name + "): " +
<a name="line4896"></a><div class="linenumber">4896</div><div style="width:10em;display:inline-block"></div>JSON.stringify(candidate));
<a name="line4897"></a><div class="linenumber">4897</div><div style="width:6em;display:inline-block"></div>}
<a name="line4898"></a><div class="linenumber">4898</div>
<a name="line4899"></a><div class="linenumber">4899</div><div style="width:6em;display:inline-block"></div>pc.addIceCandidate(candidate, iceAddSuccess, iceAddFailure);
<a name="line4900"></a><div class="linenumber">4900</div><div style="width:4em;display:inline-block"></div>};
<a name="line4901"></a><div class="linenumber">4901</div>
<a name="line4902"></a><div class="linenumber">4902</div><div style="width:4em;display:inline-block"></div>var flushCachedCandidates = function(caller) {
<a name="line4903"></a><div class="linenumber">4903</div><div style="width:6em;display:inline-block"></div>var i;
<a name="line4904"></a><div class="linenumber">4904</div><div style="width:6em;display:inline-block"></div>if (queuedMessages[caller]) {
<a name="line4905"></a><div class="linenumber">4905</div><div style="width:8em;display:inline-block"></div>for (i = 0; i < queuedMessages[caller].candidates.length; i++) {
<a name="line4906"></a><div class="linenumber">4906</div><div style="width:10em;display:inline-block"></div>processCandidateBody(caller, queuedMessages[caller].candidates[i]);
<a name="line4907"></a><div class="linenumber">4907</div><div style="width:8em;display:inline-block"></div>}
<a name="line4908"></a><div class="linenumber">4908</div><div style="width:8em;display:inline-block"></div>delete queuedMessages[caller];
<a name="line4909"></a><div class="linenumber">4909</div><div style="width:6em;display:inline-block"></div>}
<a name="line4910"></a><div class="linenumber">4910</div><div style="width:4em;display:inline-block"></div>};
<a name="line4911"></a><div class="linenumber">4911</div>
<a name="line4912"></a><div class="linenumber">4912</div><div style="width:4em;display:inline-block"></div>var processOffer = function(caller, msgData) {
<a name="line4913"></a><div class="linenumber">4913</div>
<a name="line4914"></a><div class="linenumber">4914</div><div style="width:6em;display:inline-block"></div>var helper = function(wasAccepted, streamNames) {
<a name="line4915"></a><div class="linenumber">4915</div>
<a name="line4916"></a><div class="linenumber">4916</div><div style="width:8em;display:inline-block"></div>if (streamNames) {
<a name="line4917"></a><div class="linenumber">4917</div><div style="width:10em;display:inline-block"></div>if (typeof streamNames === "string") {
<a name="line4918"></a><div class="linenumber">4918</div><div style="width:12em;display:inline-block"></div>streamNames = [streamNames];
<a name="line4919"></a><div class="linenumber">4919</div><div style="width:10em;display:inline-block"></div>}
<a name="line4920"></a><div class="linenumber">4920</div><div style="width:10em;display:inline-block"></div>else if (streamNames.length === undefined) {
<a name="line4921"></a><div class="linenumber">4921</div><div style="width:12em;display:inline-block"></div>self.showError(self.errCodes.DEVELOPER_ERR, "accept callback passed invalid streamNames");
<a name="line4922"></a><div class="linenumber">4922</div><div style="width:12em;display:inline-block"></div>return;
<a name="line4923"></a><div class="linenumber">4923</div><div style="width:10em;display:inline-block"></div>}
<a name="line4924"></a><div class="linenumber">4924</div><div style="width:8em;display:inline-block"></div>}
<a name="line4925"></a><div class="linenumber">4925</div>
<a name="line4926"></a><div class="linenumber">4926</div><div style="width:8em;display:inline-block"></div>logDebug("offer accept=" + wasAccepted);
<a name="line4927"></a><div class="linenumber">4927</div>
<a name="line4928"></a><div class="linenumber">4928</div><div style="width:8em;display:inline-block"></div>delete offersPending[caller];
<a name="line4929"></a><div class="linenumber">4929</div>
<a name="line4930"></a><div class="linenumber">4930</div><div style="width:8em;display:inline-block"></div>if (wasAccepted) {
<a name="line4931"></a><div class="linenumber">4931</div><div style="width:10em;display:inline-block"></div>if (!self.supportsPeerConnections()) {
<a name="line4932"></a><div class="linenumber">4932</div><div style="width:12em;display:inline-block"></div>self.showError(self.errCodes.CALL_ERR, self.getConstantString("noWebrtcSupport"));
<a name="line4933"></a><div class="linenumber">4933</div><div style="width:12em;display:inline-block"></div>return;
<a name="line4934"></a><div class="linenumber">4934</div><div style="width:10em;display:inline-block"></div>}
<a name="line4935"></a><div class="linenumber">4935</div><div style="width:10em;display:inline-block"></div>doAnswer(caller, msgData, streamNames);
<a name="line4936"></a><div class="linenumber">4936</div><div style="width:10em;display:inline-block"></div>flushCachedCandidates(caller);
<a name="line4937"></a><div class="linenumber">4937</div><div style="width:8em;display:inline-block"></div>}
<a name="line4938"></a><div class="linenumber">4938</div><div style="width:8em;display:inline-block"></div>else {
<a name="line4939"></a><div class="linenumber">4939</div><div style="width:10em;display:inline-block"></div>sendSignalling(caller, "reject", null, null, null);
<a name="line4940"></a><div class="linenumber">4940</div><div style="width:10em;display:inline-block"></div>clearQueuedMessages(caller);
<a name="line4941"></a><div class="linenumber">4941</div><div style="width:8em;display:inline-block"></div>}
<a name="line4942"></a><div class="linenumber">4942</div><div style="width:6em;display:inline-block"></div>};
<a name="line4943"></a><div class="linenumber">4943</div><div style="width:6em;display:inline-block"></div>//
<a name="line4944"></a><div class="linenumber">4944</div><div style="width:6em;display:inline-block"></div>// There is a very rare case of two callers sending each other offers
<a name="line4945"></a><div class="linenumber">4945</div><div style="width:6em;display:inline-block"></div>// before receiving the others offer. In such a case, the caller with the
<a name="line4946"></a><div class="linenumber">4946</div><div style="width:6em;display:inline-block"></div>// greater valued easyrtcid will delete its pending call information and do a
<a name="line4947"></a><div class="linenumber">4947</div><div style="width:6em;display:inline-block"></div>// simple answer to the other caller's offer.
<a name="line4948"></a><div class="linenumber">4948</div><div style="width:6em;display:inline-block"></div>//
<a name="line4949"></a><div class="linenumber">4949</div><div style="width:6em;display:inline-block"></div>if (acceptancePending[caller] && caller < self.myEasyrtcid) {
<a name="line4950"></a><div class="linenumber">4950</div><div style="width:8em;display:inline-block"></div>delete acceptancePending[caller];
<a name="line4951"></a><div class="linenumber">4951</div><div style="width:8em;display:inline-block"></div>if (queuedMessages[caller]) {
<a name="line4952"></a><div class="linenumber">4952</div><div style="width:10em;display:inline-block"></div>delete queuedMessages[caller];
<a name="line4953"></a><div class="linenumber">4953</div><div style="width:8em;display:inline-block"></div>}
<a name="line4954"></a><div class="linenumber">4954</div><div style="width:8em;display:inline-block"></div>if (peerConns[caller]) {
<a name="line4955"></a><div class="linenumber">4955</div><div style="width:10em;display:inline-block"></div>if (peerConns[caller].wasAcceptedCB) {
<a name="line4956"></a><div class="linenumber">4956</div><div style="width:12em;display:inline-block"></div>peerConns[caller].wasAcceptedCB(true, caller);
<a name="line4957"></a><div class="linenumber">4957</div><div style="width:10em;display:inline-block"></div>}
<a name="line4958"></a><div class="linenumber">4958</div><div style="width:10em;display:inline-block"></div>delete peerConns[caller];
<a name="line4959"></a><div class="linenumber">4959</div><div style="width:8em;display:inline-block"></div>}
<a name="line4960"></a><div class="linenumber">4960</div><div style="width:8em;display:inline-block"></div>helper(true);
<a name="line4961"></a><div class="linenumber">4961</div><div style="width:8em;display:inline-block"></div>return;
<a name="line4962"></a><div class="linenumber">4962</div><div style="width:6em;display:inline-block"></div>}
<a name="line4963"></a><div class="linenumber">4963</div>
<a name="line4964"></a><div class="linenumber">4964</div><div style="width:6em;display:inline-block"></div>offersPending[caller] = msgData;
<a name="line4965"></a><div class="linenumber">4965</div><div style="width:6em;display:inline-block"></div>if (!self.acceptCheck) {
<a name="line4966"></a><div class="linenumber">4966</div><div style="width:8em;display:inline-block"></div>helper(true);
<a name="line4967"></a><div class="linenumber">4967</div><div style="width:6em;display:inline-block"></div>}
<a name="line4968"></a><div class="linenumber">4968</div><div style="width:6em;display:inline-block"></div>else {
<a name="line4969"></a><div class="linenumber">4969</div><div style="width:8em;display:inline-block"></div>self.acceptCheck(caller, helper);
<a name="line4970"></a><div class="linenumber">4970</div><div style="width:6em;display:inline-block"></div>}
<a name="line4971"></a><div class="linenumber">4971</div><div style="width:4em;display:inline-block"></div>};
<a name="line4972"></a><div class="linenumber">4972</div>
<a name="line4973"></a><div class="linenumber">4973</div><div style="width:4em;display:inline-block"></div>function processReject(caller) {
<a name="line4974"></a><div class="linenumber">4974</div><div style="width:6em;display:inline-block"></div>delete acceptancePending[caller];
<a name="line4975"></a><div class="linenumber">4975</div><div style="width:6em;display:inline-block"></div>if (queuedMessages[caller]) {
<a name="line4976"></a><div class="linenumber">4976</div><div style="width:8em;display:inline-block"></div>delete queuedMessages[caller];
<a name="line4977"></a><div class="linenumber">4977</div><div style="width:6em;display:inline-block"></div>}
<a name="line4978"></a><div class="linenumber">4978</div><div style="width:6em;display:inline-block"></div>if (peerConns[caller]) {
<a name="line4979"></a><div class="linenumber">4979</div><div style="width:8em;display:inline-block"></div>if (peerConns[caller].wasAcceptedCB) {
<a name="line4980"></a><div class="linenumber">4980</div><div style="width:10em;display:inline-block"></div>peerConns[caller].wasAcceptedCB(false, caller);
<a name="line4981"></a><div class="linenumber">4981</div><div style="width:8em;display:inline-block"></div>}
<a name="line4982"></a><div class="linenumber">4982</div><div style="width:8em;display:inline-block"></div>delete peerConns[caller];
<a name="line4983"></a><div class="linenumber">4983</div><div style="width:6em;display:inline-block"></div>}
<a name="line4984"></a><div class="linenumber">4984</div><div style="width:4em;display:inline-block"></div>}
<a name="line4985"></a><div class="linenumber">4985</div>
<a name="line4986"></a><div class="linenumber">4986</div><div style="width:4em;display:inline-block"></div>function processAnswer(caller, msgData) {
<a name="line4987"></a><div class="linenumber">4987</div>
<a name="line4988"></a><div class="linenumber">4988</div><div style="width:6em;display:inline-block"></div>delete acceptancePending[caller];
<a name="line4989"></a><div class="linenumber">4989</div>
<a name="line4990"></a><div class="linenumber">4990</div><div style="width:6em;display:inline-block"></div>//
<a name="line4991"></a><div class="linenumber">4991</div><div style="width:6em;display:inline-block"></div>// if we've discarded the peer connection, ignore the answer.
<a name="line4992"></a><div class="linenumber">4992</div><div style="width:6em;display:inline-block"></div>//
<a name="line4993"></a><div class="linenumber">4993</div><div style="width:6em;display:inline-block"></div>if (!peerConns[caller]) {
<a name="line4994"></a><div class="linenumber">4994</div><div style="width:8em;display:inline-block"></div>return;
<a name="line4995"></a><div class="linenumber">4995</div><div style="width:6em;display:inline-block"></div>}
<a name="line4996"></a><div class="linenumber">4996</div><div style="width:6em;display:inline-block"></div>peerConns[caller].connectionAccepted = true;
<a name="line4997"></a><div class="linenumber">4997</div>
<a name="line4998"></a><div class="linenumber">4998</div>
<a name="line4999"></a><div class="linenumber">4999</div>
<a name="line5000"></a><div class="linenumber">5000</div><div style="width:6em;display:inline-block"></div>if (peerConns[caller].wasAcceptedCB) {
<a name="line5001"></a><div class="linenumber">5001</div><div style="width:8em;display:inline-block"></div>peerConns[caller].wasAcceptedCB(true, caller);
<a name="line5002"></a><div class="linenumber">5002</div><div style="width:6em;display:inline-block"></div>}
<a name="line5003"></a><div class="linenumber">5003</div>
<a name="line5004"></a><div class="linenumber">5004</div><div style="width:6em;display:inline-block"></div>var onSignalSuccess = function() {
<a name="line5005"></a><div class="linenumber">5005</div>
<a name="line5006"></a><div class="linenumber">5006</div><div style="width:6em;display:inline-block"></div>};
<a name="line5007"></a><div class="linenumber">5007</div><div style="width:6em;display:inline-block"></div>var onSignalFailure = function(errorCode, errorText) {
<a name="line5008"></a><div class="linenumber">5008</div><div style="width:8em;display:inline-block"></div>if (peerConns[caller]) {
<a name="line5009"></a><div class="linenumber">5009</div><div style="width:10em;display:inline-block"></div>delete peerConns[caller];
<a name="line5010"></a><div class="linenumber">5010</div><div style="width:8em;display:inline-block"></div>}
<a name="line5011"></a><div class="linenumber">5011</div><div style="width:8em;display:inline-block"></div>self.showError(errorCode, errorText);
<a name="line5012"></a><div class="linenumber">5012</div><div style="width:6em;display:inline-block"></div>};
<a name="line5013"></a><div class="linenumber">5013</div><div style="width:6em;display:inline-block"></div>// peerConns[caller].startedAV = true;
<a name="line5014"></a><div class="linenumber">5014</div><div style="width:6em;display:inline-block"></div>sendQueuedCandidates(caller, onSignalSuccess, onSignalFailure);
<a name="line5015"></a><div class="linenumber">5015</div><div style="width:6em;display:inline-block"></div>pc = peerConns[caller].pc;
<a name="line5016"></a><div class="linenumber">5016</div><div style="width:6em;display:inline-block"></div>var sd = new RTCSessionDescription(msgData);
<a name="line5017"></a><div class="linenumber">5017</div><div style="width:6em;display:inline-block"></div>if (!sd) {
<a name="line5018"></a><div class="linenumber">5018</div><div style="width:8em;display:inline-block"></div>throw "Could not create the RTCSessionDescription";
<a name="line5019"></a><div class="linenumber">5019</div><div style="width:6em;display:inline-block"></div>}
<a name="line5020"></a><div class="linenumber">5020</div>
<a name="line5021"></a><div class="linenumber">5021</div><div style="width:6em;display:inline-block"></div>logDebug("about to call initiating setRemoteDescription");
<a name="line5022"></a><div class="linenumber">5022</div>
<a name="line5023"></a><div class="linenumber">5023</div><div style="width:6em;display:inline-block"></div>try {
<a name="line5024"></a><div class="linenumber">5024</div><div style="width:8em;display:inline-block"></div>if (sdpRemoteFilter) {
<a name="line5025"></a><div class="linenumber">5025</div><div style="width:10em;display:inline-block"></div>sd.sdp = sdpRemoteFilter(sd.sdp);
<a name="line5026"></a><div class="linenumber">5026</div><div style="width:8em;display:inline-block"></div>}
<a name="line5027"></a><div class="linenumber">5027</div><div style="width:8em;display:inline-block"></div>pc.setRemoteDescription(sd, function() {
<a name="line5028"></a><div class="linenumber">5028</div><div style="width:10em;display:inline-block"></div>if (pc.connectDataConnection) {
<a name="line5029"></a><div class="linenumber">5029</div><div style="width:12em;display:inline-block"></div>logDebug("calling connectDataConnection(5001,5002)");
<a name="line5030"></a><div class="linenumber">5030</div>
<a name="line5031"></a><div class="linenumber">5031</div><div style="width:12em;display:inline-block"></div>pc.connectDataConnection(5001, 5002); // these are like ids for data channels
<a name="line5032"></a><div class="linenumber">5032</div><div style="width:10em;display:inline-block"></div>}
<a name="line5033"></a><div class="linenumber">5033</div><div style="width:8em;display:inline-block"></div>}, function(message){
<a name="line5034"></a><div class="linenumber">5034</div><div style="width:10em;display:inline-block"></div>logDebug("setRemoteDescription failed ", message);
<a name="line5035"></a><div class="linenumber">5035</div><div style="width:8em;display:inline-block"></div>});
<a name="line5036"></a><div class="linenumber">5036</div><div style="width:6em;display:inline-block"></div>} catch (smdException) {
<a name="line5037"></a><div class="linenumber">5037</div><div style="width:8em;display:inline-block"></div>logDebug("setRemoteDescription failed ", smdException);
<a name="line5038"></a><div class="linenumber">5038</div><div style="width:6em;display:inline-block"></div>}
<a name="line5039"></a><div class="linenumber">5039</div><div style="width:6em;display:inline-block"></div>flushCachedCandidates(caller);
<a name="line5040"></a><div class="linenumber">5040</div><div style="width:4em;display:inline-block"></div>}
<a name="line5041"></a><div class="linenumber">5041</div>
<a name="line5042"></a><div class="linenumber">5042</div><div style="width:4em;display:inline-block"></div>function processCandidateQueue(caller, msgData) {
<a name="line5043"></a><div class="linenumber">5043</div>
<a name="line5044"></a><div class="linenumber">5044</div><div style="width:6em;display:inline-block"></div>if (peerConns[caller] && peerConns[caller].pc) {
<a name="line5045"></a><div class="linenumber">5045</div><div style="width:8em;display:inline-block"></div>processCandidateBody(caller, msgData);
<a name="line5046"></a><div class="linenumber">5046</div><div style="width:6em;display:inline-block"></div>}
<a name="line5047"></a><div class="linenumber">5047</div><div style="width:6em;display:inline-block"></div>else {
<a name="line5048"></a><div class="linenumber">5048</div><div style="width:8em;display:inline-block"></div>if (!peerConns[caller]) {
<a name="line5049"></a><div class="linenumber">5049</div><div style="width:10em;display:inline-block"></div>queuedMessages[caller] = {
<a name="line5050"></a><div class="linenumber">5050</div><div style="width:12em;display:inline-block"></div>candidates: []
<a name="line5051"></a><div class="linenumber">5051</div><div style="width:10em;display:inline-block"></div>};
<a name="line5052"></a><div class="linenumber">5052</div><div style="width:8em;display:inline-block"></div>}
<a name="line5053"></a><div class="linenumber">5053</div><div style="width:8em;display:inline-block"></div>queuedMessages[caller].candidates.push(msgData);
<a name="line5054"></a><div class="linenumber">5054</div><div style="width:6em;display:inline-block"></div>}
<a name="line5055"></a><div class="linenumber">5055</div><div style="width:4em;display:inline-block"></div>}
<a name="line5056"></a><div class="linenumber">5056</div>
<a name="line5057"></a><div class="linenumber">5057</div><div style="width:4em;display:inline-block"></div>switch (msgType) {
<a name="line5058"></a><div class="linenumber">5058</div><div style="width:6em;display:inline-block"></div>case "sessionData":
<a name="line5059"></a><div class="linenumber">5059</div><div style="width:8em;display:inline-block"></div>processSessionData(msgData.sessionData);
<a name="line5060"></a><div class="linenumber">5060</div><div style="width:8em;display:inline-block"></div>break;
<a name="line5061"></a><div class="linenumber">5061</div><div style="width:6em;display:inline-block"></div>case "roomData":
<a name="line5062"></a><div class="linenumber">5062</div><div style="width:8em;display:inline-block"></div>processRoomData(msgData.roomData);
<a name="line5063"></a><div class="linenumber">5063</div><div style="width:8em;display:inline-block"></div>break;
<a name="line5064"></a><div class="linenumber">5064</div><div style="width:6em;display:inline-block"></div>case "iceConfig":
<a name="line5065"></a><div class="linenumber">5065</div><div style="width:8em;display:inline-block"></div>processIceConfig(msgData.iceConfig);
<a name="line5066"></a><div class="linenumber">5066</div><div style="width:8em;display:inline-block"></div>break;
<a name="line5067"></a><div class="linenumber">5067</div><div style="width:6em;display:inline-block"></div>case "forwardToUrl":
<a name="line5068"></a><div class="linenumber">5068</div><div style="width:8em;display:inline-block"></div>if (msgData.newWindow) {
<a name="line5069"></a><div class="linenumber">5069</div><div style="width:10em;display:inline-block"></div>window.open(msgData.forwardToUrl.url);
<a name="line5070"></a><div class="linenumber">5070</div><div style="width:8em;display:inline-block"></div>}
<a name="line5071"></a><div class="linenumber">5071</div><div style="width:8em;display:inline-block"></div>else {
<a name="line5072"></a><div class="linenumber">5072</div><div style="width:10em;display:inline-block"></div>window.location.href = msgData.forwardToUrl.url;
<a name="line5073"></a><div class="linenumber">5073</div><div style="width:8em;display:inline-block"></div>}
<a name="line5074"></a><div class="linenumber">5074</div><div style="width:8em;display:inline-block"></div>break;
<a name="line5075"></a><div class="linenumber">5075</div><div style="width:6em;display:inline-block"></div>case "offer":
<a name="line5076"></a><div class="linenumber">5076</div><div style="width:8em;display:inline-block"></div>processOffer(caller, msgData);
<a name="line5077"></a><div class="linenumber">5077</div><div style="width:8em;display:inline-block"></div>break;
<a name="line5078"></a><div class="linenumber">5078</div><div style="width:6em;display:inline-block"></div>case "reject":
<a name="line5079"></a><div class="linenumber">5079</div><div style="width:8em;display:inline-block"></div>processReject(caller);
<a name="line5080"></a><div class="linenumber">5080</div><div style="width:8em;display:inline-block"></div>break;
<a name="line5081"></a><div class="linenumber">5081</div><div style="width:6em;display:inline-block"></div>case "answer":
<a name="line5082"></a><div class="linenumber">5082</div><div style="width:8em;display:inline-block"></div>processAnswer(caller, msgData);
<a name="line5083"></a><div class="linenumber">5083</div><div style="width:8em;display:inline-block"></div>break;
<a name="line5084"></a><div class="linenumber">5084</div><div style="width:6em;display:inline-block"></div>case "candidate":
<a name="line5085"></a><div class="linenumber">5085</div><div style="width:8em;display:inline-block"></div>processCandidateQueue(caller, msgData);
<a name="line5086"></a><div class="linenumber">5086</div><div style="width:8em;display:inline-block"></div>break;
<a name="line5087"></a><div class="linenumber">5087</div><div style="width:6em;display:inline-block"></div>case "hangup":
<a name="line5088"></a><div class="linenumber">5088</div><div style="width:8em;display:inline-block"></div>onRemoteHangup(caller);
<a name="line5089"></a><div class="linenumber">5089</div><div style="width:8em;display:inline-block"></div>clearQueuedMessages(caller);
<a name="line5090"></a><div class="linenumber">5090</div><div style="width:8em;display:inline-block"></div>break;
<a name="line5091"></a><div class="linenumber">5091</div><div style="width:6em;display:inline-block"></div>case "error":
<a name="line5092"></a><div class="linenumber">5092</div><div style="width:8em;display:inline-block"></div>self.showError(msgData.errorCode, msgData.errorText);
<a name="line5093"></a><div class="linenumber">5093</div><div style="width:8em;display:inline-block"></div>break;
<a name="line5094"></a><div class="linenumber">5094</div><div style="width:6em;display:inline-block"></div>default:
<a name="line5095"></a><div class="linenumber">5095</div><div style="width:8em;display:inline-block"></div>self.showError(self.errCodes.DEVELOPER_ERR, "received unknown message type from server, msgType is " + msgType);
<a name="line5096"></a><div class="linenumber">5096</div><div style="width:8em;display:inline-block"></div>return;
<a name="line5097"></a><div class="linenumber">5097</div><div style="width:4em;display:inline-block"></div>}
<a name="line5098"></a><div class="linenumber">5098</div>
<a name="line5099"></a><div class="linenumber">5099</div><div style="width:4em;display:inline-block"></div>if (ackAcceptorFn) {
<a name="line5100"></a><div class="linenumber">5100</div><div style="width:6em;display:inline-block"></div>ackAcceptorFn(self.ackMessage);
<a name="line5101"></a><div class="linenumber">5101</div><div style="width:4em;display:inline-block"></div>}
<a name="line5102"></a><div class="linenumber">5102</div><div style="width:2em;display:inline-block"></div>}
<a name="line5103"></a><div class="linenumber">5103</div>
<a name="line5104"></a><div class="linenumber">5104</div><div style="width:2em;display:inline-block"></div>/**
<a name="line5105"></a><div class="linenumber">5105</div><div style="width:2em;display:inline-block"></div>* Sets the presence state on the server.
<a name="line5106"></a><div class="linenumber">5106</div><div style="width:2em;display:inline-block"></div>* @param {String} state - one of 'away','chat','dnd','xa'
<a name="line5107"></a><div class="linenumber">5107</div><div style="width:2em;display:inline-block"></div>* @param {String} statusText - User configurable status string. May be length limited.
<a name="line5108"></a><div class="linenumber">5108</div><div style="width:2em;display:inline-block"></div>* @example easyrtc.updatePresence('dnd', 'sleeping');
<a name="line5109"></a><div class="linenumber">5109</div><div style="width:2em;display:inline-block"></div>*/
<a name="line5110"></a><div class="linenumber">5110</div><div style="width:2em;display:inline-block"></div>this.updatePresence = function(state, statusText) {
<a name="line5111"></a><div class="linenumber">5111</div>
<a name="line5112"></a><div class="linenumber">5112</div><div style="width:4em;display:inline-block"></div>self.presenceShow = state;
<a name="line5113"></a><div class="linenumber">5113</div><div style="width:4em;display:inline-block"></div>self.presenceStatus = statusText;
<a name="line5114"></a><div class="linenumber">5114</div>
<a name="line5115"></a><div class="linenumber">5115</div><div style="width:4em;display:inline-block"></div>if (self.webSocketConnected) {
<a name="line5116"></a><div class="linenumber">5116</div><div style="width:6em;display:inline-block"></div>sendSignalling(null, 'setPresence', {
<a name="line5117"></a><div class="linenumber">5117</div><div style="width:8em;display:inline-block"></div>setPresence: {
<a name="line5118"></a><div class="linenumber">5118</div><div style="width:10em;display:inline-block"></div>'show': self.presenceShow,
<a name="line5119"></a><div class="linenumber">5119</div><div style="width:10em;display:inline-block"></div>'status': self.presenceStatus
<a name="line5120"></a><div class="linenumber">5120</div><div style="width:8em;display:inline-block"></div>}
<a name="line5121"></a><div class="linenumber">5121</div><div style="width:6em;display:inline-block"></div>}, null);
<a name="line5122"></a><div class="linenumber">5122</div><div style="width:4em;display:inline-block"></div>}
<a name="line5123"></a><div class="linenumber">5123</div><div style="width:2em;display:inline-block"></div>};
<a name="line5124"></a><div class="linenumber">5124</div>
<a name="line5125"></a><div class="linenumber">5125</div><div style="width:2em;display:inline-block"></div>/**
<a name="line5126"></a><div class="linenumber">5126</div><div style="width:2em;display:inline-block"></div>* Fetch the collection of session fields as a map. The map has the structure:
<a name="line5127"></a><div class="linenumber">5127</div><div style="width:2em;display:inline-block"></div>* {key1: {"fieldName": key1, "fieldValue": value1}, ...,
<a name="line5128"></a><div class="linenumber">5128</div><div style="width:2em;display:inline-block"></div>* key2: {"fieldName": key2, "fieldValue": value2}
<a name="line5129"></a><div class="linenumber">5129</div><div style="width:2em;display:inline-block"></div>* }
<a name="line5130"></a><div class="linenumber">5130</div><div style="width:2em;display:inline-block"></div>* @returns {Object}
<a name="line5131"></a><div class="linenumber">5131</div><div style="width:2em;display:inline-block"></div>*/
<a name="line5132"></a><div class="linenumber">5132</div><div style="width:2em;display:inline-block"></div>this.getSessionFields = function() {
<a name="line5133"></a><div class="linenumber">5133</div><div style="width:4em;display:inline-block"></div>return sessionFields;
<a name="line5134"></a><div class="linenumber">5134</div><div style="width:2em;display:inline-block"></div>};
<a name="line5135"></a><div class="linenumber">5135</div>
<a name="line5136"></a><div class="linenumber">5136</div><div style="width:2em;display:inline-block"></div>/**
<a name="line5137"></a><div class="linenumber">5137</div><div style="width:2em;display:inline-block"></div>* Fetch the value of a session field by name.
<a name="line5138"></a><div class="linenumber">5138</div><div style="width:2em;display:inline-block"></div>* @param {String} name - name of the session field to be fetched.
<a name="line5139"></a><div class="linenumber">5139</div><div style="width:2em;display:inline-block"></div>* @returns the field value (which can be anything). Returns undefined if the field does not exist.
<a name="line5140"></a><div class="linenumber">5140</div><div style="width:2em;display:inline-block"></div>*/
<a name="line5141"></a><div class="linenumber">5141</div><div style="width:2em;display:inline-block"></div>this.getSessionField = function(name) {
<a name="line5142"></a><div class="linenumber">5142</div><div style="width:4em;display:inline-block"></div>if (sessionFields[name]) {
<a name="line5143"></a><div class="linenumber">5143</div><div style="width:6em;display:inline-block"></div>return sessionFields[name].fieldValue;
<a name="line5144"></a><div class="linenumber">5144</div><div style="width:4em;display:inline-block"></div>}
<a name="line5145"></a><div class="linenumber">5145</div><div style="width:4em;display:inline-block"></div>else {
<a name="line5146"></a><div class="linenumber">5146</div><div style="width:6em;display:inline-block"></div>return undefined;
<a name="line5147"></a><div class="linenumber">5147</div><div style="width:4em;display:inline-block"></div>}
<a name="line5148"></a><div class="linenumber">5148</div><div style="width:2em;display:inline-block"></div>};
<a name="line5149"></a><div class="linenumber">5149</div>
<a name="line5150"></a><div class="linenumber">5150</div><div style="width:2em;display:inline-block"></div>/**
<a name="line5151"></a><div class="linenumber">5151</div><div style="width:2em;display:inline-block"></div>* Returns an array of easyrtcid's of peers in a particular room.
<a name="line5152"></a><div class="linenumber">5152</div><div style="width:2em;display:inline-block"></div>* @param roomName
<a name="line5153"></a><div class="linenumber">5153</div><div style="width:2em;display:inline-block"></div>* @returns {Array} of easyrtcids or null if the client is not in the room.
<a name="line5154"></a><div class="linenumber">5154</div><div style="width:2em;display:inline-block"></div>* @example
<a name="line5155"></a><div class="linenumber">5155</div><div style="width:2em;display:inline-block"></div>* var occupants = easyrtc.getRoomOccupants("default");
<a name="line5156"></a><div class="linenumber">5156</div><div style="width:2em;display:inline-block"></div>* var i;
<a name="line5157"></a><div class="linenumber">5157</div><div style="width:2em;display:inline-block"></div>* for( i = 0; i < occupants.length; i++ ) {
<a name="line5158"></a><div class="linenumber">5158</div><div style="width:2em;display:inline-block"></div>* console.log( occupants[i] + " is in the room");
<a name="line5159"></a><div class="linenumber">5159</div><div style="width:2em;display:inline-block"></div>* }
<a name="line5160"></a><div class="linenumber">5160</div><div style="width:2em;display:inline-block"></div>*/
<a name="line5161"></a><div class="linenumber">5161</div><div style="width:2em;display:inline-block"></div>this.getRoomOccupantsAsArray = function(roomName) {
<a name="line5162"></a><div class="linenumber">5162</div><div style="width:4em;display:inline-block"></div>if (!lastLoggedInList[roomName]) {
<a name="line5163"></a><div class="linenumber">5163</div><div style="width:6em;display:inline-block"></div>return null;
<a name="line5164"></a><div class="linenumber">5164</div><div style="width:4em;display:inline-block"></div>}
<a name="line5165"></a><div class="linenumber">5165</div><div style="width:4em;display:inline-block"></div>else {
<a name="line5166"></a><div class="linenumber">5166</div><div style="width:6em;display:inline-block"></div>return Object.keys(lastLoggedInList[roomName]);
<a name="line5167"></a><div class="linenumber">5167</div><div style="width:4em;display:inline-block"></div>}
<a name="line5168"></a><div class="linenumber">5168</div><div style="width:2em;display:inline-block"></div>};
<a name="line5169"></a><div class="linenumber">5169</div>
<a name="line5170"></a><div class="linenumber">5170</div><div style="width:2em;display:inline-block"></div>/**
<a name="line5171"></a><div class="linenumber">5171</div><div style="width:2em;display:inline-block"></div>* Returns a map of easyrtcid's of peers in a particular room. You should only test elements in the map to see if they are
<a name="line5172"></a><div class="linenumber">5172</div><div style="width:2em;display:inline-block"></div>* null; their actual values are not guaranteed to be the same in different releases.
<a name="line5173"></a><div class="linenumber">5173</div><div style="width:2em;display:inline-block"></div>* @param roomName
<a name="line5174"></a><div class="linenumber">5174</div><div style="width:2em;display:inline-block"></div>* @returns {Object} of easyrtcids or null if the client is not in the room.
<a name="line5175"></a><div class="linenumber">5175</div><div style="width:2em;display:inline-block"></div>* @example
<a name="line5176"></a><div class="linenumber">5176</div><div style="width:2em;display:inline-block"></div>* if( easyrtc.getRoomOccupantsAsMap("default")[some_easyrtcid]) {
<a name="line5177"></a><div class="linenumber">5177</div><div style="width:2em;display:inline-block"></div>* console.log("yep, " + some_easyrtcid + " is in the room");
<a name="line5178"></a><div class="linenumber">5178</div><div style="width:2em;display:inline-block"></div>* }
<a name="line5179"></a><div class="linenumber">5179</div><div style="width:2em;display:inline-block"></div>*/
<a name="line5180"></a><div class="linenumber">5180</div><div style="width:2em;display:inline-block"></div>this.getRoomOccupantsAsMap = function(roomName) {
<a name="line5181"></a><div class="linenumber">5181</div><div style="width:4em;display:inline-block"></div>return lastLoggedInList[roomName];
<a name="line5182"></a><div class="linenumber">5182</div><div style="width:2em;display:inline-block"></div>};
<a name="line5183"></a><div class="linenumber">5183</div>
<a name="line5184"></a><div class="linenumber">5184</div><div style="width:2em;display:inline-block"></div>/**
<a name="line5185"></a><div class="linenumber">5185</div><div style="width:2em;display:inline-block"></div>* Returns true if the ipAddress parameter was the address of a turn server. This is done by checking against information
<a name="line5186"></a><div class="linenumber">5186</div><div style="width:2em;display:inline-block"></div>* collected during peer to peer calls. Don't expect it to work before the first call, or to identify turn servers that aren't
<a name="line5187"></a><div class="linenumber">5187</div><div style="width:2em;display:inline-block"></div>* in the ice config.
<a name="line5188"></a><div class="linenumber">5188</div><div style="width:2em;display:inline-block"></div>* @param ipAddress
<a name="line5189"></a><div class="linenumber">5189</div><div style="width:2em;display:inline-block"></div>* @returns {boolean} true if ip address is known to be that of a turn server, false otherwise.
<a name="line5190"></a><div class="linenumber">5190</div><div style="width:2em;display:inline-block"></div>*/
<a name="line5191"></a><div class="linenumber">5191</div><div style="width:2em;display:inline-block"></div>this.isTurnServer = function(ipAddress) {
<a name="line5192"></a><div class="linenumber">5192</div><div style="width:4em;display:inline-block"></div>return !!self._turnServers[ipAddress];
<a name="line5193"></a><div class="linenumber">5193</div><div style="width:2em;display:inline-block"></div>};
<a name="line5194"></a><div class="linenumber">5194</div>
<a name="line5195"></a><div class="linenumber">5195</div><div style="width:2em;display:inline-block"></div>/**
<a name="line5196"></a><div class="linenumber">5196</div><div style="width:2em;display:inline-block"></div>* Returns true if the ipAddress parameter was the address of a stun server. This is done by checking against information
<a name="line5197"></a><div class="linenumber">5197</div><div style="width:2em;display:inline-block"></div>* collected during peer to peer calls. Don't expect it to work before the first call, or to identify turn servers that aren't
<a name="line5198"></a><div class="linenumber">5198</div><div style="width:2em;display:inline-block"></div>* in the ice config.
<a name="line5199"></a><div class="linenumber">5199</div><div style="width:2em;display:inline-block"></div>* @param {string} ipAddress
<a name="line5200"></a><div class="linenumber">5200</div><div style="width:2em;display:inline-block"></div>* @returns {boolean} true if ip address is known to be that of a stun server, false otherwise.
<a name="line5201"></a><div class="linenumber">5201</div><div style="width:2em;display:inline-block"></div>*/
<a name="line5202"></a><div class="linenumber">5202</div><div style="width:2em;display:inline-block"></div>this.isStunServer = function(ipAddress) {
<a name="line5203"></a><div class="linenumber">5203</div><div style="width:4em;display:inline-block"></div>return !!self._stunServers[ipAddress];
<a name="line5204"></a><div class="linenumber">5204</div><div style="width:2em;display:inline-block"></div>};
<a name="line5205"></a><div class="linenumber">5205</div>
<a name="line5206"></a><div class="linenumber">5206</div><div style="width:2em;display:inline-block"></div>/**
<a name="line5207"></a><div class="linenumber">5207</div><div style="width:2em;display:inline-block"></div>* Request fresh ice config information from the server.
<a name="line5208"></a><div class="linenumber">5208</div><div style="width:2em;display:inline-block"></div>* This should be done periodically by long running applications.
<a name="line5209"></a><div class="linenumber">5209</div><div style="width:2em;display:inline-block"></div>* @param {Function} callback is called with a value of true on success, false on failure.
<a name="line5210"></a><div class="linenumber">5210</div><div style="width:2em;display:inline-block"></div>*/
<a name="line5211"></a><div class="linenumber">5211</div><div style="width:2em;display:inline-block"></div>this.getFreshIceConfig = function(callback) {
<a name="line5212"></a><div class="linenumber">5212</div><div style="width:4em;display:inline-block"></div>var dataToShip = {
<a name="line5213"></a><div class="linenumber">5213</div><div style="width:6em;display:inline-block"></div>msgType: "getIceConfig",
<a name="line5214"></a><div class="linenumber">5214</div><div style="width:6em;display:inline-block"></div>msgData: {}
<a name="line5215"></a><div class="linenumber">5215</div><div style="width:4em;display:inline-block"></div>};
<a name="line5216"></a><div class="linenumber">5216</div><div style="width:4em;display:inline-block"></div>if (!callback) {
<a name="line5217"></a><div class="linenumber">5217</div><div style="width:6em;display:inline-block"></div>callback = function() {
<a name="line5218"></a><div class="linenumber">5218</div><div style="width:6em;display:inline-block"></div>};
<a name="line5219"></a><div class="linenumber">5219</div><div style="width:4em;display:inline-block"></div>}
<a name="line5220"></a><div class="linenumber">5220</div><div style="width:4em;display:inline-block"></div>self.webSocket.json.emit("easyrtcCmd", dataToShip,
<a name="line5221"></a><div class="linenumber">5221</div><div style="width:8em;display:inline-block"></div>function(ackMsg) {
<a name="line5222"></a><div class="linenumber">5222</div><div style="width:10em;display:inline-block"></div>if (ackMsg.msgType === "iceConfig") {
<a name="line5223"></a><div class="linenumber">5223</div><div style="width:12em;display:inline-block"></div>processIceConfig(ackMsg.msgData.iceConfig);
<a name="line5224"></a><div class="linenumber">5224</div><div style="width:12em;display:inline-block"></div>callback(true);
<a name="line5225"></a><div class="linenumber">5225</div><div style="width:10em;display:inline-block"></div>}
<a name="line5226"></a><div class="linenumber">5226</div><div style="width:10em;display:inline-block"></div>else {
<a name="line5227"></a><div class="linenumber">5227</div><div style="width:12em;display:inline-block"></div>self.showError(ackMsg.msgData.errorCode, ackMsg.msgData.errorText);
<a name="line5228"></a><div class="linenumber">5228</div><div style="width:12em;display:inline-block"></div>callback(false);
<a name="line5229"></a><div class="linenumber">5229</div><div style="width:10em;display:inline-block"></div>}
<a name="line5230"></a><div class="linenumber">5230</div><div style="width:8em;display:inline-block"></div>}
<a name="line5231"></a><div class="linenumber">5231</div><div style="width:4em;display:inline-block"></div>);
<a name="line5232"></a><div class="linenumber">5232</div><div style="width:2em;display:inline-block"></div>};
<a name="line5233"></a><div class="linenumber">5233</div>
<a name="line5234"></a><div class="linenumber">5234</div><div style="width:2em;display:inline-block"></div>/**
<a name="line5235"></a><div class="linenumber">5235</div><div style="width:2em;display:inline-block"></div>* This method allows you to join a single room. It may be called multiple times to be in
<a name="line5236"></a><div class="linenumber">5236</div><div style="width:2em;display:inline-block"></div>* multiple rooms simultaneously. It may be called before or after connecting to the server.
<a name="line5237"></a><div class="linenumber">5237</div><div style="width:2em;display:inline-block"></div>* Note: the successCB and failureDB will only be called if you are already connected to the server.
<a name="line5238"></a><div class="linenumber">5238</div><div style="width:2em;display:inline-block"></div>* @param {String} roomName the room to be joined.
<a name="line5239"></a><div class="linenumber">5239</div><div style="width:2em;display:inline-block"></div>* @param {Object} roomParameters application specific parameters, can be null.
<a name="line5240"></a><div class="linenumber">5240</div><div style="width:2em;display:inline-block"></div>* @param {Function} successCB called once, with a roomName as it's argument, once the room is joined.
<a name="line5241"></a><div class="linenumber">5241</div><div style="width:2em;display:inline-block"></div>* @param {Function} failureCB called if the room can not be joined. The arguments of failureCB are errorCode, errorText, roomName.
<a name="line5242"></a><div class="linenumber">5242</div><div style="width:2em;display:inline-block"></div>*/
<a name="line5243"></a><div class="linenumber">5243</div><div style="width:2em;display:inline-block"></div>this.joinRoom = function(roomName, roomParameters, successCB, failureCB) {
<a name="line5244"></a><div class="linenumber">5244</div><div style="width:4em;display:inline-block"></div>if (self.roomJoin[roomName]) {
<a name="line5245"></a><div class="linenumber">5245</div><div style="width:6em;display:inline-block"></div>self.showError(self.errCodes.DEVELOPER_ERR, "Attempt to join room " + roomName + " which you are already in.");
<a name="line5246"></a><div class="linenumber">5246</div><div style="width:6em;display:inline-block"></div>return;
<a name="line5247"></a><div class="linenumber">5247</div><div style="width:4em;display:inline-block"></div>}
<a name="line5248"></a><div class="linenumber">5248</div>
<a name="line5249"></a><div class="linenumber">5249</div><div style="width:4em;display:inline-block"></div>var newRoomData = {roomName: roomName};
<a name="line5250"></a><div class="linenumber">5250</div><div style="width:4em;display:inline-block"></div>if (roomParameters) {
<a name="line5251"></a><div class="linenumber">5251</div><div style="width:6em;display:inline-block"></div>try {
<a name="line5252"></a><div class="linenumber">5252</div><div style="width:8em;display:inline-block"></div>JSON.stringify(roomParameters);
<a name="line5253"></a><div class="linenumber">5253</div><div style="width:6em;display:inline-block"></div>} catch (error) {
<a name="line5254"></a><div class="linenumber">5254</div><div style="width:8em;display:inline-block"></div>self.showError(self.errCodes.DEVELOPER_ERR, "non-jsonable parameter to easyrtc.joinRoom");
<a name="line5255"></a><div class="linenumber">5255</div><div style="width:8em;display:inline-block"></div>throw "Developer error, see application error messages";
<a name="line5256"></a><div class="linenumber">5256</div><div style="width:6em;display:inline-block"></div>}
<a name="line5257"></a><div class="linenumber">5257</div><div style="width:6em;display:inline-block"></div>var parameters = {};
<a name="line5258"></a><div class="linenumber">5258</div><div style="width:6em;display:inline-block"></div>for (var key in roomParameters) {
<a name="line5259"></a><div class="linenumber">5259</div><div style="width:8em;display:inline-block"></div>if (roomParameters.hasOwnProperty(key)) {
<a name="line5260"></a><div class="linenumber">5260</div><div style="width:10em;display:inline-block"></div>parameters[key] = roomParameters[key];
<a name="line5261"></a><div class="linenumber">5261</div><div style="width:8em;display:inline-block"></div>}
<a name="line5262"></a><div class="linenumber">5262</div><div style="width:6em;display:inline-block"></div>}
<a name="line5263"></a><div class="linenumber">5263</div><div style="width:6em;display:inline-block"></div>newRoomData.roomParameter = parameters;
<a name="line5264"></a><div class="linenumber">5264</div><div style="width:4em;display:inline-block"></div>}
<a name="line5265"></a><div class="linenumber">5265</div><div style="width:4em;display:inline-block"></div>var msgData = {
<a name="line5266"></a><div class="linenumber">5266</div><div style="width:6em;display:inline-block"></div>roomJoin: {}
<a name="line5267"></a><div class="linenumber">5267</div><div style="width:4em;display:inline-block"></div>};
<a name="line5268"></a><div class="linenumber">5268</div><div style="width:4em;display:inline-block"></div>var roomData;
<a name="line5269"></a><div class="linenumber">5269</div><div style="width:4em;display:inline-block"></div>var signallingSuccess, signallingFailure;
<a name="line5270"></a><div class="linenumber">5270</div><div style="width:4em;display:inline-block"></div>if (self.webSocket) {
<a name="line5271"></a><div class="linenumber">5271</div>
<a name="line5272"></a><div class="linenumber">5272</div><div style="width:6em;display:inline-block"></div>msgData.roomJoin[roomName] = newRoomData;
<a name="line5273"></a><div class="linenumber">5273</div><div style="width:6em;display:inline-block"></div>signallingSuccess = function(msgType, msgData) {
<a name="line5274"></a><div class="linenumber">5274</div>
<a name="line5275"></a><div class="linenumber">5275</div><div style="width:8em;display:inline-block"></div>roomData = msgData.roomData;
<a name="line5276"></a><div class="linenumber">5276</div><div style="width:8em;display:inline-block"></div>self.roomJoin[roomName] = newRoomData;
<a name="line5277"></a><div class="linenumber">5277</div><div style="width:8em;display:inline-block"></div>if (successCB) {
<a name="line5278"></a><div class="linenumber">5278</div><div style="width:10em;display:inline-block"></div>successCB(roomName);
<a name="line5279"></a><div class="linenumber">5279</div><div style="width:8em;display:inline-block"></div>}
<a name="line5280"></a><div class="linenumber">5280</div>
<a name="line5281"></a><div class="linenumber">5281</div><div style="width:8em;display:inline-block"></div>processRoomData(roomData);
<a name="line5282"></a><div class="linenumber">5282</div><div style="width:6em;display:inline-block"></div>};
<a name="line5283"></a><div class="linenumber">5283</div><div style="width:6em;display:inline-block"></div>signallingFailure = function(errorCode, errorText) {
<a name="line5284"></a><div class="linenumber">5284</div><div style="width:8em;display:inline-block"></div>if (failureCB) {
<a name="line5285"></a><div class="linenumber">5285</div><div style="width:10em;display:inline-block"></div>failureCB(errorCode, errorText, roomName);
<a name="line5286"></a><div class="linenumber">5286</div><div style="width:8em;display:inline-block"></div>}
<a name="line5287"></a><div class="linenumber">5287</div><div style="width:8em;display:inline-block"></div>else {
<a name="line5288"></a><div class="linenumber">5288</div><div style="width:10em;display:inline-block"></div>self.showError(errorCode, self.format(self.getConstantString("unableToEnterRoom"), roomName, errorText));
<a name="line5289"></a><div class="linenumber">5289</div><div style="width:8em;display:inline-block"></div>}
<a name="line5290"></a><div class="linenumber">5290</div><div style="width:6em;display:inline-block"></div>};
<a name="line5291"></a><div class="linenumber">5291</div><div style="width:6em;display:inline-block"></div>sendSignalling(null, "roomJoin", msgData, signallingSuccess, signallingFailure);
<a name="line5292"></a><div class="linenumber">5292</div><div style="width:4em;display:inline-block"></div>}
<a name="line5293"></a><div class="linenumber">5293</div><div style="width:4em;display:inline-block"></div>else {
<a name="line5294"></a><div class="linenumber">5294</div><div style="width:6em;display:inline-block"></div>self.roomJoin[roomName] = newRoomData;
<a name="line5295"></a><div class="linenumber">5295</div><div style="width:4em;display:inline-block"></div>}
<a name="line5296"></a><div class="linenumber">5296</div>
<a name="line5297"></a><div class="linenumber">5297</div><div style="width:2em;display:inline-block"></div>};
<a name="line5298"></a><div class="linenumber">5298</div>
<a name="line5299"></a><div class="linenumber">5299</div><div style="width:2em;display:inline-block"></div>/**
<a name="line5300"></a><div class="linenumber">5300</div><div style="width:2em;display:inline-block"></div>* This function allows you to leave a single room. Note: the successCB and failureDB
<a name="line5301"></a><div class="linenumber">5301</div><div style="width:2em;display:inline-block"></div>* arguments are optional and will only be called if you are already connected to the server.
<a name="line5302"></a><div class="linenumber">5302</div><div style="width:2em;display:inline-block"></div>* @param {String} roomName
<a name="line5303"></a><div class="linenumber">5303</div><div style="width:2em;display:inline-block"></div>* @param {Function} successCallback - A function which expects a roomName.
<a name="line5304"></a><div class="linenumber">5304</div><div style="width:2em;display:inline-block"></div>* @param {Function} failureCallback - A function which expects the following arguments: errorCode, errorText, roomName.
<a name="line5305"></a><div class="linenumber">5305</div><div style="width:2em;display:inline-block"></div>* @example
<a name="line5306"></a><div class="linenumber">5306</div><div style="width:2em;display:inline-block"></div>* easyrtc.leaveRoom("freds_room");
<a name="line5307"></a><div class="linenumber">5307</div><div style="width:2em;display:inline-block"></div>* easyrtc.leaveRoom("freds_room", function(roomName){ console.log("left the room")},
<a name="line5308"></a><div class="linenumber">5308</div><div style="width:2em;display:inline-block"></div>* function(errorCode, errorText, roomName){ console.log("left the room")});
<a name="line5309"></a><div class="linenumber">5309</div><div style="width:2em;display:inline-block"></div>*/
<a name="line5310"></a><div class="linenumber">5310</div><div style="width:2em;display:inline-block"></div>this.leaveRoom = function(roomName, successCallback, failureCallback) {
<a name="line5311"></a><div class="linenumber">5311</div><div style="width:4em;display:inline-block"></div>var roomItem;
<a name="line5312"></a><div class="linenumber">5312</div><div style="width:4em;display:inline-block"></div>if (self.roomJoin[roomName]) {
<a name="line5313"></a><div class="linenumber">5313</div><div style="width:6em;display:inline-block"></div>if (!self.webSocket) {
<a name="line5314"></a><div class="linenumber">5314</div><div style="width:8em;display:inline-block"></div>delete self.roomJoin[roomName];
<a name="line5315"></a><div class="linenumber">5315</div><div style="width:6em;display:inline-block"></div>}
<a name="line5316"></a><div class="linenumber">5316</div><div style="width:6em;display:inline-block"></div>else {
<a name="line5317"></a><div class="linenumber">5317</div><div style="width:8em;display:inline-block"></div>roomItem = {};
<a name="line5318"></a><div class="linenumber">5318</div><div style="width:8em;display:inline-block"></div>roomItem[roomName] = {roomName: roomName};
<a name="line5319"></a><div class="linenumber">5319</div><div style="width:8em;display:inline-block"></div>sendSignalling(null, "roomLeave", {roomLeave: roomItem},
<a name="line5320"></a><div class="linenumber">5320</div><div style="width:8em;display:inline-block"></div>function(msgType, msgData) {
<a name="line5321"></a><div class="linenumber">5321</div><div style="width:10em;display:inline-block"></div>var roomData = msgData.roomData;
<a name="line5322"></a><div class="linenumber">5322</div><div style="width:10em;display:inline-block"></div>processRoomData(roomData);
<a name="line5323"></a><div class="linenumber">5323</div><div style="width:10em;display:inline-block"></div>if (successCallback) {
<a name="line5324"></a><div class="linenumber">5324</div><div style="width:12em;display:inline-block"></div>successCallback(roomName);
<a name="line5325"></a><div class="linenumber">5325</div><div style="width:10em;display:inline-block"></div>}
<a name="line5326"></a><div class="linenumber">5326</div><div style="width:8em;display:inline-block"></div>},
<a name="line5327"></a><div class="linenumber">5327</div><div style="width:12em;display:inline-block"></div>function(errorCode, errorText) {
<a name="line5328"></a><div class="linenumber">5328</div><div style="width:14em;display:inline-block"></div>if (failureCallback) {
<a name="line5329"></a><div class="linenumber">5329</div><div style="width:16em;display:inline-block"></div>failureCallback(errorCode, errorText, roomName);
<a name="line5330"></a><div class="linenumber">5330</div><div style="width:14em;display:inline-block"></div>}
<a name="line5331"></a><div class="linenumber">5331</div><div style="width:12em;display:inline-block"></div>});
<a name="line5332"></a><div class="linenumber">5332</div><div style="width:6em;display:inline-block"></div>}
<a name="line5333"></a><div class="linenumber">5333</div><div style="width:4em;display:inline-block"></div>}
<a name="line5334"></a><div class="linenumber">5334</div><div style="width:2em;display:inline-block"></div>};
<a name="line5335"></a><div class="linenumber">5335</div>
<a name="line5336"></a><div class="linenumber">5336</div><div style="width:2em;display:inline-block"></div>/** Get a list of the rooms you are in. You must be connected to call this function.
<a name="line5337"></a><div class="linenumber">5337</div><div style="width:2em;display:inline-block"></div>* @returns {Object} A map whose keys are the room names
<a name="line5338"></a><div class="linenumber">5338</div><div style="width:2em;display:inline-block"></div>*/
<a name="line5339"></a><div class="linenumber">5339</div><div style="width:2em;display:inline-block"></div>this.getRoomsJoined = function() {
<a name="line5340"></a><div class="linenumber">5340</div><div style="width:4em;display:inline-block"></div>var roomsIn = {};
<a name="line5341"></a><div class="linenumber">5341</div><div style="width:4em;display:inline-block"></div>var key;
<a name="line5342"></a><div class="linenumber">5342</div><div style="width:4em;display:inline-block"></div>for (key in self.roomJoin) {
<a name="line5343"></a><div class="linenumber">5343</div><div style="width:6em;display:inline-block"></div>if (self.roomJoin.hasOwnProperty(key)) {
<a name="line5344"></a><div class="linenumber">5344</div><div style="width:8em;display:inline-block"></div>roomsIn[key] = true;
<a name="line5345"></a><div class="linenumber">5345</div><div style="width:6em;display:inline-block"></div>}
<a name="line5346"></a><div class="linenumber">5346</div><div style="width:4em;display:inline-block"></div>}
<a name="line5347"></a><div class="linenumber">5347</div><div style="width:4em;display:inline-block"></div>return roomsIn;
<a name="line5348"></a><div class="linenumber">5348</div><div style="width:2em;display:inline-block"></div>};
<a name="line5349"></a><div class="linenumber">5349</div>
<a name="line5350"></a><div class="linenumber">5350</div><div style="width:2em;display:inline-block"></div>/** Get server defined fields associated with a particular room. Only valid
<a name="line5351"></a><div class="linenumber">5351</div><div style="width:2em;display:inline-block"></div>* after a connection has been made.
<a name="line5352"></a><div class="linenumber">5352</div><div style="width:2em;display:inline-block"></div>* @param {String} roomName - the name of the room you want the fields for.
<a name="line5353"></a><div class="linenumber">5353</div><div style="width:2em;display:inline-block"></div>* @returns {Object} A dictionary containing entries of the form {key:{'fieldName':key, 'fieldValue':value1}} or undefined
<a name="line5354"></a><div class="linenumber">5354</div><div style="width:2em;display:inline-block"></div>* if you are not connected to the room.
<a name="line5355"></a><div class="linenumber">5355</div><div style="width:2em;display:inline-block"></div>*/
<a name="line5356"></a><div class="linenumber">5356</div><div style="width:2em;display:inline-block"></div>this.getRoomFields = function(roomName) {
<a name="line5357"></a><div class="linenumber">5357</div><div style="width:4em;display:inline-block"></div>return (!fields || !fields.rooms || !fields.rooms[roomName]) ?
<a name="line5358"></a><div class="linenumber">5358</div><div style="width:10em;display:inline-block"></div>undefined : fields.rooms[roomName];
<a name="line5359"></a><div class="linenumber">5359</div><div style="width:2em;display:inline-block"></div>};
<a name="line5360"></a><div class="linenumber">5360</div>
<a name="line5361"></a><div class="linenumber">5361</div><div style="width:2em;display:inline-block"></div>/** Get server defined fields associated with the current application. Only valid
<a name="line5362"></a><div class="linenumber">5362</div><div style="width:2em;display:inline-block"></div>* after a connection has been made.
<a name="line5363"></a><div class="linenumber">5363</div><div style="width:2em;display:inline-block"></div>* @returns {Object} A dictionary containing entries of the form {key:{'fieldName':key, 'fieldValue':value1}}
<a name="line5364"></a><div class="linenumber">5364</div><div style="width:2em;display:inline-block"></div>*/
<a name="line5365"></a><div class="linenumber">5365</div><div style="width:2em;display:inline-block"></div>this.getApplicationFields = function() {
<a name="line5366"></a><div class="linenumber">5366</div><div style="width:4em;display:inline-block"></div>return fields.application;
<a name="line5367"></a><div class="linenumber">5367</div><div style="width:2em;display:inline-block"></div>};
<a name="line5368"></a><div class="linenumber">5368</div>
<a name="line5369"></a><div class="linenumber">5369</div><div style="width:2em;display:inline-block"></div>/** Get server defined fields associated with the connection. Only valid
<a name="line5370"></a><div class="linenumber">5370</div><div style="width:2em;display:inline-block"></div>* after a connection has been made.
<a name="line5371"></a><div class="linenumber">5371</div><div style="width:2em;display:inline-block"></div>* @returns {Object} A dictionary containing entries of the form {key:{'fieldName':key, 'fieldValue':value1}}
<a name="line5372"></a><div class="linenumber">5372</div><div style="width:2em;display:inline-block"></div>*/
<a name="line5373"></a><div class="linenumber">5373</div><div style="width:2em;display:inline-block"></div>this.getConnectionFields = function() {
<a name="line5374"></a><div class="linenumber">5374</div><div style="width:4em;display:inline-block"></div>return fields.connection;
<a name="line5375"></a><div class="linenumber">5375</div><div style="width:2em;display:inline-block"></div>};
<a name="line5376"></a><div class="linenumber">5376</div>
<a name="line5377"></a><div class="linenumber">5377</div><div style="width:2em;display:inline-block"></div>/**
<a name="line5378"></a><div class="linenumber">5378</div><div style="width:2em;display:inline-block"></div>* Supply a socket.io connection that will be used instead of allocating a new socket.
<a name="line5379"></a><div class="linenumber">5379</div><div style="width:2em;display:inline-block"></div>* The expected usage is that you allocate a websocket, assign options to it, call
<a name="line5380"></a><div class="linenumber">5380</div><div style="width:2em;display:inline-block"></div>* easyrtc.useThisSocketConnection, followed by easyrtc.connect or easyrtc.easyApp. Easyrtc will not attempt to
<a name="line5381"></a><div class="linenumber">5381</div><div style="width:2em;display:inline-block"></div>* close sockets that were supplied with easyrtc.useThisSocketConnection.
<a name="line5382"></a><div class="linenumber">5382</div><div style="width:2em;display:inline-block"></div>* @param {Object} alreadyAllocatedSocketIo A value allocated with the connect method of socket.io.
<a name="line5383"></a><div class="linenumber">5383</div><div style="width:2em;display:inline-block"></div>*/
<a name="line5384"></a><div class="linenumber">5384</div><div style="width:2em;display:inline-block"></div>this.useThisSocketConnection = function(alreadyAllocatedSocketIo) {
<a name="line5385"></a><div class="linenumber">5385</div><div style="width:4em;display:inline-block"></div>preallocatedSocketIo = alreadyAllocatedSocketIo;
<a name="line5386"></a><div class="linenumber">5386</div><div style="width:2em;display:inline-block"></div>};
<a name="line5387"></a><div class="linenumber">5387</div>
<a name="line5388"></a><div class="linenumber">5388</div><div style="width:2em;display:inline-block"></div>/** @private */
<a name="line5389"></a><div class="linenumber">5389</div><div style="width:2em;display:inline-block"></div>function processToken(msg) {
<a name="line5390"></a><div class="linenumber">5390</div><div style="width:4em;display:inline-block"></div>var msgData = msg.msgData;
<a name="line5391"></a><div class="linenumber">5391</div><div style="width:4em;display:inline-block"></div>logDebug("entered process token");
<a name="line5392"></a><div class="linenumber">5392</div>
<a name="line5393"></a><div class="linenumber">5393</div><div style="width:4em;display:inline-block"></div>if (msgData.easyrtcid) {
<a name="line5394"></a><div class="linenumber">5394</div><div style="width:6em;display:inline-block"></div>self.myEasyrtcid = msgData.easyrtcid;
<a name="line5395"></a><div class="linenumber">5395</div><div style="width:4em;display:inline-block"></div>}
<a name="line5396"></a><div class="linenumber">5396</div><div style="width:4em;display:inline-block"></div>if (msgData.field) {
<a name="line5397"></a><div class="linenumber">5397</div><div style="width:6em;display:inline-block"></div>fields.connection = msgData.field;
<a name="line5398"></a><div class="linenumber">5398</div><div style="width:4em;display:inline-block"></div>}
<a name="line5399"></a><div class="linenumber">5399</div><div style="width:4em;display:inline-block"></div>if (msgData.iceConfig) {
<a name="line5400"></a><div class="linenumber">5400</div><div style="width:6em;display:inline-block"></div>processIceConfig(msgData.iceConfig);
<a name="line5401"></a><div class="linenumber">5401</div><div style="width:4em;display:inline-block"></div>}
<a name="line5402"></a><div class="linenumber">5402</div>
<a name="line5403"></a><div class="linenumber">5403</div><div style="width:4em;display:inline-block"></div>if (msgData.sessionData) {
<a name="line5404"></a><div class="linenumber">5404</div><div style="width:6em;display:inline-block"></div>processSessionData(msgData.sessionData);
<a name="line5405"></a><div class="linenumber">5405</div><div style="width:4em;display:inline-block"></div>}
<a name="line5406"></a><div class="linenumber">5406</div><div style="width:4em;display:inline-block"></div>if (msgData.roomData) {
<a name="line5407"></a><div class="linenumber">5407</div><div style="width:6em;display:inline-block"></div>processRoomData(msgData.roomData);
<a name="line5408"></a><div class="linenumber">5408</div><div style="width:4em;display:inline-block"></div>}
<a name="line5409"></a><div class="linenumber">5409</div><div style="width:4em;display:inline-block"></div>if (msgData.application.field) {
<a name="line5410"></a><div class="linenumber">5410</div><div style="width:6em;display:inline-block"></div>fields.application = msgData.application.field;
<a name="line5411"></a><div class="linenumber">5411</div><div style="width:4em;display:inline-block"></div>}
<a name="line5412"></a><div class="linenumber">5412</div><div style="width:2em;display:inline-block"></div>}
<a name="line5413"></a><div class="linenumber">5413</div>
<a name="line5414"></a><div class="linenumber">5414</div><div style="width:2em;display:inline-block"></div>/** @private */
<a name="line5415"></a><div class="linenumber">5415</div><div style="width:2em;display:inline-block"></div>function sendAuthenticate(successCallback, errorCallback) {
<a name="line5416"></a><div class="linenumber">5416</div><div style="width:4em;display:inline-block"></div>//
<a name="line5417"></a><div class="linenumber">5417</div><div style="width:4em;display:inline-block"></div>// find our easyrtcsid
<a name="line5418"></a><div class="linenumber">5418</div><div style="width:4em;display:inline-block"></div>//
<a name="line5419"></a><div class="linenumber">5419</div><div style="width:4em;display:inline-block"></div>var cookies, target, i;
<a name="line5420"></a><div class="linenumber">5420</div><div style="width:4em;display:inline-block"></div>var easyrtcsid = null;
<a name="line5421"></a><div class="linenumber">5421</div>
<a name="line5422"></a><div class="linenumber">5422</div><div style="width:4em;display:inline-block"></div>if (self.cookieId && document.cookie) {
<a name="line5423"></a><div class="linenumber">5423</div><div style="width:6em;display:inline-block"></div>cookies = document.cookie.split(/[; ]/g);
<a name="line5424"></a><div class="linenumber">5424</div><div style="width:6em;display:inline-block"></div>target = self.cookieId + "=";
<a name="line5425"></a><div class="linenumber">5425</div><div style="width:6em;display:inline-block"></div>for (i = 0; i < cookies.length; i++) {
<a name="line5426"></a><div class="linenumber">5426</div><div style="width:8em;display:inline-block"></div>if (cookies[i].indexOf(target) === 0) {
<a name="line5427"></a><div class="linenumber">5427</div><div style="width:10em;display:inline-block"></div>easyrtcsid = cookies[i].substring(target.length);
<a name="line5428"></a><div class="linenumber">5428</div><div style="width:8em;display:inline-block"></div>}
<a name="line5429"></a><div class="linenumber">5429</div><div style="width:6em;display:inline-block"></div>}
<a name="line5430"></a><div class="linenumber">5430</div><div style="width:4em;display:inline-block"></div>}
<a name="line5431"></a><div class="linenumber">5431</div>
<a name="line5432"></a><div class="linenumber">5432</div><div style="width:4em;display:inline-block"></div>var msgData = {
<a name="line5433"></a><div class="linenumber">5433</div><div style="width:6em;display:inline-block"></div>apiVersion: self.apiVersion,
<a name="line5434"></a><div class="linenumber">5434</div><div style="width:6em;display:inline-block"></div>applicationName: self.applicationName,
<a name="line5435"></a><div class="linenumber">5435</div><div style="width:6em;display:inline-block"></div>setUserCfg: collectConfigurationInfo(true)
<a name="line5436"></a><div class="linenumber">5436</div><div style="width:4em;display:inline-block"></div>};
<a name="line5437"></a><div class="linenumber">5437</div>
<a name="line5438"></a><div class="linenumber">5438</div><div style="width:4em;display:inline-block"></div>if (!self.roomJoin) {
<a name="line5439"></a><div class="linenumber">5439</div><div style="width:6em;display:inline-block"></div>self.roomJoin = {};
<a name="line5440"></a><div class="linenumber">5440</div><div style="width:4em;display:inline-block"></div>}
<a name="line5441"></a><div class="linenumber">5441</div><div style="width:4em;display:inline-block"></div>if (self.presenceShow) {
<a name="line5442"></a><div class="linenumber">5442</div><div style="width:6em;display:inline-block"></div>msgData.setPresence = {
<a name="line5443"></a><div class="linenumber">5443</div><div style="width:8em;display:inline-block"></div>show: self.presenceShow,
<a name="line5444"></a><div class="linenumber">5444</div><div style="width:8em;display:inline-block"></div>status: self.presenceStatus
<a name="line5445"></a><div class="linenumber">5445</div><div style="width:6em;display:inline-block"></div>};
<a name="line5446"></a><div class="linenumber">5446</div><div style="width:4em;display:inline-block"></div>}
<a name="line5447"></a><div class="linenumber">5447</div><div style="width:4em;display:inline-block"></div>if (self.username) {
<a name="line5448"></a><div class="linenumber">5448</div><div style="width:6em;display:inline-block"></div>msgData.username = self.username;
<a name="line5449"></a><div class="linenumber">5449</div><div style="width:4em;display:inline-block"></div>}
<a name="line5450"></a><div class="linenumber">5450</div><div style="width:4em;display:inline-block"></div>if (self.roomJoin && !isEmptyObj(self.roomJoin)) {
<a name="line5451"></a><div class="linenumber">5451</div><div style="width:6em;display:inline-block"></div>msgData.roomJoin = self.roomJoin;
<a name="line5452"></a><div class="linenumber">5452</div><div style="width:4em;display:inline-block"></div>}
<a name="line5453"></a><div class="linenumber">5453</div><div style="width:4em;display:inline-block"></div>if (easyrtcsid) {
<a name="line5454"></a><div class="linenumber">5454</div><div style="width:6em;display:inline-block"></div>msgData.easyrtcsid = easyrtcsid;
<a name="line5455"></a><div class="linenumber">5455</div><div style="width:4em;display:inline-block"></div>}
<a name="line5456"></a><div class="linenumber">5456</div><div style="width:4em;display:inline-block"></div>if (credential) {
<a name="line5457"></a><div class="linenumber">5457</div><div style="width:6em;display:inline-block"></div>msgData.credential = credential;
<a name="line5458"></a><div class="linenumber">5458</div><div style="width:4em;display:inline-block"></div>}
<a name="line5459"></a><div class="linenumber">5459</div>
<a name="line5460"></a><div class="linenumber">5460</div><div style="width:4em;display:inline-block"></div>self.webSocket.json.emit(
<a name="line5461"></a><div class="linenumber">5461</div><div style="width:6em;display:inline-block"></div>"easyrtcAuth",
<a name="line5462"></a><div class="linenumber">5462</div><div style="width:6em;display:inline-block"></div>{
<a name="line5463"></a><div class="linenumber">5463</div><div style="width:8em;display:inline-block"></div>msgType: "authenticate",
<a name="line5464"></a><div class="linenumber">5464</div><div style="width:8em;display:inline-block"></div>msgData: msgData
<a name="line5465"></a><div class="linenumber">5465</div><div style="width:6em;display:inline-block"></div>},
<a name="line5466"></a><div class="linenumber">5466</div><div style="width:6em;display:inline-block"></div>function(msg) {
<a name="line5467"></a><div class="linenumber">5467</div><div style="width:8em;display:inline-block"></div>var room;
<a name="line5468"></a><div class="linenumber">5468</div><div style="width:8em;display:inline-block"></div>if (msg.msgType === "error") {
<a name="line5469"></a><div class="linenumber">5469</div><div style="width:10em;display:inline-block"></div>errorCallback(msg.msgData.errorCode, msg.msgData.errorText);
<a name="line5470"></a><div class="linenumber">5470</div><div style="width:10em;display:inline-block"></div>self.roomJoin = {};
<a name="line5471"></a><div class="linenumber">5471</div><div style="width:8em;display:inline-block"></div>}
<a name="line5472"></a><div class="linenumber">5472</div><div style="width:8em;display:inline-block"></div>else {
<a name="line5473"></a><div class="linenumber">5473</div><div style="width:10em;display:inline-block"></div>processToken(msg);
<a name="line5474"></a><div class="linenumber">5474</div><div style="width:10em;display:inline-block"></div>if (self._roomApiFields) {
<a name="line5475"></a><div class="linenumber">5475</div><div style="width:12em;display:inline-block"></div>for (room in self._roomApiFields) {
<a name="line5476"></a><div class="linenumber">5476</div><div style="width:14em;display:inline-block"></div>if (self._roomApiFields.hasOwnProperty(room)) {
<a name="line5477"></a><div class="linenumber">5477</div><div style="width:16em;display:inline-block"></div>enqueueSendRoomApi(room);
<a name="line5478"></a><div class="linenumber">5478</div><div style="width:14em;display:inline-block"></div>}
<a name="line5479"></a><div class="linenumber">5479</div><div style="width:12em;display:inline-block"></div>}
<a name="line5480"></a><div class="linenumber">5480</div><div style="width:10em;display:inline-block"></div>}
<a name="line5481"></a><div class="linenumber">5481</div>
<a name="line5482"></a><div class="linenumber">5482</div><div style="width:10em;display:inline-block"></div>if (successCallback) {
<a name="line5483"></a><div class="linenumber">5483</div><div style="width:12em;display:inline-block"></div>successCallback(self.myEasyrtcid);
<a name="line5484"></a><div class="linenumber">5484</div><div style="width:10em;display:inline-block"></div>}
<a name="line5485"></a><div class="linenumber">5485</div><div style="width:8em;display:inline-block"></div>}
<a name="line5486"></a><div class="linenumber">5486</div><div style="width:6em;display:inline-block"></div>}
<a name="line5487"></a><div class="linenumber">5487</div><div style="width:4em;display:inline-block"></div>);
<a name="line5488"></a><div class="linenumber">5488</div><div style="width:2em;display:inline-block"></div>}
<a name="line5489"></a><div class="linenumber">5489</div>
<a name="line5490"></a><div class="linenumber">5490</div><div style="width:2em;display:inline-block"></div>/** @private */
<a name="line5491"></a><div class="linenumber">5491</div><div style="width:2em;display:inline-block"></div>function connectToWSServer(successCallback, errorCallback) {
<a name="line5492"></a><div class="linenumber">5492</div><div style="width:4em;display:inline-block"></div>var i;
<a name="line5493"></a><div class="linenumber">5493</div><div style="width:4em;display:inline-block"></div>if (preallocatedSocketIo) {
<a name="line5494"></a><div class="linenumber">5494</div><div style="width:6em;display:inline-block"></div>self.webSocket = preallocatedSocketIo;
<a name="line5495"></a><div class="linenumber">5495</div><div style="width:4em;display:inline-block"></div>}
<a name="line5496"></a><div class="linenumber">5496</div><div style="width:4em;display:inline-block"></div>else if (!self.webSocket) {
<a name="line5497"></a><div class="linenumber">5497</div><div style="width:6em;display:inline-block"></div>try {
<a name="line5498"></a><div class="linenumber">5498</div><div style="width:7em;display:inline-block"></div>self.webSocket = io.connect(serverPath, connectionOptions);
<a name="line5499"></a><div class="linenumber">5499</div>
<a name="line5500"></a><div class="linenumber">5500</div><div style="width:8em;display:inline-block"></div>if (!self.webSocket) {
<a name="line5501"></a><div class="linenumber">5501</div><div style="width:10em;display:inline-block"></div>throw "io.connect failed";
<a name="line5502"></a><div class="linenumber">5502</div><div style="width:8em;display:inline-block"></div>}
<a name="line5503"></a><div class="linenumber">5503</div>
<a name="line5504"></a><div class="linenumber">5504</div><div style="width:6em;display:inline-block"></div>} catch(socketErr) {
<a name="line5505"></a><div class="linenumber">5505</div><div style="width:8em;display:inline-block"></div>self.webSocket = 0;
<a name="line5506"></a><div class="linenumber">5506</div><div style="width:8em;display:inline-block"></div>errorCallback( self.errCodes.SYSTEM_ERROR, socketErr.toString());
<a name="line5507"></a><div class="linenumber">5507</div>
<a name="line5508"></a><div class="linenumber">5508</div><div style="width:7em;display:inline-block"></div>return;
<a name="line5509"></a><div class="linenumber">5509</div><div style="width:6em;display:inline-block"></div>}
<a name="line5510"></a><div class="linenumber">5510</div><div style="width:4em;display:inline-block"></div>}
<a name="line5511"></a><div class="linenumber">5511</div><div style="width:4em;display:inline-block"></div>else {
<a name="line5512"></a><div class="linenumber">5512</div><div style="width:6em;display:inline-block"></div>for (i in self.websocketListeners) {
<a name="line5513"></a><div class="linenumber">5513</div><div style="width:8em;display:inline-block"></div>if (!self.websocketListeners.hasOwnProperty(i)) {
<a name="line5514"></a><div class="linenumber">5514</div><div style="width:10em;display:inline-block"></div>continue;
<a name="line5515"></a><div class="linenumber">5515</div><div style="width:8em;display:inline-block"></div>}
<a name="line5516"></a><div class="linenumber">5516</div><div style="width:8em;display:inline-block"></div>self.webSocket.removeEventListener(self.websocketListeners[i].event,
<a name="line5517"></a><div class="linenumber">5517</div><div style="width:12em;display:inline-block"></div>self.websocketListeners[i].handler);
<a name="line5518"></a><div class="linenumber">5518</div><div style="width:6em;display:inline-block"></div>}
<a name="line5519"></a><div class="linenumber">5519</div><div style="width:4em;display:inline-block"></div>}
<a name="line5520"></a><div class="linenumber">5520</div>
<a name="line5521"></a><div class="linenumber">5521</div><div style="width:4em;display:inline-block"></div>self.websocketListeners = [];
<a name="line5522"></a><div class="linenumber">5522</div>
<a name="line5523"></a><div class="linenumber">5523</div><div style="width:4em;display:inline-block"></div>function addSocketListener(event, handler) {
<a name="line5524"></a><div class="linenumber">5524</div><div style="width:6em;display:inline-block"></div>self.webSocket.on(event, handler);
<a name="line5525"></a><div class="linenumber">5525</div><div style="width:6em;display:inline-block"></div>self.websocketListeners.push({event: event, handler: handler});
<a name="line5526"></a><div class="linenumber">5526</div><div style="width:4em;display:inline-block"></div>}
<a name="line5527"></a><div class="linenumber">5527</div>
<a name="line5528"></a><div class="linenumber">5528</div><div style="width:4em;display:inline-block"></div>addSocketListener("close", function(event) {
<a name="line5529"></a><div class="linenumber">5529</div><div style="width:6em;display:inline-block"></div>logDebug("the web socket closed");
<a name="line5530"></a><div class="linenumber">5530</div><div style="width:4em;display:inline-block"></div>});
<a name="line5531"></a><div class="linenumber">5531</div>
<a name="line5532"></a><div class="linenumber">5532</div><div style="width:4em;display:inline-block"></div>addSocketListener('error', function(event) {
<a name="line5533"></a><div class="linenumber">5533</div><div style="width:6em;display:inline-block"></div>function handleErrorEvent() {
<a name="line5534"></a><div class="linenumber">5534</div><div style="width:8em;display:inline-block"></div>if (self.myEasyrtcid) {
<a name="line5535"></a><div class="linenumber">5535</div><div style="width:10em;display:inline-block"></div>//
<a name="line5536"></a><div class="linenumber">5536</div><div style="width:10em;display:inline-block"></div>// socket.io version 1 got rid of the socket member, moving everything up one level.
<a name="line5537"></a><div class="linenumber">5537</div><div style="width:10em;display:inline-block"></div>//
<a name="line5538"></a><div class="linenumber">5538</div><div style="width:10em;display:inline-block"></div>if (isSocketConnected(self.webSocket)) {
<a name="line5539"></a><div class="linenumber">5539</div><div style="width:12em;display:inline-block"></div>self.showError(self.errCodes.SIGNAL_ERR, self.getConstantString("miscSignalError"));
<a name="line5540"></a><div class="linenumber">5540</div><div style="width:10em;display:inline-block"></div>}
<a name="line5541"></a><div class="linenumber">5541</div><div style="width:10em;display:inline-block"></div>else {
<a name="line5542"></a><div class="linenumber">5542</div><div style="width:12em;display:inline-block"></div>/* socket server went down. this will generate a 'disconnect' event as well, so skip this event */
<a name="line5543"></a><div class="linenumber">5543</div><div style="width:12em;display:inline-block"></div>errorCallback(self.errCodes.CONNECT_ERR, self.getConstantString("noServer"));
<a name="line5544"></a><div class="linenumber">5544</div><div style="width:10em;display:inline-block"></div>}
<a name="line5545"></a><div class="linenumber">5545</div><div style="width:8em;display:inline-block"></div>}
<a name="line5546"></a><div class="linenumber">5546</div><div style="width:8em;display:inline-block"></div>else {
<a name="line5547"></a><div class="linenumber">5547</div><div style="width:10em;display:inline-block"></div>errorCallback(self.errCodes.CONNECT_ERR, self.getConstantString("noServer"));
<a name="line5548"></a><div class="linenumber">5548</div><div style="width:8em;display:inline-block"></div>}
<a name="line5549"></a><div class="linenumber">5549</div><div style="width:6em;display:inline-block"></div>}
<a name="line5550"></a><div class="linenumber">5550</div><div style="width:6em;display:inline-block"></div>handleErrorEvent();
<a name="line5551"></a><div class="linenumber">5551</div><div style="width:4em;display:inline-block"></div>});
<a name="line5552"></a><div class="linenumber">5552</div>
<a name="line5553"></a><div class="linenumber">5553</div><div style="width:4em;display:inline-block"></div>function connectHandler(event) {
<a name="line5554"></a><div class="linenumber">5554</div><div style="width:6em;display:inline-block"></div>self.webSocketConnected = true;
<a name="line5555"></a><div class="linenumber">5555</div><div style="width:6em;display:inline-block"></div>if (!self.webSocket) {
<a name="line5556"></a><div class="linenumber">5556</div><div style="width:8em;display:inline-block"></div>self.showError(self.errCodes.CONNECT_ERR, self.getConstantString("badsocket"));
<a name="line5557"></a><div class="linenumber">5557</div><div style="width:6em;display:inline-block"></div>}
<a name="line5558"></a><div class="linenumber">5558</div>
<a name="line5559"></a><div class="linenumber">5559</div><div style="width:6em;display:inline-block"></div>logDebug("saw socket-server onconnect event");
<a name="line5560"></a><div class="linenumber">5560</div>
<a name="line5561"></a><div class="linenumber">5561</div><div style="width:6em;display:inline-block"></div>if (self.webSocketConnected) {
<a name="line5562"></a><div class="linenumber">5562</div><div style="width:8em;display:inline-block"></div>sendAuthenticate(successCallback, errorCallback);
<a name="line5563"></a><div class="linenumber">5563</div><div style="width:6em;display:inline-block"></div>}
<a name="line5564"></a><div class="linenumber">5564</div><div style="width:6em;display:inline-block"></div>else {
<a name="line5565"></a><div class="linenumber">5565</div><div style="width:8em;display:inline-block"></div>errorCallback(self.errCodes.SIGNAL_ERR, self.getConstantString("icf"));
<a name="line5566"></a><div class="linenumber">5566</div><div style="width:6em;display:inline-block"></div>}
<a name="line5567"></a><div class="linenumber">5567</div><div style="width:4em;display:inline-block"></div>}
<a name="line5568"></a><div class="linenumber">5568</div>
<a name="line5569"></a><div class="linenumber">5569</div><div style="width:4em;display:inline-block"></div>if (isSocketConnected(preallocatedSocketIo)) {
<a name="line5570"></a><div class="linenumber">5570</div><div style="width:6em;display:inline-block"></div>connectHandler(null);
<a name="line5571"></a><div class="linenumber">5571</div><div style="width:4em;display:inline-block"></div>}
<a name="line5572"></a><div class="linenumber">5572</div><div style="width:4em;display:inline-block"></div>else {
<a name="line5573"></a><div class="linenumber">5573</div><div style="width:6em;display:inline-block"></div>addSocketListener("connect", connectHandler);
<a name="line5574"></a><div class="linenumber">5574</div><div style="width:4em;display:inline-block"></div>}
<a name="line5575"></a><div class="linenumber">5575</div>
<a name="line5576"></a><div class="linenumber">5576</div><div style="width:4em;display:inline-block"></div>addSocketListener("easyrtcMsg", onChannelMsg);
<a name="line5577"></a><div class="linenumber">5577</div><div style="width:4em;display:inline-block"></div>addSocketListener("easyrtcCmd", onChannelCmd);
<a name="line5578"></a><div class="linenumber">5578</div><div style="width:4em;display:inline-block"></div>addSocketListener("disconnect", function(/* code, reason, wasClean */) {
<a name="line5579"></a><div class="linenumber">5579</div>
<a name="line5580"></a><div class="linenumber">5580</div><div style="width:6em;display:inline-block"></div>self.webSocketConnected = false;
<a name="line5581"></a><div class="linenumber">5581</div><div style="width:6em;display:inline-block"></div>updateConfigurationInfo = function() {}; // dummy update function
<a name="line5582"></a><div class="linenumber">5582</div><div style="width:6em;display:inline-block"></div>oldConfig = {};
<a name="line5583"></a><div class="linenumber">5583</div><div style="width:6em;display:inline-block"></div>disconnectBody();
<a name="line5584"></a><div class="linenumber">5584</div>
<a name="line5585"></a><div class="linenumber">5585</div><div style="width:6em;display:inline-block"></div>if (self.disconnectListener) {
<a name="line5586"></a><div class="linenumber">5586</div><div style="width:8em;display:inline-block"></div>self.disconnectListener();
<a name="line5587"></a><div class="linenumber">5587</div><div style="width:6em;display:inline-block"></div>}
<a name="line5588"></a><div class="linenumber">5588</div><div style="width:4em;display:inline-block"></div>});
<a name="line5589"></a><div class="linenumber">5589</div><div style="width:2em;display:inline-block"></div>}
<a name="line5590"></a><div class="linenumber">5590</div>
<a name="line5591"></a><div class="linenumber">5591</div><div style="width:2em;display:inline-block"></div>/**
<a name="line5592"></a><div class="linenumber">5592</div><div style="width:2em;display:inline-block"></div>* Connects to the EasyRTC signaling server. You must connect before trying to
<a name="line5593"></a><div class="linenumber">5593</div><div style="width:2em;display:inline-block"></div>* call other users.
<a name="line5594"></a><div class="linenumber">5594</div><div style="width:2em;display:inline-block"></div>* @param {String} applicationName is a string that identifies the application so that different applications can have different
<a name="line5595"></a><div class="linenumber">5595</div><div style="width:2em;display:inline-block"></div>* lists of users. Note that the server configuration specifies a regular expression that is used to check application names
<a name="line5596"></a><div class="linenumber">5596</div><div style="width:2em;display:inline-block"></div>* for validity. The default pattern is that of an identifier, spaces are not allowed.
<a name="line5597"></a><div class="linenumber">5597</div><div style="width:2em;display:inline-block"></div>* @param {Function} successCallback (easyrtcId, roomOwner) - is called on successful connect. easyrtcId is the
<a name="line5598"></a><div class="linenumber">5598</div><div style="width:2em;display:inline-block"></div>* unique name that the client is known to the server by. A client usually only needs it's own easyrtcId for debugging purposes.
<a name="line5599"></a><div class="linenumber">5599</div><div style="width:2em;display:inline-block"></div>* roomOwner is true if the user is the owner of a room. It's value is random if the user is in multiple rooms.
<a name="line5600"></a><div class="linenumber">5600</div><div style="width:2em;display:inline-block"></div>* @param {Function} errorCallback (errorCode, errorText) - is called on unsuccessful connect. if null, an alert is called instead.
<a name="line5601"></a><div class="linenumber">5601</div><div style="width:2em;display:inline-block"></div>* The errorCode takes it's value from easyrtc.errCodes.
<a name="line5602"></a><div class="linenumber">5602</div><div style="width:2em;display:inline-block"></div>* @example
<a name="line5603"></a><div class="linenumber">5603</div><div style="width:2em;display:inline-block"></div>* easyrtc.connect("my_chat_app",
<a name="line5604"></a><div class="linenumber">5604</div><div style="width:2em;display:inline-block"></div>* function(easyrtcid, roomOwner){
<a name="line5605"></a><div class="linenumber">5605</div><div style="width:2em;display:inline-block"></div>* if( roomOwner){ console.log("I'm the room owner"); }
<a name="line5606"></a><div class="linenumber">5606</div><div style="width:2em;display:inline-block"></div>* console.log("my id is " + easyrtcid);
<a name="line5607"></a><div class="linenumber">5607</div><div style="width:2em;display:inline-block"></div>* },
<a name="line5608"></a><div class="linenumber">5608</div><div style="width:2em;display:inline-block"></div>* function(errorText){
<a name="line5609"></a><div class="linenumber">5609</div><div style="width:2em;display:inline-block"></div>* console.log("failed to connect ", erFrText);
<a name="line5610"></a><div class="linenumber">5610</div><div style="width:2em;display:inline-block"></div>* });
<a name="line5611"></a><div class="linenumber">5611</div><div style="width:2em;display:inline-block"></div>*/
<a name="line5612"></a><div class="linenumber">5612</div><div style="width:2em;display:inline-block"></div>this.connect = function(applicationName, successCallback, errorCallback) {
<a name="line5613"></a><div class="linenumber">5613</div>
<a name="line5614"></a><div class="linenumber">5614</div><div style="width:4em;display:inline-block"></div>// Detect invalid or missing socket.io
<a name="line5615"></a><div class="linenumber">5615</div><div style="width:4em;display:inline-block"></div>if (!io) {
<a name="line5616"></a><div class="linenumber">5616</div><div style="width:6em;display:inline-block"></div>self.showError(self.errCodes.DEVELOPER_ERR, "Your HTML has not included the socket.io.js library");
<a name="line5617"></a><div class="linenumber">5617</div><div style="width:4em;display:inline-block"></div>}
<a name="line5618"></a><div class="linenumber">5618</div>
<a name="line5619"></a><div class="linenumber">5619</div><div style="width:4em;display:inline-block"></div>if (!preallocatedSocketIo && self.webSocket) {
<a name="line5620"></a><div class="linenumber">5620</div><div style="width:6em;display:inline-block"></div>self.showError(self.errCodes.DEVELOPER_ERR, "Attempt to connect when already connected to socket server");
<a name="line5621"></a><div class="linenumber">5621</div><div style="width:6em;display:inline-block"></div>return;
<a name="line5622"></a><div class="linenumber">5622</div><div style="width:4em;display:inline-block"></div>}
<a name="line5623"></a><div class="linenumber">5623</div><div style="width:4em;display:inline-block"></div>pc_config = {};
<a name="line5624"></a><div class="linenumber">5624</div><div style="width:4em;display:inline-block"></div>closedChannel = null;
<a name="line5625"></a><div class="linenumber">5625</div><div style="width:4em;display:inline-block"></div>oldConfig = {}; // used internally by updateConfiguration
<a name="line5626"></a><div class="linenumber">5626</div><div style="width:4em;display:inline-block"></div>queuedMessages = {};
<a name="line5627"></a><div class="linenumber">5627</div><div style="width:4em;display:inline-block"></div>self.applicationName = applicationName;
<a name="line5628"></a><div class="linenumber">5628</div><div style="width:4em;display:inline-block"></div>fields = {
<a name="line5629"></a><div class="linenumber">5629</div><div style="width:6em;display:inline-block"></div>rooms: {},
<a name="line5630"></a><div class="linenumber">5630</div><div style="width:6em;display:inline-block"></div>application: {},
<a name="line5631"></a><div class="linenumber">5631</div><div style="width:6em;display:inline-block"></div>connection: {}
<a name="line5632"></a><div class="linenumber">5632</div><div style="width:4em;display:inline-block"></div>};
<a name="line5633"></a><div class="linenumber">5633</div>
<a name="line5634"></a><div class="linenumber">5634</div><div style="width:4em;display:inline-block"></div>logDebug("attempt to connect to WebRTC signalling server with application name=" + applicationName);
<a name="line5635"></a><div class="linenumber">5635</div>
<a name="line5636"></a><div class="linenumber">5636</div><div style="width:4em;display:inline-block"></div>if (errorCallback === null) {
<a name="line5637"></a><div class="linenumber">5637</div><div style="width:6em;display:inline-block"></div>errorCallback = function(errorCode, errorText) {
<a name="line5638"></a><div class="linenumber">5638</div><div style="width:8em;display:inline-block"></div>self.showError(errorCode, errorText);
<a name="line5639"></a><div class="linenumber">5639</div><div style="width:6em;display:inline-block"></div>};
<a name="line5640"></a><div class="linenumber">5640</div><div style="width:4em;display:inline-block"></div>}
<a name="line5641"></a><div class="linenumber">5641</div>
<a name="line5642"></a><div class="linenumber">5642</div><div style="width:4em;display:inline-block"></div>connectToWSServer(successCallback, errorCallback);
<a name="line5643"></a><div class="linenumber">5643</div><div style="width:2em;display:inline-block"></div>};
<a name="line5644"></a><div class="linenumber">5644</div><div style="width:0em;display:inline-block"></div>};
<a name="line5645"></a><div class="linenumber">5645</div>
<a name="line5646"></a><div class="linenumber">5646</div><div style="width:0em;display:inline-block"></div>return new Easyrtc();
<a name="line5647"></a><div class="linenumber">5647</div>
<a name="line5648"></a><div class="linenumber">5648</div><div style="width:0em;display:inline-block"></div>}));
</code></pre>
</article>
</section>
</div>
</div>
</div>
<footer class="template">
<div class="wrapper-content">
<p>Copyright ©2016 EasyRTC</p>
</div>
</footer>
<!-- <script>prettyPrint();</script> -->
<!-- <script src="scripts/linenumber.js"></script> -->
</body>
</html>