Page 1 of 5
Proposition: solution for sysex...SOLVED!!!
Posted: Thu Mar 11, 2010 7:35 am
by amounra93
I'm looking for information about how the API hooks are inserted into the Remote Scripts that are API-reachable (e.g. Launchpad and APC40). If these are purely within the scripts themselves (and there are no preventative measures hardcoded into Live preventing non-Ableton Remote Scripts from functioning with the API) then I don't see a reason that we shouldn't be able to send and receive sysex messages by creating a rather simple Remote Script and sending the data from Live through the API to the Remote Script (and thus to whatever MIDI port is connected to that Remote Script).
Any ideas? I'm not terribly Python savvy, but I know some of you out there are....
Re: Proposition: solution for sysex
Posted: Thu Mar 11, 2010 8:11 am
by ST8
I've been thinking about this, midi remote scripts can definitely send sysex, its how the lcds are updated on the remote sl and other control surfaces. So it makes sense that you could write a dummy script that just sends sysex. Problem is how to communicate with it from maxforlive? Not having m4l i dont know what the control_surfaces part of the api actually provides. Can you hook any function from the control script, or only certain ones?
Re: Proposition: solution for sysex
Posted: Thu Mar 11, 2010 9:02 am
by amounra93
It seems like all the functionality is implemented within the "Good" scripts (APC40, LP). But the RemoteSL and Mackie control (and anything that uses lcd's that I can think of) aren't available to the API in M4L. I've checked the decompyled scripts from the current build (all those below 4k, anyway, which doesn't allow one to see the real guts of what's going on, but actually DOES mirror the callbacks I'm getting through the M4L API for class descriptors and whatnot), and I don't see anything specifically different about them from the old scripts that would allow the hooks. Then again, like I said, I'm not that experienced with Python, so I don't necessarily know what I'm looking at (even when I think I do).
It seems like a modification of a simple User Script might do the trick. One could simply send the data byte at a time, through it into an array, then compile it in the Python script to be sent out as Sysex when the last byte is recieved (I'm assuming the API calls would be fast enough to deal with this...I could be wrong, though). With the Launchpad, for instance, access to "control_surfaces controls" allows calls to the device so that one can illumine the buttons at different intensities. Same with buttons and dials on the APC. Modification of an existing script should allow one to simply send to that particular hook and then reroute the data within the python script to be sent out as sysex instead.
ST8, you'd be the one to do it....too bad you don't have a copy of M4L. It will take me 2 weeks to figure out everything I need to know in order to make this happen LOL. Still, it seems like it might be worth the effort. LCD support is the one thing I don't have access to through Live, and its ticking me off. Everything else I need to do I'm still doing directly within M4L, but I still have to run a pesky little Max Standalone to access the LCD on my Controller.
I just dl'd the newest Live beta with the new Novation scripts that support the SLMKII. I was hoping that they had made them hookable like the other scripts, but, alas, no love.....<sigh>....that would have been a problem solved and move on.
There's a post on here somewhere with all the hooks for the APC40 listed....
Re: Proposition: solution for sysex
Posted: Thu Mar 11, 2010 9:26 am
by ST8
Do you have the post about the apc40, cant find it doing a quick search? I think somewhere in _Framework functions must be made available to the m4l api.
As far as the live object model goes you're looking for something like:
control_surface -> PhysicalDisplayElement -> display_message
display_message if implemented in your particular script should update the display with a string
Reading:
http://forum.ableton.com/viewtopic.php? ... ol+surface
it seems to me that you should be able to directly access the python functions.
Can you getinfo on the RemoteSL and see what children it has, and then get info on a display component if there is one?
you need to find the id of the physicaldisplayelement and try calling display_message from live.object?
Re: Proposition: solution for sysex
Posted: Thu Mar 11, 2010 6:57 pm
by amounra93
I've been looking for that post and can't find it either right now...I'll have more time on Saturday to dig into this, as I'm going on vacation for a week and plan on doing a lot of poking and coding (lol that's vacation for me)...
The Remote25SL doesn't show up in the M4L API. You can't get any info on it through M4L at all, that's the problem. The only way to do the thing I'm proposing is to rewrite one of the standard scripts, and pull out the pertinent sections from the old RMSL scripts (that are decompyled) in order to facilitate sysex handling in the new hot-rodded script.
Normally when you have a RemoteScript installed in Live, you can access it by calling the "control_surfaces.getcount" or something like that (I've been doing all my M4L coding in JS lately, so my methods are a little different from what most people are doing with M4L, I think). If you only have a RMSL selected in MIDI setup, you get 0 in return, which means M4L isn't even seeing the RMSL script in the LOM. Same with all of the other control surfaces that utilize sysex. Maybe the new M-Audio keyboards use sysex, and I think they are accessible. But I haven't ever got my hands on one of them, so I don't really know how they work. Even if so, there are no decompyled scripts to the newer hardware that would allow rewriting of the pertinent code in Python.
I'll keep poking around for that post about the APC40. It had a comparison list of new additions to the LOM for that particular script between two different versions of Live.
Anyone else know what I'm talking about and where it might be? I just saw it the other day when I was searching for something else....grrrrrr.
Re: Proposition: solution for sysex
Posted: Fri Mar 12, 2010 5:52 am
by 3dot...
ST8 wrote:
you need to find the id of the physicaldisplayelement and try calling display_message from live.object?
neither the sl or the mackie are accessible from API..yet another bummer
Re: Proposition: solution for sysex
Posted: Thu Mar 18, 2010 4:16 pm
by Hanz_Petrov
The central base class for the Framework MIDI remote scripts is
ControlSurface - this class has a
receive_midi method, which the newer scripts use:
Code: Select all
def receive_midi(self, midi_bytes):
""" Live -> Script
MIDI messages are only received through this function, when explicitly
forwarded in 'build_midi_map'.
"""
assert (midi_bytes != None)
assert isinstance(midi_bytes, tuple)
self.set_suppress_rebuild_requests(True)
if (len(midi_bytes) is 3):
msg_type = (midi_bytes[0] & 240)
forwarding_key = [midi_bytes[0]]
if (msg_type is not MIDI_PB_TYPE):
forwarding_key.append(midi_bytes[1])
if (tuple(forwarding_key) in self._forwarding_registry.keys()):
recipient = self._forwarding_registry[tuple(forwarding_key)]
if (recipient != None):
recipient.receive_value(midi_bytes[2])
else:
debug_print(('Got unknown message: ' + str(midi_bytes)))
else:
self.handle_sysex(midi_bytes)
self.set_suppress_rebuild_requests(False)
ControlSurface also has a
handle_sysex method, which as you can see, is meant to be overridden:
Code: Select all
def handle_sysex(self, midi_bytes):
debug_print('handle_sysex is abstract. Forgot to override it?')
assert False
The newer scripts, which are based on the Framework classes, seem to use these methods for sysex. Here's an example from the AxiomPro script:
Code: Select all
def handle_sysex(self, midi_bytes):
if (midi_bytes[0:-2] == (SYSEX_START + (32))):
msg_id_byte = midi_bytes[-2]
is_setup_response = (msg_id_byte in (46,
38))
has_sliders = (msg_id_byte == 46)
if is_setup_response:
if self._waiting_for_first_response:
self._waiting_for_first_response = False
self._display_on_button.send_value(0)
for component in self._components:
component.set_enabled(True)
self._display_on_button.send_value(127)
self._send_midi((SYSEX_START + (16,
247)))
self._send_midi((SYSEX_START + (17,3,0,1,65,98,108, # string truncated here for brevity
247)))
self._mixer_encoder_modes.set_show_volume_page((not has_sliders))
for display in self._displays:
display.set_block_messages(False)
self.schedule_message(25, self._refresh_displays)
elif (msg_id_byte == 43):
self._send_midi((SYSEX_START + (16,
247)))
for display in self._displays:
if (display is self._track_display):
display.update()
else:
display.set_block_messages(True)
Don't know if this helps or not, nor how to hook from Max (and I'm not sure that this is the right place to post python code ;), but anyway...
Hanz
Re: Proposition: solution for sysex
Posted: Thu Mar 18, 2010 6:13 pm
by hoffman2k
Maybe a dumb question since I know we used these scripts in the past to send sysex to a Lemur.
Knowing what you figured out here, could somebody use that to pass the data to UDP? Or is there still some information missing?
Maybe this is just me dreaming, but passing all incoming midibytes to a UDP port, wouldn't that be the key to building a midi driver that doesn't require a max runtime app?
Re: Proposition: solution for sysex
Posted: Thu Mar 18, 2010 9:16 pm
by amounra93
@hoffman2k: Not sure why you want to pass it to UDP, since you can do that directly within M4L via UDPSend.
@Hanz: Thanks for joining in the discussion. The info I got from your site coupled with your last post is exactly the sort of thing I've been looking for. I haven't created any successful Python scripts before, but I was probably exceeding my grasp with what I was atttempting to do (in all too casual a fashion to begin with).
I've been looking at the 7.18 py's for the axiom and I don't see anything in those scripts that make them explicitly addressable from M4L. Still, they are accessible...even though I think that some of the methods listed (e.g. display_message, set_message_parts) are not intended to be used from a live.object input. Anyway, I can't figure out the proper syntax for using these calls, if anyone has any ideas? Trying to access them gives a "invalid syntax" complaint, but I can't figure out how to format the arguments for them, even after looking at the py's themselves.
Re: Proposition: solution for sysex
Posted: Fri Mar 19, 2010 2:57 am
by Hanz_Petrov
@amounra93: I'm not sure what makes a script accessible to M4L (let alone addressable). Perhaps M4L polls for ControlSurface objects? In any event, you might want to try setting up a very simple Framework controller script, with one or two simple methods, then see if you can get M4L to talk to it. To be honest, I've only just begun looking at M4L, so I'm on a learning curve here too. ;)
Hanz
Re: Proposition: solution for sysex
Posted: Fri Mar 19, 2010 4:03 am
by hoffman2k
amounra93 wrote:@hoffman2k: Not sure why you want to pass it to UDP, since you can do that directly within M4L via UDPSend.
You can't since there are no MIDI drivers. And regular MIDI Tracks filter out almost all the actual MIDI.
Re: Proposition: solution for sysex
Posted: Fri Mar 19, 2010 6:13 am
by amounra93
@hoffman2k:
What are your intentions? [udpsend] and [udpreceive] both work fine when embedded in a M4L patch. True, there is no MIDI connectivity outside of Live's built in drivers, but UDP works fine. If you are trying to build a patch that connects to something OSC based, there is no problem (I think you know this already and we are talking about two different things, which is why I'm asking for clarification).
@Hanz:
I just read somewhere recently in these posts someone who was working with Python scripts (the Generic one, to be exact) and said that certain controls became addressable from within M4L via the API when he started naming functions and providing them with arguments. I never have any luck with the search engine here....I've been looking for an hour and still can't locate what I was reading.
Re: Proposition: solution for sysex
Posted: Fri Mar 19, 2010 1:49 pm
by hoffman2k
Not sure how you're missing this as its related to your original post:
Unfiltered MIDI > Remote Script > UDP
UDP > Remote Script > Unfiltered MIDI
A remote script has a MIDI input and output. Couldn't a script be made that sends/receives unfiltered MIDI? This would eliminate most workarounds that require a 3rd party MIDI translator (like people are using a runtime bridge now to send unfiltered MIDI to a device).
Re: Proposition: solution for sysex
Posted: Fri Mar 19, 2010 2:16 pm
by ST8
@hofmann2k
that is totally doable, i'll try and sort out a test script over the weekend that just pipes raw midi too and from a udp socket,
Re: Proposition: solution for sysex
Posted: Fri Mar 19, 2010 2:17 pm
by 3dot...
..a simple 'pass sysex' button for each controller would be so easy to implement..
packing/unpacking messages for osc is a bummer.. waste of ms..
and running the max runtime for use with live kinda beats the purpose of the whole thing ..
but I believe it would change..sysex is very important to communicate with musical gear ..
maybe next version?