Creating a "Learn" button for MIDI

This forum is for developers of Rack Extensions to discuss the RE SDK, share code, and offer tips to other developers.
sschoener
Posts: 11
Joined: 25 Dec 2020

Post 29 Dec 2020

Hello there!

I'm trying to build "Learn" button for a MIDI value in a device. For example, the Dual Arpeggiator has a LRN button below the two MIDI notes that define its input range. I'm hitting the following problem: Where should the property representing the note live?
If it lives in document_owner or gui_owner, I cannot set it from native code because the realtime processor can only set rt properties.
If it lives in rt_owner or rtc_owner, I cannot create a GUI for the user to set the value manually (e.g. by dragging the mouse, as works for the Dual Arpeggiator notes).

It seems to me that these three requirements cannot be satisfied at the same time:
1. Be able to learn the midi note by pressing a key (which for all I know must happen in native code).
2. Be able to edit the value of the midi note using a GUI.
3. Store the value of the midi note in a patch.

(The closest thing that I have been able to come up with so far is: use two properties (one document_owned called P1, the other rt_owned called P2), have the GUI modify P1 but show P2 (probably using a custom display). Then let the native code react to changes to P1 to update P2. I'm not even sure this works, and my lack of familiarity with custom displays suggests this might be a day long excursion.)

Is this possible? What am I missing?

sschoener
Posts: 11
Joined: 25 Dec 2020

Post 29 Dec 2020

Turns out using a custom display is actually the right way, and presumably also what Dual Arpeggiator is doing: It doesn't have a property for whether the user has enabled learning - the learning happens in the GUI. The way it is implemented is like this: The Learn 'button' itself is a custom display. The realtime processor itself provides the last played note as an rt-owned property that the custom display can query.

The only downside of this approach is that a custom display makes it very hard to make it clear that the display is interactable because you cannot add more frames to the button (the custom display cannot draw textures - it can only use one as the background).

User avatar
pongasoft
RE Developer
Posts: 290
Joined: 21 Apr 2016
Location: Las Vegas

Post 30 Dec 2020

sschoener wrote:
29 Dec 2020
Turns out using a custom display is actually the right way, and presumably also what Dual Arpeggiator is doing: It doesn't have a property for whether the user has enabled learning - the learning happens in the GUI. The way it is implemented is like this: The Learn 'button' itself is a custom display. The realtime processor itself provides the last played note as an rt-owned property that the custom display can query.

The only downside of this approach is that a custom display makes it very hard to make it clear that the display is interactable because you cannot add more frames to the button (the custom display cannot draw textures - it can only use one as the background).
Yup custom displays are limited and I have been pushing for extending it and allow to "draw" pre-rendered image. I even submitted a full on proposal about how to do it. It has been years now...

That being said, if you look at the A/B 12 Switch (code), the buttons are all custom displays with a background image that is a button, and when pressed I simply draw a semi transparent rectangle on top of it. Not perfect, but it works I suppose (no complains ;))

sschoener
Posts: 11
Joined: 25 Dec 2020

Post 30 Dec 2020

Thanks! Let's hope they get back to your proposal some time :) I had a similar idea (drawing a semi transparent rect) but it didn't work as nicely as I would have wanted it to :( I'm spending way too much time on the GUI and trying to make it look fancy, and then it's just a little bit frustrating to have to make these compromises. Oh well...

User avatar
buddard
RE Developer
Posts: 947
Joined: 17 Jan 2015
Location: Stockholm

Post 04 Jan 2021

Yes, you have the right approach, you need to use (at least) two properties and a custom display to implement MIDI learn.

As for the graphics, a trick that we frequently use is to overlay the custom display with static_decorations controlled by visibility switches.
So you add another property (in either the doc or GUI scope), which is a stepped number property with the values 0 and 1.
In the display's gesture handlers, you set the property to 1 in the on_tap function, and 0 in the on_release function.
Create two static decorations: One for the button's pressed state and one for the released state, and draw them in the same place, on top of the custom display.
Use the "pressed" property as a visibility switch for both of the decorations, so that one is showed when the value is 0, and the other when the value is 1.

sschoener
Posts: 11
Joined: 25 Dec 2020

Post 05 Jan 2021

Thanks, that's a great idea :)
I've tried something similar but I noticed that Reason sometimes has trouble with static decorations that have non-uniform alpha values (e.g. most displays on Reason devices have this slight reflection that you need to implement as a static decoration if you want to overlap it over a custom display - but I can't get Reason/Recon to actually show the static decoration with correct alpha values: it seems to round the alpha mask to either 0 or 1). Is that something you have experienced as well? I think it might be related to the PNG encoding, but couldn't find anything on the topic so far...

User avatar
buddard
RE Developer
Posts: 947
Joined: 17 Jan 2015
Location: Stockholm

Post 05 Jan 2021

sschoener wrote:
05 Jan 2021
I've tried something similar but I noticed that Reason sometimes has trouble with static decorations that have non-uniform alpha values (e.g. most displays on Reason devices have this slight reflection that you need to implement as a static decoration if you want to overlap it over a custom display - but I can't get Reason/Recon to actually show the static decoration with correct alpha values: it seems to round the alpha mask to either 0 or 1). Is that something you have experienced as well? I think it might be related to the PNG encoding, but couldn't find anything on the topic so far...
All you have to do is explicitly set blend_mode to normal:

Code: Select all

    jbox.static_decoration {
        graphics = { node = "graphics_node"},
        blend_mode = "normal",
    }
This is supposed to be the default according to docs, but it isn't... Once you do this, alpha blending should behave as expected. :D

Just be careful not to overuse static decorations, we made this mistake with Select 2.0, and it turns out it caused some Windows resource problem in earlier versions of Reason. So try and keep them down to a reasonable amount.

sschoener
Posts: 11
Joined: 25 Dec 2020

Post 06 Jan 2021

That did it! Thanks a bunch -- I'm not sure how much I can trust the documentation anymore, haha :)

  • Information
  • Who is online

    Users browsing this forum: CommonCrawl [Bot] and 0 guests