LOM.Navigator v1.0 - With *full* control surface support.

Learn about building and using Max for Live devices.
amounra93
Posts: 432
Joined: Sat Jan 24, 2009 8:16 pm
Location: Arcata, CA
Contact:

Re: LOM.Navigator v1.0 - With *full* control surface support.

Post by amounra93 » Thu Sep 23, 2010 7:07 pm

@ Surreal: yeah...I'm in the same boat. I'm just getting around to the Python stuff, even though I've been banging my head on the LOM for the c_s scripts for a while.

I'm only saying "suddenly" because I see a flood of posts in different areas with people talking about this specifically. I think we have all wanted (and expected) better access to this functionality since the beginning, and a lot of us have been working towards that end for a while. These tools have been available in some form or another since the beginning, though. I'd say Hanz's blog is the single greatest leap that has been made in this area....you can either learn Python or not, but knowing as much as you can about it is ONLY going to make all of this API stuff easier, since all of the API integration is built on top of it.

Same boat: I've spent a lot of time emulating functions that the _Framework scripts and LiveOSC do easily, from within m4l, only to find those processes are slower/buggier. So now I'm going back the other way somewhat. Hehe...kinda silly.
http://www.aumhaa.com for Monomod and other m4l goodies.

Hanz_Petrov
Posts: 119
Joined: Sat Feb 06, 2010 2:39 pm
Contact:

Re: LOM.Navigator v1.0 - With *full* control surface support.

Post by Hanz_Petrov » Thu Sep 23, 2010 10:09 pm

amounra93 wrote:@ Hanz: I'm still having trouble wrapping my head around how the _Framework classes handle add_value_listener methods; I can add them manually myself, no problem, but can't figure out how to hijack the listeners that are already created by the scripts. It seems like the only component with a listenable property is the ModeSelectorComponent, and I'm obviously just missing something about how it operates.

I think what can be done here is to create a super-class to wrap the original c_s class in, and define some basic utility functions inside that class that aren't necessary to the _Framework stuff, but can operate on top of it. Basic listener functions to be initiated after the main c_s class is constructed, some tuple_wrappers, the sysex_out stuff we already figured out for talking directly to the control surface (mainly for control_surfaces with LCD's or other unordinaries), and whatever else might be needed.

I don't even know if that is possible...theoretically, I think it is though. If it works like that, there would be no need to modify any of the existing _Framework docs or compiled scripts...all the additional functionality could be attained in the top Class, and other sub-classes could be added to deal with API stuff that's not included in the _Framework already. Thoughts?
Actually, the _MxDCore scripts might be a good place to start. These are the remote scripts which Max for Live uses to interact with the LiveAPI, and also make use of the _Framework classes. The MxDCore docstring reads as follows: " Central class for the Max-integration ". There is also an MxDUtils module, which includes a couple of interesting functions:

Code: Select all

class TupleWrapper(object):
	__doc__ = ' Wrapper class for the access to volatile lists and tuples in the Python API '

class StringHandler(object):
	__doc__ = ' Class that can parse incoming strings and format outgoing strings '
Might be interesting to try renaming the MxDCore file, create a replacement which imports from the original, then override and/or add good stuff as required. "Wrap the wrapper" as it were.

Best,

Hanz

PS: add_value_listener is a NotifyingControlElement method which simply registers a callback. As the docstring says, this method "Registers a callback that is triggerd[sic] when a message is received." Its counterpart is remove_value_listener, which "Unregisters a forwarding callback." Not sure what you mean by "hijack the listeners", however. What are you trying to accomplish?
http://remotescripts.blogspot.com/ - an introduction to the Framework classes

amounra93
Posts: 432
Joined: Sat Jan 24, 2009 8:16 pm
Location: Arcata, CA
Contact:

Re: LOM.Navigator v1.0 - With *full* control surface support.

Post by amounra93 » Thu Sep 23, 2010 10:58 pm

It seems like I have a copy of that stuff...that is probably a good place to start.

The "add_value_listener" thing: this is how Live knows to trigger a function whenever an internal mapped value changes that the notifying controller is mapped to (or something like that). I'm trying to find a way to link another callback to this same dictionary, so that we can also receive notification to an observable property in m4l.

I'm basically trying to determine what makes the ModeSelectorComponent differ in its ability to send a change notification when its _mode_index changes, while other similar components do not have observable properties.

Practical application: iPad w/TouchOSC. I would prefer to create a Python script as the framework for the iPad controller, but still be able to manage the interaction with that script from m4l. Its currently impossible to change properties of Live's functionality via a c_s python script from backend of the script. You can send a MIDI value to change something in live (e.g. Volume or Pan) from outside live, but if you try to use receive_midi in the Python script, it will change the current value of the controller in the script, but will not affect the associated control in Live. Does that make any sense?

EDIT:: actually, they're kind of completely different issues, but in the end they relate to the same thing. If we can get updates from the scripts regarding the current state of their associated controls, we will be better able to utilize the scripts in a creative way. Thus "hijacking" the listener dictionary already created by the components/controls and triggering a function that changes a listenable property (by listenable, I mean on that we can observe in m4l).

Vice versa, we need to be able to set those same values from m4l, which seems even harder to do. I mean, its easy to simply write a new function:

