livepilot 1.8.3 → 1.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,5 +1,5 @@
1
1
  """
2
- LivePilot - Track domain handlers (14 commands).
2
+ LivePilot - Track domain handlers (17 commands).
3
3
  """
4
4
 
5
5
  from .router import register
@@ -101,7 +101,8 @@ def get_track_info(song, params):
101
101
  result["arm"] = None
102
102
  result["has_midi_input"] = None
103
103
  result["has_audio_input"] = None
104
- result["is_return_track"] = True
104
+ result["is_return_track"] = track_index != -1000
105
+ result["is_master_track"] = track_index == -1000
105
106
 
106
107
  return result
107
108
 
@@ -266,3 +267,73 @@ def set_track_input_monitoring(song, params):
266
267
  "index": track_index,
267
268
  "monitoring_state": track.current_monitoring_state,
268
269
  }
270
+
271
+
272
+ # ── Freeze / Flatten ────────────────────────────────────────────────────
273
+
274
+
275
+ @register("get_freeze_status")
276
+ def get_freeze_status(song, params):
277
+ """Return freeze state for a track."""
278
+ track_index = int(params["track_index"])
279
+ track = get_track(song, track_index)
280
+ return {
281
+ "track_index": track_index,
282
+ "is_frozen": track.is_frozen,
283
+ }
284
+
285
+
286
+ @register("freeze_track")
287
+ def freeze_track(song, params):
288
+ """Freeze a track — render all devices to audio for CPU savings.
289
+
290
+ Freeze is async in Ableton — this call initiates it and returns
291
+ immediately. Use get_freeze_status to poll for completion.
292
+ """
293
+ track_index = int(params["track_index"])
294
+ track = get_track(song, track_index)
295
+ if track.is_frozen:
296
+ return {
297
+ "track_index": track_index,
298
+ "is_frozen": True,
299
+ "note": "Track is already frozen",
300
+ }
301
+ # In Live 12, freeze is a track method accessible from ControlSurface
302
+ try:
303
+ track.freeze()
304
+ except AttributeError:
305
+ raise ValueError(
306
+ "freeze() not available on this track type. "
307
+ "Only MIDI and audio tracks with devices can be frozen."
308
+ )
309
+ return {
310
+ "track_index": track_index,
311
+ "freezing": True,
312
+ "note": "Freeze initiated. Poll get_freeze_status to check completion.",
313
+ }
314
+
315
+
316
+ @register("flatten_track")
317
+ def flatten_track(song, params):
318
+ """Flatten a frozen track — commits rendered audio permanently.
319
+
320
+ Destructive operation. The track must already be frozen.
321
+ Wrapped in undo step so it can be reverted.
322
+ """
323
+ track_index = int(params["track_index"])
324
+ track = get_track(song, track_index)
325
+ if not track.is_frozen:
326
+ raise ValueError(
327
+ "Track %d is not frozen. Freeze it first with freeze_track."
328
+ % track_index
329
+ )
330
+ song.begin_undo_step()
331
+ try:
332
+ # flatten() is a method on the track, not the song
333
+ track.flatten()
334
+ finally:
335
+ song.end_undo_step()
336
+ return {
337
+ "track_index": track_index,
338
+ "flattened": True,
339
+ }