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

Reply
 
Thread Tools Display Modes
Old 11-21-2022, 03:23 PM   #2961
Puck
Human being with feelings
 
Puck's Avatar
 
Join Date: Feb 2022
Location: Almost Canada
Posts: 499
Default

Quote:
Originally Posted by helgoboss View Post
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?
Good catch, Helgoboss! It does not count as a change. Just tested it.

I think I can just rework my logic here and be fine. I can take the FXButtonLabel that I'm using to set the instance track and if that matches the Label on the FX page then I can also switch pages. It will be easier when the FX alias feature comes to light but I'm sure I could make it work with partial string matches as it sits.

Either that or I can go back to a FocusedFX approach. That way the label will be blank when we click off anywhere.
Puck is offline   Reply With Quote
Old 11-22-2022, 07:33 AM   #2962
RamboMadCow
Human being with feelings
 
Join Date: Nov 2022
Posts: 14
Default

So I'm experiencing a new issue with the mapping and haven't been able to figure out why it's happening or how to work around it.

I was able to successfully map 16 MIDI PC messages to change to 16 different songs using the correct method that @helgoboss laid out for me a few days ago. For reference, when I press each switch it unmutes the track it's assign to while muting everything else except the selected song. Everything was working great. Then I decided to make one change on one of the switches.

I decided to change my switch that sends MIDI Channel 1 PC 0 from selecting a song, to using the Reaper Play/Stop function. This way I could have this functionality on this foot controller without having to use a secondary controller. However, the behavior I was experiencing was not what I expected. To make this selection work, I had to set Mode to "Toggle button". If I left it in Normal, every time I pressed the switch it was execute a Stop followed by a Play, resulting in constantly restarting the song and unable to completed stop.

However...When set to Toggle button, for some reason all of my other switches except PC 1 would switch to the track AND execute the Play/Stop functionality when the Play/Stop switch was set to Toggle button. This is a bit surprising to because when I got the song selection step done correctly after helgoboss' advice, I simply just duplicated the action, changed the song it should select, and update the source Min/Max accordingly. This explains why all 10 switches worked flawlessly when using them to select songs.

After a frustrating attempt at trying to figure out why this only happens when using Reaper Play/Stop and only on Toggle button for the mode, I decided to change that switch over to Channel 2 PC 0. I tested the switch in Reaper by selecting some action and Adding a shortcut and pressing the switch. Reaper successfully saw it as MIDI Channel 2 PC 0 - However...ReaLearn somehow still interpreted this as Channel 1 PC 0 thus resulting in the exact same incorrect behavior as before.

I attempted to manually set this definition to Channel 2 in the Mapping panel, but this resulted in the switch no longer registering with ReaLearn.

Has anyone experienced this before and know how to work around it or fix it? Ideally it'd be nice to do it without forcing this switch to be Channel 2, but if there's a way to make it work on Channel 2 that's fine.
RamboMadCow is offline   Reply With Quote
Old 11-22-2022, 09:08 AM   #2963
helgoboss
Human being with feelings
 
helgoboss's Avatar
 
Join Date: Aug 2010
Location: Germany
Posts: 1,951
Default

Quote:
Originally Posted by Puck View Post
Good catch, Helgoboss! It does not count as a change. Just tested it.

I think I can just rework my logic here and be fine. I can take the FXButtonLabel that I'm using to set the instance track and if that matches the Label on the FX page then I can also switch pages. It will be easier when the FX alias feature comes to light but I'm sure I could make it work with partial string matches as it sits.

Either that or I can go back to a FocusedFX approach. That way the label will be blank when we click off anywhere.
It sounds like what you really need is a kind of signal (feedback message) that fires whenever a new FX is added (or an existing one is replaced) and becomes the instance FX. And that signal doesn't need to contain any value, it's just a trigger. Right?
helgoboss is offline   Reply With Quote
Old 11-22-2022, 09:22 AM   #2964
Puck
Human being with feelings
 
Puck's Avatar
 
Join Date: Feb 2022
Location: Almost Canada
Posts: 499
Default

Quote:
Originally Posted by helgoboss View Post
It sounds like what you really need is a kind of signal (feedback message) that fires whenever a new FX is added (or an existing one is replaced) and becomes the instance FX. And that signal doesn't need to contain any value, it's just a trigger. Right?
Right! I didnít realize thatís what I wanted but yes that would work.

On the other hand, what we have now basically works well except for when you want to load the same plugin. This feature request would just be for me only as I canít think of another use case. If I can take care of the logic on my side maybe itís better I do that instead of potentially bloating Realearn for something that just applies to me.
Puck is offline   Reply With Quote
Old 11-22-2022, 10:11 AM   #2965
helgoboss
Human being with feelings
 
helgoboss's Avatar
 
Join Date: Aug 2010
Location: Germany
Posts: 1,951
Default

Quote:
Originally Posted by Puck View Post
Right! I didnít realize thatís what I wanted but yes that would work.

On the other hand, what we have now basically works well except for when you want to load the same plugin. This feature request would just be for me only as I canít think of another use case. If I can take care of the logic on my side maybe itís better I do that instead of potentially bloating Realearn for something that just applies to me.
Yes ... Just asking to get an idea of the bigger picture. There might be others who have different but maybe similar use cases. Will think about it and hope to arrive at some kind of generalized solution for this.
helgoboss is offline   Reply With Quote
Old 11-22-2022, 10:25 AM   #2966
Puck
Human being with feelings
 
Puck's Avatar
 
Join Date: Feb 2022
Location: Almost Canada
Posts: 499
Default

Quote:
Originally Posted by helgoboss View Post
Yes ... Just asking to get an idea of the bigger picture. There might be others who have different but maybe similar use cases. Will think about it and hope to arrive at some kind of generalized solution for this.
For a generalized solution, my head goes to the following;

1. Realearn adds virtual sources. Youíd have to call them something else as you already have virtual sources from controllers presets. But what I mean is, have a source that triggers when certain things happen (i.e. init, when project is playing, when project stops, instance fx instantiated, fx unfocus)

2. We flesh out SendOSCMessage and SendMidiMessage (not sure of the state of the midi variant) that users can pair with the virtual (again, theyíd be called something else) sources.

With the above I could use the ďnew instance fxĒ source and send whatever message I wanted. In my case I could set up an osc message that controls the pages of my layout.
Puck is offline   Reply With Quote
Old 11-22-2022, 10:49 AM   #2967
helgoboss
Human being with feelings
 
helgoboss's Avatar
 
Join Date: Aug 2010
Location: Germany
Posts: 1,951
Default

Quote:
Originally Posted by RamboMadCow View Post
I decided to change my switch that sends MIDI Channel 1 PC 0 from selecting a song, to using the Reaper Play/Stop function. This way I could have this functionality on this foot controller without having to use a secondary controller. However, the behavior I was experiencing was not what I expected. To make this selection work, I had to set Mode to "Toggle button". If I left it in Normal, every time I pressed the switch it was execute a Stop followed by a Play, resulting in constantly restarting the song and unable to completed stop.
This is expected behavior. If you want to toggle between play and stop with each button press, you need to use "Toggle button", yes! If you don't do this, it will just always invoke "Play" because your program change message is always the same. Invoking "Play" repeatedly in REAPER has the effect of starting again from the edit cursor.

I recommend to watch my video tutorials, they cover this.

Quote:
Originally Posted by RamboMadCow View Post
However...When set to Toggle button, for some reason all of my other switches except PC 1 would switch to the track AND execute the Play/Stop functionality when the Play/Stop switch was set to Toggle button. This is a bit surprising to because when I got the song selection step done correctly after helgoboss' advice, I simply just duplicated the action, changed the song it should select, and update the source Min/Max accordingly. This explains why all 10 switches worked flawlessly when using them to select songs.
That means you got your "Play/Stop" mapping wrong: Source min/max both must be 0, out-of-range must be "Ignore". The other mappings must have the same settings but min/max set to 1, 2 and so on.

If you really don't get it running, you can send me the result of "Export from clipboard => Export main compartment as Lua" and I'll have a look.

BTW, in case you didn't realize, there's a new "Specific program change" source now which doesn't require messing with the glue settings! Only thing: It's not the default yet when pressing "Learn source". I'll change that for the final release.

Quote:
Originally Posted by RamboMadCow View Post
After a frustrating attempt at trying to figure out why this only happens when using Reaper Play/Stop and only on Toggle button for the mode, I decided to change that switch over to Channel 2 PC 0. I tested the switch in Reaper by selecting some action and Adding a shortcut and pressing the switch. Reaper successfully saw it as MIDI Channel 2 PC 0 - However...ReaLearn somehow still interpreted this as Channel 1 PC 0 thus resulting in the exact same incorrect behavior as before.

I attempted to manually set this definition to Channel 2 in the Mapping panel, but this resulted in the switch no longer registering with ReaLearn.

Has anyone experienced this before and know how to work around it or fix it? Ideally it'd be nice to do it without forcing this switch to be Channel 2, but if there's a way to make it work on Channel 2 that's fine.
There must be something weird about your setup. If ReaLearn sees channel 1, then it means it gets channel 1. Troubleshooting: Are you using input "FX input"? If yes, try not to use it. Use the specific device instead. If you have to use "FX input", make absolutely sure that you accidentally mapped the MIDI track input to channel 1 (using REAPER track controls).

But you don't have to change the channel at all! So try above suggestions first.
helgoboss is offline   Reply With Quote
Old 11-22-2022, 11:00 AM   #2968
helgoboss
Human being with feelings
 
helgoboss's Avatar
 
Join Date: Aug 2010
Location: Germany
Posts: 1,951
Default

Quote:
Originally Posted by Puck View Post
For a generalized solution, my head goes to the following;

