Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions packages/app/studio/src/ui/devices/DeviceEditor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
*
* The component renders a device header, delegates menu and control creation,
* and wires up drag-and-drop reordering for effect devices.
*
* @packageDocumentation
*/
import css from "./DeviceEditor.sass?inline"
import {Lifecycle, ObservableValue, Procedure, Provider} from "@opendaw/lib-std"
Expand All @@ -21,6 +23,9 @@ import {Colors, Project} from "@opendaw/studio-core"

const className = Html.adoptStyleSheet(css, "DeviceEditor")

/**
* Returns the color used for the editor's header based on device type.
*/
const getColorFor = (type: DeviceType) => {
switch (type) {
case "midi-effect":
Expand All @@ -33,6 +38,7 @@ const getColorFor = (type: DeviceType) => {
}
}

/** Parameters required to construct a {@link DeviceEditor}. */
type Construct = {
lifecycle: Lifecycle
project: Project
Expand All @@ -44,6 +50,9 @@ type Construct = {
icon: IconSymbol
}

/**
* Creates a label element bound to the box's label field.
*/
const defaultLabelFactory = (lifecycle: Lifecycle, labelField: StringField): Provider<JsxValue> =>
() => {
const label: HTMLElement = <h1/>
Expand All @@ -54,6 +63,9 @@ const defaultLabelFactory = (lifecycle: Lifecycle, labelField: StringField): Pro
return label
}

/**
* Renders an editor for the given device box.
*/
export const DeviceEditor =
({lifecycle, project, adapter, populateMenu, populateControls, populateMeter, createLabel, icon}: Construct) => {
const {editing} = project
Expand Down
9 changes: 8 additions & 1 deletion packages/app/studio/src/ui/devices/panel/DevicePanel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
*
* The panel hosts individual device editors, meters and the channel strip
* while supporting scrolling and drag-and-drop reordering of devices.
*
* @packageDocumentation
*/
import css from "./DevicePanel.sass?inline"
import {asDefined, Lifecycle, ObservableValue, Option, Terminable, Terminator, UUID} from "@opendaw/lib-std"
Expand Down Expand Up @@ -34,6 +36,7 @@ import {Project} from "@opendaw/studio-core"

const className = Html.adoptStyleSheet(css, "DevicePanel")

/** Options used to construct a {@link DevicePanel}. */
/** Props for {@link DevicePanel}. */
type Construct = {
lifecycle: Lifecycle
Expand Down Expand Up @@ -77,7 +80,8 @@ export const DevicePanel = ({lifecycle, service}: Construct) => {
scrollModel.contentSize = containers.clientWidth
}

const getContext = (project: Project, box: Box): Context => {
/** Resolves the device host context for the box being edited. */
const getContext = (project: Project, box: Box): Context => {
const deviceHost = project.boxAdapters.adapterFor(box, Devices.isHost)
return asDefined(box.accept<BoxVisitor<Context>>({
visitAudioUnitBox: (_box: AudioUnitBox): Context => ({
Expand Down Expand Up @@ -138,6 +142,9 @@ export const DevicePanel = ({lifecycle, service}: Construct) => {
updateScroller()
}))

/**
* Subscribes to changes in the device chain and manages editor mounts.
*/
const subscribeChain = ({midiEffects, instrument, audioEffects, host}: {
midiEffects: IndexedBoxAdapterCollection<MidiEffectDeviceAdapter, Pointers.MidiEffectHost>,
instrument: ObservableValue<Option<AudioUnitInputAdapter>>,
Expand Down
20 changes: 20 additions & 0 deletions packages/docs/docs-dev/extending/plugin-host.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# Plugin Host

OpenDAW's plugin host allows devices written with the SDK to run inside the
application. It manages the lifecycle of plugins and provides access to the
transport, parameter automation and messaging APIs.

## Capabilities

- Loads WebAssembly or JavaScript based processors
- Connects plugin parameters to the automation system
- Exposes audio and MIDI buffers for real‑time processing

## Host environment

Plugins execute in a sandboxed environment and communicate with the host via
a message channel. The host is responsible for instantiating the processor and
supplying state such as the current tempo or sample rate.

For a walk‑through on creating your own plugin, see the
[plugin guide](./plugin-guide.md).
2 changes: 1 addition & 1 deletion packages/docs/docs-user/features/devices-and-plugins.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ OpenDAW loads plugins built with the project's SDK or other compatible Web Audio
- Traditional desktop formats like VST or Audio Unit may require additional support and are not guaranteed to work.
- Different plugins may expose unique parameters; test them in your environment to confirm full compatibility.

Interested in building your own plugins? Check out the [plugin guide](../../docs-dev/extending/plugin-guide.md) and the [device boxes guide](../../docs-dev/extending/device-boxes.md) in the developer documentation.
Interested in building your own plugins? Check out the [plugin guide](../../docs-dev/extending/plugin-guide.md), the [device boxes guide](../../docs-dev/extending/device-boxes.md), and the [plugin host overview](../../docs-dev/extending/plugin-host.md) in the developer documentation.

For how device controls are connected to automation, see the [parameter adapter guide](../../docs-dev/extending/parameter-adapters.md).

Expand Down
1 change: 1 addition & 0 deletions packages/docs/sidebarsDev.js
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,7 @@ module.exports = {
{ type: "doc", id: "extending/plugin-guide" },
{ type: "doc", id: "extending/plugin-api" },
{ type: "doc", id: "extending/plugin-examples" },
{ type: "doc", id: "extending/plugin-host" },
{ type: "doc", id: "extending/device-boxes" },
{ type: "doc", id: "extending/testing-plugins" },
{ type: "doc", id: "extending/processor-guide" },
Expand Down
5 changes: 5 additions & 0 deletions packages/studio/adapters/src/DeviceBox.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
/**
* Utility types and helper functions for working with device boxes.
*
* @packageDocumentation
*/
import { Pointers } from "@opendaw/studio-enums";
import {
BooleanField,
Expand Down
5 changes: 5 additions & 0 deletions packages/studio/adapters/src/ParameterAdapterSet.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
/**
* Maintains adapters for device parameters and provides lookup utilities.
*
* @packageDocumentation
*/
import {FieldKeys, PointerTypes, PrimitiveField, PrimitiveValues} from "@opendaw/lib-box"
import {assert, NumberArrayComparator, SortedSet, StringMapping, Terminable, unitValue, ValueMapping} from "@opendaw/lib-std"
import {AutomatableParameterFieldAdapter} from "./AutomatableParameterFieldAdapter"
Expand Down
5 changes: 4 additions & 1 deletion packages/studio/boxes/src/device-boxes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,8 @@ export interface DeviceBox {
id: string;
}

/** Collection of registered device boxes. */
/**
* Registry of all available device boxes. Plugins may append to this list
* during initialization to expose new device types to the host.
*/
export const deviceBoxes: DeviceBox[] = [];
28 changes: 28 additions & 0 deletions packages/studio/core-processors/src/DeviceProcessorFactory.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,10 @@
/**
* Factories that construct processor instances for the various device
* categories used by the engine.
*
* @packageDocumentation
*/

import {
ArpeggioDeviceBox,
AudioBusBox,
Expand Down Expand Up @@ -66,6 +73,13 @@ import { UnknownMidiEffectDeviceProcessor } from "./devices/midi-effects/Unknown
* {@link @opendaw/studio-enums#AudioUnitType.Instrument | AudioUnitType.Instrument}.
*/
export namespace InstrumentDeviceProcessorFactory {
/**
* Creates an instrument processor for the provided device box.
*
* @param context - Engine context used to resolve adapters.
* @param box - Box describing the instrument device.
* @returns Processor instance or `undefined` when the box is not supported.
*/
export const create = (
context: EngineContext,
box: Box,
Expand Down Expand Up @@ -110,6 +124,13 @@ export namespace InstrumentDeviceProcessorFactory {
* {@link @opendaw/studio-enums#AudioSendRouting | AudioSendRouting}.
*/
export namespace MidiEffectDeviceProcessorFactory {
/**
* Instantiates a MIDI effect processor for the given box.
*
* @param context - Engine context used to resolve adapters.
* @param box - Box describing the MIDI effect device.
* @returns The created processor.
*/
export const create = (
context: EngineContext,
box: Box,
Expand Down Expand Up @@ -157,6 +178,13 @@ export namespace MidiEffectDeviceProcessorFactory {
* ```
*/
export namespace AudioEffectDeviceProcessorFactory {
/**
* Creates an audio effect processor for the specified device box.
*
* @param context - Engine context used to resolve adapters.
* @param box - Box describing the audio effect.
* @returns The created processor.
*/
export const create = (
context: EngineContext,
box: Box,
Expand Down
18 changes: 12 additions & 6 deletions packages/studio/core/src/EffectFactories.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
/**
* Built-in collection of effect factory definitions.
*
* @packageDocumentation
*/
import {INVERSE_SQRT_2, UUID} from "@opendaw/lib-std"
import {
ArpeggioDeviceBox,
Expand Down Expand Up @@ -192,17 +197,18 @@ export namespace EffectFactories {
})
}
}

/** Mapping of MIDI effect names to their factory definitions. */
/** Mapping of available MIDI effect factories by name. */
export const MidiNamed = {Arpeggio, Pitch, Zeitgeist}
/** Mapping of audio effect names to their factory definitions. */
/** Mapping of available audio effect factories by name. */
export const AudioNamed = {StereoTool, Delay, Reverb, Revamp, Modular}
/** List of all built-in MIDI effect factories. */
/** List of registered MIDI effect factories. */
export const MidiList: ReadonlyArray<Readonly<EffectFactory>> = Object.values(MidiNamed)
/** List of all built-in audio effect factories. */
/** List of registered audio effect factories. */
export const AudioList: ReadonlyArray<Readonly<EffectFactory>> = Object.values(AudioNamed)
/** Combined lookup of MIDI and audio effect factories. */
/** Combined mapping of all effect factories. */
export const MergedNamed = {...MidiNamed, ...AudioNamed}
/** Keys of the {@link MidiNamed} mapping. */
export type MidiEffectKeys = keyof typeof MidiNamed
/** Keys of the {@link AudioNamed} mapping. */
export type AudioEffectKeys = keyof typeof AudioNamed
}
5 changes: 5 additions & 0 deletions packages/studio/core/src/EffectFactory.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
/**
* Interface definition for effect factories used to construct effect boxes.
*
* @packageDocumentation
*/
import {EffectPointerType, IconSymbol} from "@opendaw/studio-adapters"
import {Field} from "@opendaw/lib-box"
import {int} from "@opendaw/lib-std"
Expand Down
6 changes: 6 additions & 0 deletions packages/studio/core/src/InstrumentFactories.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
/**
* Built-in instrument factory descriptors.
*
* @packageDocumentation
*/

import {
AudioFileBox,
NanoDeviceBox,
Expand Down
7 changes: 7 additions & 0 deletions packages/studio/sdk/src/device-api.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,10 @@
/**
* High level abstraction for interacting with connected audio and MIDI
* hardware.
*
* @packageDocumentation
*/

/**
* Interacts with input and output devices such as audio interfaces or MIDI
* controllers.
Expand Down