The latest stable Synchronet release is v3.21e-Win32 (install), released Mar-2026.

You can donate to the Synchronet project using PayPal.

cterm_lib.js

The CTerm JavaScript library (cterm_lib.js) exposes the enhanced features of SyncTERM and other CTerm-compatible terminals to Synchronet JavaScript: terminal capability detection, loadable fonts, palette redefinition, detection of high-resolution graphics (Sixel, JPEG-XL) support, screen and pixel geometry queries, and digital audio playback.

Most of these features exist only on a capable terminal (principally SyncTERM), so the library also provides supports_*() functions to detect a feature before using it. On a terminal that lacks the feature, the corresponding output is simply ignored by the terminal, so a capability check is about avoiding wasted work and graceful fallback rather than preventing errors.

Loading

cterm_lib.js is a Return-style library: load it into an empty scope object and keep the returned object.

var cterm = load({}, 'cterm_lib.js');
if (cterm.supports_jpegxl())
    console.write(my_jpegxl_image);

When first loaded, the library queries the terminal's device attributes to learn its CTerm version and caches the result in the console object (so it is shared among multiple JavaScript contexts). Load it from a script running on a user's terminal session, not from an unconnected context such as a timed event.

Capability detection

Each function reports whether the connected terminal supports a feature. All return a boolean except supports_fonts(), which may also return undefined for an older CTerm (e.g. SyncTERM 1.0) that predates feature queries.

Function True when the terminal supports...
supports_fonts() loadable / selectable fonts
supports_palettes() palette (color) redefinition
supports_sixel() Sixel bitmap graphics
supports_jpegxl() JPEG-XL image display
supports_audio() the audio channel (at least synthesized tones)
supports_audio_files() audio and decoding of sound files (client libsndfile)
var cterm = load({}, 'cterm_lib.js');
if (cterm.supports_sixel())
    console.write(my_sixel_image);

Fonts

For the common case of loading the fonts configured in fonts.ini, use the higher-level fonts.js library instead. cterm_lib.js provides the lower-level primitives it is built on:

  • load_font(slot, data, force) – load raw font bitmap data into terminal font slot (43..255).
  • activate_font(style, slot, wantblink) – select a loaded slot for a display style (font_styles.normal, .high, .blink, .highblink).
  • activate_fonts(slots) – activate an array of { style, slot } selections at once.

Palettes

  • redefine_palette(palette, bits) – redefine the terminal's color palette. palette is an array of RGB entries; bits is the per-channel bit depth of the supplied values.
  • reset_palette() – restore the terminal's default palette.
  • bright_background(enable) – enable (or disable) bright background colors (high-intensity background attribute rather than blink).

Screen geometry

  • cterm_screen_geometry() – resolve the terminal's character and pixel geometry for pixel-addressed protocols (image tiers, Z-machine v6, etc.). Returns { cols, rows, cellW, cellH, pxW, pxH }, falling back to sane defaults (an 8-pixel-wide graphics cell) when the terminal does not report a value.
  • query_graphicsdim() – the terminal's graphics canvas size, in pixels.

Audio

On SyncTERM v1.10 and later, cterm_lib.js can play digital sound effects and music through the terminal's audio channel. The terminal keeps 256 patch slots of decoded audio and mixes them on channels 2..15; the library manages those slots and channels for you.

Check capability first: supports_audio_files() is true when the terminal can decode a sound file, and supports_audio() is true when at least synthesized tones are available (a terminal built without libsndfile). On any other terminal the audio calls are harmless no-ops.

Sound data is a file's raw bytes as a binary string, i.e. File.open("rb") then read(). The format is whatever the client's libsndfile decodes: WAV, VOC, OGG/Opus and FLAC work everywhere; MP3 only where the client's libsndfile is 1.1.0 or newer. Prefer OGG or WAV for portability – there is no per-format capability probe.

Playing audio

The convenience functions handle slot and channel allocation and upload each sound only once per session:

  • play_sound(name, data, opts) – play a one-shot sound-effect file. opts: vol (0..100, default 100), pan (-100 left .. 0 center .. +100 right), loop, ch. Returns { slot, ch }.
  • play_tone(freq, ms, opts) – play a synthesized tone (no file needed). opts: shape ("SINE", "SQUARE", "SAWTOOTH", ...), vol, pan, ch.
  • play_music(name, data, opts) – play a sound file looped on a reserved music channel. Returns a handle { volume: function(0..100), stop: function([fade_ms]) } for a live volume slider and stop/fade-out.
var cterm = load({}, 'cterm_lib.js');
 
if (cterm.supports_audio_files()) {
    // one-shot sound effect
    var f = new File(js.exec_dir + "beep.wav");
    f.open("rb"); var beep = f.read(); f.close();
    cterm.play_sound("beep", beep);
 
    // looping background music with a live volume control
    f = new File(js.exec_dir + "theme.ogg");
    f.open("rb"); var theme = f.read(); f.close();
    var music = cterm.play_music("theme", theme, { vol: 60 });
    // later:  music.volume(30);  music.stop(500 /* ms fade-out */);
} else if (cterm.supports_audio()) {
    cterm.play_tone(440, 250);      // a 440 Hz beep, no sound file required
}

Low-level control

The convenience functions above are built from one-verb primitives, available when you want to manage slots and channels yourself (e.g. to preload a bank of effects):

Function Purpose
audio_store(name, data) cache a sound file under name
audio_load(slot, name) decode the cached name into patch slot (0..255)
audio_queue(ch, slot, opts) play slot on channel ch (2..15); opts: vol/pan/loop
audio_volume(ch, vol) set a channel's live volume (adjusts a sound already playing)
audio_volume_lr(ch, vl, vr) set a channel's live per-side volume (stereo balance)
audio_synth(slot, shape, freq, ms) synthesize a tone into slot (works without libsndfile)
audio_flush(ch, fade_ms) stop a channel, with an optional fade-out

See Also