1. Realearn adds virtual sources. You’d have to call them something else as you already have virtual sources from controllers presets. But what I mean is, have a source that triggers when certain things happen (i.e. init, when project is playing, when project stops, instance fx instantiated, fx unfocus)

2. We flesh out SendOSCMessage and SendMidiMessage (not sure of the state of the midi variant) that users can pair with the virtual (again, they’d be called something else) sources.

With the above I could use the “new instance fx” source and send whatever message I wanted. In my case I could set up an osc message that controls the pages of my layout.
No need for a new kind of virtual source and fleshed out targets for sending OSC/MIDI! Just change perspective and gain the insight that information can also flow from target to source. Imagine the target as the sender and the source as the receiver.

Or simply, in other words: The direction from target to source is called "feedback direction". Feedback is the thing that makes your controller (source) reflect changes that happen within REAPER (target) ... which is exactly what you want, BTW.

As soon as you internalize this, your idea boils down to one thing: A "new instance FX" target. Much easier.
helgoboss is offline   Reply With Quote
Old 11-22-2022, 11:16 AM   #2969
Puck
Human being with feelings
 
Puck's Avatar
 
Join Date: Feb 2022
Location: Almost Canada
Posts: 499
Default

Quote:
Originally Posted by helgoboss View Post
No need for a new kind of virtual source and fleshed out targets for sending OSC/MIDI! Just change perspective and gain the insight that information can also flow from target to source. Imagine the target as the sender and the source as the receiver.

Or simply, in other words: The direction from target to source is called "feedback direction". Feedback is the thing that makes your controller (source) reflect changes that happen within REAPER (target).

As soon as you internalize this, your idea boils down to one thing: A "new instance FX" target. Much easier.
Amazing!

Yes you are right I have yet to internalize that. That explanation helped immensely!
Puck is offline   Reply With Quote
Old 11-22-2022, 12:35 PM   #2970
Puck
Human being with feelings
 
Puck's Avatar
 
Join Date: Feb 2022
Location: Almost Canada
Posts: 499
Default With regard to building mappings with LUA and FX

@helgoboss and @vonglan or anyone else

One point of friction is pairing fx parameters with the correct sources. Helgoboss was right when he said that what I’m doing is complex and repetitive. So I need to make this as easy as possible.

CSI faces a similar problem. A few of us made what we call FX configurators in excel where we made the connections via dropdown menus and fill color. After you filled everything out, the configurator would spit out a text file to use as an fx zone in CSI. I could do the same thing here and it could spit out the tables needed for the LUA looping structure I would set up.

My question is this;

Each mapping would have 3 attributes (source/target/color) so I think my goal would be to output from my fx configurator a table of tables? Then I could pop those tables into the top of the LUA code and load it into Realearn. Admittedly that’s more complex than anything I’ve done thus far but I was just asking to see if I was on the right track or if I should think about it differently? Any guidance is appreciated immensely.
Puck is offline   Reply With Quote
Old 11-22-2022, 12:41 PM   #2971
RamboMadCow
Human being with feelings
 
Join Date: Nov 2022
Posts: 14
Default

Quote:
Originally Posted by helgoboss View Post
That means you got your "Play/Stop" mapping wrong: Source min/max both must be 0, out-of-range must be "Ignore". The other mappings must have the same settings but min/max set to 1, 2 and so on.

If you really don't get it running, you can send me the result of "Export from clipboard => Export main compartment as Lua" and I'll have a look.
There must be something weird about your setup. If ReaLearn sees channel 1, then it means it gets channel 1. Troubleshooting: Are you using input "FX input"? If yes, try not to use it. Use the specific device instead. If you have to use "FX input", make absolutely sure that you accidentally mapped the MIDI track input to channel 1 (using REAPER track controls).
Does the Play/Stop have to be on PC 0 or was that just an example? I had my Play/Stop set to PC9 and made sure min/max was set to 9/9 and no other switches were assigned to 9 and all switches had out-of-range set to Ignore.

My current setup is set to have ReaLearn Input set directly to the MIDI input already. Reaper see's Channel 2 when I have it assigned but ReaLearn was not seeing Channel 2 even though I made no changes to the switches when I did that testing.
RamboMadCow is offline   Reply With Quote
Old 11-22-2022, 01:23 PM   #2972
vonglan
Human being with feelings
 
Join Date: Oct 2019
Location: LŁbeck, Germany
Posts: 46
Default

Quote:
Originally Posted by Puck View Post
@helgoboss and @vonglan or anyone else
Each mapping would have 3 attributes (source/target/color) so I think my goal would be to output from my fx configurator a table of tables? Then I could pop those tables into the top of the LUA code and load it into Realearn. Admittedly thatís more complex than anything Iíve done thus far but I was just asking to see if I was on the right track or if I should think about it differently? Any guidance is appreciated immensely.
Yes, sounds correct, from the Lua side of things.
I did not get into the details, whether your mappings only have three variable bits.

Setting up a table of tables in Lua can be done like this:

plugins = {}
plugins[1] = { file = 'VPROM' }
plugins[2] = { file = 'M1', preset = 'SoulFunk Kit' }
plugins[3] = { file = 'WAVESTATION', preset = 'Kit 1 Gated' }
plugins[4] = { file = 'TAL-Drum', preset = '909' }

As you are talking about mapping lots of parameters for lots of VSTs, you might be interested in my SY mappings, or the idea behind it (defining a standard set of VST parameters) https://github.com/vonglan/realearn-sy-presets
vonglan is offline   Reply With Quote
Old 11-22-2022, 02:24 PM   #2973
helgoboss
Human being with feelings
 
helgoboss's Avatar
 
Join Date: Aug 2010
Location: Germany
Posts: 1,951
Default

Quote:
Originally Posted by Puck View Post
@helgoboss and @vonglan or anyone else

One point of friction is pairing fx parameters with the correct sources. Helgoboss was right when he said that what I’m doing is complex and repetitive. So I need to make this as easy as possible.

CSI faces a similar problem. A few of us made what we call FX configurators in excel where we made the connections via dropdown menus and fill color. After you filled everything out, the configurator would spit out a text file to use as an fx zone in CSI. I could do the same thing here and it could spit out the tables needed for the LUA looping structure I would set up.

My question is this;

Each mapping would have 3 attributes (source/target/color) so I think my goal would be to output from my fx configurator a table of tables? Then I could pop those tables into the top of the LUA code and load it into Realearn. Admittedly that’s more complex than anything I’ve done thus far but I was just asking to see if I was on the right track or if I should think about it differently? Any guidance is appreciated immensely.
Yes, I think that's what you want. A table of tables. Actually not that complicated ... in other languages this would be called a list of objects, which sounds easier. It's just that in Lua everything is a table, even lists

If you don't like to convert the tabular data to Lua tables in Excel or Google Spreadsheets itself, you could even choose to embed CSV in the Lua code and then use a Lua function to convert it into a table of tables - on the fly.

Would look a bit like that:

Code:
-- Configuration (paste your CSV below)

config_csv = [[
  source, target, color
  s1, t1, red
  s2, t2, blue
]]

-- Convert CSV to table of tables
config = parse_csv(config_csv)

-- Transform config to some mappings

...

-- Return ReaLearn compartment

