Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Changing MIDI Fighter Twister LED colors using ReaLearn? #154

Closed
stereokai opened this issue Feb 19, 2021 · 35 comments
Closed

Changing MIDI Fighter Twister LED colors using ReaLearn? #154

stereokai opened this issue Feb 19, 2021 · 35 comments
Labels
documentation Improvements or additions to documentation high priority

Comments

@stereokai
Copy link

Currently I have the MIDI Fighter Twister set up using its built-in banks function, where I have a different layout and colors in every bank.

I would like to use the virtual mapping as you recommend in your guides, however, I would prefer not to use my color layouts.

In the guide for MIDI Twister, it says it's possible to control the colored LEDs using by sending MIDI CCs to the Twister, like so:
image

Can ReaLearn be configured to send multiple MIDI CCs when changing a mapping to configure the colors layout of the buttons?

Thanks!

@helgoboss
Copy link
Owner

helgoboss commented Feb 19, 2021

This is something I want to support with #113, which is high on my todo list (currently still working on OSC). My rough plan to support this use case (and a multitude of other ones) is to implement the following concept:

  • Provide a button "Details" (or similarly-named) in the mapping source section which opens up a small window containing mostly a text area.
  • This text area allows you to enter key-value pairs such as:
    mft.rgb_color: 54
    midi.send_on_activate: "F0 43 10 4C 02 01 5B 7F F7"
  • ReaLearn itself would read these key-value pairs and handle them if there's a handler.
  • In the beginning I plan to implement handlers for exactly the keys that you can see in the above example snippet (although details might still change). The handlers will be hard-coded into ReaLearn, but in a maintainable way. Example handlers:
    • mft.rgb_color: ReaLearn will translate the value into the correct Twister-specific MIDI message to be sent whenever that mapping gets active.
    • midi.send_on_activate: ReaLearn will interpret this as raw MIDI data (in this case sys-ex) and send it whenever the mapping gets active.
  • In order to support also more complicated scenarios, this shouldn't be just a flat key-value list but allow for deeply nested data. That's why I plan to not use simple INI file syntax but support YAML - which is as expressive as JSON while at the same time less verbose to write for humans. Another advantage of YAML is that users who are not into programming can still write this as a simple key-value list (such as in the example above) - everybody should be able to understand that.
  • Important: I prefer YAML over a scripting language because it's declarative. While a full-blown scripting language would give the user great power, it would severely limit the ability of ReaLearn to make future optimizations and improvements. It's also more extensible and easier for most users. Plus, nothing would prevent one in future to add a key that contains a little script as value. Plus, everything being YAML means that in future a UI could be made for these sort of things.

Best of all: It's very straightforward to implement this. And it provides a simple but scaleable framework for future extension. Writing handlers should be easy.

Your last use case of sending multiple CCs on mapping init could be done by using midi.send_on_activate but obviously for most people, entering raw MIDI data would be too difficult. Therefore the handler of this key could support also an alternative way of writing the init MIDI messages, something like the following:

midi.send_on_activate:
  - cc: [0, 7, 50]
  - cc: [0, 64, 2]

I'll probably start with working on that next week. If you have some feedback/comments/ideas, let me know.

@stereokai
Copy link
Author

stereokai commented Feb 20, 2021

@helgoboss I like this idea. Sounds like a sensible and flexible solution.

  • midi.send_on_activate: ReaLearn will interpret this as raw MIDI data (in this case sys-ex) and send it whenever the mapping gets active.
  • mft.rgb_color: ReaLearn will translate the value into the correct Twister-specific MIDI message to be sent whenever that mapping gets active.

Best of all: It's very straightforward to implement this. And it provides a simple but scaleable framework for future extension. Writing handlers should be easy.

Agree, but...

Are you sure you want to implement controller specific properties (that under the hood are generic MIDI)?
There are 2 reasons for my question:

  1. While I like the solution and find it highly flexible, it is not the most user friendly. Perhaps it is accessible to software devs like you and me, but to the everyday musician/producer might be too intimidating to approach. Have you considered a UI on top of this feature? It's my opinion that in general, your users should learn how their controllers' work, not (just) you. So maybe something like this:

image

  1. Supporting those specific rules in the long run will shape into an infinite maintenance hassle. Adding more controllers, updating the key-to-MIDI "translations" if and when controllers receive firmware updates, deciding which 3rd party features to include and which not. This in my eyes is even less justified if you go for a text only solution - it's super flexible but will simply be too complicated for most people to use. ReaLearn is already very rich and has a lot to offer - and a lot to learn as well. Try to think about it from you users' perspective.
* Important: I prefer YAML...

You're preaching to the choir here :)

@helgoboss
Copy link
Owner

Agree, but...

Are you sure you want to implement controller specific properties (that under the hood are generic MIDI)?
There are 2 reasons for my question:

  1. While I like the solution and find it highly flexible, it is not the most user friendly. Perhaps it is accessible to software devs like you and me, but to the everyday musician/producer might be too intimidating to approach. Have you considered a UI on top of this feature? It's my opinion that in general, your users should learn how their controllers' work, not (just) you. So maybe something like this:
image

Writing such a GUI can be done on top of that, totally independently. I'm providing the basic foundation for that. That's what I meant when writing "everything being YAML means that in future a UI could be made for these sort of things.".

One thing I'm rather sure about is that I'm not going to write this sort of GUI as part of ReaLearn's core, simply because of the fact that the underlying UI technology makes this too hard. I think you are coming from a web development perspective where building a GUI such as the one you showed is very easy. Doing this with the raw Win32 API / SWELL is pain. Just look at my GUI code and you will see why.

I develop ReaLearn for free for idealistic reasons and for the fun of it. Working on its UI often takes the fun out of it but I keep going because some things really need a GUI to be instantly and intuitively usable. However, things like setting light colors, initializing controllers ... that sounds a lot like configuration work to me, it's not something that needs to be done instantly and all the time. So I don't really see an urgent need for providing a very nice GUI for that - this would be just a small GUI-less part of ReaLearn. While I think user friendliness is important, I also think that one should not underestimate what a user can do. Writing a simple key value pair such as mft.rgb_color: 50 should be doable by everyone. Could be part of a preset also so it doesn't always have to be repeated. Or maybe a little UI where on the left side one can enter the keys and on the right side the values.

That said, having a GUI for things like this would of course still be better than not having one. This is actually one part where users with programming skills could contribute: It would be cool if someone could write little browser-based UI components that generate e.g. some aspects of the YAML: A GUI such as the one you sketched, or one to generate bezier curves. I could provide a way to integrate that into ReaLearn, e.g. via WebView.

  1. Supporting those specific rules in the long run will shape into an infinite maintenance hassle. Adding more controllers, updating the key-to-MIDI "translations" if and when controllers receive firmware updates, deciding which 3rd party features to include and which not. This in my eyes is even less justified if you go for a text only solution - it's super flexible but will simply be too complicated for most people to use. ReaLearn is already very rich and has a lot to offer - and a lot to learn as well. Try to think about it from you users' perspective.

I think even for the normal user, writing a simple mft.rgb_color: 50 requires less knowledge and effort than clicking together a list of MIDI messages using a generic UI. And this is a simple example ... just imagine you need to send sys-ex. From a user-friendliness perspective, I think it's desireable to have dedicated support for features of a particular controller because the user wouldn't need to look up the specific MIDI messages - which can be very troublesome, often not even documented. And if their controller feature is not supported or a new firmware broke things (which should be the exception), one could still resort to the generic MIDI way.

Concerning potential maintainance issues, organizing the code in the right way could prevent most of the maintenance hassle. The hassle that remains is just what it takes to provide such a feature. And even if just the handful of controllers that I own are supported in this way, it would be already better than no support at all. That's how I see it.

@helgoboss
Copy link
Owner

Note to self: #113 (the generic YAML thing) is implemented. The more controller-specific "RGB color" support discussed in this ticket would be most useful if it can somehow detect which control element the mapping actually is associated with so that we can really just write mft.rgb_color: 50 and don't need to write mft.encoder_1_2.rgb_color: 50.

@stereokai
Copy link
Author

stereokai commented Mar 12, 2021

Hey, totally missed your post from 3 weeks ago. Must say, you raise pretty sensible points there, can't really argue with them :) The (default?) idea that I had of a dedicated UI is indeed compelling, but most definitely the greater picture as you presented it certainly pushes me to join the camp of your minimalistic and elegant YAML, text based solution. Minimum viable product, minimum time spent. Well done.

so that we can really just write mft.rgb_color: 50 and don't need to write mft.encoder_1_2.rgb_color: 50.

