64 bit plugins -what support is available in Juce?

Discuss issues relating to audio plugins

Re: 64 bit plugins -what support is available in Juce?

Postby Mikey » Mon Mar 14, 2011 3:23 pm

Thanks for freshening up this thread. I'm facing the 64-bit conundrum again and am glad to see people have made progress. Are you doing this with Juce 1.51 or are you using tip code?

Thx
Mikey
JUCE UberWeenie
 
Posts: 227
Joined: Fri Feb 20, 2009 7:36 pm
Location: The Rockies

Re: 64 bit plugins -what support is available in Juce?

Postby steffen » Tue Mar 15, 2011 6:23 pm

The 64-bit au builds have been possible for a while, even before the 1.51 release. Last time I tried I was building code with a pre-1.5.1 juce, but using the Introjucer from the current tip.
steffen
JUCE UberWeenie
 
Posts: 140
Joined: Tue May 04, 2010 11:52 am

Re: 64 bit plugins -what support is available in Juce?

Postby yfede » Mon Apr 04, 2011 9:13 am

Requests for 64 bit VSTs are becoming more frequent now that Cubase fully supports them.

Trying to build a JUCE-based 64 bit VST plug-in now results in some compilation errors due to the use of some HIView* functions, that are declared to be unavailable on 64-bit systems on their specifications.

Are they repleaceable somehow? I'd do it myself if I were more fluent in Cocoa/Carbon stuff.. Maybe what has already been done for getting rid of Carbon calls in the AU wrapper comes handy in this case too? :?:
User avatar
yfede
JUCE UberWeenie
 
Posts: 426
Joined: Fri Jun 08, 2007 5:04 pm
Location: Modena - Italy

Re: 64 bit plugins -what support is available in Juce?

Postby MadScientist » Mon Apr 04, 2011 7:20 pm

I've fiddled a bit with juce vst wrapper on mac, to get 64bit vst working. I've removed (from 64bit builds) all the unnecessary (I think :P ) Carbon stuff from juce_VST_Wrapper.mm, and assume that a pointer passed to attachComponentToWindowRef() function is a NSView pointer, so my version of that function for 64bit build looks like:

Code: Select all
void* attachComponentToWindowRef(Component* comp, void* windowRef)
{
  const ScopedAutoReleasePool pool;
  comp->addToDesktop(0,windowRef);
  return windowRef; 
}


Seems to work quite well, except for this one major problem, that if I want to "mouse interact" with any of the components, I need to first click it (so that it kind of gets "mouse focus"), and only then this component becomes responsive to mouse events. I'm a total ass... I mean newbie :wink: to osx, so if anyone got any idea how I could deal with this problem, it would be sweet, as we also want to get rid of listening to those series of questions like "when is 64bit vst mac version of your plugin coming?" ;)
BTW this is with juce 1.51.


cheers,
Bart :wink:
MadScientist
JUCE Weenie
 
Posts: 9
Joined: Mon Jan 19, 2009 9:58 pm

Re: 64 bit plugins -what support is available in Juce?

Postby MadScientist » Mon Apr 04, 2011 9:09 pm

Oh, nevermind. I figured it out. This additional code in attachComponentToWindowRef() seem to fix my problem:

Code: Select all
NSView* hostWindow = (NSView*)windowRef;
if ([hostWindow window] != 0)
{
  [[hostWindow window] setAcceptsMouseMovedEvents: YES];
}



cheers,
Bart ;)
MadScientist
JUCE Weenie
 
Posts: 9
Joined: Mon Jan 19, 2009 9:58 pm

Re: 64 bit plugins -what support is available in Juce?

Postby yfede » Tue Apr 05, 2011 8:18 am

Thank you very much. Would you mind posting the entire code for your juce_VST_Wrapper.mm file, so we (and hopefully jules as well) can have a look at it, and at the Carbon stuff you got rid off?
User avatar
yfede
JUCE UberWeenie
 
Posts: 426
Joined: Fri Jun 08, 2007 5:04 pm
Location: Modena - Italy

Re: 64 bit plugins -what support is available in Juce?

Postby jules » Tue Apr 05, 2011 9:24 am

Thanks for the tips!

Did you also change setNativeHostWindowSize() ? - I'd have thought that you'd need to make that deal with an NSView too..
User avatar
jules
Fearless Leader
 
Posts: 17218
Joined: Mon Sep 06, 2004 9:03 am
Location: London, UK

Re: 64 bit plugins -what support is available in Juce?

Postby MadScientist » Tue Apr 05, 2011 12:28 pm

jules wrote:Did you also change setNativeHostWindowSize() ? - I'd have thought that you'd need to make that deal with an NSView too..