return {
    ...
}
Or ... you say no to the comfort of Excel and color dropdowns and just enter the tabular data directly into the Lua script (can also be done using vonglan's syntax)!

Code:
config = {
   {
      source = "s1",
      target = "t1",
      color = "red",
   },
   {
      source = "s2",
      target = "t2",
      color = "blue",
   },
}
Yeah, repeating the source, target and color keys over and over is not cool, so you could also settle with:

Code:
config = {
   { "s1", "t1", "red" },
   { "s2", "t2", "blue" },
}
It's a programming language. So you can turn anything into anything. Let me know which way you would prefer and I can give you more tips.
helgoboss is offline   Reply With Quote
Old 11-22-2022, 02:30 PM   #2974
helgoboss
Human being with feelings
 
helgoboss's Avatar
 
Join Date: Aug 2010
Location: Germany
Posts: 1,951
Default

Quote:
Originally Posted by RamboMadCow View Post
Does the Play/Stop have to be on PC 0 or was that just an example? I had my Play/Stop set to PC9 and made sure min/max was set to 9/9 and no other switches were assigned to 9 and all switches had out-of-range set to Ignore.

My current setup is set to have ReaLearn Input set directly to the MIDI input already. Reaper see's Channel 2 when I have it assigned but ReaLearn was not seeing Channel 2 even though I made no changes to the switches when I did that testing.
No, Play/Stop can be anywhere, I just thought you had it on 0.

Both things you are writing here sound very strange. This is not how ReaLearn works. I need to see it in detail. Please send the RPP file to info@helgoboss.org. If you use instances on the monitoring FX chain, copy them into the project as well before that! (e.g. put them on the master FX chain)
helgoboss is offline   Reply With Quote
Old 11-23-2022, 09:41 AM   #2975
helgoboss
Human being with feelings
 
helgoboss's Avatar
 
Join Date: Aug 2010
Location: Germany
Posts: 1,951
Default

@ALL Okay guys, be quick if you still want to report severe bugs in the latest pre-release. I would like to publish 2.14.0 tomorrow (24.11.) and hope it's ready for prime time.
helgoboss is offline   Reply With Quote
Old 11-23-2022, 11:22 AM   #2976
Michelob
Human being with feelings
 
Michelob's Avatar
 
Join Date: Sep 2010
Location: Mons, Belgium
Posts: 3,053
Default

Congratulations, danke schŲn, bravo !
Michelob is offline   Reply With Quote
Old 11-24-2022, 10:05 AM   #2977
helgoboss
Human being with feelings
 
helgoboss's Avatar
 
Join Date: Aug 2010
Location: Germany
Posts: 1,951
Default

Released ReaLearn 2.14.0 (ReaPack installation instructions)

Changes:
- #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"
- #747 Added menu and help buttons to the header panel
- #224 Added previous/next buttons to the mapping panel (for navigating in the list of mappings that's currently visible in the main panel)
- #685 Added more comfortable editing for OSC feedback arguments and help button
- #729 Added Lua snippet versioning (from now on, all Lua exports from ReaLearn will contain the ReaLearn version number; used for getting version conflict warnings on import and applying migration logic; in your own Lua code, you should make sure it's set from now on ... removing it will make ReaLearn think that it's an old preset and then it might apply some migration logic that you don't want)
- #485 Added new takeover mode "Pickup (tolerant)" (prevents jumps but also makes extra sure the target doesn't get stuck, in addition to below mdmayfield improvements)
- #756 Added new text feedback placeholder "target.width.mcu" to target "Track: Set stereo width" for pretty display of width value
- #221 Added new experimental "Pot" targets for preset browsing in a large pot of presets (first supported preset database: Komplete NKS, see dedicated REAPER forum thread for details)
- #713 Added new feedback-only source "Speech" for speaking out numeric or text feedback via Windows/macOS built-in text-to-speech engine (no Linux yet, sorry)
- #529 Added new track selectors that respect track visibility in TCP or MCP
- #529 Added new dynamic track variables "selected_track_tcp_index" and "selected_track_mcp_index"
- #529 Added new options to target "Project: Navigate within tracks" to respect visibility in TCP or MCP
- #698 Added fancy control transformation editor with visual preview of curve/transition (Windows/macOS only for now)
- #605 Added control transformation template facility (including some first templates, hard-coded, Windows/macOS only for now)
- #45 Added option to respect/ignore track grouping to supported track targets
- #45 Added option to enable/disable selection ganging to supported track targets
- #691 Added target control information to mapping panel (Very useful to understand what's going on! For real-time-MIDI-controlled mappings, this only works if target control logging is enabled.)
- #686 Added new target "Global: Mouse" to control the mouse (one use case is to control the FX parameter which is currently under the mouse cursor)
- #555 Added possibility to save compartment notes (they are also saved with compartment presets)
- #679 Added multi-line editing and error reporting for EEL transformation formulas
- #680 Added possibility to force or prevent smooth seek in seek and marker/region targets
- #670 Added display type "Studiologic SL Keyboard display" for showing arbitrary text on the keyboard (tested with SL88)
- #660 Added display types "X-Touch Mackie LCD" and "X-Touch Mackie LCD XT" for enabling LCD color support when certain X-Touch devices are in MCU mode
- #657 Added various options to decide whether to keep ReaLearn active if its project tab is in the background (accessible via right-click menu)
- #627 Added option to play sound when target has been invoked successfully ("Beep on success" checkbox at the bottom left of the mapping panel, great for trigger-like targets such as saving a snapshot)
- #648 Added target "Track: Enable/disable parent send" (great for MIDI routing in the context of song switching)
- #658 Added option to prevent resetting feedback when releasing sources (accessible via right-click menu, good for using REAPER/ReaLearn as a remote control for hardware devices)
- #635 Added stop function to be used in control transformation formulas to emit a target value and stop the currently running transition at once
- #677 Added context menu entry "Open preset folder"
- Added "Retrigger" option to target "FX parameter: Set value" (sets parameter even if it already has desired value)
- #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)
- #485 Improved takeover modes substantially by applying the "mdmayfield improvements": No more backwards jumps! Much less getting-stuck situations! Ability to choose a fixed default for jump max! (Thanks a lot to mdmayfield who made the initial contribution!)
- #485 Improved usability by removing "Jump min/max" settings and introducing an "Off" mode instead (the value for jump max is now an implementation detail; custom min/max values are still supported but only for old presets to ensure backward compatibility; one can use a value sequence as alternative to jump min)
- #408 Improved auto-load mode by automagically falling back to memorized mappings when FX loses focus (users will love this because it's much more intuitive than "Make instance superior", which still has its uses though in more complex scenarios where you want multiple instances)
- #721 Improved wording by consistently using "Browse ..." instead of "Navigate within ..." or "Cycle through ..."
- #721 Improved wording by using less technical object selector names (e.g. "Particular" instead of "By ID")
- #664 Improved usability by displaying in status bar if control/feedback globally off (don't show by greying out mapping rows anymore)
- #700 Improved usability by insisting on keyboard focus, even if 'Send all keyboard focus to plug-in' is disabled
- #692 Improved target-based conditional activation by listening to target activation/deactivation as well
- #695 Improved usability by marking targets that support MIDI real-time control (because MIDI real-time control has a few restrictions)
- #689 Improved source "MIDI script" when used with Lua language by making color information available (allows users to provide support for arbitrary MIDI color LEDs/displays, in addition to the built-in ones)
- Improved target logging by including target control errors and other information
- Improved usability by making it possible to copy and paste the activation condition of a mapping
- #675 Improved preset loading by supporting placing preset files in sub directories (1 level, ATTENTION: The parent directory will become part of the preset ID, so don't move existing presets!)
- #674 Improved preset loading by supporting symlinked preset files
- #630 Improved target "ReaLearn: Load mapping snapshot" by respecting the "Reverse" checkbox when loading the default value (great for changing the perspective when it comes to on/off targets)
- #639 Improved usability of the snapshot targets by displaying the snapshot ID in the row label
- #666 Improved usability of source "ReaLearn parameter" by displaying the parameter index in the row label
- #626 Improved usability of source "ReaLearn parameter" by making the parameter learnable
- #671 Improved usability by making text feedback available with dummy target (great for sending just some constant text or using placeholders that don't need target context)
- #629 Improved usability by displaying session ID in the status bar (should help detecting duplicate IDs, which can be useful e.g. when using projection)
- #628 Improved target "ReaLearn: Load mapping snapshot" by enabling feedback (showing if the desired snapshot is currently loaded or not)
- #644 Improved versatility of target "Project: Invoke REAPER action" by making trigger-like actions controllable by relative endless encoders (via invocation mode "Trigger")
- #640 Improved target "ReaLearn: Take mapping snapshot" by adding the "Last loaded" selector (great for assigning a particular button to update the currently loaded snapshot)
- #722 Fixed missing feedback of "FX: Enable/disable" target when Bypass parameter is automated
- #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)
- #529 Fixed unreliable refresh of dynamic track result UI refresh in target section of mapping panel
- Fixed various mapping panel GUI bugs
- #727 Fixed missing feedback refresh when dealing with multiple instances (e.g. via "Make instance superior")
- #730 Fixed missing automatic feedback for target "FX: Set online/offline"
- #724 Fixed unreliable track visibility change detection
- #707 Fixed rel_time transformations to respect reverse, target min/max/sequence and rounding (also hide some settings that don't make sense)
- #706 Fixed OSC compatibility with certain apps such as Syntien (control didn't work when both control and feedback were enabled for the device)
- Fixed target "Project: Invoke REAPER action" invocation mode "Trigger" (could potentially suffer from not being retriggered in some situations)
- #696 Fixed bug that caused retriggerable targets to not be retriggered with relative control if they already had the desired value
- Fixed error when learning/using special keys on macOS (keyboard source)
- #681 Fixed REAPER track color detection
- #682 Fixed bug that caused parameters and custom projection data to not be cleared when switching preset to None
- #667 Fixed fire modes when using rel_time transitions
- #631 Fixed saving of snapshot IDs in target "ReaLearn: Take mapping snapshot"
- #663 Fixed feedback of target "Marker/region: Go to" (it was changing even when playback was stopped)
- #659 Fixed ReaLearn still being active when disabling it via its automatable "Bypass" parameter (as opposed to disabling it via checkbox or ReaScript)
- #652 Fixed deletion of mapping snapshots when copying and pasting a compartment
- #673 Fixed "mapping not found" error when removing a mapping while still learning it
- #678 Fixed infinite error loop and certain "track is not available"-like errors
- #676 Fixed change detection for FX on the monitoring FX chain (most importantly enable/disable, in general ReaLearn should now work much better when targeting monitoring FX and also work better if it's placed on the monitoring FX chain itself)
helgoboss is offline   Reply With Quote
Old 11-26-2022, 05:20 AM   #2978
Puck
Human being with feelings
 
Puck's Avatar
 
Join Date: Feb 2022
Location: Almost Canada
Posts: 499
Default Building mappings via LUA

That's quite the changelog again there, Ben! Everything seems to be running well here!

......

Ok, so I've made it pretty far in my building maps with lua journey. I've adapted my FX configurator to spit out a lua table + the lua code that goes with it. When I'm finished it will just be one click to copy the lua for an fx and then going to realearn and click import! But I ran into a snag with syntax that I'm sure will be easy for you or vonglan to spot. A very simple example worked. But when I started to incorporate more stuff I messed up somewhere and I can't debug it with my knowledge and the syntax error messaging.

Simple example that worked:
Code:
local RotaryTBL = {	
	{ source = "A2", target = 3, alias = "MOOD", color = "#FF0000" },
	{ source = "A3", target = 1, alias = "Soften", color = "#B4C6E7" }
}	
	
local RotaryPushTBL = {	
	{ source = "PushA1", target = 0, alias = "Boost", color = "#B4FBFF" }
}	

local mappings = {}

for i = 1, #RotaryTBL do
	
	local rotary_FX_mapping = {
	    id = RotaryTBL[i]["source"] .. RotaryTBL[i]["target"],
            name = "Rotary" .. RotaryTBL[i]["source"] .. " - "  .. RotaryTBL[i]["target"],
            visible_in_projection = false,
            source = {
                kind = "Virtual",
                id = "Rotary" .. RotaryTBL[i]["source"],
            },
            glue = {
                step_size_interval = {0.01, 0.05},
                step_factor_interval = {1, 5},
            },
            target = {
                kind = "FxParameterValue",
                parameter = {
                    address = "ById",
                    fx = {
                        address = "Instance",
                    },
                    index = RotaryTBL[i]["target"],
                },
            },
	 }		
         table.insert(mappings, rotary_FX_mapping)
end

return {
    kind = "MainCompartment",
    value = {
        mappings = mappings,
    },
}
Slightly more complex example (the error message it gave I'll write at the bottom):
Code:
local groups = {
    {
        id = "rotaryA",
        name = "RotaryA",
    },
    {
        id = "rotaryb",
        name = "RotaryB",
    },
    {
        id = "rotaryc",
        name = "RotaryC",
    },
    {
        id = "rotaryd",
        name = "RotaryD",
    },
    {
        id = "rotarypusha",
        name = "RotaryPushA",
    },
    {
        id = "rotarypushb",
        name = "RotaryPushB",
    },
    {
        id = "rotarypushc",
        name = "RotaryPushC",
    },
    {
        id = "rotarypushd",
        name = "RotaryPushD",
    }
}

local FXName = "AdClip7"

local RotaryTBL = {	
	{ source = "A2", FXindex = 3, alias = "Mood", color = "#FF0000", group = "RotaryA" },
	{ source = "A3", FXindex = 1, alias = "Soften", color = "#B4C6E7", group = "RotaryA" }
}	
	
local RotaryPushTBL = {	
	{ source = "PushA1", FXindex = 0, alias = "Boost", color = "#B4FBFF", group = "RotaryPushA" }
}	


local mappings = {}

for i = 1, #RotaryTBL do
	
	local rotary_FX_mapping = {
	    id = FXName.."-Rotary"..RotaryTBL[i]["source"].."-" RotaryTBL[i]["alias"],
        name = "Rotary"..RotaryTBL[i]["source"].." - "..RotaryTBL[i]["alias"],
        group = RotaryTBL[i]["group"],
        visible_in_projection = false,
        source = {
            kind = "Virtual",
            id = "Rotary" .. RotaryTBL[i]["source"],
        },
        glue = {
            step_size_interval = {0.01, 0.05},
            step_factor_interval = {1, 5},
        },
        target = {
            kind = "FxParameterValue",
            parameter = {
                address = "ById",
                    fx = {
                        address = "Instance",
                    },
                    index = RotaryTBL[i]["FXindex"],
            },
        },
    }
    local rotaryNameDisplay_FX_mapping = {
        id = FXName .. "-RotaryNameDisplay" .. RotaryTBL[i]["source"] .. "-" RotaryTBL[i]["alias"],
        name = "Rotary.. RotaryTBL[i]["source"] .. " - " .. RotaryTBL[i]["alias"]",
        group = RotaryTBL[i]["group"],
        visible_in_projection = false,
        control_enabled = false,
        source = {
            kind = "Virtual",
            id = "RotaryNameDisplay" .. RotaryTBL[i]["source"],
        },
        glue = {
            step_size_interval = {0.01, 0.05},
            step_factor_interval = {1, 5},
            feedback = {
                kind = "Text",
                text_expression = RotaryTBL[i]["alias"],
            },
        },
        target = {
            kind = "FxParameterValue",
            parameter = {
                address = "ById",
                fx = {
                    address = "Instance",
                },
                index = RotaryTBL[i]["FXindex"],
            },
        },
    }		
    table.insert(mappings, rotary_FX_mapping)
    table.insert(mappings, rotaryNameDisplay_FX_mapping)

end

return {
    kind = "MainCompartment",
    value = {
        mappings = mappings,
        groups = groups,
    },
}

error message: syntax error. [string "Import"]53; '}' expected (to close '{' at line 52) near 'RotaryTBL'

Line 52 and 53 are the first two nonempty lines under the loop. Help would be much appreciated. I've been staring at it for bit long now

oh one more thing! How would I add versioning to this? I tried but I wasn't doing it the correct way. I just pasted what realearn gives me directly at the top.

Code:
version = "2.14.0-pre.10"
I figure its supposed to be under some sort of heading but I'm not sure where it goes.

Edit: Should have clarified... at first I tried doing local rotary_FX_Mapping and then sticking the two mappings that are there right under it. I'm not sure if I could do that or not because this error cropped up either way. I then separated them and gave them different variable names. Then inserted them at the bottom. I remember vonglan mentions that he doesn't do this bit of the code and does something else. I tried to figure out what he did but am not clear on that yet either

Last edited by Puck; 11-26-2022 at 05:37 AM.
Puck is offline   Reply With Quote
Old 11-26-2022, 06:13 AM   #2979
helgoboss
Human being with feelings
 
helgoboss's Avatar
 
Join Date: Aug 2010
Location: Germany
Posts: 1,951
Default

This works (you need to close the string quotes correctly and always use .. to concatenate strings).

BTW, I realized you use virtual sources. I know, I often recommend this and it makes a whole lot of sense for MIDI controllers, even if it's just for getting nice labels. But you use OSC, right? OSC has addresses, e.g. "/panel2/fader1" which already are quite self-explaining. And from how it appears to me, you don't want your main preset to be super-reusable with a lot of controllers and so on ... it's just for this one OSC template that you built, right? In this case I personally would use OSC sources directly, not virtual sources. It's more direct and less abstraction.

Code:
local groups = {
    {
        id = "rotaryA",
        name = "RotaryA",
    },
    {
        id = "rotaryb",
        name = "RotaryB",
    },
    {
        id = "rotaryc",
        name = "RotaryC",
    },
    {
        id = "rotaryd",
        name = "RotaryD",
    },
    {
        id = "rotarypusha",
        name = "RotaryPushA",
    },
    {
        id = "rotarypushb",
        name = "RotaryPushB",
    },
    {
        id = "rotarypushc",
        name = "RotaryPushC",
    },
    {
        id = "rotarypushd",
        name = "RotaryPushD",
    }
}

local FXName = "AdClip7"

local RotaryTBL = {	
	{ source = "A2", FXindex = 3, alias = "Mood", color = "#FF0000", group = "RotaryA" },
	{ source = "A3", FXindex = 1, alias = "Soften", color = "#B4C6E7", group = "RotaryA" }
}	
	
local RotaryPushTBL = {	
	{ source = "PushA1", FXindex = 0, alias = "Boost", color = "#B4FBFF", group = "RotaryPushA" }
}	


local mappings = {}

for i = 1, #RotaryTBL do
	
	local rotary_FX_mapping = {
	    id = FXName.."-Rotary"..RotaryTBL[i]["source"].."-" .. RotaryTBL[i]["alias"],
        name = "Rotary"..RotaryTBL[i]["source"].." - "..RotaryTBL[i]["alias"],
        group = RotaryTBL[i]["group"],
        visible_in_projection = false,
        source = {
            kind = "Virtual",
            id = "Rotary" .. RotaryTBL[i]["source"],
        },
        glue = {
            step_size_interval = {0.01, 0.05},
            step_factor_interval = {1, 5},
        },
        target = {
            kind = "FxParameterValue",
            parameter = {
                address = "ById",
                    fx = {
                        address = "Instance",
                    },
                    index = RotaryTBL[i]["FXindex"],
            },
        },
    }
    local rotaryNameDisplay_FX_mapping = {
        id = FXName .. "-RotaryNameDisplay" .. RotaryTBL[i]["source"] .. "-" .. RotaryTBL[i]["alias"],
        name = "Rotary".. RotaryTBL[i]["source"] .. " - " .. RotaryTBL[i]["alias"],
        group = RotaryTBL[i]["group"],
        visible_in_projection = false,
        control_enabled = false,
        source = {
            kind = "Virtual",
            id = "RotaryNameDisplay" .. RotaryTBL[i]["source"],
        },
        glue = {
            step_size_interval = {0.01, 0.05},
            step_factor_interval = {1, 5},
            feedback = {
                kind = "Text",
                text_expression = RotaryTBL[i]["alias"],
            },
        },
        target = {
            kind = "FxParameterValue",
            parameter = {
                address = "ById",
                fx = {
                    address = "Instance",
                },
                index = RotaryTBL[i]["FXindex"],
            },
        },
    }		
    table.insert(mappings, rotary_FX_mapping)
    table.insert(mappings, rotaryNameDisplay_FX_mapping)

end

return {
    kind = "MainCompartment",
    value = {
        mappings = mappings,
        groups = groups,
    },
}
helgoboss is offline   Reply With Quote
Old 11-26-2022, 06:45 AM   #2980
Puck
Human being with feelings
 
Puck's Avatar
 
Join Date: Feb 2022
Location: Almost Canada
Posts: 499
Default

Quote:
Originally Posted by helgoboss View Post
This works (you need to close the string quotes correctly and always use .. to concatenate strings).
Thank you! Those errors were embarrassing lol.

There were quite a few of them and I obviously concatenated correctly in other places. Sheesh


Quote:
BTW, I realized you use virtual sources. I know, I often recommend this and it makes a whole lot of sense for MIDI controllers, even if it's just for getting nice labels. But you use OSC, right? OSC has addresses, e.g. "/panel2/fader1" which already are quite self-explaining. And from how it appears to me, you don't want your main preset to be super-reusable with a lot of controllers and so on ... it's just for this one OSC template that you built, right? In this case I personally would use OSC sources directly, not virtual sources. It's more direct and less abstraction.
I don't mind the virtual sources here. There were a couple naming conventions I followed in my osc layout just to be able to use some already completed CSI FX maps. This way I can sort of obfuscate those and make the virtual source names make more sense with my controller. I suppose if I need something special/direct I can also just incorporate a real source into any of these presets.

Last edited by Puck; 11-26-2022 at 06:55 AM.
Puck is offline   Reply With Quote
Old 11-26-2022, 06:54 AM   #2981
Puck
Human being with feelings
 
Puck's Avatar
 
Join Date: Feb 2022
Location: Almost Canada
Posts: 499
Default

Code:
return {
    kind = "MainCompartment",
    version = "2.14.0-pre.10",
    value = {
        mappings = mappings,
        groups = groups,
    },
}
This would be the correct place to do the versioning, right?
Puck is offline   Reply With Quote
Old 11-26-2022, 07:08 AM   #2982
helgoboss
Human being with feelings
 
helgoboss's Avatar
 
Join Date: Aug 2010
Location: Germany
Posts: 1,951
Default

Quote:
Originally Posted by Puck View Post
Code:
return {
    kind = "MainCompartment",
    version = "2.14.0-pre.10",
    value = {
        mappings = mappings,
        groups = groups,
    },
}
This would be the correct place to do the versioning, right?
Yes. It tells ReaLearn for which version of ReaLearn this preset was built. It should always be there (can make a difference). If it's not there, ReaLearn assumes it was built for a version < 2.14.0.
helgoboss is offline   Reply With Quote
Old 11-26-2022, 07:41 AM   #2983
Puck
Human being with feelings
 
Puck's Avatar
 
Join Date: Feb 2022
Location: Almost Canada
Posts: 499
Default

Quote:
Originally Posted by helgoboss View Post

BTW, I realized you use virtual sources...
Actually, I was just thinking that someone with a Mackie C4 or two midifighter Twisters or maybe even a behringer BCR2000 wouldn't have to change this much at all to get it to work for them. They could just take my controller preset, "Realearn" (see what I did there?) the real sources with their controller and then delete the display stuff that doesn't apply both in the controller preset and the lua code.


.............

Two things I'll want to change in the future about this excel FX configurator:

1. I'm using Excel and can't use google sheets because most of the processing is done in VBA. The main reason for this is VBA can look at files on your computer. The files I'm having it look at are RawFXZone text files generated by CSI. I have excel parse these files to populate a nice dropdown lists and basically provide a nice gui to do this complex mapping very simply. It would be wonderful if we could take excel out of the equation here. I honestly don't know how far google sheets has come in terms of scripting, so I'll have to do some research on that.

2. I basically already said it, but users of my layout would also have to install CSI to generate these text files that excel currently parses for the dropdown lists. So depending on Google sheets capabilities, I could figure out a feature request.

Last edited by Puck; 11-26-2022 at 08:16 AM.
Puck is offline   Reply With Quote
Old 11-26-2022, 10:45 AM   #2984
Puck
Human being with feelings
 
Puck's Avatar
 
Join Date: Feb 2022
Location: Almost Canada
Posts: 499
Default

Sorry for all the questions

This one is a bit complex.

CSI had modifiers by default. Shift/Control/Option/Alt So those are already on my FX page and can be edited via my FX Configurator. I'd like to achieve the same functionality with Realearn. I know that it's possible, obviously. In fact, I think there are a few ways this can be done.

1. Conditional Activation

2. Enable/Disable Mappings

3. I'm not sure but I'm pretty positive there's one more way

Now that I'm making headway with building the mappings via LUA, I am trying to think through the best way to implement these modifiers also with LUA.

(the actual question is similar to one I've asked before so I hope it's a similar answer)

The behavior I would like is:

1. RotaryA1 and all of it's displays are mapped control FX Parameter 1

2. Engaging the Shift modifier maps RotaryA1 and all of it's displays to FX Parameter 2

3. Disengaging Shift remaps RotaryA1 and all of its displays back to FX Parameter 1

.....

I want this in a global sort of way where I don't have to go in and edit the mappings after I build them with LUA. I think I can work this out in my head but I wanted someone's opinion before I coded myself in a corner.

What I think I would do;

Just globally map those four modifiers to four Realearn params and just build out my lua including mappings that have conditional activations via those realearn params.
Puck is offline   Reply With Quote
Old 11-26-2022, 11:01 AM   #2985
binbinhfr
Human being with feelings
 
binbinhfr's Avatar
 
Join Date: Oct 2021
Location: France
Posts: 363
Default

Hi Helgoboss,

about the transmission of parameters to a script (#761), I installed the latest 2.14.0 version, but alas it seems that the problem is globally back.
My test script only returns -1 values, for any option (relative, 14 bit or 7 bits).
I tested the normal Reaper actionlist bindings, that still works. So there must be a regression problem between 2.14.0 pre 7 and 2.14.0 final.

PS: I reverted to 2.14.0pre7 which was working the last time, and it's not working anymore here.... So I wonder if something has changed in last Reaper's version...

For memory, here is the script :
Code:
reaper.ShowConsoleMsg("----\n")

local is_new_value , filename_with_path, sectionID, cmdID, mode, resolution, val = reaper.get_action_context()

reaper.ShowConsoleMsg( "mode: " .. mode .. " res: " .. resolution .. " val = " .. val .. "\n")
__________________
Reaper's lunatic
Reapack repository / GitHub / SoundCloud / Donate

Last edited by binbinhfr; 11-26-2022 at 12:13 PM.
binbinhfr is offline   Reply With Quote
Old 11-26-2022, 12:17 PM   #2986
helgoboss
Human being with feelings
 
helgoboss's Avatar
 
Join Date: Aug 2010
Location: Germany
Posts: 1,951
Default

Quote:
Originally Posted by binbinhfr View Post
Hi Helgoboss,

about the transmission of parameters to a script (#761), I installed the latest 2.14.0 version, but alas it seems that the problem is globally back.
My test script only returns -1 values, for any option (relative, 14 bit or 7 bits).
I tested the normal Reaper actionlist bindings, that still works. So there must be a regression problem between 2.14.0 pre 7 and 2.14.0 final.

PS: I reverted to 2.14.0pre7 which was working the last time, and it's not working anymore here.... So I wonder if something has changed in last Reaper's version...

For memory, here is the script :
Code:
reaper.ShowConsoleMsg("----\n")

local is_new_value , filename_with_path, sectionID, cmdID, mode, resolution, val = reaper.get_action_context()

reaper.ShowConsoleMsg( "mode: " .. mode .. " res: " .. resolution .. " val = " .. val .. "\n")
Remember, it depends on the REAPER version, not the ReaLearn version You might have to use a dev release.
helgoboss is offline   Reply With Quote
Old 11-26-2022, 12:31 PM   #2987
binbinhfr
Human being with feelings
 
binbinhfr's Avatar
 
Join Date: Oct 2021
Location: France
Posts: 363
Default

Quote:
Originally Posted by helgoboss View Post
Remember, it depends on the REAPER version, not the ReaLearn version You might have to use a dev release.
I tested the last dev version and you're right : it works (with the latest Realearn release)

But I do not understand : the dev version where Justin corrected the problem was 669dev1111. It means that 670 was released without the correction ? But that this correction is again present in 671rc4 ???
__________________
Reaper's lunatic
Reapack repository / GitHub / SoundCloud / Donate

Last edited by binbinhfr; 11-26-2022 at 12:37 PM.
binbinhfr is offline   Reply With Quote
Old 11-26-2022, 01:27 PM   #2988
helgoboss
Human being with feelings
 
helgoboss's Avatar
 
Join Date: Aug 2010
Location: Germany
Posts: 1,951
Default

Quote:
Originally Posted by binbinhfr View Post
I tested the last dev version and you're right : it works (with the latest Realearn release)

But I do not understand : the dev version where Justin corrected the problem was 669dev1111. It means that 670 was released without the correction ? But that this correction is again present in 671rc4 ???
It's up to Justin which dev feature to include in which final release.
helgoboss is offline   Reply With Quote
Old 11-27-2022, 01:18 PM   #2989
helgoboss
Human being with feelings
 
helgoboss's Avatar
 
Join Date: Aug 2010
Location: Germany
Posts: 1,951
Default

Quote:
Originally Posted by Puck View Post
Actually, I was just thinking that someone with a Mackie C4 or two midifighter Twisters or maybe even a behringer BCR2000 wouldn't have to change this much at all to get it to work for them. They could just take my controller preset, "Realearn" (see what I did there?) the real sources with their controller and then delete the display stuff that doesn't apply both in the controller preset and the lua code.
Glad you are aware of the advantages of virtual sources/targets.


Quote:
Originally Posted by Puck View Post

Two things I'll want to change in the future about this excel FX configurator:

1. I'm using Excel and can't use google sheets because most of the processing is done in VBA. The main reason for this is VBA can look at files on your computer. The files I'm having it look at are RawFXZone text files generated by CSI. I have excel parse these files to populate a nice dropdown lists and basically provide a nice gui to do this complex mapping very simply. It would be wonderful if we could take excel out of the equation here. I honestly don't know how far google sheets has come in terms of scripting, so I'll have to do some research on that.

2. I basically already said it, but users of my layout would also have to install CSI to generate these text files that excel currently parses for the dropdown lists. So depending on Google sheets capabilities, I could figure out a feature request.
1. Ah, so you are creating some kind of user-configurable preset builder. Yes, I think using Google Sheets or Zoho Creator would be more user-friendly options.

2. I wonder what's the content of those RawFXZone files, I mean which info is included there and what the preset builder GUI looks like.
helgoboss is offline   Reply With Quote
Old 11-27-2022, 01:20 PM   #2990
helgoboss
Human being with feelings
 
helgoboss's Avatar
 
Join Date: Aug 2010
Location: Germany
Posts: 1,951
Default

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

This one is a bit complex.

CSI had modifiers by default. Shift/Control/Option/Alt So those are already on my FX page and can be edited via my FX Configurator. I'd like to achieve the same functionality with Realearn. I know that it's possible, obviously. In fact, I think there are a few ways this can be done.

1. Conditional Activation

2. Enable/Disable Mappings

3. I'm not sure but I'm pretty positive there's one more way

Now that I'm making headway with building the mappings via LUA, I am trying to think through the best way to implement these modifiers also with LUA.

(the actual question is similar to one I've asked before so I hope it's a similar answer)

The behavior I would like is:

1. RotaryA1 and all of it's displays are mapped control FX Parameter 1

2. Engaging the Shift modifier maps RotaryA1 and all of it's displays to FX Parameter 2

3. Disengaging Shift remaps RotaryA1 and all of its displays back to FX Parameter 1

.....

I want this in a global sort of way where I don't have to go in and edit the mappings after I build them with LUA. I think I can work this out in my head but I wanted someone's opinion before I coded myself in a corner.

What I think I would do;

Just globally map those four modifiers to four Realearn params and just build out my lua including mappings that have conditional activations via those realearn params.
Yes, that's what I would do. Modifiers are best implemented using conditional activation.
helgoboss is offline   Reply With Quote
Old 11-27-2022, 02:55 PM   #2991
Puck
Human being with feelings
 
Puck's Avatar
 
Join Date: Feb 2022
Location: Almost Canada
Posts: 499
Default

Quote:
Originally Posted by helgoboss View Post
Yes, that's what I would do. Modifiers are best implemented using conditional activation.
So I'm doing some preliminary testing on this now.

One hitch I have is being able to do this at scale. Really off the deep end here

I'm pretty much to the point where I can use my excel fx configurator to build the lua (there are just a couple naming bugs to squash)

But being able to incorporate the modifiers is even more complex than what I'm doing now. For the mappings I want to override, they will also have to have conditional activation with the flag set to false. I can't just type that in there in the loop, because only the controls that exist in both the rotaryTBL and the shiftrotaryTBL will get conditional activation. I guess at that point of the loop I would set up an if statement and somehow get all of the controls that exist in both the regular and shift tables and then change those controls to have conditional activation... but I'm currently racking my brain on how to do that.

I see you do a bit of this in the DAW Control source (conditionally write one thing or the other, that is). I'll try and study that. Generating the table of controls that exist in both tables is perplexing me though.
Puck is offline   Reply With Quote
Old 11-27-2022, 03:38 PM   #2992
helgoboss
Human being with feelings
 
helgoboss's Avatar
 
Join Date: Aug 2010
Location: Germany
Posts: 1,951
Default

Quote:
Originally Posted by Puck View Post
So I'm doing some preliminary testing on this now.

One hitch I have is being able to do this at scale. Really off the deep end here

I'm pretty much to the point where I can use my excel fx configurator to build the lua (there are just a couple naming bugs to squash)

But being able to incorporate the modifiers is even more complex than what I'm doing now. For the mappings I want to override, they will also have to have conditional activation with the flag set to false. I can't just type that in there in the loop, because only the controls that exist in both the rotaryTBL and the shiftrotaryTBL will get conditional activation. I guess at that point of the loop I would set up an if statement and somehow get all of the controls that exist in both the regular and shift tables and then change those controls to have conditional activation... but I'm currently racking my brain on how to do that.

I see you do a bit of this in the DAW Control source (conditionally write one thing or the other, that is). I'll try and study that. Generating the table of controls that exist in both tables is perplexing me though.
Yes, if you want a mapping to get inactive when you press shift, it also needs an activation condition. Just give it one. If you need help with it, post some code.

BTW, you can also put multiple mappings into one group and then assign the activation condition to the group instead of the single mappings. If that helps somehow ... but it shouldn't make a difference with Lua. It's more helpful in situations in which you don't want to use Lua, so you can avoid having to set the same activation condition again and again for each mapping. As soon as you use Lua to build your mappings though, repetition can be avoided by means of programming (variables, functions, etc.)
helgoboss is offline   Reply With Quote
Old 11-27-2022, 03:43 PM   #2993
TonE
Human being with feelings
 
Join Date: Feb 2009
Location: Reaper HAS send control via midi !!!
Posts: 3,945
Default

Wow, since when there is a win32 of Realearn? Just saw it, quickly tested, Reaper not crashing. Cool, can start testing then... thanks a lot for adding win32 as well!
TonE is online now   Reply With Quote
Old 11-29-2022, 05:32 AM   #2994
Puck
Human being with feelings
 
Puck's Avatar
 
Join Date: Feb 2022
Location: Almost Canada
Posts: 499
Default

I was really trying not to have to bug you with this. But I've been at this for quite a while now.

1. Code is below.
2. Loop starts at line 163
3. Tables are on line 74

I'm not sure why this isn't working

I'm not sure if a) logic part is incorrect or b) the parser doesn't like multi line strings but it's also not throwing an error. Or something else entirely.

Code:
local groups = {
    {
        id = "rotarya",
        name = "RotaryA",
    },
    {
        id = "rotaryb",
        name = "RotaryB",
    },
    {
        id = "rotaryc",
        name = "RotaryC",
    },
    {
        id = "rotaryd",
        name = "RotaryD",
    },
    {
        id = "rotarypusha",
        name = "RotaryPushA",
    },
    {
        id = "rotarypushb",
        name = "RotaryPushB",
    },
    {
        id = "rotarypushc",
        name = "RotaryPushC",
    },
    {
        id = "rotarypushd",
        name = "RotaryPushD",
    },
    {
        id = "shiftotarya",
        name = "ShiftRotaryA",
    },
    {
        id = "shiftotaryb",
        name = "ShiftRotaryB",
    },
    {
        id = "shiftotaryc",
        name = "ShiftRotaryC",
    },
    {
        id = "shiftotaryd",
        name = "ShiftRotaryD",
    },
    {
        id = "shiftotarypusha",
        name = "ShiftRotaryPushA",
    },
    {
        id = "shiftotarypushb",
        name = "ShiftRotaryPushB",
    },
    {
        id = "shiftotarypushc",
        name = "ShiftRotaryPushC",
    },
    {
        id = "shiftotarypushd",
        name = "ShiftRotaryPushD",
    },
    {
        id = "fxmainpanel",
        name = "FXMainPanel",
    }
}

local FXName = "YellowDrive"

local RotaryTBL = {
    { source = "A2", FXindex = 3, alias = "Level", color = "#38C838", group = "rotarya" },
    { source = "B3", FXindex = 1, alias = "Drive", color = "#FFFF00", group = "rotaryb" },
    { source = "B4", FXindex = 2, alias = "Tone", color = "#FFFF00", group = "rotaryb" }
}

local RotaryPushTBL = {
    { source = "PushA1", FXindex = 0, alias = "Bypass", color = "#C00000", group = "rotarypusha" },
    { source = "PushB1", FXindex = 4, alias = "Setting", color = "#C00000", group = "rotarypushb" }
}

local ShiftRotaryTBL = {
    { source = "B3", FXindex = 2, alias = "Tone", color = "#C00000", group = "shiftrotaryb" },
    { source = "B4", FXindex = 1, alias = "Drive", color = "#C00000", group = "shiftrotaryb" }
}

local mappings = {}

local FXName_FX_Mapping = {
    id = FXName,
    name = "FXName" .. " - " .. FXName,
    group = "fxmainpanel",
    tags = {
        "fxname",
    },
    visible_in_projection = false,
    control_enabled = false,
    source = {
        kind = "Virtual",
        id = "FXName",
    },
    glue = {
        step_size_interval = {0.01, 0.05},
        step_factor_interval = {1, 5},
        feedback = {
            kind = "Text",
            text_expression = FXName,
        },
    },
    target = {
        kind = "Dummy",
    },
       
    
}
table.insert(mappings, FXName_FX_Mapping)

--local ShiftDeactivate = {}

-- function table.contains(table, element)
    -- for i = 1, #table do
        -- if table[i]["source"] == element then
            -- return true
        -- end
    -- end
    -- return false
-- end



local FXBypass_FX_Mapping = {
    id = FXName .. " - FXBypass",
    name = "FXBypass - " .. FXName,
    group = "fxmainpanel",
    tags = {
        "fxbypass",
    },
    visible_in_projection = false,
    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",
        },
    },
}
table.insert(mappings, FXBypass_FX_Mapping)



for i = 1, #RotaryTBL do

    local counter = 0

    for j = 1, #ShiftRotaryTBL do
        if RotaryTBL[i]["source"] == ShiftRotaryTBL[j]["source"] then
            counter = counter + 1
            end
    end

    if counter > 0 then
        local activation_expression = [[{
            kind = "Modifier",
            modifiers = {
                {
                    parameter = 0,
                    on = false,
                },
            },
        }]]
        else local activation_expression = nil
    end
	
	local rotary_FX_mapping = {
	    id = FXName .. "-Rotary"..RotaryTBL[i]["source"] .. " - " .. RotaryTBL[i]["alias"],
        name = "- - - - - - - - - - - Rotary" .. RotaryTBL[i]["source"] .. " - " .. RotaryTBL[i]["alias"],
        activation_condition = activation_expression,
        tags = {
            "rotary" .. string.lower(RotaryTBL[i]["source"]),
        },
        group = RotaryTBL[i]["group"],
        visible_in_projection = false,
        source = {
            kind = "Virtual",
            id = "Rotary" .. RotaryTBL[i]["source"],
        },
        glue = {
            step_size_interval = {0.01, 0.05},
            step_factor_interval = {1, 5},
        },
        target = {
            kind = "FxParameterValue",
            parameter = {
                address = "ById",
                    fx = {
                        address = "Instance",
                    },
                    index = RotaryTBL[i]["FXindex"],
            },
        },
    }
    local rotaryNameDisplay_FX_mapping = {
        id = FXName .. "-RotaryNameDisplay" .. RotaryTBL[i]["source"] .. "-" .. RotaryTBL[i]["alias"],
        name = "Rotary" .. RotaryTBL[i]["source"] .. " - " .. RotaryTBL[i]["alias"] .. " - " .. "FXParamNameDisplay",
        tags = {
            "rotary" .. string.lower(RotaryTBL[i]["source"]),
        },
        group = RotaryTBL[i]["group"],
        visible_in_projection = false,
        control_enabled = false,
        source = {
            kind = "Virtual",
            id = "RotaryNameDisplay" .. RotaryTBL[i]["source"],
        },
        glue = {
            step_size_interval = {0.01, 0.05},
            step_factor_interval = {1, 5},
            feedback = {
                kind = "Text",
                text_expression = RotaryTBL[i]["alias"],
            },
        },
        target = {
            kind = "FxParameterValue",
            parameter = {
                address = "ById",
                fx = {
                    address = "Instance",
                },
                index = RotaryTBL[i]["FXindex"],
            },
        },
    }	
    local rotaryValueDisplay_FX_mapping = {
        id = FXName .. "-RotaryValueDisplay" .. RotaryTBL[i]["source"] .. "-" .. RotaryTBL[i]["alias"],
        name = "Rotary" .. RotaryTBL[i]["source"] .. " - " .. RotaryTBL[i]["alias"] .. " - " .. "FXParamValueDisplay",
        tags = {
            "rotary" .. string.lower(RotaryTBL[i]["source"]),
        },
        group = RotaryTBL[i]["group"],
        visible_in_projection = false,
        control_enabled = false,
        source = {
            kind = "Virtual",
            id = "RotaryValueDisplay" .. RotaryTBL[i]["source"],
        },
        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 = RotaryTBL[i]["FXindex"],
            },
        },
    }		
    local rotaryColor_FX_mapping = {
        id = FXName .. "-RotaryColor" .. RotaryTBL[i]["source"] .. "-" .. RotaryTBL[i]["alias"],
        name = "Rotary" .. RotaryTBL[i]["source"] .. " - " .. RotaryTBL[i]["alias"] .. " - Color",
        tags = {
            "rotary" .. string.lower(RotaryTBL[i]["source"]),
        },
        group = RotaryTBL[i]["group"],
        visible_in_projection = false,
        control_enabled = false,
        source = {
            kind = "Virtual",
            id = "Rotary" .. RotaryTBL[i]["source"] .. "/Color",
        },
        glue = {
            step_size_interval = {0.01, 0.05},
            step_factor_interval = {1, 5},
            feedback = {
                kind = "Text",
                text_expression = RotaryTBL[i]["color"],
            },
        },
        target = {
            kind = "FxParameterValue",
            parameter = {
                address = "ById",
                fx = {
                    address = "Instance",
                },
                index = RotaryTBL[i]["FXindex"],
            },
        },
    }	
    local rotaryTouch_FX_mapping = {
        id = FXName .. "-RotaryTouch" .. RotaryTBL[i]["source"] .. "-" .. RotaryTBL[i]["alias"],
        name = "Rotary" .. RotaryTBL[i]["source"] .. " - " .. RotaryTBL[i]["alias"] .. " - Touch",
        tags = {
            "rotary" .. string.lower(RotaryTBL[i]["source"]),
        },
        group = RotaryTBL[i]["group"],
        visible_in_projection = false,
        feedback_enabled = false,
        source = {
            kind = "Virtual",
            id = "Rotary" .. RotaryTBL[i]["source"] .. "/touch",
            character = "Button",
        },
        glue = {
            step_size_interval = {0.01, 0.05},
            step_factor_interval = {1, 5},
        },
        target = {
            kind = "FxParameterAutomationTouchState",
            parameter = {
                address = "ById",
                fx = {
                    address = "Instance",
                },
                index = RotaryTBL[i]["FXindex"],
            },
        },
    }							
    table.insert(mappings, rotary_FX_mapping)
    table.insert(mappings, rotaryNameDisplay_FX_mapping)
    table.insert(mappings, rotaryValueDisplay_FX_mapping)
    table.insert(mappings, rotaryColor_FX_mapping)
    table.insert(mappings, rotaryTouch_FX_mapping)