That should be rather easy. The way I see it, mft.rgb_color: 50 would translate to F0 B1 00 32 F7. From end to start the bytes are:

  • F7 - hex for color code 50 (by the way, 0 and 127 both turn the color off. The lit colors are between 1-126)
  • 00 - the CC number - is the control identifier. That can be pulled out of the mapping
  • B1 - Channel number - in this case channel 2. These are by default channel 2 on MFT, but unfortunately can be reconfigured per button by the user using the MFT configuration utility. This is the only problematic part, because if the mapping is bound to the rotary encoder in place of the button, you can't pull this info out of the mapping. Might as well hardcode it? Or perhaps like earlier, you have another creative solution ;)

Thought I'd let you know though, I gave the new Advanced Settings feature a try. However, for some reason, it wasn't working. This SysEx line for example, is supposed to paint the first two knobs on the MFT green and yellow, respectively: F0 B1 00 36 B1 01 3F F7. I tried it out with a separate MIDI tool, and verified it to be working.

Unfortunately, trying out the new feature using the following configuration did not change the colors as expected:

---
on_activate:
  send_midi_feedback:
    - raw: F0 B1 00 36 B1 01 3F F7

I tried the following ways to trigger a mapping: Preset loading/unloading, Conditional activation, Target condition as well as just toggling the feedback checkbox as recommended, but nothing triggered the color change in the MFT. I double checked that the feedback was still working with other mappings. I also tried the same code, again with no result using on_deactivate. Probably I missed something in the guide?

@helgoboss
Copy link
Owner

The MFT doesn't need/want sys-ex for that:

---
on_activate:
  send_midi_feedback:
    - raw: B1 00 32

This is a normal control-change message (0xB0 is the status byte of a CC message on channel 1).

It's surprising that this works with another sys-ex tool.

@stereokai
Copy link
Author

@helgoboss Yep, that totally works. Thanks.

It's surprising that this works with another sys-ex tool.

The tool is called "Pocket MIDI", if you're interested.

@stereokai
Copy link
Author

@helgoboss I wrote a tool for designing MIDI Fighter Twister color layouts. It makes it easy peasy to create color banks to use with ReaLearn and makes this feature even more attractive now :)

I hope you find it useful!

https://www.stereokai.com/midi-fighter-twister-color-designer/

@helgoboss
Copy link
Owner

@stereokai Very cool, the idea of using the controller itself to modify the colors! Playful way of changing them :) In my case, it doesn't work because I have all encoders switched to relative control. Any chance you could support relative messages?

@stereokai
Copy link
Author

Yeah sure, can you share/explain how ReaLearn identifies if a control is absolute or relative? That would be helpful :)

@helgoboss
Copy link
Owner

helgoboss commented Mar 21, 2021

It's only a heuristic because there's no reliable way to detect it, not sure if you want to go into that. But here's the code that ReaLearn's learn function uses to guess among all popular encoder types (MFT only has "Encoder 2" type): https://github.com/helgoboss/realearn/blob/master/main/src/domain/midi_source_scanner.rs#L240-L240. The values parameter is an accumulation of all message "data 2 bytes" that arrived within a certain time slot.

An alternative could be to provide another dropdown menu / checkbox that lets users choose between Absolute and Relative.

@stereokai
Copy link
Author

If it's good enough for you, it's good enough for me :)

I read the code. Since I am not familiar with Rust yet, I'd like to ask, how many input values are you checking against in this heuristic? And for type 2 encoder, why are you checking against 57-71 when the values set in relative mode on the MFT are 63 and 65?

@helgoboss
Copy link
Owner

helgoboss commented Mar 21, 2021

I start a timer on the first incoming message and stop either if 10 messages are collected or 250ms are over. If you really want to do the same, RxJS is great in doing this :)

I check for 57 - 71 in order to also catch slightly accelerated encoder moves (MFT for example supports this, optionally).

@stereokai
Copy link
Author

Yes I'm familiar with RxJS, but I'm trying to keep this project as barebones as possible :)

Accelerated encoder moves? I am not familiar with this feature. How do you activate it on the MFT?

@helgoboss
Copy link
Owner

Understand.

You activate it by setting "Sensivity" to "Velocity Sensitive" in the MF Utility. To have an effect in ReaLearn, you must set "Step size max" to a higher value than "Step size min".

@helgoboss
Copy link
Owner

