5252
5353extern " C" yup::AudioProcessor* createPluginProcessor ();
5454
55+ @class AudioPluginEditorViewAU ;
56+
5557namespace yup
5658{
5759
@@ -221,6 +223,7 @@ class AudioPluginProcessorAU final
221223 {
222224 YUP_MODULE_DBG (PLUGIN_CLIENT_AU , " destroying processor instance: wrapper=" << yup::describePointer (this ) << " , component=" << yup::describePointer (componentInstance) << " , processor=" << yup::describePointer (processor.get ()));
223225
226+ closeEditorViews ();
224227 removeParameterListeners ();
225228 yup::endActiveParameterGestures (processor.get ());
226229
@@ -948,6 +951,26 @@ class AudioPluginProcessorAU final
948951
949952 AudioProcessor* getProcessor () const { return processor.get (); }
950953
954+ void registerEditorView (AudioPluginEditorViewAU* view)
955+ {
956+ if (view == nil)
957+ return ;
958+
959+ std::lock_guard<std::mutex> lock (editorViewsMutex);
960+ editorViews.push_back ((__bridge void *) view);
961+ }
962+
963+ void unregisterEditorView (AudioPluginEditorViewAU* view)
964+ {
965+ if (view == nil)
966+ return ;
967+
968+ std::lock_guard<std::mutex> lock (editorViewsMutex);
969+ editorViews.erase (std::remove (editorViews.begin (), editorViews.end (), (__bridge void *) view), editorViews.end ());
970+ }
971+
972+ void closeEditorViews ();
973+
951974 static AudioPluginProcessorAU* findInstance (AudioUnit component)
952975 {
953976 std::lock_guard<std::mutex> lock (getInstanceRegistryMutex ());
@@ -1047,6 +1070,7 @@ class AudioPluginProcessorAU final
10471070 }
10481071
10491072 ScopedYupInitialiser_GUI scopeInitialiser;
1073+ ScopedYupInitialiser_Windowing scopeWindowingInitialiser;
10501074 std::unique_ptr<AudioProcessor> processor;
10511075
10521076 MidiBuffer midiBuffer;
@@ -1055,9 +1079,11 @@ class AudioPluginProcessorAU final
10551079 ParameterChangeBuffer emptyParamChangeBuffer;
10561080 std::mutex midiMutex;
10571081 std::mutex parameterChangeMutex;
1082+ std::mutex editorViewsMutex;
10581083 std::vector<AUChannelInfo> channelInfoCache;
10591084 std::vector<AudioParameter::Ptr> listenedParameters;
10601085 std::vector<float *> audioChannels;
1086+ std::vector<void *> editorViews;
10611087 AudioUnit componentInstance = nullptr ;
10621088 bool renderingOffline = false ;
10631089 bool isBypassed = false ;
@@ -1068,8 +1094,6 @@ class AudioPluginProcessorAU final
10681094// ==============================================================================
10691095// Objective-C editor view
10701096
1071- @class AudioPluginEditorViewAU ;
1072-
10731097namespace yup
10741098{
10751099
@@ -1093,38 +1117,44 @@ class AudioPluginEditorViewAUListener final : public ComponentListener
10931117
10941118@interface AudioPluginEditorViewAU : NSView
10951119{
1096- yup::ScopedYupInitialiser_Windowing _scopeInitialiser ;
1120+ yup::AudioPluginProcessorAU* _processorWrapper ;
10971121 yup::AudioProcessor* _processor;
10981122 std::unique_ptr<yup::AudioProcessorEditor> _processorEditor;
10991123 std::unique_ptr<yup::AudioPluginEditorViewAUListener> _processorEditorListener;
11001124 bool _resizingEditorToBounds;
11011125}
1102- - (instancetype)initWithProcessor :(yup::AudioProcessor*)processor
1103- preferredSize:(NSSize)size;
1126+ - (instancetype)initWithAudioUnitWrapper :(yup::AudioPluginProcessorAU*)processorWrapper
1127+ preferredSize:(NSSize)size;
11041128- (void )attachEditorIfNeeded;
11051129- (void )detachEditorIfNeeded;
1130+ - (void )closeEditorIfNeeded;
1131+ - (void )closeEditorForProcessorDestruction;
11061132- (void )resizeEditorToBounds;
11071133- (void )resizeViewToEditorSize;
11081134- (void )processorEditorResized;
11091135@end
11101136
11111137@implementation AudioPluginEditorViewAU
11121138
1113- - (instancetype)initWithProcessor :(yup::AudioProcessor*)processor
1114- preferredSize:(NSSize)size
1139+ - (instancetype)initWithAudioUnitWrapper :(yup::AudioPluginProcessorAU*)processorWrapper
1140+ preferredSize:(NSSize)size
11151141{
1116- YUP_MODULE_DBG (PLUGIN_CLIENT_AU , " creating editor view: requestedWidth=" << yup::String (static_cast <double > (size.width )) << " , requestedHeight=" << yup::String (static_cast <double > (size.height )) << " , processor =" << yup::describePointer (processor ) << " , view=" << yup::describePointer ((__bridge void *) self));
1142+ YUP_MODULE_DBG (PLUGIN_CLIENT_AU , " creating editor view: requestedWidth=" << yup::String (static_cast <double > (size.width )) << " , requestedHeight=" << yup::String (static_cast <double > (size.height )) << " , wrapper =" << yup::describePointer (processorWrapper ) << " , view=" << yup::describePointer ((__bridge void *) self));
11171143
11181144 if ((self = [super initWithFrame:NSMakeRect (0 , 0 , size.width , size.height )]))
11191145 {
11201146 YUP_MODULE_DBG (PLUGIN_CLIENT_AU , " editor view initialised: view=" << yup::describePointer ((__bridge void *) self));
1121- _processor = processor;
1147+ _processorWrapper = processorWrapper;
1148+ _processor = processorWrapper != nullptr ? processorWrapper->getProcessor () : nullptr ;
11221149 _resizingEditorToBounds = false ;
11231150 [self setPostsFrameChangedNotifications:YES ];
11241151
1125- if (processor != nullptr && processor->hasEditor ())
1152+ if (_processorWrapper != nullptr )
1153+ _processorWrapper->registerEditorView (self);
1154+
1155+ if (_processor != nullptr && _processor->hasEditor ())
11261156 {
1127- _processorEditor.reset (processor ->createEditor ());
1157+ _processorEditor.reset (_processor ->createEditor ());
11281158
11291159 if (_processorEditor != nullptr )
11301160 {
@@ -1245,6 +1275,27 @@ class AudioPluginEditorViewAUListener final : public ComponentListener
12451275 YUP_MODULE_DBG (PLUGIN_CLIENT_AU , " editor detached from native view: isOnDesktop=" << yup::String (_processorEditor->isOnDesktop () ? " true" : " false" ));
12461276}
12471277
1278+ - (void )closeEditorIfNeeded
1279+ {
1280+ [self detachEditorIfNeeded];
1281+
1282+ yup::endActiveParameterGestures (_processor);
1283+
1284+ if (_processorEditor != nullptr && _processorEditorListener != nullptr )
1285+ _processorEditor->removeComponentListener (_processorEditorListener.get ());
1286+
1287+ _processorEditorListener.reset ();
1288+ _processorEditor.reset ();
1289+ }
1290+
1291+ - (void )closeEditorForProcessorDestruction
1292+ {
1293+ [self closeEditorIfNeeded];
1294+
1295+ _processorWrapper = nullptr ;
1296+ _processor = nullptr ;
1297+ }
1298+
12481299- (void )resizeEditorToBounds
12491300{
12501301 if (_processorEditor == nullptr )
@@ -1290,15 +1341,12 @@ class AudioPluginEditorViewAUListener final : public ComponentListener
12901341{
12911342 YUP_MODULE_DBG (PLUGIN_CLIENT_AU , " destroying editor view: view=" << yup::describePointer ((__bridge void *) self) << " , editor=" << yup::describePointer (_processorEditor.get ()) << " , processor=" << yup::describePointer (_processor));
12921343
1293- [self detachEditorIfNeeded ];
1344+ [self closeEditorIfNeeded ];
12941345
1295- yup::endActiveParameterGestures (_processor);
1346+ if (_processorWrapper != nullptr )
1347+ _processorWrapper->unregisterEditorView (self);
12961348
1297- if (_processorEditor != nullptr && _processorEditorListener != nullptr )
1298- _processorEditor->removeComponentListener (_processorEditorListener.get ());
1299-
1300- _processorEditorListener.reset ();
1301- _processorEditor.reset ();
1349+ _processorWrapper = nullptr ;
13021350 _processor = nullptr ;
13031351}
13041352
@@ -1315,6 +1363,20 @@ void AudioPluginEditorViewAUListener::componentResized (Component& component)
13151363 [owner processorEditorResized];
13161364}
13171365
1366+ void AudioPluginProcessorAU::closeEditorViews ()
1367+ {
1368+ std::vector<void *> viewsToClose;
1369+
1370+ {
1371+ std::lock_guard<std::mutex> lock (editorViewsMutex);
1372+ viewsToClose.swap (editorViews);
1373+ }
1374+
1375+ for (auto * view : viewsToClose)
1376+ if (view != nullptr )
1377+ [(__bridge AudioPluginEditorViewAU*) view closeEditorForProcessorDestruction];
1378+ }
1379+
13181380} // namespace yup
13191381
13201382// ==============================================================================
@@ -1354,8 +1416,8 @@ void AudioPluginEditorViewAUListener::componentResized (Component& component)
13541416 return nil;
13551417 }
13561418
1357- return [[AudioPluginEditorViewAU alloc] initWithProcessor :proc-> getProcessor ()
1358- preferredSize:inPreferredSize];
1419+ return [[AudioPluginEditorViewAU alloc] initWithAudioUnitWrapper :proc
1420+ preferredSize:inPreferredSize];
13591421}
13601422
13611423@end
0 commit comments