omx-panel

The skin package

El text del projecte, en anglès. La font d'aquesta pàgina

The skin package

A skin package is a directory named after the plugin it draws. The plugin id is the name. An id that holds a byte outside A-Z a-z 0-9 . _ - (an LV2 URI) has each such byte written as %XX, and . and .. alone are never a name, so the name is always safe in a path. One function writes the name, encodeSkinId (src/skin-package.ts), and decodeSkinId reads it back. This package creates /usr/share/omx/skins for packages to be installed into; which directories a host reads, and in what order, is the host's.

<plugin id>/
  skin.json          the override file, required, even if it only names the licence
  view/              optional: a view of the skin's own
    index.mjs        an ES module, the entry
  i18n/<lang>.json   optional: label key to text, one file per language
  art/               optional: the images the override file names
  modgui/            optional: a MOD GUI, imported from a bundle or generated

skin.json

One schema, declared twice in one place: schema/skin-package.schema.json (JSON Schema, what omx-panel validate checks) and parseSkinOverride (src/skin-package.ts, what a reader applies). A test holds the two to the same verdict on every broken copy of the example. A file holds:

Field Meaning
schema 1, the file's schema version; any other value refuses the file
plugin the plugin id; a reader refuses a file whose id is not the directory's decoded name
licence the SPDX expression of everything in the package; required
source where the package came from: own, generated or modgui, with the bundle and the licenceEvidence an importer read; an imported MOD GUI may name its own icon template and stylesheet, modgui: { html, css }, both under modgui/
fingerprint the panel description fingerprint the file was written against; a mismatch is a warning, never a refusal
family a panel family; replaces the description's
roles role (time, band_freq[2]) to control symbol; replaces the description's roles, each checked against the family
sections [{ key, labelKey?, label?, controls }]; replaces the sections and their order; a control named nowhere goes to a last section, never hidden
labels control symbol to { labelKey?, label? }
visibleWhen control symbol to { param, values }, the integer values 0 to 63 that show it
displays [{ kind, section, source, ... }], the displays the panel draws
houseView the family of the house view to use
look the default look; a client's own choice still wins
backdrop an image under art/
view { entry, api }: the view's entry under view/ (view/index.mjs) and the skin API version it was written for, MAJOR.MINOR
modgui { entry } under modgui/: the opt-in for a MOD GUI's own script, never beside a view

A path in a skin is relative to the package and stays inside it: no absolute path, no .. segment, no backslash.

The skin restates no range, unit or scale. The plugin's own description holds those, and the skin binds to a control by its symbol and its meaning.

Applying it

applySkinOverride(description, override) applies the file to a panel description field by field. An entry that names an unknown symbol, a role the family has no place for or whose unit it does not take, or a display in no section is dropped and listed with its reason (unknown-symbol, unknown-section, role-not-in-family, role-unit, role-repeats); the rest of the file stands. The role check reads ROLES of tools/panel-description.mjs; a caller may pass its own. That table is wider than the console's own at five roles: threshold of gate, dynamics, limiter and deesser and ceiling of limiter take db, dbfs, dbu, lufs here and db, dbfs in the console. A console that keeps its own table passes it as the check; one that adopts this table accepts a threshold in dBu or LUFS.

Refusals

Each refusal is a code with named arguments (SKIN_REFUSAL_CODES): SKIN_OVERRIDE_INVALID (the file does not parse or fails the schema, args.field the first field that broke it), SKIN_OVERRIDE_ENTRY_DROPPED, SKIN_API_MISMATCH, SKIN_VIEW_ERROR, SKIN_VIEW_LINT, SKIN_MODGUI_LICENCE, and the importer's own ten, MODGUI_* (below).

The licence

SKIN_LICENCE_ALLOW_LIST is the one list a MOD GUI's licence must be on: GPL-2.0-or-later, GPL-3.0-or-later, LGPL-2.1-or-later, LGPL-3.0-or-later, MIT, BSD-2-Clause, BSD-3-Clause, ISC, Zlib, CC0-1.0 and CC-BY-4.0. spdxFromDoapLicence reads a plugin's doap:license as an SPDX id; mapping is not permission.

Importing a MOD GUI

