Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

Sign In with Twitter

Pad LEDs in User Mode with Base

edited November 2013 in Hardware

Hi, I have been using the Base for a little while now just as a regular MIDI controller with Ableton. I found being able to customize the colors of the pads in the editor very useful for my particular workflow.


I just installed the Python scripts and see that none of the pads in the user modes light up... Are there ways to assign colors to the pads for each of the different user modes? Does it involve editing the MIDI remote script? Or am I able to do it within the Livid Editor? Looked to see if this question had already been answered before but couldn't find anything, any insight would be appreciated since I would really like to have the MIDI remote scripts handy to mess with alongside my usual mappings with the color feedback :)

Cheers

Comments

  • Note: I am simply using the user mode as a drum pad, I am looking to simply have the lights stagnant - no "interactive" type feedback is necessary

  • You can assign different colors to the pads in the Base.py script, inside the function _set_layer3().  


    There's lots of ways to do it;  I might do it like this:

    # this goes after the last line of the _set_layer3() function...make sure it's indented at the same level or it won't work
    # assign your color values inside of a list:

    PAD_COLORS = (1, 1, 1, 1, 1, 1, 1, 1.......(there should be 32 integers here)...., 1)

    # send those colors to the pads:

    for pad in self._pad:
    pad.send_value(PAD_COLORS[self._pad.index(pad)], True)

    That should be enough to get your pads lit up.  If you want different colors for each User Mode, you'll need to do a little more than that....when you get that far, hit me up and I can help you further.  And of course, if what I told you thus far isn't clear, just let me know and I'll break it down in more detail.

    a

  • I really appreciate you taking the time to respond to me!


    To clarify, this is the .py (NOT .pyc file) that I am editing?

    In the .py file, I see where layer 3 is defined...



    def _set_layer3(self, shifted = False):
    with self.component_guard():
    for pad in self._pad:
    pad.send_value(0, True)
    self._display_mode()
    self._deassign_all()
    self._send_midi(USERBUTTONMODE)
    for index in range(8):




    Is the code that you gave me to follow this section? There is also a section that starts with "self._mixer.channel_strip" that directly follows and seems related.. I'm just getting my feet wet with Frameworks and Python so forgive my noobiness, once again thank you for the help!
  • edited November 2013

    No trouble....I'd always rather explain to someone how to do something than just give them an answer.  More fishes, and all that ;)


    Yes, the py file.  The pyc file is the compiled version of the py file, and generally gets rebuilt each time you open the script by installing it as a control surface in Live.

    The code I wrote should go after the entire block of that function, but at the same indentation.  Basically, it would look like this in my current working version (which may be slightly different from yours, since I don't know which version you have):


    def _set_layer3(self, shifted = False):
    with self.component_guard():
    for pad in self._pad:
    pad.send_value(0, True)
    self._display_mode()
    self._deassign_all()
    self._send_midi(USERBUTTONMODE)
    for index in range(8):
    self._mixer.channel_strip(index).set_select_button(self._touchpad[index])
    self._touchpad[index].set_on_off_values(CHAN_SELECT, 0)
    self._mixer.master_strip().set_volume_control(self._fader[8])
    for button in self._button[4:8]:
    button.set_on_off_values(USERMODE, 0)
    self._user_mode_selector.set_enabled(True)
    self._assign_alternate_mappings(self._user_layer+12)
    self._send_midi(tuple([240, 0, 1, 97, 12, 61, 1, 1, 1, 1, 1, 1, 1, 1, 2, 247]))
    self._send_midi(tuple([191, 122, 72])) #turn local ON for CapFaders
    PAD_COLORS = (1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1)
    for pad in self._pad:
    pad.send_value(PAD_COLORS[self._pad.index(pad)], True)

    Be careful of formatting....you probably can't copy and paste, as the forum software screws up the indention of the text.  You'll have to restart Live after each time you make a change, and it's good to keep an eye on your log.txt file to see any errors.  

    Does this get you working?

    Disclaimer:  I haven't checked this code yet, but I'll give it a go later when I have my Base next to me.  It does compile, and theoretically it should work right.


  • Works beautifully!! I now realize that you are the author of this script..it is excellent and I really appreciate all of your help with this!


    If you would be willing to guide me through how to have different color mappings for the various User Modes that would be super helpful.

    Also, I have found the numbers for all of the colors with the exception of dark blue... Would you be able to tell me what the number for that is?

    For the reference of anyone else potentially looking at this thread for assistance, here are what I've found the colors to be...

    1 - White
    2 - Yellow
    3 - Cyan (Light Blue)
    4 - Magenta
    5 - Red
    6 - Green
  • Cool, glad that's working.


    127 = Blue

    To get different colors for each UserMode, you'll need to add some new arrays.

    Basically, it'll look like this:

    PAD_COLORS =     [ [1, 1, ....your colors for User1..., 1],
    [1, 1, ....your colors for User2..., 1],
    [1, 1, ....your colors for User3..., 1],
    [1, 1, ....your colors for User4..., 1] ]

    for pad in self._pad:
    pad.send_value(PAD_COLORS[self._user_mode_selector._mode_index][self._pad.index(pad)], True)

    I think that will do it, let me know if you have any trouble ;)

    a

  • Amazing, works perfectly!! Thank you yet again!


    Two final questions for you..

    Is it possible to make the Buttons (specifically Buttons 5-8) send CCs with specific CCvalues rather than notes? I tried to manipulate the script with my very limited knowledge (I've only made it through the early chapters of "Learning Python" thus far..) but to no avail.. I realize that there a lot of bigger picture things at play and that doing so is possibly very convoluted to explain and tedious to do, but if it's simple to explain and tedious to do, I don't mind the work! This would be the last puzzle piece to making my Base workflow seamless.

    Also, have you heard about any issues with the master fader jumping around? I've only had the base for a little over a month and I downloaded the MIDI Remote Script within the past week so I'm pretty sure that side of things is up to date, however I have yet to update the firmware for the Base so I'm not sure if that might be the cause..

    Cheers
  • Note - To troubleshoot I disabled all other MIDI outputs in my preferences and disconnected all other MIDI controllers and still experienced the issue. I have, however, edited the note order for the Pads within the MIDI remote script.

  • Definitely try updating the firmware. Do you know which version you're on?

  • edited November 2013

    Re:  CC's.  By button 5-8, you mean the navigation buttons on the side?


    You can change their functionality in the Base Editor software, but that will prevent them from working correctly in the script.

    Unfortunately, due technical reasons, you can't translate a Note to a CC inside the script.

    What are you trying to accomplish exactly?  Maybe there's another way to do things.  For instance, if you're trying to map some control to 4 different values to be changed when you change UserModes, it's probably possible to simply access that parameter directly from the script....

    Re:  Learning Python.  That's a good start.  The hard part with this stuff is learning what Ableton has written in the _Framework.  There's a lot of stuff in there !
  • Yes, I mean the buttons on the side. All I'm looking to do is to have them send the same MIDI CC1 value with consecutive CC2 values, i.e. 0-3. Specifically what I want to do is to map the CC1 value to a chain selector so I can toggle to a different part of the chain when I select each one of the different user pages.


    Yes, lots to learn.. I switched from Logic to Ableton about 4 months ago and am disappointed I didn't realize to do so years ago.. At least I've seen the light now!!
  • edited November 2013

    This is exactly what I thought you were trying to do ;)  I'm not sure of an easy way to do it....


    You can do it in the script, but it's far from straightforward.  Basically, you'd have to find the device in the script through a search process, then the particular parameter in the device, then change that parameter based on what mode you are entering.  It's pretty complicated, but totally doable.  

    I delayed answering you because  I was hoping to think of a simpler way to do this , but I haven't yet.  If I do, I'll get back to you.  If not,  I'll try to write some extra scripting that will do this, but it may be a little while before I can get to it....I'm swamped at the moment.

    a

  • Got it. Just for the sake of brainstorming.. Is there way to keep those buttons as they are within the script and just have them ALSO trigger a CC value output, sent in addition to its normally assigned note? So that when the already existing MIDI message that the buttons output gets sent, it also triggers that CC value as well? This would of course have to only occur when within User Mode (I do not need it sent when entering User Mode, only when selecting one of the 4 pages within User Mode) so if even possible at all, I don't know if this is making things simpler or more complex.. Once again, please forgive my newbie-isms!


    Don't worry about it at all, I certainly realize there is not nearly enough time in the day... I am currently using this in a production setting so executing what I need to manually isn't a huge issue.. I have the color mappings all sorted and that was what I needed. Thanks again!
  • edited November 2013

    There's not a way to do it, unfortunately.  


    Basically, a control can either be forwarded to the python script or it can be assigned a translation.  It can't do both.  And, more importantly in this situation, if you forward it to the script, it is invisible to Live in terms of Track or Remote input.  

    You could do it in m4l more easily than in Python:  you'd need to create a patch that observed those four buttons, and forwarded their value to a live.object connected to the chain selector in question.  It's still not an easy thing to do, but far easier than doing it in Python for most people.

    Anyway, since I was working on something similar elsewhere, I made a something that will do what you want, I think.  First off, add this at the top of the script, right before the section that says """Framework Files"""

    from _Tools.re import *

    Next, add this to the end of the set_layer3() function, where everything else has gone:

    self.set_chain_selector(self._user_mode_selector._mode_index)

    Now add the function itself.  You can put it right below the set_layer3() function:

    def set_chain_selector(self, mode):
    key = str('ThisOne!')
    preset = None
    for track in range(len(self.song().tracks)):
    for device in range(len(self.song().tracks[track].devices)):
    if match(key, str(self.song().tracks[track].devices[device].name)) != None:
    preset = self.song().tracks[track].devices[device]

    for return_track in range(len(self.song().return_tracks)):
    for device in range(len(self.song().return_tracks[return_track].devices)):
    if match(key, str(self.song().return_tracks[return_track].devices[device].name)) != None:
    preset = self.song().return_tracks[return_track].devices[device]

    for device in range(len(self.song().master_track.devices)):
    if match(key, str(self.song().master_track.devices[device].name)) != None:
    preset = self.song().master_track.devices[device]

    if preset != None:
    for parameter in preset.parameters:
    if parameter.name == 'Chain Selector':
    parameter.value = max(min((128/3)*mode, 127),0)
    break



  • I had to split this up into two posts, as the forum software is being belligerent. 

    Couple of caveats:  your rack can't be nested in another rack, or this won't work.  Also, this will only work for one device, and it has to have "ThisOne!" in the name (you can change that pretty easily, I just used that for testing purposes).

    Let me know if you have trouble, its kinda tricky.   I did test it though, and I wanted to document it here for others use ;)

    a
  • @amounra:


    Does the code you supplied above still work/apply for the latest remote script for the Base controller? I can't seem to get it working on my end. I've checked and double-checked the formatting (I'm just using xcode) and it seems to be in place, but after I delete my pyc files and fire up Ableton, I just get a non-responsive Base.

    Also, this is super cool that you're helping out like this. Could you explain how to add the pad LED response when a pad is hit as well, similar to how the default mapping works? That way we can edit the pad colors and add pad response when hit for the user mode as well? Hopefully my question makes sense!
  • Hi I just posted a question before finding this, but is it possible to have dynamically mapped (ie responsive LEDs) type drum pads with the top buttons and faders midi mapped? thanks

  • edited May 2014

    @navigateur:


    Sorry, this post post got buried after I looked at it initially and forgot to give you a response.

    Complicated answer, I'm afraid.  There are two ways this can be done, depending on the intention.  

    Without getting into the the nuts and bolts of how it works, here's the simple way to do things:  for each pad that you want to change color while being pressed, you need to change that pad's "display_press" property.  So, for the User pages, it's only necessary to add a line to the "_assign_alternate_mappings" method of the script (line 2813 in the version I'm looking at), within the loop that sets up the pads:

    for pad in self._pad:
    pad.display_press = True

    That SHOULD be all it takes.  I haven't checked this with the hardware, though, so let me know if that gives you an error or something.


    I think you're asking the same question?  If not, please clarify because I'm not exactly sure what you're asking for.

    cheers :)

    a
  • thanks @amounra i'm going to give this another shot and i'll report back!

Sign In or Register to comment.