File not found: /tmp/abletonosc-song-structure.json
I’ve run into a few problems trying to run the example from the README, all based around a missing file which seems like it should be getting generated by the live set. I don’t know if AbletonOSC is responsible for this or not, but I’m getting nowhere trying to resolve this issue with no prior knowledge.
I installed pylive via pip3 install pylive. When I try to run the example script from the README, I get the following error:
> python3 test.py
Traceback (most recent call last):
File “/…/test.py", line 10, in <module>
set = live.Set(scan=True)
File "/Library/Frameworks/Python.framework/Versions/3.13/lib/python3.13/site-packages/live/classes/set.py", line 92, in __init__
self.scan()
~~~~~~~~~^^
File "/Library/Frameworks/Python.framework/Versions/3.13/lib/python3.13/site-packages/live/classes/set.py", line 135, in scan
self._scan_via_file()
~~~~~~~~~~~~~~~~~~~^^
File "/Library/Frameworks/Python.framework/Versions/3.13/lib/python3.13/site-packages/live/classes/set.py", line 289, in _scan_via_file
with open(json_path, "r") as fd:
~~~~^^^^^^^^^^^^^^^^
FileNotFoundError: [Errno 2] No such file or directory: '/tmp/abletonosc-song-structure.json'
If I manually create the missing file:
> touch /tmp/abletonosc-song-structure.json
> python3 test.py
Traceback (most recent call last):
File “/…/test.py", line 10, in <module>
set = live.Set(scan=True)
File "/Library/Frameworks/Python.framework/Versions/3.13/lib/python3.13/site-packages/live/classes/set.py", line 92, in __init__
self.scan()
~~~~~~~~~^^
File "/Library/Frameworks/Python.framework/Versions/3.13/lib/python3.13/site-packages/live/classes/set.py", line 135, in scan
self._scan_via_file()
~~~~~~~~~~~~~~~~~~~^^
File "/Library/Frameworks/Python.framework/Versions/3.13/lib/python3.13/site-packages/live/classes/set.py", line 290, in _scan_via_file
data = json.load(fd)
File "/Library/Frameworks/Python.framework/Versions/3.13/lib/python3.13/json/__init__.py", line 293, in load
return loads(fp.read(),
cls=cls, object_hook=object_hook,
parse_float=parse_float, parse_int=parse_int,
parse_constant=parse_constant, object_pairs_hook=object_pairs_hook, **kw)
File "/Library/Frameworks/Python.framework/Versions/3.13/lib/python3.13/json/__init__.py", line 346, in loads
return _default_decoder.decode(s)
~~~~~~~~~~~~~~~~~~~~~~~^^^
File "/Library/Frameworks/Python.framework/Versions/3.13/lib/python3.13/json/decoder.py", line 345, in decode
obj, end = self.raw_decode(s, idx=_w(s, 0).end())
~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^
File "/Library/Frameworks/Python.framework/Versions/3.13/lib/python3.13/json/decoder.py", line 363, in raw_decode
raise JSONDecodeError("Expecting value", s, err.value) from None
json.decoder.JSONDecodeError: Expecting value: line 1 column 1 (char 0)
Populating the JSON file with an empty object ({}) gives me this error:
> python3 test.py
Traceback (most recent call last):
File “/../test.py", line 10, in <module>
set = live.Set(scan=True)
File "/Library/Frameworks/Python.framework/Versions/3.13/lib/python3.13/site-packages/live/classes/set.py", line 92, in __init__
self.scan()
~~~~~~~~~^^
File "/Library/Frameworks/Python.framework/Versions/3.13/lib/python3.13/site-packages/live/classes/set.py", line 135, in scan
self._scan_via_file()
~~~~~~~~~~~~~~~~~~~^^
File "/Library/Frameworks/Python.framework/Versions/3.13/lib/python3.13/site-packages/live/classes/set.py", line 291, in _scan_via_file
tracks = data["tracks"]
~~~~^^^^^^^^^^
KeyError: 'tracks'
And adding an empty tracks array to the JSON file gives me this error:
{
"tracks": []
}
> python3 test.py
Traceback (most recent call last):
File “/../test.py", line 16, in <module>
track = set.tracks[0]
~~~~~~~~~~^^^
IndexError: list index out of range
How curious. What version of macOS are you running? I assume you have cloned the latest AbletonOSC from GitHub?
Could you open up a Python 3 interpreter, run the below, and let me know what the output is?
import os, tempfile
os.environ["TMPDIR"] = ""
print(tempfile.gettempdir())
AbletonOSC should indeed write to /tmp/abletonosc-song-structure.json, but it looks like it's not being created correctly for some reason...
What version of macOS are you running?
Sonoma 14.3.1
I assume you have cloned the latest
AbletonOSCfrom GitHub?
Correct.
print(tempfile.gettempdir())
/tmp
I have validated that AbletonOSC is installed correctly by running run-console.py and issuing some commands. Works fine. Additionally, I can run commands that don’t require the set to be scanned. I’ve been able to change the tempo and start/stop playback using both the pylive API and sending OSC directly with set.live.cmd()
I don’t know how important this is. Calling /live/song/export/structure in the OSC console seems to give the result that set.py expects.
> python3 run-console.py
Scripts/AbletonOSC 2.6.10p210
AbletonOSC command console with tab completion
Usage: /live/osc/command [params]
Type 'quit' or 'exit' to exit the console.
>>> /live/song/export/structure
1
Yes, that's what's odd: if /live/song/export/structure returns 1, it should mean that the data file (/tmp/abletonosc-song-structure.json) has been created successfully. I'm wracking my brains about why this might not happen.
If you delete the current /tmp/abletonosc-song-structure.json and run /live/song/export/structure from the console, can you check if the file is created?
If not, more logging may be needed.... Could you add the below line to abletonosc/song.py around line 214 (just before the return (1,) line), restart Live, trigger an export, and let me know if an unexpected location is logged in the abletonosc log file (~/Music/Ableton/User Library/Remote Scripts/AbletonOSC/logs/abletonosc.log)?
self.logger.warning("Exported song structure to directory %s" % tempfile.gettempdir())
Or indeed if any other unexpected things are appearing in abletonosc.log....
If you delete the current /tmp/abletonosc-song-structure.json and run /live/song/export/structure from the console, can you check if the file is created?
Forgot to mention, that’s what I was hoping for when I ran /live/song/export/structure from the console before. Ran it again just now and same result.
Or indeed if any other unexpected things are appearing in
abletonosc.log.
I checked this first before adding more logging. Tailed the log and ran /live/song/export/structure. Nothing was logged.
more logging may be needed
Added the logging line, restarted Ableton and tailed the log.
[WARNING] Exported song structure to directory /var/folders/f8/6lwj_bmd1rj3wx7gb7f4s35h0000gn/T
Found it!
> pwd
/var/folders/f8/6lwj_bmd1rj3wx7gb7f4s35h0000gn/T
> cat abletonosc-song-structure.json
{"tracks": [{"index": 0, "name": "Click Track", "is_foldable": false, "group_track": null, "clips": [{"index": 0, "name": "", "length": 6.0}, {"index": 1, "name": "", "length": 156.0}, {"index": 2, "name": "", "length": 12.0}, {"index": 3, "name": "", "length": 48.0}, {"index": 4, "name": "", "length": 6.0}, {"index": 5, "name": "", "length": 36.0}, {"index": 6, "name": "", "length": 72.0}, {"index": 7, "name": "", "length": 6.0}, {"index": 8, "name": "", "length": 36.0}, {"index": 9, "name": "", "length": 42.0}, {"index": 10, "name": "", "length": 12.0}, {"index": 11, "name": "", "length": 48.0}, {"index": 12, "name": "", "length": 6.0}, {"index": 13, "name": "", "length": 36.0}, {"index": 14, "name": "", "length": 72.0}, {"index": 15, "name": "", "length": 6.0}, {"index": 16, "name": "", "length": 64.0}, {"index": 17, "name": "", "length": 32.0}, {"index": 18, "name": "", "length": 16.0}, {"index": 21, "name": "", "length": 626.923399777306}, {"index": 26, "name": "", "length": 840.89158367674}, {"index": 32, "name": "", "length": 571.7780370670996}, {"index": 38, "name": "", "length": 872.5}], "devices": [{"class_name": "DrumGroupDevice", "type": 1, "name": "Drum Rack", "parameters": [{"name": "Device On", "value": 1.0, "min": 0.0, "max": 1.0, "is_quantized": true}, {"name": "Macro 1", "value": 0.0, "min": 0.0, "max": 127.0, "is_quantized": false}, {"name": "Macro 2", "value": 0.0, "min": 0.0, "max": 127.0, "is_quantized": false}, {"name": "Macro 3", "value": 0.0, "min": 0.0, "max": 127.0, "is_quantized": false}, {"name": "Macro 4", "value": 0.0, "min": 0.0, "max": 127.0, "is_quantized": false}, {"name": "Macro 5", "value": 0.0, "min": 0.0, "max": 127.0, "is_quantized": false}, {"name": "Macro 6", "value": 0.0, "min": 0.0, "max": 127.0, "is_quantized": false}, {"name": "Macro 7", "value": 0.0, "min": 0.0, "max": 127.0, "is_quantized": false}, {"name": "Macro 8", "value": 0.0, "min": 0.0, "max": 127.0, "is_quantized": false}, {"name": "Macro 9", "value": 0.0, "min": 0.0, "max": 127.0, "is_quantized": false}, {"name": "Macro 10", "value": 0.0, "min": 0.0, "max": 127.0, "is_quantized": false}, {"name": "Macro 11", "value": 0.0, "min": 0.0, "max": 127.0, "is_quantized": false}, {"name": "Macro 12", "value": 0.0, "min": 0.0, "max": 127.0, "is_quantized": false}, {"name": "Macro 13", "value": 0.0, "min": 0.0, "max": 127.0, "is_quantized": false}, {"name": "Macro 14", "value": 0.0, "min": 0.0, "max": 127.0, "is_quantized": false}, {"name": "Macro 15", "value": 0.0, "min": 0.0, "max": 127.0, "is_quantized": false}, {"name": "Macro 16", "value": 0.0, "min": 0.0, "max": 127.0, "is_quantized": false}]}, {"class_name": "ProxyAudioEffectDevice", "type": 2, "name": "Ext. Audio Effect", "parameters": [{"name": "Device On", "value": 0.0, "min": 0.0, "max": 1.0, "is_quantized": true}, {"name": "Dry/Wet", "value": 1.0, "min": 0.0, "max": 1.0, "is_quantized": false}, {"name": "Output Gain", "value": 0.4000000059604645, "min": 0.0, "max": 1.0, "is_quantized": false}, {"name": "Input Gain", "value": 0.4000000059604645, "min": 0.0, "max": 1.0, "is_quantized": false}]}]}, {"index": 1, "name": "Sections +CC", "is_foldable": false, "group_track": null, "clips": [], "devices": []}, {"index": 2, "name": "3-MIDI", "is_foldable": false, "group_track": null, "clips": [], "devices": []}, {"index": 3, "name": "4-Audio", "is_foldable": false, "group_track": null, "clips": [], "devices": []}]}
Aaaaand here’s why:
> echo $TMPDIR
/var/folders/f8/6lwj_bmd1rj3wx7gb7f4s35h0000gn/T/
I patched python3.13/site-packages/live/classes/set.py,
ln 284: tempdir = os.environ.get("TMPDIR")
With that change, the demo script ran without error and was able to talk to AbletonOSC.
OK, great find! But what I'm confused about is that TMPDIR is set to null on the line immediately before tempfile.gettempdir(), which should cause gettempdir() to fall back on using /tmp.
I wonder.... do you have any other MIDI control scripts enabled?
gettempdir() uses one temp dir for the entirety of the process, so it's possible that if something else has called gettempdir(), it has settled on (e.g.) /var/folders/f8/6lwj_bmd1rj3wx7gb7f4s35h0000gn/T/, which then persists throughout Live's lifetime.
Whether or not that is the case, I think a good fix here is to change the signature of /live/song/export/structure to return the path of the resultant .json file, which can then be used by clients like pylive to query the file.
I wonder.... do you have any other MIDI control scripts enabled?
Hmm… yes. ClyphX Pro. I could see that being a conflict. So let’s disable it.
First, I unpatched set.py and re-ran the demo script.
> python3 test.py
Traceback (most recent call last):
File “/…/test.py", line 11, in <module>
set = live.Set(scan=True)
File "/Library/Frameworks/Python.framework/Versions/3.13/lib/python3.13/site-packages/live/classes/set.py", line 92, in __init__
self.scan()
~~~~~~~~~^^
File "/Library/Frameworks/Python.framework/Versions/3.13/lib/python3.13/site-packages/live/classes/set.py", line 135, in scan
self._scan_via_file()
~~~~~~~~~~~~~~~~~~~^^
File "/Library/Frameworks/Python.framework/Versions/3.13/lib/python3.13/site-packages/live/classes/set.py", line 289, in _scan_via_file
with open(json_path, "r") as fd:
~~~~^^^^^^^^^^^^^^^^
FileNotFoundError: [Errno 2] No such file or directory: '/tmp/abletonosc-song-structure.json’
Cool, expected. I then disabled ClyphX Pro and re-ran.
Same error.
I disabled all other vendor hardware control scripts leaving only AbletonOSC enabled.
Same error.
What version of Ableton Live are you running? It's possible it's something internal to Live that has changed in a recent version..?
If that's not it.... it might be that we never discover the root cause :) I'll implement the fix nevertheless, as it's ultimately a more elegant and robust solution anyhow.
What version of Ableton Live are you running?
v12.1.5
it might be that we never discover the root cause :) I'll implement the fix nevertheless, as it's ultimately a more elegant and robust solution anyhow.
Agreed, it’s a bummer we don’t get to learn something from this… however I am already at peak information overload on the task I’m actually trying to accomplish. I’ll close this since this workaround does work for now, and there is a more permanent fix incoming.
Additionally, I was able to confirm that pylive is able to move my project forward, which is really exciting! I’ve been parked on it all week.
Thanks for the quick response @ideoforms !
(Reopening to remind me to fix this...)