Emulate keystrokes from 0 to 99 from MIDI Controller value

TG37

2016-12-08 00:32:14

Hi,

I looked years for your software but didn't find it. This really saves my day for controlling Photoshop with Midi controllers.

But as I see you cannot use any variables in keystrokes and I saw this was already planned in 2011??? Will this ever happen?

This would be so hardly needed.

Would be great if you could get back to me.

For instance I will output Shift key + the value of a knob. Because like now it seems I would have to use a translator for every possible keystroke (1-100) this isn't even practical in any way.

Thanks,
Thomas

florian

2016-12-11 22:49:30

Hi Thomas,
thanks for posting and for requesting! Indeed, variables for keystrokes is on our feature request database, but so are hundreds (or thousands?) of other useful features... Priorities get raised if requested more often, and in fact, this feature is not asked for much, so we took the liberty to first work on other features.

One reason is certainly that there is a work-around. As you say, creating 100 translators is not practical, but it's definitely possible. There's a lot of copy/paste (or better: Duplicate Ctrl+D), but it shouldn't take more than 15 minutes to create all 100 translators and then you're done.

However, 3 notes for that approach:
  1. MIDI controllers usually go from 0 to 127, while Photoshop (I believe) usually has values from 0 to 99.
  2. MIDI controllers can send at a very fast rate, while keystrokes are relatively slow. They would pile up and cause sluggish behavior for fast knob movements
  3. With MT Pro's scripting, it is no problem to separate a number into the individual digits and then send digit by digit. So instead of 100 translators, only 10 are needed (plus the coordination rules)
I found your problem quite interesting, so I renamed your topic, and created a test project for the fun of it.

For 1), use a Rule to scale from 0..127 to 0..99. The basic Math is (using pp as incoming controller variable):

Code: Select all

pp=pp*99
pp=pp/127
For 2), we use a timer "Delayed Number" with 20ms delay. Only after 20ms, the actual keystrokes are executed. When a new MIDI controller message comes in during the 20ms, the new value is remembered, but the timer is restarted. That way, we throttle keystrokes to a rate of max. one per 20ms. The 20ms are somewhat arbitrary, but work fine.

For 3) we trigger the keystrokes in response to the "Delayed Number" timer. There, we have 3 translators:
Translator 0: calculate 10s digit, issue timer "send 10s digit"
Translator 1: calculate 1s digit, issue timer "send 1s digit"
Translator 2: issue timer "send ENTER" -- to terminate this value

In the example project, the main translator "Knob Movement" receives Controller #1 on MIDI Channel 1, scales this value to a value from 0..99, and stores this value in a global variable g0. As outgoing action, this translator starts (or restarts) the timer "Delayed Number".

Then, the translator "Send 10s digit" is executed when the timer expires (after 30ms). The rules calculate the 10s digit by dividing g0 by 10 and remember that value in the global variable g1. If that value is 0, we don't need to output a key and bail out. Otherwise, a 0-ms timer is started to actually send that 10s digit. 0-ms timers are a special feature which cause all translators which react to that timer to be executed with very little overhead.

The translator "send 1s digit" is executed directly afterwards (also in response to the "Delayed Number" timer. It calculates the 1s digit by calculating the remainder of the division by 10, i.e. the MOD function, using the % operator in the Rules in the translator.

The last translator in that preset issues a 0-ms timer to send ENTER (aka Return), also in response to the Delayed Number timer. We could generate the keystroke directly as an outgoing action here, but MT Pro only guarantees the correct order of outgoing actions if they're triggered in the same way. So to prevent that the ENTER is sent before, e.g., the 1s digit, we also queue it up using the 0ms timer.

For sending the actual digits, there are 2 presets with 10 translators each. For the 10s digits, the variable g1 is evaluated in the Rules and the corresponding digit is sent. For the 1s digits, the same, but for variable g2. It took me 2 minutes to create all these translators (using the duplicate function).

Of course, this is quite a lot to digest for a newbie... but it achieves a lot, and it should be easy to adapt to your needs. Whenever stuck, you know where to ask :)

The project is attached for direct download (see below), and here in text form:

Code: Select all

[x] Preset 0: Knob Input
 Default MIDI IN ports:   From Controller

[x] Translator 0.0: Knob Movement
Options: swallow
Incoming: Control Change on ch. 1 with CC#:1 (0x01) set 'pp' to value
Rules:
  pp=pp*99
  g0=pp/127
