diff --git a/mac/Audacity.xcodeproj/project.pbxproj b/mac/Audacity.xcodeproj/project.pbxproj index dd6756f09..6360cea2c 100644 --- a/mac/Audacity.xcodeproj/project.pbxproj +++ b/mac/Audacity.xcodeproj/project.pbxproj @@ -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 = ""; tabWidth = 3; }; 1790B01709883BFD008A330A /* Echo.cpp */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 3; lastKnownFileType = sourcecode.cpp.cpp; path = Echo.cpp; sourceTree = ""; tabWidth = 3; }; 1790B01809883BFD008A330A /* Echo.h */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 3; lastKnownFileType = sourcecode.c.h; path = Echo.h; sourceTree = ""; tabWidth = 3; }; - 1790B01909883BFD008A330A /* Effect.cpp */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 3; lastKnownFileType = sourcecode.cpp.cpp; path = Effect.cpp; sourceTree = ""; tabWidth = 3; }; + 1790B01909883BFD008A330A /* Effect.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.objcpp; fileEncoding = 30; indentWidth = 3; path = Effect.cpp; sourceTree = ""; tabWidth = 3; }; 1790B01A09883BFD008A330A /* Effect.h */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 3; lastKnownFileType = sourcecode.c.h; path = Effect.h; sourceTree = ""; tabWidth = 3; }; 1790B01B09883BFD008A330A /* Equalization.cpp */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 3; lastKnownFileType = sourcecode.cpp.cpp; path = Equalization.cpp; sourceTree = ""; tabWidth = 3; }; 1790B01C09883BFD008A330A /* Equalization.h */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 3; lastKnownFileType = sourcecode.c.h; path = Equalization.h; sourceTree = ""; tabWidth = 3; }; @@ -2607,6 +2608,9 @@ 2897F6EF0AB3DB5A003C20C5 /* TranscriptionToolBar.h */ = {isa = PBXFileReference; fileEncoding = 5; indentWidth = 3; lastKnownFileType = sourcecode.c.h; path = TranscriptionToolBar.h; sourceTree = ""; tabWidth = 3; }; 2897F6FC0AB3DCD0003C20C5 /* Grabber.cpp */ = {isa = PBXFileReference; fileEncoding = 5; indentWidth = 3; lastKnownFileType = sourcecode.cpp.cpp; path = Grabber.cpp; sourceTree = ""; tabWidth = 3; }; 2897F6FD0AB3DCD0003C20C5 /* Grabber.h */ = {isa = PBXFileReference; fileEncoding = 5; indentWidth = 3; lastKnownFileType = sourcecode.c.h; path = Grabber.h; sourceTree = ""; tabWidth = 3; }; + 289D12771B44D57F00B5B6AA /* VSTControl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = VSTControl.h; path = VST/VSTControl.h; sourceTree = ""; }; + 289D12781B44D57F00B5B6AA /* VSTControlMac.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = VSTControlMac.h; path = VST/VSTControlMac.h; sourceTree = ""; }; + 289D12791B44D57F00B5B6AA /* VSTControlMac.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = VSTControlMac.mm; path = VST/VSTControlMac.mm; sourceTree = ""; }; 289E75081006D0BD00CEF79B /* MixerBoard.cpp */ = {isa = PBXFileReference; fileEncoding = 5; indentWidth = 3; lastKnownFileType = sourcecode.cpp.cpp; path = MixerBoard.cpp; sourceTree = ""; tabWidth = 3; }; 289E75091006D0BD00CEF79B /* MixerBoard.h */ = {isa = PBXFileReference; fileEncoding = 5; indentWidth = 3; lastKnownFileType = sourcecode.c.h; path = MixerBoard.h; sourceTree = ""; tabWidth = 3; }; 289F9C7C0AC671BB00797DC1 /* DeviceToolBar.cpp */ = {isa = PBXFileReference; fileEncoding = 5; indentWidth = 3; lastKnownFileType = sourcecode.cpp.cpp; path = DeviceToolBar.cpp; sourceTree = ""; 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 = ""; @@ -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 */, diff --git a/mac/Info.plist b/mac/Info.plist index 35c03b8da..0716895f1 100644 --- a/mac/Info.plist +++ b/mac/Info.plist @@ -226,9 +226,9 @@ Version AUDACITY_VERSION.AUDACITY_RELEASE.AUDACITY_REVISION.AUDACITY_MODLEVEL NSHumanReadableCopyright Audacity version AUDACITY_VERSION.AUDACITY_RELEASE.AUDACITY_REVISION.AUDACITY_MODLEVEL - LSRequiresCarbon - - CSResourcesFileMapped + NSHighResolutionCapable + NSPrincipalClass + NSApplication diff --git a/mac/config/i386/src/configunix.h b/mac/config/i386/src/configunix.h index 8da46d89a..2afa6107e 100644 --- a/mac/config/i386/src/configunix.h +++ b/mac/config/i386/src/configunix.h @@ -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" diff --git a/src/effects/Effect.cpp b/src/effects/Effect.cpp index a82b7cd71..7377e60cd 100644 --- a/src/effects/Effect.cpp +++ b/src/effects/Effect.cpp @@ -49,6 +49,10 @@ greater use in future. #include "TimeWarper.h" #include "nyquist/Nyquist.h" +#if defined(__WXMAC__) +#include +#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); diff --git a/src/effects/VST/VSTControl.h b/src/effects/VST/VSTControl.h index 35b60e11b..6763bb03c 100644 --- a/src/effects/VST/VSTControl.h +++ b/src/effects/VST/VSTControl.h @@ -8,66 +8,57 @@ **********************************************************************/ -#ifndef AUDACITY_AUCONTROL_H -#define AUDACITY_AUCONTROL_H +#ifndef AUDACITY_VSTCONTROL_H +#define AUDACITY_VSTCONTROL_H -#if !defined(_LP64) -#include -#endif - -#include #include -//#include -#include -//#include +#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 diff --git a/src/effects/VST/VSTControl.mm b/src/effects/VST/VSTControl.mm deleted file mode 100644 index 19f485692..000000000 --- a/src/effects/VST/VSTControl.mm +++ /dev/null @@ -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 -#include -#include -#include -#include - -#if !defined(_LP64) -#include -#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 diff --git a/src/effects/VST/VSTControlMac.h b/src/effects/VST/VSTControlMac.h new file mode 100644 index 000000000..d1ed795d4 --- /dev/null +++ b/src/effects/VST/VSTControlMac.h @@ -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 +#endif + +#include + +#include + +#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 diff --git a/src/effects/VST/VSTControlMac.mm b/src/effects/VST/VSTControlMac.mm new file mode 100644 index 000000000..572e05b8e --- /dev/null +++ b/src/effects/VST/VSTControlMac.mm @@ -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 diff --git a/src/effects/VST/VSTEffect.cpp b/src/effects/VST/VSTEffect.cpp index a948ca53a..3888f299a 100644 --- a/src/effects/VST/VSTEffect.cpp +++ b/src/effects/VST/VSTEffect.cpp @@ -38,6 +38,7 @@ #include #include +#include #include #include @@ -68,18 +69,6 @@ #include #include -#if defined(__WXMAC__) -#include -#include -#elif defined(__WXMSW__) -#include -#include -#include -#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 -#define Region XRegion // Conflicts with Audacity's Region structure -#include -#include -#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() diff --git a/src/effects/VST/VSTEffect.h b/src/effects/VST/VSTEffect.h index 48596ca11..58a050115 100644 --- a/src/effects/VST/VSTEffect.h +++ b/src/effects/VST/VSTEffect.h @@ -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; diff --git a/src/effects/audiounits/AUControl.h b/src/effects/audiounits/AUControl.h index 810741713..061f01258 100644 --- a/src/effects/audiounits/AUControl.h +++ b/src/effects/audiounits/AUControl.h @@ -18,9 +18,7 @@ #include #include -//#include #include -//#include class AUControlImpl : public wxWidgetCocoaImpl { diff --git a/src/effects/audiounits/AUControl.mm b/src/effects/audiounits/AUControl.mm index abf4da64c..929631813 100644 --- a/src/effects/audiounits/AUControl.mm +++ b/src/effects/audiounits/AUControl.mm @@ -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 diff --git a/src/prefs/TracksPrefs.cpp b/src/prefs/TracksPrefs.cpp index 37ec58fb3..f8d582d1e 100644 --- a/src/prefs/TracksPrefs.cpp +++ b/src/prefs/TracksPrefs.cpp @@ -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(); }