DSL Inspector

The DSL Inspector is a built-in browser-side authoring tool that lets you add, edit, and remove cue behaviour directly in the running score — without leaving the browser or editing SVG files by hand. Changes are written back to score.svg immediately.

It is the recommended way to author cues during the composition and testing phase.


Enabling the Inspector

Click the pencil icon (✏) in the top bar to toggle the inspector on and off.

When active:

Closing the editor panel (×, Cancel) also switches inspector mode off — the topbar icon unhighlights and normal score interaction resumes. Creating an object with the + tool switches it on.


Inspecting Elements

With the inspector on, hover over any SVG element to see its cue definition in a tooltip:

data-oscilla="rotate(dur:2, uid:myShape, trig:auto)"

Elements with no cue show no tooltip. Elements with cues show the full DSL string.


Editing an Existing Cue

Click any element that has a cue to open the editor panel on the right side of the screen.

A group is a region: clicking anywhere inside a group's bounding box — between its members, on empty space — targets the group itself, the innermost one when groups nest, with its ancestors offered in the target breadcrumb. An element you actually click still wins over any group whose box happens to overlap it. Layers, and any group whose box covers the whole view (a page-colour rect inside a title group makes that group's box the entire score), never count as click regions; reach those through a member or the breadcrumb.

The panel shows one cue block for each cue on the element (most elements have one). Each block contains:

If an element's DSL fails to parse (a typo, an unbalanced paren), the panel still opens — the broken expression appears as an ⚠ unparsed DSL block: a raw text editor with live parse feedback, saved back verbatim. Nothing is lost, and once fixed it reopens as normal fields.

The live preview at the bottom of the panel shows the serialized DSL as you type — it updates with every keystroke.

Click Save to SVG to write the change to score.svg. The change takes effect immediately in the browser (the animation restarts) without a full page reload.


Adding a Cue to a Plain Element

Click any SVG element that does not already have a cue (it must have an id attribute). The panel opens in Add Cue mode:

  1. Type in the search box to filter cue types
  2. Click a cue type to open its parameter form
  3. Fill in the required parameters
  4. Click Save to SVG

The element's id is used as the cue's uid. The cue is stored in a data-oscilla attribute (not in the id itself), so the element keeps its original identifier.

New audio cues default to trig:playhead. Primary-source fields — src (audio), path (audioPool / audioImpulse), file (video) — are always visible in the form, even while empty, so they can't disappear from a saved cue that lacks them.


Favourites — your own presets

Any cue you have tuned can be kept as a favourite: press ☆ favourite in its block header, give it a name, Enter. From then on + Add cue offers it as a chip above the cue-type list, on any element in any project; one click applies it exactly as picking a cue type does (a uid is assigned from the element, and a propagate() favourite gets fresh member uids each time). × on a chip forgets it.

Favourites live in a plain text file beside your projects, ~/oscilla-projects/dsl-favourites.txt (wherever your projects folder is), one per line:

# Oscilla favourite cues — one per line, "name: dsl"
breathe: propagate(scale(values:[1,${1}], dur:${2}, mode:alternate, trig:playhead, uid:br), rnd(0.6, 1.6), rnd(0.8, 2.5))
fade in: fade(from:0, to:1, dur:4, trig:playhead)
pause(dur:4, count:true)

Edit it by hand as freely as with the button: the name is everything before the first colon, the DSL everything after; a line with no name is named after its cue; # starts a comment. Saving a favourite under an existing name replaces that line. A project can also carry its own dsl-favourites.txt, which the picker shows alongside (read-only from the GUI) — handy for the cues a particular piece is built from.


Creating Score Objects — the "+" Tool

The + button in the top bar (next to the inspector icon) creates new SVG elements directly on the score — no Inkscape round-trip needed for a quick trigger box or label.

  1. Click + — the button highlights and the cursor becomes a crosshair (press Esc or click + again to cancel)
  2. Click anywhere on the score — it doesn't matter what's under the click: background images, page rects, and empty canvas all work
  3. The Create Element panel opens with the click point pre-filled:
    • rect / ellipse: x, y, width, height (default 10×10) and a fill color
    • text: the text content, font family, font size, and color
    • rehearsal / notes: a mark letter or note text — score furniture, not cues
    • mic: an audio input source, drawn as a small microphone (see below)
  4. Click Create

