Skip to content

Conversation

@elzinko
Copy link

@elzinko elzinko commented Nov 18, 2025

Device Variations API Support for Live 12

Adds comprehensive OSC control for Device Variations (Macro Variations) in Ableton Live 12, enabling remote control of rack variation states and parameters.

What's Added

Core API

Properties (read/write):

  • /live/device/get/variations/variation_count - Number of available variations
  • /live/device/get/variations/selected_variation_index - Get/set active variation (-1 = none)
  • /live/device/set/variations/selected_variation_index

Methods:

  • /live/device/variations/recall_selected_variation - Apply the selected variation
  • /live/device/variations/recall_last_used_variation - Recall last used variation
  • /live/device/variations/store_variation - Store current macro state as new variation
  • /live/device/variations/delete_selected_variation - Delete selected variation
  • /live/device/variations/randomize_macros - Randomize all macro values

Listeners:

  • /live/device/start_listen/variations/variation_count
  • /live/device/start_listen/variations/selected_variation_index
  • (and corresponding stop_listen endpoints)

Developer Tools

Introspection API:

  • /live/introspect - OSC endpoint to discover properties/methods on any Live object
  • tools/introspect.py - CLI tool with formatted output and highlighting
./tools/introspect.py device 0 0
./tools/introspect.py device 0 0 --highlight variation

API Design

All endpoint names match the exact Live API property/method names (e.g., variation_count, selected_variation_index) for consistency and discoverability.

Testing

Automated Tests:

All tests include auto-setup functionality:

  • If a RackDevice exists but has no variations, tests automatically create 2 variations
  • Tests clean up auto-created variations after completion
  • Tests skip gracefully if no RackDevice found
pytest tests/test_device.py -v

Requirements:

  • Ableton Live 12+ (variations introduced in Live 12)
  • A RackDevice on track 0 (Instrument Rack, Audio Effect Rack, etc.)
  • Variations are auto-created if needed

Usage Examples

Via Python Client

from client.client import AbletonOSCClient

client = AbletonOSCClient()

# Get variation count
count = client.query("/live/device/get/variations/variation_count", (0, 0))

# Select and recall a variation
client.send_message("/live/device/set/variations/selected_variation_index", (0, 0, 1))
client.send_message("/live/device/variations/recall_selected_variation", (0, 0))

# Store new variation
client.send_message("/live/device/variations/store_variation", (0, 0))

Via Interactive Console

./run-console.py
>>> /live/device/get/variations/variation_count 0 0
(0, 0, 4)
>>> /live/device/set/variations/selected_variation_index 0 0 1
>>> /live/device/variations/recall_selected_variation 0 0

Via Introspection

./tools/introspect.py device 0 0 --highlight variation

Compatibility

Requirements:

  • Ableton Live 12+
  • Only works with RackDevice objects (Instrument Rack, Audio Effect Rack, MIDI Effect Rack, Drum Rack)

Graceful Degradation:

  • Returns appropriate errors on non-RackDevice types
  • Tests auto-skip if no suitable RackDevice available
  • Works alongside existing Live 11 functionality

elzinko and others added 7 commits November 18, 2025 18:48
Implements comprehensive support for Ableton Live 12 Device Variations
(Macro Variations) feature in AbletonOSC, enabling OSC control of rack
variation states and parameters.

## Features Added

### Device API Extensions (abletonosc/device.py)
- Properties (read-only): variation_count, can_have_chains, chains,
  has_macro_mappings, macros_mapped, visible_macro_count
- Properties (read/write): selected_variation_index
- Methods: recall_selected_variation(), recall_last_used_variation(),
  store_variation(), delete_selected_variation(), randomize_macros()
- Introspection: /live/device/introspect endpoint for API discovery

### Scripts
- introspect_device.py: Discovers available properties/methods on devices
- explore_device_variations.py: Initial exploration script for variations
- test_device_variations.py: Comprehensive test suite for variation APIs

### Documentation
- DEVICE_VARIATIONS_PROPOSAL.md: Complete API documentation and implementation
  plan with test results

## Testing
All core functionality tested successfully:
- ✅ All read-only properties working
- ✅ selected_variation_index read/write tested (index switching -1 → 0 → -1)
- ✅ recall_* methods operational
- ✅ Modification methods available (store, delete, randomize)