Uhmm... our plugin does not use resizable editor, so I didn't bother with setNativeHostWindowSize(). In fact, I removed it from the wrapper code :oops: 8)

I've also spotted another problem with Cubase6 64bit. Seems that calling forwardCurrentKeyEventToHost() triggers massive CPU usage (I'm not sure why). After I open plugin editor, and give it's window keyboard focus (by clicking inside editor), pressing any key will just freeze Cubase (ActivityMonitor shows, that Cubase process eats almost 100% of CPU).

Anyway, for those interested, here is juce_vst_wrapper.mm code I used:

Code: Select all
#include "../juce_IncludeCharacteristics.h"

#if JucePlugin_Build_VST

#include <Cocoa/Cocoa.h>
#include <Carbon/Carbon.h>

#include "../juce_PluginHeaders.h"

#ifndef __LP64__
  #define ADD_CARBON_BODGE 1   // see note below..
#endif

//==============================================================================
BEGIN_JUCE_NAMESPACE

#if ADD_CARBON_BODGE
/* When you wrap a WindowRef as an NSWindow, it seems to bugger up the HideWindow
   function, so when the host tries (and fails) to hide the window, this catches
   the event and does the job properly.
*/

static pascal OSStatus windowVisibilityBodge (EventHandlerCallRef, EventRef e, void* user)
{
    NSWindow* hostWindow = (NSWindow*) user;

    switch (GetEventKind (e))
    {
    case kEventWindowShown:
        [hostWindow orderFront: nil];
        break;
    case kEventWindowHidden:
        [hostWindow orderOut: nil];
        break;
    }

    return eventNotHandledErr;
}
#endif

#ifndef __LP64__
static void updateComponentPos (Component* const comp)
{
    HIViewRef dummyView = (HIViewRef) (void*) (pointer_sized_int)
                            comp->getProperties() ["dummyViewRef"].toString().getHexValue64();

    HIRect r;
    HIViewGetFrame (dummyView, &r);
    HIViewRef root;
    HIViewFindByID (HIViewGetRoot (HIViewGetWindow (dummyView)), kHIViewWindowContentID, &root);
    HIViewConvertRect (&r, HIViewGetSuperview (dummyView), root);

    Rect windowPos;
    GetWindowBounds (HIViewGetWindow (dummyView), kWindowContentRgn, &windowPos);

    comp->setTopLeftPosition ((int) (windowPos.left + r.origin.x),
                              (int) (windowPos.top + r.origin.y));
}

static pascal OSStatus viewBoundsChangedEvent (EventHandlerCallRef, EventRef, void* user)
{
    updateComponentPos ((Component*) user);
    return noErr;
}
#endif // __LP64__

//==============================================================================
void initialiseMac()
{
#ifndef __LP64__
    NSApplicationLoad();
#endif
}

