Go Back   Cockos Incorporated Forums > REAPER Forums > MIDI Hardware, Control Surfaces, and OSC

Reply
 
Thread Tools Display Modes
Old 11-17-2022, 01:50 PM   #2921
helgoboss
Human being with feelings
 
helgoboss's Avatar
 
Join Date: Aug 2010
Location: Germany
Posts: 1,885
Default

Quote:
Originally Posted by Puck View Post
What I mean is this:

While banking through your project and you get to the last track, you can actually keep on banking past that for as long as you like. There should be some logic there that tells Realearn that you no longer need to bank. Let’s say you bank 6 times past the last track, you now need to bank in the opposite direction 6 times to be where you were before you went past the last track. We shouldn’t be able to do that, Realearn should stop us

Is that more clear than “off the edge of the project into a pit of despair”?

Sorry again for being vague and using weird phrases!
Longer answer, sorry.

It's actually what I thought, thanks for clarifying. Technically that's not a bug, but I get what you mean.

There's not the one approach to implement "track banking" in ReaLearn. There are actually 3 of them! You happen to use one which lets you keep banking past the actual number of tracks With your way, you don't actually control a track bank. You control a parameter value.


Here are the 3 approaches of implementing track banking (which I'm aware of):


a) Following a parameter value

b) Following the currently selected track

c) Following the instance track


a) Following a parameter value

This is the approach which you use. You let some buttons/encoders/... change a parameter value (e.g. a parameter called "track bank"). Then you derive the currently controlled tracks from that value (by using dynamic track expressions which use that parameter, e.g. "p[0] + 0", "p[1]", etc.). The parameter's configured value count (= number of possible values) is constant and it's not limited by the number of tracks in your project, in fact it doesn't know anything about tracks, it's just a parameter. ReaLearn is deliberately neutral. It doesn't magically presume that it has any relation to the number of tracks ... because you could use that parameter for anything.

Here's some pro/contra if you use this technique for track banking:

(+) You can easily control the bank from automation envelopes, other instances or scripts.
(+) You can influence not just tracks by this but also let it guide other things at the same time (e.g. activate/deactivate mappings by using conditional activation)
(+) You can easily define multiple track bank parameters (e.g. let one portion of your controller work on tracks 8-16 and another one on tracks 64-72). Even within just one ReaLearn instance.
(-) You can exceed the number of tracks.


b) Following the currently selected track

With this approach, you let some buttons/encoders/... change the currently selected track. Then you derive the currently controlled tracks from that (by using dynamic track expressions with "selected_track_index + 0", "selected_track_index + 1", etc.).

Pro/contra:

(+) You can't exceed the number of tracks (because you can't select a track which doesn't exist).
(+) Track selection by definition follows track banking.
(-) Track selection by definition follows track banking It might also be a disadvantage, depending on what you desire.


c) Following the instance track

You let some buttons/encoders/... change the instance track of a ReaLearn instance. Then you derive the currently controlled track from that (by using a dynamic track expression with "instance_track_index + 0", "instance_track_index + 1", etc.).

Pro/contra:

(+) You can't exceed the number of tracks (at least if you get the dynamic because an instance track ).
(+) You can use different banking in different ReaLearn instances (e.g. let one controller work on tracks 8-16 and another one on tracks 64-72).
(-) I haven't really built a preset for that yet because it's one of the newer features, so I'm not 100% sure if a puzzle piece is yet missing to make this the perfect track banking approach.


So ... there are many options. The choice is yours.

The Lua script which produces the DAW control preset defaults to approach (a) but can be configured to use (b). It doesn't support (c) yet, but it's something I want to add eventually. (c) can already be done in ReaLearn, I just didn't have the time to create a decent preset using this approach.

I could in theory add some features to make "exceeding the number of tracks" impossible with (a) as well:

- Make a "track_count" variable available in dynamic track expressions, so you can limit things yourself ... but I think that wouldn't really help because it would not prevent the parameter value from increasing more and more. However, might still be a good idea to add it, also for approach (c).
- Make it possible to define a "max value expression" for a parameter. And then you could enter "track_count - 1" (or "(track_count - 1)/ 8" if the parameter stands for a bank of 8 tracks) and ReaLearn would make sure at all times that it never exceeds that maximum. Not sure yet if this is a good idea.
helgoboss is offline   Reply With Quote
Old 11-18-2022, 03:45 AM   #2922
Puck
Human being with feelings
 
Puck's Avatar
 
Join Date: Feb 2022
Location: Almost Canada
Posts: 494
Default

Quote:
Originally Posted by helgoboss View Post
Longer answer, sorry.
I quite enjoyed reading that! Thank you.

You were super clear but I still have some questions;

1. If I want to respect mcp/tcp visibility, I have to use option a, right?

2. I need to know more about dynamic expression in general.

- When we do dynamic expression for tracks, why are we multiplying the parameter by 10000? I see that we are dealing with Realearn's internal parameters and that stepping through that parameter is what actually banks the tracks. But I can't make the math make sense, therefore it'd be really hard to apply it to other things (like being able to bank through FX or Sends)

In terms of the math, I see we have a step size in the mapping of .01 (talking about the ch+ mapping) but if you look at the actual value of the parameter it takes something like 6 presses to even see .001 so it's hard to tell what's happening.

- The Daw control preset names the first few parameters in some way, where is that happening?

In terms of solving my issue. Let me just say it's not a big deal, I just thought it was a bug but I get it now

However, I was wondering if we could use conditional activation on all the bank+/ch+ mappings and that condition would be whether or not there is a non-empty string on channel 8. Obviously that's specific to my set up, but maybe something worth exploring. Actually, I could even set that up within TouchOSC itself.

[with TouchOSC scripting]When the value changes for the 8th track label, if empty we send a message to toggle the mappings off.

Last edited by Puck; 11-18-2022 at 06:46 AM.
Puck is online now   Reply With Quote
Old 11-18-2022, 10:07 AM   #2923
helgoboss
Human being with feelings
 
helgoboss's Avatar
 
Join Date: Aug 2010
Location: Germany
Posts: 1,885
Default

Quote:
Originally Posted by Puck View Post
I quite enjoyed reading that! Thank you.

You were super clear but I still have some questions;

1. If I want to respect mcp/tcp visibility, I have to use option a, right?

2. I need to know more about dynamic expression in general.

- When we do dynamic expression for tracks, why are we multiplying the parameter by 10000? I see that we are dealing with Realearn's internal parameters and that stepping through that parameter is what actually banks the tracks. But I can't make the math make sense, therefore it'd be really hard to apply it to other things (like being able to bank through FX or Sends)

In terms of the math, I see we have a step size in the mapping of .01 (talking about the ch+ mapping) but if you look at the actual value of the parameter it takes something like 6 presses to even see .001 so it's hard to tell what's happening.

- The Daw control preset names the first few parameters in some way, where is that happening?

In terms of solving my issue. Let me just say it's not a big deal, I just thought it was a bug but I get it now

However, I was wondering if we could use conditional activation on all the bank+/ch+ mappings and that condition would be whether or not there is a non-empty string on channel 8. Obviously that's specific to my set up, but maybe something worth exploring. Actually, I could even set that up within TouchOSC itself.

[with TouchOSC scripting]When the value changes for the 8th track label, if empty we send a message to toggle the mappings off.
1. You can also use approach (b). There is "selected_track_mcp_index" and "selected_track_tcp_index". Right, approach (c) is not possible, I should add "instance_track_mcp_index" and so on, then it is.

