Use core capabilities

Call typed media, keyboard, pointer and app operations.

A capability is a versioned service. A generated client turns its method/type schema into normal language calls. Permissions and compatible version declarations are part of the manifest, not optional comments in source.

Available contracts

The authoritative contracts are under capabilities/schemas. Generated clients are under capabilities/generated; Python clients also ship in its SDK package.

CapabilityOperations
core.mediaPlayback, track details, volume and mute
core.keyboardKeyboard operations
core.pointerPointer operations
core.appsApplication catalog and launching

Read each schema for exact method names, payload types and permission IDs. Supported behavior depends on the user's OS and helper version. A successful command does not guarantee that a player supports every operation.

Go media example

import (
    "context"
    media "github.com/codewhen/air_deck_plugin_sdk/capabilities/generated/go/media"
    "github.com/codewhen/air_deck_plugin_sdk/deck-plugins/sdk/go/decksdk"
)

type plugin struct { media *media.Client }
func (p *plugin) Init(host *decksdk.Host) {
    p.media = media.NewClient(host)
}
// Inside Invoke, return the error from the operation:
// _, err := p.media.TogglePlayback(context.Background(), media.Empty{})

Declare core.media.playback.control in permissions and the core.media compatible version in uses. Add read permissions only when reading playback, track or volume state.

Python media example

from airdeck_sdk.core.media import Client, Empty

def init(self, host):
    self.media = Client(host)

# Inside invoke:
# self.media.toggle_playback(Empty())

In Java, generated clients are in com.airdeck.capabilities; pass PluginHost as transport. In C++, include the generated capability header and instantiate its client with the host transport. Both complete SDK transport examples are exercised by the public cross-language integration tests.

Subscriptions and permissions

Use the generated subscribe methods for updates rather than polling continuously. Store the returned unsubscribe function and release it when the consumer no longer needs updates. Handle denied permissions and unavailable services visibly; do not silently fall back to unintended OS input.

If a capability schema changes, regenerate with:

python3 capabilities/tools/generate.py

Private helper integration assets are not required for community plugin development.

A complete integration sequence

  1. Read the capability schema and choose the exact methods/topics you need.
  2. Add only their required permission IDs to the plugin manifest.
  3. Declare the capability's compatible version range in uses.
  4. Construct a generated client from the host during initialization.
  5. Call the method from an action handler, preserve any failure and handle unavailable services.
  6. If subscribing, retain and eventually call the unsubscribe function.
  7. Rebuild, approve the changed permissions in the helper and test the real action.

Permission ownership

A permission ID belongs to a capability namespace. A provider's permission namespace must be under its plugin ID. A consumer requests those IDs; a provider exposing its own method does not need to request its consumer permission merely to register the provider.

Schemas can define groups of permission IDs. Follow the helper's supported permission expansion/approval behavior rather than inventing a new group name. Review the leaf permissions needed by each operation.

Exact request/result types

Schema object types are closed and declare required properties. Send all required fields and reject unexpected fields in your own contract. Generated types help you match that shape, but they do not remove semantic validation such as whether an application target or keyboard key is actually supported.

Read Media, Keyboard, Pointer and Applications for method/topic/type tables and example payload shapes.

Commands versus observed state

A command request asks for an operation. A state read/topic reports what the helper can observe. Sending pause does not mean every player exposes reliable paused metadata immediately. Check availability and handle unknown state explicitly.

Use subscriptions when state must stay current. Avoid spinning high-frequency timers in every consumer; the helper owns core refresh and broker delivery policy.

Edit this page on GitHub ↗Community-maintained · API v2