void* attachComponentToWindowRef (Component* comp, void* windowRef)
{
    const ScopedAutoReleasePool pool;
 
#ifndef __LP64__

    NSWindow* hostWindow = [[NSWindow alloc] initWithWindowRef: windowRef];
    [hostWindow retain];
    [hostWindow setCanHide: YES];
    [hostWindow setReleasedWhenClosed: YES];

    HIViewRef parentView = 0;

    WindowAttributes attributes;
    GetWindowAttributes ((WindowRef) windowRef, &attributes);
    if ((attributes & kWindowCompositingAttribute) != 0)
    {
        HIViewRef root = HIViewGetRoot ((WindowRef) windowRef);
        HIViewFindByID (root, kHIViewWindowContentID, &parentView);

        if (parentView == 0)
            parentView = root;
    }
    else
    {
        GetRootControl ((WindowRef) windowRef, (ControlRef*) &parentView);

        if (parentView == 0)
            CreateRootControl ((WindowRef) windowRef, (ControlRef*) &parentView);
    }

    // It seems that the only way to successfully position our overlaid window is by putting a dummy
    // HIView into the host's carbon window, and then catching events to see when it gets repositioned
    HIViewRef dummyView = 0;
    HIImageViewCreate (0, &dummyView);
    HIRect r = { {0, 0}, {comp->getWidth(), comp->getHeight()} };
    HIViewSetFrame (dummyView, &r);
    HIViewAddSubview (parentView, dummyView);
    comp->getProperties().set ("dummyViewRef", String::toHexString ((pointer_sized_int) (void*) dummyView));

    EventHandlerRef ref;
    const EventTypeSpec kControlBoundsChangedEvent = { kEventClassControl, kEventControlBoundsChanged };
    InstallEventHandler (GetControlEventTarget (dummyView), NewEventHandlerUPP (viewBoundsChangedEvent), 1, &kControlBoundsChangedEvent, (void*) comp, &ref);
    comp->getProperties().set ("boundsEventRef", String::toHexString ((pointer_sized_int) (void*) ref));

    updateComponentPos (comp);

#if ! JucePlugin_EditorRequiresKeyboardFocus
    comp->addToDesktop (ComponentPeer::windowIsTemporary | ComponentPeer::windowIgnoresKeyPresses);
#else
    comp->addToDesktop (ComponentPeer::windowIsTemporary);
#endif

    comp->setVisible (true);
    comp->toFront (false);

    NSView* pluginView = (NSView*) comp->getWindowHandle();
    NSWindow* pluginWindow = [pluginView window];
    [pluginWindow setExcludedFromWindowsMenu: YES];
    [pluginWindow setCanHide: YES];

    [hostWindow addChildWindow: pluginWindow
                       ordered: NSWindowAbove];
    [hostWindow orderFront: nil];
    [pluginWindow orderFront: nil];

#if ADD_CARBON_BODGE
    // Adds a callback bodge to work around some problems with wrapped
    // carbon windows..
    const EventTypeSpec eventsToCatch[] = {
        { kEventClassWindow, kEventWindowShown },
        { kEventClassWindow, kEventWindowHidden }
    };

    InstallWindowEventHandler ((WindowRef) windowRef,
                               NewEventHandlerUPP (windowVisibilityBodge),
                               GetEventTypeCount (eventsToCatch), eventsToCatch,
                               (void*) hostWindow, &ref);
    comp->getProperties().set ("carbonEventRef", String::toHexString ((pointer_sized_int) (void*) ref));
#endif // ADD_CARBON_BODGE
    return hostWindow;
 
#else // __LP64__
#if ! JucePlugin_EditorRequiresKeyboardFocus
    comp->addToDesktop (ComponentPeer::windowIgnoresKeyPresses, windowRef);
#else
    comp->addToDesktop (0,windowRef);
#endif
    NSView* hostWindow = (NSView*)windowRef;
    if ([hostWindow window] != 0)
    {
        [[hostWindow window] setAcceptsMouseMovedEvents: YES];
    }
    return windowRef;
#endif // __LP64__
}

void detachComponentFromWindowRef (Component* comp, void* nsWindow)
{
    {
        const ScopedAutoReleasePool pool;
#ifndef __LP64__
        EventHandlerRef ref = (EventHandlerRef) (void*) (pointer_sized_int)
                                    comp->getProperties() ["boundsEventRef"].toString().getHexValue64();
        RemoveEventHandler (ref);

#if ADD_CARBON_BODGE
        ref = (EventHandlerRef) (void*) (pointer_sized_int)
                  comp->getProperties() ["carbonEventRef"].toString().getHexValue64();
        RemoveEventHandler (ref);
#endif

        HIViewRef dummyView = (HIViewRef) (void*) (pointer_sized_int)
                                comp->getProperties() ["dummyViewRef"].toString().getHexValue64();

        if (HIViewIsValid (dummyView))
            CFRelease (dummyView);

        NSWindow* hostWindow = (NSWindow*) nsWindow;
        NSView* pluginView = (NSView*) comp->getWindowHandle();
        NSWindow* pluginWindow = [pluginView window];

        [hostWindow removeChildWindow: pluginWindow];
        comp->removeFromDesktop();

        [hostWindow release];
#else     
        comp->removeFromDesktop();
#endif __LP64__
    }

    // The event loop needs to be run between closing the window and deleting the plugin,
    // presumably to let the cocoa objects get tidied up. Leaving out this line causes crashes
    // in Live and Reaper when you delete the plugin with its window open.
    // (Doing it this way rather than using a single longer timout means that we can guarantee
    // how many messages will be dispatched, which seems to be vital in Reaper)
    for (int i = 20; --i >= 0;)
        MessageManager::getInstance()->runDispatchLoopUntil (1);
}


void checkWindowVisibility (void* nsWindow, Component* comp)
{
    NSWindow* hostWindow = (NSWindow*) nsWindow;
    comp->setVisible ([hostWindow isVisible]);
}

void forwardCurrentKeyEventToHost (Component* comp)
{
    NSWindow* win = [(NSView*) comp->getWindowHandle() window];
    [[win parentWindow] makeKeyWindow];
    [NSApp postEvent: [NSApp currentEvent] atStart: YES];
}


END_JUCE_NAMESPACE

#endif




cheers,
Bart ;)
MadScientist
JUCE Weenie
 
Posts: 9
Joined: Mon Jan 19, 2009 9:58 pm

Re: 64 bit plugins -what support is available in Juce?

Postby jules » Tue Apr 05, 2011 1:20 pm

Thanks! I've checked in some quick (and completely untested!) changes that should hopefully have the same effect. I've not got a copy of 64-bit cubase so would appreciate it if anyone fancies giving it a whirl!