2. The reason for the multiplication by 10000 in "daw-control.lua" is that it doesn't yet use one of ReaLearn's newer features: The ability to give parameters a value count. The modern way to do this would be to tell ReaLearn that the parameter has a value count of 10000 (menu => compartment parameters => parameter x ... that's also where you name parameters). Then you don't do the multiplication by 10000 in the expression, but just use it as is. I chose the 10000 because that sounded like a safe maximum for me when it comes to the number of tracks in a project But it could be any number. By the way, defining the "value count" also solves your problems of not seeing the parameter value change.

I guess "daw-control.lua" deserves some update to modern ReaLearn features.
helgoboss is offline   Reply With Quote
Old 11-18-2022, 10:33 AM   #2924
cjunekim
Human being with feelings
 
Join Date: Dec 2016
Posts: 253
Default Repurposing a MIDI controller for a monitoring device

Today I was looking at some TC Electronics' Icon series plug-in and controller hybrid products' sales ads. And I came up with an interesting idea to test.

Thanks to the flexiblity of realearn, I could repurpose my nanoKONTROL Studio as a monitoring device! (controller at the same time, actually)



The four buttons on the top-left of the midi controller show how much attenuation there is on the limiter for the audio playback. If all four are lit, that means about -4db attenuation/compression. If none is lit, there is no attenuation -- actually, 0.23db attenuation due to the resolution limitation of 7-bit midi CC.

For my use case, this is enough and pretty much convenient. Now I don't have to put reaper on screen to check if there is any attenuation.

I used blue cat's Protector, which can be configured to output its states to midi cc. I wish more plugins support this.

Thanks, helgoboss!

Last edited by cjunekim; 11-18-2022 at 10:38 AM.
cjunekim is offline   Reply With Quote
Old 11-18-2022, 10:54 AM   #2925
helgoboss
Human being with feelings
 
helgoboss's Avatar
 
Join Date: Aug 2010
Location: Germany
Posts: 1,885
Default

Quote:
Originally Posted by cjunekim View Post
I used blue cat's Protector, which can be configured to output its states to midi cc. I wish more plugins support this.

Thanks, helgoboss!
Looks cool. Puck posted this FR: https://github.com/helgoboss/realearn/issues/767 ... so actually something similar seems to be supported by some plug-ins. I'll add that ASAP.
helgoboss is offline   Reply With Quote
Old 11-19-2022, 06:24 AM   #2926
Puck
Human being with feelings
 
Puck's Avatar
 
Join Date: Feb 2022
Location: Almost Canada
Posts: 494
Default

Going to have some more FX questions/possible bugs/FR's today:

1. {{target.fx.name}} does not work on the vanilla "FX" target. That's fine, it does work on some of the other FX targets. Just mentioning.

2. The name {{target.fx.name}} spits out could be much more useful than it is at the moment. My OSC labels have 10 or 11 characters, which is a few more than most displays have, so we want the most useful output as possible. CSI lets us choose an alias for each FX within the FX Zones that we make. There isn't really a mechanism for that here(that I know of) so that will be a feature request. However, we can make it better right away by stripping all the prepended FX Types and so that:

Code:
"VST3: Lindell SBC"
instead comes out as

Code:
"Lindell SBC"
and we could also filter everything after " (" so that now

Code:
"Unfiltered Audio Bass Mint(Plugin Alliance)"
becomes

Code:
"Unfiltered Audio Bass Mint"
I chose Unfiltered Audio here to illustrate that we should also definitely have a way to have an Alias


...........

also @cjunekim: Very cool!
Puck is online now   Reply With Quote
Old 11-19-2022, 06:44 AM   #2927
Puck
Human being with feelings
 
Puck's Avatar
 
Join Date: Feb 2022
Location: Almost Canada
Posts: 494
Default

I have a dumb question that I should be able to figure out especially after watching your last video.

With the Track Select/Unselect target, I do not want to be able to unselect at all. The reason is the FX Menu that I'm building works on the selected track, so unselecting the track makes the menu wrong. What setting in the glue section should I change?
Puck is online now   Reply With Quote
Old 11-19-2022, 07:02 AM   #2928
Puck
Human being with feelings
 
Puck's Avatar
 
Join Date: Feb 2022
Location: Almost Canada
Posts: 494
Default

When Right-Clicking -> Move to group (great feature btw!) and you have more than 5 mappings, the window shoots back up to the first mapping. I'm not sure if there is a case where that'd be useful. The way I was using it, I would much prefer the window not go back to the top. I had 20 or so mappings that I was moving to different groups, and after the 5th one, each time I would have to scroll down to find where I was at.
Puck is online now   Reply With Quote
Old 11-19-2022, 11:27 AM   #2929
helgoboss
Human being with feelings
 
helgoboss's Avatar
 
Join Date: Aug 2010
Location: Germany
Posts: 1,885
Default

Quote:
Originally Posted by Puck View Post
Going to have some more FX questions/possible bugs/FR's today:

1. {{target.fx.name}} does not work on the vanilla "FX" target. That's fine, it does work on some of the other FX targets. Just mentioning.

2. The name {{target.fx.name}} spits out could be much more useful than it is at the moment. My OSC labels have 10 or 11 characters, which is a few more than most displays have, so we want the most useful output as possible. CSI lets us choose an alias for each FX within the FX Zones that we make. There isn't really a mechanism for that here(that I know of) so that will be a feature request. However, we can make it better right away by stripping all the prepended FX Types and so that:

Code:
"VST3: Lindell SBC"
instead comes out as

Code:
"Lindell SBC"
and we could also filter everything after " (" so that now

Code:
"Unfiltered Audio Bass Mint(Plugin Alliance)"
becomes

Code:
"Unfiltered Audio Bass Mint"
I chose Unfiltered Audio here to illustrate that we should also definitely have a way to have an Alias


...........

also @cjunekim: Very cool!
Makes sense. Please add both as FR on GitHub, then we can discuss details there. I already have a concept in mind for the alias feature.
helgoboss is offline   Reply With Quote
Old 11-19-2022, 11:28 AM   #2930
helgoboss
Human being with feelings
 
helgoboss's Avatar
 
Join Date: Aug 2010
Location: Germany
Posts: 1,885
Default

Quote:
Originally Posted by Puck View Post
I have a dumb question that I should be able to figure out especially after watching your last video.

With the Track Select/Unselect target, I do not want to be able to unselect at all. The reason is the FX Menu that I'm building works on the selected track, so unselecting the track makes the menu wrong. What setting in the glue section should I change?
"Press only" or set target min/max both to 100%.
helgoboss is offline   Reply With Quote
Old 11-19-2022, 11:29 AM   #2931
helgoboss
Human being with feelings
 
helgoboss's Avatar
 
Join Date: Aug 2010
Location: Germany
Posts: 1,885
Default

Quote:
Originally Posted by Puck View Post
When Right-Clicking -> Move to group (great feature btw!) and you have more than 5 mappings, the window shoots back up to the first mapping. I'm not sure if there is a case where that'd be useful. The way I was using it, I would much prefer the window not go back to the top. I had 20 or so mappings that I was moving to different groups, and after the 5th one, each time I would have to scroll down to find where I was at.
Please add a FR.
helgoboss is offline   Reply With Quote
Old 11-20-2022, 06:24 AM   #2932
Puck
Human being with feelings
 
Puck's Avatar
 
Join Date: Feb 2022
Location: Almost Canada
Posts: 494
Default

Quote:
Originally Posted by helgoboss View Post
Please add a FR.
I will add those shortly!

........

I've been having a rough time with FX mapping.

1. Can I set the "Instance FX" of one instance of Realearn from another instance of Realearn?
- The FXMenu approach I'm trying to go with would seem to require this. I always want the FXMenu active and the Realearn instance that AutoLoads presets is obviously changing presets all the time so theoretically I would need to include the FXMenu in every preset? I'm sure there's a way around that. Let me know if a different approach would be better. I am considering just using Focused FX and having the FXMenu still, but this way the FXMenu would just contain actions that float/focus the plugins. The drawback I see with that is unfocusing the plugins loses the mappings. Sometimes that's not ideal. But maybe that is the path of least resistance here.

2. Going with the instance approach, the mapping on the target side just needs to say

FXParameter: Set Value
Track: <irrelevant> (this just disappears in the mapping panel)
FX: <instance>
Param 1: Cutoff (for example)

and then as long as I can set the instance correctly, Realearn will autoload the mapping? Also, while doing it the FX Instance way, do I have to set global FX preset links?


edit: I'd still like to hear the answer here. However, I think I'm going to go with the Focused FX approach. I was able to test it and it works pretty well. You would think that clicking on Reaper would "unfocus" the FX but it actually doesn't. You have to a) click on another FX or b)close the FX with the 'x' in the top right corner of the floating window (on Windows)

edit 2: While I do like this way, we absolutely need a way to unfocus the plugin that doesn't involve clicking the X or floating another plugin.

Last edited by Puck; 11-20-2022 at 07:11 AM.
Puck is online now   Reply With Quote
Old 11-20-2022, 06:52 AM   #2933
Puck
Human being with feelings
 
Puck's Avatar
 
Join Date: Feb 2022
Location: Almost Canada
Posts: 494
Default

Sorry for all the posts

This is more of an advanced concept though and I wanted any of the pros around here to chime in.

So, on my fx page, there are 32 encoders and 32 buttons. They each have a label for the parameter name (Cutoff for example) and another label for the parameter value and they can all take a color message.

That means for each parameter I'd like to map, that's four mappings in total. Those four mappings are always going to be tied to eachother in the same manner.

- They can all share the same target.
- The Parameter name mapping will have textual feedback with {{target.fx_parameter.name}} in the textbox
- The Value name will have numeric feedback (so it's just as the default mapping shows up)

The only thing that will change is the obviously the Target(what it's mapped to) and the color I choose.

Are there any ideas on how streamline this approach?

....

I could just learn many in Realearn and figure out macros for the additional mappings in a text editor potentially. But that's alot of text to be moving around/generating. I'm hoping for some suggestions here
Puck is online now   Reply With Quote
Old 11-20-2022, 08:38 AM   #2934
helgoboss
Human being with feelings
 
helgoboss's Avatar
 
Join Date: Aug 2010
Location: Germany
Posts: 1,885
Default

Quote:
Originally Posted by Puck View Post
1. Can I set the "Instance FX" of one instance of Realearn from another instance of Realearn?
- The FXMenu approach I'm trying to go with would seem to require this. I always want the FXMenu active and the Realearn instance that AutoLoads presets is obviously changing presets all the time so theoretically I would need to include the FXMenu in every preset? I'm sure there's a way around that. Let me know if a different approach would be better. I am considering just using Focused FX and having the FXMenu still, but this way the FXMenu would just contain actions that float/focus the plugins. The drawback I see with that is unfocusing the plugins loses the mappings. Sometimes that's not ideal. But maybe that is the path of least resistance here.
Yes, you can. Use "FX" target with "Act" (as usual). But in addition, give the ReaLearn instance that you control a tag, by using the "Instance data..." button on the bottom right. Then, in the other instance, in the mapping with the "FX" target, enter this tag in the text field next to "Act".

Don't include the FX menu in every preset, that would be extremely unmaintainable.


Quote:
Originally Posted by Puck View Post
2. Going with the instance approach, the mapping on the target side just needs to say

FXParameter: Set Value
Track: <irrelevant> (this just disappears in the mapping panel)
FX: <instance>
Param 1: Cutoff (for example)

and then as long as I can set the instance correctly, Realearn will autoload the mapping? Also, while doing it the FX Instance way, do I have to set global FX preset links?
Yes the mapping target should look like that. And it's actually the default if you follow the "Auto-load" tutorial (after you saved the preset and confirmed ReaLearn's question whether it should make mapping project-independent).

You should also set FX preset links, that's how auto-load always works, no matter the content of the preset. In fact, following the "Focused" FX is the same as following the "Instance FX". The instance FX can be anything! By default it represents the currently focused FX, but it can also be a particular FX (as a result of pinning). Or it can be the currently selected FX, .... Choice is yours, as always.

Quote:
Originally Posted by Puck View Post
edit: I'd still like to hear the answer here. However, I think I'm going to go with the Focused FX approach. I was able to test it and it works pretty well. You would think that clicking on Reaper would "unfocus" the FX but it actually doesn't. You have to a) click on another FX or b)close the FX with the 'x' in the top right corner of the floating window (on Windows)

edit 2: While I do like this way, we absolutely need a way to unfocus the plugin that doesn't involve clicking the X or floating another plugin.
I think I'm just going to change the behavior. I also don't particularly like that clicking out of the FX still leaves the FX active. It comes at a surprise. I want to fix this ASAP but if you want to be safe, create a bug ticket or FR.
helgoboss is offline   Reply With Quote
Old 11-20-2022, 08:44 AM   #2935
helgoboss
Human being with feelings
 
helgoboss's Avatar
 
Join Date: Aug 2010
Location: Germany
Posts: 1,885
Default

Quote:
Originally Posted by Puck View Post
Sorry for all the posts

This is more of an advanced concept though and I wanted any of the pros around here to chime in.

So, on my fx page, there are 32 encoders and 32 buttons. They each have a label for the parameter name (Cutoff for example) and another label for the parameter value and they can all take a color message.

That means for each parameter I'd like to map, that's four mappings in total. Those four mappings are always going to be tied to eachother in the same manner.

- They can all share the same target.
- The Parameter name mapping will have textual feedback with {{target.fx_parameter.name}} in the textbox
- The Value name will have numeric feedback (so it's just as the default mapping shows up)

The only thing that will change is the obviously the Target(what it's mapped to) and the color I choose.

Are there any ideas on how streamline this approach?

....

I could just learn many in Realearn and figure out macros for the additional mappings in a text editor potentially. But that's alot of text to be moving around/generating. I'm hoping for some suggestions here
Lua, Lua, Lua. The thing you want to do is complex and repetitive. Complex things are best done with ReaLearn's integrated Lua support. One tip to get you started: It doesn't matter what Lua code you write. The only thing that matters is that it returns something at the end which is loadable by ReaLearn. This is quite different from ReaScript. The Lua script is only used for building a preset.
helgoboss is offline   Reply With Quote
Old 11-20-2022, 11:33 AM   #2936
vonglan
Human being with feelings
 
Join Date: Oct 2019
Location: Lübeck, Germany
Posts: 46
Default

I want an endless encoder to choose the source track (track 8-19 in a folder) in a Super 8 project.
In order to do this, the ReaLearn preset should select the chosen source track, and unselect all others.
At the same time, unmute the chosen source track, and mute all others.

In a previous version of my preset, I had 2 mappings for each source track. One for activation, one for selection. All with the same source (a knob, in that case), and with an EEL formula like this:

y = (x == 0.03) ? 0 : 1
(This could be generated by Lua. I think I did it manually at that time.)

With the new "Exclusive" and "Grouping" features, is there an easier way to do this, which does not require 2*n mappings?

(On a side note, wouldn't it be helpful to have the mapped source value available in the dynamic selector formulas?)
vonglan is offline   Reply With Quote
Old 11-20-2022, 11:56 AM   #2937
helgoboss
Human being with feelings
 
helgoboss's Avatar
 
Join Date: Aug 2010
Location: Germany
Posts: 1,885
Default

Quote:
Originally Posted by vonglan View Post
I want an endless encoder to choose the source track (track 8-19 in a folder) in a Super 8 project.
In order to do this, the ReaLearn preset should select the chosen source track, and unselect all others.
At the same time, unmute the chosen source track, and mute all others.

In a previous version of my preset, I had 2 mappings for each source track. One for activation, one for selection. All with the same source (a knob, in that case), and with an EEL formula like this:

y = (x == 0.03) ? 0 : 1
(This could be generated by Lua. I think I did it manually at that time.)

With the new "Exclusive" and "Grouping" features, is there an easier way to do this, which does not require 2*n mappings?

(On a side note, wouldn't it be helpful to have the mapped source value available in the dynamic selector formulas?)
Maybe using "Project: Browse tracks" in one mapping and "Track: Mute/unmute" in the mapping below (with track "Selected" and exclusive "Within folder (on only)"). The problem is that "Project: Browse tracks" doesn't operate in one folder only. There's an FR though.
helgoboss is offline   Reply With Quote
Old 11-20-2022, 12:03 PM   #2938
Puck
Human being with feelings
 
Puck's Avatar
 
Join Date: Feb 2022
Location: Almost Canada
Posts: 494
Default

Quote:
Originally Posted by helgoboss View Post
Lua, Lua, Lua. The thing you want to do is complex and repetitive. Complex things are best done with ReaLearn's integrated Lua support. One tip to get you started: It doesn't matter what Lua code you write. The only thing that matters is that it returns something at the end which is loadable by ReaLearn. This is quite different from ReaScript. The Lua script is only used for building a preset.
Unfortunately, the only way I know to attack this is to make huge macros and/or search/replace copy/paste sort of operations. I don't really have a problem doing that, however I was wondering, are there processes out there that would make this a little more sophisticated that I should look into?

Right now the process would be to learn many in realearn. Hook up control elements to parameters. Export that into a text editor and run the macros to generate necessary lua. Is that how you would go about it?
Puck is online now   Reply With Quote
Old 11-20-2022, 12:10 PM   #2939
Puck
Human being with feelings
 
Puck's Avatar
 
Join Date: Feb 2022
Location: Almost Canada
Posts: 494
Default

One minor niggle:

I have touch messages set up on my FX page. When learning, that's the first thing that Realearn sees so it "learns" that instead of the actual rotary. I tried disabling the touch messages via a modifier in the controller preset but I found (and this makes complete sense) that just disables the virtual widgets. Realearn would then "learn" the OSC source with the touch message. I'm not quite sure how to even suggest getting around this but I remember someone else in recent memory had a similar issue.

I suppose this also means that I would have to have a 5th message per mapping as I have forgotten about the touch automation. It seems to me that the touch messages should just work automagically behind the scenes and they should also be ignored when learning?
Puck is online now   Reply With Quote
Old 11-20-2022, 12:19 PM   #2940
sonicowl
Human being with feelings
 
sonicowl's Avatar
 
Join Date: Oct 2015
Posts: 691
Default

Helgoboss, ReaLearn is really good. One thing I cannot figure out, and need some help. I'd like to map Track Controls to Selected Track. Meaning that I have 8 knobs on controller dedicated for the first 8 Track controls on any selected track, with midi feedback for knob leds. Which target type enables this? Thnx.
sonicowl is offline   Reply With Quote
Old 11-20-2022, 12:23 PM   #2941
vonglan
Human being with feelings
 
Join Date: Oct 2019
Location: Lübeck, Germany
Posts: 46
Default

Quote:
Originally Posted by Puck View Post
Unfortunately, the only way I know to attack this is to make huge macros and/or search/replace copy/paste sort of operations. I don't really have a problem doing that, however I was wondering, are there processes out there that would make this a little more sophisticated that I should look into?
The kind of Lua that you need isn't really that complicated. Do you have access to an example?
vonglan is offline   Reply With Quote
Old 11-20-2022, 01:04 PM   #2942
Puck
Human being with feelings
 
Puck's Avatar
 
Join Date: Feb 2022
Location: Almost Canada
Posts: 494
Default

Quote:
Originally Posted by vonglan View Post
The kind of Lua that you need isn't really that complicated. Do you have access to an example?
Thanks for chiming in vonglan! Here's an example of what I'd like to do. I've learned many in Realearn and then saved the preset so that Realearn changes everything to FX<instance> for reusability. That looks like this:

Code:
{
    kind = "Mappings",
    version = "2.14.0-pre.10",
    value = {
        {
            id = "fFBJOCu3Wbr3q2jfZ_AsN",
            name = "1",
            source = {
                kind = "Virtual",
                id = "RotaryC2/z",
                character = "Button",
            },
            glue = {
                step_size_interval = {0.01, 0.05},
                step_factor_interval = {1, 5},
            },
            target = {
                kind = "FxParameterValue",
                parameter = {
                    address = "ById",
                    fx = {
                        address = "Instance",
                    },
                    index = 1,
                },
            },
        },
        {
            id = "XDi1sYAQh8DQ8-rqOYCQn",
            name = "2",
            source = {
                kind = "Virtual",
                id = "RotaryPushC3",
                character = "Button",
            },
            glue = {
                step_size_interval = {0.01, 0.05},
                step_factor_interval = {1, 5},
            },
            target = {
                kind = "FxParameterValue",
                parameter = {
                    address = "ById",
                    fx = {
                        address = "Instance",
                    },
                    index = 2,
                },
            },
        },
        {
            id = "3kOugy4SwgXzvOPZZwTv-",
            name = "3",
            source = {
                kind = "Virtual",
                id = "RotaryC4/z",
                character = "Button",
            },
            glue = {
                step_size_interval = {0.01, 0.05},
                step_factor_interval = {1, 5},
            },
            target = {
                kind = "FxParameterValue",
                parameter = {
                    address = "ById",
                    fx = {
                        address = "Instance",
                    },
                    index = 3,
                },
            },
        },
        {
            id = "oeyDOIC1D-lE4fF5A6qqy",
            name = "4",
            source = {
                kind = "Virtual",
                id = "RotaryPushB5",
                character = "Button",
            },
            glue = {
                step_size_interval = {0.01, 0.05},
                step_factor_interval = {1, 5},
            },
            target = {
                kind = "FxParameterValue",
                parameter = {
                    address = "ById",
                    fx = {
                        address = "Instance",
                    },
                    index = 4,
                },
            },
        },
        {
            id = "xul_mk8DlVdEPijnBeO7Z",
            name = "5",
            source = {
                kind = "Virtual",
                id = "RotaryPushC5",
                character = "Button",
            },
            glue = {
                step_size_interval = {0.01, 0.05},
                step_factor_interval = {1, 5},
            },
            target = {
                kind = "FxParameterValue",
                parameter = {
                    address = "ById",
                    fx = {
                        address = "Instance",
                    },
                    index = 5,
                },
            },
        },
        {
            id = "rzvCl44L6d7TVN548B7Cf",
            name = "6",
            source = {
                kind = "Virtual",
                id = "RotaryB6/z",
                character = "Button",
            },
            glue = {
                step_size_interval = {0.01, 0.05},
                step_factor_interval = {1, 5},
            },
            target = {
                kind = "FxParameterValue",
                parameter = {
                    address = "ById",
                    fx = {
                        address = "Instance",
                    },
                    index = 6,
                },
            },
        },
        {
            id = "yOLlAikCp8hBFNDNlt48Y",
            name = "7",
            source = {
                kind = "Virtual",
                id = "RotaryPushC6",
                character = "Button",
            },
            glue = {
                step_size_interval = {0.01, 0.05},
                step_factor_interval = {1, 5},
            },
            target = {
                kind = "FxParameterValue",
                parameter = {
                    address = "ById",
                    fx = {
                        address = "Instance",
                    },
                    index = 7,
                },
            },
        },
        {
            id = "_b0X98qRT7y22_FpF4aDo",
            name = "8",
            source = {
                kind = "Virtual",
                id = "RotaryPushC5",
                character = "Button",
            },
            glue = {
                step_size_interval = {0.01, 0.05},
                step_factor_interval = {1, 5},
            },
            target = {
                kind = "FxParameterValue",
                parameter = {
                    address = "ById",
                    fx = {
                        address = "Instance",
                    },
                    index = 5,
                },
            },
        },
        {
            id = "hV4lk8j-DkysHHdh1G219",
            name = "9",
            source = {
                kind = "Virtual",
                id = "FXBypass",
                character = "Button",
            },
            glue = {
                step_size_interval = {0.01, 0.05},
                step_factor_interval = {1, 5},
            },
            target = {
                kind = "FxOnOffState",
                fx = {
                    address = "Instance",
                },
            },
        },
        {
            id = "TpcrYeKxEUU-_A8zbNobk",
            name = "10",
            source = {
                kind = "Virtual",
                id = "FXDelta",
                character = "Button",
            },
            glue = {
                step_size_interval = {0.01, 0.05},
                step_factor_interval = {1, 5},
            },
            target = {
                kind = "FxParameterValue",
                parameter = {
                    address = "ById",
                    fx = {
                        address = "Instance",
                    },
                    index = 11,
                },
            },
        },
        {
            id = "4t74B0jmCrg7ERWhwTjSq",
            name = "11",
            source = {
                kind = "Virtual",
                id = "FXWet/z",
                character = "Button",
            },
            glue = {
                step_size_interval = {0.01, 0.05},
                step_factor_interval = {1, 5},
            },
            target = {
                kind = "FxParameterValue",
                parameter = {
                    address = "ById",
                    fx = {
                        address = "Instance",
                    },
                    index = 10,
                },
            },
        },
    },
}
I changed everything the manual way to how I want it. That looks like this:

Code:
{
    kind = "Mappings",
    version = "2.14.0-pre.10",
    value = {
        {
            id = "g5XfyDF7OwY0Nm1Neg97I",
            source = {
                kind = "Virtual",
                id = "RotaryC2",
            },
            glue = {
                step_size_interval = {0.01, 0.05},
                step_factor_interval = {1, 5},
            },
            target = {
                kind = "FxParameterValue",
                parameter = {
                    address = "ById",
                    fx = {
                        address = "Instance",
                    },
                    index = 1,
                },
            },
        },
        {
            id = "WCVKEt9pi4K4U4u2o4Tlx",
            source = {
                kind = "Virtual",
                id = "RotaryNameDisplayC2",
            },
            glue = {
                step_size_interval = {0.01, 0.05},
                step_factor_interval = {1, 5},
                feedback = {
                    kind = "Text",
                    text_expression = "{{target.fx_parameter.name}}",
                },
            },
            target = {
                kind = "FxParameterValue",
                parameter = {
                    address = "ById",
                    fx = {
                        address = "Instance",
                    },
                    index = 1,
                },
            },
        },
        {
            id = "C2lYtNJlMoevvoAyNtgUS",
            source = {
                kind = "Virtual",
                id = "RotaryValueDisplayC2",
            },
            glue = {
                step_size_interval = {0.01, 0.05},
                step_factor_interval = {1, 5},
                feedback = {
                    kind = "Text",
                },
            },
            target = {
                kind = "FxParameterValue",
                parameter = {
                    address = "ById",
                    fx = {
                        address = "Instance",
                    },
                    index = 1,
                },
            },
        },
        {
            id = "u26AFdQreuu-MmeiiyM4k",
            source = {
                kind = "Virtual",
                id = "RotaryC2/Color",
            },
            glue = {
                step_size_interval = {0.01, 0.05},
                step_factor_interval = {1, 5},
                feedback = {
                    kind = "Text",
                    text_expression = "#FF0000",
                },
            },
            target = {
                kind = "FxParameterValue",
                parameter = {
                    address = "ById",
                    fx = {
                        address = "Instance",
                    },
                    index = 1,
                },
            },
        },
        {
            id = "WRL0Aji3vXcVS2g61VtIi",
            source = {
                kind = "Virtual",
                id = "RotaryPushC3",
                character = "Button",
            },
            glue = {
                absolute_mode = "ToggleButton",
                step_size_interval = {0.01, 0.05},
            },
            target = {
                kind = "FxParameterValue",
                parameter = {
                    address = "ById",
                    fx = {
                        address = "Instance",
                    },
                    index = 2,
                },
            },
        },
        {
            id = "Xqp4SgpG-hckRgk3uIs91",
            source = {
                kind = "Virtual",
                id = "RotaryPushNameDisplayC3",
            },
            glue = {
                absolute_mode = "ToggleButton",
                step_size_interval = {0.01, 0.05},
                feedback = {
                    kind = "Text",
                    text_expression = "{{target.fx_parameter.name}}",
                },
            },
            target = {
                kind = "FxParameterValue",
                parameter = {
                    address = "ById",
                    fx = {
                        address = "Instance",
                    },
                    index = 2,
                },
            },
        },
        {
            id = "r1Ve6IRr8iJ24OPeCyVAB",
            source = {
                kind = "Virtual",
                id = "RotaryPushValueDisplayC3",
            },
            glue = {
                absolute_mode = "ToggleButton",
                step_size_interval = {0.01, 0.05},
                feedback = {
                    kind = "Text",
                },
            },
            target = {
                kind = "FxParameterValue",
                parameter = {
                    address = "ById",
                    fx = {
                        address = "Instance",
                    },
                    index = 2,
                },
            },
        },
        {
            id = "yGly-o0Mn1p6_yEriH8dG",
            source = {
                kind = "Virtual",
                id = "RotaryPushC3/Color",
            },
            glue = {
                absolute_mode = "ToggleButton",
                step_size_interval = {0.01, 0.05},
                feedback = {
                    kind = "Text",
                    text_expression = "#d19f2a",
                },
            },
            target = {
                kind = "FxParameterValue",
                parameter = {
                    address = "ById",
                    fx = {
                        address = "Instance",
                    },
                    index = 2,
                },
            },
        },
        {
            id = "s98NjOohBMc8grImcF5hz",
            source = {
                kind = "Virtual",
                id = "RotaryC4",
            },
            glue = {
                step_size_interval = {0.01, 0.05},
                step_factor_interval = {1, 5},
            },
            target = {
                kind = "FxParameterValue",
                parameter = {
                    address = "ById",
                    fx = {
                        address = "Instance",
                    },
                    index = 3,
                },
            },
        },
        {
            id = "psKRJBIIUCcjHl230kRKi",
            source = {
                kind = "Virtual",
                id = "RotaryNameDisplayC4",
            },
            glue = {
                step_size_interval = {0.01, 0.05},
                step_factor_interval = {1, 5},
                feedback = {
                    kind = "Text",
                    text_expression = "{{target.fx_parameter.name}}",
                },
            },
            target = {
                kind = "FxParameterValue",
                parameter = {
                    address = "ById",
                    fx = {
                        address = "Instance",
                    },
                    index = 3,
                },
            },
        },
        {
            id = "kZxVuieUJERqsBUjaUMNt",
            source = {
                kind = "Virtual",
                id = "RotaryValueDisplayC4",
            },
            glue = {
                step_size_interval = {0.01, 0.05},
                step_factor_interval = {1, 5},
                feedback = {
                    kind = "Text",
                },
            },
            target = {
                kind = "FxParameterValue",
                parameter = {
                    address = "ById",
                    fx = {
                        address = "Instance",
                    },
                    index = 3,
                },
            },
        },
        {
            id = "5d21V3xQiAqA-gsM-KRdO",
            source = {
                kind = "Virtual",
                id = "RotaryC4/Color",
            },
            glue = {
                step_size_interval = {0.01, 0.05},
                step_factor_interval = {1, 5},
                feedback = {
                    kind = "Text",
                    text_expression = "#FF0000",
                },
            },
            target = {
                kind = "FxParameterValue",
                parameter = {
                    address = "ById",
                    fx = {
                        address = "Instance",
                    },
                    index = 3,
                },
            },
        },
        {
            id = "NZ_Z8fXyX_at4zCQptGDr",
            source = {
                kind = "Virtual",
                id = "RotaryB6",
            },
            glue = {
                step_size_interval = {0.01, 0.05},
                step_factor_interval = {1, 5},
            },
            target = {
                kind = "FxParameterValue",
                parameter = {
                    address = "ById",
                    fx = {
                        address = "Instance",
                    },
                    index = 6,
                },
            },
        },
        {
            id = "RiL830PFBLT4VBjD7xrPN",
            source = {
                kind = "Virtual",
                id = "RotaryNameDisplayB6",
            },
            glue = {
                step_size_interval = {0.01, 0.05},
                step_factor_interval = {1, 5},
                feedback = {
                    kind = "Text",
                    text_expression = "{{target.fx_parameter.name}}",
                },
            },
            target = {
                kind = "FxParameterValue",
                parameter = {
                    address = "ById",
                    fx = {
                        address = "Instance",
                    },
                    index = 6,
                },
            },
        },
        {
            id = "t1i-nUzq0bSEnTJbFpOUu",
            source = {
                kind = "Virtual",
                id = "RotaryValueDisplayB6",
            },
            glue = {
                step_size_interval = {0.01, 0.05},
                step_factor_interval = {1, 5},
                feedback = {
                    kind = "Text",
                },
            },
            target = {
                kind = "FxParameterValue",
                parameter = {
                    address = "ById",
                    fx = {
                        address = "Instance",
                    },
                    index = 6,
                },
            },
        },
        {
            id = "wPGbqRfFheRXy4RL99DbE",
            source = {
                kind = "Virtual",
                id = "RotaryB6/Color",
            },
            glue = {
                step_size_interval = {0.01, 0.05},
                step_factor_interval = {1, 5},
                feedback = {
                    kind = "Text",
                    text_expression = "#FF0000",
                },
            },
            target = {
                kind = "FxParameterValue",
                parameter = {
                    address = "ById",
                    fx = {
                        address = "Instance",
                    },
                    index = 6,
                },
            },
        },
        {
            id = "S1IQJtthtkIbIYWVtg7oP",
            source = {
                kind = "Virtual",
                id = "RotaryPushB5",
                character = "Button",
            },
            glue = {
                absolute_mode = "ToggleButton",
                step_size_interval = {0.01, 0.05},
            },
            target = {
                kind = "FxParameterValue",
                parameter = {
                    address = "ById",
                    fx = {
                        address = "Instance",
                    },
                    index = 4,
                },
            },
        },
        {
            id = "8lSP05z5JgyBcnsYFboSc",
            source = {
                kind = "Virtual",
                id = "RotaryPushNameDisplayB5",
            },
            glue = {
                absolute_mode = "ToggleButton",
                step_size_interval = {0.01, 0.05},
                feedback = {
                    kind = "Text",
                    text_expression = "{{target.fx_parameter.name}}",
                },
            },
            target = {
                kind = "FxParameterValue",
                parameter = {
                    address = "ById",
                    fx = {
                        address = "Instance",
                    },
                    index = 4,
                },
            },
        },
        {
            id = "iQjc-I70zn1Da2LQHCWJN",
            source = {
                kind = "Virtual",
                id = "RotaryPushValueDisplayB5",
            },
            glue = {
                absolute_mode = "ToggleButton",
                step_size_interval = {0.01, 0.05},
                feedback = {
                    kind = "Text",
                },
            },
            target = {
                kind = "FxParameterValue",
                parameter = {
                    address = "ById",
                    fx = {
                        address = "Instance",
                    },
                    index = 4,
                },
            },
        },
        {
            id = "bNbu08ntYfLTW3V15Bowb",
            source = {
                kind = "Virtual",
                id = "RotaryPushB5/Color",
            },
            glue = {
                absolute_mode = "ToggleButton",
                step_size_interval = {0.01, 0.05},
                feedback = {
                    kind = "Text",
                    text_expression = "#d19f2a",
                },
            },
            target = {
                kind = "FxParameterValue",
                parameter = {
                    address = "ById",
                    fx = {
                        address = "Instance",
                    },
                    index = 4,
                },
            },
        },
        {
            id = "p6J5QJnCg_vEB-W680TLM",
            source = {
                kind = "Virtual",
                id = "RotaryC6",
            },
            glue = {
                step_size_interval = {0.01, 0.05},
                step_factor_interval = {1, 5},
            },
            target = {
                kind = "FxParameterValue",
                parameter = {
                    address = "ById",
                    fx = {
                        address = "Instance",
                    },
                    index = 7,
                },
            },
        },
        {
            id = "i9wr82r4Ghkx-mmWquYsx",
            source = {
                kind = "Virtual",
                id = "RotaryNameDisplayC6",
            },
            glue = {
                step_size_interval = {0.01, 0.05},
                step_factor_interval = {1, 5},
                feedback = {
                    kind = "Text",
                    text_expression = "{{target.fx_parameter.name}}",
                },
            },
            target = {
                kind = "FxParameterValue",
                parameter = {
                    address = "ById",
                    fx = {
                        address = "Instance",
                    },
                    index = 7,
                },
            },
        },
        {
            id = "mL4dMYrpchB1P7eaannct",
            source = {
                kind = "Virtual",
                id = "RotaryValueDisplayC6",
            },
            glue = {
                step_size_interval = {0.01, 0.05},
                step_factor_interval = {1, 5},
                feedback = {
                    kind = "Text",
                },
            },
            target = {
                kind = "FxParameterValue",
                parameter = {
                    address = "ById",
                    fx = {
                        address = "Instance",
                    },
                    index = 7,
                },
            },
        },
        {
            id = "zNvaxDrYw6G61R11s-w4s",
            source = {
                kind = "Virtual",
                id = "RotaryC6/Color",
            },
            glue = {
                step_size_interval = {0.01, 0.05},
                step_factor_interval = {1, 5},
                feedback = {
                    kind = "Text",
                    text_expression = "#FF0000",
                },
            },
            target = {
                kind = "FxParameterValue",
                parameter = {
                    address = "ById",
                    fx = {
                        address = "Instance",
                    },
                    index = 7,
                },
            },
        },
        {
            id = "LNsYHeY6Pg-o83HD5jpaG",
            source = {
                kind = "Virtual",
                id = "RotaryPushC5",
                character = "Button",
            },
            glue = {
                absolute_mode = "ToggleButton",
                step_size_interval = {0.01, 0.05},
            },
            target = {
                kind = "FxParameterValue",
                parameter = {
                    address = "ById",
                    fx = {
                        address = "Instance",
                    },
                    index = 5,
                },
            },
        },
        {
            id = "IQpxPGUH3c4zF8emEE6Zc",
            source = {
                kind = "Virtual",
                id = "RotaryPushNameDisplayC5",
            },
            glue = {
                step_size_interval = {0.01, 0.05},
                step_factor_interval = {1, 5},
                feedback = {
                    kind = "Text",
                    text_expression = "{{target.fx_parameter.name}}",
                },
            },
            target = {
                kind = "FxParameterValue",
                parameter = {
                    address = "ById",
                    fx = {
                        address = "Instance",
                    },
                    index = 5,
                },
            },
        },
        {
            id = "5yO1P5NpPb4JVAoFN6QMN",
            source = {
                kind = "Virtual",
                id = "RotaryPushValueDisplayC5",
            },
            glue = {
                step_size_interval = {0.01, 0.05},
                step_factor_interval = {1, 5},
                feedback = {
                    kind = "Text",
                },
            },
            target = {
                kind = "FxParameterValue",
                parameter = {
                    address = "ById",
                    fx = {
                        address = "Instance",
                    },
                    index = 5,
                },
            },
        },
        {
            id = "GANA8i9bN7w7fYGP0L6_j",
            source = {
                kind = "Virtual",
                id = "RotaryPushC5/Color",
            },
            glue = {
                absolute_mode = "ToggleButton",
                step_size_interval = {0.01, 0.05},
                feedback = {
                    kind = "Text",
                    text_expression = "#d19f2a",
                },
            },
            target = {
                kind = "FxParameterValue",
                parameter = {
                    address = "ById",
                    fx = {
                        address = "Instance",
                    },
                    index = 5,
                },
            },
        },
        {
            id = "KPkzyBei9wy724iFjArv6",
            source = {
                kind = "Virtual",
                id = "FXBypass",
                character = "Button",
            },
            glue = {
                absolute_mode = "ToggleButton",
                reverse = true,
                step_size_interval = {0.01, 0.05},
            },
            target = {
                kind = "FxOnOffState",
                fx = {
                    address = "Instance",
                },
            },
        },
        {
            id = "G1jC9mSuC4YuIwu4kvfEd",
            source = {
                kind = "Virtual",
                id = "FXWet",
            },
            glue = {
                step_size_interval = {0.01, 0.05},
                step_factor_interval = {1, 5},
            },
            target = {
                kind = "FxParameterValue",
                parameter = {
                    address = "ById",
                    fx = {
                        address = "Instance",
                    },
                    index = 10,
                },
            },
        },
        {
            id = "YxHJeZ0_D3Ap8GaJTn1C4",
            source = {
                kind = "Virtual",
                id = "FXWetValueDisplay",
            },
            glue = {
                step_size_interval = {0.01, 0.05},
                step_factor_interval = {1, 5},
                feedback = {
                    kind = "Text",
                },
            },
            target = {
                kind = "FxParameterValue",
                parameter = {
                    address = "ById",
                    fx = {
                        address = "Instance",
                    },
                    index = 10,
                },
            },
        },
        {
            id = "PwA1kLcYm0k0fFIVhM3YW",
            name = "31",
            source = {
                kind = "Virtual",
                id = "FXDelta",
                character = "Button",
            },
            glue = {
                absolute_mode = "ToggleButton",
                step_size_interval = {0.01, 0.05},
            },
            target = {
                kind = "FxParameterValue",
                parameter = {
                    address = "ById",
                    fx = {
                        address = "Instance",
                    },
                    index = 11,
                },
            },
        },
        {
            id = "Sfltka4TmO0kvK1kgpT2p",
            name = "33",
            source = {
                kind = "Virtual",
                id = "FXName",
            },
            glue = {
                step_size_interval = {0.01, 0.05},
                step_factor_interval = {1, 5},
                feedback = {
                    kind = "Text",
                    text_expression = "SuperCharger",
                },
            },
            target = {
                kind = "Dummy",
            },
        },
    },
}
Basically, it's a touch complex for me personally and while I get the idea of what I'd be doing, I just don't know where to start or the best way to do it.
Puck is online now   Reply With Quote
Old 11-20-2022, 02:10 PM   #2943
vonglan
Human being with feelings
 
Join Date: Oct 2019
Location: Lübeck, Germany
Posts: 46
Default

Quote:
Originally Posted by Puck View Post
Thanks for chiming in vonglan! Here's an example of what I'd like to do. ...
Did you find the example that Benjamin gave here:
https://forum.cockos.com/showpost.ph...postcount=1652
?

It seems you are counting up the target index. And then for each index you have about 5 different mapping types (name display, value display, color, ...).
But you also have some alphanumerical field C2, C3, C4, B5. Or are the B/C variations just by accident?

You would then best create a table that relates the index to the alphanumerical ID.
One way would be like this:

relation = { 'C2', 'C3', 'C4', 'B5' }

You then have a loop, like in Benjamin's simple example. If there are 4 relations (it seems you have many more, but as an example) that would be:

for i=1,4 do

In that loop, you have one mapping for each of your different mapping types.

For each mapping, you need to replace the actual value (e.g. "1") with a value based on the loop index.
- For numbers, you just use i (or a formula, like i+1)
- For strings (in quotes), you have to use .. (two dots) to connect various strings to one big string
- to use the alphanumerical id, you have to get it from the relation table: relation[i]

At the end of each mapping, instead of inserting the mapping in the mappings list via index (Benjamin's example), I recommend the more general

table.insert(mappings, mapping)
vonglan is offline   Reply With Quote
Old 11-20-2022, 02:11 PM   #2944
Puck
Human being with feelings
 
Puck's Avatar
 
Join Date: Feb 2022
Location: Almost Canada
Posts: 494
Default

Quote:
Originally Posted by sonicowl View Post
Helgoboss, ReaLearn is really good. One thing I cannot figure out, and need some help. I'd like to map Track Controls to Selected Track. Meaning that I have 8 knobs on controller dedicated for the first 8 Track controls on any selected track, with midi feedback for knob leds. Which target type enables this? Thnx.

I haven't tried it but since I've been reading the user guide I've ran across this:


E.g. selected_fx_parameter_indexes[2] will resolve to the index of the third FX parameter displayed in the track control panel.

This only makes sense if used in conjunction with tcp_fx_indexes.

....

Presumably your fx mapping for the first track control would look like this:

FX Parameter: Set Value
Track <Selected>
FX <This> or <instance> (I wouldn't think this matters)
Parameter <Dynamic> selected_fx_parameter_indexes[0]

I apologize if this is wrong. Just trying to help and if you were out of ideas, here's one that has a good chance of working
Puck is online now   Reply With Quote
Old 11-20-2022, 02:23 PM   #2945
helgoboss
Human being with feelings
 
helgoboss's Avatar
 
Join Date: Aug 2010
Location: Germany
Posts: 1,885
Default

Quote:
Originally Posted by Puck View Post
Unfortunately, the only way I know to attack this is to make huge macros and/or search/replace copy/paste sort of operations. I don't really have a problem doing that, however I was wondering, are there processes out there that would make this a little more sophisticated that I should look into?

Right now the process would be to learn many in realearn. Hook up control elements to parameters. Export that into a text editor and run the macros to generate necessary lua. Is that how you would go about it?
I was more thinking along the lines of what vonglan suggested. Search&replace is of course also an option, but it's super annoying, no?
helgoboss is offline   Reply With Quote
Old 11-20-2022, 02:25 PM   #2946
Puck
Human being with feelings
 
Puck's Avatar
 
Join Date: Feb 2022
Location: Almost Canada
Posts: 494
Default

Quote:
Originally Posted by vonglan View Post
Did you find the example that Benjamin gave here:
https://forum.cockos.com/showpost.ph...postcount=1652
?

It seems you are counting up the target index. And then for each index you have about 5 different mapping types (name display, value display, color, ...).
But you also have some alphanumerical field C2, C3, C4, B5. Or are the B/C variations just by accident?

You would then best create a table that relates the index to the alphanumerical ID.
One way would be like this:

relation = { 'C2', 'C3', 'C4', 'B5' }

You then have a loop, like in Benjamin's simple example. If there are 4 relations (it seems you have many more, but as an example) that would be:

for i=1,4 do

In that loop, you have one mapping for each of your different mapping types.

For each mapping, you need to replace the actual value (e.g. "1") with a value based on the loop index.
- For numbers, you just use i (or a formula, like i+1)
- For strings (in quotes), you have to use .. (two dots) to connect various strings to one big string
- to use the alphanumerical id, you have to get it from the relation table: relation[i]

At the end of each mapping, instead of inserting the mapping in the mappings list via index (Benjamin's example), I recommend the more general

table.insert(mappings, mapping)
I definitely appreciate this. Thanks for taking the time to look and the time to explain!

The B3/C4 stuff is referencing my layout. RotaryB3 is the 3rd rotary on row B, etc.

And while this is definitely a step in the right direction, I'm still not sure where to go. In Benjamin's example (thanks for that by the way!) it's nice and clean. He's taking a group of consecutive CC's and making them control one thing (TrackVolume)

With what I'm doing, the controls aren't consecutive (the relation table you provide would take care of this) and the things I'm controlling are all over the place, different parameter index numbers and the like. That index number is tied to the parameter list in a given plugin and it definitely doesn't always line up that way where it's clean. But on top of that, there's also a different set of rules I'd use for RotaryPush(the buttons) as opposed to Rotary. This is adding alot of layers (in my mind anyways) and I don't have my head fully wrapped around a solution yet. But your reply did help quite a bit.
Puck is online now   Reply With Quote
Old 11-20-2022, 02:26 PM   #2947
Puck
Human being with feelings
 
Puck's Avatar
 
Join Date: Feb 2022
Location: Almost Canada
Posts: 494
Default

Quote:
Originally Posted by helgoboss View Post
I was more thinking along the lines of what vonglan suggested. Search&replace is of course also an option, but it's super annoying, no?
YES

I replied to vonglan just now. I am learning basic computer programming now so this would be a good test for me.
Puck is online now   Reply With Quote
Old 11-20-2022, 02:27 PM   #2948
helgoboss
Human being with feelings
 
helgoboss's Avatar
 
Join Date: Aug 2010
Location: Germany
Posts: 1,885
Default

Quote:
Originally Posted by Puck View Post
One minor niggle:

I have touch messages set up on my FX page. When learning, that's the first thing that Realearn sees so it "learns" that instead of the actual rotary. I tried disabling the touch messages via a modifier in the controller preset but I found (and this makes complete sense) that just disables the virtual widgets. Realearn would then "learn" the OSC source with the touch message. I'm not quite sure how to even suggest getting around this but I remember someone else in recent memory had a similar issue.

I suppose this also means that I would have to have a 5th message per mapping as I have forgotten about the touch automation. It seems to me that the touch messages should just work automagically behind the scenes and they should also be ignored when learning?
ReaLearn doesn't pretend to know what's a touch and what's not. It treats each control event equally. And sometimes it's exactly the touch event that you want to learn. I usually work around this by touching the element before moving/turning.

I can imagine though that this can confuse first-time users who don't even know that there's such a thing as touch (e.g. motor fader touch). Maybe I could add some kind of warning ... but how to make it unobtrusive, I don't know yet.
helgoboss is offline   Reply With Quote
Old 11-20-2022, 02:27 PM   #2949
vonglan
Human being with feelings
 
Join Date: Oct 2019
Location: Lübeck, Germany
Posts: 46
Default

Another question, copied from #567:

Best way to use one virtual button to toggle between two different Reaper actions?

Use case: button to switch between track recording modes "MIDI overdub" and "MIDI replace".
Restriction: mappings should be in Main Mapping, based on virtual button as source.

I currently solved it with two mappings "Fire after single press" and "Fire on double click". Not exactly what I wanted, but does the job.

I assume another solution would be to let the button toggle a ReaLearn parameter on/off, and then use the new source "Reaper: ReaLearn parameter" in two further mappings.

Is there another (simpler) way?
vonglan is offline   Reply With Quote
Old 11-20-2022, 02:30 PM   #2950
Puck
Human being with feelings
 
Puck's Avatar
 
Join Date: Feb 2022
Location: Almost Canada
Posts: 494
Default

Quote:
Originally Posted by helgoboss View Post
ReaLearn doesn't pretend to know what's a touch and what's not. It treats each control event equally. And sometimes it's exactly the touch event that you want to learn. I usually work around this by touching the element before moving/turning.

I can imagine though that this can confuse first-time users who don't even know that there's such a thing as touch (e.g. motor fader touch). Maybe I could add some kind of warning ... but how to make it unobtrusive, I don't know yet.
Touching before learning is a nice workaround. But that doesn't help with "learn many"

I maybe able to alter my TouchOSC layout to toggle the touch messages. I'll have a think about that.
Puck is online now   Reply With Quote
Old 11-20-2022, 02:39 PM   #2951
vonglan
Human being with feelings
 
Join Date: Oct 2019
Location: Lübeck, Germany
Posts: 46
Default

Quote:
Originally Posted by Puck View Post
With what I'm doing, the controls aren't consecutive ...
You need to structure the complete work:
- mappings which are just a sequence (like in Benjamin's example), maybe several sets of these
- maybe mappings which are a matrix (rows and columns), requiring two nested loops
- and things which are "singular" and therefore best added manually (tip: keep the Lua-generated mappings in a separate group, so you just replace the mappings in that group every time you change the Lua code)

Another issue might be the parameter numbers in the VSTs.
Usually you will see some pattern, e.g. for an FM synthesizer you will find something like:
- Parameter 1 = Operator 1 Frequency Rough
- Parameter 2 = Operator 1 Frequency Fine
- Parameter 3 = Operator 1 Volume
- ...
- Parameter 129 = Operator 2 Frequency Rough
- Parameter 130 = Operator 2 Frequency Fine
- Parameter 131 = Operator 2 Volume
- ...
- Parameter 257 = Operator 2 Frequency Rough
- Parameter 258 = Operator 2 Frequency Fine
- Parameter 259 = Operator 2 Volume
- ...

You can then program a loop over the operators, and set the parameters with a formula like
op_index * 128 + 1
(for Frequency Rough)

If the parameters are not in a neat sequence (usually they are), then you could work with a relation table again. (I am avoiding to call it a mapping table ;-)

Yes, I think Lua-generated mappings are a nice exercise when you are learning to program, because you do not have to learn the complete vocabulary of the programming language, only a relatively small subset.
vonglan is offline   Reply With Quote
Old 11-20-2022, 02:41 PM   #2952
helgoboss
Human being with feelings
 
helgoboss's Avatar
 
Join Date: Aug 2010
Location: Germany
Posts: 1,885
Default

Quote:
Originally Posted by Puck View Post
I haven't tried it but since I've been reading the user guide I've ran across this:


E.g. selected_fx_parameter_indexes[2] will resolve to the index of the third FX parameter displayed in the track control panel.

This only makes sense if used in conjunction with tcp_fx_indexes.

....

Presumably your fx mapping for the first track control would look like this:

FX Parameter: Set Value
Track <Selected>
FX <This> or <instance> (I wouldn't think this matters)
Parameter <Dynamic> selected_fx_parameter_indexes[0]

I apologize if this is wrong. Just trying to help and if you were out of ideas, here's one that has a good chance of working
Almost. It's tcp_fx_indexes for the dynamic FX selector and tcp_fx_parameter_indexes for the dynamic parameter selector. You would use "tcp_fx_indexes[0]" (for FX) in combination with "tcp_fx_parameter_indexes[0]" (for parameter) for addressing the first track panel control, for example.
helgoboss is offline   Reply With Quote
Old 11-20-2022, 02:46 PM   #2953
helgoboss
Human being with feelings
 
helgoboss's Avatar
 
Join Date: Aug 2010
Location: Germany
Posts: 1,885
Default

Quote:
Originally Posted by Puck View Post
Touching before learning is a nice workaround. But that doesn't help with "learn many"

I maybe able to alter my TouchOSC layout to toggle the touch messages. I'll have a think about that.
Oh right, didn't think about that ... mmmmmh. Maybe I could add a global checkbox to ignore OSC addresses and virtual control IDs that include the word "touch"? I slightly remember having discussed this idea somewhere already. Maybe there's an FR already. If not, feel free to create one.
helgoboss is offline   Reply With Quote
Old 11-20-2022, 03:39 PM   #2954
sonicowl
Human being with feelings
 
sonicowl's Avatar
 
Join Date: Oct 2015
Posts: 691
Default

Quote:
Originally Posted by helgoboss View Post
Almost. It's tcp_fx_indexes for the dynamic FX selector and tcp_fx_parameter_indexes for the dynamic parameter selector. You would use "tcp_fx_indexes[0]" (for FX) in combination with "tcp_fx_parameter_indexes[0]" (for parameter) for addressing the first track panel control, for example.
EDITED...
==========
I tried, but not able to set the following:
FX Parameter: Set Value
Track <Selected>
FX <This> or <instance> (I wouldn't think this matters)
Parameter <Dynamic> selected_fx_parameter_indexes[0]

When I set FX Parameter-Set Value, then there is no option for Track <Selected>. I would have to use one of the Track Types, but then there is no Parameter <Dynamic>.

I think something is missing, or I'm doing something wrong?

Plus, I have no idea how to achieve what you say "use in combination". Do I need to map it twice? Or use (*), like this?: "tcp_fx_indexes[0] * tcp_fx_parameter_indexes[0]"
========

Nevermind, figured it out. It is:
Type: FX Parameter: Set Value
Track: Selected (becomes visible ONLY when below two are selected too)
FX: Dynamic : tcp_fx_indexes[0]
Parameter: Dynamic: tcp_fx_parameter_indexes[0]

Last edited by sonicowl; 11-20-2022 at 03:54 PM.
sonicowl is offline   Reply With Quote
Old 11-21-2022, 10:22 AM   #2955
Puck
Human being with feelings
 
Puck's Avatar
 
Join Date: Feb 2022
Location: Almost Canada
Posts: 494
Default

When loading either the same instance of a plugin or a different instance of the same plugin. Realearn doesn’t send the FX name. That makes sense because if it hasn’t changed, why send the same string.

My whole template is based on when the fx name changes, though. When you load a plugin and that name changes, TouchOSC automatically takes you to the FX page. It’s pretty nice but falls apart when you want to load the same plugin. Am I going to have to rethink the logic on my end or is there a way I could sort of force that FX name to be sent?

I suppose this also falls into the category of Realearn is declarative and it’s goal is not for us to have to tell it what to do.

By the way I started using pinning as instance FX, thanks for the help there! I may go back to focused to try the new functionality out in the next pre.
Puck is online now   Reply With Quote
Old 11-21-2022, 10:54 AM   #2956
helgoboss
Human being with feelings
 
helgoboss's Avatar
 
Join Date: Aug 2010
Location: Germany
Posts: 1,885
Default

Quote:
Originally Posted by Puck View Post
When loading either the same instance of a plugin or a different instance of the same plugin. Realearn doesn’t send the FX name. That makes sense because if it hasn’t changed, why send the same string.

My whole template is based on when the fx name changes, though. When you load a plugin and that name changes, TouchOSC automatically takes you to the FX page. It’s pretty nice but falls apart when you want to load the same plugin. Am I going to have to rethink the logic on my end or is there a way I could sort of force that FX name to be sent?

I suppose this also falls into the category of Realearn is declarative and it’s goal is not for us to have to tell it what to do.

By the way I started using pinning as instance FX, thanks for the help there! I may go back to focused to try the new functionality out in the next pre.
Can you go into detail what your setup does if it receives an FX name Update?
helgoboss is offline   Reply With Quote
Old 11-21-2022, 11:21 AM   #2957
Puck
Human being with feelings
 
Puck's Avatar
 
Join Date: Feb 2022
Location: Almost Canada
Posts: 494
Default

Quote:
Originally Posted by helgoboss View Post
Can you go into detail what your setup does if it receives an FX name Update?
I have two main pages. Daw control stuff is on the first and FX stuff is on the second. At the top of the FX page I have a label that displays the FX name. In the script section of that label there is some LUA that says:

Code:
function onValueChanged(key,value)
   if key == ‘text’ and self.values.text ~= “” then
       root.children.pager1.values.page = 1
   end
end
onValueChanged is a callback function and fires every time any value changes on the control. So basically, if that label changes and it’s not an empty string, the layout switches to the 2nd page.
Puck is online now   Reply With Quote
Old 11-21-2022, 12:34 PM   #2958
vonglan
Human being with feelings
 
Join Date: Oct 2019
Location: Lübeck, Germany
Posts: 46
Default

Quote:
Originally Posted by helgoboss View Post
Maybe using "Project: Browse tracks" in one mapping and "Track: Mute/unmute" in the mapping below (with track "Selected" and exclusive "Within folder (on only)"). The problem is that "Project: Browse tracks" doesn't operate in one folder only. There's an FR though.
This works fine.

I did not find a FR for "Browse Tracks" with folders. Anyway, in my use case, because I have a project template for Super 8 with a fixed number and position of source tracks, I can simply use target min/max.

For mute/unmute, I needed "Within folder", target min=max=0

By the way, the arrows for switching to previous/next mapping are great!
vonglan is offline   Reply With Quote
Old 11-21-2022, 02:11 PM   #2959
helgoboss
Human being with feelings
 
helgoboss's Avatar
 
Join Date: Aug 2010
Location: Germany
Posts: 1,885
Default

Quote:
Originally Posted by Puck View Post
I have two main pages. Daw control stuff is on the first and FX stuff is on the second. At the top of the FX page I have a label that displays the FX name. In the script section of that label there is some LUA that says:

Code:
function onValueChanged(key,value)
   if key == ‘text’ and self.values.text ~= “” then
       root.children.pager1.values.page = 1
   end
end
onValueChanged is a callback function and fires every time any value changes on the control. So basically, if that label changes and it’s not an empty string, the layout switches to the 2nd page.
Understand. But even if ReaLearn wouldn't mind duplicate feedback and fire the same FX name again, would that even count as change? For TouchOSC?
helgoboss is offline   Reply With Quote
Old 11-21-2022, 02:16 PM   #2960
helgoboss
Human being with feelings
 
helgoboss's Avatar
 
Join Date: Aug 2010
Location: Germany
Posts: 1,885
Default

Released ReaLearn 2.14.0-pre.11 (ReaPack installation instructions)

Changes:
- Migrated to Rust 1.65.0
- #763 Added new MIDI source "Specific program change" (which makes it more straightforward to react to specific programs)
- #529 Added dynamic track expression variables "instance_track_tcp_index" and "instance_track_mcp_index"
- #764 Improved usability by allowing raw MIDI pattern (e.g. sysex) to be edited in separate editor window which also indicates whether the pattern is valid (both in source and target)
- #770 Fixed FX still being considered as focused when focus is changed from the FX window to the main area
- #760 Fixed track peak target not respecting solo state of other tracks
- #761 Fixed action target invocation mode 7-bit/14-bit confusion (existing presets will automatically be migrated, so existing behavior will not change)
- #775 Fixed failed scan on macOS El Capitan (ReaLearn stopped working on it since v2.13, fixed by removing Prometheus metrics support for macOS Intel builds)
- #762 Fixed crash when pressing a key on older macOS installations (a problem since 2.14.0-pre.6)
- #529 Fixed unreliable refresh of dynamic track result UI refresh in target section of mapping panel
- #221 Fixed failing NKS sub filter item gathering in pot target
helgoboss is offline   Reply With Quote
Reply

Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump


All times are GMT -7. The time now is 05:13 PM.


Powered by vBulletin® Version 3.8.11
Copyright ©2000 - 2023, vBulletin Solutions Inc.