The element appears immediately, is appended to score.svg, and draws above all existing layers. It gets a unique plain id (rect-k3j9ab1-style), and the panel drops straight into Add Cue mode so you can attach behaviour right away. Creating also switches the inspector on, so the new object stays clickable for further editing.

The placement point is clamped into the score's viewBox, so a click outside the rendered band still produces a visible element.

The mic object

mic is not a shape — it is an adc() cue with a drawing, so placing one gives the score an ear. It writes an element whose id is the cue:

adc(uid:adc)

The fields are that cue's parameters:

Field What it does
uid the name the rest of the score binds to — follow(adc.amp, …)
channel mix (mono, or both channels summed), left, or right
size height in score units; the drawing scales to it
colour the microphone's colour
hidden still listens, but is not drawn

Because it is a real element rather than an invisible system source, it appears in the connections view as an object with its ten outlets, and cords run from it like any other. A hidden mic still has a position and a size, so it still has somewhere to anchor those cords — which is why hiding uses visibility, not display:none.

For a stereo pair, place two: one ch: left with uid left, one ch: right with uid right. They share a single microphone permission prompt between them.

Inkscape warning: the element is written to score.svg on disk. If the score is open in Inkscape at the time, do File → Revert there before saving from Inkscape, or its next save will overwrite the new element.


Editing Object Geometry & Appearance

Clicking a rect, ellipse, circle, text, line, or image element (with a plain id) shows an Object section at the bottom of the editor panel — in both the cue editor and Add Cue modes. It edits the element itself, independent of its cues:

Changes apply live as you type. Click Apply object to SVG to persist them — the element's attributes are patched in place in score.svg, leaving its data-oscilla and everything else untouched. The same Inkscape File → Revert caveat applies.


Composite Cues — Multiple Cues per Element

An element can carry more than one cue. For example: an audio trigger that also behaves as a draggable panel, or a shape that both fades and sends an OSC message.

To add a second cue to an element that already has one:

  1. Click the element to open its editor
  2. Click + Add cue (visible below the cue blocks, always in view)
  3. Search for and select the new cue type
  4. The new cue is placed in a wrapper <g> element that Oscilla creates automatically around the original element in score.svg

Each cue lives on its own element so that transform operations (scale, rotate, o2p) do not conflict with each other. The panel shows all ancestor cues together, labelled with the element they live on:

rotate()  ·  myShape-rotate-a3f1      ← lives on the wrapper <g>
scale()                                ← lives on the original element

When you click Save to SVG, each cue is written to its correct element.


Cue Types

The page cue is edited as its pattern (intro, or Pseq([pageA:5, pageB:5], 1) …) plus an optional after action, with the pattern written first and bare, the way the parser expects it.

The inspector supports all standard cue types. Use the Add Cue search to see the full list:

Category Cues
Animation rotate, scale, fade, color, o2p
Audio audio, audioPool, audioImpulse
Media video, synth, osc, midi, metro
Text & nav text, nav, page, ui, ext
Transport pause, speed, stopwatch, pin
Interaction drag, button
Marks draw

The audio-family schemas match the session-layer audio object editor: speed, pan, and amp accept rand() / birand() / pattern expressions, and filter / delay / reverb take object literals — see audio shared features.

The speed cue exposes both of its runtime forms (value, uid, loop, dur, add, revtrig) and the editor writes the right one automatically: setting dur or add saves the keyed trigger/ramp form, otherwise the positional marker form the position watcher expects — see speed(). Saving rebuilds the speed watcher map immediately, so marker edits apply without a reload.


Audio & Video File Upload

