From 0c4c76f77ed95f588c73d1fb6e7ad28f1b1fbd27 Mon Sep 17 00:00:00 2001 From: Georgi Gerganov Date: Sun, 29 Nov 2020 11:21:06 +0000 Subject: [PATCH] ggwave-wasm : add html shell --- examples/ggwave-wasm/CMakeLists.txt | 5 + examples/ggwave-wasm/index-tmpl.html | 400 +++++++++++++++++++++++++++ examples/ggwave-wasm/main.js | 60 ++++ examples/ggwave-wasm/plucky.mp3 | Bin 0 -> 28003 bytes examples/ggwave-wasm/style.css | 279 +++++++++++++++++++ 5 files changed, 744 insertions(+) create mode 100644 examples/ggwave-wasm/index-tmpl.html create mode 100644 examples/ggwave-wasm/main.js create mode 100644 examples/ggwave-wasm/plucky.mp3 create mode 100644 examples/ggwave-wasm/style.css diff --git a/examples/ggwave-wasm/CMakeLists.txt b/examples/ggwave-wasm/CMakeLists.txt index f9db37e..18937da 100644 --- a/examples/ggwave-wasm/CMakeLists.txt +++ b/examples/ggwave-wasm/CMakeLists.txt @@ -16,3 +16,8 @@ target_link_libraries(${TARGET} PRIVATE ggwave-common ggwave-common-sdl2 ) + +configure_file(${CMAKE_CURRENT_SOURCE_DIR}/index-tmpl.html ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${TARGET}/index.html @ONLY) +configure_file(${CMAKE_CURRENT_SOURCE_DIR}/style.css ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${TARGET}/style.css COPYONLY) +configure_file(${CMAKE_CURRENT_SOURCE_DIR}/main.js ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${TARGET}/main.js COPYONLY) +configure_file(${CMAKE_CURRENT_SOURCE_DIR}/plucky.mp3 ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${TARGET}/plucky.mp3 COPYONLY) diff --git a/examples/ggwave-wasm/index-tmpl.html b/examples/ggwave-wasm/index-tmpl.html new file mode 100644 index 0000000..10fbff8 --- /dev/null +++ b/examples/ggwave-wasm/index-tmpl.html @@ -0,0 +1,400 @@ + + + + + ggwave : emscripten example + + + + + + + +
+

ggwave

+ + Open this page on multiple devices (computers, phones, tables, etc.).
+ Press the init button and broadcast some text. Make sure your speakers and microphones are enabled. + +

+ +
+
+ + + + + + + + + + + +
+ +
+
+

Output:

+
+
+

Capture:

+
+
+

Browser:

+
+
+
+
+
+
+
+
+
+
+
+
+ + + + + + + + + + + + + + + + + +
+ +

+ +

Standard output:

