Files
2026-08-16 18:24:52 +07:00

276 lines
8.4 KiB
Plaintext

//------------------------------------------------------------------------
// Project : VST SDK
//
// Category : Helpers
// Filename : public.sdk/source/vst/auwrapper/aucocoaview.mm
// Created by : Steinberg, 12/2007
// Description : VST 3 -> AU Wrapper
//
//-----------------------------------------------------------------------------
// This file is part of a Steinberg SDK. It is subject to the license terms
// in the LICENSE file found in the top-level directory of this distribution
// and at www.steinberg.net/sdklicenses.
// No part of the SDK, including this file, may be copied, modified, propagated,
// or distributed except according to the terms contained in the LICENSE file.
//-----------------------------------------------------------------------------
/// \cond ignore
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
#import "aucocoaview.h"
#import "auwrapper.h"
#import "public.sdk/source/vst/utility/objcclassbuilder.h"
#import "pluginterfaces/base/funknownimpl.h"
#import "pluginterfaces/gui/iplugview.h"
#import "pluginterfaces/vst/ivsteditcontroller.h"
//------------------------------------------------------------------------
@interface NSObject (SMTG_AUView)
- (id)initWithEditController:(Steinberg::Vst::IEditController*)editController
audioUnit:(AudioUnit)au
preferredSize:(NSSize)size;
@end
//------------------------------------------------------------------------
namespace Steinberg {
namespace {
//------------------------------------------------------------------------
struct AUPlugFrame : U::Implements<U::Directly<IPlugFrame>>
{
AUPlugFrame (NSView* parent) : parent (parent) {}
tresult PLUGIN_API resizeView (IPlugView* view, ViewRect* vr) override
{
NSRect newSize = NSMakeRect ([parent frame].origin.x, [parent frame].origin.y,
vr->right - vr->left, vr->bottom - vr->top);
[parent setFrame:newSize];
return kResultTrue;
}
NSView* parent;
};
//------------------------------------------------------------------------
struct AUView
{
static constexpr auto VarNamePlugView = "plugView";
static constexpr auto VarNameEditController = "editController";
static constexpr auto VarNameAudioUnit = "audioUnit";
static constexpr auto VarNameDynlib = "dynlib";
static constexpr auto VarNamePlugFrame = "plugFrame";
static constexpr auto VarNameIsAttached = "isAttached";
struct Instance : ObjCInstance
{
using PlugViewVar = std::optional<ObjCVariable<IPlugView*>>;
using EditControllerVar = std::optional<ObjCVariable<Vst::IEditController*>>;
using AudioUnitVar = std::optional<ObjCVariable<AudioUnit>>;
using DynlibVar = std::optional<ObjCVariable<FObject*>>;
using PlugFrameVar = std::optional<ObjCVariable<AUPlugFrame*>>;
using IsAttachedVar = std::optional<ObjCVariable<BOOL>>;
Instance (__unsafe_unretained id obj) : ObjCInstance (obj, [NSView class])
{
plugView = getVariable<IPlugView*> (VarNamePlugView);
editController = getVariable<Vst::IEditController*> (VarNameEditController);
audioUnit = getVariable<AudioUnit> (VarNamePlugView);
dynlib = getVariable<FObject*> (VarNameDynlib);
plugFrame = getVariable<AUPlugFrame*> (VarNamePlugFrame);
isAttached = getVariable<BOOL> (VarNameIsAttached);
}
PlugViewVar plugView;
EditControllerVar editController;
AudioUnitVar audioUnit;
DynlibVar dynlib;
PlugFrameVar plugFrame;
IsAttachedVar isAttached;
};
static id alloc ()
{
static ObjCClass gInstance;
return [gInstance.cl alloc];
}
private:
struct ObjCClass
{
Class cl;
ObjCClass ()
{
cl = ObjCClassBuilder ()
.init ("SMTG_AUView", [NSView class])
.addIvar<IPlugView*> (VarNamePlugView)
.addIvar<Vst::IEditController*> (VarNameEditController)
.addIvar<AudioUnit> (VarNameAudioUnit)
.addIvar<FObject*> (VarNameDynlib)
.addIvar<AUPlugFrame*> (VarNamePlugFrame)
.addIvar<BOOL> (VarNameIsAttached)
.addMethod (@selector (initWithEditController:audioUnit:preferredSize:),
initWithEditController)
.addMethod (@selector (setFrame:), setFrame)
.addMethod (@selector (isFlipped), isFlipped)
.addMethod (@selector (viewDidMoveToSuperview), viewDidMoveToSuperview)
.addMethod (@selector (dealloc), dealloc)
.finalize ();
}
static id initWithEditController (id self, SEL cmd, Vst::IEditController* editController,
AudioUnit au, NSSize size)
{
ObjCInstance obj (self);
self = obj.callSuper<id (NSRect), id> (@selector (initWithFrame:),
NSMakeRect (0, 0, size.width, size.height));
if (self)
{
Instance inst (self);
inst.editController->set (editController);
editController->addRef ();
inst.audioUnit->set (au);
auto plugView = editController->createView (Vst::ViewType::kEditor);
if (!plugView ||
plugView->isPlatformTypeSupported (kPlatformTypeNSView) != kResultTrue)
{
[self dealloc];
return nil;
}
inst.plugView->set (plugView);
auto plugFrame = NEW AUPlugFrame (self);
inst.plugFrame->set (plugFrame);
plugView->setFrame (plugFrame);
if (plugView->attached (self, kPlatformTypeNSView) != kResultTrue)
{
[self dealloc];
return nil;
}
ViewRect vr;
if (plugView->getSize (&vr) == kResultTrue)
{
NSRect newSize = NSMakeRect (0, 0, vr.right - vr.left, vr.bottom - vr.top);
[self setFrame:newSize];
}
inst.isAttached->set (YES);
FObject* fObject = nullptr;
UInt32 size = sizeof (FObject*);
if (AudioUnitGetProperty (au, 64001, kAudioUnitScope_Global, 0, &fObject, &size) ==
noErr)
{
fObject->addRef ();
inst.dynlib->set (fObject);
}
}
return self;
}
static void setFrame (id self, SEL cmd, NSRect newSize)
{
Instance inst (self);
inst.callSuper<void (NSRect)> (@selector (setFrame:), newSize);
ViewRect viewRect (0, 0, newSize.size.width, newSize.size.height);
if (inst.plugView->get ())
inst.plugView->get ()->onSize (&viewRect);
}
static BOOL isFlipped (id self, SEL cmd) { return YES; }
static void viewDidMoveToSuperview (id self, SEL cmd)
{
Instance inst (self);
if (inst.plugView->get ())
{
if ([self superview])
{
if (!inst.isAttached->get ())
{
if (inst.plugView->get ()->attached (self, kPlatformTypeNSView) ==
kResultTrue)
{
inst.isAttached->set (YES);
}
}
}
else
{
if (inst.isAttached->get ())
{
inst.plugView->get ()->removed ();
inst.isAttached->set (NO);
}
}
}
}
static void dealloc (id self, SEL cmd)
{
Instance inst (self);
if (auto plugView = inst.plugView->get ())
{
if (inst.isAttached->get ())
{
plugView->setFrame (0);
plugView->removed ();
}
plugView->release ();
if (auto plugFrame = inst.plugFrame->get ())
plugFrame->release ();
if (auto editController = inst.editController->get ())
{
auto refCount = editController->addRef ();
if (refCount == 2)
editController->terminate ();
editController->release ();
editController->release ();
inst.editController->set (nullptr);
}
}
if (auto dynlib = inst.dynlib->get ())
dynlib->release ();
inst.callSuper<void ()> (@selector (dealloc));
}
};
};
//------------------------------------------------------------------------
} // anonymous
} // Steinberg
//------------------------------------------------------------------------
@implementation SMTG_AUCocoaUIBase_CLASS_NAME
//------------------------------------------------------------------------
- (unsigned)interfaceVersion
{
return 0;
}
//------------------------------------------------------------------------
- (NSString*)description
{
return @"Cocoa View";
}
//------------------------------------------------------------------------
- (NSView*)uiViewForAudioUnit:(AudioUnit)inAU withSize:(NSSize)inPreferredSize
{
using namespace Steinberg;
Vst::IEditController* editController = 0;
UInt32 size = sizeof (Vst::IEditController*);
if (AudioUnitGetProperty (inAU, 64000, kAudioUnitScope_Global, 0, &editController, &size) !=
noErr)
return nil;
return [[AUView::alloc () initWithEditController:editController
audioUnit:inAU
preferredSize:inPreferredSize] autorelease];
}
@end
/// \endcond