Repository navigation
Stations
The code lives under crates/ and bins/ in the glass repository. The sections follow a frame through the display, from its inputs to the window, and then the crates the others stand on. No crate reads from a binary, and none reads from a crate that reads from it; bank and logline read from no other crate.
The types and the readers, no drawing and no windows. Input is one snapshot: Levels, Bins and Metadata (the track, the player's status, position and length, volume, mute, random, repeat, infinity). SkinDesc is a theme as geometry: sizes, angles, boxes, keys, font files, the indicators, the buttons, the run settings. lead parses the display's meter.txt and a theme's meters.txt into those, resolves the fonts per style (fonts_from_config), reads the format key aliases, and holds the small pure helpers the others share (current_value, frame_period, the dismiss rule). Files and the clock go through it: read_file, is_file and dir_entries read the file system first and the table a host filled (vfs) after, and clock_us is the process's own clock, or the host's where the target has none, so the same code runs on a player, a remote and in a browser. lead::tailor is the cutter's table: every key the parser reads classified by what its value is (a point on the screen, a size, a length, a font size, a picture, or something that does not scale), the Plan from one screen size to another, and a theme's text files rewritten by it line by line; a test holds the parser to the table.
Where a frame's inputs come from. TapSource reads the tap's ring under /dev/shm (tap::ring, a ring of the previous version projected onto the bank on the way) and the plugin's channel (intake::channel, a local socket of JSON lines; the player is asked over HTTP once a second without it), and sends the display's commands up the same channel. Selector rolls the meter rotation. Album art, the pictures from the track's folder and the artist fanart are fetched off the frame loop; in a browser, where nothing can be fetched, intake::wants lists what the meter is waiting for so the page brings it. intake::hops merges the frames a remote or a page receives. intake::bring is what a display brings from a player's manager, the files to fetch as a plan and the player's configuration rewritten for a home of the display's own, the same for a remote, which fetches into a directory, and a page, which fetches into the file table. intake::remote is the remote's side: Beacon (finding players), NetHops (the frames over UDP, the gain and the decay), and Sync (the player's configuration, theme and assets into a cache home, by checksum, with the configuration rewritten to point there, or at a folder on the remote's own machine).
step(skin, input) -> Scene. Pure. The scene is every drawn thing as geometry: needle angles, bar heights, text lines and their motion, art boxes, the record's and reels' angles, the indicators' states, the spectrum's bars, and for a spectrum section with a style the Analyser: its look, its box and the bands per channel on the bar scale. Recorded steps under testdata/frames/ replay it without a display.
Rasters a scene into a Frame of RGBA bytes: pictures, fonts (ab_glyph, a fallback face per glyph), needles and bars, turning pictures by row spans, fades, the spectrum, the indicators and the buttons. A scene becomes a list of read-only ops with keys and boxes; only the boxes whose keys changed are painted, in strips across the painter threads, over a base composed once per meter. raster_over is the entry; Motion keeps what moves between frames, AnalyserMotion the analyser's smoothed bars and peaks with the two frames it draws them into, TypeIcon the format's icon decoded once, and Pictures keeps every picture a scene names (the album art, the type icon, the folder layers, the fanart, the record and the reels), decoded once per file and box, off the frame loop on a machine and in the frame in a browser. expose::ui holds the primitives a face draws with: a filled rectangle, a frame blitted with an alpha, a line of text. write_png writes a frame as a PNG file, for snapshots and a package's preview.
A meter's controls under a finger, shared by the display, the remotes and the browser module: where the theme's buttons and indicators are drawn (controls_of, from the scene's indicators and the pictures' sizes), which control a point lands on with the touch margin (control_at), what a tap asks for (Tapped: a command, a meter step, a dismiss), and Touch, the state between frames: a finger down on a bar starts a drag whose value stands over the scene's (override_scene) and goes out as the volume every 150 ms, a finger on a button shows its active picture, a lift ends the drag or is a tap. Pure: the display and the module hand it their pointer events and send what comes back down the channel.
The contract between the display and a face drawn over the theme, the same on the player's own screen and in a browser. Overlay is what a face is asked: what it covers of the frame about to be shown (Cover: nothing, the same as the frame before, or something new), to draw over the frame after the theme, every pointer event before the theme's controls see it, and the commands it wants sent to the player. View is what a face is shown each frame: the input, the fonts, the picture's size, the display's clock, the time of day (Wall), and its own face.<name> settings from the configuration. Laid lays a face over a copy of the frame kept between frames, so a face that stands over a picture that stands is not drawn again; Black is the black picture put behind a face once the player has stood still past the persist countdown (stands_black). overlay::face gathers the types a face is written against. No window and no file system here.
The pipeline for a page in a browser: the same configuration, theme, fonts and icons a remote display brings, the same hops, the same scene and the same raster, compiled to WebAssembly and driven by the page. The page fetches; Page reads what the page put in the file table, steps and paints, takes the page's pointer events, and lays a face over the frame in a module that carries one. page::exports! writes the raw exports a host without bindings calls into the crate that is the module's root.
The window: SDL2, full screen, windowed or frameless, on a chosen screen, a streaming texture the frame's changed boxes are uploaded into. Surface::show returns what the window saw: kept, closed, touched, or a key asking to leave or take full screen; pointer events come out in the frame's own pixels through take_pointer. write_ppm writes a frame as a PPM file for headless runs.
The audio tap: relay carries periods off the audio thread, sample, dsd and dop read the stream's words and tell one-bit audio apart, analysis takes the peaks, RMS and the bank a hop at a time, measure runs the stream through it by its shape and follows demand, the file the plugin writes to say what bank the theme on show wants, ring is the shared file readers take hops from, wire is the frame datagram remotes receive, fifo is a FIFO written without ever blocking the audio thread, open only while a reader has it open, legacy the FIFO records and the old decay for what still reads them, the regrouping that gives a theme of the previous engine its bars from the bank, and the projection of a raw spectrum from a ring of the previous version. tapdump lives here as a binary.
The spectrum analyser behind every spectrum Glass draws, a port of the evo framework's terminus analyser under its Apache-2.0 licence. Analyser::new(rate, demand) for a Demand of bands (up to 256), channels (1 or 2), Scale (log, mel, linear) and window (2048 to 16384); process takes the last window of each channel and gives a Bank: the bands per channel with a full-scale sine reading one, the peak hold per band falling by half every quarter second, an onset per band group (Onsets: sub-bass, bass, mid, high, as bits), the left-right correlation per band; process_into fills a bank the caller keeps. Projector puts a raw spectrum from an older tap onto the same bands. edges and centres give a demand's band frequencies. The log scale is the ANSI/IEC S1.11 equal-ratio partition of 20 Hz to 20 kHz; bands that would read the same FFT bins are told apart at construction. Pure compute, no I/O, and no allocation per hop through process_into.
The lines every program writes: a level from GLASS_LOG or set while running, targets at the fine levels, standard output and error on the desktop, logcat on Android.
| Binary | What it does |
|---|---|
glass |
The display: polls, steps, rasters and shows at the frame rate; the review switches (--list, --theme, --meter, --snapshot, --record, --dev); the cutter and the packager (--tailor, --from, --out, --spectrum, --stretch, --package); as glass --remote, the same display fed over the network, with its settings page (bins/glass/src/remote). Its library entry run_with runs the same display with a face over it (the overlay crate). |
glass-serve |
The frames daemon on the player: reads the ring, sends one datagram per tick of its rate to subscribed remotes with the hops since the last merged, and serves the same datagrams to browser pages as an event stream on a local socket. |
glass-face |
The page crate's pipeline as a WebAssembly module with no face over it, for the manager's Face tab and Anymote; the files and the clock come from the page. A module that carries a face is the same one line, page::exports!, with the face named. |
glasstap |
The ALSA PCM plugin and scope, built around tap. |
tapdump |
Prints the live ring. |
glass-android |
The display as the library SDL's Android activity enters. |
glass-remote |
A name kept from the first design; the remote is glass --remote. |
- Home
- Quick-Start
- Settings
- Manager
- Manager-API
- Screen
- Artwork
- Catalog
- Backups
- Remotes
- Anymote
- Performance
- Troubleshooting
- Logging
Themes
Developers
The Glass interface