webrtc/test/sanity_check/www/html/call_client.html
2011-09-30 13:26:14 +00:00

395 lines
10 KiB
HTML

<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
<html>
<head>
<title>WebRTC Autocaller</title>
<script type="text/javascript">
var local_name;
var server;
var my_id = -1;
var other_peers = {};
var request = null;
var hanging_get = null;
var pc = null;
var local_stream = null;
var call_state = 0;
// 0 - Not started
// 1 - Call ongoing
// 2 - We have initiated closing the call
// 3 - Other side has initiated closing the call
// General
function toggleExtraButtons() {
document.getElementById("createPcBtn").hidden =
!document.getElementById("createPcBtn").hidden;
document.getElementById("addStreamBtn").hidden =
!document.getElementById("addStreamBtn").hidden;
}
function trace(txt) {
var elem = document.getElementById("debug");
elem.innerHTML += txt + "<br>";
}
function trace_warning(txt) {
var wtxt = "<b>" + txt + "</b>";
trace(wtxt);
}
function setCallState(state) {
trace("Changing call state: " + call_state + " -> " + state);
call_state = 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 webcam. url = " + url);
local_stream = s;
}
function gotStreamFailed(error) {
alert("Failed to get access to webcam. Error code was " + error.code);
trace("Failed to get access to webcam. Error code was " + error.code);
}
// Call control
function createPeerConnection() {
if (pc) {
trace_warning("PeerConnection object already exists.");
}
trace("Creating PeerConnection object.");
// CRASH TEST
pc = new webkitPeerConnection("STUN 1.2.3.4:43", onSignalingMessage);
pc.onaddstream = onAddStream;
pc.onremovestream = onRemoveStream;
}
function startCall() {
document.getElementById("startcall").disabled = true;
createPeerConnection();
addStream();
}
function addStream() {
trace("Starting call. [pc.addStream(local_stream)]");
pc.addStream(local_stream);
document.getElementById("stopcall").disabled = false;
}
function stopCall() {
document.getElementById("stopcall").disabled = true;
trace("Stopping call [pc.close()]");
setCallState(2);
pc.close();
}
function test1() {
addStream();
}
function callHasStarted() {
setCallState(1);
}
// PeerConnection callbacks
function onAddStream(e) {
var stream = pc.remoteStreams[0];
var url = webkitURL.createObjectURL(stream);
document.getElementById("remoteView").src = url;
trace("Started showing remote stream. url = " + url);
setTimeout(callHasStarted, 5000); // TODO(hta): workaround, to be removed
}
function onRemoveStream(e) {
// Currently if we get this callback, call has ended.
document.getElementById("remoteView").src = "";
trace("Stopped showing remote stream.");
if (call_state == 2) {
// Finalize close call. We assume here that this callback comes
// after onSignalingMessage.
pc = null;
setCallState(0);
document.getElementById("startcall").disabled = false;
}
}
function onSignalingMessage(msg) {
var peer_id = parseInt(document.getElementById("peer_id").value);
trace("Sending message to " + other_peers[peer_id] +
" (ID " + peer_id + "):\n" + msg);
sendToPeer(peer_id, msg);
}
// Server interaction
function handleServerNotification(data) {
trace("Server notification: " + data);
notePeerAndMaybeCall(data);
}
function handlePeerMessage(peer_id, msg) {
trace("Received message from " + other_peers[peer_id] +
" (ID " + peer_id + "):\n" + msg);
// Assuming we have created a PeerConnection and that we receive the
// message from the peer want to communicate with
document.getElementById("peer_id").value =
peer_id; // Ensure we reply to the same peer
if (pc) {
try {
pc.processSignalingMessage(msg);
} catch (e) {
trace_warning("Signaling message error: " + e.description);
}
if (call_state == 1)
setCallState(3);
} else {
createPeerConnection();
pc.processSignalingMessage(msg);
}
}
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 (hanging_get.readyState != 4)
return;
if (hanging_get.status != 200) {
trace("server error, status: " + hanging_get.status + ", text: " +
hanging_get.statusText);
disconnect();
} else {
var peer_id = getIntHeader(hanging_get, "Pragma");
if (peer_id == my_id) {
handleServerNotification(hanging_get.responseText);
} else {
handlePeerMessage(peer_id, hanging_get.responseText);
}
}
if (hanging_get) {
hanging_get.abort();
hanging_get = null;
}
if (my_id != -1)
window.setTimeout(startHangingGet, 0);
} catch (e) {
trace("Hanging get error: " + e.description);
}
}
function onHangingGetTimeout() {
trace("hanging get timeout. issuing again.");
hanging_get.abort();
hanging_get = null;
if (my_id != -1)
window.setTimeout(startHangingGet, 0);
}
function startHangingGet() {
try {
hanging_get = new XMLHttpRequest();
hanging_get.onreadystatechange = hangingGetCallback;
hanging_get.ontimeout = onHangingGetTimeout;
hanging_get.open("GET", server + "/wait?peer_id=" + my_id, true);
hanging_get.send();
} catch (e) {
trace("error" + e.description);
}
}
function sendToPeer(peer_id, data) {
if (my_id == -1) {
alert("Not connected");
return;
}
if (peer_id == my_id) {
alert("Can't send a message to oneself :)");
return;
}
var r = new XMLHttpRequest();
r.open("POST", server + "/message?peer_id=" + my_id + "&to=" +
peer_id, false);
r.setRequestHeader("Content-Type", "text/plain");
r.send(data);
r = null;
}
function notePeerAndMaybeCall(peerInfo) {
var parsed = peerInfo.split(",");
if (parseInt(parsed[2]) != 0) {
trace("Peer came on: " + peerInfo);
other_peers[parseInt(parsed[1])] = parsed[0];
// If we're not already in a call, call it.
if (!document.getElementById("startcall").disabled) {
document.getElementById("peer_id").value = parsed[1];
startCall();
}
} else {
trace("Peer went away: " + peerInfo);
other_peers[parseInt(parsed[1])] = null;
}
}
function signInCallback() {
try {
if (request.readyState == 4) {
if (request.status == 200) {
var peers = request.responseText.split("\n");
my_id = parseInt(peers[0].split(",")[1]);
trace("My id: " + my_id);
for (var i = 1; i < peers.length; ++i) {
if (peers[i].length > 0) {
trace("Peer " + i + ": " + peers[i]);
notePeerAndMaybeCall(peers[i]);
}
}
startHangingGet();
request = null;
}
}
} catch (e) {
trace("error: " + e.description);
}
}
function signIn() {
try {
request = new XMLHttpRequest();
request.onreadystatechange = signInCallback;
request.open("GET", server + "/sign_in?" + local_name, true);
request.send();
} catch (e) {
trace("error: " + e.description);
}
}
function connect() {
local_name = document.getElementById("local").value.toLowerCase();
server = document.getElementById("server").value.toLowerCase();
if (local_name.length == 0) {
alert("I need a name please.");
document.getElementById("local").focus();
} else {
document.getElementById("connect").disabled = true;
document.getElementById("disconnect").disabled = false;
trace("Connecting to server");
signIn();
}
}
function disconnect() {
if (request) {
request.abort();
request = null;
}
if (hanging_get) {
hanging_get.abort();
hanging_get = null;
}
if (my_id != -1) {
request = new XMLHttpRequest();
request.open("GET", server + "/sign_out?peer_id=" + my_id, false);
request.send();
request = null;
my_id = -1;
}
document.getElementById("connect").disabled = false;
document.getElementById("disconnect").disabled = true;
}
function toggleLog()
{
document.getElementById('debug').hidden =!
document.getElementById('debug').hidden;
}
window.onbeforeunload = disconnect;
// TODO: Add audio here when available. Note: now it's hard coded,
// audio will also be started.
navigator.webkitGetUserMedia("video", gotStream, gotStreamFailed);
</script>
</head>
<body>
<h1>WebRTC autocaller</h1>
This page should show your local camera, and connect to a remote browser.
<table border="0">
<tr>
<th align="left">Local Preview</th>
<th align="left">Remote Video</th>
</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>
<tr>
<td valign="top">
<form>
Target peer ID: <input type="text" id="peer_id" size="3" value="1"/><br>
<button id="startcall" onclick="startCall();">(4) Start call</button><br>
<button id="stopcall" onclick="stopCall();" disabled="true">(5) Stop call
</button><br>
<!--<input type="button" value="Test 1" onclick="test1()"/><br>-->
</form>
</td>
<td valign="top">
<button onclick="toggleExtraButtons();">Toggle extra buttons</button><br>
<button id="createPcBtn" onclick="createPeerConnection();" hidden="true">
Create peer connection</button><br>
<button id="addStreamBtn" onclick="addStream();" hidden="true">
Add stream</button><br>
</td>
</tr>
<tr><td colspan="2">
(1) Server: <input type="text" id="server" value="http://localhost:8888" />
<br>
(2) Your name: <input type="text" id="local" value="caller"/>
<button id="connect" onclick="connect();" disabled="true">(3) Connect</button>
<button id="disconnect" onclick="disconnect();" disabled="true">(6) Disconnect
</button>
<br>
&nbsp;<br>
<button onclick="toggleLog()">Toggle view log</button>
<button onclick="document.getElementById('debug').innerHTML='';">
Clear log</button>
<pre id="debug">
</pre>
</td></tr>
</table>
</body>
<script>
// On init, we connect to the server.
connect();
</script>
</html>