Rename package directory AbletonOSC/ -> ableton_osc/
Python package naming convention uses snake_case. Update the import in the root __init__.py and the setuptools include pattern in pyproject.toml. Internal relative imports within the package are unaffected. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,144 @@
|
||||
"""
|
||||
Main ControlSurface entry point for Ableton Live.
|
||||
Manages OSC server lifecycle and all handler registrations.
|
||||
"""
|
||||
import logging
|
||||
import os
|
||||
import sys
|
||||
|
||||
try:
|
||||
from ableton.v2.control_surface import ControlSurface
|
||||
except ImportError:
|
||||
from contextlib import contextmanager
|
||||
|
||||
class ControlSurface: # type: ignore
|
||||
def __init__(self, c_instance=None):
|
||||
self._c_instance = c_instance
|
||||
|
||||
def song(self):
|
||||
return None
|
||||
|
||||
def application(self):
|
||||
return None
|
||||
|
||||
def disconnect(self):
|
||||
pass
|
||||
|
||||
def update_display(self):
|
||||
pass
|
||||
|
||||
def log_message(self, msg):
|
||||
print(msg)
|
||||
|
||||
def show_message(self, msg):
|
||||
print(msg)
|
||||
|
||||
def schedule_message(self, delay, callback):
|
||||
pass
|
||||
|
||||
@contextmanager
|
||||
def component_guard(self):
|
||||
yield
|
||||
|
||||
from .osc_server import OSCServer
|
||||
from .song import SongHandler
|
||||
from .track import TrackHandler
|
||||
from .return_track import ReturnTrackHandler
|
||||
from .clip import ClipHandler
|
||||
from .clip_slot import ClipSlotHandler
|
||||
from .device import DeviceHandler
|
||||
from .scene import SceneHandler
|
||||
from .view import ViewHandler
|
||||
from .application import ApplicationHandler
|
||||
from .browser import BrowserHandler
|
||||
from .groove import GrooveHandler
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
LISTEN_PORT = int(os.environ.get("ABLETON_OSC_LISTEN_PORT", 11000))
|
||||
SEND_PORT = int(os.environ.get("ABLETON_OSC_SEND_PORT", 11001))
|
||||
|
||||
|
||||
class Manager(ControlSurface):
|
||||
def __init__(self, c_instance=None):
|
||||
super().__init__(c_instance)
|
||||
self._setup_logging()
|
||||
self._handlers = []
|
||||
try:
|
||||
self.osc_server = OSCServer(listen_port=LISTEN_PORT, send_port=SEND_PORT)
|
||||
self.osc_server.start()
|
||||
self._setup_handlers()
|
||||
self.show_message("AbletonOSC: Listening on port %d" % LISTEN_PORT)
|
||||
logger.info("AbletonOSC started (listen=%d, send=%d)", LISTEN_PORT, SEND_PORT)
|
||||
self.osc_server.send("/live/startup", ())
|
||||
except OSError as e:
|
||||
self.show_message("AbletonOSC: Couldn't bind to port %d (%s)" % (LISTEN_PORT, e))
|
||||
logger.error("Couldn't bind to port %d: %s", LISTEN_PORT, e)
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
|
||||
def _setup_logging(self) -> None:
|
||||
logging.basicConfig(
|
||||
level=logging.DEBUG,
|
||||
format="%(asctime)s [%(levelname)s] %(name)s: %(message)s",
|
||||
)
|
||||
|
||||
def _setup_handlers(self) -> None:
|
||||
handler_classes = [
|
||||
ApplicationHandler,
|
||||
SongHandler,
|
||||
TrackHandler,
|
||||
ReturnTrackHandler,
|
||||
ClipHandler,
|
||||
ClipSlotHandler,
|
||||
DeviceHandler,
|
||||
SceneHandler,
|
||||
ViewHandler,
|
||||
BrowserHandler,
|
||||
GrooveHandler,
|
||||
]
|
||||
with self.component_guard():
|
||||
for cls in handler_classes:
|
||||
h = cls(self)
|
||||
h.init_api()
|
||||
self._handlers.append(h)
|
||||
|
||||
# Control endpoints
|
||||
self.osc_server.add_handler("/live/test", self._handle_test)
|
||||
self.osc_server.add_handler("/live/api/reload", self._handle_reload)
|
||||
self.osc_server.add_handler("/live/api/show_message", self._handle_show_message)
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
# ControlSurface interface
|
||||
# ------------------------------------------------------------------
|
||||
|
||||
def update_display(self) -> None:
|
||||
"""Called by Live ~100ms; drives the OSC poll loop."""
|
||||
self.osc_server.process()
|
||||
|
||||
def disconnect(self) -> None:
|
||||
for h in self._handlers:
|
||||
h.clear_listeners()
|
||||
self.osc_server.send("/live/shutdown", ())
|
||||
self.osc_server.stop()
|
||||
super().disconnect()
|
||||
logger.info("AbletonOSC disconnected")
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
# Built-in handlers
|
||||
# ------------------------------------------------------------------
|
||||
|
||||
def _handle_test(self, params: tuple):
|
||||
return ("AbletonOSC active",)
|
||||
|
||||
def _handle_reload(self, params: tuple):
|
||||
# Re-init all handlers (clears listeners and re-registers)
|
||||
for h in self._handlers:
|
||||
h.clear_listeners()
|
||||
h.init_api()
|
||||
return ("reloaded",)
|
||||
|
||||
def _handle_show_message(self, params: tuple):
|
||||
if params:
|
||||
self.log_message(str(params[0]))
|
||||
return None
|
||||
Reference in New Issue
Block a user