omx-panel import <bundle.lv2> --out <skins dir> [--plugin <uri>] (tools/modgui-import.mjs) reads a bundle's modgui.ttl and the plugin's doap:license and writes a package: one section in modgui:port order, each port's lv2:name as its label, the screenshot as the backdrop under art/, the whole resources directory and the TTL under modgui/, and source { kind: "modgui", bundle, licenceEvidence }. It writes no view, no family and no roles. It refuses, with a code that names the file it read and nothing written: MODGUI_NOT_FOUND, MODGUI_TTL_INVALID, MODGUI_NO_LICENCE, MODGUI_LICENCE_UNMAPPED, MODGUI_LICENCE_REFUSED (outside the allow-list), MODGUI_UNKNOWN_PROPERTY, MODGUI_PORT_UNKNOWN (a modgui:port or modgui:monitoredOutputs symbol the plugin does not carry), MODGUI_IMAGE_NOT_FOUND (a template image the bundle does not hold), MODGUI_PATH_ESCAPE (a resource, or a template reference, outside the bundle) and MODGUI_TARGET_EXISTS.

The known modgui:gui properties are mod-ui's whole list, not only the ones a reviewed bundle used: resourcesDirectory, iconTemplate, settingsTemplate, javascript, stylesheet, screenshot, thumbnail, documentation, discussionURL, brand, label, model, panel, color, knob, port and monitoredOutputs (MODGUI_GUI_PROPERTIES). Any other modgui: property is MODGUI_UNKNOWN_PROPERTY, as is an lv2: property on a modgui:port other than index, symbol and name. The file-valued ones (iconTemplate, settingsTemplate, javascript, stylesheet, screenshot, thumbnail, and documentation when it names a file: IRI; MODGUI_FILE_PROPERTIES) must resolve inside the bundle and are copied with the package; discussionURL, and a documentation that names a web address, are kept as text and never fetched.

Every modgui:port is checked against the plugin's own lv2:port declarations in the bundle, the same TTL the importer reads for the licence: a modgui:port whose lv2:symbol names no lv2:symbol of the plugin's own ports is MODGUI_PORT_UNKNOWN, naming the file and the symbol, so a renamed or stale modgui entry is never imported as if it controlled a real parameter. A modgui:monitoredOutputs entry is checked the same way: its lv2:symbol (or the literal symbol it names) must be one of the plugin's own ports.

Every image a template names (MODGUI_TEMPLATE_PROPERTIES: the icon template and the settings template; an HTML src="..." or src='...' or a CSS url(...) inside it) is checked. A Mustache suffix like {{{ns}}} (mod-ui's ?uri=...), a query and a fragment are dropped, and the path is percent-decoded once and its dot segments resolved, as a browser and mod-ui's server do, before anything else is decided. Under mod-ui's /resources/ route (MODGUI_RESOURCES_ROUTE, the bundle's resourcesDirectory) a path that climbs out of the resources directory is MODGUI_PATH_ESCAPE, whether its target exists or not; one that names no file there, the directory itself included, is MODGUI_IMAGE_NOT_FOUND, naming the template file and the path it names. A web address, any other absolute path, or a relative path that climbs out of the bundle is MODGUI_PATH_ESCAPE, so a drawn template never reaches outside the package. The absolute paths kept are mod-ui's own routes, the directories its static handler serves from its html directory, /fonts/, /img/, /js/, /css/ and /include/ (MODGUI_SERVER_ROUTES): a file the drawing supplies or replaces, kept as text and never fetched. A path holding a Mustache tag anywhere cannot be checked before mod-ui fills it in, so it is kept; a data: address and a value that is only a Mustache tag are left as they are too. The stylesheet is not checked this way: MOD's shared pedal stylesheets are one theme file covering every knob count and colour a style offers, most of it unused by any one plugin, so most of its url()s name no file the bundle carries, on purpose.

What the validator checks

The shape. That every control id exists in the plugin's description and that a role fits its control is applySkinOverride's, against the description it is applied to.

openmixer

Una taula de mescles de programari per a Linux. La taula és el programari; el navegador n'és la superfície.

Pàgines

Llicència

OpenMixer és programari lliure sota la llicència GPL-3.0-or-later. Tots els paquets del projecte tenen la mateixa llicència.

Roland, Midas, Behringer, RME i els noms de producte que s'hi esmenten són dels seus propietaris respectius. OpenMixer és un projecte independent sense cap vincle amb cap d'ells.