1
0
mirror of https://github.com/cookiengineer/audacity synced 2025-05-01 16:19:43 +02:00

Round 2 of wx3 changes on OSX

Main change is that VST GUI support is now integrate with new Cocoa
views.  Direct support for VST Cocoa views (via Cockos extensions:
http://www.reaper.fm/sdk/vst/vst_ext.php) has been added.
This commit is contained in:
Leland Lucius 2015-07-11 19:33:04 -05:00
parent a9184af222
commit b8872a4a02
13 changed files with 670 additions and 1409 deletions

View File

@ -876,6 +876,7 @@
2897F6F80AB3DB5A003C20C5 /* ToolsToolBar.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2897F6EC0AB3DB5A003C20C5 /* ToolsToolBar.cpp */; };
2897F6F90AB3DB5A003C20C5 /* TranscriptionToolBar.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2897F6EE0AB3DB5A003C20C5 /* TranscriptionToolBar.cpp */; };
2897F6FE0AB3DCD0003C20C5 /* Grabber.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2897F6FC0AB3DCD0003C20C5 /* Grabber.cpp */; };
289D127A1B44D57F00B5B6AA /* VSTControlMac.mm in Sources */ = {isa = PBXBuildFile; fileRef = 289D12791B44D57F00B5B6AA /* VSTControlMac.mm */; };
289E750A1006D0BD00CEF79B /* MixerBoard.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 289E75081006D0BD00CEF79B /* MixerBoard.cpp */; };
289F9C7E0AC671BB00797DC1 /* DeviceToolBar.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 289F9C7C0AC671BB00797DC1 /* DeviceToolBar.cpp */; };
28A4E2AC0F60319300E9E7F2 /* fftext.c in Sources */ = {isa = PBXBuildFile; fileRef = 28A4E2A40F60319300E9E7F2 /* fftext.c */; };
@ -1793,7 +1794,7 @@
1790B01509883BFD008A330A /* Compressor.h */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 3; lastKnownFileType = sourcecode.c.h; path = Compressor.h; sourceTree = "<group>"; tabWidth = 3; };
1790B01709883BFD008A330A /* Echo.cpp */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 3; lastKnownFileType = sourcecode.cpp.cpp; path = Echo.cpp; sourceTree = "<group>"; tabWidth = 3; };
1790B01809883BFD008A330A /* Echo.h */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 3; lastKnownFileType = sourcecode.c.h; path = Echo.h; sourceTree = "<group>"; tabWidth = 3; };
1790B01909883BFD008A330A /* Effect.cpp */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 3; lastKnownFileType = sourcecode.cpp.cpp; path = Effect.cpp; sourceTree = "<group>"; tabWidth = 3; };
1790B01909883BFD008A330A /* Effect.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.objcpp; fileEncoding = 30; indentWidth = 3; path = Effect.cpp; sourceTree = "<group>"; tabWidth = 3; };
1790B01A09883BFD008A330A /* Effect.h */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 3; lastKnownFileType = sourcecode.c.h; path = Effect.h; sourceTree = "<group>"; tabWidth = 3; };
1790B01B09883BFD008A330A /* Equalization.cpp */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 3; lastKnownFileType = sourcecode.cpp.cpp; path = Equalization.cpp; sourceTree = "<group>"; tabWidth = 3; };
1790B01C09883BFD008A330A /* Equalization.h */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 3; lastKnownFileType = sourcecode.c.h; path = Equalization.h; sourceTree = "<group>"; tabWidth = 3; };
@ -2607,6 +2608,9 @@
2897F6EF0AB3DB5A003C20C5 /* TranscriptionToolBar.h */ = {isa = PBXFileReference; fileEncoding = 5; indentWidth = 3; lastKnownFileType = sourcecode.c.h; path = TranscriptionToolBar.h; sourceTree = "<group>"; tabWidth = 3; };
2897F6FC0AB3DCD0003C20C5 /* Grabber.cpp */ = {isa = PBXFileReference; fileEncoding = 5; indentWidth = 3; lastKnownFileType = sourcecode.cpp.cpp; path = Grabber.cpp; sourceTree = "<group>"; tabWidth = 3; };
2897F6FD0AB3DCD0003C20C5 /* Grabber.h */ = {isa = PBXFileReference; fileEncoding = 5; indentWidth = 3; lastKnownFileType = sourcecode.c.h; path = Grabber.h; sourceTree = "<group>"; tabWidth = 3; };
289D12771B44D57F00B5B6AA /* VSTControl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = VSTControl.h; path = VST/VSTControl.h; sourceTree = "<group>"; };
289D12781B44D57F00B5B6AA /* VSTControlMac.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = VSTControlMac.h; path = VST/VSTControlMac.h; sourceTree = "<group>"; };
289D12791B44D57F00B5B6AA /* VSTControlMac.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = VSTControlMac.mm; path = VST/VSTControlMac.mm; sourceTree = "<group>"; };
289E75081006D0BD00CEF79B /* MixerBoard.cpp */ = {isa = PBXFileReference; fileEncoding = 5; indentWidth = 3; lastKnownFileType = sourcecode.cpp.cpp; path = MixerBoard.cpp; sourceTree = "<group>"; tabWidth = 3; };
289E75091006D0BD00CEF79B /* MixerBoard.h */ = {isa = PBXFileReference; fileEncoding = 5; indentWidth = 3; lastKnownFileType = sourcecode.c.h; path = MixerBoard.h; sourceTree = "<group>"; tabWidth = 3; };
289F9C7C0AC671BB00797DC1 /* DeviceToolBar.cpp */ = {isa = PBXFileReference; fileEncoding = 5; indentWidth = 3; lastKnownFileType = sourcecode.cpp.cpp; path = DeviceToolBar.cpp; sourceTree = "<group>"; tabWidth = 3; };
@ -5304,9 +5308,12 @@
28B97B800FBF77030076CF28 /* vst */ = {
isa = PBXGroup;
children = (
2885BFF10FC108F800128165 /* aeffectx.h */,
289D12771B44D57F00B5B6AA /* VSTControl.h */,
289D12781B44D57F00B5B6AA /* VSTControlMac.h */,
289D12791B44D57F00B5B6AA /* VSTControlMac.mm */,
28B97B850FBF771A0076CF28 /* VSTEffect.cpp */,
28B97B860FBF771A0076CF28 /* VSTEffect.h */,
2885BFF10FC108F800128165 /* aeffectx.h */,
);
name = vst;
sourceTree = "<group>";
@ -7585,6 +7592,7 @@
2888496F131B6CF600B59735 /* tr.po in Sources */,
28884970131B6CF600B59735 /* uk.po in Sources */,
28884971131B6CF600B59735 /* vi.po in Sources */,
289D127A1B44D57F00B5B6AA /* VSTControlMac.mm in Sources */,
28884972131B6CF600B59735 /* zh_TW.po in Sources */,
28884973131B6CF600B59735 /* zh.po in Sources */,
EDF3B7B01588C0D50032D35F /* Paulstretch.cpp in Sources */,

View File

@ -226,9 +226,9 @@
<string>Version AUDACITY_VERSION.AUDACITY_RELEASE.AUDACITY_REVISION.AUDACITY_MODLEVEL</string>
<key>NSHumanReadableCopyright</key>
<string>Audacity version AUDACITY_VERSION.AUDACITY_RELEASE.AUDACITY_REVISION.AUDACITY_MODLEVEL</string>
<key>LSRequiresCarbon</key>
<true/>
<key>CSResourcesFileMapped</key>
<key>NSHighResolutionCapable</key>
<true/>
<key>NSPrincipalClass</key>
<string>NSApplication</string>
</dict>
</plist>

View File

@ -178,7 +178,7 @@
#define USE_VAMP 1
/* Define if VST plug-in support is enabled */
#define USE_VST 0
#define USE_VST 1
/* Version number of package */
#define VERSION "2.0.6"

View File

@ -49,6 +49,10 @@ greater use in future.
#include "TimeWarper.h"
#include "nyquist/Nyquist.h"
#if defined(__WXMAC__)
#include <Cocoa/Cocoa.h>
#endif
static const int kDummyID = 30000;
static const int kSaveAsID = 30001;
static const int kImportID = 30002;
@ -2755,6 +2759,11 @@ EffectUIHost::EffectUIHost(wxWindow *parent,
wxDefaultPosition, wxDefaultSize,
wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER | wxMINIMIZE_BOX | wxMAXIMIZE_BOX)
{
#if defined(__WXMAC__)
// Make sure the effect window actually floats above the main window
[[((NSView *)GetHandle()) window] setLevel:NSFloatingWindowLevel];
#endif
SetName(effect->GetName());
SetExtraStyle(wxWS_EX_VALIDATE_RECURSIVELY);

View File

@ -8,66 +8,57 @@
**********************************************************************/
#ifndef AUDACITY_AUCONTROL_H
#define AUDACITY_AUCONTROL_H
#ifndef AUDACITY_VSTCONTROL_H
#define AUDACITY_VSTCONTROL_H
#if !defined(_LP64)
#include <Carbon/Carbon.h>
#endif
#include <wx/osx/private.h>
#include <wx/control.h>
//#include <AudioUnit/AudioUnit.h>
#include <AudioUnit/AudioComponent.h>
//#include <AudioUnit/AudioUnitProperties.h>
#include "aeffectx.h"
class VSTControlImpl : public wxWidgetCocoaImpl
{
public :
VSTControlImpl(wxWindowMac *peer, NSView *view);
~VSTControlImpl();
};
class VSTControl : public wxControl
class VSTEffectLink
{
public:
VSTControl();
~VSTControl();
bool Create(wxWindow *parent, AudioComponent comp, AudioUnit unit, bool custom);
void CreateCocoa();
void CreateGeneric();
void CocoaViewResized();
void OnSize(wxSizeEvent & evt);
#if !defined(_LP64)
void CreateCarbon();
void CreateCarbonOverlay();
void CarbonViewResized();
static pascal OSStatus ControlEventHandlerCallback(EventHandlerCallRef handler,
EventRef event,
void *data);
#endif
private:
AudioComponent mComponent;
AudioUnit mUnit;
NSView *mAUView;
NSView *mView;
wxSize mLastMin;
bool mSettingSize;
#if !defined(_LP64)
AudioComponentInstance mInstance;
WindowRef mWindowRef;
HIViewRef mHIView;
#endif
DECLARE_EVENT_TABLE();
virtual ~VSTEffectLink() {};
virtual intptr_t callDispatcher(int opcode, int index, intptr_t value, void *ptr, float opt) = 0;
};
class VSTControlBase : public wxControl
{
public:
VSTControlBase()
{
}
virtual ~VSTControlBase()
{
}
virtual bool Create(wxWindow *parent, VSTEffectLink *link)
{
mParent = parent;
mLink = link;
DontCreatePeer();
if (!wxControl::Create(parent, wxID_ANY, wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator, wxEmptyString))
{
return false;
}
return true;
}
protected:
wxWindow *mParent;
VSTEffectLink *mLink;
};
#if defined(__WXMAC__)
#include "VSTControlMac.h"
#elif defined(__WXMSW__)
#include "VSTControlMSW.h"
#elif defined(__WXGTK__)
#include "VSTControlGTK.h"
#endif
#endif

View File

@ -1,658 +0,0 @@
/**********************************************************************
Audacity: A Digital Audio Editor
VSTControl.mm
Leland Lucius
Several ideas and code snippets taken from HairerSoft's HSAUView class:
http://www.hairersoft.com/Downloads/HSAUView.zip
Created by Martin on 02/06/2007.
Copyright 2010 by HairerSoft.
You are most welcome to use this code in your own (open source or not)
project. Use at your own risk of course, etc. Please acknowledge at an
appropriate location (manual or about box for example).
Bug reports most welcome: Martin@HairerSoft.com
**********************************************************************/
#include <AudioUnit/AudioUnit.h>
#include <AudioUnit/AudioComponent.h>
#include <AudioUnit/AudioUnitProperties.h>
#include <AudioUnit/AUCocoaUIView.h>
#include <CoreAudioKit/CoreAudioKit.h>
#if !defined(_LP64)
#include <AudioUnit/AudioUnitCarbonView.h>
#endif
#include "VSTControl.h"
@interface AUView : NSView
{
VSTControl *mControl;
}
@end
@implementation AUView
+ (void)initialize
{
static BOOL initialized = NO;
if (!initialized)
{
initialized = YES;
wxOSXCocoaClassAddWXMethods(self);
}
}
- (instancetype)initWithControl:(VSTControl *)control
{
// Make sure a parameters were provided
NSParameterAssert(control);
mControl = control;
[super init];
return self;
}
- (BOOL)autoresizesSubviews
{
return NO;
}
- (void)cocoaViewResized:(NSNotification *)notification
{
mControl->CocoaViewResized();
}
@end
VSTControlImpl::VSTControlImpl(wxWindowMac *peer, NSView *view)
: wxWidgetCocoaImpl(peer, view, false, false)
{
}
VSTControlImpl::~VSTControlImpl()
{
}
BEGIN_EVENT_TABLE(VSTControl, wxControl)
EVT_SIZE(VSTControl::OnSize)
END_EVENT_TABLE()
VSTControl::VSTControl()
{
mComponent = NULL;
mUnit = NULL;
mAUView = nil;
mView = nil;
mSettingSize = false;
#if !defined(_LP64)
mHIView = NULL;
mWindowRef = NULL;
#endif
}
VSTControl::~VSTControl()
{
#if !defined(_LP64)
if (mHIView)
{
}
if (mInstance)
{
AudioComponentInstanceDispose(mInstance);
}
#endif
if (mView)
{
NSNotificationCenter *center = [NSNotificationCenter defaultCenter];
[center removeObserver:mAUView
name:NSViewFrameDidChangeNotification
object:mView];
[mView release];
}
if (mAUView)
{
[mAUView release];
}
}
bool VSTControl::Create(wxWindow *parent, AudioComponent comp, AudioUnit unit, bool custom)
{
mComponent = comp;
mUnit = unit;
DontCreatePeer();
if (!wxControl::Create(parent, wxID_ANY, wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator, wxEmptyString))
{
return false;
}
mAUView = [AUView alloc];
if (!mAUView)
{
return false;
}
[(AUView *)mAUView initWithControl:this];
[mAUView retain];
if (custom)
{
CreateCocoa();
#if !defined(_LP64)
if (!mView)
{
CreateCarbon();
}
#endif
}
if (!mView && !mHIView)
{
CreateGeneric();
}
if (!mView && !mHIView)
{
return false;
}
SetPeer(new VSTControlImpl(this, mAUView));
if (mHIView)
{
CreateCarbonOverlay();
}
// Must get the size again since SetPeer() could cause it to change
SetInitialSize(GetMinSize());
MacPostControlCreate(wxDefaultPosition, wxDefaultSize);
return true;
}
void VSTControl::OnSize(wxSizeEvent & evt)
{
evt.Skip();
if (mSettingSize)
{
return;
}
mSettingSize = true;
wxSize sz = GetSize();
if (mView)
{
int mask = [mView autoresizingMask];
NSRect viewFrame = [mAUView frame];
NSRect viewRect = [mView frame];
if (mask & NSViewWidthSizable)
{
viewRect.size.width = sz.GetWidth();
}
if (mask & NSViewHeightSizable)
{
viewRect.size.height = sz.GetHeight();
}
viewRect.origin.x = (viewFrame.size.width - viewRect.size.width) / 2;
viewRect.origin.y = (viewFrame.size.height - viewRect.size.height) / 2;
[mView setFrame:viewRect];
}
#if !defined(_LP64)
else if (mHIView)
{
HIRect rect;
HIViewGetFrame(mHIView, &rect);
CGFloat x = (sz.x - rect.size.width) / 2;
CGFloat y = (sz.y - rect.size.height) / 2;
SizeWindow(mWindowRef, sz.x, sz.y, true);
HIViewPlaceInSuperviewAt(mHIView, x, y);
wxWindow *w = wxGetTopLevelParent(this);
wxSize min = w->GetMinSize();
min.x += (rect.size.width - mLastMin.GetWidth());
min.y += (rect.size.height - mLastMin.GetHeight());
w->SetMinSize(min);
w->SetMaxSize(min);
mLastMin = wxSize(rect.size.width, rect.size.height);
}
#endif
mSettingSize = false;
return;
}
void VSTControl::CreateCocoa()
{
OSStatus result;
UInt32 dataSize;
result = AudioUnitGetPropertyInfo(mUnit,
kAudioUnitProperty_CocoaUI,
kAudioUnitScope_Global,
0,
&dataSize,
NULL);
if (result != noErr)
{
return;
}
int cnt = (dataSize - sizeof(CFURLRef)) / sizeof(CFStringRef);
if (cnt == 0)
{
return;
}
AudioUnitCocoaViewInfo *viewInfo = (AudioUnitCocoaViewInfo *) malloc(dataSize);
if (viewInfo == NULL)
{
return;
}
// Get the view info
result = AudioUnitGetProperty(mUnit,
kAudioUnitProperty_CocoaUI,
kAudioUnitScope_Global,
0,
viewInfo,
&dataSize);
if (result == noErr)
{
// Looks like the AU has a Cocoa UI, so load the factory class
NSURL *bundleLoc = (NSURL *) viewInfo->mCocoaAUViewBundleLocation;
NSString *viewClass = (NSString *) viewInfo->mCocoaAUViewClass[0];
if (bundleLoc != nil && viewClass != nil)
{
// Load the bundle
NSBundle *bundle = [NSBundle bundleWithPath:[bundleLoc path]];
if (bundle != nil)
{
// Load the class from the bundle
Class factoryClass = [bundle classNamed:viewClass];
if (factoryClass != nil)
{
// Create an instance of the class
id factoryInst = [[[factoryClass alloc] init] autorelease];
if (factoryInst != nil)
{
// Suggest a reasonable size
NSSize size = {800, 600};
// Create the view
mView = [factoryInst uiViewForAudioUnit:mUnit withSize:size];
}
}
}
}
if (viewInfo->mCocoaAUViewBundleLocation != nil)
{
CFRelease(viewInfo->mCocoaAUViewBundleLocation);
}
for (int i = 0; i < cnt; i++)
{
CFRelease(viewInfo->mCocoaAUViewClass[i]);
}
}
free(viewInfo);
if (!mView)
{
return;
}
[mView retain];
NSNotificationCenter *center = [NSNotificationCenter defaultCenter];
[center addObserver:mAUView
selector:@selector(cocoaViewResized:)
name:NSViewFrameDidChangeNotification
object:mView];
[mAUView addSubview:mView];
NSSize viewSize = [mView frame].size;
mLastMin = wxSize(viewSize.width, viewSize.height);
SetMinSize(mLastMin);
[mAUView setAutoresizingMask:[mView autoresizingMask]];
return;
}
void VSTControl::CreateGeneric()
{
OSStatus result;
AudioComponentDescription desc;
result = AudioComponentGetDescription(mComponent, &desc);
if (result == noErr && desc.componentType == kAudioUnitType_Panner)
{
mView = [AUPannerView AUPannerViewWithAudioUnit:mUnit];
if (mView == nil)
{
return;
}
}
else
{
// Create a generic AU view
AUGenericView *view = [AUGenericView alloc];
if (view == nil)
{
return;
}
int flags = AUViewPropertiesDisplayFlag |
AUViewParametersDisplayFlag;
[view initWithAudioUnit:mUnit displayFlags:flags];
[view setShowsExpertParameters:YES];
mView = view;
}
[mView retain];
NSNotificationCenter *center = [NSNotificationCenter defaultCenter];
[center addObserver:mAUView
selector:@selector(cocoaViewResized:)
name:NSViewFrameDidChangeNotification
object:mView];
[mAUView addSubview:mView];
NSSize viewSize = [mView frame].size;
mLastMin = wxSize(viewSize.width, viewSize.height);
SetMinSize(mLastMin);
[mAUView setAutoresizingMask:[mView autoresizingMask]];
return;
}
void VSTControl::CocoaViewResized()
{
if (mSettingSize)
{
return;
}
NSSize viewSize = [mView frame].size;
NSSize frameSize = [mAUView frame].size;
[mAUView setFrameSize:viewSize];
int diffW = (viewSize.width - frameSize.width);
int diffH = (viewSize.height - frameSize.height);
wxWindow *w = wxGetTopLevelParent(this);
wxSize min = w->GetMinSize();
if ([mView autoresizingMask] == NSViewNotSizable)
{
min.x += (viewSize.width - mLastMin.GetWidth());
min.y += (viewSize.height - mLastMin.GetHeight());
mLastMin = wxSize(viewSize.width, viewSize.height);;
}
else
{
min.x += diffW;
min.y += diffH;
}
w->SetMinSize(min);
wxSize size = w->GetSize();
size.x += diffW;
size.y += diffH;
w->SetSize(size);
}
#if !defined(_LP64)
void VSTControl::CreateCarbon()
{
OSStatus result;
UInt32 dataSize;
result = AudioUnitGetPropertyInfo(mUnit,
kAudioUnitProperty_GetUIComponentList,
kAudioUnitScope_Global,
0,
&dataSize,
NULL);
if (result != noErr)
{
return;
}
int cnt = (dataSize - sizeof(CFURLRef)) / sizeof(CFStringRef);
if (cnt == 0)
{
return;
}
AudioComponentDescription *compList = (AudioComponentDescription *) malloc(dataSize);
if (compList == NULL)
{
return;
}
// Get the view info
result = AudioUnitGetProperty(mUnit,
kAudioUnitProperty_GetUIComponentList,
kAudioUnitScope_Global,
0,
compList,
&dataSize);
if (result != noErr)
{
free(compList);
return;
}
// Get the component
AudioComponent comp = AudioComponentFindNext(NULL, &compList[0]);
// Try to create an instance
result = AudioComponentInstanceNew(comp, &mInstance);
// Done with the list
free(compList);
if (result != noErr)
{
return;
}
Rect bounds = { 100, 100, 200, 200 };
result = CreateNewWindow(kOverlayWindowClass,
kWindowStandardHandlerAttribute |
kWindowCompositingAttribute |
kWindowOpaqueForEventsAttribute,
&bounds,
&mWindowRef);
if (result != noErr)
{
AudioComponentInstanceDispose(mInstance);
mInstance = NULL;
return;
}
// Get the root control
ControlRef root = HIViewGetRoot(mWindowRef);
// Find the content view within our window
HIViewRef content;
result = HIViewFindByID(root, kHIViewWindowContentID, &content);
if (result != noErr)
{
DisposeWindow(mWindowRef);
mWindowRef = NULL;
AudioComponentInstanceDispose(mInstance);
mInstance = NULL;
return nil;
}
SetWindowActivationScope(mWindowRef, kWindowActivationScopeIndependent);
// Suggest a reasonable size
Float32Point loc = {0.0, 0.0};
Float32Point size = {800.0, 600.0};
// And create it
result = AudioUnitCarbonViewCreate(mInstance,
mUnit,
mWindowRef,
root,
&loc,
&size,
&mHIView);
if (result != noErr)
{
DisposeWindow(mWindowRef);
mWindowRef = NULL;
AudioComponentInstanceDispose(mInstance);
mInstance = NULL;
return;
}
HIViewAddSubview(root, mHIView);
HIViewPlaceInSuperviewAt(mHIView, 0, 0);
HIViewSetVisible(mHIView, TRUE);
HIRect rect;
HIViewGetFrame(mHIView, &rect);
SetMinSize(wxSize(rect.size.width, rect.size.height));
mLastMin = GetMinSize();
EventTypeSpec controlEventList[] =
{
{kEventClassControl, kEventControlBoundsChanged},
};
InstallControlEventHandler(mHIView,
ControlEventHandlerCallback,
GetEventTypeCount(controlEventList),
controlEventList,
(void *) this,
NULL);
return;
}
void VSTControl::CreateCarbonOverlay()
{
NSWindow *parent = [mAUView window];
WindowRef parentRef = (WindowRef)[parent windowRef];
NSWindow *host = [[[NSWindow alloc] initWithWindowRef:mWindowRef] autorelease];
[parent addChildWindow:host ordered:NSWindowAbove];
WindowGroupRef group;
CreateWindowGroup(0, &group);
SetWindowGroupParent(group, GetWindowGroup(parentRef));
ChangeWindowGroupAttributes(group,
kWindowGroupAttrLayerTogether |
kWindowGroupAttrSharedActivation |
kWindowGroupAttrHideOnCollapse,
0);
SetWindowGroup(parentRef, group);
SetWindowGroup(mWindowRef, group);
Rect location;
GetWindowBounds(parentRef, kWindowContentRgn, &location);
MoveWindow(mWindowRef, location.left, location.top, true);
ShowWindow(mWindowRef);
}
pascal OSStatus
VSTControl::ControlEventHandlerCallback(EventHandlerCallRef handler, EventRef event, void *data)
{
((VSTControl *) data)->CarbonViewResized();
return eventNotHandledErr;
}
void VSTControl::CarbonViewResized()
{
if (mSettingSize)
{
return;
}
// resize and move window
HIRect rect;
HIViewGetFrame(mHIView, &rect);
HIViewPlaceInSuperviewAt(mHIView, 0, 0);
SizeWindow(mWindowRef, rect.size.width, rect.size.height, true);
[mAUView setFrameSize:NSMakeSize(rect.size.width, rect.size.height)];
NSSize frameSize = [mAUView frame].size;
wxWindow *w = wxGetTopLevelParent(this);
wxSize size = w->GetSize();
size.x += (rect.size.width - frameSize.width);
size.y += (rect.size.height - frameSize.height);
w->SetMinSize(wxDefaultSize);
w->SetMaxSize(wxDefaultSize);
w->SetSize(size);
w->SetMinSize(size);
w->SetMaxSize(size);
mLastMin = size;
}
#endif

View File

@ -0,0 +1,71 @@
/**********************************************************************
Audacity: A Digital Audio Editor
VSTControlOSX.h
Leland Lucius
**********************************************************************/
#ifndef AUDACITY_VSTCONTROLOSX_H
#define AUDACITY_VSTCONTROLOSX_H
#if !defined(_LP64)
#include <Carbon/Carbon.h>
#endif
#include <wx/osx/private.h>
#include <wx/control.h>
#include "aeffectx.h"
class VSTControlImpl : public wxWidgetCocoaImpl
{
public :
VSTControlImpl(wxWindowMac *peer, NSView *view);
~VSTControlImpl();
};
class VSTControl : public VSTControlBase
{
public:
VSTControl();
~VSTControl();
bool Create(wxWindow *parent, VSTEffectLink *link);
void CreateCocoa();
void CocoaViewResized();
void OnSize(wxSizeEvent & evt);
#if !defined(_LP64)
void CreateCarbon();
void CreateCarbonOverlay();
void CarbonViewResized();
static pascal OSStatus ControlEventHandlerCallback(EventHandlerCallRef handler,
EventRef event,
void *data);
#endif
private:
NSView *mVSTView;
NSView *mView;
wxSize mLastMin;
bool mSettingSize;
#if !defined(_LP64)
WindowRef mWindowRef;
WindowRef mPreviousRef;
HIViewRef mHIView;
#endif
DECLARE_EVENT_TABLE();
};
#endif

View File

@ -0,0 +1,476 @@
/**********************************************************************
Audacity: A Digital Audio Editor
VSTControlMac.mm
Leland Lucius
Several ideas and code snippets taken from HairerSoft's HSVSTView class:
http://www.hairersoft.com/Downloads/HSVSTView.zip
Created by Martin on 02/06/2007.
Copyright 2010 by HairerSoft.
You are most welcome to use this code in your own (open source or not)
project. Use at your own risk of course, etc. Please acknowledge at an
appropriate location (manual or about box for example).
Bug reports most welcome: Martin@HairerSoft.com
**********************************************************************/
#include "VSTControl.h"
@interface VSTView : NSView
{
VSTControl *mControl;
}
@end
@implementation VSTView
+ (void)initialize
{
static BOOL initialized = NO;
if (!initialized)
{
initialized = YES;
wxOSXCocoaClassAddWXMethods(self);
}
}
- (instancetype)initWithControl:(VSTControl *)control
{
// Make sure a parameters were provided
NSParameterAssert(control);
mControl = control;
[super init];
return self;
}
- (BOOL)autoresizesSubviews
{
return NO;
}
- (void)cocoaViewResized:(NSNotification *)notification
{
mControl->CocoaViewResized();
}
@end
VSTControlImpl::VSTControlImpl(wxWindowMac *peer, NSView *view)
: wxWidgetCocoaImpl(peer, view, false, false)
{
}
VSTControlImpl::~VSTControlImpl()
{
}
BEGIN_EVENT_TABLE(VSTControl, wxControl)
EVT_SIZE(VSTControl::OnSize)
END_EVENT_TABLE()
VSTControl::VSTControl()
{
mLink = NULL;
mVSTView = nil;
mView = nil;
mSettingSize = false;
#if !defined(_LP64)
mHIView = NULL;
mWindowRef = NULL;
#endif
}
VSTControl::~VSTControl()
{
if (mWindowRef)
{
mLink->callDispatcher(effEditClose, 0, 0, mWindowRef, 0.0);
mWindowRef = 0;
}
}
bool VSTControl::Create(wxWindow *parent, VSTEffectLink *link)
{
if (!VSTControlBase::Create(parent, link))
{
return false;
}
mVSTView = [VSTView alloc];
if (!mVSTView)
{
return false;
}
[(VSTView *)mVSTView initWithControl:this];
[mVSTView retain];
CreateCocoa();
#if !defined(_LP64)
if (!mView)
{
CreateCarbon();
}
#endif
if (!mView && !mHIView)
{
return false;
}
SetPeer(new VSTControlImpl(this, mVSTView));
if (mHIView)
{
CreateCarbonOverlay();
}
// Must get the size again since SetPeer() could cause it to change
SetInitialSize(GetMinSize());
MacPostControlCreate(wxDefaultPosition, wxDefaultSize);
return true;
}
void VSTControl::OnSize(wxSizeEvent & evt)
{
evt.Skip();
if (mSettingSize)
{
return;
}
mSettingSize = true;
wxSize sz = GetSize();
if (mView)
{
int mask = [mView autoresizingMask];
NSRect viewFrame = [mVSTView frame];
NSRect viewRect = [mView frame];
if (mask & NSViewWidthSizable)
{
viewRect.size.width = sz.GetWidth();
}
if (mask & NSViewHeightSizable)
{
viewRect.size.height = sz.GetHeight();
}
viewRect.origin.x = (viewFrame.size.width - viewRect.size.width) / 2;
viewRect.origin.y = (viewFrame.size.height - viewRect.size.height) / 2;
[mView setFrame:viewRect];
}
#if !defined(_LP64)
else if (mHIView)
{
HIRect rect;
HIViewGetFrame(mHIView, &rect);
CGFloat x = (sz.x - rect.size.width) / 2;
CGFloat y = (sz.y - rect.size.height) / 2;
SizeWindow(mWindowRef, sz.x, sz.y, true);
HIViewPlaceInSuperviewAt(mHIView, x, y);
wxWindow *w = wxGetTopLevelParent(this);
wxSize min = w->GetMinSize();
min.x += (rect.size.width - mLastMin.GetWidth());
min.y += (rect.size.height - mLastMin.GetHeight());
w->SetSizeHints(min, min);
mLastMin = wxSize(rect.size.width, rect.size.height);
}
#endif
mSettingSize = false;
return;
}
void VSTControl::CreateCocoa()
{
bool mIsCocoa = (mLink->callDispatcher(effCanDo, 0, 0, (void *) "hasCockosViewAsConfig", 0.0) & 0xffff0000) == 0xbeef0000;
if (!mIsCocoa)
{
return;
}
// Ask the effect to add its GUI
mLink->callDispatcher(effEditOpen, 0, 0, mVSTView, 0.0);
// Get the subview it created
mView = [[mVSTView subviews] objectAtIndex:0];
if (mView == NULL)
{
// Doesn't seem the effect created the subview. This can
// happen when an effect uses the content view directly.
// As of this time, we will not try to support those and
// just fall back to the textual interface.
return;
}
NSNotificationCenter *center = [NSNotificationCenter defaultCenter];
[center addObserver:mVSTView
selector:@selector(cocoaViewResized:)
name:NSViewFrameDidChangeNotification
object:mView];
[mVSTView addSubview:mView];
NSSize viewSize = [mView frame].size;
mLastMin = wxSize(viewSize.width, viewSize.height);
SetMinSize(mLastMin);
[mVSTView setAutoresizingMask:[mView autoresizingMask]];
return;
}
void VSTControl::CocoaViewResized()
{
if (mSettingSize)
{
return;
}
NSSize viewSize = [mView frame].size;
NSSize frameSize = [mVSTView frame].size;
[mVSTView setFrameSize:viewSize];
int diffW = (viewSize.width - frameSize.width);
int diffH = (viewSize.height - frameSize.height);
wxWindow *w = wxGetTopLevelParent(this);
wxSize min = w->GetMinSize();
if ([mView autoresizingMask] == NSViewNotSizable)
{
min.x += (viewSize.width - mLastMin.GetWidth());
min.y += (viewSize.height - mLastMin.GetHeight());
mLastMin = wxSize(viewSize.width, viewSize.height);;
}
else
{
min.x += diffW;
min.y += diffH;
}
w->SetMinSize(min);
wxSize size = w->GetSize();
size.x += diffW;
size.y += diffH;
w->SetSize(size);
}
#if !defined(_LP64)
void VSTControl::CreateCarbon()
{
OSStatus result;
struct
{
short top, left, bottom, right;
} *rect;
// Some effects like to have us get their rect before opening them.
mLink->callDispatcher(effEditGetRect, 0, 0, &rect, 0.0);
// Suggest a dummy size
Rect bounds = { 100, 100, 200, 200 };
// And create the window
result = CreateNewWindow(kOverlayWindowClass,
kWindowStandardHandlerAttribute |
kWindowCompositingAttribute |
kWindowOpaqueForEventsAttribute,
&bounds,
&mWindowRef);
if (result != noErr)
{
return;
}
// Get the root control
ControlRef root = HIViewGetRoot(mWindowRef);
// Find the content view within our window
HIViewRef content;
result = HIViewFindByID(root, kHIViewWindowContentID, &content);
if (result != noErr)
{
DisposeWindow(mWindowRef);
mWindowRef = NULL;
return nil;
}
SetWindowActivationScope(mWindowRef, kWindowActivationScopeIndependent);
// Some effects (iZotope Vinyl) seem to need an existing subview
// of the content view. So just use a "dummy" scrollview.
result = HIScrollViewCreate(kHIScrollViewOptionsVertScroll, &mHIView);
// Don't want to see the scroll bars
HIScrollViewSetScrollBarAutoHide(mHIView, true);
// Add it as a subview of the content view
HIViewAddSubview(content, mHIView);
// Ask the effect to add its GUI
mLink->callDispatcher(effEditOpen, 0, 0, mWindowRef, 0.0);
// Get the subview it created
HIViewRef subview = HIViewGetFirstSubview(content);
if (subview)
{
// The scrollview was used, so it leave it.
if (subview == mHIView)
{
subview = HIViewGetFirstSubview(mHIView);
}
// The effect didn't use our scrollview, so dispose of it.
else
{
HIViewRemoveFromSuperview(mHIView);
CFRelease(mHIView);
mHIView = subview;
}
}
// Doesn't seem the effect created a subview. This can
// happen when an effect uses the content view directly.
// As of this time, we will not try to support those and
// just fall back to the textual interface.
if (subview == NULL)
{
return;
}
// Get the final bounds of the effect GUI
mLink->callDispatcher(effEditGetRect, 0, 0, &rect, 0.0);
// Set the size of the scrollview to match
HIRect r = { 0, 0, rect->right - rect->left, rect->bottom - rect->top };
HIViewSetFrame(mHIView, &r);
// Make sure it can be seen
HIViewSetVisible(mHIView, TRUE);
SetMinSize(wxSize(r.size.width, r.size.height));
mLastMin = GetMinSize();
EventTypeSpec controlEventList[] =
{
{kEventClassControl, kEventControlBoundsChanged},
};
InstallControlEventHandler(mHIView,
ControlEventHandlerCallback,
GetEventTypeCount(controlEventList),
controlEventList,
(void *) this,
NULL);
return;
}
void VSTControl::CreateCarbonOverlay()
{
NSWindow *parent = [mVSTView window];
WindowRef parentRef = (WindowRef)[parent windowRef];
NSWindow *host = [[[NSWindow alloc] initWithWindowRef:mWindowRef] autorelease];
[parent addChildWindow:host ordered:NSWindowAbove];
WindowGroupRef group;
CreateWindowGroup(0, &group);
SetWindowGroupParent(group, GetWindowGroup(parentRef));
ChangeWindowGroupAttributes(group,
kWindowGroupAttrLayerTogether |
kWindowGroupAttrSharedActivation |
kWindowGroupAttrHideOnCollapse,
0);
SetWindowGroup(parentRef, group);
SetWindowGroup(mWindowRef, group);
Rect location;
GetWindowBounds(parentRef, kWindowContentRgn, &location);
MoveWindow(mWindowRef, location.left, location.top, true);
ShowWindow(mWindowRef);
}
pascal OSStatus
VSTControl::ControlEventHandlerCallback(EventHandlerCallRef handler, EventRef event, void *data)
{
((VSTControl *) data)->CarbonViewResized();
return eventNotHandledErr;
}
void VSTControl::CarbonViewResized()
{
if (mSettingSize)
{
return;
}
// resize and move window
HIRect rect;
HIViewGetFrame(mHIView, &rect);
HIViewPlaceInSuperviewAt(mHIView, 0, 0);
SizeWindow(mWindowRef, rect.size.width, rect.size.height, true);
NSSize frameSize = [mVSTView frame].size;
[mVSTView setFrameSize:NSMakeSize(rect.size.width, rect.size.height)];
wxWindow *w = wxGetTopLevelParent(this);
wxSize size = w->GetSize();
size.x += (rect.size.width - frameSize.width);
size.y += (rect.size.height - frameSize.height);
// Reset the current max/min
w->SetSizeHints(wxDefaultSize, wxDefaultSize);
// Set the dialog size
w->SetSize(size);
// And finally set the new max/min
w->SetSizeHints(size, size);
mLastMin = wxSize(rect.size.width, rect.size.height);
}
#endif

View File

@ -38,6 +38,7 @@
#include <limits.h>
#include <stdio.h>
#include <dlfcn.h>
#include <wx/app.h>
#include <wx/defs.h>
@ -68,18 +69,6 @@
#include <wx/tokenzr.h>
#include <wx/utils.h>
#if defined(__WXMAC__)
#include <dlfcn.h>
#include <wx/osx/core/private.h>
#elif defined(__WXMSW__)
#include <wx/dynlib.h>
#include <wx/msw/seh.h>
#include <shlwapi.h>
#pragma comment(lib, "shlwapi")
#else
// Includes for GTK are later since they cause conflicts with our class names
#endif
// TODO: Unfortunately we have some dependencies on Audacity provided
// dialogs, widgets and other stuff. This will need to be cleaned up.
@ -96,15 +85,6 @@
#include "audacity/ConfigInterface.h"
// Must include after ours since we have a lot of name collisions
#if defined(__WXGTK__)
#include <dlfcn.h>
#define Region XRegion // Conflicts with Audacity's Region structure
#include <gtk/gtk.h>
#include <gdk/gdkx.h>
#undef Region
#endif
#include "VSTEffect.h"
// NOTE: To debug the subprocess, use wxLogDebug and, on Windows, Debugview
@ -898,421 +878,6 @@ BEGIN_EVENT_TABLE(VSTEffect, wxEvtHandler)
EVT_COMMAND(wxID_ANY, EVT_SIZEWINDOW, VSTEffect::OnSizeWindow)
END_EVENT_TABLE()
#if defined(__WXMAC__)
// To use, change the SDK in the project to at least 10.5
extern void DebugPrintControlHierarchy(WindowRef inWindow);
extern void DebugPrintWindowList(void);
// Event handler to track when the mouse enters/exits the various view
static const EventTypeSpec trackingEventList[] =
{
{kEventClassControl, kEventControlTrackingAreaEntered},
{kEventClassControl, kEventControlTrackingAreaExited},
};
pascal OSStatus VSTEffect::TrackingEventHandler(EventHandlerCallRef handler, EventRef event, void *data)
{
return ((VSTEffect *)data)->OnTrackingEvent(event);
}
OSStatus VSTEffect::OnTrackingEvent(EventRef event)
{
OSStatus result = eventNotHandledErr;
if (GetEventKind(event) == kEventControlTrackingAreaEntered)
{
// Should we save the existing cursor???
SetThemeCursor(kThemeArrowCursor);
}
if (GetEventKind(event) == kEventControlTrackingAreaExited)
{
// Possibly restore a saved cursor
}
return result;
}
// ----------------------------------------------------------------------------
// Most of the following is used to deal with VST effects that create an overlay
// window on top of ours. This is usually done because Cocoa is being used
// instead of Carbon.
//
// That works just fine...usually. But, we display the effect in a modal dialog
// box and, since that overlay window is just another window in the application,
// the modality of the dialog causes the overlay to be disabled and the user
// can't interact with the effect.
//
// Examples of these effects would be BlueCat's Freeware Pack and GRM Tools,
// though I'm certain there are other's out there. Anything JUCE based would
// affected...that's what GRM Tools uses.
//
// So, to work around the problem (without moving to Cocoa or wxWidgets 3.x),
// we install an event handler if the overlay is detected. This handler and
// the companion handler on our window use the kEventWindowGetClickModality
// event to tell the system that events can be passed to our window and the
// overlay window.
//
// In addition, there's some window state management that must be dealt with
// to keep our window from becoming unhightlighted when the floater is clicked.
// ----------------------------------------------------------------------------
// Events to be captured in the overlay window
static const EventTypeSpec OverlayEventList[] =
{
#if 0
{ kEventClassMouse, kEventMouseDown },
{ kEventClassMouse, kEventMouseUp },
{ kEventClassMouse, kEventMouseMoved },
{ kEventClassMouse, kEventMouseDragged },
{ kEventClassMouse, kEventMouseEntered },
{ kEventClassMouse, kEventMouseExited },
{ kEventClassMouse, kEventMouseWheelMoved },
#endif
};
// Overlay window event handler callback thunk
pascal OSStatus VSTEffect::OverlayEventHandler(EventHandlerCallRef handler, EventRef event, void *data)
{
return ((VSTEffect *)data)->OnOverlayEvent(handler, event);
}
// Overlay window event handler
OSStatus VSTEffect::OnOverlayEvent(EventHandlerCallRef handler, EventRef event)
{
// Get the current window in front of all the rest of the non-floaters.
WindowRef frontwin = FrontNonFloatingWindow();
// Get the target window of the event
WindowRef evtwin = 0;
GetEventParameter(event,
kEventParamDirectObject,
typeWindowRef,
NULL,
sizeof(evtwin),
NULL,
&evtwin);
#if defined(DEBUG_VST)
int cls = GetEventClass(event);
printf("OVERLAY class %4.4s kind %d ewin %p owin %p mwin %p anf %p fnf %p\n",
&cls,
GetEventKind(event),
evtwin,
mOverlayRef,
mWindowRef,
ActiveNonFloatingWindow(),
frontwin);
#endif
bool block = false;
WindowModality kind;
WindowRef ref = NULL;
GetWindowModality(frontwin, &kind, &ref);
switch (kind)
{
case kWindowModalityNone:
{
// Allow
}
break;
case kWindowModalityWindowModal:
{
if (ref == mWindowRef || ref == mOverlayRef)
{
block = true;
}
}
break;
case kWindowModalitySystemModal:
case kWindowModalityAppModal:
{
if (frontwin != mWindowRef && frontwin != mOverlayRef)
{
block = true;
}
}
break;
}
// We must block mouse events because plugins still act on mouse
// movement and drag events, even if they are supposed to be disabled
// due to other modal dialogs (like when Load or Settings are clicked).
if (GetEventClass(event) == kEventClassMouse)
{
if (block)
{
return noErr;
}
return eventNotHandledErr;
}
// Only kEventClassWindow events at this point
switch (GetEventKind(event))
{
// The system is asking if the target of an upcoming event
// should be passed to the overlay window or not.
//
// We allow it when the overlay window or our window is the
// curret top window. Any other windows would mean that a
// modal dialog box has been opened on top and we should block.
case kEventWindowGetClickModality:
{
// Announce the event may need blocking
HIModalClickResult res = block ? kHIModalClickIsModal | kHIModalClickAnnounce : 0;
// Set the return parameters
SetEventParameter(event,
kEventParamWindowModality,
typeWindowRef,
sizeof(kind),
&kind);
SetEventParameter(event,
kEventParamModalWindow,
typeWindowRef,
sizeof(ref),
&ref);
SetEventParameter(event,
kEventParamModalClickResult,
typeModalClickResult,
sizeof(res),
&res);
return noErr;
}
break;
}
return eventNotHandledErr;
}
// Events to be captured in the our window
static const EventTypeSpec WindowEventList[] =
{
{ kEventClassWindow, kEventWindowGetClickModality },
{ kEventClassWindow, kEventWindowShown },
{ kEventClassWindow, kEventWindowClose },
#if 0
{ kEventClassMouse, kEventMouseDown },
{ kEventClassMouse, kEventMouseUp },
{ kEventClassMouse, kEventMouseMoved },
{ kEventClassMouse, kEventMouseDragged },
{ kEventClassMouse, kEventMouseEntered },
{ kEventClassMouse, kEventMouseExited },
{ kEventClassMouse, kEventMouseWheelMoved },
#endif
};
// Our window event handler callback thunk
pascal OSStatus VSTEffect::WindowEventHandler(EventHandlerCallRef handler, EventRef event, void *data)
{
return ((VSTEffect *)data)->OnWindowEvent(handler, event);
}
// Our window event handler
OSStatus VSTEffect::OnWindowEvent(EventHandlerCallRef handler, EventRef event)
{
// Get the current window in from of all the rest non-floaters.
WindowRef frontwin = FrontNonFloatingWindow();
// Get the target window of the event
WindowRef evtwin = 0;
GetEventParameter(event,
kEventParamDirectObject,
typeWindowRef,
NULL,
sizeof(evtwin),
NULL,
&evtwin);
#if defined(DEBUG_VST)
int cls = GetEventClass(event);
printf("WINDOW class %4.4s kind %d ewin %p owin %p mwin %p anf %p fnf %p\n",
&cls,
GetEventKind(event),
evtwin,
mOverlayRef,
mWindowRef,
ActiveNonFloatingWindow(),
frontwin);
#endif
bool block = false;
WindowModality kind;
WindowRef ref = NULL;
GetWindowModality(frontwin, &kind, &ref);
switch (kind)
{
case kWindowModalityNone:
{
// Allow
}
break;
case kWindowModalityWindowModal:
{
if (ref == mWindowRef || ref == mOverlayRef)
{
block = true;
}
}
break;
case kWindowModalitySystemModal:
case kWindowModalityAppModal:
{
if (frontwin != mWindowRef && frontwin != mOverlayRef)
{
block = true;
}
}
break;
}
// We must block mouse events because plugins still act on mouse
// movement and drag events, even if they are supposed to be disabled
// due to other modal dialogs (like when Load or Settings are clicked).
if (GetEventClass(event) == kEventClassMouse)
{
if (block)
{
return noErr;
}
return eventNotHandledErr;
}
// Only kEventClassWindow events at this point
switch (GetEventKind(event))
{
// If we don't capture the close event, Audacity will crash at termination
// since the window is still on the wxWidgets toplevel window lists, but
// it has already been deleted from the system.
case kEventWindowClose:
{
RemoveHandler();
mDialog->Close();
return noErr;
}
break;
// This is where we determine if the effect has created a window above
// ours. Since the overlay is created on top of our window, we look at
// the topmost window to see if it is different that ours. If so, then
// we assume an overlay has been created and install the event handler
// on the overlay.
case kEventWindowShown:
{
// Have an overlay?
WindowRef newprev = GetPreviousWindow(mWindowRef);
if (newprev != mPreviousRef)
{
// We have an overlay
mOverlayRef = newprev;
// Set our window's activatino scope to make sure it alway
// stays active.
SetWindowActivationScope(mWindowRef,
kWindowActivationScopeIndependent);
// Install the overlay handler
mOverlayEventHandlerUPP = NewEventHandlerUPP(OverlayEventHandler);
InstallWindowEventHandler(mOverlayRef,
mOverlayEventHandlerUPP,
GetEventTypeCount(OverlayEventList),
OverlayEventList,
this,
&mOverlayEventHandlerRef);
ControlRef root = HIViewGetRoot(mOverlayRef);
HIViewRef view;
HIViewFindByID(root, kHIViewWindowContentID, &view);
InstallControlEventHandler(root,
mTrackingHandlerUPP,
GetEventTypeCount(trackingEventList),
trackingEventList,
this,
&mOverlayRootTrackingHandlerRef);
InstallControlEventHandler(view,
mTrackingHandlerUPP,
GetEventTypeCount(trackingEventList),
trackingEventList,
this,
&mOverlayViewTrackingHandlerRef);
HIViewNewTrackingArea(root, NULL, 0, NULL);
HIViewNewTrackingArea(view, NULL, 0, NULL);
}
}
break;
// The system is asking if the target of an upcoming event
// should be passed to the overlay window or not.
//
// We allow it when the overlay window or our window is the
// curret top window. Any other windows would mean that a
// modal dialog box has been opened on top and we should block.
case kEventWindowGetClickModality:
{
// Announce the event may need blocking
HIModalClickResult res = block ? kHIModalClickIsModal | kHIModalClickAnnounce : 0;
// Set the return parameters
SetEventParameter(event,
kEventParamWindowModality,
typeWindowRef,
sizeof(kind),
&kind);
SetEventParameter(event,
kEventParamModalWindow,
typeWindowRef,
sizeof(ref),
&ref);
SetEventParameter(event,
kEventParamModalClickResult,
typeModalClickResult,
sizeof(res),
&res);
if (mOverlayRef)
{
// If the front window is the overlay, then make our window
// the selected one so that the mouse click go to it instead.
WindowRef act = ActiveNonFloatingWindow();
if (frontwin == mOverlayRef || act == NULL || act == mOverlayRef)
{
SelectWindow(mWindowRef);
}
}
return noErr;
}
break;
}
return eventNotHandledErr;
}
#endif
#if defined(__WXGTK__)
static int trappedErrorCode = 0;
static int X11TrapHandler(Display *, XErrorEvent *err)
{
return 0;
}
#endif
// Needed to support shell plugins...sucks, but whatcha gonna do???
intptr_t VSTEffect::mCurrentEffectID;
@ -1529,28 +1094,6 @@ VSTEffect::VSTEffect(const wxString & path, VSTEffect *master)
mLabels = NULL;
mContainer = NULL;
#if defined(__WXMAC__)
mOverlayRef = 0;
mOverlayEventHandlerUPP = 0;
mOverlayEventHandlerRef = 0;
mWindowRef = 0;
mWindowEventHandlerUPP = 0;
mWindowEventHandlerRef = 0;
mRootTrackingHandlerRef = 0;
mViewTrackingHandlerRef = 0;
mSubviewTrackingHandlerRef = 0;
mOverlayRootTrackingHandlerRef = 0;
mOverlayViewTrackingHandlerRef = 0;
#elif defined(__WXMSW__)
mHwnd = 0;
#else
mXdisp = 0;
mXwin = 0;
#endif
// If we're a slave then go ahead a load immediately
if (mMaster)
{
@ -2443,7 +1986,7 @@ bool VSTEffect::Load()
mResource = -1;
// Convert the path to a CFSTring
wxMacCFStringHolder path(realPath);
wxCFStringRef path(realPath);
// Convert the path to a URL
CFURLRef urlRef =
@ -3243,239 +2786,57 @@ int VSTEffect::b64decode(wxString in, void *out)
void VSTEffect::RemoveHandler()
{
#if defined(__WXMAC__)
if (mWindowRef)
{
callDispatcher(effEditClose, 0, 0, mWindowRef, 0.0);
mWindowRef = 0;
}
if (mOverlayViewTrackingHandlerRef)
{
::RemoveEventHandler(mOverlayViewTrackingHandlerRef);
mOverlayViewTrackingHandlerRef = 0;
}
if (mOverlayRootTrackingHandlerRef)
{
::RemoveEventHandler(mOverlayRootTrackingHandlerRef);
mOverlayRootTrackingHandlerRef = 0;
}
if (mOverlayEventHandlerRef)
{
::RemoveEventHandler(mOverlayEventHandlerRef);
mOverlayEventHandlerRef = 0;
}
if (mOverlayEventHandlerUPP)
{
DisposeEventHandlerUPP(mOverlayEventHandlerUPP);
mOverlayEventHandlerUPP = 0;
}
if (mSubviewTrackingHandlerRef)
{
::RemoveEventHandler(mSubviewTrackingHandlerRef);
mSubviewTrackingHandlerRef = 0;
}
if (mViewTrackingHandlerRef)
{
::RemoveEventHandler(mViewTrackingHandlerRef);
mViewTrackingHandlerRef = 0;
}
if (mRootTrackingHandlerRef)
{
::RemoveEventHandler(mRootTrackingHandlerRef);
mRootTrackingHandlerRef = 0;
}
if (mTrackingHandlerUPP)
{
DisposeEventHandlerUPP(mTrackingHandlerUPP);
mTrackingHandlerUPP = 0;
}
if (mWindowEventHandlerRef)
{
::RemoveEventHandler(mWindowEventHandlerRef);
mWindowEventHandlerRef = 0;
mDialog->MacInstallTopLevelWindowEventHandler();
}
if (mWindowEventHandlerUPP)
{
DisposeEventHandlerUPP(mWindowEventHandlerUPP);
mWindowEventHandlerUPP = 0;
}
#elif defined(__WXMSW__)
if (mHwnd)
{
callDispatcher(effEditClose, 0, 0, mHwnd, 0.0);
mHwnd = 0;
}
#else
if (mXwin)
{
callDispatcher(effEditClose, 0, (intptr_t)mXdisp, (void *)mXwin, 0.0);
mXdisp = 0;
mXwin = 0;
}
#endif
}
void VSTEffect::BuildFancy()
{
struct
{
short top, left, bottom, right;
} *rect;
// Turn the power on...some effects need this when the editor is open
PowerOn();
// Some effects like to have us get their rect before opening them.
callDispatcher(effEditGetRect, 0, 0, &rect, 0.0);
OSStatus result;
#if defined(__WXMAC__)
// Retrieve the current window and the one above it. The window list
// is kept in top-most to bottom-most order, so we'll use that to
// determine if another window was opened above ours.
mWindowRef = (WindowRef) mDialog->MacGetWindowRef();
mPreviousRef = GetPreviousWindow(mWindowRef);
wxBoxSizer *mainSizer = new wxBoxSizer(wxVERTICAL);
// Install the event handler on our window
mWindowEventHandlerUPP = NewEventHandlerUPP(WindowEventHandler);
InstallWindowEventHandler(mWindowRef,
mWindowEventHandlerUPP,
GetEventTypeCount(WindowEventList),
WindowEventList,
this,
&mWindowEventHandlerRef);
wxPanel *container = new wxPanel(mParent, wxID_ANY);
mainSizer->Add(container, 1, wxEXPAND);
// Find the content view within our window
ControlRef root = HIViewGetRoot(mWindowRef);
HIViewRef view;
HIViewFindByID(root, kHIViewWindowContentID, &view);
mParent->SetSizer(mainSizer);
// And ask the effect to add it's GUI
callDispatcher(effEditOpen, 0, 0, mWindowRef, 0.0);
// Get the subview it created
HIViewRef subview = HIViewGetFirstSubview(view);
if (subview == NULL)
#if 0
if (mUIType == wxT("Plain"))
{
// Doesn't seem the effect created the subview, so switch
// to the plain dialog. This can happen when an effect
// uses the content view directly. As of this time, we
// will not try to support those and fall back to the
// textual interface.
mGui = false;
RemoveHandler();
BuildPlain();
return;
if (!CreatePlain(mParent))
{
return false;
}
}
// Install the tracking event handler on our views
mTrackingHandlerUPP = NewEventHandlerUPP(VSTEffect::TrackingEventHandler);
InstallControlEventHandler(root,
mTrackingHandlerUPP,
GetEventTypeCount(trackingEventList),
trackingEventList,
this,
&mRootTrackingHandlerRef);
InstallControlEventHandler(view,
mTrackingHandlerUPP,
GetEventTypeCount(trackingEventList),
trackingEventList,
this,
&mViewTrackingHandlerRef);
InstallControlEventHandler(subview,
mTrackingHandlerUPP,
GetEventTypeCount(trackingEventList),
trackingEventList,
this,
&mSubviewTrackingHandlerRef);
HIViewNewTrackingArea(root, NULL, 0, NULL);
HIViewNewTrackingArea(view, NULL, 0, NULL);
HIViewNewTrackingArea(subview, NULL, 0, NULL);
#elif defined(__WXMSW__)
// Use a panel to host the plugins GUI
wxPanel *w = new wxPanel(mParent, wxID_ANY);
mHwnd = w->GetHWND();
callDispatcher(effEditOpen, 0, 0, mHwnd, 0.0);
#else
// Use a panel to host the plugins GUI
wxPanel *w = new wxPanel(mParent, wxID_ANY);
// Make sure the parent has a window
if (!gtk_widget_get_realized(GTK_WIDGET(w->m_wxwindow)))
else
#endif
{
gtk_widget_realize(GTK_WIDGET(w->m_wxwindow));
mControl = new VSTControl;
if (!mControl)
{
return;
}
if (!mControl->Create(mParent, this))
{
return;
}
wxBoxSizer *innerSizer = new wxBoxSizer(wxVERTICAL);
innerSizer->Add(mControl, 1, wxEXPAND);
container->SetSizer(innerSizer);
mParent->SetMinSize(wxDefaultSize);
}
GdkWindow *gwin = gtk_widget_get_window(GTK_WIDGET(w->m_wxwindow));
mXdisp = GDK_WINDOW_XDISPLAY(gwin);
mXwin = GDK_WINDOW_XID(gwin);
callDispatcher(effEditOpen, 0, (intptr_t)mXdisp, (void *)mXwin, 0.0);
#endif
// Get the final bounds of the effect GUI
callDispatcher(effEditGetRect, 0, 0, &rect, 0.0);
// Build our display now
wxBoxSizer *vs = new wxBoxSizer(wxVERTICAL);
wxBoxSizer *hs = new wxBoxSizer(wxHORIZONTAL);
#if defined(__WXMAC__)
// Reserve space for the effect GUI
mContainer = hs->Add(rect->right - rect->left, rect->bottom - rect->top);
#elif defined(__WXMSW__)
// Add the effect host window to the layout
mContainer = hs->Add(w, 1, wxCENTER | wxEXPAND);
mContainer->SetMinSize(rect->right - rect->left, rect->bottom - rect->top);
#else
// Add the effect host window to the layout
mContainer = hs->Add(w, 1, wxCENTER | wxEXPAND);
mContainer->SetMinSize(rect->right - rect->left, rect->bottom - rect->top);
#endif
vs->Add(hs, 0, wxCENTER);
mParent->SetSizerAndFit(vs);
#if defined(__WXMAC__)
// Found out where the reserved space wound up
wxPoint pos = mContainer->GetPosition();
// Reposition the subview into the reserved space
HIViewPlaceInSuperviewAt(subview, pos.x, pos.y);
// Some VST effects do not work unless the default handler is removed since
// it captures many of the events that the plugins need. But, it must be
// done last since proper window sizing will not occur otherwise.
::RemoveEventHandler((EventHandlerRef) mDialog->MacGetEventHandler());
#elif defined(__WXMSW__)
#else
#endif
NeedEditIdle(true);
// mParent->PushEventHandler(this);
return;
}
void VSTEffect::BuildPlain()

View File

@ -18,7 +18,7 @@
#include "../../widgets/NumericTextCtrl.h"
#include "aeffectx.h"
#include "VSTControl.h"
#define VSTCMDKEY wxT("-checkvst")
#define VSTPLUGINTYPE wxT("VST")
@ -64,7 +64,8 @@ DECLARE_LOCAL_EVENT_TYPE(EVT_UPDATEDISPLAY, -1);
class VSTEffect : public wxEvtHandler,
public EffectClientInterface,
public EffectUIClientInterface,
public XMLTagHandler
public XMLTagHandler,
public VSTEffectLink
{
public:
VSTEffect(const wxString & path, VSTEffect *master = NULL);
@ -301,6 +302,8 @@ private:
wxSizerItem *mContainer;
bool mGui;
VSTControl *mControl;
NumericTextCtrl *mDuration;
wxStaticText **mNames;
wxSlider **mSliders;

View File

@ -18,9 +18,7 @@
#include <wx/osx/private.h>
#include <wx/control.h>
//#include <AudioUnit/AudioUnit.h>
#include <AudioUnit/AudioComponent.h>
//#include <AudioUnit/AudioUnitProperties.h>
class AUControlImpl : public wxWidgetCocoaImpl
{

View File

@ -107,9 +107,6 @@ AUControl::AUControl()
AUControl::~AUControl()
{
#if !defined(_LP64)
if (mHIView)
{
}
if (mInstance)
{
@ -117,6 +114,7 @@ AUControl::~AUControl()
}
#endif
if (mView)
{
NSNotificationCenter *center = [NSNotificationCenter defaultCenter];
@ -242,8 +240,8 @@ void AUControl::OnSize(wxSizeEvent & evt)
wxSize min = w->GetMinSize();
min.x += (rect.size.width - mLastMin.GetWidth());
min.y += (rect.size.height - mLastMin.GetHeight());
w->SetMinSize(min);
w->SetMaxSize(min);
w->SetSizeHints(min, min);
mLastMin = wxSize(rect.size.width, rect.size.height);
}
@ -537,7 +535,7 @@ void AUControl::CreateCarbon()
AudioComponentInstanceDispose(mInstance);
mInstance = NULL;
return nil;
return;
}
SetWindowActivationScope(mWindowRef, kWindowActivationScopeIndependent);
@ -647,12 +645,16 @@ void AUControl::CarbonViewResized()
size.x += (rect.size.width - frameSize.width);
size.y += (rect.size.height - frameSize.height);
w->SetMinSize(wxDefaultSize);
w->SetMaxSize(wxDefaultSize);
// Reset the current max/min
w->SetSizeHints(wxDefaultSize, wxDefaultSize);
// Set the dialog size
w->SetSize(size);
w->SetMinSize(size);
w->SetMaxSize(size);
mLastMin = size;
// And finally set the new max/min
w->SetSizeHints(size, size);
mLastMin = wxSize(rect.size.width, rect.size.height);
}
#endif

View File

@ -36,7 +36,7 @@ TracksPrefs::TracksPrefs(wxWindow * parent)
// Bugs 1043, 1044
// First rewrite legacy preferences
gPrefs->Write(wxT("/GUI/DefaultViewModeNew"),
WaveTrack::FindDefaultViewMode());
(int) WaveTrack::FindDefaultViewMode());
Populate();
}