Keystrokes / Keyboard Input in Cubase 7 64bit

Yeah, passKeyUpDownToPeer was just a temporary hack I was trying. The easiest way to make a call from the plugin module code into the HWNDComponentPeer stuff is just to implement a function in the win32 code, and then declare it internally in the plugin code so it can be called.

Hi Greg,

While afaik you are right that JUCE has this issue, it is not at all true that all plugins built with JUCE are affected. I know that our (Sound Radix) plugins don't have this problem as well as another dev. I'll explain how it works:

When JUCE has problems such as this one, developers sometimes fix it in their own copies of JUCE, and often also share their fix or work-around with Jules and the community.

Often Jules will apply their suggested fixes. Some times he will not use their alleged fix, and that's ok. There are good and valid reason for this, but that's another discussion.

In the case of this issue, there was a thread (I couldn't find it by Googling, so working from memory here) where many devs discussed this very problem and offered different work-arounds. Some solutions worked in some hosts in some versions and some didn't. At the end I came with a version of the work around which seemed to work for me on all the DAWs I tested on.

Here's the work-around for Pro Tools, Cubase and Wavelab on Windows: https://github.com/yairchu/JUCE/commit/554cf7e2f9ac9a40f67641bc47d139bbabb94ace

What do I mean by work-around, rather than fix? My code checks if the DAW is PT, Cubase or Wavelab and does something different only for these. Applying the behavior that works in Cubase in all hosts actually causes a problem in some of them, hence the code needs to check which host it is running in and only apply the work-around there.

This means that if a new DAW comes out which requires the same behavior as Cubase, my plugins won't work well with that DAW until users report the problem and we work on it and it all takes some time..

In fact, I later added Nuendo to the list of hosts which require the work-around after users reported this problem happens there too. Patch for that - https://github.com/yairchu/JUCE/commit/a374cefe0d7b3347b72a4ff7c797054eedd3ce09

After also adding Nuendo to this list and releasing an update to our plugins at 2013-04-08 (http://www.soundradix.com/products/surfer-eq/release-notes) we haven't heard of this problem from users again, so I believe that in our plugins it currently works fine in all known DAWs.

I know that another manufacturer also applies this same work-around, because I had correspondence with them about it and helped them fix it.

You can contact Ample and Valhalla and ask them to try my patches linked above and check if that helps. Note that it will only be easy for them to incorporate my patches if they are already using new versions of JUCE, otherwise it will require some more work from them.

Cheers, Yair

btw, Jules - since moving to the new forum, I can't find a list of threads I contributed to, making it harder to find relevant old threads..

Hmm.. Just thinking about the idea of using a second window as a workaround.. Did you experiment with using a child window to hold the editor? Because if that worked, then it could be possible to actually embed the entire editor component inside a child HWND inside the normal HWND, and then it could choose which of its key events it allows to propagate up to the parent one (and hence to the host).. That might be a cleaner solution than using hooks (if it works!)

(And before Greg starts asking why I've not implemented the fix you suggested above: The reason I've not used this is that it only fixes the Label class, and isn't a "real" fix for the underlying problem. What I'd like to do is to find a solution that works equally well for any component that wants keypresses)

Did you experiment with using achild window to hold the editor?

Haven't tried that. May give that a shot but it will take a bit before I find some time for that..

Cheers, Yair

Hi Yair,

my former colleague at some point also read through related threads, and hacked up (his words) a workaround by doing stuff with modal windows as well. I think this is the thread you meant: http://www.juce.com/forum/topic/vst-plugin-still-not-getting-keystrokes.
The workarounds there suggested using a modal label and adding it to the desktop at the location of the clicked text edit field, IIRC. That's what I was still using now. But then I got a user saying he had problems activating our plugin using that workaround in Live 8, so our thing is not OK.

I think Jules'/Rails' approach seems promising here!
If I can help testing / logging things in Live8/9 or Cubase 5/7 let me know!

Contributed threads (and time-sorted search results): yes please.

Koen

No reason to feel anxious about me at this point. I’m confident this is getting worked on now, and am just keeping tabs on the progress. I apologize for the “it works in these plugins” post. My frustration and poor expectations that had built up over the last several months was effecting my reading comprehension.

Yep, that's the thread!

If your former colleague is Jakob or uses Jakob's patch, then as I mentioned in my comment (http://www.juce.com/comment/293708#comment-293708), this patch, while solving the problem in Cubase, actually creates the problem in Samplitude. It is possible that Live behaves like Samplitude. In that case, using my modified patch (acts like normal JUCE in most DAWs but acts as in Jakob's patch in Pro Tools, Cubase, Nuendo, and Wavelab) may solve your problems in Live.

Cheers, Yair

I've finally found a workaround for this that seems to work..

Took me all day, and it involves some absolutely horrible hooking tricks, but it does seem to do the right thing. I've only been testing in the VST3 demo host, and am sick of the sight of it now, so any testing that you could do in other systems would be appreciated!

Working well in Cubase 7.0.7 x64 on Windows 8

The only keystroke not coming through (even in the JUCE Demo Host) is the Numeric Period (VK_DECIMAL) (using the demo plugin for testing)

Rail

Hmm.. Can't test this myself right now, but doing a bit of research on the win32 ToUnicode function, people seem to say that you need to call it twice for it to work correctly.. so in juce_win32_Windowing.cpp, line 2050, does this help:

                        WCHAR text[16] = { 0 };

                        ToUnicode ((UINT) key, scanCode, keyState, text, 8, 0);

                        if (ToUnicode ((UINT) key, scanCode, keyState, text, 8, 0) != 1)
                            text[0] = 0;

?

No, you don’t need to do that the key code sent to doKeyDown() is correct…

Near line 2032 change it to:

            case VK_ADD:
            case VK_SUBTRACT:
            case VK_MULTIPLY:
            case VK_DIVIDE:
            case VK_SEPARATOR:            
                used = handleKeyUpOrDown (true);
                break;

            case VK_DECIMAL:
            default:
                used = handleKeyUpOrDown (true);

and this works.

Rail

Thanks for the efforts Jules!

I did some testing (just today: forum subscriptions didn't seem to have worked for me: no notifications):

Context: JuceDemoPlugin (pulled today), VS2010 release build, on Windows7 Ultimate 64bit

Cubase 7.0.7 32bit:
StudioOne 2.6.2 32bit:
works fine, except for /*-+. on numeric keypad

Cubase 7.07 64bit:
plugin loaded, but typing solution does not work: keys don't get through (intercepted by Cubase) as before, might be a Cubase VST bridge problem (this was with the 32bit build of the plugin, didn't try a 64bit build yet)

Ableton Live 8.4.2 32bit:
Ableton Live 9.1.1 32bit:
Bidule 0.9734 32bit:

works almost fine, except for /*-+. on numeric keypad
I do say almost, because while typing in text, I regularly had moments where the host would "freeze" (no GUI interaction possible) for about 5 seconds, before becoming responsive again. You could get the host out of this "unresponsive" state by clicking in the window of another application (so that the host and plugin lost focus) and than clicking back in the host.
If anyone else could try this on his/her system to confirm it's not just a problem on my system?

Ableton Live 9.1.1 64bit:
Bidule 0.9734 64bit:

(didn't load the 32bit plugin, didn't try a 64bit build yet)

Will try with a 64bit build as well.

Ok, try again now. Not sure why there was some old code in there that handled the numeric keypad differently - it seems to work with it removed.

No idea about the lock-ups though.. presumably some kind of recursive message loop?

The VST Bridge runs as a separate process which would probably need a system wide hook… Which would have to use a separate DLL… I don’t think it’s going to work.

Rail

We just applied the latest update and although cubase text input seems to work fine, we now face a really ugly problem in VSTPlugin Analyser. It is similar to KoenT's report, but this one happens every time:


What happens is that as soon editing is started and user hits the first key, the whole plugin freezes until it looses focus. After loosing the focus, the returned text corresponds to a very long string of the pressed key, e.g. "666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666" (you get the idea ;))

 

Edit: This is really difficult to debug because Visual Studio grabs the focus as soon it hits a break-point (in these cases, everything behaves properly and returns the expected, single "6").

Yeah, I don't care much about that, as we build a 64bit version anyway normally. As long as that works, it's just fine.

Ok, seems pretty clear that there's a recursive loop between the different hooks.. I've added a flag to try to stop that now, so let me know if it elps..

Sadly, no. It doesn't help, freeze still happens.

That's odd.. I can't see how it could be recursive without going through that code-path..

Here's a fix from Vladislav Goncharov (my colleague):

:)


             MSG& msg = *(MSG*) lParam;
 
-            if (nCode == HC_ACTION && offerKeyMessageToJUCEWindow (msg))
+            if (nCode == HC_ACTION && wParam == PM_REMOVE && offerKeyMessageToJUCEWindow (msg))
             {
                 zerostruct (msg);
                 msg.message = WM_USER;