-
Notifications
You must be signed in to change notification settings - Fork 77
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
/live/clip/get/notes should return all notes #87
Changes from all commits
0c2ff28
31cf307
2cc85ba
02917a9
0f2022b
9a4d707
51e6a5c
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -88,7 +88,9 @@ def clip_callback(params: Tuple[Any]) -> Tuple: | |
"looping", | ||
"loop_start", | ||
"loop_end", | ||
"warping" | ||
"warping", | ||
"start_marker", | ||
"end_marker" | ||
] | ||
|
||
for method in methods: | ||
|
@@ -106,9 +108,53 @@ def clip_callback(params: Tuple[Any]) -> Tuple: | |
self.osc_server.add_handler("/live/clip/set/%s" % prop, | ||
create_clip_callback(self._set_property, prop)) | ||
|
||
def clip_get_notes_helper(clip, params: Tuple[Any] = ()): | ||
if clip is None: | ||
self.logger.info("Trying to get notes from an empty clip") | ||
return () | ||
# Define default values | ||
default_min_from_time = -16000 | ||
default_max_time_span = 1000000 # Ableton clip max length is 24 hours. This is more than enough at over 200bpm | ||
# These numbers were came up after a bunch of try and error. They look arbitrary but it works. | ||
# I have tried different comnination of min and max time including using sys.maxsize, sys.float_info.min, sys.float_info.max | ||
# clip.end_marker, clip_start_marker... but those don't work well. Notes are still missing | ||
# https://github.com/ideoforms/AbletonOSC/issues/86 | ||
|
||
|
||
# Check if parameters are provided in the params tuple | ||
if len(params) == 4: | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should flag an error if There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @ideoforms In the |
||
from_time, from_pitch, time_span, pitch_span = params | ||
else: | ||
from_time, from_pitch, time_span, pitch_span = default_min_from_time, 0, default_max_time_span, 128 | ||
|
||
return clip.get_notes(from_time, from_pitch, time_span, pitch_span) | ||
|
||
def clip_get_notes(clip, params: Tuple[Any] = ()): | ||
notes = clip.get_notes(0, 0, clip.length, 127) | ||
return tuple(item for sublist in notes for item in sublist) | ||
notes = clip_get_notes_helper(clip, params) | ||
return tuple(item for note in notes for item in note) | ||
|
||
def clip_get_notes_range(clip, params: Tuple[Any] = ()): | ||
notes = clip_get_notes_helper(clip, params) | ||
|
||
min_start_time = float('inf') # Initialize with a large value | ||
max_end_time = float('-inf') # Initialize with a small value | ||
min_pitch = float('inf') # Initialize with a large value | ||
max_pitch = float('-inf') # Initialize with a small value | ||
|
||
for note in notes: | ||
pitch, start_time, duration, velocity, mute = note | ||
|
||
# Update smallest start time | ||
min_start_time = min(min_start_time, start_time) | ||
|
||
# Update largest end time (start_time + duration) | ||
max_end_time = max(max_end_time, start_time + duration) | ||
|
||
# Update minimum and maximum pitch | ||
min_pitch = min(min_pitch, pitch) | ||
max_pitch = max(max_pitch, pitch) | ||
|
||
return (min_start_time, max_end_time, min_pitch, max_pitch) | ||
|
||
def clip_add_notes(clip, params: Tuple[Any] = ()): | ||
notes = [] | ||
|
@@ -127,6 +173,7 @@ def clip_remove_notes(clip, params: Tuple[Any] = ()): | |
clip.remove_notes_extended(start_pitch, pitch_span, start_time, time_span) | ||
|
||
self.osc_server.add_handler("/live/clip/get/notes", create_clip_callback(clip_get_notes)) | ||
self.osc_server.add_handler("/live/clip/get/notes_range", create_clip_callback(clip_get_notes_range)) | ||
self.osc_server.add_handler("/live/clip/add/notes", create_clip_callback(clip_add_notes)) | ||
self.osc_server.add_handler("/live/clip/remove/notes", create_clip_callback(clip_remove_notes)) | ||
|
||
|
@@ -208,4 +255,4 @@ def _build_clip_name_cache(self): | |
clip_notes_str = re.sub("[1-9]", "", clip_notes_str) | ||
clip_notes_list = clip_notes_str.split("-") | ||
clip_notes_list = [note_name_to_midi(name) for name in clip_notes_list] | ||
self._clip_notes_cache[-1][-1] = clip_notes_list | ||
self._clip_notes_cache[-1][-1] = clip_notes_list |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think a neater approach here would be just to have the single
/live/clip/get/notes
endpoint, with the final 4 parameters as optional (min_start_time, max_end_time, min_pitch, max_pitch
) - would that work? That would then also have symmetry with/live/clip/remove/notes
.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@ideoforms This api was added as a temporary fix for #88, before PR #89 was made
If there are too many notes,
/live/clip/get/notes
would fail. To address this,/live/clip/get/notes_range
was introduced to determine the range of notes, and later/live/clip/get/notes
could be called with optional parameters [from_time, from_pitch, time_span, pitch_span] for pagination purposes.After merging PR #89, this API may no longer be required. However, it would still be beneficial to retain it for those who prefer to implement pagination.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks, will have another think on this once #89 is merged 👍