"""Status panel additions to AbletonOSC (installed by tools/abletonosc/install.sh on the Tracks Mac). /live/statuspanel/move_note 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 (, , , ). 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)