Initial implementation: full Ableton Live 11 OSC remote script

Covers all major Live API objects with get/set/listen/method handlers:
song, track, return_track, clip, clip_slot, device (incl. rack chains
and drum pads), scene, view, application, browser, groove.

Zero external runtime dependencies — OSC encoded/decoded in osc_server.py.
Wildcard * support for track/scene indices. Listener callbacks fire to
matching /get/ addresses for bidirectional state sync.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-06-01 12:27:47 +02:00
commit aad042650e
17 changed files with 3159 additions and 0 deletions
+60
View File
@@ -0,0 +1,60 @@
"""Handles /live/groove/* OSC addresses."""
import logging
from typing import Optional
from .handler import AbletonOSCHandler
logger = logging.getLogger(__name__)
class GrooveHandler(AbletonOSCHandler):
def init_api(self) -> None:
self.clear_listeners()
self._add("/live/groove/get/grooves", self._get_grooves)
self._add("/live/groove/get/amount", self._get_groove_amount)
self._add("/live/groove/set/amount", self._set_groove_amount)
def _pool(self):
try:
return self.song.groove_pool
except Exception:
return None
def _get_grooves(self, params: tuple) -> Optional[tuple]:
pool = self._pool()
if pool is None:
return None
try:
return tuple(g.name for g in pool.grooves)
except Exception as e:
logger.warning("get grooves: %s", e)
return None
def _get_groove_amount(self, params: tuple) -> Optional[tuple]:
"""params: groove_name"""
pool = self._pool()
if pool is None or not params:
return None
name = str(params[0])
try:
for g in pool.grooves:
if g.name == name:
return (name, float(g.amount))
except Exception as e:
logger.warning("get groove amount: %s", e)
return None
def _set_groove_amount(self, params: tuple) -> None:
"""params: groove_name, amount"""
pool = self._pool()
if pool is None or len(params) < 2:
return None
name = str(params[0])
amount = float(params[1])
try:
for g in pool.grooves:
if g.name == name:
g.amount = amount
break
except Exception as e:
logger.warning("set groove amount: %s", e)
return None