When a viewer window has no incoming stream, renders animated analog-TV noise (hash-based, scanlines, phosphor tint) at configurable fps (default 15) with a centred "NO SIGNAL" text overlay. - xorg: FRAG_NOSIGNAL_SRC shader + xorg_viewer_render_no_signal(v, time, noise_res) - main: Display_Slot gains no_signal_fps + last_no_signal_t; display_loop_tick drives no-signal render on idle slots via clock_gettime rate limiting - protocol: START_DISPLAY extended by 2 bytes — no_signal_fps (0=default 15) + reserved; reader is backward-compatible (defaults 0 if length < 18) - controller_cli: no_signal_fps optional arg on start-display - docs: protocol.md updated with new field Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
91 lines
3.3 KiB
C
91 lines
3.3 KiB
C
#pragma once
|
|
|
|
#include <stdbool.h>
|
|
#include <stddef.h>
|
|
#include <stdint.h>
|
|
|
|
typedef struct Xorg_Viewer Xorg_Viewer;
|
|
|
|
/*
|
|
* How the frame is scaled to fit the window.
|
|
* SCALE_STRETCH is the only implemented mode; others are reserved.
|
|
*/
|
|
typedef enum Xorg_Scale {
|
|
XORG_SCALE_STRETCH, /* fill window, ignore aspect ratio (default) */
|
|
XORG_SCALE_FIT, /* largest rect that fits, preserve aspect, black bars */
|
|
XORG_SCALE_FILL, /* smallest rect that covers, preserve aspect, crop edges */
|
|
XORG_SCALE_1_1, /* native pixel size, no scaling */
|
|
} Xorg_Scale;
|
|
|
|
/*
|
|
* Where the frame is positioned within the window.
|
|
* Used with XORG_SCALE_FIT, XORG_SCALE_FILL, and XORG_SCALE_1_1.
|
|
*/
|
|
typedef enum Xorg_Anchor {
|
|
XORG_ANCHOR_CENTER, /* center frame in window (default) */
|
|
XORG_ANCHOR_TOP_LEFT, /* align frame to top-left corner */
|
|
} Xorg_Anchor;
|
|
|
|
/* Returns false when compiled without HAVE_GLFW. */
|
|
bool xorg_available(void);
|
|
|
|
/*
|
|
* Open a viewer window at screen position (x, y) with the given size.
|
|
* Returns NULL if xorg is unavailable or if window/context creation fails.
|
|
*/
|
|
Xorg_Viewer *xorg_viewer_open(int x, int y, int width, int height,
|
|
const char *title);
|
|
|
|
/* Push a YUV 4:2:0 planar frame for immediate display. */
|
|
bool xorg_viewer_push_yuv420(Xorg_Viewer *v,
|
|
const uint8_t *y, const uint8_t *cb, const uint8_t *cr,
|
|
int width, int height);
|
|
|
|
/* Push a packed BGRA frame for immediate display. */
|
|
bool xorg_viewer_push_bgra(Xorg_Viewer *v,
|
|
const uint8_t *data, int width, int height);
|
|
|
|
/*
|
|
* Push a MJPEG frame. Decoded via libjpeg-turbo to planar YUV before upload.
|
|
* Returns false if compiled without HAVE_TURBOJPEG.
|
|
*/
|
|
bool xorg_viewer_push_mjpeg(Xorg_Viewer *v,
|
|
const uint8_t *data, size_t size);
|
|
|
|
/* Change scale/anchor at any time; takes effect on the next render. */
|
|
void xorg_viewer_set_scale(Xorg_Viewer *v, Xorg_Scale scale);
|
|
void xorg_viewer_set_anchor(Xorg_Viewer *v, Xorg_Anchor anchor);
|
|
|
|
/*
|
|
* Set a text overlay at window-pixel position (x, y) — top-left of the text.
|
|
* Up to 8 overlays (idx 0..7); calling with the same idx replaces it.
|
|
* r, g, b are in [0, 1].
|
|
*/
|
|
void xorg_viewer_set_overlay_text(Xorg_Viewer *v, int idx, int x, int y,
|
|
const char *text, float r, float g, float b);
|
|
|
|
/* Remove all text overlays. */
|
|
void xorg_viewer_clear_overlays(Xorg_Viewer *v);
|
|
|
|
/*
|
|
* Render one frame of animated analog-TV noise with a centred "NO SIGNAL"
|
|
* label. time is seconds (e.g. glfwGetTime()); noise_res is cells per axis
|
|
* (lower = coarser, default 80 when 0 is passed).
|
|
* Call at low frame rate (~15 fps) when the viewer has no incoming stream.
|
|
*/
|
|
void xorg_viewer_render_no_signal(Xorg_Viewer *v, float time, float noise_res);
|
|
|
|
/*
|
|
* Process pending window events.
|
|
* Returns false when the user has closed the window.
|
|
* Must be called from the thread that created the viewer.
|
|
*
|
|
* poll() — processes events then re-renders; use for static images.
|
|
* handle_events() — processes events only, no render; use when push_* drives
|
|
* rendering (e.g. live camera feed).
|
|
*/
|
|
bool xorg_viewer_poll(Xorg_Viewer *v);
|
|
bool xorg_viewer_handle_events(Xorg_Viewer *v);
|
|
|
|
void xorg_viewer_close(Xorg_Viewer *v);
|