<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">

<!--
Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.

Use of this source code is governed by a BSD-style license
that can be found in the LICENSE file in the root of the source
tree. An additional intellectual property rights grant can be found
in the file PATENTS. All contributing project authors may
be found in the AUTHORS file in the root of the source tree.
-->

<html>

<head>
<title>WebRTC Test</title>

<style type="text/css">
body, input, button, select, table {
  font-family:"Lucida Grande", "Lucida Sans", Verdana, Arial, sans-serif;
  font-size: 13 px;
}
body, input:enable, button:enable, select:enable, table {
  color: rgb(51, 51, 51);
}
h1 {font-size: 40 px;}
</style>

<script type="text/javascript">

// TODO: Catch more exceptions

var server;
var myId = -1;
var myName;
var remoteId = -1;
var remoteName;
var request = null;
var hangingGet = null;
var pc = null;
var localStream = null;
var disconnecting = false;
var callState = 0; // 0 - Not started, 1 - Call ongoing


// General

function setElementValuesFromURL() {
  window.location.href.replace(/[?&]+([^=&]+)=([^&]*)/gi,
    function(m, key, value) {
      document.getElementById(key).value = unescape(value);
    });
}

function trace(txt) {
  var elem = document.getElementById("debug");
  elem.innerHTML += txt + "<br>";
}

function trace_warning(txt) {
  var wtxt = "<b>" + txt + "</b>";
  trace(wtxt);
}

function trace_exception(e, txt) {
  var etxt = "<b>" + txt + "</b> (" + e.name + " / " + e.message + ")";
  trace(etxt);
}

function setCallState(state) {
  trace("Changing call state: " + callState + " -> " + state);
  callState = state;
}

function checkPeerConnection() {
  if (!pc) {
    trace_warning("No PeerConnection object exists");
    return 0;
  }
  return 1;
}


// Local stream generation

function gotStream(s) {
  var url = webkitURL.createObjectURL(s);
  document.getElementById("localView").src = url;
  trace("User has granted access to local media. url = " + url);
  localStream = s;
}

function gotStreamFailed(error) {
  alert("Failed to get access to local media. Error code was " + error.code +
    ".");
  trace_warning("Failed to get access to local media. Error code was " +
    error.code);
}

function getUserMedia() {
  try {
    navigator.webkitGetUserMedia("video,audio", gotStream, gotStreamFailed);
    trace("Requested access to local media");
  } catch (e) {
    trace_exception(e, "getUserMedia error");
  }
}


// Peer list and remote peer handling

function peerExists(id) {
  try {
    var peerList = document.getElementById("peers");
    for (var i = 0; i < peerList.length; i++) {
      if (parseInt(peerList.options[i].value) == id)
        return true;
    }
  } catch (e) {
    trace_exception(e, "Error searching for peer");
  }
  return false;
}

function addPeer(id, pname) {
  try {
    var peerList = document.getElementById("peers");
    var option = document.createElement("option");
    option.text = pname;
    option.value = id;
    peerList.add(option, null);
  } catch (e) {
    trace_exception(e, "Error adding peer");
  }
}

function removePeer(id) {
  try {
    var peerList = document.getElementById("peers");
    for (var i = 0; i < peerList.length; i++) {
      if (parseInt(peerList.options[i].value) == id) {
        peerList.remove(i);
        break;
      }
    }
  } catch (e) {
    trace_exception(e, "Error removing peer");
  }
}

function clearPeerList() {
  var peerList = document.getElementById("peers");
  while (peerList.length > 0)
    peerList.remove(0);
}

function setSelectedPeer(id) {
  try {
    var peerList = document.getElementById("peers");
    for (var i = 0; i < peerList.length; i++) {
      if (parseInt(peerList.options[i].value) == id) {
        peerList.options[i].selected = true;
        return true;
      }
    }
  } catch (e) {
    trace_exception(e, "Error setting selected peer");
  }
  return false;
}