end

for j = 1, #RotaryPushTBL do

    local rotaryPush_FX_mapping = {
	    id = FXName.."-RotaryPush"..RotaryPushTBL[j]["source"] .. "-" .. RotaryPushTBL[j]["alias"],
        name = "- - - - - - - - - - - Rotary" .. RotaryPushTBL[j]["source"] .. "-" .. RotaryPushTBL[j]["alias"],
        tags = {
            "rotarypush" .. string.lower(RotaryPushTBL[j]["source"]),
        },
        group = RotaryPushTBL[j]["group"],
        visible_in_projection = false,
        source = {
            kind = "Virtual",
            id = "Rotary" .. RotaryPushTBL[j]["source"],
            character = "Button",
        },
        glue = {
            absolute_mode = "ToggleButton",
            step_factor_interval = {1, 5},
        },
        target = {
            kind = "FxParameterValue",
            parameter = {
                address = "ById",
                    fx = {
                        address = "Instance",
                    },
                    index = RotaryPushTBL[j]["FXindex"],
            },
        },
    }
    local rotaryPushNameDisplay_FX_mapping = {
	    id = FXName .. "-RotaryPushNameDisplay" .. RotaryPushTBL[j]["source"] .. "-" .. RotaryPushTBL[j]["alias"],
        name = "RotaryPushNameDisplay" .. string.gsub(RotaryPushTBL[j]["source"],"Push","") .. " - " .. RotaryPushTBL[j]["alias"],
        tags = {
            "rotarypush" .. string.lower(RotaryPushTBL[j]["source"]),
        },
        group = RotaryPushTBL[j]["group"],
        visible_in_projection = false,
        source = {
            kind = "Virtual",
            id = "RotaryPushNameDisplay" .. string.gsub(RotaryPushTBL[j]["source"],"Push",""),
        },
        glue = {
            absolute_mode = "ToggleButton",
            step_factor_interval = {1, 5},
            feedback = {
                kind = "Text",
                text_expression = RotaryPushTBL[j]["alias"],
            },
        },
        target = {
            kind = "FxParameterValue",
            parameter = {
                address = "ById",
                    fx = {
                        address = "Instance",
                    },
                    index = RotaryPushTBL[j]["FXindex"],
            },
        },
    }
    local rotaryPushValueDisplay_FX_mapping = {
	    id = FXName .. "-RotaryPushValueDisplay" .. RotaryPushTBL[j]["source"] .. "-" .. RotaryPushTBL[j]["alias"],
        name = "Rotary" .. RotaryPushTBL[j]["source"] .. " - " .. RotaryPushTBL[j]["alias"] .. " - " .. "FXParamValueDisplay",
        tags = {
            "rotarypush" .. string.lower(RotaryPushTBL[j]["source"]),
        },
        group = RotaryPushTBL[j]["group"],
        visible_in_projection = false,
        source = {
            kind = "Virtual",
            id = "RotaryPushValueDisplay" .. string.gsub(RotaryPushTBL[j]["source"],"Push",""),
        },
        glue = {
            absolute_mode = "ToggleButton",
            step_factor_interval = {1, 5},
            feedback = {
                kind = "Text",
            },
        },
        target = {
            kind = "FxParameterValue",
            parameter = {
                address = "ById",
                    fx = {
                        address = "Instance",
                    },
                    index = RotaryPushTBL[j]["FXindex"],
            },
        },
    }
    local rotaryPushColor_FX_mapping = {
        id = FXName .. "-rotaryPushColor" .. RotaryPushTBL[j]["source"] .. "-" .. RotaryPushTBL[j]["alias"],
        name = "Rotary" .. RotaryPushTBL[j]["source"] .. " - " .. RotaryPushTBL[j]["alias"] .. " - Color",
        tags = {
            "rotarypush" .. string.lower(RotaryPushTBL[j]["source"]),
        },
        group = RotaryPushTBL[j]["group"],
        visible_in_projection = false,
        control_enabled = false,
        source = {
            kind = "Virtual",
            id = "RotaryPush" .. string.gsub(RotaryPushTBL[j]["source"],"Push","") .. "/Color",
        },
        glue = {
            step_size_interval = {0.01, 0.05},
            step_factor_interval = {1, 5},
            feedback = {
                kind = "Text",
                text_expression = RotaryPushTBL[j]["color"],
            },
        },
        target = {
            kind = "FxParameterValue",
            parameter = {
                address = "ById",
                fx = {
                    address = "Instance",
                },
                index = RotaryPushTBL[j]["FXindex"],
            },
        },
    }	
    local rotaryPushTouch_FX_mapping = {
        id = FXName .. "-rotaryPushTouch" .. RotaryPushTBL[j]["source"] .. "-" .. RotaryPushTBL[j]["alias"],
        name = "Rotary" .. RotaryPushTBL[j]["source"] .. " - " .. RotaryPushTBL[j]["alias"] .. " - Touch",
        tags = {
            "rotarypush" .. string.lower(RotaryPushTBL[j]["source"]),
        },
        group = RotaryPushTBL[j]["group"],
        visible_in_projection = false,
        control_enabled = false,
        source = {
            kind = "Virtual",
            id = "RotaryPush" .. string.gsub(RotaryPushTBL[j]["source"],"Push","") .. "/touch",
            character = "Button",
        },
        glue = {
            step_size_interval = {0.01, 0.05},
            step_factor_interval = {1, 5},
            feedback = {
                kind = "Text",
                text_expression = RotaryPushTBL[j]["color"],
            },
        },
        target = {
            kind = "FxParameterAutomationTouchState",
            parameter = {
                address = "ById",
                fx = {
                    address = "Instance",
                },
                index = RotaryPushTBL[j]["FXindex"],
            },
        },
    }	
    table.insert(mappings, rotaryPush_FX_mapping)
    table.insert(mappings, rotaryPushNameDisplay_FX_mapping)
    table.insert(mappings, rotaryPushValueDisplay_FX_mapping)
    table.insert(mappings, rotaryPushColor_FX_mapping)
    table.insert(mappings, rotaryPushTouch_FX_mapping)
