Skip to content
Back to skills

Ableton Link

ASecurity

Configure, implement, and test Pulp's optional desktop Ableton Link tempo-sync adapter while preserving the developer-supplied SDK, licensing, realtime, latency-compensation, and no-install boundaries.

  • 22 stars
  • 0 votes
  • 0 copies
  • 1 view
  • Added September 3, 2026
developmentc++bashgitapibackend

Works with

  • api

Security analysis

A100/100

Pro scans all 2 files and shows the line behind each finding

Scanned September 30, 2026

npx -y skills add danielraffel/pulp --skill ableton-link --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Ableton Link?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Ableton Link
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/danielraffel-ableton-link/badge)](https://www.skillsdirectory.com/skills/danielraffel-ableton-link)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: ableton-link
description: Configure, implement, and test Pulp's optional desktop Ableton Link tempo-sync adapter while preserving the developer-supplied SDK, licensing, realtime, latency-compensation, and no-install boundaries.
---

# Ableton Link

Use this skill for Pulp's desktop `Ableton/link` integration, its CMake opt-in,
or the backend-neutral tempo-sync seam in `core/playback`.

## Scope and licensing boundary

- This is the desktop C++ `Ableton/link` SDK. It is not iOS LinkKit and not
  `m4l-connection-kit`. LinkKit needs a separate licensing decision, option,
  SDK path, and implementation.
- Link is available under GPLv2+ or a proprietary arrangement with Ableton.
  Pulp's MIT license grants no Link rights. The developer enabling the adapter
  is responsible for having suitable rights.
- Pulp never fetches, bundles, installs, exports, or redistributes Link. Keep
  the SDK outside the Pulp source tree. Do not add it to `DEPENDENCIES.md` or
  `NOTICE.md` because Pulp ships none of it.
- The portable `pulp::playback` target owns only Pulp code. The optional
  `pulp::ableton-link` target exists only in a source build with the SDK enabled
  and must never enter `cmake --install` or Pulp's exported target closure. Its
  adapter declaration lives under `core/playback/adapters/include`, exposed
  only through that target's `BUILD_INTERFACE`; do not place it under the
  installed `core/playback/include` tree.

## Obtain and enable the desktop SDK

Clone recursively to an absolute path outside the checkout; Link requires its
ASIO submodule even on platforms that do not use an ASIO audio device:

```bash
git clone --recurse-submodules https://github.com/Ableton/link.git /absolute/path/to/link

cmake -S . -B build-link -DCMAKE_BUILD_TYPE=Release \
  -DPULP_ENABLE_ABLETON_LINK=ON \
  -DPULP_ABLETON_LINK_SDK_DIR=/absolute/path/to/link
```

`PULP_ENABLE_ABLETON_LINK` defaults to `OFF`. When enabled, a missing, partial,
in-tree, or non-desktop SDK path is a configure error. The SDK path can also
come from the `PULP_ABLETON_LINK_SDK_DIR` environment variable, but an explicit
CMake cache value is easier to audit.

## Runtime contract

- `TempoSyncSource` is Pulp's backend-neutral, audio-thread interface. Keep
  Link types and Link-specific peer/enable/start-stop controls out of it.
- `AbletonLinkTempoSync` owns those Link-specific controls. Call `set_enabled`
  and `set_start_stop_sync_enabled` from a control thread, never from the audio
  callback. `output_host_time` and `capture_audio_block` are realtime-safe.
- Call `output_host_time(output_latency_frames, sample_rate, time)` in the audio
  callback, then pass its opaque `TempoSyncHostTime` to `MasterTransport`. The
  adapter reads Link's realtime clock and adds device/output latency so the
  timestamp names the first sample at the output boundary. A callback timestamp
  without compensation produces a stable audible offset.
- `TempoSyncHostTime` is tagged with its producing source. A transport rejects
  a default token or one from another source before asking its backend to
  capture a block, preventing Link, device, and wall-clock epochs from mixing.
- The public desktop adapter models APIs that report output latency from the
  callback. It does not accept an arbitrary device-host timestamp. A platform
  integration whose audio API exposes a calibrated future device timestamp
  needs an explicit Link-clock conversion boundary; do not forward that raw
  timestamp or a jittery wall-clock read as though it were Link time.
- A configured `TempoSyncSource` must outlive `MasterTransport`. Use the
  host-time `begin_block(frame_count, output_host_time, snapshot)`
  overload. The ordinary overload returns `TempoSyncHostTimeRequired`.
- The session mapping is authoritative. Disabled, failed, or invalid sources
  fail the block; they never fall back to the document tempo clock.
- Joining does not send the config's initial tempo, position, or play state.
  Only explicit `set_tempo_sync_tempo`, `seek`, and `set_playing` calls publish
  session commands, which avoids hijacking an existing jam on attach.
- A Link-projected block retains Pulp's fixed one-or-two-range transport
  contract and precise fractional host ticks. `begin_scrub()` rejects an active
  shared tempo source because scrubbing needs a private repositioning clock;
  use an unsynchronized transport for scrub playback.
- Preserve `SessionState::timeForIsPlaying()` in
  `TempoSyncBlockState::is_playing_at_host_time_micros`. A
  `TransportSnapshot` has one playing state for its whole half-open block: a
  start/stop effective at or before the first sample applies immediately, while
  one inside or at/after the block end is deterministically deferred until a
  later block starts at or beyond that timestamp. Do not flatten the timestamp
  into `SessionState::isPlaying()` or claim sample-accurate start/stop splitting
  that the snapshot contract cannot represent.

## Verification

The SDK-independent interface tests are the public-CI gate. They compile into
the grouped `pulp-test-group-timeline-playback` executable, so build that
target and select the suite by its file tag. The SDK-present
test is always registered: a stock build exits 77 and CTest reports `Skipped`
with the enablement flags, while an enabled local build executes the real
adapter.

```bash
cmake --build build --target \
  pulp-test-group-timeline-playback \
  pulp-test-ableton-link-sdk \
  timeline-program-threadless-no-exceptions-check

build/test/pulp-test-group-timeline-playback -# "[#test_playback_tempo_sync]" \
  --reporter compact
ctest --test-dir build -V -R '^playback-ableton-link-sdk-present$'

cmake --build build-link --target \
  pulp-test-group-timeline-playback pulp-test-ableton-link-sdk
ctest --test-dir build-link -V -R '^playback-ableton-link-sdk-present$'
```

Check the interface assertion count; a filtered CTest command can match
nothing. For substantive changes, prove negative controls for fail-closed
source errors and precise beat projection, then restore the implementation.

When the portable interface or transport integration changes, also update the
`playback` skill and keep `tempo_sync.cpp` in the native, threadless, WAM, and
WebCLAP playback source closure. Keep the SDK adapter under
`core/playback/adapters/`, outside the portable `src/` closure.

Files in this skill

  • SKILL.md6 KB
  • agents/openai.yaml196 B

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…