Add no-signal animation to display windows
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>
This commit is contained in:
@@ -7,6 +7,7 @@
|
||||
#include <pthread.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <time.h>
|
||||
#include <sys/sysmacros.h>
|
||||
#include <linux/videodev2.h>
|
||||
|
||||
@@ -183,6 +184,10 @@ struct Display_Slot {
|
||||
uint32_t frame_len;
|
||||
int frame_ready;
|
||||
|
||||
/* No-signal animation */
|
||||
int no_signal_fps; /* 0 → default 15 */
|
||||
double last_no_signal_t;
|
||||
|
||||
/* Viewer — created and used only on the main thread */
|
||||
Xorg_Viewer *viewer;
|
||||
};
|
||||
@@ -521,6 +526,16 @@ static void display_loop_tick(struct Node *node)
|
||||
xorg_viewer_push_mjpeg(d->viewer, vf.data, vf.data_len);
|
||||
}
|
||||
free(fdata);
|
||||
} else {
|
||||
/* No live frame — render no-signal animation at configured fps */
|
||||
struct timespec ts;
|
||||
clock_gettime(CLOCK_MONOTONIC, &ts);
|
||||
double now = (double)ts.tv_sec + (double)ts.tv_nsec * 1e-9;
|
||||
double interval = 1.0 / (double)(d->no_signal_fps > 0 ? d->no_signal_fps : 15);
|
||||
if (now - d->last_no_signal_t >= interval) {
|
||||
xorg_viewer_render_no_signal(d->viewer, (float)now, 80.0f);
|
||||
d->last_no_signal_t = now;
|
||||
}
|
||||
}
|
||||
|
||||
/* Poll GLFW events; if user closes the window, treat as STOP_DISPLAY */
|
||||
@@ -1083,9 +1098,10 @@ static void handle_start_display(struct Node *node,
|
||||
d->win_y = (int)req.win_y;
|
||||
d->win_w = req.win_w > 0 ? (int)req.win_w : 1280;
|
||||
d->win_h = req.win_h > 0 ? (int)req.win_h : 720;
|
||||
d->scale = proto_scale_to_xorg(req.scale);
|
||||
d->anchor = proto_anchor_to_xorg(req.anchor);
|
||||
d->wanted_state = DISP_OPEN; /* reconciled by display_loop_tick */
|
||||
d->scale = proto_scale_to_xorg(req.scale);
|
||||
d->anchor = proto_anchor_to_xorg(req.anchor);
|
||||
d->no_signal_fps = req.no_signal_fps > 0 ? (int)req.no_signal_fps : 15;
|
||||
d->wanted_state = DISP_OPEN; /* reconciled by display_loop_tick */
|
||||
pthread_mutex_unlock(&d->mutex);
|
||||
|
||||
proto_write_control_response(conn, req.request_id, PROTO_STATUS_OK, NULL, 0);
|
||||
|
||||
Reference in New Issue
Block a user