function getPeerName(id) {
  try {
    var peerList = document.getElementById("peers");
    for (var i = 0; i < peerList.length; i++) {
      if (parseInt(peerList.options[i].value) == id) {
        return peerList.options[i].text;
      }
    }
  } catch (e) {
    trace_exception(e, "Error finding peer name");
    return;
  }
  return;
}

function storeRemoteInfo() {
  try {
    var peerList = document.getElementById("peers");
    if (peerList.selectedIndex < 0) {
      alert("Please select a peer.");
      return false;
    } else
      remoteId = parseInt(peerList.options[peerList.selectedIndex].value);
      remoteName = peerList.options[peerList.selectedIndex].text;
  } catch (e) {
    trace_exception(e, "Error storing remote peer info");
    return false;
  }
  return true;
}


// Call control

function createPeerConnection() {
  if (pc) {
    trace_warning("PeerConnection object already exists");
  }
  trace("Creating PeerConnection object");
  try {
    pc = new webkitPeerConnection("STUN stun.l.google.com:19302",
      onSignalingMessage);
  pc.onaddstream = onAddStream;
  pc.onremovestream = onRemoveStream;
  } catch (e) {
    trace_exception(e, "Create PeerConnection error");
  }
}

function doCall() {
  if (!storeRemoteInfo())
    return;
  document.getElementById("call").disabled = true;
  document.getElementById("peers").disabled = true;
  createPeerConnection();
  trace("Adding stream");
  pc.addStream(localStream);
  document.getElementById("hangup").disabled = false;
  setCallState(1);
}

function hangUp() {
  document.getElementById("hangup").disabled = true;
  trace("Sending BYE to " + remoteName + " (ID " + remoteId + ")");
  sendToPeer(remoteId, "BYE");
  closeCall();
}

function closeCall() {
  trace("Stopping showing remote stream");
  document.getElementById("remoteView").src = "dummy";
  if (pc) {
    trace("Stopping call [pc.close()]");
    pc.close();
    pc = null;
  } else
    trace("No pc object to close");
  remoteId = -1;
  document.getElementById("call").disabled = false;
  document.getElementById("peers").disabled = false;
  setCallState(0);
}


// PeerConnection callbacks

function onAddStream(e) {
  var stream = e.stream;
  var url = webkitURL.createObjectURL(stream);
  document.getElementById("remoteView").src = url;
  trace("Started showing remote stream. url = " + url);
}

function onRemoveStream(e) {
  // Currently if we get this callback, call has ended.
  document.getElementById("remoteView").src = "";
  trace("Stopped showing remote stream");
}

function onSignalingMessage(msg) {
  trace("Sending message to " + remoteName + " (ID " + remoteId + "):\n" + msg);
  sendToPeer(remoteId, msg);
}

// TODO: Add callbacks onconnecting, onopen and onstatechange.


// Server interaction

function handleServerNotification(data) {
  trace("Server notification: " + data);
  var parsed = data.split(",");
  if (parseInt(parsed[2]) == 1) { // New peer
    var peerId = parseInt(parsed[1]);
    if (!peerExists(peerId)) {
      var peerList = document.getElementById("peers");
      if (peerList.length == 1 && peerList.options[0].value == -1)
        clearPeerList();
      addPeer(peerId, parsed[0]);
      document.getElementById("peers").disabled = false;
      document.getElementById("call").disabled = false;
    }
  } else if (parseInt(parsed[2]) == 0) { // Removed peer
    removePeer(parseInt(parsed[1]));
    if (document.getElementById("peers").length == 0) {
      document.getElementById("peers").disabled = true;
      addPeer(-1, "No other peer connected");
    }
  }
}