Just realized that the current "Midi Fighter Twister" controller preset sets "Speed min" = "Speed max", so acceleration doesn't currently have an effect if you use this particular preset. I'll fix that.

@stereokai
Copy link
Author

I see. Yeah I tried this mode out when I was just getting into ReaLearn 2. Forgot it exists!

@stereokai
Copy link
Author

stereokai commented Apr 5, 2021

@helgoboss I just published an update to the color designer with support for all knob types and all sensitivities!

It was fun and challenging working with the relative & velocity sensitive knobs. Probably you already know that, but in fact the ENC 3FH/41H knob also sends values other than 63 and 65, and the velocity sensitive one is not limited to 57-71, but in fact sends values across (almost) the entire 0-127 range (lowest I measured was 30).

I ended up writing a different solution to ReaLearn's scanner, which detects in real time what kind of knob is being twisted (supporting all knob types and sensitivities). The knob profile will also adjust if the MFT configuration has been changed. Based on my MFT unit, it works rather well, so I'm interested to know if the implementation is relevant to ReaLearn, although perhaps it's not, because it is (I assume - you tell me!) very MFT specific. Regardless, you're invited to try it out and have a look at the code - I would be happy to know what you think. :)

PS. I have to follow up on all the other issue updates lol!

@helgoboss
Copy link
Owner

@stereokai Super cool. Works great! It actually makes me want to drop that issue because entering the generated hex string of your web app into one "init mapping" seems easier than entering something like mft_color: red in each mapping.

Yes, I was aware that the devices with acceleration support (in MFT called "velocity") send values beyond 57-71. I took this limited range in order to decrease the probability of getting false positives for relative control elements (which would actually be absolute control elements).

Not sure yet if it's relevant to ReaLearn, but either way I would be interested to know how your scanning approach works.

@stereokai
Copy link
Author

It actually makes me want to drop that issue because entering the generated hex string of your web app into one "init mapping" seems easier than entering something like mft_color: red in each mapping.

I agree and I'm happy I was able to solve the issue in a way that pleases you :)

Not sure yet if it's relevant to ReaLearn, but either way I would be interested to know how your scanning approach works.

So if you think about it, the input values sent by absolute and relative knobs have very obvious "signatures". The differences are few and very simple: relative values are in the 61-67 range. Absolute values can be anything between 0-127, and are consecutive (except when they're velocity sensitive). Velocity sensitive knobs extend the relative range effectively to 47-81, and change nothing significant for absolute knobs (it's as if some values are dropped). So just by counting a few (I went with the lowly 3) consecutive inputs, you can infer quite a lot about what kind of knob you're dealing with. If an input falls out of 47-81, it's safe enough to deduce the knob is absolute. On the other hand, if you're getting repeated inputs between 47-81, it's likely that the knob is either relative or velocity sensitive relative. Now granted, you can probably see that this system is prone to false positives between 47-81. What keeps it in check however, is a simple error correction mechanism that checks for absolute knobs identified as relative, and ignores values outside of 47-87 for relative knobs (as I'm writing these lines I'm thinking about an alternative that would achieve the same error correction for relative knobs without the dropping the inputs). The key that makes this whole system work is that it's running on every input in real time, so the whole inference and error correction process takes milliseconds in most "normal" usage. That of course is untrue in the case of extremely slow user input, but it's an exception that in my use case can be ignored.

@helgoboss helgoboss added documentation Improvements or additions to documentation high priority labels Apr 10, 2021
@helgoboss
Copy link
Owner

So if you think about it, the input values sent by absolute and relative knobs have very obvious "signatures". The differences are few and very simple: relative values are in the 61-67 range. Absolute values can be anything between 0-127, and are consecutive (except when they're velocity sensitive). Velocity sensitive knobs extend the relative range effectively to 47-81, and change nothing significant for absolute knobs (it's as if some values are dropped). So just by counting a few (I went with the lowly 3) consecutive inputs, you can infer quite a lot about what kind of knob you're dealing with. If an input falls out of 47-81, it's safe enough to deduce the knob is absolute. On the other hand, if you're getting repeated inputs between 47-81, it's likely that the knob is either relative or velocity sensitive relative. Now granted, you can probably see that this system is prone to false positives between 47-81. What keeps it in check however, is a simple error correction mechanism that checks for absolute knobs identified as relative, and ignores values outside of 47-87 for relative knobs (as I'm writing these lines I'm thinking about an alternative that would achieve the same error correction for relative knobs without the dropping the inputs). The key that makes this whole system work is that it's running on every input in real time, so the whole inference and error correction process takes milliseconds in most "normal" usage. That of course is untrue in the case of extremely slow user input, but it's an exception that in my use case can be ignored.