end 

return {
    kind = "MainCompartment",
    version = "2.14.0-pre.10",
    value = {
        groups = groups,
        mappings = mappings,
    },
}
#pleasehelp

Thanks in advance
Puck is offline   Reply With Quote
Old 11-29-2022, 12:07 PM   #2995
KennyG5000
Human being with feelings
 
Join Date: Nov 2022
Posts: 49
Default

I wonder if anyone knows if this is achievable using Realearn: Can you use Realearn to somehow invoke OSC messages out of Reaper, such as the OSC message /fx/name that is sent by Reaper when there is a bank change instruction for the selected FX. This would be so handy, as by sending out the actual name of the VST/FX instance, I could then use this in Open Stage Control via a script to auto select the correct FX template.

I couldn't see any obvious way to trigger this via Reaper itself (bar changing the bank via the bank select OSC message), but hoping something like this is possible via Realearn (I am sure it likely is as it seems an incredible piece of software!). Thanks very much for any assistance!
KennyG5000 is offline   Reply With Quote
Old 11-29-2022, 12:56 PM   #2996
helgoboss
Human being with feelings
 
helgoboss's Avatar
 
Join Date: Aug 2010
Location: Germany
Posts: 1,951
Default

Quote:
Originally Posted by TonE View Post
Wow, since when there is a win32 of Realearn? Just saw it, quickly tested, Reaper not crashing. Cool, can start testing then... thanks a lot for adding win32 as well!
Oh, Win32! Has been there for years already, I think? Never testing it though. Wonder if the new control transformation editor works there.

