Skip to Content
Docs

The Library

How an app adds sounds, MIDI and other files to the person's Library, and how a page reads it.

View as Markdown

The Library is where a musician keeps their sounds, on their own computer. Mixel stores each item's file in its own folder and remembers which app made it. An app can add to the Library. With a separate permission the person allows, its page can also show the sounds already there, so they can pick one. It can't change or remove anything.

Add from an action

Return what you made. Each ox.sound, ox.midi or ox.file is copied into the Library when the action finishes, or when the person presses Stop:

app.py
import numpy as np

import ox1audio as ox


@ox.action("Make a click track")
def click(bpm: ox.Slider(60, 200, 1, label="Tempo (BPM)") = 120, bars: ox.Number(1, 64, 1) = 4):
    rate = 44100
    beat = int(rate * 60 / bpm)
    samples = np.zeros((beat * 4 * bars, 1), dtype=np.float32)
    tick = np.sin(np.linspace(0, 2 * np.pi * 40, rate // 50, dtype=np.float32)) * 0.5
    for start in range(0, len(samples), beat):
        samples[start : start + len(tick), 0] += tick[: len(samples) - start]
    out = ox.audio.write(samples, rate, "wav", name=f"Click {bpm} BPM")
    return ox.sound(out, title=f"Click {bpm} BPM", bpm=bpm)
KindUse it for
ox.sound(path, title, **metadata)Audio
ox.midi(path, title, **metadata)MIDI files
ox.file(path, title, **metadata)Anything else, like a text file of lyrics

Metadata goes after the title. Mixel keeps bpm, key, duration, rate and channels as columns the person can sort and filter by. The length of a sound is measured for you.

The item shows which app made it, and the badge stays after the app is uninstalled. This needs the library permission; mixel check --fix adds it when your code returns sounds.

If an action needs to add something before it returns, use ox.library.add(kind, path, title, **metadata), where kind is "sound", "midi" or "other".

Read from a page

A page can list the Library, so the person can pick a sound they already have. This is its own permission, library-read, apart from adding: ask for it in app.json with a sentence that says why, and it stays off until the person allows it.

"permissions": {
  "files": "Open the recording you choose and save the dry copy next to it.",
  "library": "Add the dry copy to your Library.",
  "library-read": "Show the recordings in your Library, so you can choose one to dry."
}
import { ox } from "@ox1audio/sdk/page"

const sounds = await ox.library.list({ kind: "sound" })
const path = await ox.library.file(sounds[0].id)
const stop = ox.library.onChange(() => refresh())

Each item has id, kind, title, filename, duration, bpm, musicalKey, appName and created. There are no paths in the list, and nothing about where the person keeps their files. ox.library.add(paths) needs only library. It adds sounds and MIDI the person chose for your app (picked, dropped, or inside a folder they chose), results your actions saved, and files in your app's own data. A file that merely sits in the same folder as a chosen one is refused. If the Library already has the same audio as someone else's sound, you get back only { imported: "already" } for it, with no id or name.

ox.library.file(id) gives you a path your actions can open. It needs library-read and files, and Mixel hands over one sound at a time:

  • A sound your app added is yours to open, with no question asked.
  • For any other sound, Mixel asks the person first, naming every sound, so call it only for what they chose in your page. One question covers at most 20 sounds; calls past that fail. If they say no, the call throws.
  • Mixel asks for library-read the first time your page uses it, not when the app opens. If the person says no, the rest of your app keeps working, so show the Library as unavailable rather than failing.
  • The sound's url plays once the person has picked it, or straight away when your app added it.

library-read needs Mixel 0.1.23 and mixel 0.3.5 or later; an older mixel check reports it as permission_unknown.

An app with library alone can't list the Library or open a sound it didn't make.

The drawn form has a From Library button on every ox.Files control. It follows the same rule: it lists the Library only for an app that asks for library-read.

On this page