AAX GetModifiers 12.5 Win

I’m trying to do this in my aax plugin running in Pro Tools Version 2018.4 and using the Juce 5.4.5 development branch:

bool altDown = ModifierKeys::getCurrentModifiersRealtime().isAltDown();

However I’m getting only false most of the time on Windows 10 when Alt is pressed. It is working fine on Mac OS X. If I keep hitting Alt I occasionally get one value of true when the key is hit, but I’d like to detect holding the Alt key. After reading this thread I tried only fetching the modifiers in the mouse callbacks but that didn’t help. I also tried reading the state directly from Windows using getAsyncKeyState(), but it appears Pro Tools is somehow blocking the information.

Has anyone managed to detect holding Alt successfully in an AAX plugin?

I don’t have any issue with the Alt modifier in mouseDown()… but you can use the AAX function GetModifiers()… I use it to get the Start modifier:

void EQNode::mouseDown (const MouseEvent& e)
{
    bool bIsCtrlDown = e.mods.isCtrlDown();
    bool bIsCommandDown = e.mods.isCommandDown();
    
#if JUCE_WINDOWS
    
    if (m_ViewContainer != nullptr)
        {
        uint32_t mods = 0;
        
        m_ViewContainer->GetModifiers (&mods);
        
        bIsCtrlDown = (mods & AAX_eModifiers_WINKEY) != 0;
        }
    
#endif
    
    if (e.mods.isAltDown() && ! bIsCtrlDown && ! e.mods.isShiftDown() && ! bIsCommandDown)
        {
        resetToDefault();
        
        return;
        }
    :
}

It depends where you’re testing though… as I mentioned earlier – in a ComboBox derived class I had to do some kludge work.

Rail

Rail, Thanks a lot for the response. In the meantime I found that getting the modifiers in MouseMoved is definitely broken, while it does work in MouseDown and MouseUp. That’s why I sometimes got a quick correct value when reading the modifiers supplied to the mouse callbacks.

I think there is a bug in the juce code. In juce_win32_Windowing.cpp in the doMouseMove method. The modifiers are fetched from the AAX wrapper in line 2561 and written to ModifierKeys::currentModifiers, but then in the doMouseEvent call the old value is sent which doesn’t get the information from the AAX call.

So I switched to using ModifierKeys::currentModifiers directly inside the mouse callbacks, but it’s also not working in MouseMoved - at least this way I can retain the last value. Maybe ProTools does not update Modifiers unless click events happen.

ModifierKeys::getCurrentModifiersRealtime() appears to always use getAsyncKeyState() which means it does not work right inside an AAX plugin.

Rail, how do you get the m_ViewContainer inside your Component?

Well the code snippet is from a DSP AAX plugin… so I have more access directly to the API… but check out the JUCE AAX wrapper method: getWin32Modifiers()

Have you checked out: Win/PT modifier fixes in JUCE 4.1

Rail

Thanks for linking to the other thread I hadn’t seen yet. The fix presented there does help a bit, but things aren’t working 100% yet.

It seems that during mouse move, other events reset the modifier state. I see now that the AAX SDK’s GetModifier() call works correctly, but unfortunately the current AAX wrapper implementation in juce is incomplete and only works reliably for mouseDown and mouseUp events. My best guess is that some events still poll GetAsyncKeyState() and then reset the modifier state.

I’ll now try to get access to the AAX_IViewContainer* to call it directly in my client code, but it’s tricky as the juce wrappers abstracts things away and debugging in Pro Tools is no joy.

I have tried many things getting the modifiers to work right in MouseMove, but even to get things half-working requires massive changes to both the AAX Wrapper and juce_win32_windowing and now I’ve given up on it.
What makes fixing the issue tricky is the way AAX modifiers have been patched in on top of the existing code. The non-aax code expects modifiers to be system-global and uses static methods, while in AAX modifiers are per plugin editor and have to be queried from the AAX owner. Right now, modifiers are overwritten for mouseDown and mouseUp, but other spots overwrite the state with bad information because inside PT getAsyncKeyState() always returns non-pressed for the Alt key.
Hopefully in the future someone can pick this up and find a real solution, but I’ve spent more than a day on it and now just use a different key instead of Alt.