function handlePeerMessage(peer_id, msg) {
  var peerName = getPeerName(peer_id);
  if (peerName == undefined) {
    trace_warning("Received message from unknown peer (ID " + peer_id +
      "), ignoring message:");
    trace(msg);
    return;
  }
  trace("Received message from " + peerName + " (ID " + peer_id + "):\n" + msg);
  // Assuming we receive the message from the peer we want to communicate with.
  // TODO: Only accept messages from peer we communicate with with if call is
  // ongoing.
  if (msg.search("BYE") == 0) {
    // Other side has hung up.
    document.getElementById("hangup").disabled = true;
    closeCall()
  } else {
    if (!pc) {
      // Other side is calling us, startup
      if (!setSelectedPeer(peer_id)) {
        trace_warning("Recevied message from unknown peer, ignoring");
        return;
      }
      if (!storeRemoteInfo())
        return;
      document.getElementById("call").disabled = true;
      document.getElementById("peers").disabled = true;
      createPeerConnection();
      try {
        pc.processSignalingMessage(msg);
      } catch (e) {
        trace_exception(e, "Process signaling message error");
      }
      trace("Adding stream");
      pc.addStream(localStream);
      document.getElementById("hangup").disabled = false;
    } else {
      try {
        pc.processSignalingMessage(msg);
      } catch (e) {
        trace_exception(e, "Process signaling message error");
      }
    }
  }
}

function getIntHeader(r, name) {
  var val = r.getResponseHeader(name);
  trace("header value: " + val);
  return val != null && val.length ? parseInt(val) : -1;
}

function hangingGetCallback() {
  try {
    if (hangingGet.readyState != 4 || disconnecting)
      return;
    if (hangingGet.status != 200) {
      trace_warning("server error, status: " + hangingGet.status + ", text: " +
        hangingGet.statusText);
      disconnect();
    } else {
      var peer_id = getIntHeader(hangingGet, "Pragma");
      if (peer_id == myId) {
        handleServerNotification(hangingGet.responseText);
      } else {
        handlePeerMessage(peer_id, hangingGet.responseText);
      }
    }

    if (hangingGet) {
      hangingGet.abort();
      hangingGet = null;
    }

    if (myId != -1)
      window.setTimeout(startHangingGet, 0);
  } catch (e) {
    trace_exception(e, "Hanging get error");
  }
}

function onHangingGetTimeout() {
  trace("hanging get timeout. issuing again");
  hangingGet.abort();
  hangingGet = null;
  if (myId != -1)
    window.setTimeout(startHangingGet, 0);
}

function startHangingGet() {
  try {
    hangingGet = new XMLHttpRequest();
    hangingGet.onreadystatechange = hangingGetCallback;
    hangingGet.ontimeout = onHangingGetTimeout;
    hangingGet.open("GET", server + "/wait?peer_id=" + myId, true);
    hangingGet.send();  
  } catch (e) {
    trace_exception(e, "Start hanging get error");
  }
}

function sendToPeer(peer_id, data) {
  if (myId == -1) {
    alert("Not connected.");
    return;
  }
  if (peer_id == myId) {
    alert("Can't send a message to oneself.");
    return;
  }
  var r = new XMLHttpRequest();
  r.open("POST", server + "/message?peer_id=" + myId + "&to=" + peer_id, false);
  r.setRequestHeader("Content-Type", "text/plain");
  r.send(data);
  r = null;
}

function signInCallback() {
  try {
    if (request.readyState == 4) {
      if (request.status == 200) {
        var peers = request.responseText.split("\n");
        myId = parseInt(peers[0].split(",")[1]);
        trace("My id: " + myId);
        clearPeerList();
        var added = 0;
        for (var i = 1; i < peers.length; ++i) {
          if (peers[i].length > 0) {
            trace("Peer " + i + ": " + peers[i]);
            var parsed = peers[i].split(",");
            addPeer(parseInt(parsed[1]), parsed[0]);
            ++added;
          }
        }
        if (added == 0)
          addPeer(-1, "No other peer connected");
        else {
          document.getElementById("peers").disabled = false;
          document.getElementById("call").disabled = false;
        }
        startHangingGet();
        request = null;
        document.getElementById("connect").disabled = true;
        document.getElementById("disconnect").disabled = false;
      }
    }
  } catch (e) {
    trace_exception(e, "Sign in error");
    document.getElementById("connect").disabled = false;
  }
}

