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:
parent
a9184af222
commit
b8872a4a02
@ -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 */,
|
||||
|
@ -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>
|
||||
|
@ -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"
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
71
src/effects/VST/VSTControlMac.h
Normal file
71
src/effects/VST/VSTControlMac.h
Normal 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
|
476
src/effects/VST/VSTControlMac.mm
Normal file
476
src/effects/VST/VSTControlMac.mm
Normal 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
|
@ -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()
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
{
|
||||
|
@ -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
|
||||
|
@ -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();
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user