The audio cue's src field and the video cue's file field each have a Browse… button. Clicking it opens a file picker; the selected file is uploaded to the project's audio/ or video/ folder and the filename is filled in automatically (WAV uploads are transcoded to FLAC when ffmpeg is available).

If a file with the same name already exists in the project, no duplicate is made — the field is pointed at the existing project file.

Supported formats — audio: .flac, .wav, .ogg, .mp3, .aif · video: .mp4, .webm, .ogg, .mov, .m4v


Removing Cues


Freeze Animations

The snowflake icon (❄) in the top bar freezes all running animations in place. This makes it easy to click on animated elements that would otherwise be moving. Click again to unfreeze and restart all animations.


A freeze is a state, not a snapshot: an animation that starts while the freeze is on — a page opening with a trig:auto cue, the playhead reaching a cluster — is held with the rest and released with them.

Fader Preset Panel

The fader icon in the top bar opens the Fader Presets panel. This lets you place pre-built o2p fader groups (horizontal or vertical, in counts of 1–24) directly into the score by clicking a placement point.

Placed faders are inserted into score.svg and visible immediately. Reload the score to activate their o2p cues.


Extent Handle

Audio-family cues (audio, audioPool, audioImpulse, synth) can extend their active trigger region past the element with the extent parameter — see extent.

While inspector mode is on, the extent line's end bar in the score is draggable directly — resizing applies live and persists to score.svg on release, without opening the editor panel. Dragging it back to the element's right edge clears the extent (plain bounding-box mode).

With the editor panel open, a grip above the element does the same, and the extent (score units) field can be typed; Save to SVG persists it. The line itself is saved into score.svg as a real element, so the region marking survives outside the app (Inkscape, exports, print).


Page Buttons

The button cue's trigger field holds a whole cue — the one the button fires. Beside it an open page… dropdown lists the project's pages; picking one writes page(<name>) into the field, so a shape that opens a page is one click: add button, choose the page, save. The chips under the field give the other common triggers — nav(scroll) and nav(scrollPaused@A) to come back to the score, pause(4), audio(src:…).

mode defaults to overlay, which keeps the shape you drew and lays an invisible hit area over it. Clear it to get an HTML button in place of the shape, styled by the style(…) field. See button().


Path Pick Mode

The o2p cue's path parameter has a pick button. When active, the next SVG element you click has its id inserted into the path field. This avoids having to type element ids by hand.


Waypoint Pick Mode

The trans cue's to field has a click score button. Arm it and every click on the score appends a waypoint to the list — [x, y] in the edited element's own coordinates, the same frame trans() measures against, so a click lands the element's centre exactly where you pointed. Shift+click appends the clicked element's id instead of coordinates. Each pick drops a numbered marker on the score so the route is visible while you work; the markers are view-only and vanish when the panel closes. Press Esc or the button (now reading done) to finish; the list stays editable by hand.

Coordinate Readout

While the inspector is active, a small chip in the bottom corner shows the score coordinates under the mouse (SVG user units — the same units used for [x, y] waypoints in trans(to:…) and for object geometry):

x 4700 · y 100     click = copy · alt+click score = insert

The readout tracks zoom and scroll, so what you see is always the authored coordinate you would type.


How Changes Are Saved

The inspector writes directly to score.svg on disk via the server API. There is no separate save step — Save to SVG is the save.

The file watcher is suppressed for 10 seconds after each save so the page does not auto-reload. Animations restart immediately using the new parameters, and saved cues are (re)registered with the playhead trigger system live — a newly added trig:playhead cue arms without a reload.

If you are working in local folder mode (File System Access API), changes are written to the locally-opened score.svg instead of the server. A project that exists on the server (in the projects folder) always loads from the server — a remembered local folder with the same name is released automatically, so edits made in Inkscape to the served copy are never shadowed by a stale duplicate elsewhere.


In page mode the edits go to the page's own file, pages/<id>.svg, not to score.svg: the editor names the file with every write, and the server refuses any name that is not a page or score file of the project.

Keyboard and Interaction Notes

Tip: use ← → or ↑ ↓ to navigate the docs