I've also added a resizing function, although don't know whether it should actually be implemented or not.. (it could be the case that the host's NSView automatically reacts to changes in the size of the plugin's child view, so no action would be required for resizable views). If there are problems resizing, you could try commenting-out that function body and see if it still works..
User avatar
jules
Fearless Leader
 
Posts: 17218
Joined: Mon Sep 06, 2004 9:03 am
Location: London, UK

Re: 64 bit plugins -what support is available in Juce?

Postby ke20 » Tue Apr 05, 2011 1:35 pm

jules wrote:Thanks! I've checked in some quick (and completely untested!) changes that should hopefully have the same effect. I've not got a copy of 64-bit cubase so would appreciate it if anyone fancies giving it a whirl!

You can try with Presonus Studio One. The demo version is usable for one month.
User avatar
ke20
JUCE UberWeenie
 
Posts: 131
Joined: Thu Feb 08, 2007 2:56 pm

Re: 64 bit plugins -what support is available in Juce?

Postby yfede » Tue Apr 05, 2011 3:17 pm

Reaper also has its 64bit release, if I remember correctly
User avatar
yfede
JUCE UberWeenie
 
Posts: 426
Joined: Fri Jun 08, 2007 5:04 pm
Location: Modena - Italy

Re: 64 bit plugins -what support is available in Juce?

Postby ke20 » Tue Apr 05, 2011 3:26 pm

I had to change this to compile it:
- in setNativeHostWindowSize replace
Code: Select all
      // xxx is this necessary, or do the hosts detect a change in the child view and do this automatically?
         [hostView setSize: NSMakeSize ([hostView size].width + (newWidth - component->getWidth()),
                                 [hostView size].height + (newHeight - component->getHeight()))];

by
Code: Select all
      // xxx is this necessary, or do the hosts detect a change in the child view and do this automatically?
         [hostView setFrameSize: NSMakeSize ([hostView frame].size.width + (newWidth - component->getWidth()),
                                 [hostView frame].size.height + (newHeight - component->getHeight()))];


- in checkWindowVisibility
Code: Select all
void checkWindowVisibility (void* nsWindow, Component* comp)
{
#if JUCE_64BIT
    NSView* hostWindow = (NSView*) nsWindow;
   comp->setVisible ([[hostWindow window] isVisible]);
#else
    NSWindow* hostWindow = (NSWindow*) nsWindow;
   comp->setVisible ([hostWindow isVisible]);
#endif 


I achieved to load the plugin in Studio One but have no GUI for the moment.
Have to investigate a little bit.
User avatar
ke20
JUCE UberWeenie
 
Posts: 131
Joined: Thu Feb 08, 2007 2:56 pm

Re: 64 bit plugins -what support is available in Juce?

Postby jules » Tue Apr 05, 2011 3:38 pm

Whoops! When I said "completely untested", I really meant it! Thanks!

Looking at it again, the checkWindowVisibility() method actually isn't needed at all for NSViews, so can just become:

Code: Select all
void checkWindowVisibility (void* nsWindow, Component* comp)
{
   #if ! JUCE_64BIT
    comp->setVisible ([((NSWindow*) nsWindow) isVisible]);
   #endif
}


So the resizing code is required, then?
User avatar
jules
Fearless Leader
 
Posts: 17218
Joined: Mon Sep 06, 2004 9:03 am
Location: London, UK

Re: 64 bit plugins -what support is available in Juce?

Postby ke20 » Tue Apr 05, 2011 4:34 pm

It seems to be not called despite the window has the correct size but without any component inside.
I will compare 32 bit version to see what is going wrong.

[EDIT]
Ok so I checked in 32bit mode, setNativeHostWindowSize is only called when I change manually the size of the plugin, that's why it was not called in 64bit (I can not change the size because I don't have any component). So I think it is required.

[EDIT 2]
I tried it with Reaper Beta and it works. Maybe the no GUI bug is only on Studio One. I will try Cubase 6 ASAP.
User avatar
ke20
JUCE UberWeenie
 
Posts: 131
Joined: Thu Feb 08, 2007 2:56 pm

Re: 64 bit plugins -what support is available in Juce?

Postby ke20 » Wed Apr 06, 2011 9:25 am

Tried on Cubase 6 Demo and ... It works!!!
So the bug is more related to Studio One than 64bit despite it works fine on Studio One 32bit.

Thanks a lot MadScientist for your contribution :).

Kevin
User avatar
ke20
JUCE UberWeenie
 
Posts: 131
Joined: Thu Feb 08, 2007 2:56 pm

PreviousNext

Return to Audio Plugins

Who is online

Users browsing this forum: rbocquier and 1 guest