There’s a lot of talk about the incompatibility of VST 2.3 plug-ins in Cubase 4 on MacIntel.
I will try to give an overview about this issue from my viewpoint.
First get back to the announcement of Apple that they will switch from PowerPC processors to Intel processors. It was some kind of shock to say at least, because for us developers it was the next big transition after the two before namely from m68k to powerpc and then from classic Mac OS to Mac OS X.
At the same time Steinberg development was going to define and implement VST 3 and an update for VST 2.
VST 2.4 had 3 main goals :
- 64 bit system compatibility (not processing)
- MacIntel compatibility
- SDK clean up (with an eye on VST 3) so that we don’t need to make a VST 2.5 update
So we deprecated most stuff which was not used and stuff which won’t work on 64 bit systems.
At that time the only 64 bit operating system available was Windows XP 64 bit (besides all the unix/linux OS we don’t support at the moment). But we knew that Apple is working on a 64 bit OS as well. So we tried to get some information of how it would look like to write an SDK which we don’t need to update when Apple is shipping a 64 bit OS. One thing what was very clear is that Quickdraw won’t be ported by Apple and that there won’t be any support for non composited windows. Because of NDA we could not talk about this aspect in the public, but some Apple developers talked about it on some official mailing-lists in the past month, so I think this should be OK to post now.
So it was clear that the way the UI is handled in VST won’t be supported with Mac OS X 64 bit.
Looking at VST SDK 2.3 we saw that there were special treatment for the Mac UI: effEditDraw, effEditMouse, effEditTop, effEditSleep, effEditKey.
Part of the clean up was to remove special platform opcodes if possible. As we looked at what Mac OS API we could use in the future, we saw that we don’t need these opcodes anymore with HIViews. So we deprecated them and defined that with VST SDK 2.4 all windows must be composited (something previously wasn’t defined at all) and we clearly defined how to embed a plug-in editor into the host window (which was also not defined in previous SDK’s). So for the first time with VST on the Macintosh, we clearly described the editor part and we took care of future compatibility with Mac OS X 64 bit in mind.
One other aspect of switching to HIViews is that we may see more stability, because of some obscure bugs in Quickdraw we saw. (remember the “exception occurred in Module QD” crash ?)
Now comes backwards compatibility, the most discussed thing about VST 2.4.
As MacIntel was only officially supported with VST 2.4 and at that time no shipping Mac had an Intel processor, we saw the opportunity to get out of this special macintosh treatments in the SDK with only supporting VST 2.4 on MacIntel. We made it clear with the announcement of 2.4 that we won’t support 2.3 plug-ins on MacIntel and Windows 64 bit. We released 2.4 before Apple shipped any Intel Mac.
But there was and there are plug-ins which are compiled for MacIntel with VST 2.3. So what ?
There are two possibilities:
- these plug-ins are ported to 2.4
- VST hosts should support 2.3 and 2.4
Porting plug-ins to 2.4 may costs time for the plug-in developers to rewrite their UI code.
Supporting 2.3 for hosts (at least for the ones who support it on mac ppc) must be completely retested.
Even if you think that enabling 2.3 support in Cubase would be just a developer switch, I must admit that this is not the case. We never tested non compositing windows on MacIntel, all the code for support 2.3 on ppc is not compiled into Cubase 4 for MacIntel. This would mean Cubase 4 MacIntel must be completely tested again only for plug-ins where the developers know early on that their plug-in won’t work if they release it without 2.4 support.
I’ve mixed feelings about this, on the one hand I understand plug-in developers who don’t want to waste time supporting MacIntel.
On the other hand I think it’s their mistake to release a UB VST version of their plug-ins compiled with 2.3 as they should have known better.
And I think plug-in developers should take the opportunity for an easier transition to 64 bit on Mac OS. If they get their editors working without Quickdraw with VST 2.4 the chances are very high that they are getting a 64 bit version of their plug-in much earlier running than the others.
And even for those who don’t care at the moment for 64 bit, I think I gave any possible help on the VST mailing-list to get the editors working without much afford on their side.
Just as a reminder, here’s the source code I posted how to get an old plug-in working with HIViews:
-
// Start of Header
-
#include "aeffeditor.h"
-
-
class MacEditorWrapper
-
{
-
public:
-
MacEditorWrapper (AEffEditor* editor);
-
~MacEditorWrapper ();
-
-
bool attach (WindowRef window);
-
bool remove ();
-
-
virtual void draw (ERect* rect);
-
virtual bool mouse (VstInt32 x, VstInt32 y);
-
virtual bool wheel (float distance);
-
-
virtual void warpOrigin ();
-
virtual void resetOrigin ();
-
-
virtual void offsetChanged (int x, int y) { offsetX= x; offsetY = y; }
-
-
protected:
-
static pascal OSStatus carbonEventHandler (EventHandlerCallRef inHandlerCallRef, EventRef inEvent, void *inUserData);
-
-
AEffEditor* editor;
-
HIViewRef userPane;
-
HIViewRef contentView;
-
WindowRef window;
-
int offsetX;
-
int offsetY;
-
};
-
// End of Header
-
-
// Start of Source
-
#include "maceditorwrapper.h"
-
-
MacEditorWrapper::MacEditorWrapper (AEffEditor* editor)
-
: editor (editor)
-
, userPane (0)
-
, contentView (0)
-
, window (0)
-
, offsetX (0)
-
, offsetY (0)
-
{
-
}
-
-
MacEditorWrapper::~MacEditorWrapper ()
-
{
-
}
-
-
void MacEditorWrapper::draw (ERect* rect)
-
{
-
if (userPane)
-
editor->draw (rect);
-
}
-
-
bool MacEditorWrapper::mouse (VstInt32 x, VstInt32 y)
-
{
-
if (userPane)
-
return editor->mouse (x, y);
-
return false;
-
}
-
-
bool MacEditorWrapper::wheel (float distance)
-
{
-
if (userPane)
-
return editor->onWheel (distance);
-
return false;
-
}
-
-
void MacEditorWrapper::warpOrigin ()
-
{
-
if (userPane)
-
SetOrigin (-offsetX, -offsetY);
-
}
-
-
void MacEditorWrapper::resetOrigin ()
-
{
-
if (userPane)
-
SetOrigin (0, 0);
-
}
-
-
bool MacEditorWrapper::attach (WindowRef window)
-
{
-
WindowAttributes attr;
-
if (GetWindowAttributes (window, &attr) == noErr)
-
{
-
if (attr & kWindowCompositingAttribute)
-
{
-
if (HIViewFindByID (HIViewGetRoot (window), kHIViewWindowContentID, &contentView) == noErr)
-
{
-
ERect* r;
-
editor->getRect (&r);
-
if (CreateUserPaneControl (NULL, (Rect*)r, 0, &userPane) == noErr)
-
{
-
OSStatus err = HIViewAddSubview (contentView, userPane);
-
assert (err == noErr);
-
const EventTypeSpec eventTypes[] = { {kEventClassControl, kEventControlDraw},
-
{kEventClassControl, kEventControlHitTest},
-
{kEventClassControl, kEventControlClick},
-
{kEventClassControl, kEventControlBoundsChanged},
-
{kEventClassMouse, kEventMouseWheelMoved},
-
};
-
err = InstallControlEventHandler (userPane, MacEditorWrapper::carbonEventHandler, GetEventTypeCount (eventTypes), eventTypes, this, NULL);
-
assert (err == noErr);
-
this->window = window;
-
return true;
-
}
-
}
-
}
-
}
-
return false;
-
}
-
-
bool MacEditorWrapper::remove ()
-
{
-
if (userPane)
-
{
-
HIViewRemoveFromSuperview (userPane);
-
userPane = 0;
-
window = 0;
-
return true;
-
}
-
return false;
-
}
-
-
pascal OSStatus MacEditorWrapper::carbonEventHandler (EventHandlerCallRef inHandlerCallRef, EventRef inEvent, void *inUserData)
-
{
-
MacEditorWrapper* wrapper = (MacEditorWrapper*)inUserData;
-
OSStatus result = eventNotHandledErr;
-
-
CGrafPtr savedPort;
-
Boolean portChanged = QDSwapPort (GetWindowPort (wrapper->window), &savedPort);
-
SetOrigin (-wrapper->offsetX, -wrapper->offsetY);
-
-
switch (GetEventClass (inEvent))
-
{
-
case kEventClassMouse:
-
{
-
if (GetEventKind (inEvent) == kEventMouseWheelMoved)
-
{
-
SInt32 wheelDelta;
-
GetEventParameter (inEvent, kEventParamMouseWheelDelta, typeLongInteger, NULL, sizeof (SInt32), NULL, &wheelDelta);
-
if (wrapper->wheel ((float)wheelDelta))
-
result = noErr;
-
}
-
break;
-
}
-
case kEventClassControl:
-
{
-
switch (GetEventKind (inEvent))
-
{
-
case kEventControlDraw:
-
{
-
ERect* r;
-
wrapper->editor->getRect (&r);
-
wrapper->draw (r);
-
result = noErr;
-
break;
-
}
-
case kEventControlHitTest:
-
{
-
result = noErr;
-
break;
-
}
-
case kEventControlClick:
-
{
-
HIPoint hipoint;
-
GetEventParameter (inEvent, kEventParamWindowMouseLocation, typeHIPoint, NULL, sizeof (HIPoint), NULL, &hipoint);
-
HIPointConvert (&hipoint, kHICoordSpaceWindow, wrapper->window, kHICoordSpaceView, wrapper->userPane);
-
if (wrapper->mouse ((VstInt32)hipoint.x, (VstInt32)hipoint.y) == 1)
-
result = noErr;
-
break;
-
}
-
case kEventControlBoundsChanged:
-
{
-
UInt32 flags;
-
GetEventParameter (inEvent, kEventParamAttributes, typeUInt32, NULL, sizeof (UInt32), NULL, &flags);
-
if (flags & kControlBoundsChangePositionChanged)
-
{
-
HIPoint hipoint = {0, 0 };
-
HIPointConvert (&hipoint, kHICoordSpaceView, wrapper->userPane, kHICoordSpaceView, wrapper->contentView);
-
wrapper->offsetChanged (hipoint.x, hipoint.y);
-
}
-
break;
-
}
-
}
-
break;
-
}
-
}
-
-
SetOrigin (0, 0);
-
if (portChanged)
-
QDSwapPort (savedPort, NULL);
-
-
return result;
-
}
-
// End of Source
With this code you only need to do this in your editor open (void* ptr) method:
-
#if MAC
-
guiWrapper = new MacEditorWrapper (this);
-
guiWrapper->attach ((WindowRef)ptr);
-
#endif
And this on close :
-
#if MAC
-
guiWrapper->remove ();
-
delete guiWrapper;
-
guiWrapper = 0;
-
#endif
And of course guiWrapper should be a member of your editor class.