Files
ggwave/examples/ggwave-wasm/index-tmpl.html
2021-01-06 21:21:20 +00:00

334 lines
15 KiB
HTML

<!doctype html>
<html lang="en-us">
<head>
<meta charset="utf-8">
<title>ggwave : emscripten example</title>
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no"/>
<link rel="shortcut icon" href="favicon.ico">
<link rel="stylesheet" href="style.css">
</head>
<body>
<div id="main-container">
<h1>ggwave</h1>
Open this page on multiple devices (computers, phones, tablets, etc.). <br>
Press the init button and broadcast some text. Make sure your speakers and microphones are enabled.
<br><br>
<section>
<div id="sound"></div>
<table>
<tr>
<td colspan=3 align="center">
<button onClick="doInit()" id="butInit" disabled>Init</button>
</td>
</tr>
<tr>
<td colspan=3 align="center">
<div class="led-box">
<p>Output:</p>
</div>
<div class="led-box">
<p>Capture:</p>
</div>
<div class="led-box">
<p>Browser:</p>
</div>
</td>
</tr>
<tr>
<td colspan=3 align="center">
<div class="led-box" id="has-device-output" title="Indicates if an audio output device is available">
<div class="led-yellow"></div>
</div>
<div class="led-box" id="has-device-capture" title="Indicates if an audio capture device is available. Make sure this page has access to the microphone">
<div class="led-yellow"></div>
</div>
<div class="led-box" id="is-browser-supported" title="Indicates if the browser is supported">
<div class="led-yellow"></div>
</div>
</td>
</tr>
</table>
<table id="main-controls" hidden>
<tr>
<td colspan=1>
Tx protocol:
<select id="waveConfig" onChange="selectConfig(this.value);" title="Before broadcast/receive make sure this is set to the same value for all peers">
<option value=0>Normal</option>
<option value=1 selected>Fast</option>
<option value=2>Fastest</option>
<option value=3>[Ultrasound] Normal</option>
<option value=4>[Ultrasound] Fast</option>
<option value=5>[Ultrasound] Fastest</option>
</select>
</td>
<td colspan=1>
Volume:
<input type="range" min="1" max="100" value="10" class="slider" id="paramVolume" onInput="updateScroll('Volume');">
/ <label id="paramVolumeScroll"></label></td>
</td>
</tr>
<tr>
<td colspan=1>
<div>Rx data:</div> <textarea name="textarea" id="rxData" style="width:300px;height:100px;" disabled>
</textarea>
</td>
<td colspan=1>
<div>Tx Data:</div> <textarea name="textarea" id="txData" style="width:300px;height:100px;">This is the message to transmit.</textarea><br>
</td>
</tr>
<tr>
<td colspan=1>
<a id="peer-info"></a>
</td>
<td colspan=1>
<button onClick="lockoutSubmit(this); transmitText(document.getElementById('txData').value);">Broadcast</button>
</td>
</tr>
</table>
<span id="status"></span>
</section>
<br><hr>
<p>Standard output:</p>
<textarea id="output" rows="8"></textarea>
<div class="spinner" id='spinnerEm'></div>
<div class="emscripten" id="statusEm">Downloading...</div>
<div class="emscripten">
<progress value="0" max="100" id="progressEm" hidden=1></progress>
</div>
</div>
<div class="cell-version">
<span>
|
Build time: <span class="nav-link">@GIT_DATE@</span> |
Commit hash: <a class="nav-link" href="https://github.com/ggerganov/ggwave/commit/@GIT_SHA1@">@GIT_SHA1@</a> |
Commit subject: <span class="nav-link">@GIT_COMMIT_SUBJECT@</span> |
</span>
</div>
<div class="cell-about">
<a class="nav-link" href="https://github.com/ggerganov/ggwave/tree/master"><span class="d-none d-sm-inline">View on GitHub </span>
<svg version="1.1" width="16" height="16" viewBox="0 0 16 16" class="octicon octicon-mark-github" aria-hidden="true"><path fill-rule="evenodd" d="M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 0-.19-.01-.82-.01-1.49-2.01.37-2.53-.49-2.69-.94-.09-.23-.48-.94-.82-1.13-.28-.15-.68-.52-.01-.53.63-.01 1.08.58 1.23.82.72 1.21 1.87.87 2.33.66.07-.52.28-.87.51-1.07-1.78-.2-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82.64-.18 1.32-.27 2-.27.68 0 1.36.09 2 .27 1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08 2.12.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 1.93-.01 2.2 0 .21.15.46.55.38A8.013 8.013 0 0 0 16 8c0-4.42-3.58-8-8-8z"></path></svg>
</a>
</div>
<script type='text/javascript'>
var bufferRx = null;
var brx = new Uint8Array(256);
var volume = 10;
var protocolId = 1;
function lockoutSubmit(button) {
var oldValue = button.value;
button.setAttribute('disabled', true);
button.value = '...processing...';
setTimeout(function(){
button.value = oldValue;
button.removeAttribute('disabled');
}, 5000)
}
function selectConfig(configId) {
protocolId = parseInt(configId);
}
function updateScroll(sName) {
val = document.getElementById('param'+sName).value;
document.getElementById('param'+sName+'Scroll').innerHTML = val;
volume = val;
}
function getSampleRate() {
if (typeof Module === 'undefined') return;
var sampleRate = Module._getSampleRate();
}
var isiOS = /iPad|iPhone|iPod|CriOS/.test(navigator.userAgent) && !window.MSStream;
var isInitialized = false;
var isAudioContextUnlocked = !isiOS;
var htmlGreenLED = "<div class=\"led-green\"></div>";
var htmlRedLED = "<div class=\"led-red\"></div>";
var htmlYellowLED = "<div class=\"led-yellow\"></div>";
function checkStatus() {
var hasDeviceOutput = Module._hasDeviceOutput();
{
var el = document.getElementById('has-device-output');
if (hasDeviceOutput != 0 && isAudioContextUnlocked) {
if (el.innerHTML != htmlGreenLED) {
el.innerHTML = htmlGreenLED;
}
} else {
if (el.innerHTML != htmlRedLED) {
el.innerHTML = htmlRedLED;
}
}
}
var hasDeviceCapture = Module._hasDeviceCapture();
{
var el = document.getElementById('has-device-capture');
if (hasDeviceCapture != 0) {
if (el.innerHTML != htmlGreenLED) {
el.innerHTML = htmlGreenLED;
}
} else {
if (el.innerHTML != htmlRedLED) {
el.innerHTML = htmlRedLED;
}
}
}
var isBrowserSupported = !isiOS;
{
var el = document.getElementById('is-browser-supported');
if (isBrowserSupported) {
if (el.innerHTML != htmlGreenLED) {
el.innerHTML = htmlGreenLED;
}
} else {
if (el.innerHTML != htmlYellowLED) {
el.innerHTML = htmlYellowLED;
}
}
}
}
var statusElement = document.getElementById('statusEm');
var progressElement = document.getElementById('progressEm');
var spinnerElement = document.getElementById('spinnerEm');
var Module = {
doNotCaptureKeyboard: true,
pre: [],
preRun: [(function() {
let constraints = {
audio: {
echoCancellation: false,
autoGainControl: false,
noiseSuppression: false
}
};
let mediaInput = navigator.mediaDevices.getUserMedia( constraints );
}) ],
postRun: [ (function() { document.getElementById("butInit").disabled = false; }) ],
print: (function() {
var element = document.getElementById('output');
if (element) element.alue = ''; // clear browser cache
return function(text) {
if (arguments.length > 1) text = Array.prototype.slice.call(arguments).join(' ');
console.log(text);
if (element) {
element.value += text + "\n";
element.scrollTop = element.scrollHeight; // focus on bottom
}
};
})(),
printErr: function(text) {
if (arguments.length > 1) text = Array.prototype.slice.call(arguments).join(' ');
console.error(text);
},
setStatus: function(text) {
if (!Module.setStatus.last) Module.setStatus.last = { time: Date.now(), text: '' };
if (text === Module.setStatus.text) return;
var m = text.match(/([^(]+)\((\d+(\.\d+)?)\/(\d+)\)/);
var now = Date.now();
if (m && now - Date.now() < 30) return; // if this is a progress update, skip it if too soon
if (m) {
text = m[1];
progressElement.value = parseInt(m[2])*100;
progressElement.max = parseInt(m[4])*100;
progressElement.hidden = false;
spinnerElement.hidden = false;
} else {
progressElement.value = null;
progressElement.max = null;
progressElement.hidden = true;
if (!text) spinnerElement.style.display = 'none';
}
statusElement.innerHTML = text;
},
totalDependencies: 0,
monitorRunDependencies: function(left) {
this.totalDependencies = Math.max(this.totalDependencies, left);
Module.setStatus(left ? 'Preparing... (' + (this.totalDependencies-left) + '/' + this.totalDependencies + ')' : 'All downloads complete.');
}
};
function doInit() {
if (isInitialized == false) {
Module._doInit();
e = document.getElementById('waveConfig');
selectConfig(e.options[e.selectedIndex].value);
updateScroll('Volume');
bufferRx = Module._malloc(256);
setInterval(updatePeerInfo, 100);
setInterval(updateRx, 1000);
setInterval(checkStatus, 1000);
isInitialized = true;
}
playSound("plucky");
var x = document.getElementById("main-controls");
//x.style.display = "block";
x.hidden = false;
}
Module.setStatus('Initializing...');
window.onerror = function(event) {
Module.setStatus('Exception thrown, see JavaScript console');
spinnerElement.style.display = 'none';
Module.setStatus = function(text) {
if (text) Module.printErr('[post-exception status] ' + text);
};
};
window.addEventListener('touchstart', function() {
if (isAudioContextUnlocked == false && SDL2.audioContext) {
var buffer = SDL2.audioContext.createBuffer(1, 1, 22050);
var source = SDL2.audioContext.createBufferSource();
source.buffer = buffer;
source.connect(SDL2.audioContext.destination);
source.start();
setTimeout(function() {
if((source.playbackState === source.PLAYING_STATE || source.playbackState === source.FINISHED_STATE)) {
isAudioContextUnlocked = true;
Module.setStatus('Wab Audio API unlocked successfully!');
} else {
Module.setStatus('Failed to unlock Web Audio APIi. This browser seems to not be supported');
}
}, 0);
}
}, false);
function playSound(filename){
document.getElementById("sound").innerHTML='<audio id="soundInner"><source src="' + filename + '.mp3" type="audio/mpeg" /><embed hidden="true" autostart="true" loop="false" src="' + filename +'.mp3" /></audio>';
document.getElementById("soundInner").volume = paramVolume.value/100.0;
document.getElementById("soundInner").play();
}
</script>
<script async type="text/javascript" src="@TARGET@.js"></script>
<script type="text/javascript" src="main.js"></script>
</body>
</html>