Outgoing: One-shot timer "Delayed Number": 20 ms delay

[x] Translator 0.1: Send 10s digit
Incoming: On timer "Delayed Number"
Rules:
  g1=g0/10
  if g1==0 then exit rules, skip Outgoing Action
Outgoing: One-shot timer "Send 10s Digit": 0 ms delay

[x] Translator 0.2: Send 1s digit
Incoming: On timer "Delayed Number"
Rules: g2=g0%10
Outgoing: One-shot timer "Send 1s Digit": 0 ms delay

[x] Translator 0.3: Send ENTER
Incoming: On timer "Delayed Number"
Rules: 
Outgoing: One-shot timer "Send ENTER": 0 ms delay


[x] Preset 1: Send 10s digits (g1)

[x] Translator 1.0: Digit 0
Incoming: On timer "Send 10s Digit"
Rules: if g1!=0 then exit rules, skip Outgoing Action
Outgoing: Text: 0

[x] Translator 1.1: Digit 1
Incoming: On timer "Send 10s Digit"
Rules: if g1!=1 then exit rules, skip Outgoing Action
Outgoing: Text: 1

[x] Translator 1.2: Digit 2
Incoming: On timer "Send 10s Digit"
Rules: if g1!=2 then exit rules, skip Outgoing Action
Outgoing: Text: 2

[x] Translator 1.3: Digit 3
Incoming: On timer "Send 10s Digit"
Rules: if g1!=3 then exit rules, skip Outgoing Action
Outgoing: Text: 3

[x] Translator 1.4: Digit 4
Incoming: On timer "Send 10s Digit"
Rules: if g1!=4 then exit rules, skip Outgoing Action
Outgoing: Text: 4

[x] Translator 1.5: Digit 5
Incoming: On timer "Send 10s Digit"
Rules: if g1!=5 then exit rules, skip Outgoing Action
Outgoing: Text: 5

[x] Translator 1.6: Digit 6
Incoming: On timer "Send 10s Digit"
Rules: if g1!=6 then exit rules, skip Outgoing Action
Outgoing: Text: 6

[x] Translator 1.7: Digit 7
Incoming: On timer "Send 10s Digit"
Rules: if g1!=7 then exit rules, skip Outgoing Action
Outgoing: Text: 7

[x] Translator 1.8: Digit 8
Incoming: On timer "Send 10s Digit"
Rules: if g1!=8 then exit rules, skip Outgoing Action
Outgoing: Text: 8

[x] Translator 1.9: Digit 9
Incoming: On timer "Send 10s Digit"
Rules: if g1!=9 then exit rules, skip Outgoing Action
Outgoing: Text: 9


[x] Preset 2: Send 1s digits (g2)

[x] Translator 2.0: Digit 0
Incoming: On timer "Send 1s Digit"
Rules: if g2!=0 then exit rules, skip Outgoing Action
Outgoing: Text: 0

[x] Translator 2.1: Digit 1
Incoming: On timer "Send 1s Digit"
Rules: if g2!=1 then exit rules, skip Outgoing Action
Outgoing: Text: 1

[x] Translator 2.2: Digit 2
Incoming: On timer "Send 1s Digit"
Rules: if g2!=2 then exit rules, skip Outgoing Action
Outgoing: Text: 2

[x] Translator 2.3: Digit 3
Incoming: On timer "Send 1s Digit"
Rules: if g2!=3 then exit rules, skip Outgoing Action
Outgoing: Text: 3

[x] Translator 2.4: Digit 4
Incoming: On timer "Send 1s Digit"
Rules: if g2!=4 then exit rules, skip Outgoing Action
Outgoing: Text: 4

[x] Translator 2.5: Digit 5
Incoming: On timer "Send 1s Digit"
Rules: if g2!=5 then exit rules, skip Outgoing Action
Outgoing: Text: 5

[x] Translator 2.6: Digit 6
Incoming: On timer "Send 1s Digit"
Rules: if g2!=6 then exit rules, skip Outgoing Action
Outgoing: Text: 6

[x] Translator 2.7: Digit 7
Incoming: On timer "Send 1s Digit"
Rules: if g2!=7 then exit rules, skip Outgoing Action
Outgoing: Text: 7