## Compatibility
- Requires Ableton Live 12+ (variations feature introduced in Live 12)
- Properties gracefully fail on non-RackDevice types
- Backward compatible with Live 11 (properties return errors on unsupported devices)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
Cleanup to keep the PR focused on Device Variations only:
- Removed non-essential properties (can_have_chains, chains, has_macro_mappings,
  macros_mapped, visible_macro_count) as they are rack-related but not
  variation-specific
- Kept only variation-essential properties: variation_count, selected_variation_index

Added comprehensive pytest unit tests:
- tests/test_device.py with 9 automated tests
- Tests for properties (read-only and read/write)
- Tests for all variation methods
- Tests for listeners
- Auto-skip when no RackDevice with variations found

Updated documentation:
- Clarified which properties are variation-specific vs general rack properties
- Updated DEVICE_VARIATIONS_PROPOSAL.md with refined scope
- Updated PR_DESCRIPTION.md to reflect changes

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
Architecture improvements:
- Move development scripts to devel/ (excluded from git)
- Create generic utils/introspect.py for any Live object (not just devices)
- Consolidate DEVICE_VARIATIONS_PROPOSAL.md into PR_DESCRIPTION.md

Changes:
- devel/ directory for development-only scripts (explore, introspect, test)
- utils/introspect.py: Generic CLI tool for introspecting any Live object
  - Extensible design supports device/clip/track/song (device implemented)
  - Clean output with highlighted variation-related properties
  - Proper argument parsing and error handling
- PR_DESCRIPTION.md: Merged and simplified documentation
  - Complete yet concise (was 192+43 lines, now 122 lines)
  - Includes usage examples for all interaction methods
  - Documents discovery process and future extensibility
- .gitignore: Added devel/ and logs/