So here’s the thing… I just added the Pro Tools automation menu for a client’s Native plugin… and I’d guess about 70% of the time on Windows the Start modifier is detected… so I looked into doing a hack… which I got to work… but the results are that even the AAX GetModifiers() is unreliable…

I had to modify the JUCE JUCE_AAX_Modifier_Injector.h

namespace juce
{

#ifndef DOXYGEN

struct ModifierKeyProvider
{
    virtual ~ModifierKeyProvider() {}
    virtual int getWin32Modifiers() const = 0;
    virtual uint32 getWin32AAXModifiers() const = 0;
};

struct ModifierKeyReceiver
{
    virtual ~ModifierKeyReceiver() {}
    virtual void setModifierKeyProvider (ModifierKeyProvider*) = 0;
    virtual void removeModifierKeyProvider() = 0;
    virtual ModifierKeyProvider* getModifierKeyProvider() = 0;
};

#endif

} // namespace juce

In the AAX Wrapper after int getWin32Modifiers() add:

uint32 getWin32AAXModifiers() const override
{
            uint32 aaxViewMods = 0;

            if (auto* viewContainer = GetViewContainer())
            {
                const_cast<AAX_IViewContainer*> (viewContainer)->GetModifiers (&aaxViewMods);
            }

            return aaxViewMods;
}

and in JUCE_Win32_Windowing add:

ModifierKeyProvider* getModifierKeyProvider() override
    {
        return modProvider;
    }

So my code:

#include <juce_audio_plugin_client/AAX/juce_AAX_Modifier_Injector.h>
#include <AAX_Enums.h>

void MySlider::mouseDown (const MouseEvent& e)
{
    Slider::mouseDown (e);
    
#if JUCE_WINDOWS
    
#if JUCE_MODULE_AVAILABLE_juce_audio_plugin_client
    
    PluginHostType host;
    
    if (host.isProTools())
        {
        ModifierKeyProvider* modProvider = nullptr;
        
        Component* pComponent = getParentComponent();           // The Editor
    
        if (pComponent != nullptr)
            pComponent = pComponent->getParentComponent();      // The ContentWrapperComponent
        
        if (pComponent != nullptr)
            {
            if (ModifierKeyReceiver* modReceiver = dynamic_cast<ModifierKeyReceiver*> (pComponent->getPeer()))
                modProvider = modReceiver->getModifierKeyProvider();
            
            if (modProvider != nullptr)
                {
                uint32_t mods = modProvider->getWin32AAXModifiers();
                
                bool bIsWinKeyDown = (mods & AAX_eModifiers_WINKEY) != 0;
                bool bIsControlKeyDown = (mods & AAX_eModifiers_Cntl) != 0;
                bool bIsAltKeyDown = (mods & AAX_eModifiers_Alt) != 0;
                
                if (bIsWinKeyDown)
                    DBG ("WIN KEY DOWN");
                
                if (bIsControlKeyDown)
                    DBG ("CTRL KEY DOWN");
                
                if (bIsAltKeyDown)
                    DBG ("ALT KEY DOWN");
                }
            }
        }
    
#endif // JUCE_MODULE_AVAILABLE_juce_audio_plugin_client
    
#endif // JUCE_WINDOWS
    
    :
}

Shows about the same ability to detect the Automation keystrokes (CTRL+ALT+START) as before I did the hack :slight_smile:

Hrmph

This will detect the ALT and CTRL 100% of the time though

Rail

Thanks for putting in the work I chose not to do. I haven’t tried your solution yet, but it looks very promising and it would be nice if the JUCE library could include it, so ctrl and alt would become reliable in AAX. I think the START/WINDOWS key is not a good key to use for anything in a plugin as Windows itself might interfere. I consider it reserved by Windows and not a modifier key.