Closed esaruoho closed 1 month ago
I don't currently have access to the Live 12 beta, but will get a copy when it's released and be able to confirm then.
If you have access to the beta and can verify, any reports would be appreciated!
I do have access but am on a new computer so dont yet ha e AbletonOSC installed. I will check and see if it works!! Fingers crossed :)
i'll try and send messages to it hopefully tomorrow evening. is this promising, however, @ideoforms ?
edit: I had to put in an image a second time to make sure it shows the bottom bar info
i can confirm that my clip pitchers, track volume controls and clip launchers + recorders work. unfortunately i'm still having issues with Grid objects - which seems to be a TouchOSC specific issue, all Grid objects are unstable. not sure how to proceed with this, since I'd need to talk with TouchOSC developers about this.
But yes, TouchOSC definitely works with Live12. So closing this!
Thanks for the report @esaruoho !
yep, TouchOSC people fixed the Grid object issues.
i'm now trying to figure out how to get my TouchOSC script to talk to Ableton Live 12 again. I definitely had them working on February, but it's September now. Trying to remember where all of this was.
what i can say is that i'm on macOS Sonoma 14.6.1
I've tried with Ableton Live 11 and Ableton Live 12, i've re-installed and copied and installed, and both state that the old folder is able to be recognized and they connect to 11000, but for some reason, i can't make the connection.
to add insult to injury, even sending messages from ./run-console.py
no longer work.
Is there some form of getting more details from ./run-console.py ? @ideoforms like more logging?
this is definitely the computer i was using back then, which is very strange. i might've updated to a newer version of Python and a newer version of macOS, but i'm completely in the dark here, being unable to get ./run
Hmm, that's strange. Try running ./run-console.py -v
— this turns on verbose output, which will report whenever a message is received from Ableton.
I've just tested here with the latest Live 12 on macOS Ventura and it is behaving as expected. Here's the output I get if I try querying the tempo:
(1823)(master)(mbp2022:AbletonOSC)$ ./run-console.py
AbletonOSC command console
Usage: /live/osc/command [params]
>>> /live/song/get/tempo
120.0
>>> ^D
(1823)(master)(mbp2022:AbletonOSC)$ ./run-console.py -v
AbletonOSC command console
Usage: /live/osc/command [params]
>>> /live/startup ()
/live/application/get/average_process_usage ()
/live/song/get/tempo
/live/song/get/tempo (120.0,)
120.0
>>> ^D
Can you confirm that: AbletonOSC is visible in the Control Surface column in "Link, Tempo & MIDI" (in Preferences)?
You should also see some logging in the internal AbletonOSC logs: ~/Music/Ableton/User Library/Remote Scripts/AbletonOSC/logs/abletonosc.log
this is what i get, unfortunately:
$ ./run-console.py -v
AbletonOSC command console
Usage: /live/osc/command [params]
>>> /live/osc/get/tempo
>>> /live/osc/get/tempo
>>> /live/osc/get/tempo
>>> /live/startup ()
(after which i pressed ctrl-c)
>>> Traceback (most recent call last):
File "/Users/esaruoho/work/AbletonOSC/./run-console.py", line 96, in <module>
main(args)
File "/Users/esaruoho/work/AbletonOSC/./run-console.py", line 52, in main
command_str = input(">>> ")
^^^^^^^^^^^^^
KeyboardInterrupt
i tried it without sync,remote,mpe. no change.
when i turn the row the AbletonOSC is on, to Off, and re-select it, i do get the yellow message at the bottom:
there's a brief delay between /live/osc/get/tempo
and the next >>>
but nothing more.
not sure how to proceed.
also, no logging appears in the Remote Scripts folder in the expected place.
ok, three more details.
$ ./run-console.py -v
/Users/esaruoho/Music/Ableton/User Library/Remote Scripts/AbletonOSC/pythonosc/dispatcher.py:153: SyntaxWarning: invalid escape sequence '\w'
pattern = pattern.replace('\\*', '[\w|\+]*')
AbletonOSC command console
Usage: /live/osc/command [params]
>>>
this strange error.
also, i am using an older AbletonOSC build. the reason for that? i downloaded the current zip, and followed the advice for unzipping, and renaming the folder abletonosc-master to AbletonOSC. i put that folder into the User Scripts, and while it shows in the settings menu, it does not give me the yellow message at the bottom, which is very strange, right?
ok, i was told to do this:
replace
pattern = pattern.replace('\\*', '[\w|\+]*')
with
pattern = pattern.replace('\\*', '[\\w|\\+]*')
let's see if that helps. ok i fixed it, and now -v no longer gives an error. but also no information.
is the problem that i'm using Live 12.0.25 ( Build: 2024-08-27_2627c43816)
To debug the startup issue with the latest .zip, could you try running Live with the latest AbletonOSC installed/enabled, run the instructions in "Debugging compile-time issues" and paste the output? And do the same with the older version installed in case it's hitting some runtime error.
I am also running Live 12.0.25 and no problems. I wonder if it's a network issue.
Could you also paste the output of the below terminal command which will list UDP ports that Live is listening on?
sudo lsof -nP -i4UDP | grep ^Live
(old version) ok. this is very strange. i was getting no results, until i thought, let's close TouchOSC.
now that i completely quit TouchOSC - but have TouchOSC Bridge running, now i get messages!
i'm starting to think i maybe had TouchOSC listening to 11000 and capturing it, and that's why the errors. i'll continue troubleshooting from this point of view. Thanks a lot for your help!
>>> /live/song/get/tempo
/live/song/get/tempo (86.75,)
(86.75,)
>>>
i ran this on the new version.
$ pytest
================================================================= test session starts ==================================================================
platform darwin -- Python 3.12.6, pytest-8.3.3, pluggy-1.5.0
rootdir: /Users/esaruoho/Music/Ableton/User Library/Remote Scripts/AbletonOSC
collected 54 items
tests/test_application.py .F. [ 5%]
tests/test_bundle.py . [ 7%]
tests/test_clip.py FFFFFFFFF [ 24%]
tests/test_clip_slot.py FFF [ 29%]
tests/test_song.py ..F..................FFFF [ 75%]
tests/test_track.py .......FFF [ 94%]
tests/test_view.py ..F [100%]
======================================================================= FAILURES =======================================================================
_____________________________________________________________ test_application_get_version _____________________________________________________________
client = <AbletonOSC.client.client.AbletonOSCClient object at 0x104b47200>
def test_application_get_version(client):
rv = client.query("/live/application/get/version")
> assert len(rv) == 2 and rv[0] == 11
E assert (2 == 2 and 12 == 11)
E + where 2 = len((12, 0))
tests/test_application.py:12: AssertionError
_______________________________________________________________ test_clip_property_name ________________________________________________________________
client = <AbletonOSC.client.client.AbletonOSCClient object at 0x105aadb50>
def test_clip_property_name(client):
> _test_clip_property(client, 0, 0, "name", ("Alpha", "Beta"))
tests/test_clip.py:40:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
tests/test_clip.py:37: in _test_clip_property
assert client.query("/live/clip/get/%s" % property, (track_id, clip_id)) == (track_id, clip_id, value,)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <AbletonOSC.client.client.AbletonOSCClient object at 0x105aadb50>, address = '/live/clip/get/name', params = (0, 0), timeout = 0.15
def query(self,
address: str,
params: tuple = (),
timeout: float = TICK_DURATION):
rv = None
_event = threading.Event()
def received_response(address, params):
nonlocal rv
nonlocal _event
rv = params
_event.set()
self.set_handler(address, received_response)
self.send_message(address, params)
_event.wait(timeout)
self.remove_handler(address)
if not _event.is_set():
> raise RuntimeError("No response received to query: %s" % address)
E RuntimeError: No response received to query: /live/clip/get/name
client/client.py:153: RuntimeError
_______________________________________________________________ test_clip_property_color _______________________________________________________________
client = <AbletonOSC.client.client.AbletonOSCClient object at 0x105aadb50>
def test_clip_property_color(client):
> _test_clip_property(client, 0, 0, "color", (0x001AFF2F, 0x001A2F96))
tests/test_clip.py:43:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
tests/test_clip.py:37: in _test_clip_property
assert client.query("/live/clip/get/%s" % property, (track_id, clip_id)) == (track_id, clip_id, value,)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <AbletonOSC.client.client.AbletonOSCClient object at 0x105aadb50>, address = '/live/clip/get/color', params = (0, 0), timeout = 0.15
def query(self,
address: str,
params: tuple = (),
timeout: float = TICK_DURATION):
rv = None
_event = threading.Event()
def received_response(address, params):
nonlocal rv
nonlocal _event
rv = params
_event.set()
self.set_handler(address, received_response)
self.send_message(address, params)
_event.wait(timeout)
self.remove_handler(address)
if not _event.is_set():
> raise RuntimeError("No response received to query: %s" % address)
E RuntimeError: No response received to query: /live/clip/get/color
client/client.py:153: RuntimeError
_______________________________________________________________ test_clip_property_gain ________________________________________________________________
client = <AbletonOSC.client.client.AbletonOSCClient object at 0x105aadb50>
def test_clip_property_gain(client):
> _test_clip_property(client, 2, 0, "gain", (0.5, 1.0))
tests/test_clip.py:46:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
tests/test_clip.py:37: in _test_clip_property
assert client.query("/live/clip/get/%s" % property, (track_id, clip_id)) == (track_id, clip_id, value,)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <AbletonOSC.client.client.AbletonOSCClient object at 0x105aadb50>, address = '/live/clip/get/gain', params = (2, 0), timeout = 0.15
def query(self,
address: str,
params: tuple = (),
timeout: float = TICK_DURATION):
rv = None
_event = threading.Event()
def received_response(address, params):
nonlocal rv
nonlocal _event
rv = params
_event.set()
self.set_handler(address, received_response)
self.send_message(address, params)
_event.wait(timeout)
self.remove_handler(address)
if not _event.is_set():
> raise RuntimeError("No response received to query: %s" % address)
E RuntimeError: No response received to query: /live/clip/get/gain
client/client.py:153: RuntimeError
___________________________________________________________ test_clip_property_pitch_coarse ____________________________________________________________
client = <AbletonOSC.client.client.AbletonOSCClient object at 0x105aadb50>
def test_clip_property_pitch_coarse(client):
> _test_clip_property(client, 2, 0, "pitch_coarse", (4, 0))
tests/test_clip.py:49:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
tests/test_clip.py:37: in _test_clip_property
assert client.query("/live/clip/get/%s" % property, (track_id, clip_id)) == (track_id, clip_id, value,)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <AbletonOSC.client.client.AbletonOSCClient object at 0x105aadb50>, address = '/live/clip/get/pitch_coarse', params = (2, 0), timeout = 0.15
def query(self,
address: str,
params: tuple = (),
timeout: float = TICK_DURATION):
rv = None
_event = threading.Event()
def received_response(address, params):
nonlocal rv
nonlocal _event
rv = params
_event.set()
self.set_handler(address, received_response)
self.send_message(address, params)
_event.wait(timeout)
self.remove_handler(address)
if not _event.is_set():
> raise RuntimeError("No response received to query: %s" % address)
E RuntimeError: No response received to query: /live/clip/get/pitch_coarse
client/client.py:153: RuntimeError
____________________________________________________________ test_clip_property_pitch_fine _____________________________________________________________
client = <AbletonOSC.client.client.AbletonOSCClient object at 0x105aadb50>
def test_clip_property_pitch_fine(client):
> _test_clip_property(client, 2, 0, "pitch_fine", (0.5, 0.0))
tests/test_clip.py:52:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
tests/test_clip.py:37: in _test_clip_property
assert client.query("/live/clip/get/%s" % property, (track_id, clip_id)) == (track_id, clip_id, value,)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <AbletonOSC.client.client.AbletonOSCClient object at 0x105aadb50>, address = '/live/clip/get/pitch_fine', params = (2, 0), timeout = 0.15
def query(self,
address: str,
params: tuple = (),
timeout: float = TICK_DURATION):
rv = None
_event = threading.Event()
def received_response(address, params):
nonlocal rv
nonlocal _event
rv = params
_event.set()
self.set_handler(address, received_response)
self.send_message(address, params)
_event.wait(timeout)
self.remove_handler(address)
if not _event.is_set():
> raise RuntimeError("No response received to query: %s" % address)
E RuntimeError: No response received to query: /live/clip/get/pitch_fine
client/client.py:153: RuntimeError
______________________________________________________________ test_clip_add_remove_notes ______________________________________________________________
client = <AbletonOSC.client.client.AbletonOSCClient object at 0x105aadb50>
def test_clip_add_remove_notes(client):
> assert client.query("/live/clip/get/notes", (0, 0)) == (0, 0)
tests/test_clip.py:55:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <AbletonOSC.client.client.AbletonOSCClient object at 0x105aadb50>, address = '/live/clip/get/notes', params = (0, 0), timeout = 0.15
def query(self,
address: str,
params: tuple = (),
timeout: float = TICK_DURATION):
rv = None
_event = threading.Event()
def received_response(address, params):
nonlocal rv
nonlocal _event
rv = params
_event.set()
self.set_handler(address, received_response)
self.send_message(address, params)
_event.wait(timeout)
self.remove_handler(address)
if not _event.is_set():
> raise RuntimeError("No response received to query: %s" % address)
E RuntimeError: No response received to query: /live/clip/get/notes
client/client.py:153: RuntimeError
_______________________________________________________________ test_clip_add_many_notes _______________________________________________________________
client = <AbletonOSC.client.client.AbletonOSCClient object at 0x105aadb50>
def test_clip_add_many_notes(client):
"""
Test adding large numbers of notes to a clip.
Note that Ableton API's get_notes returns notes sorted by pitch, then time, so add notes
in this same order.
"""
random.seed(0)
all_note_data = []
pitch = 0
for pitch_index in range(127):
time = random.randrange(-32, 32) / 4
duration = random.randrange(1, 4) / 4
velocity = random.randrange(1, 128)
# Create multiple instances of the same sequence, shifted in time.
for timeshift in range(3):
note = (pitch,
time + (timeshift * 8),
duration,
velocity,
False)
all_note_data += note
pitch += 1
all_note_data = tuple(all_note_data)
# Check clip is initially empty
> assert client.query("/live/clip/get/notes", (0, 0)) == (0, 0)
tests/test_clip.py:108:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <AbletonOSC.client.client.AbletonOSCClient object at 0x105aadb50>, address = '/live/clip/get/notes', params = (0, 0), timeout = 0.15
def query(self,
address: str,
params: tuple = (),
timeout: float = TICK_DURATION):
rv = None
_event = threading.Event()
def received_response(address, params):
nonlocal rv
nonlocal _event
rv = params
_event.set()
self.set_handler(address, received_response)
self.send_message(address, params)
_event.wait(timeout)
self.remove_handler(address)
if not _event.is_set():
> raise RuntimeError("No response received to query: %s" % address)
E RuntimeError: No response received to query: /live/clip/get/notes
client/client.py:153: RuntimeError
__________________________________________________________ test_clip_playing_position_listen ___________________________________________________________
client = <AbletonOSC.client.client.AbletonOSCClient object at 0x105aadb50>
def test_clip_playing_position_listen(client):
client.send_message("/live/clip/start_listen/playing_position", [0, 0])
client.send_message("/live/clip/fire", [0, 0])
> rv = client.await_message("/live/clip/get/playing_position", TICK_DURATION * 2)
tests/test_clip.py:121:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <AbletonOSC.client.client.AbletonOSCClient object at 0x105aadb50>, address = '/live/clip/get/playing_position', timeout = 0.25
def await_message(self,
address: str,
timeout: float = TICK_DURATION):
"""
Awaits a reply from the given `address`, and optionally asserts that the function `fn`
returns True when called with the returned OSC parameters.
Args:
address: OSC query (and reply) address
fn: Optional assertion function
timeout: Maximum number of seconds to wait for a successful reply
Returns:
True if the reply is received within the timeout period and the assertion succeeds,
False otherwise
"""
rv = None
_event = threading.Event()
def received_response(address, params):
print("Received response: %s %s" % (address, str(params)))
nonlocal rv
nonlocal _event
rv = params
_event.set()
self.set_handler(address, received_response)
_event.wait(timeout)
self.remove_handler(address)
if not _event.is_set():
> raise RuntimeError("No response received to query: %s" % address)
E RuntimeError: No response received to query: /live/clip/get/playing_position
client/client.py:132: RuntimeError
______________________________________________________________ test_clip_listen_lifecycle ______________________________________________________________
client = <AbletonOSC.client.client.AbletonOSCClient object at 0x105aadb50>
def test_clip_listen_lifecycle(client):
client.send_message("/live/clip/set/name", [0, 0, "Alpha"])
wait_one_tick()
client.send_message("/live/clip/start_listen/name", [0, 0])
> assert client.await_message("/live/clip/get/name", TICK_DURATION * 2) == (0, 0, "Alpha")
tests/test_clip.py:135:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <AbletonOSC.client.client.AbletonOSCClient object at 0x105aadb50>, address = '/live/clip/get/name', timeout = 0.25
def await_message(self,
address: str,
timeout: float = TICK_DURATION):
"""
Awaits a reply from the given `address`, and optionally asserts that the function `fn`
returns True when called with the returned OSC parameters.
Args:
address: OSC query (and reply) address
fn: Optional assertion function
timeout: Maximum number of seconds to wait for a successful reply
Returns:
True if the reply is received within the timeout period and the assertion succeeds,
False otherwise
"""
rv = None
_event = threading.Event()
def received_response(address, params):
print("Received response: %s %s" % (address, str(params)))
nonlocal rv
nonlocal _event
rv = params
_event.set()
self.set_handler(address, received_response)
_event.wait(timeout)
self.remove_handler(address)
if not _event.is_set():
> raise RuntimeError("No response received to query: %s" % address)
E RuntimeError: No response received to query: /live/clip/get/name
client/client.py:132: RuntimeError
_______________________________________________________________ test_clip_slot_has_clip ________________________________________________________________
client = <AbletonOSC.client.client.AbletonOSCClient object at 0x105aafb30>
def test_clip_slot_has_clip(client):
> assert client.query("/live/clip_slot/get/has_clip", (0, 0)) == (0, 0, False)
tests/test_clip_slot.py:4:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <AbletonOSC.client.client.AbletonOSCClient object at 0x105aafb30>, address = '/live/clip_slot/get/has_clip', params = (0, 0), timeout = 0.15
def query(self,
address: str,
params: tuple = (),
timeout: float = TICK_DURATION):
rv = None
_event = threading.Event()
def received_response(address, params):
nonlocal rv
nonlocal _event
rv = params
_event.set()
self.set_handler(address, received_response)
self.send_message(address, params)
_event.wait(timeout)
self.remove_handler(address)
if not _event.is_set():
> raise RuntimeError("No response received to query: %s" % address)
E RuntimeError: No response received to query: /live/clip_slot/get/has_clip
client/client.py:153: RuntimeError
_______________________________________________________________ test_clip_slot_duplicate _______________________________________________________________
client = <AbletonOSC.client.client.AbletonOSCClient object at 0x105aafb30>
def test_clip_slot_duplicate(client):
client.send_message("/live/clip_slot/create_clip", [0, 0, 4.0])
client.send_message("/live/clip/get/notes", (0, 0))
> assert client.await_message("/live/clip/get/notes") == (0, 0)
tests/test_clip_slot.py:12:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <AbletonOSC.client.client.AbletonOSCClient object at 0x105aafb30>, address = '/live/clip/get/notes', timeout = 0.15
def await_message(self,
address: str,
timeout: float = TICK_DURATION):
"""
Awaits a reply from the given `address`, and optionally asserts that the function `fn`
returns True when called with the returned OSC parameters.
Args:
address: OSC query (and reply) address
fn: Optional assertion function
timeout: Maximum number of seconds to wait for a successful reply
Returns:
True if the reply is received within the timeout period and the assertion succeeds,
False otherwise
"""
rv = None
_event = threading.Event()
def received_response(address, params):
print("Received response: %s %s" % (address, str(params)))
nonlocal rv
nonlocal _event
rv = params
_event.set()
self.set_handler(address, received_response)
_event.wait(timeout)
self.remove_handler(address)
if not _event.is_set():
> raise RuntimeError("No response received to query: %s" % address)
E RuntimeError: No response received to query: /live/clip/get/notes
client/client.py:132: RuntimeError
____________________________________________________________ test_clip_slot_property_listen ____________________________________________________________
client = <AbletonOSC.client.client.AbletonOSCClient object at 0x105aafb30>
def test_clip_slot_property_listen(client):
client.send_message("/live/clip_slot/start_listen/has_clip", (0, 0))
assert client.await_message("/live/clip_slot/get/has_clip", TICK_DURATION * 2) == (0, 0, False)
client.send_message("/live/clip_slot/create_clip", [0, 0, 4.0])
> assert client.await_message("/live/clip_slot/get/has_clip", TICK_DURATION * 2) == (0, 0, True)
tests/test_clip_slot.py:29:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <AbletonOSC.client.client.AbletonOSCClient object at 0x105aafb30>, address = '/live/clip_slot/get/has_clip', timeout = 0.25
def await_message(self,
address: str,
timeout: float = TICK_DURATION):
"""
Awaits a reply from the given `address`, and optionally asserts that the function `fn`
returns True when called with the returned OSC parameters.
Args:
address: OSC query (and reply) address
fn: Optional assertion function
timeout: Maximum number of seconds to wait for a successful reply
Returns:
True if the reply is received within the timeout period and the assertion succeeds,
False otherwise
"""
rv = None
_event = threading.Event()
def received_response(address, params):
print("Received response: %s %s" % (address, str(params)))
nonlocal rv
nonlocal _event
rv = params
_event.set()
self.set_handler(address, received_response)
_event.wait(timeout)
self.remove_handler(address)
if not _event.is_set():
> raise RuntimeError("No response received to query: %s" % address)
E RuntimeError: No response received to query: /live/clip_slot/get/has_clip
client/client.py:132: RuntimeError
----------------------------------------------------------------- Captured stdout call -----------------------------------------------------------------
Received response: /live/clip_slot/get/has_clip (0, 0, False)
_______________________________________________________________ test_song_stop_all_clips _______________________________________________________________
client = <AbletonOSC.client.client.AbletonOSCClient object at 0x105ac3710>
def test_song_stop_all_clips(client):
client.send_message("/live/clip_slot/create_clip", (0, 0, 4))
client.send_message("/live/clip_slot/create_clip", (1, 0, 4))
client.send_message("/live/clip/fire", (0, 0))
client.send_message("/live/clip/fire", (1, 0))
# Sometimes a wait >one tick is required here. Not sure why.
wait_one_tick()
wait_one_tick()
> assert client.query("/live/clip/get/is_playing", (0, 0)) == (0, 0, True,)
tests/test_song.py:40:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <AbletonOSC.client.client.AbletonOSCClient object at 0x105ac3710>, address = '/live/clip/get/is_playing', params = (0, 0), timeout = 0.15
def query(self,
address: str,
params: tuple = (),
timeout: float = TICK_DURATION):
rv = None
_event = threading.Event()
def received_response(address, params):
nonlocal rv
nonlocal _event
rv = params
_event.set()
self.set_handler(address, received_response)
self.send_message(address, params)
_event.wait(timeout)
self.remove_handler(address)
if not _event.is_set():
> raise RuntimeError("No response received to query: %s" % address)
E RuntimeError: No response received to query: /live/clip/get/is_playing
client/client.py:153: RuntimeError
___________________________________________________________________ test_song_tracks ___________________________________________________________________
client = <AbletonOSC.client.client.AbletonOSCClient object at 0x105ac3710>
def test_song_tracks(client):
> assert client.query("/live/song/get/num_tracks") == (4,)
E assert (85,) == (4,)
E
E At index 0 diff: 85 != 4
E Use -v to get more diff
tests/test_song.py:144: AssertionError
___________________________________________________________________ test_song_scenes ___________________________________________________________________
client = <AbletonOSC.client.client.AbletonOSCClient object at 0x105ac3710>
def test_song_scenes(client):
> assert client.query("/live/song/get/num_scenes") == (8,)
E assert (2,) == (8,)
E
E At index 0 diff: 2 != 8
E Use -v to get more diff
tests/test_song.py:161: AssertionError
______________________________________________________________ test_song_duplicate_scene _______________________________________________________________
client = <AbletonOSC.client.client.AbletonOSCClient object at 0x105ac3710>
def test_song_duplicate_scene(client):
track_id = 0
scene_id = 7
> assert client.query("/live/song/get/num_scenes") == (8,)
E assert (2,) == (8,)
E
E At index 0 diff: 2 != 8
E Use -v to get more diff
tests/test_song.py:172: AssertionError
_________________________________________________________________ test_song_undo_redo __________________________________________________________________
client = <AbletonOSC.client.client.AbletonOSCClient object at 0x105ac3710>
def test_song_undo_redo(client):
> assert client.query("/live/song/get/num_scenes") == (8,)
E assert (2,) == (8,)
E
E At index 0 diff: 2 != 8
E Use -v to get more diff
tests/test_song.py:186: AssertionError
___________________________________________________________________ test_track_clips ___________________________________________________________________
client = <AbletonOSC.client.client.AbletonOSCClient object at 0x105b722d0>
def test_track_clips(client):
track_id = 0
client.send_message("/live/clip_slot/create_clip", (track_id, 0, 4))
client.send_message("/live/clip_slot/create_clip", (track_id, 1, 2))
client.send_message("/live/clip/set/name", (track_id, 0, "Alpha"))
client.send_message("/live/clip/set/name", (track_id, 1, "Beta"))
wait_one_tick()
> assert client.query("/live/track/get/clips/name", (track_id,)) == (track_id,
"Alpha", "Beta", None, None,
None, None, None, None)
tests/test_track.py:60:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <AbletonOSC.client.client.AbletonOSCClient object at 0x105b722d0>, address = '/live/track/get/clips/name', params = (0,), timeout = 0.15
def query(self,
address: str,
params: tuple = (),
timeout: float = TICK_DURATION):
rv = None
_event = threading.Event()
def received_response(address, params):
nonlocal rv
nonlocal _event
rv = params
_event.set()
self.set_handler(address, received_response)
self.send_message(address, params)
_event.wait(timeout)
self.remove_handler(address)
if not _event.is_set():
> raise RuntimeError("No response received to query: %s" % address)
E RuntimeError: No response received to query: /live/track/get/clips/name
client/client.py:153: RuntimeError
__________________________________________________________________ test_track_devices __________________________________________________________________
client = <AbletonOSC.client.client.AbletonOSCClient object at 0x105b722d0>
def test_track_devices(client):
track_id = 0
> assert client.query("/live/track/get/num_devices", (track_id,)) == (track_id, 0,)
tests/test_track.py:76:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <AbletonOSC.client.client.AbletonOSCClient object at 0x105b722d0>, address = '/live/track/get/num_devices', params = (0,), timeout = 0.15
def query(self,
address: str,
params: tuple = (),
timeout: float = TICK_DURATION):
rv = None
_event = threading.Event()
def received_response(address, params):
nonlocal rv
nonlocal _event
rv = params
_event.set()
self.set_handler(address, received_response)
self.send_message(address, params)
_event.wait(timeout)
self.remove_handler(address)
if not _event.is_set():
> raise RuntimeError("No response received to query: %s" % address)
E RuntimeError: No response received to query: /live/track/get/num_devices
client/client.py:153: RuntimeError
_________________________________________________________ test_track_listen_playing_slot_index _________________________________________________________
client = <AbletonOSC.client.client.AbletonOSCClient object at 0x105b722d0>
def test_track_listen_playing_slot_index(client):
# 1/16th quantize
client.send_message("/live/song/set/clip_trigger_quantization", (11,))
for track_id, clip_id in itertools.product((0, 1), (0, 1)):
client.send_message("/live/clip_slot/create_clip", (track_id, clip_id, 4))
client.send_message("/live/track/start_listen/playing_slot_index", (0,))
> assert client.await_message("/live/track/get/playing_slot_index", TICK_DURATION * 2) == (0, -1,)
tests/test_track.py:89:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <AbletonOSC.client.client.AbletonOSCClient object at 0x105b722d0>, address = '/live/track/get/playing_slot_index', timeout = 0.25
def await_message(self,
address: str,
timeout: float = TICK_DURATION):
"""
Awaits a reply from the given `address`, and optionally asserts that the function `fn`
returns True when called with the returned OSC parameters.
Args:
address: OSC query (and reply) address
fn: Optional assertion function
timeout: Maximum number of seconds to wait for a successful reply
Returns:
True if the reply is received within the timeout period and the assertion succeeds,
False otherwise
"""
rv = None
_event = threading.Event()
def received_response(address, params):
print("Received response: %s %s" % (address, str(params)))
nonlocal rv
nonlocal _event
rv = params
_event.set()
self.set_handler(address, received_response)
_event.wait(timeout)
self.remove_handler(address)
if not _event.is_set():
> raise RuntimeError("No response received to query: %s" % address)
E RuntimeError: No response received to query: /live/track/get/playing_slot_index
client/client.py:132: RuntimeError
__________________________________________________________________ test_selected_clip __________________________________________________________________
client = <AbletonOSC.client.client.AbletonOSCClient object at 0x105ac1580>
def test_selected_clip(client):
client.send_message("/live/view/set/selected_clip", (3, 4))
> rv = client.query("/live/view/get/selected_clip")
tests/test_view.py:19:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <AbletonOSC.client.client.AbletonOSCClient object at 0x105ac1580>, address = '/live/view/get/selected_clip', params = (), timeout = 0.15
def query(self,
address: str,
params: tuple = (),
timeout: float = TICK_DURATION):
rv = None
_event = threading.Event()
def received_response(address, params):
nonlocal rv
nonlocal _event
rv = params
_event.set()
self.set_handler(address, received_response)
self.send_message(address, params)
_event.wait(timeout)
self.remove_handler(address)
if not _event.is_set():
> raise RuntimeError("No response received to query: %s" % address)
E RuntimeError: No response received to query: /live/view/get/selected_clip
client/client.py:153: RuntimeError
=============================================================== short test summary info ================================================================
FAILED tests/test_application.py::test_application_get_version - assert (2 == 2 and 12 == 11)
FAILED tests/test_clip.py::test_clip_property_name - RuntimeError: No response received to query: /live/clip/get/name
FAILED tests/test_clip.py::test_clip_property_color - RuntimeError: No response received to query: /live/clip/get/color
FAILED tests/test_clip.py::test_clip_property_gain - RuntimeError: No response received to query: /live/clip/get/gain
FAILED tests/test_clip.py::test_clip_property_pitch_coarse - RuntimeError: No response received to query: /live/clip/get/pitch_coarse
FAILED tests/test_clip.py::test_clip_property_pitch_fine - RuntimeError: No response received to query: /live/clip/get/pitch_fine
FAILED tests/test_clip.py::test_clip_add_remove_notes - RuntimeError: No response received to query: /live/clip/get/notes
FAILED tests/test_clip.py::test_clip_add_many_notes - RuntimeError: No response received to query: /live/clip/get/notes
FAILED tests/test_clip.py::test_clip_playing_position_listen - RuntimeError: No response received to query: /live/clip/get/playing_position
FAILED tests/test_clip.py::test_clip_listen_lifecycle - RuntimeError: No response received to query: /live/clip/get/name
FAILED tests/test_clip_slot.py::test_clip_slot_has_clip - RuntimeError: No response received to query: /live/clip_slot/get/has_clip
FAILED tests/test_clip_slot.py::test_clip_slot_duplicate - RuntimeError: No response received to query: /live/clip/get/notes
FAILED tests/test_clip_slot.py::test_clip_slot_property_listen - RuntimeError: No response received to query: /live/clip_slot/get/has_clip
FAILED tests/test_song.py::test_song_stop_all_clips - RuntimeError: No response received to query: /live/clip/get/is_playing
FAILED tests/test_song.py::test_song_tracks - assert (85,) == (4,)
FAILED tests/test_song.py::test_song_scenes - assert (2,) == (8,)
FAILED tests/test_song.py::test_song_duplicate_scene - assert (2,) == (8,)
FAILED tests/test_song.py::test_song_undo_redo - assert (2,) == (8,)
FAILED tests/test_track.py::test_track_clips - RuntimeError: No response received to query: /live/track/get/clips/name
FAILED tests/test_track.py::test_track_devices - RuntimeError: No response received to query: /live/track/get/num_devices
FAILED tests/test_track.py::test_track_listen_playing_slot_index - RuntimeError: No response received to query: /live/track/get/playing_slot_index
FAILED tests/test_view.py::test_selected_clip - RuntimeError: No response received to query: /live/view/get/selected_clip
============================================================ 22 failed, 32 passed in 19.50s ============================================================
i hope this helps @ideoforms
Thanks @esaruoho, those errors just indicate that AbletonOSC can't be reached.
If you run sudo lsof -nP -i4UDP | grep 11000
, that will tell you if anything else is listening on that port (the process name being in the first column), which would definitely produce the symptoms you've described.
I've also added an error message to the latest commit of AbletonOSC that will indicate whether it encounters a problem binding to the network port.
thanks for adding the error message!
upon checking, i had both running:
$ sudo lsof -nP -i4UDP | grep 11000
Password:
Live 16844 esaruoho 179u IPv4 0x634db4a0a3942f99 0t0 UDP *:11000
TouchOSC 25783 esaruoho 7u IPv6 0x6d2de584fb3ca3e9 0t0 UDP *:11000
so i closed TouchOSC and only ran Live, and i still got 22 failed and 32 passed.
here's a video of various trials of it. https://www.loom.com/share/910732a274cd470dacfe82df82f74977?sid=458d2b3a-d67d-4915-bb9c-a890562697df
what i noticed, is, that if i have a clip in the session view, then only 18 tests fail - otherwise 22 tests fail.
also, i am wondering about this
FAILED tests/test_application.py::test_application_get_version - assert (2 == 2 and 12 == 11)
is the test trying to see that my version 12 is not version11 and thus fails?
i'm wondering if the test clip stuff fails because the clip is not created first, or..?
is there a specific ableton live project i should load before starting pytests?
@ideoforms
Listening network sockets can sometimes hang around after their process has died. Try restarting your computer, checking that nothing is listening on port 11000, and starting Live again.
Info on preconditions for running unit tests is here.
I've just updated that version test to pass for Live 11 and 12, and all tests are now passing on my end.
Tested and confirmed, closing issue
Hi, is Live 12 support incoming for AbletonOSC?