GSoC 2026 Final Work Product: gr-cyberether
Youssef Mahmoud. Graphical interoperability between CyberEther and GNU Radio Mentors: Luigi Cruz , Håkon Vågsether Code: github.com/joeonit/gr-cyberether Weekly blog: joeonit.github.io
Overview
gr-cyberether is a GNU Radio Out-of-Tree (OOT) module that provides high-performance, modern visualization capabilities by relying on CyberEther rendering and visualization engine. The module is built using C++ and integrates with the GNU Radio ecosystem.
Deliverables
| Proposal | Outcome | |
|---|---|---|
| D0 | Module scaffold, CyberEther discovery, GNU Radio main and 3.10 compatibility | Done |
| D1 | Data-ingest path, investigate a custom cyber_buffer |
Done. Custom buffer investigated and rejected — why |
| D2 | cyber_context lifecycle manager |
Done, but not the design the proposal specified |
| D3 | Line plot + waterfall sinks, Python QA | Done |
| D4 | GRC integration | Done |
| More | constellation sink, spectrum analyzer and cyber_range for slider control and windows support | Done |
Where the work is
66 commits on main, 105 files, 10 pull requests.
| PR | ||
|---|---|---|
| #1 | Merged | Minimal lineplot sink + examples |
| #2 | Merged | SPSC ring buffer |
| #3 | Merged | cyber_context, dropping the ring buffer |
| #4 | Merged | Waterfall sink |
| #5 | Merged | Constellation sink |
| #6 | Open | cyber_range — blocked on CyberEther #289 |
| #7 | Merged | Require CyberEther 1.7.0, test against 1.9.1 |
| #8 | Merged | Windows release workflow |
| #9 | Merged | Reproducible Windows build |
| #10 | Open | Spectrum analyzer sink |
Also upstream, in CyberEther itself
| PR | ||
|---|---|---|
| #216 | Merged | feat: expose scatter/constellation plot type through superluminal |
| #289 | Open | feat(superluminal): add GlobalInterface for controls above the mosaic |
More details
Four sinks :
cyber_lineplot_sink— line plot, time or frequencycyber_waterfall_sink— scrolling waterfallcyber_constellation_sink— IQ scattercyber_spectrum_analyzer_sink— spectrum line over a waterfall, one shared FFT
Plus cyber_range, a slider drawn inside the window that retargets a GRC variable
while the flowgraph runs.

cyber_context
The cyber_context class is the central coordinator for gr-cyberether. It acts as a singleton that manages the registration of plot requests from GNU Radio sink blocks and orchestrates the lifecycle of the Superluminal rendering engine.

Source: lib/cyber_context.cc
· include/gnuradio/cyberether/cyber_context.h
Mosaic Layout
Once more than one sink could exist, they had to share a window without knowing about each other. Superluminal lays plots on a mosaic, so the question was how a GRC user says where a plot goes. Rather than invent a syntax, sinks take a GUI Hint in the one GNU Radio users already know:
"row, col" one cell
"row, col, row_span, col_span" a rectangle
The translation lives in lib/mosaic_layout.{h,cc} — compute_layout(hints) in,
grid and per-sink rects out. It is a pure function of its inputs, so it needs no
GPU, no window and no flowgraph to exercise.
sink hint resulting mosaic
─────────────────────────────────────────────────────
constellation "0, 0, 2, 1" ┌───┬───┬───┐
scope "0, 1" │ 0 │ 1 │ 2 │
spectrum "0, 2" │ ├───┴───┤
waterfall "1, 1, 1, 2" │ 0 │ 3 │
magnitude "2, 0, 1, 3" ├───┴───┴───┤
│ 4 │
└───────────┘
Source: lib/mosaic_layout.cc
· lib/mosaic_layout.h
Controls
cyber_range is the GNU Radio qtgui_range equivalent, a slider inside the
CyberEther window that retargets a flowgraph variable live.
It needed somewhere to draw that wasn’t a mosaic cell, because controls should not
eat a plot slot. so I added one upstream: Superluminal::GlobalInterface(), a full-width panel above the mosaic whose height is measured and reserved so it never overlaps the grid.

Packaging and support
- CI builds against GNU Radio 3.10 and main, CyberEther pinned by ref and cached
- Tagged releases publish archives for Linux x86_64, macOS arm64 and Windows x86_64,
with
libjetstreambundled and rpath rewritten — no CyberEther install needed packaging/install.shinside each archive finds your GNU Radio, checks compatibility, installs, and verifies- Examples install to
share/gnuradio/examples/cyberether, including an FM receive chain and a QPSK receiver with sync
Notable bugs, Code that is deleted or not yet done
Getting a window out of GRC
The hardest integration problem, and invisible when it works. CyberEther needs the
main thread’s event loop, and a generated top_block doesn’t expect to hand it
over. The easy answer is telling every user to paste in a Python Snippet block,
which wasn’t optimal.Instead the module ships its custom GRC workflow cyberether_standalone_gui.workflow.yml plus a generator module and Mako template. Pick it in the Options block and the generated top_block starts the flowgraph and calls cyberether.present() on the main thread.
Windows problems Five CI runs, five failures, each a genuinely different cause: Git’s
link.exe shadowing MSVC’s, the Vulkan SDK installed but not on INCLUDE,
PKG_CONFIG_PATH joined with a Unix : on a platform whose paths contain D:\,
pkgconf treating backslashes as escapes, and conda activate silently overwriting
PKG_CONFIG_PATH at the start of every step. None of these are findable without
executing on a real Windows runner. It passes now and publishes an archive.
The deleted ring buffer (#2, removed in #3). Solved a synchronisation problem that zero-copy in-place reads mean doesn’t exist. Understand the consumer’s contract before optimising the producer.
Not adopted: the custom cyber_buffer from D1. The gr-cuda template exists,
but it would remove a copy that isn’t happening. Worth revisiting only if a sink
ever needs data to stay device-side.
Not done
- Spectrum analyzer sink is not merged. Complete — block, bindings, GRC YAML,
5 passing QA tests, working demo but it needs a
Type::SpectrumAnalyzerthat is on an unreleased CyberEther branch. It merges when that ships. - PR #6 is open, waiting on CyberEther #289.
Acknowledgments
I am very thankful to my mentors, Luigi Cruz and Håkon Vågsether. They have been incredibly responsive, consistently guiding me and answering my questions. Also, my interactions with the community on Matrix have been very welcoming and supportive.