1//------------------------------------------------------------------------
2// Project     : VST SDK
3//
4// Category    : Helpers
5// Filename    : public.sdk/source/vst/auwrapper/aucocoaview.mm
6// Created by  : Steinberg, 12/2007
7// Description : VST 3 -> AU Wrapper
8//
9//-----------------------------------------------------------------------------
10// LICENSE
11// (c) 2020, Steinberg Media Technologies GmbH, All Rights Reserved
12//-----------------------------------------------------------------------------
13// Redistribution and use in source and binary forms, with or without modification,
14// are permitted provided that the following conditions are met:
15//
16//   * Redistributions of source code must retain the above copyright notice,
17//     this list of conditions and the following disclaimer.
18//   * Redistributions in binary form must reproduce the above copyright notice,
19//     this list of conditions and the following disclaimer in the documentation
20//     and/or other materials provided with the distribution.
21//   * Neither the name of the Steinberg Media Technologies nor the names of its
22//     contributors may be used to endorse or promote products derived from this
23//     software without specific prior written permission.
24//
25// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
26// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
27// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
28// IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
29// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
30// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
31// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
32// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
33// OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE  OF THIS SOFTWARE, EVEN IF ADVISED
34// OF THE POSSIBILITY OF SUCH DAMAGE.
35//-----------------------------------------------------------------------------
36
37/// \cond ignore
38
39#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
40
41#import "aucocoaview.h"
42#import "auwrapper.h"
43#import "pluginterfaces/vst/ivsteditcontroller.h"
44#import "pluginterfaces/gui/iplugview.h"
45#import "base/source/fobject.h"
46
47namespace Steinberg {
48
49//------------------------------------------------------------------------
50class AUPlugFrame : public FObject, public IPlugFrame
51//------------------------------------------------------------------------
52{
53public:
54	AUPlugFrame (NSView* parent) : parent (parent) {}
55	tresult PLUGIN_API resizeView (IPlugView* view, ViewRect* vr) SMTG_OVERRIDE
56	{
57		NSRect newSize = NSMakeRect ([parent frame].origin.x, [parent frame].origin.y, vr->right - vr->left, vr->bottom - vr->top);
58		[parent setFrame:newSize];
59		return kResultTrue;
60	}
61
62	OBJ_METHODS(AUPlugFrame, FObject)
63	DEF_INTERFACES_1(IPlugFrame, FObject)
64	REFCOUNT_METHODS(FObject)
65protected:
66	NSView* parent;
67};
68
69} // namespace Steinberg
70
71using namespace Steinberg;
72
73//------------------------------------------------------------------------
74#define SMTGCocoa_NSViewWrapperForAU SMTG_AU_PLUGIN_NAMESPACE (NSViewWrapperForAU)
75
76//------------------------------------------------------------------------
77@interface SMTGCocoa_NSViewWrapperForAU : NSView {
78//------------------------------------------------------------------------
79	IPlugView* plugView;
80	Vst::IEditController* editController;
81	AudioUnit audioUnit;
82	FObject* dynlib;
83	AUPlugFrame* plugFrame;
84
85	BOOL isAttached;
86}
87
88- (id) initWithEditController: (Vst::IEditController*) editController audioUnit: (AudioUnit) au preferredSize: (NSSize) size;
89
90@end
91
92//------------------------------------------------------------------------
93// SMTG_AU_PLUGIN_NAMESPACE (SMTGAUPluginCocoaView)
94//------------------------------------------------------------------------
95
96//------------------------------------------------------------------------
97@implementation SMTG_AU_PLUGIN_NAMESPACE (SMTGAUPluginCocoaView)
98
99//------------------------------------------------------------------------
100- (unsigned) interfaceVersion
101{
102    return 0;
103}
104
105//------------------------------------------------------------------------
106- (NSString *) description
107{
108    return @"Cocoa View";
109}
110
111//------------------------------------------------------------------------
112- (NSView *)uiViewForAudioUnit:(AudioUnit)inAU withSize:(NSSize)inPreferredSize
113{
114    Vst::IEditController* editController = 0;
115    UInt32 size = sizeof (Vst::IEditController*);
116    if (AudioUnitGetProperty (inAU, 64000, kAudioUnitScope_Global, 0, &editController, &size) != noErr)
117        return nil;
118    return [[[SMTGCocoa_NSViewWrapperForAU alloc] initWithEditController:editController audioUnit:inAU preferredSize:inPreferredSize] autorelease];
119}
120
121@end
122
123//------------------------------------------------------------------------
124@implementation SMTGCocoa_NSViewWrapperForAU
125//------------------------------------------------------------------------
126- (id) initWithEditController: (Vst::IEditController*) _editController audioUnit: (AudioUnit) au preferredSize: (NSSize) size
127{
128	self = [super initWithFrame: NSMakeRect (0, 0, size.width, size.height)];
129	if (self)
130	{
131		editController = _editController;
132		editController->addRef ();
133		audioUnit = au;
134		plugView = editController->createView (Vst::ViewType::kEditor);
135		if (!plugView || plugView->isPlatformTypeSupported (kPlatformTypeNSView) != kResultTrue)
136		{
137			[self dealloc];
138			return nil;
139		}
140
141		plugFrame = NEW AUPlugFrame (self);
142		plugView->setFrame (plugFrame);
143
144		if (plugView->attached (self, kPlatformTypeNSView) != kResultTrue)
145		{
146			[self dealloc];
147			return nil;
148		}
149		ViewRect vr;
150		if (plugView->getSize (&vr) == kResultTrue)
151		{
152			NSRect newSize = NSMakeRect (0, 0, vr.right - vr.left, vr.bottom - vr.top);
153			[self setFrame:newSize];
154		}
155
156		isAttached = YES;
157		UInt32 size = sizeof (FObject*);
158		if (AudioUnitGetProperty (audioUnit, 64001, kAudioUnitScope_Global, 0, &dynlib, &size) == noErr)
159			dynlib->addRef ();
160	}
161	return self;
162}
163
164
165//------------------------------------------------------------------------
166- (void) setFrame: (NSRect) newSize
167{
168	[super setFrame: newSize];
169	ViewRect viewRect (0, 0, newSize.size.width, newSize.size.height);
170
171	if (plugView)
172		plugView->onSize (&viewRect);
173}
174
175
176//------------------------------------------------------------------------
177- (BOOL)isFlipped { return YES; }
178
179//------------------------------------------------------------------------
180- (void)viewDidMoveToSuperview
181{
182	if (plugView)
183	{
184		if ([self superview])
185		{
186			if (!isAttached)
187			{
188				isAttached = plugView->attached (self, kPlatformTypeNSView) == kResultTrue;
189			}
190		}
191		else
192		{
193			if (isAttached)
194			{
195				plugView->removed ();
196				isAttached = NO;
197			}
198		}
199	}
200}
201
202//------------------------------------------------------------------------
203- (void) dealloc
204{
205	if (plugView)
206	{
207		if (isAttached)
208		{
209			plugView->setFrame (0);
210			plugView->removed ();
211		}
212		plugView->release ();
213		if (plugFrame)
214			plugFrame->release ();
215
216		if (editController)
217		{
218			Steinberg::uint32 refCount= editController->addRef ();
219			if (refCount == 2)
220				editController->terminate ();
221
222			editController->release ();
223			editController->release ();
224			editController = 0;
225		}
226	}
227	if (dynlib)
228		dynlib->release ();
229	[super dealloc];
230}
231
232@end
233
234/// \endcond
235