Permalink
Fetching contributors…
Cannot retrieve contributors at this time
executable file 540 lines (452 sloc) 20 KB
<!--
> Muaz Khan - github.com/muaz-khan
> MIT License - www.webrtc-experiment.com/licence
> Documentation - www.RTCMultiConnection.org
-->
<!DOCTYPE html>
<html lang="en">
<head>
<title>RTCMultiConnection All-in-One Test ® Muaz Khan</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no">
<link rel="author" type="text/html" href="https://plus.google.com/+MuazKhan">
<meta name="author" content="Muaz Khan">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<link rel="stylesheet" href="https://cdn.webrtc-experiment.com/style.css">
<style>
audio,
video {
-moz-transition: all 1s ease;
-ms-transition: all 1s ease;
-o-transition: all 1s ease;
-webkit-transition: all 1s ease;
transition: all 1s ease;
vertical-align: top;
}
input {
border: 1px solid #d9d9d9;
border-radius: 1px;
font-size: 2em;
margin: .2em;
width: 20%;
}
select {
border: 1px solid #d9d9d9;
border-radius: 1px;
height: 50px;
margin-left: 1em;
margin-right: -12px;
padding: 1.1em;
vertical-align: 6px;
}
.setup {
border-bottom-left-radius: 0;
border-top-left-radius: 0;
font-size: 102%;
height: 47px;
margin-left: -9px;
margin-top: 8px;
position: absolute;
}
p {
padding: 1em;
}
#chat-output div,
#file-progress div {
border: 1px solid black;
border-bottom: 0;
padding: .1em .4em;
}
#chat-output,
#file-progress {
margin: 0 0 0 .4em;
max-height: 12em;
overflow: auto;
}
.data-box input {
border: 1px solid black;
font-family: inherit;
font-size: 1em;
margin: .1em .3em;
outline: none;
padding: .1em .2em;
width: 97%;
}
</style>
<script>
document.createElement('article');
document.createElement('footer');
</script>
<!-- webrtc library used for streaming -->
<script src="https://cdn.webrtc-experiment.com/firebase.js">
</script>
<script src="https://cdn.webrtc-experiment.com/getMediaElement.min.js">
</script>
<script src="https://cdn.webrtc-experiment.com/RTCMultiConnection.js">
</script>
</head>
<body>
<article>
<header style="text-align: center;">
<h1>
<a href="http://www.RTCMultiConnection.org/" target="_blank">RTCMultiConnection</a> All-in-One test ®
<a href="https://github.com/muaz-khan" target="_blank">Muaz Khan</a>
</h1>
<p>
<a href="https://www.webrtc-experiment.com/">HOME</a>
<span> &copy; </span>
<a href="http://www.MuazKhan.com/" target="_blank">Muaz Khan</a> .
<a href="http://twitter.com/WebRTCWeb" target="_blank" title="Twitter profile for WebRTC Experiments">@WebRTCWeb</a> .
<a href="https://github.com/muaz-khan?tab=repositories" target="_blank" title="Github Profile">Github</a> .
<a href="https://github.com/muaz-khan/RTCMultiConnection/issues?state=open" target="_blank">Latest issues</a> .
<a href="https://github.com/muaz-khan/RTCMultiConnection/commits/master" target="_blank">What's New?</a>
</p>
</header>
<div class="github-stargazers"></div>
<!-- just copy this <section> and next script -->
<section class="experiment">
<div style="float: right;">
<input type="checkbox" id="fakeDataChannels" style="width: auto;">
<label for="fakeDataChannels" title="You can chat and share files using your preferred signaling gateway instead of using WebRTC data channels!">Setup Fake Data Connection?</label>
</div>
<h2 class="header" id="feedback">
Select SessionType and Direction-of-Flow!
</h2>
<section>
<select id="session" title="Session">
<option>audio+video+data+screen</option>
<option>audio+video+data</option>
<option>audio+data+screen</option>
<option>audio+video+screen</option>
<option selected>audio+video</option>
<option>audio+screen</option>
<option>video+screen</option>
<option>data+screen</option>
<option>audio+data</option>
<option>video+data</option>
<option>audio</option>
<option>video</option>
<option>data</option>
<option>screen</option>
</select>
<select id="direction" title="Direction">
<option>many-to-many</option>
<option>one-to-one</option>
<option>one-to-many</option>
<option>one-way</option>
</select>
<input type="text" id="session-name">
<button id="setup-new-session" class="setup">New Session</button>
</section>
<!-- list of all available broadcasting rooms -->
<table style="width: 100%;" id="rooms-list"></table>
<!-- local/remote videos container -->
<div id="videos-container"></div>
</section>
<section class="experiment data-box">
<h2 class="header" style="border-bottom: 0;">WebRTC DataChannel</h2>
<table style="width: 100%;">
<tr>
<td>
<h2 style="display: block; font-size: 1em; text-align: center;">Text Chat</h2>
<div id="chat-output"></div>
<input type="text" id="chat-input" style="font-size: 1.2em;" placeholder="chat message" disabled>
</td>
<td style="background: white;">
<h2 style="display: block; font-size: 1em; text-align: center;">Share Files</h2>
<input type="file" id="file" disabled>
<div id="file-progress"></div>
</td>
</tr>
</table>
</section>
<script>
// Muaz Khan - www.MuazKhan.com
// MIT License - www.WebRTC-Experiment.com/licence
// Documentation - www.RTCMultiConnection.org
var connection = new RTCMultiConnection();
connection.session = {
audio: true,
video: true
};
var roomsList = document.getElementById('rooms-list'),
sessions = {};
connection.onNewSession = function(session) {
if (sessions[session.sessionid]) return;
sessions[session.sessionid] = session;
var tr = document.createElement('tr');
tr.innerHTML = '<td><strong>' + session.extra['session-name'] + '</strong> is an active session.</td>' +
'<td><button class="join">Join</button></td>';
roomsList.insertBefore(tr, roomsList.firstChild);
tr.querySelector('.join').setAttribute('data-sessionid', session.sessionid);
tr.querySelector('.join').onclick = function() {
this.disabled = true;
session = sessions[this.getAttribute('data-sessionid')];
if (!session) alert('No room to join.');
connection.join(session);
};
};
var videosContainer = document.getElementById('videos-container') || document.body;
connection.onstream = function(e) {
var buttons = ['mute-audio', 'mute-video', 'record-audio', 'record-video', 'full-screen', 'volume-slider', 'stop'];
if (connection.session.audio && !connection.session.video) {
buttons = ['mute-audio', 'full-screen', 'stop'];
}
var mediaElement = getMediaElement(e.mediaElement, {
width: (videosContainer.clientWidth / 2) - 50,
title: e.userid,
buttons: buttons,
onMuted: function(type) {
connection.streams[e.streamid].mute({
audio: type == 'audio',
video: type == 'video'
});
},
onUnMuted: function(type) {
connection.streams[e.streamid].unmute({
audio: type == 'audio',
video: type == 'video'
});
},
onRecordingStarted: function(type) {
// www.RTCMultiConnection.org/docs/startRecording/
connection.streams[e.streamid].startRecording({
audio: type == 'audio',
video: type == 'video'
});
},
onRecordingStopped: function(type) {
// www.RTCMultiConnection.org/docs/stopRecording/
connection.streams[e.streamid].stopRecording(function(blob) {
if (blob.audio) connection.saveToDisk(blob.audio);
else if (blob.video) connection.saveToDisk(blob.video);
else connection.saveToDisk(blob);
}, type);
},
onStopped: function() {
connection.peers[e.userid].drop();
}
});
videosContainer.insertBefore(mediaElement, videosContainer.firstChild);
if (e.type == 'local') {
mediaElement.media.muted = true;
mediaElement.media.volume = 0;
}
};
connection.onstreamended = function(e) {
if (e.mediaElement.parentNode && e.mediaElement.parentNode.parentNode && e.mediaElement.parentNode.parentNode.parentNode) {
e.mediaElement.parentNode.parentNode.parentNode.removeChild(e.mediaElement.parentNode.parentNode);
}
};
var setupNewSession = document.getElementById('setup-new-session');
setupNewSession.onclick = function() {
setupNewSession.disabled = true;
var direction = document.getElementById('direction').value;
var _session = document.getElementById('session').value;
var splittedSession = _session.split('+');
var session = {};
for (var i = 0; i < splittedSession.length; i++) {
session[splittedSession[i]] = true;
}
var maxParticipantsAllowed = 256;
if (direction == 'one-to-one') maxParticipantsAllowed = 1;
if (direction == 'one-to-many') session.broadcast = true;
if (direction == 'one-way') session.oneway = true;
var sessionName = document.getElementById('session-name').value;
connection.extra = {
'session-name': sessionName || 'Anonymous'
};
connection.session = session;
connection.maxParticipantsAllowed = maxParticipantsAllowed;
if (!!document.querySelector('#fakeDataChannels').checked) {
// http://www.rtcmulticonnection.org/docs/fakeDataChannels/
connection.fakeDataChannels = true;
}
connection.sessionid = sessionName || 'Anonymous';
connection.open();
};
connection.onmessage = function(e) {
appendDIV(e.data);
console.debug(e.userid, 'posted', e.data);
console.log('latency:', e.latency, 'ms');
};
connection.onclose = function(e) {
appendDIV('Data connection is closed between you and ' + e.userid);
};
connection.onleave = function(e) {
appendDIV(e.userid + ' left the session.');
};
// on data connection gets open
connection.onopen = function() {
if (document.getElementById('chat-input')) document.getElementById('chat-input').disabled = false;
if (document.getElementById('file')) document.getElementById('file').disabled = false;
if (document.getElementById('open-new-session')) document.getElementById('open-new-session').disabled = true;
};
var progressHelper = {};
connection.autoSaveToDisk = false;
connection.onFileProgress = function(chunk) {
var helper = progressHelper[chunk.uuid];
helper.progress.value = chunk.currentPosition || chunk.maxChunks || helper.progress.max;
updateLabel(helper.progress, helper.label);
};
connection.onFileStart = function(file) {
var div = document.createElement('div');
div.title = file.name;
div.innerHTML = '<label>0%</label> <progress></progress>';
appendDIV(div, fileProgress);
progressHelper[file.uuid] = {
div: div,
progress: div.querySelector('progress'),
label: div.querySelector('label')
};
progressHelper[file.uuid].progress.max = file.maxChunks;
};
connection.onFileEnd = function(file) {
progressHelper[file.uuid].div.innerHTML = '<a href="' + file.url + '" target="_blank" download="' + file.name + '">' + file.name + '</a>';
};
function updateLabel(progress, label) {
if (progress.position == -1) return;
var position = +progress.position.toFixed(2).split('.')[1] || 100;
label.innerHTML = position + '%';
}
function appendDIV(div, parent) {
if (typeof div === 'string') {
var content = div;
div = document.createElement('div');
div.innerHTML = content;
}
if (!parent) chatOutput.insertBefore(div, chatOutput.firstChild);
else fileProgress.insertBefore(div, fileProgress.firstChild);
div.tabIndex = 0;
div.focus();
}
document.getElementById('file').onchange = function() {
connection.send(this.files[0]);
};
var chatOutput = document.getElementById('chat-output'),
fileProgress = document.getElementById('file-progress');
var chatInput = document.getElementById('chat-input');
chatInput.onkeypress = function(e) {
if (e.keyCode !== 13 || !this.value) return;
appendDIV(this.value);
// sending text message
connection.send(this.value);
this.value = '';
};
connection.connect();
</script>
<section class="experiment">
<ol>
<li>Mesh networking model is implemented to open multiple (1:1) interconnected peer connections</li>
<li>Maximum peer connections limit per page is
<strong>256</strong> (on chrome) i.e. 256 users can connect together!</li>
</ol>
</section>
<section class="experiment">
<h2 class="header">How to use <a href="http://www.RTCMultiConnection.org/" target="_blank">RTCMultiConnection</a>?</h2>
<pre>
// https://cdn.webrtc-experiment.com/RTCMultiConnection.js
</pre>
</section>
<section class="experiment">
<h2 class="header">Common Code</h2>
<pre>
var MODERATOR_CHANNEL_ID = 'ABCDEF'; // channel-id
var MODERATOR_SESSION_ID = 'XYZ'; // room-id
var MODERATOR_ID = 'JKL'; // user-id
var MODERATOR_SESSION = { // media-type
audio: true,
video: true
};
var MODERATOR_EXTRA = {}; // empty extra-data
</pre>
</section>
<section class="experiment">
<h2 class="header">Code for Room Moderator (i.e. Initiator)</h2>
<pre>
var moderator = <a href="http://www.RTCMultiConnection.org/docs/constructor/">new RTCMultiConnection</a>(MODERATOR_CHANNEL_ID);
moderator.<a href="http://www.RTCMultiConnection.org/docs/session/">session</a> = MODERATOR_SESSION;
moderator.<a href="http://www.RTCMultiConnection.org/docs/userid/">userid</a> = MODERATOR_ID;
moderator.<a href="http://www.RTCMultiConnection.org/docs/extra/">extra</a> = MODERATOR_EXTRA;
moderator.<a href="http://www.RTCMultiConnection.org/docs/open/">open</a>({
dontTransmit: true,
sessionid: MODERATOR_SESSION_ID
});
</pre>
</section>
<section class="experiment">
<h2 class="header">Code for Room Participants</h2>
<pre>
var participants = <a href="http://www.RTCMultiConnection.org/docs/constructor/">new RTCMultiConnection</a>(MODERATOR_CHANNEL_ID);
participants.<a href="http://www.RTCMultiConnection.org/docs/join/">join</a>({
sessionid: MODERATOR_SESSION_ID,
userid: MODERATOR_ID,
extra: MODERATOR_EXTRA,
session: MODERATOR_SESSION
});
</pre>
</section>
<section class="experiment">
<h2 class="header">(optional) Handle how to get streams</h2>
<pre>
// same code can be used for participants
// (it is optional)
connection.<a href="http://www.RTCMultiConnection.org/docs/onstreamid/">onstreamid</a> = function(event) {
// got a clue of incoming remote stream
// didn't get remote stream yet
var incoming_stream_id = event.streamid;
YOUR_PREVIEW_IMAGE.show();
// or
YOUR_PREVIEW_VIDEO.show();
};
// same code can be used for participants
// it is useful
connection.<a href="http://www.RTCMultiConnection.org/docs/onstream/">onstream</a> = function(event) {
// got local or remote stream
// if(event.type == 'local') {}
// if(event.type == 'remote') {}
document.body.appendChild(event.mediaElement);
// or YOUR_VIDEO.src = event.blobURL;
// or YOUR_VIDEO.src = URL.createObjectURL(event.stream);
};
// same code can be used for participants
// it is useful but optional
connection.<a href="http://www.RTCMultiConnection.org/docs/onstreamended/">onstreamended</a> = function(event) {
event.mediaElement.parentNode.removeChild(event.mediaElement);
};
</pre>
</section>
<section class="experiment own-widgets">
<h2 class="header" id="updates" style="color: red;padding-bottom: .1em;"><a href="https://github.com/muaz-khan/RTCMultiConnection/issues">Latest Issues</a></h2>
<div id="github-issues"></div>
</section>
<section class="experiment">
<h2 class="header" id="feedback">Feedback</h2>
<div>
<textarea id="message" style="border: 1px solid rgb(189, 189, 189); height: 8em; margin: .2em; outline: none; resize: vertical; width: 98%;" placeholder="Have any message? Suggestions or something went wrong?"></textarea>
</div>
<button id="send-message" style="font-size: 1em;">Send Message</button>
<small style="margin-left: 1em;">Enter your email too; if you want "direct" reply!</small>
</section>
<section class="experiment own-widgets latest-commits">
<h2 class="header" id="updates" style="color: red; padding-bottom: .1em;"><a href="https://github.com/muaz-khan/RTCMultiConnection/commits/master" target="_blank">Latest Updates</a>
</h2>
<div id="github-commits"></div>
</section>
</article>
<a href="https://github.com/muaz-khan/RTCMultiConnection" class="fork-left"></a>
<footer>
<a href="https://www.webrtc-experiment.com/" target="_blank">WebRTC Experiments!</a> and
<a href="http://www.RTCMultiConnection.org/" target="_blank">RTCMultiConnection.js</a> ©
<a href="mailto:muazkh@gmail.com" target="_blank">Muaz Khan</a>:
<a href="https://twitter.com/WebRTCWeb" target="_blank">@WebRTCWeb</a>
</footer>
<!-- commits.js is useless for you! -->
<script>
window.useThisGithubPath = 'muaz-khan/RTCMultiConnection';
</script>
<script src="https://cdn.webrtc-experiment.com/commits.js" async>
</script>
</body>
</html>