[x] Translator 2.8: Digit 8
Incoming: On timer "Send 1s Digit"
Rules: if g2!=8 then exit rules, skip Outgoing Action
Outgoing: Text: 8

[x] Translator 2.9: Digit 9
Incoming: On timer "Send 1s Digit"
Rules: if g2!=9 then exit rules, skip Outgoing Action
Outgoing: Text: 9


[x] Preset 3: Send Other keys

[x] Translator 3.0: Send ENTER
Incoming: On timer "Send ENTER"
Outgoing: Text: Return
Attachments
KnobToKeystrokeNumber.bmtp
(5.89 KiB) Downloaded 262 times

WPNL

2016-12-19 00:20:15

Hi guys,
I would like to hitchhike on this topic. I'm looking for the same solution but only for another photo editing application, Capture One.
I don't have hte experience or programming skills I'm seeing here but I would like to contribute in the form of some 'challenges' ;-)
I've managed to generate digits as output but they're not usable. What I was struggling with is that the image is not being updated while I rotate a controller (value -1 0 +1), the values are inserted in the field but nothing 'happens' ...

Some values are:
min / max
-4 / 4
-50 / 50
-100 / 100
0 / 1000
0,2 / 2,5
0 / 255

It would be really great if we could get this to work!

Thanks a lot in advance!

florian

2016-12-19 09:21:53

Hi,
so, I guess first of all you'll need to convert the relative encoder values (+1 / -1) to an absolute value to store in g0. That shouldn't be hard.

Then you say, the values are not updated? Currently, the preset "types" 1 or 2 digits, then ENTER. Maybe your photo program needs another sequence?

Last, but not least, you have to deal with different number ranges. I'm not sure how that can be solved easily. I don't think that MT Pro knows which value it is currently changing. Unless you direct the keyboard focus from within MT Pro, too. Then you could adjust the min/max range, and even remember the last value so that changing will not cause jumps.

Thanks,
Florian

WPNL

2016-12-19 22:17:38

Hi Florian.
Thanks for responding so soon. I've 'discovered' that the rotary controls of my NanoKontrol2 range from 0 to 127.
Another user pointed out the rotaries should be infinte so the values are put in cumulative, turning in one direction sends -1, the other direction sends +1 (or a designated keystroke).
I'm going to replace my controller, seems like the easiest way haha...

florian

2016-12-21 22:29:05

Hmmm, I don't quite understand. The above preset should work fine with the NanoKontrol's knobs.
And it's actually relatively simple to convert the "absolute" values of the knobs to "relative" or incremental -1/+1 values using MIDI Translator. let us know if you'd like to try that. But it won't help for outputting numbers.
Thanks,
Florian

TG37

2016-12-23 14:47:35

Hi,

sorry that I am answering so late. I was very busy in December actually.

Thanks from your great hints florian.

There is one thing that comes to my mind even more when reading this. Most of the modern MIDI controllers have a sort of editor for their knobs.
So for instance the AKAI'S I use you can set the MIDI controler value of a knob from 0..100, no problem at all, so you avoid calculating anything, the knob just sends out 0 to 100 and nothing more/less.

As I was busy as said I didn't implement your solution but actually found out that I can set my endless rotaries to send only a given value when putting it into one direction (e.g if you turn it left it doesn't send 99,98,97 etc. but it only ever sends 0, if you turn it right it doesn't send 98,99,100 but always 100): So why is this so great, it's just simple because you need only a rule for turning left which sends the keystroke to reduce the amount in the program and vice versa with right turn.

This is simply all one needs because if you are on zero in the program (photoshop) and send a keystrke for decreasing it stays zero, simple as that.

If you have non-endless rotaries of course this is more complicated as you have to get back to calculating so that you are really on zero when the knob is on it's left end.

Cheers and have a nice xmas,
Thomas

florian

2016-12-28 16:31:35

Hi Thomas,
hope you've had some nice christmas days. Thanks for sharing. You can use MT Pro's Rules to convert absolute values in relative incremental values, but it might be easier to use the control surface's editor.
Regards,
Florian

WPNL

2016-12-30 16:46:36

Hi Florian, I switched my controller. The Beatstep can send relative values. I'm there! :-)

Thanks a lot for your replies and pointers :-)

Have a nice day!

florian

2017-01-31 00:49:34

Hi WPNL, that's great to hear! Florian