function signIn() {
  try {
    request = new XMLHttpRequest();
    request.onreadystatechange = signInCallback;
    request.open("GET", server + "/sign_in?" + myName, true);
    request.send();
  } catch (e) {
    trace_exception(e, "Start sign in error");
    document.getElementById("connect").disabled = false;
  }
}

function connect() {
  myName = document.getElementById("name").value.toLowerCase();
  server = document.getElementById("server").value.toLowerCase();
  if (myName.length == 0) {
    alert("I need a name please.");
    document.getElementById("local").focus();
  } else {
    // TODO: Disable connect button here, but we need a timeout and check if we
    // have connected, if so enable it again.
    signIn();
  }
}

function disconnect() {
  if (callState == 1)
    hangUp();

  disconnecting = true;
  
  if (request) {
    request.abort();
    request = null;
  }

  if (hangingGet) {
    hangingGet.abort();
    hangingGet = null;
  }

  if (myId != -1) {
    request = new XMLHttpRequest();
    request.open("GET", server + "/sign_out?peer_id=" + myId, false);
    request.send();
    request = null;
    myId = -1;
  }

  clearPeerList();
  addPeer(-1, "Not connected");
  document.getElementById("connect").disabled = false;
  document.getElementById("disconnect").disabled = true;
  document.getElementById("peers").disabled = true;
  document.getElementById("call").disabled = true;

  disconnecting = false;
}


// Window event handling

window.onload = function() {
  if (navigator.webkitGetUserMedia) {
    document.getElementById('testApp').hidden = false;
    setElementValuesFromURL();
    getUserMedia();
  } else {
    document.getElementById('errorText').hidden = false;
  }
}

window.onbeforeunload = disconnect;

</script>
</head>

<body>
<h1>WebRTC</h1>
<section id="errorText" hidden="true">
Could not detect WebRTC support.<p>
You must have WebRTC enabled Chrome browser to use this test page. The browser
must be started with the --enable-media-stream command line flag. For more
information, please see
<a href="https://sites.google.com/site/webrtc/blog/webrtcnowavailableinthechromedevchannel">
this blog post</a>.
</section>

<section id="testApp" hidden="true">
<table border="0">
<tr>
 <td>Local Preview</td>
 <td>Remote Video</td>
</tr>
<tr>
 <td>
  <video width="320" height="240" id="localView" autoplay="autoplay"></video>
 </td>
 <td>
  <video width="640" height="480" id="remoteView" autoplay="autoplay"></video>
 </td>
</tr>
</table>

<table border="0">
<tr>
 <td valign="top">
  <table border="0" cellpaddning="0" cellspacing="0">
  <tr>
   <td>Server:</td>
   <td>
    <input type="text" id="server" size="30" value="http://localhost:8888"/>
   </td>
  </tr>
  <tr>
   <td>Name:</td><td><input type="text" id="name" size="30" value="name"/></td>
  </tr>
  </table>
 </td>
 <td valign="top">
  <button id="connect" onclick="connect();">Connect</button><br>
  <button id="disconnect" onclick="disconnect();" disabled="true">Disconnect
  </button>
 </td>
 <td>&nbsp;&nbsp;&nbsp;</td>
 <td valign="top">
  Connected peers:<br>
  <select id="peers" size="5" disabled="true">
   <option value="-1">Not connected</option>
  </select>
  </td>
 <td valign="top">
  <!--input type="text" id="peer_id" size="3" value="1"/><br-->
  <button id="call" onclick="doCall();" disabled="true">Call</button><br>
  <button id="hangup" onclick="hangUp();" disabled="true">Hang up</button><br>
 </td>
</tr>
</table>

<button onclick="document.getElementById('debug').innerHTML='';">Clear log
</button>
<pre id="debug"></pre>
</section>

</body>

</html>

