App Model
Host side of uapmd_app::AppModel (tools/uapmd-app-model) — the façade uapmd-app itself renders against, wrapped by c-api/uapmd-c-app.h.
It is a process-wide singleton: call instantiateAppModel once, before any UI exists, then reach it with getAppModel. It owns its RealtimeSequencer, so the instance returned by sequencer must not be closed.
A host must install an event loop (see uapmd_set_event_loop, which the JVM/Android bindings do via initJvmEventLoop() / initAndroidEventLoop()) before instantiating: AppModel marshals plugin deactivation and history completions through remidy::EventLoop, and without one they never run.
Inheritors
Properties
AppModel's own blocklist — the list the Plugin Selector shows. A standalone ScanTool keeps a separate one. BlocklistEntry.timestamp in uapmd has no counterpart in uapmd_blocklist_entry_t, so it is not carried across.
Also reports busy while an asynchronous plug-in mutation is still capturing state, so shortcuts cannot race the capture.
Turning this off is not a plain stopAudio(): the model stops the transport, mutes the output, lets release/reverb tails drain inaudibly, then deactivates plugins on the main thread and resets processing state, so a restart cannot resume stale voices.
The last scanning error, or null.
Owned by the model; do not close.
Progress of the slow scan. isScanning alone cannot tell a long scan from a stuck one, which is why uapmd-app's selector shows these.
Functions
Creates an empty MIDI 2.0 clip; tickResolution is ticks per quarter.
Instantiates pluginId and attaches it to trackIndex; a negative index creates a new track. The callback runs once, on the thread that finishes instantiation.
Registers the instance as a virtual MIDI 2.0 device where the platform supports it.
Switches the track from the simple linear chain to the editable graph.
Reading counterpart to ProjectCommands.setClipMarkers/setClipAudioWarps.
Android's document-picker path: resolves a content:// handle token.
Startup lifecycle; uapmd-app calls both once the UI exists.
Runs asynchronously; watch isScanning. ScanMode.Remote launches a separate scanner process on desktop and is unavailable on WebAssembly.
Master-track tempo map. getTimelineState().tempo is a single value and cannot describe a project whose tempo changes; a beats view needs these. Rebuild once with refreshMasterTempoMap, then read the lists — they stay valid until the next refresh.