Just had some minutes to read your answer. Thanks for the writeup! This sounds actually very similar to what ReaLearn does in order to detect the source character. What do you see as the main difference?

@stereokai
Copy link
Author

stereokai commented Apr 14, 2021

Thanks for reading :)

I start a timer on the first incoming message and stop either if 10 messages are collected or 250ms are over.

This, and that I chose to do it in real time on all input, while ReaLearn only does the above initially to detect the kind of controller, and then that information is saved per mapping, and the scanning is over (unless user asks to rescan the controller).

@helgoboss
Copy link
Owner

I start a timer on the first incoming message and stop either if 10 messages are collected or 250ms are over.

This, and that I chose to do it in real time on all input, while ReaLearn only does the above initially to detect the kind of controller, and then that information is saved per mapping, and the scanning is over (unless user asks to rescan the controller).

Ah okay!

Something else: Just wanted to add a hint in the user guide and link to your tool (if okay for you). One question: I saw that the raw MIDI data copied by your web app sets the LED colors, but in a temporary way. If I map the encoder pushes in ReaLearn (with feedback enabled), it overwrites the LED color - which makes sense and was to be expected. How do you use your tool in combination with ReaLearn? With feedback disabled?

Do you plan to add support for setting the indicator type, too? That would be awesome because that's something more "persistent" compared to LED colors (which might change in the process, e.g. by representing on/off values).

@stereokai
Copy link
Author

Just wanted to add a hint in the user guide and link to your tool (if okay for you)

I'll be honored! Thanks!

If I map the encoder pushes in ReaLearn (with feedback enabled), it overwrites the LED color - which makes sense and was to be expected

Does your MFT have any colors already configured for that bank?

Do you plan to add support for setting the indicator type, too?

I definitely could! Only that it would have to wait a few weeks, due to plans :)

@helgoboss
Copy link
Owner

helgoboss commented Apr 14, 2021

Just wanted to add a hint in the user guide and link to your tool (if okay for you)

I'll be honored! Thanks!

👍

If I map the encoder pushes in ReaLearn (with feedback enabled), it overwrites the LED color - which makes sense and was to be expected

Does your MFT have any colors already configured for that bank?

I use the default settings for the first bank (except encoders being set to relative). So the default LED color is blue.

ReaLearn itself just sends the usual feedback in response to target value changes - and that overwrites the current LED color (with the color that can be set by modifying Source Min/Max).

Do you plan to add support for setting the indicator type, too?

I definitely could! Only that it would have to wait a few weeks, due to plans :)

Looking forward :)

@helgoboss
Copy link
Owner

Ah, looking at your initial use case I think you probably map the encoder pushes without LED feedback and use the LEDs purely as a kind of help for visually structuring your MFT.

@stereokai
Copy link
Author

That's true :) Although I do have a situation where I need status feedback for toggle switches. I haven't yet tried it out! I didn't imagine there would be a conflict there! I have to try it out, just haven't gotten around to using it yet

@helgoboss
Copy link
Owner

There's one thing that would make this thing a tiny bit more usable. On Windows at least, REAPER needs to be closed to use your app because it needs access to the MIDI device (not sure if there's a multi-client-capable MFT MIDI driver). That leads to the somewhat complicated workflow described in the latest user guide addition (see above commit). Maybe this could be mitigated a bit by adding a dedicated button that copies the complete ReaLearn-specific YAML to the clipboard. That way the user wouldn't have to copy once from the user guide and once from your tool.

@stereokai
Copy link
Author

@helgoboss WIP ;)

image

@stereokai
Copy link
Author

stereokai commented May 3, 2021

@helgoboss I added the capability to wrap the color midi with the ReaLearn command. Please check it out :) I hope this helps!

@stereokai
Copy link
Author

Something else: Just wanted to add a hint in the user guide and link to your tool (if okay for you). One question: I saw that the raw MIDI data copied by your web app sets the LED colors, but in a temporary way. If I map the encoder pushes in ReaLearn (with feedback enabled), it overwrites the LED color - which makes sense and was to be expected. How do you use your tool in combination with ReaLearn? With feedback disabled?