Quote:
Originally Posted by Puck View Post
I was really trying not to have to bug you with this. But I've been at this for quite a while now.

1. Code is below.
2. Loop starts at line 163
3. Tables are on line 74

I'm not sure why this isn't working

I'm not sure if a) logic part is incorrect or b) the parser doesn't like multi line strings but it's also not throwing an error. Or something else entirely.

#pleasehelp

Thanks in advance
The parsing is okay, otherwise it wouldn't load. Also, I don't see any multi-line strings (they look like [[ ... ]] in Lua). The problem must be with the logic.

Looks like your issue is that no mapping gets an activation condition, right? I don't have the time to dig in at the moment but the problem is with your counter logic, I guess.

I think one feature which might help you a lot is this: "Menu => Advanced => Dry-run Lua script". Unlike "Import from clipboard", this just executed the Lua script and shows you the result (as JSON). In other words, the "expanded" version. The data that would be imported in the next step. Good for debugging. When I do this, I can quickly see that there's not a single mapping or group with conditional activation.

Quote:
Originally Posted by KennyG5000 View Post
I wonder if anyone knows if this is achievable using Realearn: Can you use Realearn to somehow invoke OSC messages out of Reaper, such as the OSC message /fx/name that is sent by Reaper when there is a bank change instruction for the selected FX. This would be so handy, as by sending out the actual name of the VST/FX instance, I could then use this in Open Stage Control via a script to auto select the correct FX template.

