Skip to content

Binding Adapter

BindingAdapter defines the runtime-facing contract implemented by host bindings.

It is the boundary where a concrete runtime projects transport operations, snapshots, queue state, capabilities, and event streams into a shared contract surface.

interface BindingAdapter {
setup(): Promise<void>;
add(options: AddOptions): Promise<PlaybackSnapshot>;
remove(options: RemoveOptions): Promise<PlaybackSnapshot>;
reset(): Promise<PlaybackSnapshot>;
play(): Promise<void>;
pause(): Promise<void>;
stop(): Promise<void>;
seekTo(options: SeekToOptions): Promise<void>;
skipTo(options: SkipToOptions): Promise<PlaybackSnapshot>;
skipToNext(): Promise<void>;
skipToPrevious(): Promise<void>;
getState(): Promise<PlaybackState>;
getPosition(): Promise<number>;
getDuration(): Promise<number | null>;
getCurrentTrack(): Promise<Track | null>;
getQueue(): Promise<QueueSnapshot>;
getSnapshot(): Promise<PlaybackSnapshot>;
getCapabilities(): Promise<BindingCapabilitiesSnapshot>;
addListener<E extends LegatoEventName>(
eventName: E,
listener: (payload: LegatoEventPayloadMap[E]) => void,
): Promise<BindingListenerHandle>;
removeAllListeners(): Promise<void>;
}

BindingAdapter is a boundary contract, not an application service API. Its purpose is to normalize runtime behavior into stable types that higher layers can consume without depending on platform-specific SDKs.

In practice, adapter implementations sit between:

  • runtime/player integrations that perform real playback work,
  • and consumer code that expects contract-first shapes (PlaybackSnapshot, event payload maps, capability literals).
  • setup() initializes adapter runtime integration.
  • add(options), remove(options), reset(), and skipTo(options) return PlaybackSnapshot.
  • These methods are queue/topology-affecting commands where returning a snapshot allows callers to consume an updated projection immediately.
  • play(), pause(), stop(), seekTo(options), skipToNext(), and skipToPrevious() return Promise<void>.
  • Void return means the contract does not require these methods to return an updated snapshot directly.
  • getState(), getPosition(), getDuration(), getCurrentTrack(), getQueue(), getSnapshot(), and getCapabilities() expose current projections as typed reads.
  • addListener(eventName, listener) registers a typed listener and returns BindingListenerHandle.
  • BindingListenerHandle.remove() is the per-listener detach path.
  • removeAllListeners() clears listener registrations at adapter scope.
  • BindingListenerHandle: listener registration handle with remove(): Promise<void> | void.
  • BindingCapabilitiesSnapshot: { supported: Capability[] } runtime capability snapshot.
  • BindingAdapterError: LegatoError plus optional source?: string metadata.
  • AddOptions: { tracks: Track[]; startIndex?: number }.
  • RemoveOptions: { id?: string; index?: number }.
  • SeekToOptions: { position: number }.
  • SkipToOptions: { index: number }.

What is defined by this contract:

  • method names, parameter shapes, and return types,
  • event-name and payload coupling through LegatoEventName + LegatoEventPayloadMap,
  • capability snapshot shape ({ supported: Capability[] }).

What is not defined here:

  • retry strategy,
  • command/event ordering guarantees,
  • timeout, cancellation, or backpressure policy,
  • listener delivery scheduling details.

Those concerns belong to concrete adapter/runtime implementations and higher-level orchestration policy.

  • Treating Promise<void> operations as if they must return immediate snapshot truth.
  • Inferring capability support from queue state alone instead of getCapabilities().
  • Encoding platform-specific behavior into shared contract types.
  • Assuming listener registration implies any particular event sequencing semantics.

BindingAdapter is the transport boundary between runtime implementations and contract consumers. Adapters project state, queue, events, capabilities, and operation results through this interface.