diff --git a/di-edid-decode/meson.build b/di-edid-decode/meson.build
index 6c3e1a1..9aac5ff 100644
--- a/di-edid-decode/meson.build
+++ b/di-edid-decode/meson.build
@@ -9,3 +9,11 @@ di_edid_decode = executable(
dependencies: [di_dep, math],
install: true,
)
+
+if target_machine.system() == 'emscripten'
+ fs = import('fs')
+
+ foreach filename : ['index.html', 'main.js', 'style.css']
+ fs.copyfile('web' / filename)
+ endforeach
+endif
diff --git a/di-edid-decode/web/README.md b/di-edid-decode/web/README.md
new file mode 100644
index 0000000..be69050
--- /dev/null
+++ b/di-edid-decode/web/README.md
@@ -0,0 +1,11 @@
+# Webapp
+
+To build `di-edid-decode` as a webapp, install Emscripten and run:
+
+ meson setup build-wasm/ --cross-file di-edid-decode/web/wasm.txt
+ ninja -C build-wasm/
+
+Then start a web server serving static files in `build-wasm/di-edid-decode/`,
+for instance:
+
+ python -m http.server --directory build-wasm/di-edid-decode/
diff --git a/di-edid-decode/web/index.html b/di-edid-decode/web/index.html
new file mode 100644
index 0000000..b6e2ea4
--- /dev/null
+++ b/di-edid-decode/web/index.html
@@ -0,0 +1,32 @@
+
+
+
+
+ libdisplay-info
+
+
+
+
+ libdisplay-info
+
+
+ This webapp parses EDID files via
+ libdisplay-info.
+
+
+
+
+ Loading...
+
+
+
Select an EDID file:
+
+
+
+
+
+
+
+
diff --git a/di-edid-decode/web/main.js b/di-edid-decode/web/main.js
new file mode 100644
index 0000000..58a9262
--- /dev/null
+++ b/di-edid-decode/web/main.js
@@ -0,0 +1,70 @@
+let appElt = document.getElementById('app');
+let statusElt = document.getElementById('status');
+let fileInput = document.getElementById('file-input');
+let outputElt = document.getElementById('output');
+
+function handleFileChange() {
+ if (fileInput.files.length === 0) {
+ return;
+ }
+ let file = fileInput.files[0];
+ let reader = new FileReader();
+ reader.addEventListener('load', () => {
+ let filename = 'edid';
+ FS.writeFile(filename, new Uint8Array(reader.result));
+
+ outputElt.innerHTML = '';
+
+ let argv = ['di-edid-decode', filename];
+
+ let ptrSize = 4;
+ let cArgv = Module._malloc(argv.length * ptrSize);
+ for (let i = 0; i < argv.length; i++) {
+ let str = argv[i];
+ let cStr = Module._malloc(str.length + 1);
+ Module.stringToUTF8(str, cStr, str.length + 1);
+ Module.setValue(cArgv + i * ptrSize, cStr, '*');
+ }
+
+ let ret = Module._main(argv.length, cArgv);
+ console.log('di-edid-decode exited with code ' + ret);
+
+ for (let i = 0; i < argv.length; i++) {
+ let cStr = Module.getValue(cArgv + i * ptrSize, '*');
+ Module._free(cStr);
+ }
+ Module._free(cArgv);
+ });
+ reader.readAsArrayBuffer(file);
+}
+
+fileInput.addEventListener('change', handleFileChange);
+
+window.Module = {
+ noInitialRun: true,
+ setStatus: (text) => {
+ console.log(text || 'Done');
+ statusElt.innerText = text;
+ statusElt.style.display = text ? 'block' : 'none';
+ },
+ print: (text) => {
+ outputElt.appendChild(document.createTextNode(text + '\n'));
+ },
+ printErr: (text) => {
+ let elt = document.createElement('span');
+ elt.className = 'error';
+ elt.innerText = text + '\n';
+ outputElt.appendChild(elt);
+ },
+ onRuntimeInitialized: () => {
+ app.style.display = 'block';
+ handleFileChange();
+ },
+ onAbort: (text) => {
+ Module.setStatus('Abort: ' + text);
+ },
+};
+
+window.addEventListener('error', (event) => {
+ Module.setStatus('Error: ' + event.message);
+});
diff --git a/di-edid-decode/web/style.css b/di-edid-decode/web/style.css
new file mode 100644
index 0000000..ff39b3a
--- /dev/null
+++ b/di-edid-decode/web/style.css
@@ -0,0 +1,7 @@
+#app {
+ display: none;
+}
+
+.error {
+ color: red;
+}
diff --git a/di-edid-decode/web/wasm.txt b/di-edid-decode/web/wasm.txt
new file mode 100644
index 0000000..4f535f9
--- /dev/null
+++ b/di-edid-decode/web/wasm.txt
@@ -0,0 +1,15 @@
+[binaries]
+c = '/usr/lib/emscripten/emcc'
+cpp = '/usr/lib/emscripten/em++'
+ar = '/usr/lib/emscripten/emar'
+strip = '/usr/lib/emscripten/emstrip'
+
+[built-in options]
+default_library = 'static'
+c_link_args = ['-sEXPORTED_FUNCTIONS=_main,_malloc,_free', '-sEXPORTED_RUNTIME_METHODS=getValue,setValue,stringToUTF8']
+
+[host_machine]
+system = 'emscripten'
+cpu_family = 'wasm32'
+cpu = 'wasm32'
+endian = 'little'