@helgoboss so concerning this issue, can't on_activate be used with ReaLearn to display a different color when a button is pressed?

What makes it less user friendly, is that users will also add an on_deactivate command to those toggled mappings, to restore the original color they configured for that knob, and moreover, they will have figure which hex to use!

Would you be interested to collaborate on this usability challenge?

@helgoboss
Copy link
Owner

Thanks, I will check it out and update the user guide.

About your question. on_activate and on_deactivate are mapping lifecycle events, so they are intended purely for initializing and deinitializing a napping, not mor. What you are looking for is dynamic feedback in response to the target value, which has been existing in ReaLearn for a much longer time. This kind of feedback is handled in in other, more flexible ways (maybe you don't want just on/off colors but colors inbetween!). You have the following options:

a) Adjust source min/max (very easy to use but allows colors for on/off only ... see context sensitive help about button feedback)

b) Use the feedback-only "Raw MIDI" source (declarative, works on byte level).

c) Use the feedback-only "MIDI script" source (procedural, works on byte level, most flexible).

d) Use a feedback transformation formula (drawback: works with normalized floating point values, so better for continuous stuff)

e) Use "MIDI: Send message" target (just like the "Raw MIDI" source but as target instead of source ... so it doesn't react to target value changes but to control messages).

I consider your tool as the perfect way to come up with static LED layouts (which can also change in response to conditional activation). That's why I think the ability to configure the LED ring type would be a great feature addition because this is even more static in nature than LED coloring.

Maybe your tool could be improved to beat "Source min/max" (which is basically a color slider) in terms of usability but I don't know exactly how.

@stereokai
Copy link
Author

I consider your tool as the perfect way to come up with static LED layouts

Oh stop it, you! 😏 Well that's great because that was the purpose I had in mind!

Thank for the lengthy explanation, I will have to look all those terms up in the user guide to fully grasp them 😆.

The scenario I was asking about is, for example, a knob is set to control a fader, and when the knob button is held down, it deactivates the current mapping, and activates another one for a second fader. It would be beneficial to indicate the active binding with a different LED color, and in this scenario, it would be possible to do so with on_activate and on_deactivate :)

I understand why a pure toggle switch is more problematic to set up. Do I understand it correctly that those solutions you mentioned above are capable of solving it?

On the topic of setting the indicator using the tool - can you please describe what you'd like to change? I just went through the MFT manual and I'm not sure all indicator properties can be changed via MIDI, but I might be wrong. Next step would be to send some custom MIDI messages to the MFT and see what works

@stereokai
Copy link
Author

@helgoboss ? :)

@helgoboss
Copy link
Owner

The scenario I was asking about is, for example, a knob is set to control a fader, and when the knob button is held down, it deactivates the current mapping, and activates another one for a second fader. It would be beneficial to indicate the active binding with a different LED color, and in this scenario, it would be possible to do so with on_activate and on_deactivate :)

Exactly, this is what on_activate is for. Strictly speaking, on_deactivate is only necessary if it can happen that none of the mappings in question are active. If you just switch between multiple mappings, the deactivation message would immediately be voided by the activation of the next mapping - in this case you don't need on_deactivate.

I understand why a pure toggle switch is more problematic to set up. Do I understand it correctly that those solutions you mentioned above are capable of solving it?

Mmh, is it problematic to set up? I don't think so. Toggle switch is relatively easy. You set the off color via "Source Min" and on color via "Source Max".

On the topic of setting the indicator using the tool - can you please describe what you'd like to change? I just went through the MFT manual and I'm not sure all indicator properties can be changed via MIDI, but I might be wrong. Next step would be to send some custom MIDI messages to the MFT and see what works

You mean this one? https://www.recordcase.de/media/pdf/26/26/18/Midi-Fighter-Twister-User-Guide-2016.pdf

I would like to change what's described in the manual as "Detent" (make the LED ring centered). It would be useful to be able to change this on a per-mapping basis. But you are right, the docs don't say how to enable this and related settings via MIDI. Not sure if it would be possible to capture the sys-ex MIDI data which MF Utility sends to enable this.

There are other settings as well such as the animation stuff which I never experimented with but looks cool.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
documentation Improvements or additions to documentation high priority
Projects
None yet
Development

No branches or pull requests

2 participants