Code: Select all

	def to_encoder(self, num, val):
		rv=int(val*127)
		self._device._parameter_controls[num].receive_value(rv)
		p = self._device._parameter_controls[num]._parameter_to_map_to
		newval = (val * (p.max - p.min)) + p.min
		p.value = newval
(credit to ST8 for some of that)

But I'm trying to figure out a way to do this with methods already provided in the _Framework.
Last edited by amounra93 on Thu Sep 23, 2010 11:08 pm, edited 1 time in total.
http://www.aumhaa.com for Monomod and other m4l goodies.

Hanz_Petrov
Posts: 119
Joined: Sat Feb 06, 2010 2:39 pm
Contact:

Re: LOM.Navigator v1.0 - With *full* control surface support.

Post by Hanz_Petrov » Fri Sep 24, 2010 1:31 am

amounra93 wrote:The "add_value_listener" thing: this is how Live knows to trigger a function whenever an internal mapped value changes that the notifying controller is mapped to (or something like that). I'm trying to find a way to link another callback to this same dictionary, so that we can also receive notification to an observable property in m4l.

I'm basically trying to determine what makes the ModeSelectorComponent differ in its ability to send a change notification when its _mode_index changes, while other similar components do not have observable properties.

Practical application: iPad w/TouchOSC. I would prefer to create a Python script as the framework for the iPad controller, but still be able to manage the interaction with that script from m4l. Its currently impossible to change properties of Live's functionality via a c_s python script from backend of the script. You can send a MIDI value to change something in live (e.g. Volume or Pan) from outside live, but if you try to use receive_midi in the Python script, it will change the current value of the controller in the script, but will not affect the associated control in Live. Does that make any sense?

EDIT:: actually, they're kind of completely different issues, but in the end they relate to the same thing. If we can get updates from the scripts regarding the current state of their associated controls, we will be better able to utilize the scripts in a creative way. Thus "hijacking" the listener dictionary already created by the components/controls and triggering a function that changes a listenable property (by listenable, I mean on that we can observe in m4l).
"add_value_listener" simply maps a control to a function; the listener function is where the action is. ModeSelectorComponent is no different than any other component, but it just so happens that it has a listener function whose purpose is to set the mode property (_mode_index), which I assume is observable via M4L. Any control can have more than one listener, so in order to create additional observable properties, you could either add more listeners, which could update new properties, or you could override or modify the original listener functions, so that they update new properties (in addition to doing whatever they were originally doing).

On the other hand, while some listeners are listening for changes from control surface controls, other listeners are listening for changes in Live Song states (via the various LiveAPI "add_listener" functions). This way, the scripts allow control changes to change song states, and also allow song state changes to affect control surface states. Now, since M4L can talk directly to Live, and can also talk directly to a control surface, why would you want to change a control surface script property, and expect a Song state change, instead of making the change directly to the Song state and then either allow the script to do its job and update the control surface, or change it directly from M4L as well?

Best,

Hanz
http://remotescripts.blogspot.com/ - an introduction to the Framework classes

amounra93
Posts: 432
Joined: Sat Jan 24, 2009 8:16 pm
Location: Arcata, CA
Contact:

Re: LOM.Navigator v1.0 - With *full* control surface support.

Post by amounra93 » Fri Sep 24, 2010 11:32 pm

"add_value_listener" simply maps a control to a function; the listener function is where the action is. ModeSelectorComponent is no different than any other component, but it just so happens that it has a listener function whose purpose is to set the mode property (_mode_index), which I assume is observable via M4L.
K, got that. I guess the other "components" are passing all of their listening responsibilities to "controls", which I always seem to forget have an observable property: "value". Value is not listed in getinfo (m4l) so I always forget about it.

I don't think I'm fuzzy about what the value listener is, only about how (or more specifically, where in the code) its interpreted. Is this something I'm not seeing because its imported as part of the Live Class?
Now, since M4L can talk directly to Live, and can also talk directly to a control surface, why would you want to change a control surface script property, and expect a Song state change, instead of making the change directly to the Song state and then either allow the script to do its job and update the control surface, or change it directly from M4L as well?
Two reasons: Python seems to communicate more quickly with Live than m4l. There are already some component blocks built into the _Framework which simplify a lot of things (DeviceComponent, for instance). Instead of building all this stuff in js or Max, why not just use the built in objects and send them simple messages to do this or that, instead of reproducing the whole functionality in m4l? To reproduce the functionality of the DeviceComponent, there are a lot of things that have to be done in Low-Priority (every time you bank, you have to update all of the selected parameters, their names, values, etc. Granted, all of this is being done in the Python script, as well, but much more quickly and without having to port the _Generic name dictionary over to Max). If we can add a listener to some of the functions in the DeviceComponent, either by wrapping it in a new Class or modifying the existing one, then we can send that component a message 'bank 1' and the component in turn provides us with all the new corresponding data relative to the new bank we are in.

Second, when making modifications to the scripts from m4l, it is important to be in sync with what the control surface is actually doing. If I want to have a Max function modify some element in the Live song that my controller is currently controlling, I have no way of knowing through the API (with the _Framework scripts) exactly what Live function that controller is currently connected to and operating on.

Thanks for the discourse, Hanz. You are good at explaining this stuff, and your interest is greatly valued. I'm still figuring this stuff out (obviously), but I've made some great strides with your help :)
http://www.aumhaa.com for Monomod and other m4l goodies.

Post Reply