This keeps the PR focused on Device Variations while providing better
developer tools for future API exploration.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
- Step-by-step instructions for testing Device Variations
- Covers: AbletonOSC reload, console testing, introspection, pytest
- Troubleshooting section for common issues
- Success criteria checklist
- Moved utils/introspect.py to devel/introspect.py
- Updated .gitignore to exclude devel/* except devel/introspect.py
- Keeps development scripts private while providing introspect.py as example

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
- Added Device Variations commands to run-console.py autocomplete
- Updated README.md with comprehensive Device Variations API section
  - Properties: variation_count, selected_variation_index
  - Methods: recall, store, delete, randomize
  - Listeners for variation changes
  - Introspection support
- Documented Live 12+ requirement and RackDevice compatibility

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
- Integrated Device Variations commands into main Device properties table
- Moved variation methods into new "Device methods" table
- Added "(Live 12+, RackDevice only)" suffix to all variation commands
- Removed separate subsections for cleaner documentation structure
- Added bullet point about Device Variations availability

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
Copy link
Owner

@ideoforms ideoforms left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @elzinko, thanks for this. Some nice additions - I'm particularly interested in the introspection code, which I'm going to check out in a moment!

First pass review:

  • I want to keep the codebase as lean and simple as possible, as extra code and files creates a long-term maintenance burden. On that note, please remove all of the new markdown files, and all of the files in devel.
  • Please remove any mention of requiring Live 12+, as it can be assumed that the majority of users are now using this (and some existing functionality, e.g. scales/roots, already assume this)
  • A few more comments inline

BREAKING CHANGE: Device Variations API paths have been updated to follow
AbletonOSC naming conventions. Update your code to use the new paths.

### New API Structure

**Properties:**
- `/live/device/get/variations/num` (was: variation_count)
- `/live/device/get/variations/selected` (was: selected_variation_index)
- `/live/device/set/variations/selected` (was: set/selected_variation_index)

**Listeners:**
- `/live/device/start_listen/variations/num`
- `/live/device/start_listen/variations/selected`
- (and corresponding stop_listen endpoints)

**Methods:**
- `/live/device/variations/recall` (was: recall_selected_variation)
- `/live/device/variations/recall_last` (was: recall_last_used_variation)
- `/live/device/variations/store` (was: store_variation)
- `/live/device/variations/delete` (was: delete_selected_variation)
- `/live/device/variations/randomize` (was: randomize_macros)

### Rationale

- Follows existing AbletonOSC pattern: `/live/track/get/num_devices`
- Groups related endpoints under `/variations/` namespace
- Removes redundant suffixes (`_index`, `_variation`, `_macros`)
- More intuitive: `variations/num` vs `variation_count`
- Consistent with hierarchical OSC structure

### Changes

- **abletonosc/device.py**: Refactored all variation handlers with new paths
- **tests/test_device.py**: Updated all test cases with new API paths
- **run-console.py**: Updated autocomplete with new paths
- **README.md**: Updated documentation with new API structure
- **pytest.ini**: Added to exclude devel/ from test discovery

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
@CLAassistant
Copy link

CLAassistant commented Nov 19, 2025

CLA assistant check
All committers have signed the CLA.

Changes based on code review by @ideoforms:

**Code Cleanup:**
- Removed development-specific ignores from .gitignore (logs/, devel/*)
- Removed all "Live 12+" mentions (assumed majority of users on Live 12+)
- Improved introspection output: lowercase keys for consistency
- Enhanced comments: explained string length limit for OSC message size

**Tests:**
- Uncommented destructive tests (store/delete variations)
- Tests are expected to be run on non-production sets
- Now includes full test coverage: 10 tests total

**Documentation:**
- Removed redundant start_listen/stop_listen entries from README
- Simplified variation descriptions (removed "Live 12+" mentions)
- Kept only essential documentation

**Introspection Improvements:**
- Changed "PROPERTIES:" to "properties:" for consistency
- Changed "METHODS:" to "methods:" for consistency
- Added detailed comment explaining string truncation rationale

All feedback addressed while keeping devel/introspect.py for maintainer review.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
@elzinko
Copy link
Author

elzinko commented Nov 19, 2025

Hi @elzinko, thanks for this. Some nice additions - I'm particularly interested in the introspection code, which I'm going to check out in a moment!

First pass review:

  • I want to keep the codebase as lean and simple as possible, as extra code and files creates a long-term maintenance burden. On that note, please remove all of the new markdown files, and all of the files in devel.
  • Please remove any mention of requiring Live 12+, as it can be assumed that the majority of users are now using this (and some existing functionality, e.g. scales/roots, already assume this)
  • A few more comments inline

i'll check all your review in those next day and tell you when all is ready

elzinko and others added 9 commits November 19, 2025 21:26
- Removed pytest.ini (wasn't in original codebase)
- Removed PR_DESCRIPTION.md (local reference file only)
- Removed TESTING.md (development documentation)

Keeping codebase lean and simple as requested by maintainer.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
Keeping only devel/introspect.py as requested by maintainer for review.
Removed development-specific scripts:
- explore_device_variations.py
- introspect_device.py
- test_device_variations.py

These were used during development but not needed in the codebase.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
Fixed two issues with the introspection tool:

1. Fixed case-sensitivity bug in response parsing
   - Server returns lowercase markers ("properties:", "methods:")
   - Client was checking for uppercase ("PROPERTIES:", "METHODS:")
   - This caused all introspection results to appear empty

2. Made keyword highlighting generic and optional
   - Removed hardcoded keywords (variation, macro, chain, etc.)
   - Added optional --highlight CLI parameter for user-specified keywords
   - Tool now remains generic for any Live API introspection
   - Example: ./devel/introspect.py device 0 0 --highlight variation,macro

This ensures the introspection tool is feature-agnostic and usable
for discovering any Live object API, not just device variations.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
Moved introspection from device-specific to generic unified endpoint:

Server-side changes:
- Created IntrospectionHandler in abletonosc/introspection.py
- Unified endpoint: /live/introspect <object_type> <object_ids...>
- Supports: device, clip, track, song
- Removed device-specific introspection from DeviceHandler
- Registered IntrospectionHandler in manager

Client-side changes:
- Moved devel/introspect.py → tools/introspect.py
- Updated client to use unified endpoint with object_type parameter
- Tool now positioned as developer/maintainer utility

Documentation:
- Added "Introspection (Developer Tool)" section in Application API
- Clarified this is for development, debugging, and API exploration
- Removed /live/device/introspect from Device API docs
- Updated run-console.py autocomplete

This makes introspection more extensible (works for all object types)
and positions the tool appropriately as a development utility rather
than end-user feature.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
…entions

Rename all Device Variations OSC endpoints to match the exact property and
method names from Ableton Live's Python API, ensuring consistency with the
established convention used throughout the codebase.

This change maintains the bijection between Live API names and OSC endpoint
names, as seen in other handlers (song.py, track.py, clip.py, etc.) where
native properties and methods use their exact Live API names.

Changes:
- Properties:
  • variation_count: /variations/num → /variations/variation_count
  • selected_variation_index: /variations/selected → /variations/selected_variation_index

- Methods:
  • recall_selected_variation: /variations/recall → /variations/recall_selected_variation
  • recall_last_used_variation: /variations/recall_last → /variations/recall_last_used_variation
  • store_variation: /variations/store → /variations/store_variation
  • delete_selected_variation: /variations/delete → /variations/delete_selected_variation
  • randomize_macros: /variations/randomize → /variations/randomize_macros

Files updated:
- abletonosc/device.py: Updated all 12 variation endpoints
- tests/test_device.py: Updated all 9 test functions to use new names
- README.md: Updated documentation tables and added listener documentation
- run-console.py: Updated autocomplete entries

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
Keep PR focused on Device Variations naming only. The cleanup of empty
methods list can be addressed in a separate PR.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
Increase the introspection query timeout from 150ms (TICK_DURATION) to 2
seconds to accommodate the large amount of data returned by introspection,
especially for complex objects like RackDevices with many properties and
methods.

Without this fix, the introspect tool would timeout with "No response
received to query" error, even though the OSC server was responding
correctly - the response just took longer than 150ms to process and send.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
Add explicit validation for track/device/clip existence in both the
introspection handler and client tool, providing clear, actionable error
messages instead of generic "Index out of range" errors.

Server-side validation (abletonosc/introspection.py):
- Check if track exists before accessing
- Check if device exists on track before accessing
- Check if clip slot exists and has a clip before accessing
- Provide detailed error messages with available ranges

Client-side validation (tools/introspect.py):
- Pre-validate objects exist before calling introspection endpoint
- Show helpful tips when objects don't exist
- Unified 2-second timeout for all OSC queries

Error message improvements:
- Before: "Failed to access device with IDs [1, 2]: Index out of range"
- After: "Device 2 does not exist on track 1 (track has 0 device(s))"

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
Enhanced the test fixture to automatically set up the testing environment:
- If a RackDevice exists but has no variations, automatically create 2 test variations
- Store current macro state as variation 1
- Randomize macros and store as variation 2
- Clean up auto-created variations after tests complete using pytest yield pattern

This eliminates the need for manual variation setup - users only need to add a
RackDevice to track 0 and tests will handle the rest.

Also adjusted test_track_devices to check track 1 instead of track 0 to avoid
conflict with Device Variations tests that use track 0.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
@elzinko
Copy link
Author

elzinko commented Nov 23, 2025

Hi

I think everything is now updated on my side.
Could you review the code once more?

Regarding variations:

It seems impossible to store a variation with a custom name, since the Live API does not expose this functionality.

I also tried to update (overwrite) an existing variation when macro values change, but Live only provides a UI button for this, and the only workaround I found would be to map that button to a MIDI message.

For testing, I noticed that in order to properly exercise the variation-related behavior, you need to create a device with a Rack and at least one mapped macro parameter. Otherwise, some of the tests are skipped (or behave differently) when no Rack is present.

Would it make sense to add this requirement to the documentation so contributors know how to set up the proper test environment?
Also, could you confirm that the current behavior (tests being skipped when no Rack is found) is expected?

Thanks again for your time and support!

@elzinko
Copy link
Author

elzinko commented Nov 23, 2025

  • I want to keep the codebase as lean and simple as possible, as extra code and files creates a long-term maintenance burden. On that note, please remove all of the new markdown files, and all of the files in devel.

Thanks for the feedback! I completely understand your point about keeping the codebase lean and maintainable.
Regarding the tools/introspect.py file specifically, I'd like to share my perspective and get your thoughts:
Current situation:

  • The /live/introspect OSC endpoint works and returns raw data
  • Without tools/introspect.py, users can query it directly but the output is unformatted
  • With tools/introspect.py, developers get formatted, highlighted, and human-readable output

My reasoning:

  • I see /live/introspect as a developer/maintainer tool, not an end-user feature
  • tools/introspect.py significantly improves the developer experience when exploring the Live API
  • It helped us validate the Device Variations API implementation and could help future contributors

Question:
Would you be open to keeping tools/introspect.py as a developer utility while removing the other files? Or do you prefer to keep only the raw OSC endpoint?

I'm happy to follow your decision either way - just wanted to share the reasoning behind including it. Let me know your thoughts!

@elzinko
Copy link
Author

elzinko commented Dec 11, 2025

@ideoforms up

@ideoforms
Copy link
Owner

Sorry @elzinko, busy couple of weeks with end of year project deadlines. Will get back to this asap!

@elzinko
Copy link
Author

elzinko commented Dec 11, 2025

I just wanted to be sure that you were aware of. No hurry for me

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants