Audio capture and streaming app for webOS 5/6

Captures the TV's audio and sends it out over several transports. The
primary one is HyperHDR: RTP/L16 to a host-side loopback device, since
HyperHDR has no network audio input of its own. A second route renders
the spectrum on the TV and sends FlatBuffers images to port 19400
instead, for setups where touching the host's sound config is not an
option.

  native/       the service: capture backends (PulseAudio, ALSA, exec,
                test tone, all dlopen-based), DSP, and one file per sink
  frontend/     D-pad driven UI at a fixed 1920x1080
  servicefiles/ native service manifest plus the boot script
  host/         RTP receiver and the loopback installer for the HyperHDR
                machine
  tools/        build/package, asset generation, Homebrew Channel
                manifest, on-TV probe
  test/         host-side suites: FlatBuffers and RTP verified against
                real decoders, the engine end to end, the page in jsdom

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Rene Kievits
2026-08-26 10:21:00 +02:00
co-authored by Claude Opus 5
commit 7529a60650
73 changed files with 12826 additions and 0 deletions
+32
View File
@@ -0,0 +1,32 @@
// Minimal glib stand-in, used only to syntax-check service.c and main.c on a
// development machine that has no webOS SDK installed. It declares exactly the
// handful of symbols this project uses and nothing else; the real headers are
// what the TV build compiles against.
#pragma once
#include <stdbool.h>
typedef int gboolean;
typedef int gint;
typedef unsigned int guint;
typedef void* gpointer;
typedef struct _GMainLoop GMainLoop;
typedef struct _GMainContext GMainContext;
#define TRUE 1
#define FALSE 0
#define G_SOURCE_REMOVE FALSE
#define G_SOURCE_CONTINUE TRUE
typedef gboolean (*GSourceFunc)(gpointer user_data);
GMainLoop* g_main_loop_new(GMainContext* context, gboolean is_running);
void g_main_loop_run(GMainLoop* loop);
void g_main_loop_quit(GMainLoop* loop);
void g_main_loop_unref(GMainLoop* loop);
guint g_idle_add(GSourceFunc function, gpointer data);
gboolean g_atomic_int_compare_and_exchange(gint* atomic, gint oldval, gint newval);
void g_atomic_int_set(gint* atomic, gint newval);