diff --git a/abletonosc/osc_server.py b/abletonosc/osc_server.py index 4101817..fadafa8 100644 --- a/abletonosc/osc_server.py +++ b/abletonosc/osc_server.py @@ -1,8 +1,9 @@ from typing import Tuple, Any, Callable from .constants import OSC_LISTEN_PORT, OSC_RESPONSE_PORT -from ..pythonosc.osc_message import OscMessage, ParseError -from ..pythonosc.osc_bundle import OscBundle -from ..pythonosc.osc_message_builder import OscMessageBuilder, BuildError +# Live 12 fix: use full package path (relative imports fail, bare module name not found) +from AbletonOSC.pythonosc.osc_message import OscMessage, ParseError +from AbletonOSC.pythonosc.osc_bundle import OscBundle +from AbletonOSC.pythonosc.osc_message_builder import OscMessageBuilder, BuildError import re import errno diff --git a/abletonosc/track.py b/abletonosc/track.py index 5e21353..4d82bf0 100644 --- a/abletonosc/track.py +++ b/abletonosc/track.py @@ -1,4 +1,5 @@ from typing import Tuple, Any, Callable, Optional +import Live from .handler import AbletonOSCHandler @@ -108,6 +109,48 @@ def track_delete_clip(track, params: Tuple[Any]): self.osc_server.add_handler("/live/track/delete_clip", create_track_callback(track_delete_clip)) + #-------------------------------------------------------------------------------- + # Insert device by URI/name + # Usage: /live/track/insert_device [device_index] + # Example: /live/track/insert_device 0 "Reverb" -1 + #-------------------------------------------------------------------------------- + def track_insert_device(track, params: Tuple[Any]): + device_uri = str(params[0]) + device_index = int(params[1]) if len(params) > 1 else -1 + self.logger.info("Inserting device '%s' at index %d" % (device_uri, device_index)) + + # Use the browser to load the device + application = Live.Application.get_application() + browser = application.browser + + # Search for the device in available items + # Try instruments first, then audio effects, then midi effects + search_locations = [ + browser.instruments, + browser.audio_effects, + browser.midi_effects, + browser.drums, + browser.sounds, + ] + + device_item = None + for location in search_locations: + for item in location.children: + if item.name == device_uri or device_uri in item.name: + device_item = item + break + if device_item: + break + + if device_item: + browser.load_item(device_item) + return (len(track.devices) - 1,) + else: + self.logger.warning("Device not found: %s" % device_uri) + return (-1,) + + self.osc_server.add_handler("/live/track/insert_device", create_track_callback(track_insert_device)) + def track_get_clip_names(track, _): return tuple(clip_slot.clip.name if clip_slot.clip else None for clip_slot in track.clip_slots) diff --git a/tmpclaude-2f62-cwd b/tmpclaude-2f62-cwd new file mode 100644 index 0000000..c03888a --- /dev/null +++ b/tmpclaude-2f62-cwd @@ -0,0 +1 @@ +/c/Users/drane/ableton-mcp/AbletonOSC diff --git a/tmpclaude-fb7e-cwd b/tmpclaude-fb7e-cwd new file mode 100644 index 0000000..c03888a --- /dev/null +++ b/tmpclaude-fb7e-cwd @@ -0,0 +1 @@ +/c/Users/drane/ableton-mcp/AbletonOSC