I couldn't see any obvious way to trigger this via Reaper itself (bar changing the bank via the bank select OSC message), but hoping something like this is possible via Realearn (I am sure it likely is as it seems an incredible piece of software!). Thanks very much for any assistance!
By "Bank change", do you mean "Preset change"? If yes, which kind of preset? A preset internal to your plug-in or the REAPER preset (dropdown above the plug-in window)?
helgoboss is offline   Reply With Quote
Old 11-29-2022, 02:16 PM   #2997
KennyG5000
Human being with feelings
 
Join Date: Nov 2022
Posts: 49
Default

Thanks for getting back to me so quickly Helgoboss, many apologies, I did not explain very well what I was referring to with bank change. In this instance, I notice when you send the OSC message /device/track/-" (+/-) to Reaper (so it is actually is when the track in incremented or decremented with an OSC message), Reaper returns a packet of OSC messages that include all of the FX parameter values/labels (at least for however many has been set in the Reaper OSC preference file), including fx/name, which I could then use to match the correct template on Open Stage Control to the matching selected VST/FX. Is there any way to use Realearn to somehow send the FX name via OSC out to the template on Open Stage Control? (I can see that you can send custom OSC out messages, but do not know how to imbed the currently selected FX name as a string in this OSC out message). Any help greatly appreciated thanks!
KennyG5000 is offline   Reply With Quote
Old 11-29-2022, 03:01 PM   #2998
helgoboss
Human being with feelings
 
