37 lines
1.7 KiB
Python
37 lines
1.7 KiB
Python
"""Status panel additions to AbletonOSC (installed by tools/abletonosc/install.sh on the Tracks Mac).
|
|||
|
|
|
||
|
|
/live/statuspanel/move_note <track name> <beat> <pitch> <new beat>
|
||
|
|
Moves the note of `pitch` that starts at arrangement `beat` on the arrangement MIDI clip of the track
|
||
|
|
called `track name` so it starts at `new beat`, keeping where it ends (the next cue is not touched).
|
||
|
|
Answers (<track name>, <beat>, <pitch>, <moved: 0 or 1>). Undo in Live (Cmd+Z) puts it back.
|
||
|
|
"""
|
||
|
|
import logging
|
||
|
|
|
||
|
|
logger = logging.getLogger("abletonosc")
|
||
|
|
|
||
|
|
|
||
|
|
def register(handler):
|
||
|
|
def move_note(params):
|
||
|
|
song = handler.song
|
||
|
|
name, beat, pitch, new = str(params[0]), float(params[1]), int(params[2]), float(params[3])
|
||
|
|
track = next((t for t in song.tracks if t.name.strip().upper() == name.strip().upper() and t.has_midi_input), None)
|
||
|
|
moved = 0
|
||
|
|
for clip in (track.arrangement_clips if track else []):
|
||
|
|
if not (clip.start_time - 1e-6 <= beat < clip.end_time):
|
||
|
|
continue
|
||
|
|
zero = clip.start_time - (clip.loop_start if clip.looping else clip.start_marker)
|
||
|
|
local, new_local = beat - zero, new - zero
|
||
|
|
notes = clip.get_notes_extended(pitch, 1, local - 0.002, 0.004)
|
||
|
|
for n in notes:
|
||
|
|
end = n.start_time + n.duration
|
||
|
|
if new_local < end:
|
||
|
|
n.start_time, n.duration = new_local, end - new_local
|
||
|
|
moved += 1
|
||
|
|
if moved:
|
||
|
|
clip.apply_note_modifications(notes)
|
||
|
|
break
|
||
|
|
logger.info("statuspanel: %s note %d at %s -> %s: %d moved", name, pitch, beat, new, moved)
|
||
|
|
return name, beat, pitch, moved
|
||
|
|
|
||
|
|
handler.osc_server.add_handler("/live/statuspanel/move_note", move_note)
|