Join one FM-Funknetz talk group from a headset window.

The station reads ~/.funknetz.json, speaks protocol 2.0, and builds an unsigned funknetz.app.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Konrad Neitzel
2026-10-03 16:21:41 +02:00
co-authored by Cursor
parent 8e75515460
commit 9c4f6621fc
23 changed files with 2933 additions and 0 deletions
+98
View File
@@ -0,0 +1,98 @@
const button = document.getElementById("ptt");
function api() {
if (!window.go || !window.go.main || !window.go.main.App) {
return null;
}
return window.go.main.App;
}
function line(state) {
if (state.detail && state.detail !== "Idle") {
return state.detail;
}
if (state.talker) {
return state.talker;
}
return "Idle";
}
function render(state) {
document.getElementById("connection").textContent = state.connection;
document.getElementById("callsign").textContent = state.callsign;
document.getElementById("talkgroup").textContent = String(state.talkGroup);
document.getElementById("detail").textContent = line(state);
button.classList.toggle("down", !!state.transmitting);
}
function refresh() {
const app = api();
if (!app) {
return;
}
app.State().then(render).catch(function () {});
}
button.addEventListener("pointerdown", function (event) {
event.preventDefault();
button.setPointerCapture(event.pointerId);
const app = api();
if (app) {
app.HoldButton();
}
});
function releaseButton() {
const app = api();
if (app) {
app.ReleaseButton();
}
}
button.addEventListener("pointerup", releaseButton);
button.addEventListener("pointercancel", releaseButton);
let spaceHeld = false;
window.addEventListener("keydown", function (event) {
if (event.code !== "Space") {
return;
}
event.preventDefault();
if (event.repeat || spaceHeld) {
return;
}
spaceHeld = true;
const app = api();
if (app) {
app.HoldSpace();
}
});
window.addEventListener("keyup", function (event) {
if (event.code !== "Space") {
return;
}
event.preventDefault();
if (!spaceHeld) {
return;
}
spaceHeld = false;
const app = api();
if (app) {
app.ReleaseSpace();
}
});
window.addEventListener("blur", function () {
spaceHeld = false;
const app = api();
if (!app) {
return;
}
app.ReleaseButton();
app.ReleaseSpace();
});
setInterval(refresh, 100);
refresh();