{ "argumentSchema": { "$defs": { "IframeOutputData": { "properties": { "color": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "description": "Color of the notes this user places; `null` selects one from the user." }, "mutedRingIds": { "description": "Identifiers of the rings this user has silenced.", "items": { "type": "string" }, "type": "array" }, "volume": { "description": "Playback volume from 0 to 1.", "type": "number" } }, "required": [ "color", "volume", "mutedRingIds" ], "type": "object" }, "RingLoopsSetup": { "properties": { "rings": { "description": "Rings from the innermost outward.", "items": { "$ref": "#/$defs/RingSpec" }, "type": "array" }, "rootMidi": { "description": "MIDI note number of the lowest lane of an untransposed ring.", "type": "number" }, "scale": { "description": "Semitones each lane sits above the root; its length is the lane count.", "items": { "type": "number" }, "type": "array" }, "title": { "description": "Heading shown above the controls.", "type": "string" } }, "required": [ "title", "rings", "rootMidi", "scale" ], "type": "object" }, "RingSpec": { "properties": { "beats": { "description": "Whole beats the ring's hand takes to complete one turn.", "type": "number" }, "id": { "description": "Stable identifier that placed notes name their ring by.", "type": "string" }, "label": { "description": "Name shown beside the ring's mute control.", "type": "string" }, "transpose": { "description": "Semitones added to the root for this ring's lanes; drums ignore it.", "type": "number" }, "voice": { "$ref": "#/$defs/RingVoice", "description": "Instrument the ring's notes sound on." } }, "required": [ "id", "label", "voice", "beats", "transpose" ], "type": "object" }, "RingVoice": { "enum": [ "drums", "bass", "pluck", "bell" ] } }, "description": "What a piece of Ring Loops is instantiated with.", "properties": { "input": { "$ref": "#/$defs/RingLoopsSetup", "default": { "rings": [ { "beats": 4, "id": "drums", "label": "Drums", "transpose": 0, "voice": "drums" }, { "beats": 5, "id": "bells", "label": "Bells", "transpose": 12, "voice": "bell" }, { "beats": 6, "id": "bass", "label": "Bass", "transpose": -24, "voice": "bass" }, { "beats": 8, "id": "pluck", "label": "Pluck", "transpose": 0, "voice": "pluck" } ], "rootMidi": 57, "scale": [ 0, 3, 5, 7, 10 ], "title": "Ring Loops" }, "description": "The rings and the scale. Left out, four rings in A minor pentatonic." }, "output": { "$ref": "#/$defs/IframeOutputData", "asCell": [ { "kind": "cell", "scope": "user" } ], "default": { "color": null, "mutedRingIds": [], "volume": 0.7 }, "description": "The caller's own color, volume, and muted rings." } }, "type": "object" }, "pattern": "iframe-ring-loops/main.tsx", "resultSchema": { "$defs": { "AddNoteEvent": { "properties": { "agentName": { "description": "Name of the agent placing the notes, shown as their author. It is stored\nwithout control characters and cut to at most 80 characters. Left out, the\nnotes carry the caller's profile name.", "type": "string" }, "color": { "description": "One of the eight note colors, as the hex string `output.color` holds.\nLeft out, a color is picked from the author's name.", "type": "string" }, "lane": { "description": "Lane within the ring, from 0; `rings` lists what each lane plays.", "type": "number" }, "ring": { "description": "Id of the ring, as `rings` lists it.", "type": "string" }, "step": { "description": "Step along the ring, from 0; a step is a sixteenth note.", "type": "number" } }, "required": [ "ring", "step", "lane" ], "type": "object" }, "AddNotesEvent": { "properties": { "agentName": { "description": "Name of the agent placing the notes, shown as their author. It is stored\nwithout control characters and cut to at most 80 characters. Left out, the\nnotes carry the caller's profile name.", "type": "string" }, "color": { "description": "One of the eight note colors, as the hex string `output.color` holds.\nLeft out, a color is picked from the author's name.", "type": "string" }, "notes": { "description": "The cells to place notes in, each by ring id, step, and lane.", "items": { "$ref": "#/$defs/NoteSpec" }, "type": "array" } }, "required": [ "notes" ], "type": "object" }, "ClearNotesEvent": { "properties": { "ring": { "description": "Id of the one ring to clear. Left out, every ring is cleared.", "type": "string" } }, "type": "object" }, "IframeOutputData": { "properties": { "color": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "description": "Color of the notes this user places; `null` selects one from the user." }, "mutedRingIds": { "description": "Identifiers of the rings this user has silenced.", "items": { "type": "string" }, "type": "array" }, "volume": { "description": "Playback volume from 0 to 1.", "type": "number" } }, "required": [ "color", "volume", "mutedRingIds" ], "type": "object" }, "IframeStateData": { "properties": { "notes": { "additionalProperties": { "anyOf": [ { "$ref": "#/$defs/PlacedNote" }, { "type": "null" } ] }, "description": "Notes by cell key; `null` marks a cell whose note was removed.", "properties": {}, "type": "object" }, "tempoBpm": { "description": "Tempo every browser plays at, in beats per minute.", "type": "number" } }, "required": [ "notes", "tempoBpm" ], "type": "object" }, "NoteSpec": { "properties": { "lane": { "description": "Lane within the ring, from 0 at its inner edge; picks what plays.", "type": "number" }, "ring": { "description": "Identifier of the ring, such as `drums`.", "type": "string" }, "step": { "description": "Step along the ring, from 0 at the top; a step is a sixteenth note.", "type": "number" } }, "required": [ "ring", "step", "lane" ], "type": "object" }, "NoteView": { "properties": { "by": { "description": "Name of whoever placed the note.", "type": "string" }, "lane": { "description": "Lane within the ring, from 0 at its inner edge.", "type": "number" }, "plays": { "description": "What the note plays: a drum sound, or a note name such as `A3`.", "type": "string" }, "step": { "description": "Step along the ring, from 0 at the top; a step is a sixteenth note.", "type": "number" } }, "required": [ "step", "lane", "plays", "by" ], "type": "object" }, "PlacedNote": { "properties": { "authorId": { "description": "Who placed the note: the per-user instance for a note placed in the\nbrowser, or the caller's DID for one placed through a verb.", "type": "string" }, "authorName": { "description": "Name its author went by when placing it; absent where none was known.", "type": "string" }, "color": { "description": "CSS color the note is drawn in, as its author chose it.", "type": "string" }, "lane": { "description": "Lane within the ring's band, from 0 at its inner edge; picks the pitch.", "type": "number" }, "ringId": { "description": "Identifier of the ring holding the note.", "type": "string" }, "step": { "description": "Sixteenth-note position along the ring, clockwise from the top.", "type": "number" } }, "required": [ "ringId", "step", "lane", "authorId", "color" ], "type": "object" }, "RemoveNoteEvent": { "properties": { "lane": { "description": "Lane within the ring, from 0.", "type": "number" }, "ring": { "description": "Id of the ring, as `rings` lists it.", "type": "string" }, "step": { "description": "Step along the ring, from 0.", "type": "number" } }, "required": [ "ring", "step", "lane" ], "type": "object" }, "RingView": { "properties": { "id": { "description": "Identifier to name the ring by when adding or removing a note.", "type": "string" }, "label": { "description": "Name the ring is shown under.", "type": "string" }, "lanes": { "description": "What each lane plays, by lane number from 0.", "items": { "type": "string" }, "type": "array" }, "notes": { "description": "Notes on the ring, in the order its hand reaches them.", "items": { "$ref": "#/$defs/NoteView" }, "type": "array" }, "steps": { "description": "Steps in one loop of the ring; valid steps run from 0 to one less.", "type": "number" }, "voice": { "$ref": "#/$defs/RingVoice", "description": "Instrument the ring's notes sound on." } }, "required": [ "id", "label", "voice", "steps", "lanes", "notes" ], "type": "object" }, "RingVoice": { "enum": [ "drums", "bass", "pluck", "bell" ] }, "SetTempoEvent": { "properties": { "bpm": { "description": "Beats per minute, from 40 to 200.", "type": "number" } }, "required": [ "bpm" ], "type": "object" }, "SetVolumeEvent": { "properties": { "volume": { "description": "Playback volume, from 0 for silence to 1 for full.", "type": "number" } }, "required": [ "volume" ], "type": "object" } }, "description": "A loop sequencer several people play at once. Notes sit in cells on\nconcentric rings; each ring loops at its own length, so the rings drift\nagainst each other. Everyone shares the notes and the tempo, and each\nbrowser plays them from its own start. Read `rings` to see what is there,\nthen place and remove notes by ring id, step, and lane.", "properties": { "$NAME": { "type": "string" }, "$UI": { "$ref": "https://commonfabric.org/schemas/vnode.json" }, "addNote": { "$ref": "#/$defs/AddNoteEvent", "asCell": [ "stream" ], "description": "Place one note. A note already in that cell is replaced." }, "addNotes": { "$ref": "#/$defs/AddNotesEvent", "asCell": [ "stream" ], "description": "Place several notes in one call, all by the same author. Nothing is placed\nunless every cell named is valid, and a cell named twice is placed once." }, "clearNotes": { "$ref": "#/$defs/ClearNotesEvent", "asCell": [ "stream" ], "description": "Remove every note, or every note on one ring. This is for everyone." }, "output": { "$ref": "#/$defs/IframeOutputData", "description": "The caller's own note color, playback volume, and muted rings." }, "removeNote": { "$ref": "#/$defs/RemoveNoteEvent", "asCell": [ "stream" ], "description": "Remove the note in one cell." }, "rings": { "description": "Every ring with its loop length in steps, what each of its lanes plays,\nand the notes on it with who placed each. Start here. It is derived from\n`state` when the piece runs: a caller that reads without running the\npiece, as `cf cell get` does without `--step`, sees it as of the last run.", "items": { "$ref": "#/$defs/RingView" }, "type": "array" }, "setTempo": { "$ref": "#/$defs/SetTempoEvent", "asCell": [ "stream" ], "description": "Set the tempo everyone plays at." }, "setVolume": { "$ref": "#/$defs/SetVolumeEvent", "asCell": [ "stream" ], "description": "Set the caller's own playback volume. Nobody else's changes." }, "state": { "$ref": "#/$defs/IframeStateData", "description": "The stored form, current on every read: `tempoBpm`, and the notes by cell\nkey, where `null` marks a removed note. `rings` is the same notes in a\nform that says what each plays." } }, "required": [ "rings", "state", "output", "addNote", "addNotes", "removeNote", "clearNotes", "setTempo", "setVolume", "$NAME", "$UI" ], "type": "object" } }