+ + +
+
Downloading...
+ +
+ +
+
+ +
+ + | + Build time: @GIT_DATE@ | + Commit hash: @GIT_SHA1@ | + Commit subject: @GIT_COMMIT_SUBJECT@ | + +
+
+ View on GitHub + + +
+ + + + + + + diff --git a/examples/ggwave-wasm/main.js b/examples/ggwave-wasm/main.js new file mode 100644 index 0000000..fd64655 --- /dev/null +++ b/examples/ggwave-wasm/main.js @@ -0,0 +1,60 @@ +/*! \file main.js + * \brief Text transfer over sound + * \author Georgi Gerganov + */ + +function transmitText(sText) { + var r = new Uint8Array(256); + for (var i = 0; i < sText.length; ++i) { + r[i] = sText.charCodeAt(i); + } + + var buffer = Module._malloc(256); + Module.writeArrayToMemory(r, buffer, 256); + Module._setText(sText.length, buffer); + Module._free(buffer); +} + +var firstTimeFail = false; +var peerInfo = document.querySelector('a#peer-info'); + +function updatePeerInfo() { + if (typeof Module === 'undefined') return; + var framesLeftToRecord = Module._getFramesLeftToRecord(); + var framesToRecord = Module._getFramesToRecord(); + var framesLeftToAnalyze = Module._getFramesLeftToAnalyze(); + var framesToAnalyze = Module._getFramesToAnalyze(); + + if (framesToAnalyze > 0) { + peerInfo.innerHTML= + "Analyzing Rx data: "; + peerReceive.innerHTML= ""; + } else if (framesLeftToRecord > Math.max(0, 0.05*framesToRecord)) { + firstTimeFail = true; + peerInfo.innerHTML= + "Transmission in progress: "; + } else if (framesToRecord > 0) { + peerInfo.innerHTML= "Analyzing Rx data ..."; + } else if (framesToRecord == 0) { + peerInfo.innerHTML= "

Listening for waves ...

"; + } else if (framesToRecord == -1) { + if (firstTimeFail) { + playSound("/media/case-closed"); + firstTimeFail = false; + } + peerInfo.innerHTML= "

Failed to decode Rx data

"; + } +} + +function updateRx() { + if (typeof Module === 'undefined') return; + Module._getText(bufferRx); + var result = ""; + for (var i = 0; i < 140; ++i){ + result += (String.fromCharCode((Module.HEAPU8)[bufferRx + i])); + brx[i] = (Module.HEAPU8)[bufferRx + i]; + } + document.getElementById('rxData').innerHTML = result; +} diff --git a/examples/ggwave-wasm/plucky.mp3 b/examples/ggwave-wasm/plucky.mp3 new file mode 100644 index 0000000000000000000000000000000000000000..367a0e90b38a5969c5fcd6f1421fa432fc3f09a0 GIT binary patch literal 28003 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 Udj2Ek{r}}V|NrCvFHhkA01tk+TmS$7 literal 0 HcmV?d00001 diff --git a/examples/ggwave-wasm/style.css b/examples/ggwave-wasm/style.css new file mode 100644 index 0000000..7d02fde --- /dev/null +++ b/examples/ggwave-wasm/style.css @@ -0,0 +1,279 @@ +body { + margin: 0; background-color: white; + -webkit-font-smoothing: subpixel-antialiased; + font-smoothing: subpixel-antialiased; +} +#screen { + margin: 0; + padding: 0; + font-size: 13px; + height: 100%; + font: sans-serif; +} +.no-sel { + -moz-user-select: none; + -webkit-user-select: none; + -webkit-touch-callout: none; + -ms-user-select:none; + user-select:none; + -o-user-select:none; +} +.cell { + pointer-events: none; +} +.cell-version { + padding-left: 4px; + padding-top: 0.5em; + text-align: left; + display: inline-block; + float: left; + color: rgba(0, 0, 0, 0.75); +} +.cell-about { + padding-right: 24px; + padding-top: 0.5em; + text-align: right; + display: inline-block; + float: right; +} +.nav-link { + text-decoration: none; + color: rgba(0, 0, 0, 1.0); +} + +#main-container { + font-size:12px; + font-family: monospace; +} + +textarea { + font-size:12px; + font-family: monospace; +} + +.emscripten { padding-right: 0; margin-left: auto; margin-right: auto; display: block; } +div.emscripten { text-align: center; } +div.emscripten_border { border: 1px solid black; } + +canvas.emscripten { border: 0px none; background-color: black; } + +.spinner { + height: 30px; + width: 30px; + margin: 0; + margin-top: 20px; + margin-left: 20px; + display: inline-block; + vertical-align: top; + + -webkit-animation: rotation .8s linear infinite; + -moz-animation: rotation .8s linear infinite; + -o-animation: rotation .8s linear infinite; + animation: rotation 0.8s linear infinite; + + border-left: 5px solid rgb(235, 235, 235); + border-right: 5px solid rgb(235, 235, 235); + border-bottom: 5px solid rgb(235, 235, 235); + border-top: 5px solid rgb(120, 120, 120); + + border-radius: 100%; + background-color: rgb(189, 215, 46); +} + +@-webkit-keyframes rotation { + from {-webkit-transform: rotate(0deg);} + to {-webkit-transform: rotate(360deg);} +} +@-moz-keyframes rotation { + from {-moz-transform: rotate(0deg);} + to {-moz-transform: rotate(360deg);} +} +@-o-keyframes rotation { + from {-o-transform: rotate(0deg);} + to {-o-transform: rotate(360deg);} +} +@keyframes rotation { + from {transform: rotate(0deg);} + to {transform: rotate(360deg);} +} + +#status { + display: inline-block; + vertical-align: top; + margin-top: 30px; + margin-left: 20px; + font-weight: bold; + color: rgb(120, 120, 120); +} + +#progress { + height: 20px; + width: 30px; +} + +#output { + width: 800px; + height: 200px; + margin: 0 auto; + margin-top: 10px; + border-left: 0px; + border-right: 0px; + padding-left: 0px; + padding-right: 0px; + background-color: black; + color: white; + font-size:10px; + font-family: 'Lucida Console', Monaco, monospace; + outline: none; +} + +.led-box { + height: 30px; + width: 25%; + margin: 10px 0; + float: left; +} + +.led-box p { + font-size: 12px; + text-align: center; + margin: 1em; +} + +.led-red { + margin: 0 auto; + width: 12px; + height: 12px; + background-color: #F00; + border-radius: 50%; + box-shadow: rgba(0, 0, 0, 0.2) 0 -1px 7px 1px, inset #441313 0 -1px 9px, rgba(255, 0, 0, 0.5) 0 2px 12px; + -webkit-animation: blinkRed 0.5s infinite; + -moz-animation: blinkRed 0.5s infinite; + -ms-animation: blinkRed 0.5s infinite; + -o-animation: blinkRed 0.5s infinite; + animation: blinkRed 0.5s infinite; +} + +@-webkit-keyframes blinkRed { + from { background-color: #F00; } + 50% { background-color: #A00; box-shadow: rgba(0, 0, 0, 0.2) 0 -1px 7px 1px, inset #441313 0 -1px 9px, rgba(255, 0, 0, 0.5) 0 2px 0;} + to { background-color: #F00; } +} +@-moz-keyframes blinkRed { + from { background-color: #F00; } + 50% { background-color: #A00; box-shadow: rgba(0, 0, 0, 0.2) 0 -1px 7px 1px, inset #441313 0 -1px 9px, rgba(255, 0, 0, 0.5) 0 2px 0;} + to { background-color: #F00; } +} +@-ms-keyframes blinkRed { + from { background-color: #F00; } + 50% { background-color: #A00; box-shadow: rgba(0, 0, 0, 0.2) 0 -1px 7px 1px, inset #441313 0 -1px 9px, rgba(255, 0, 0, 0.5) 0 2px 0;} + to { background-color: #F00; } +} +@-o-keyframes blinkRed { + from { background-color: #F00; } + 50% { background-color: #A00; box-shadow: rgba(0, 0, 0, 0.2) 0 -1px 7px 1px, inset #441313 0 -1px 9px, rgba(255, 0, 0, 0.5) 0 2px 0;} + to { background-color: #F00; } +} +@keyframes blinkRed { + from { background-color: #F00; } + 50% { background-color: #A00; box-shadow: rgba(0, 0, 0, 0.2) 0 -1px 7px 1px, inset #441313 0 -1px 9px, rgba(255, 0, 0, 0.5) 0 2px 0;} + to { background-color: #F00; } +} + +.led-yellow { + margin: 0 auto; + width: 12px; + height: 12px; + background-color: #FF0; + border-radius: 50%; + box-shadow: rgba(0, 0, 0, 0.2) 0 -1px 7px 1px, inset #808002 0 -1px 9px, #FF0 0 2px 12px; + -webkit-animation: blinkYellow 1s infinite; + -moz-animation: blinkYellow 1s infinite; + -ms-animation: blinkYellow 1s infinite; + -o-animation: blinkYellow 1s infinite; + animation: blinkYellow 1s infinite; +} + +@-webkit-keyframes blinkYellow { + from { background-color: #FF0; } + 50% { background-color: #AA0; box-shadow: rgba(0, 0, 0, 0.2) 0 -1px 7px 1px, inset #808002 0 -1px 9px, #FF0 0 2px 0; } + to { background-color: #FF0; } +} +@-moz-keyframes blinkYellow { + from { background-color: #FF0; } + 50% { background-color: #AA0; box-shadow: rgba(0, 0, 0, 0.2) 0 -1px 7px 1px, inset #808002 0 -1px 9px, #FF0 0 2px 0; } + to { background-color: #FF0; } +} +@-ms-keyframes blinkYellow { + from { background-color: #FF0; } + 50% { background-color: #AA0; box-shadow: rgba(0, 0, 0, 0.2) 0 -1px 7px 1px, inset #808002 0 -1px 9px, #FF0 0 2px 0; } + to { background-color: #FF0; } +} +@-o-keyframes blinkYellow { + from { background-color: #FF0; } + 50% { background-color: #AA0; box-shadow: rgba(0, 0, 0, 0.2) 0 -1px 7px 1px, inset #808002 0 -1px 9px, #FF0 0 2px 0; } + to { background-color: #FF0; } +} +@keyframes blinkYellow { + from { background-color: #FF0; } + 50% { background-color: #AA0; box-shadow: rgba(0, 0, 0, 0.2) 0 -1px 7px 1px, inset #808002 0 -1px 9px, #FF0 0 2px 0; } + to { background-color: #FF0; } +} + +.led-green { + margin: 0 auto; + width: 12px; + height: 12px; + background-color: #ABFF00; + border-radius: 50%; + box-shadow: rgba(0, 0, 0, 0.2) 0 -1px 7px 1px, inset #304701 0 -1px 9px, #89FF00 0 2px 12px; +} + +.led-blue { + margin: 0 auto; + width: 18px; + height: 18px; + background-color: #24E0FF; + border-radius: 50%; + box-shadow: rgba(0, 0, 0, 0.2) 0 -1px 7px 1px, inset #006 0 -1px 9px, #3F8CFF 0 2px 14px; +} + +table td { + border: 1px solid #e8e8e8; +} +table th, table td { + padding: 10px 10px; +} +table td { + border: 1px solid #e8e8e8; +} +table th, table td { + padding: 10px 10px; +} +td[Attributes Style] { + text-align: -webkit-center; +} +td { + display: table-cell; + vertical-align: inherit; +} +table { + margin-bottom: 30px; + width: 800px; + text-align: left; + color: #3f3f3f; + border-collapse: collapse; + border: 1px solid #e8e8e8; +} +table { + margin-bottom: 30px; + width: 800px; + text-align: left; + color: #3f3f3f; + border-collapse: collapse; + border: 1px solid #e8e8e8; +} +table { + border-collapse: separate; + border-spacing: 2px; +}