mirror of
https://github.com/DeeJanuz/frametop.git
synced 2026-10-24 19:00:47 +02:00
A remote display is a screen of ft-screens whose picture comes from another computer, streamed by Vibepollo with Moonlight's protocol. ft-screens (screens/remote.c) runs one ft-stream per remote screen (101 and up) over a socket pair: ft-stream (stream/, GPLv3: moonlight-common-c and moonlight-embedded's libgamestream, pinned) decodes on the iris decoder into a ring of three RGBA buffers that ft-screens shows as a panel with a screen's controls, layout, profiles, curve, pins and hand cutouts. Mouse, keys and scroll go back to the host; a button's release goes through the stream it was pressed on, as Vibepollo wants, and a press carried onto another remote panel moves the pointer there. A panel out of sight gets 10 fps; the host's sound plays from one stream per host. ft-stream signs in with an API token and the host's pinned public key (stream/host.cpp), and chooses its path: a Steam Link dongle on the Frame's hotspot when it answers, or the network (the layout's "route": auto, network or dongle). ft-layout gets "remote" commands (list, add, connect, disconnect, host route and direct), starts the connected displays with the desktop and keeps disconnected ones parked. ft-gaze and ft-pointer know the remote panels. ft-screens now shuts its VR side down before its streams and waits for SteamVR before exiting (a vrcompositor crash at quit, in standby). docs/remote-displays.md has the design, the spikes and the test results. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
55 lines
1.9 KiB
Python
Executable File
55 lines
1.9 KiB
Python
Executable File
#!/usr/bin/env python3
|
|
"""Write the S1 colour test pattern as raw RGB24 (width x height x 3 bytes).
|
|
|
|
Bands from the top: 100% colour bars, 75% colour bars, a 16-step grey ramp,
|
|
near-black steps (0-30), near-white steps (225-255), and a black strip where the
|
|
clip's moving box runs. ft-dectest shows the same picture as an RGB reference next
|
|
to the decoded video, so a wrong YUV matrix or range shows as a visible difference:
|
|
range errors lift or crush the near-black and near-white steps, matrix errors shift
|
|
the bar hues.
|
|
|
|
usage: pattern.py WIDTH HEIGHT OUT.rgb
|
|
"""
|
|
import sys
|
|
|
|
BARS = [(1, 1, 1), (1, 1, 0), (0, 1, 1), (0, 1, 0), (1, 0, 1), (1, 0, 0), (0, 0, 1), (0, 0, 0)]
|
|
|
|
|
|
def row(width, colours):
|
|
"""One row of len(colours) equal columns; the last absorbs the remainder."""
|
|
out = bytearray()
|
|
n = len(colours)
|
|
for i, c in enumerate(colours):
|
|
x0, x1 = width * i // n, width * (i + 1) // n
|
|
out += bytes(c) * (x1 - x0)
|
|
return bytes(out)
|
|
|
|
|
|
def bands(height):
|
|
"""(rows, colours) per band, top to bottom; fractions of the height."""
|
|
split = [0.28, 0.20, 0.16, 0.14, 0.14]
|
|
rows = [int(height * f) for f in split]
|
|
rows.append(height - sum(rows)) # the box strip
|
|
level = lambda v: [tuple(int(round(v * 255 * k)) for k in c) for c in BARS]
|
|
return [
|
|
(rows[0], level(1.0)),
|
|
(rows[1], level(0.75)),
|
|
(rows[2], [(v, v, v) for v in (round(i * 255 / 15) for i in range(16))]),
|
|
(rows[3], [(v, v, v) for v in range(0, 32, 2)]),
|
|
(rows[4], [(v, v, v) for v in range(225, 256, 2)]),
|
|
(rows[5], [(0, 0, 0)]),
|
|
]
|
|
|
|
|
|
def main():
|
|
width, height, out = int(sys.argv[1]), int(sys.argv[2]), sys.argv[3]
|
|
with open(out, "wb") as f:
|
|
for n, colours in bands(height):
|
|
f.write(row(width, colours) * n)
|
|
# The box strip's top row, for make-clips.sh to place the moving box.
|
|
print(height - bands(height)[-1][0])
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|