helgoboss's Avatar
 
Join Date: Aug 2010
Location: Germany
Posts: 1,951
Default

Quote:
Originally Posted by KennyG5000 View Post
Thanks for getting back to me so quickly Helgoboss, many apologies, I did not explain very well what I was referring to with bank change. In this instance, I notice when you send the OSC message /device/track/-" (+/-) to Reaper (so it is actually is when the track in incremented or decremented with an OSC message), Reaper returns a packet of OSC messages that include all of the FX parameter values/labels (at least for however many has been set in the Reaper OSC preference file), including fx/name, which I could then use to match the correct template on Open Stage Control to the matching selected VST/FX. Is there any way to use Realearn to somehow send the FX name via OSC out to the template on Open Stage Control? (I can see that you can send custom OSC out messages, but do not know how to imbed the currently selected FX name as a string in this OSC out message). Any help greatly appreciated thanks!
The following sends OSC message "/fx/name" with the name of the first FX on the selected track, whenever you select a track:

Code:
{
    kind = "MainCompartment",
    version = "2.14.0",
    value = {
        mappings = {
            {
                id = "eYt6wFumIUMYcF9QZV-yW",
                name = "1",
                control_enabled = false,
                source = {
                    kind = "Osc",
                    address = "/fx/name",
                    argument = {
                        index = 0,
                        kind = "String",
                        value_range = {0, 1},
                    },
                },
                glue = {
                    feedback = {
                        kind = "Text",
                        text_expression = "{{ target.fx.name }}",
                    },
                },
                target = {
                    kind = "Fx",
                    fx = {
                        address = "ByIndex",
                        chain = {
                            address = "Track",
                            track = {
                                address = "Selected",
                            },
                        },
                        index = 0,
                    },
                    action = "DoNothing",
                },
            },
        },
    },
}
Copy this snippet and then press "Import from clipboard". It will replace the complete main compartment.
helgoboss is offline   Reply With Quote
Old 11-29-2022, 06:05 PM   #2999
Puck
Human being with feelings
 
Puck's Avatar
 
Join Date: Feb 2022
Location: Almost Canada
Posts: 499
Default

Thanks for taking a quick look. It's ok that you are busy

So I tried some more debugging. Here's something I found that looks suspicious:

I took out my logic and just set my activation_expression like this: (here's where the multi-line string was)

Code:
local activation_expression = [[{
        kind = "Modifier",
        modifiers = {
            {
                parameter = 0,
                on = false,
            },
        },
    }]]
The relevant lua looked like this:
Code:
local rotary_FX_mapping = {
	    id = FXName .. "-Rotary"..RotaryTBL[i]["source"] .. " - " .. RotaryTBL[i]["alias"],
        name = "- - - - - - - - - - - Rotary" .. RotaryTBL[i]["source"] .. " - " .. RotaryTBL[i]["alias"],
        activation_condition = activation_expression,
        tags = {
            "rotary" .. string.lower(RotaryTBL[i]["source"]),
        },
        group = RotaryTBL[i]["group"],
        visible_in_projection = false,
        source = {
            kind = "Virtual",
            id = "Rotary" .. RotaryTBL[i]["source"],
        },
        glue = {
            step_size_interval = {0.01, 0.05},
            step_factor_interval = {1, 5},
        },
        target = {
            kind = "FxParameterValue",
            parameter = {
                address = "ById",
                    fx = {
                        address = "Instance",
                    },
                    index = RotaryTBL[i]["FXindex"],
            },
        },
    }
The resulting dry run for one of those mappings looked like this in JSON:
Code:
{
        "visible_in_projection": false,
        "id": "YellowDrive-RotaryA2 - Level",
        "group": "rotarya",
        "name": "- - - - - - - - - - - RotaryA2 - Level",
        "source": {
          "id": "RotaryA2",
          "kind": "Virtual"
        },
        "activation_condition": "{\n        kind = \"Modifier\",\n        modifiers = {\n            {\n                parameter = 0,\n                on = false,\n            },\n        },\n    }",
        "tags": [
          "rotarya2"
        ],
        "target": {
          "parameter": {
            "fx": {
              "address": "Instance"
            },
            "index": 3,
            "address": "ById"
          },
          "kind": "FxParameterValue"
        },
        "glue": {
          "step_factor_interval": [
            1,
            5
          ],
          "step_size_interval": [
            0.01,
            0.05
          ]
        }
      },
here's how the relevant bit of a mapping like this is supposed to look. (I made the mapping manually then exported to clipboard as JSON):

Code:
},
        "activationType": "modifiers",
        "modifierCondition1": {
          "paramIndex": 0,
          "isOn": false
        }

So unless I'm missing something, that seems like a(the) problem but I don't understand what's happening just yet. No worries if you can't get to this. I'll try and figure it out myself too.

Ah. It looks like activation_condition isn't getting changed to activationType up converting from lua to JSON? The following string stuff also looks messed up obviously.
Puck is offline   Reply With Quote
Old 11-29-2022, 07:41 PM   #3000
Jkeeton72
Human being with feelings
 
Join Date: Aug 2018
Posts: 9
Default Twister!

Well it looks like I'm going to be getting a twister. My question to you Benjamin is this, while watching your video about the Twister you said you were not using the internal Banks of it. But then later in the video you said you were using the internal bank for the plug-in takeover part. I'm just curious why you used an internal Bank on part of it and not at another part? I was assuming you didn't need any internal banks with relearn. Any help with this would be greatly appreciated since I will be getting the controller soon. Thanks again!
Jkeeton72 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 11:08 AM.


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