mirror of
https://github.com/cookiengineer/audacity
synced 2025-11-08 14:13:57 +01:00
Updates for wx3
A long way to go yet, but many OSX issues fixed including conversion of Audio Unit effects.
This commit is contained in:
73
src/effects/audiounits/AUControl.h
Normal file
73
src/effects/audiounits/AUControl.h
Normal file
@@ -0,0 +1,73 @@
|
||||
/**********************************************************************
|
||||
|
||||
Audacity: A Digital Audio Editor
|
||||
|
||||
AUControl.h
|
||||
|
||||
Leland Lucius
|
||||
|
||||
**********************************************************************/
|
||||
|
||||
#ifndef AUDACITY_AUCONTROL_H
|
||||
#define AUDACITY_AUCONTROL_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>
|
||||
|
||||
class AUControlImpl : public wxWidgetCocoaImpl
|
||||
{
|
||||
public :
|
||||
AUControlImpl(wxWindowMac *peer, NSView *view);
|
||||
~AUControlImpl();
|
||||
};
|
||||
|
||||
class AUControl : public wxControl
|
||||
{
|
||||
public:
|
||||
AUControl();
|
||||
~AUControl();
|
||||
|
||||
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();
|
||||
};
|
||||
|
||||
#endif
|
||||
658
src/effects/audiounits/AUControl.mm
Normal file
658
src/effects/audiounits/AUControl.mm
Normal file
@@ -0,0 +1,658 @@
|
||||
/**********************************************************************
|
||||
|
||||
Audacity: A Digital Audio Editor
|
||||
|
||||
AUControl.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 "AUControl.h"
|
||||
|
||||
@interface AUView : NSView
|
||||
{
|
||||
AUControl *mControl;
|
||||
}
|
||||
@end
|
||||
|
||||
@implementation AUView
|
||||
|
||||
+ (void)initialize
|
||||
{
|
||||
static BOOL initialized = NO;
|
||||
if (!initialized)
|
||||
{
|
||||
initialized = YES;
|
||||
wxOSXCocoaClassAddWXMethods(self);
|
||||
}
|
||||
}
|
||||
|
||||
- (instancetype)initWithControl:(AUControl *)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
|
||||
|
||||
AUControlImpl::AUControlImpl(wxWindowMac *peer, NSView *view)
|
||||
: wxWidgetCocoaImpl(peer, view, false, false)
|
||||
{
|
||||
}
|
||||
|
||||
AUControlImpl::~AUControlImpl()
|
||||
{
|
||||
}
|
||||
|
||||
BEGIN_EVENT_TABLE(AUControl, wxControl)
|
||||
EVT_SIZE(AUControl::OnSize)
|
||||
END_EVENT_TABLE()
|
||||
|
||||
AUControl::AUControl()
|
||||
{
|
||||
mComponent = NULL;
|
||||
mUnit = NULL;
|
||||
|
||||
mAUView = nil;
|
||||
mView = nil;
|
||||
|
||||
mSettingSize = false;
|
||||
|
||||
#if !defined(_LP64)
|
||||
mHIView = NULL;
|
||||
mWindowRef = NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
AUControl::~AUControl()
|
||||
{
|
||||
#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 AUControl::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 AUControlImpl(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 AUControl::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 AUControl::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 AUControl::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 AUControl::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 AUControl::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 AUControl::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
|
||||
AUControl::ControlEventHandlerCallback(EventHandlerCallRef handler, EventRef event, void *data)
|
||||
{
|
||||
((AUControl *) data)->CarbonViewResized();
|
||||
|
||||
return eventNotHandledErr;
|
||||
}
|
||||
|
||||
void AUControl::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
|
||||
@@ -1,29 +0,0 @@
|
||||
/**********************************************************************
|
||||
|
||||
Audacity: A Digital Audio Editor
|
||||
|
||||
AudioUnitCocoaHelper.h
|
||||
|
||||
Leland Lucius
|
||||
|
||||
**********************************************************************/
|
||||
|
||||
#ifndef AUDACITY_AUDIOUNIT_COCOA_HELPER_H
|
||||
#define AUDACITY_AUDIOUNIT_COCOA_HELPER_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <AudioUnit/AudioUnitCarbonView.h>
|
||||
|
||||
HIViewRef createGeneric(AudioUnit unit);
|
||||
HIViewRef createPanner(AudioUnit unit);
|
||||
HIViewRef createCocoa(AudioUnit unit);
|
||||
HIViewRef createCarbon(AudioUnit unit, WindowRef window, AudioUnitCarbonView *carbonView);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -1,350 +0,0 @@
|
||||
/**********************************************************************
|
||||
|
||||
Audacity: A Digital Audio Editor
|
||||
|
||||
AudioUnitCocoaHelper.m
|
||||
|
||||
Leland Lucius
|
||||
|
||||
*******************************************************************//**
|
||||
|
||||
\class AUScrollView
|
||||
\brief An NSScrollView subclass that hosts AUs
|
||||
|
||||
NOTE: I do NOT to Objective-C(++), so if you see ANYTHING wrong do
|
||||
not hesitate to let me know. -Leland
|
||||
|
||||
*//*******************************************************************/
|
||||
|
||||
#import <Carbon/Carbon.h>
|
||||
#import <AudioUnit/AudioUnit.h>
|
||||
#import <AudioUnit/AUCocoaUIView.h>
|
||||
#import <CoreAudioKit/CoreAudioKit.h>
|
||||
#import <AppKit/NSScrollView.h>
|
||||
|
||||
#import "AudioUnitCocoaHelper.h"
|
||||
|
||||
@interface AUScrollView: NSScrollView
|
||||
{
|
||||
NSView *auView;
|
||||
HIViewRef hiViewRef;
|
||||
}
|
||||
|
||||
- (id)initWithFrame:(NSRect)frameRect;
|
||||
|
||||
/* Might be useful for improved resizing
|
||||
- (void)auResized:(NSNotification *)notification;
|
||||
- (void)myResized:(NSNotification *)notification;
|
||||
*/
|
||||
|
||||
@end
|
||||
|
||||
@implementation AUScrollView
|
||||
|
||||
- (id)initWithFrame:(NSRect)frameRect
|
||||
{
|
||||
self = [super initWithFrame:frameRect];
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)reflectScrolledClipView:(NSClipView *)aClipView
|
||||
{
|
||||
[super reflectScrolledClipView:aClipView];
|
||||
|
||||
// Force a full refresh as some effects seem to need it
|
||||
[self setNeedsDisplay:YES];
|
||||
}
|
||||
|
||||
- (BOOL)autoresizesSubviews
|
||||
{
|
||||
// Let NSView automatically resize our children
|
||||
return YES;
|
||||
}
|
||||
@end
|
||||
|
||||
/* Might be useful for improved resizing. I'd worked up this
|
||||
really elaborate resizing stuff that "almost" worked. Rather
|
||||
than spend even more time, I decided to get rid of it all and
|
||||
let resizing happen as it will. This code should be short
|
||||
lived anyway as it will probably not be needed once we convert
|
||||
to wxWidgets 3+.
|
||||
|
||||
-(void) setViews:(NSView *)aView hiViewRef:(HIViewRef)hView
|
||||
{
|
||||
auView = aView;
|
||||
hiViewRef = hView;
|
||||
|
||||
[[NSNotificationCenter defaultCenter]
|
||||
addObserver:self
|
||||
selector:@selector(myResized:) name:NSViewFrameDidChangeNotification object:self];
|
||||
|
||||
[[NSNotificationCenter defaultCenter]
|
||||
addObserver:self
|
||||
selector:@selector(auResized:) name:NSViewFrameDidChangeNotification object:auView];
|
||||
|
||||
}
|
||||
|
||||
- (void)myResized:(NSNotification *)notification
|
||||
{
|
||||
}
|
||||
|
||||
- (void)auResized:(NSNotification *)notification
|
||||
{
|
||||
}
|
||||
|
||||
*/
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Create a Cocoa based generic AU view wrapped in a Carbon view
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
HIViewRef createGeneric(AudioUnit unit)
|
||||
{
|
||||
HIViewRef hiView = NULL;
|
||||
OSStatus result;
|
||||
|
||||
// Create a generic AU view
|
||||
NSView *auView = [[[AUGenericView alloc] initWithAudioUnit: unit] retain];
|
||||
if (auView != nil)
|
||||
{
|
||||
// Allow expert parameters to be used
|
||||
[(AUGenericView *) auView setShowsExpertParameters:YES];
|
||||
|
||||
// Get the AU view's frame for later
|
||||
NSRect viewFrame = [auView frame];
|
||||
|
||||
// Create the view that will host the AU view
|
||||
AUScrollView *scrollView =
|
||||
[[[AUScrollView alloc] initWithFrame:viewFrame] autorelease];
|
||||
|
||||
// Not sure if this is necessary, but crashes seemed to occur
|
||||
// without it.
|
||||
[scrollView retain];
|
||||
|
||||
// Set the scroller options
|
||||
[scrollView setDrawsBackground:YES];
|
||||
[scrollView setAutohidesScrollers:YES];
|
||||
[scrollView setHasHorizontalScroller:YES];
|
||||
[scrollView setHasVerticalScroller:YES];
|
||||
[scrollView setBorderType:NSNoBorder];
|
||||
[scrollView setAutoresizingMask:NSViewWidthSizable|NSViewHeightSizable];
|
||||
|
||||
// Let the scrollview know about the AU view
|
||||
//
|
||||
// Should the AU view be released after this???
|
||||
[scrollView setDocumentView:auView];
|
||||
// [auView release];
|
||||
|
||||
// Carbonize it
|
||||
result = HICocoaViewCreate(scrollView, 0, &hiView);
|
||||
if (result == noErr)
|
||||
{
|
||||
// Resize the HIView to match the AU view
|
||||
SizeControl(hiView, viewFrame.size.width, viewFrame.size.height);
|
||||
}
|
||||
}
|
||||
|
||||
return hiView;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Create a Cocoa based generic panner AU view wrapped in a Carbon view
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
HIViewRef createPanner(AudioUnit unit)
|
||||
{
|
||||
HIViewRef hiView = NULL;
|
||||
OSStatus result;
|
||||
|
||||
// Create a generic AU view
|
||||
NSView *auView = [[AUPannerView AUPannerViewWithAudioUnit:unit] retain];
|
||||
if (auView != nil)
|
||||
{
|
||||
// Get the AU view's frame for later
|
||||
NSRect viewFrame = [auView frame];
|
||||
|
||||
// Create the view that will host the AU view
|
||||
AUScrollView *scrollView =
|
||||
[[[AUScrollView alloc] initWithFrame:viewFrame] autorelease];
|
||||
|
||||
// Not sure if this is necessary, but crashes seemed to occur
|
||||
// without it.
|
||||
[scrollView retain];
|
||||
|
||||
// Set the scroller options
|
||||
[scrollView setDrawsBackground:YES];
|
||||
[scrollView setAutohidesScrollers:YES];
|
||||
[scrollView setHasHorizontalScroller:YES];
|
||||
[scrollView setHasVerticalScroller:YES];
|
||||
[scrollView setBorderType:NSNoBorder];
|
||||
[scrollView setAutoresizingMask:NSViewWidthSizable|NSViewHeightSizable];
|
||||
|
||||
// Let the scrollview know about the AU view
|
||||
//
|
||||
// Should the AU view be released after this???
|
||||
[scrollView setDocumentView:auView];
|
||||
// [auView release];
|
||||
|
||||
// Carbonize it
|
||||
result = HICocoaViewCreate(scrollView, 0, &hiView);
|
||||
if (result == noErr)
|
||||
{
|
||||
// Resize the HIView to match the AU view
|
||||
SizeControl(hiView, viewFrame.size.width, viewFrame.size.height);
|
||||
}
|
||||
}
|
||||
|
||||
return hiView;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Create a Cocoa based custom AU view wrapped in a Carbon view
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
HIViewRef createCocoa(AudioUnit unit)
|
||||
{
|
||||
HIViewRef hiView = NULL;
|
||||
OSStatus result;
|
||||
|
||||
AudioUnitCocoaViewInfo cocoaViewInfo;
|
||||
UInt32 dataSize = sizeof(AudioUnitCocoaViewInfo);
|
||||
|
||||
// Get info about first Cocoa view
|
||||
result = AudioUnitGetProperty(unit,
|
||||
kAudioUnitProperty_CocoaUI,
|
||||
kAudioUnitScope_Global,
|
||||
0,
|
||||
&cocoaViewInfo,
|
||||
&dataSize);
|
||||
if (result != noErr)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Looks like the AU has a Cocoa UI, so load the factory class
|
||||
NSURL *bundleLoc = (NSURL *) cocoaViewInfo.mCocoaAUViewBundleLocation;
|
||||
NSString *className = (NSString *) cocoaViewInfo.mCocoaAUViewClass[0];
|
||||
if (!bundleLoc || !className)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Load the bundle
|
||||
NSBundle *bundle = [NSBundle bundleWithPath: [bundleLoc path]];
|
||||
if (bundle != nil)
|
||||
{
|
||||
// Load the class from the bundle
|
||||
Class factoryClass = [bundle classNamed: className];
|
||||
if (factoryClass != nil)
|
||||
{
|
||||
// Create an instance of the class
|
||||
id factoryInst = [[[factoryClass alloc] init] autorelease];
|
||||
if (factoryInst != nil)
|
||||
{
|
||||
// Suggest a resonable size
|
||||
NSSize size = {800, 600};
|
||||
|
||||
// Create the view
|
||||
NSView *auView = [[factoryInst uiViewForAudioUnit: unit withSize: size] retain];
|
||||
if (auView != nil)
|
||||
{
|
||||
// Get the AU views frame for later
|
||||
NSRect viewFrame = [auView frame];
|
||||
|
||||
// Create the view that will host the AU view
|
||||
AUScrollView *scrollView =
|
||||
[[[AUScrollView alloc] initWithFrame:viewFrame] autorelease];
|
||||
|
||||
// Not sure if this is necessary, but crashes seemed to occur
|
||||
// without it.
|
||||
[scrollView retain];
|
||||
|
||||
// Set the scroller options
|
||||
[scrollView setDrawsBackground:YES];
|
||||
[scrollView setAutohidesScrollers:YES];
|
||||
[scrollView setHasHorizontalScroller:YES];
|
||||
[scrollView setHasVerticalScroller:YES];
|
||||
[scrollView setBorderType:NSNoBorder];
|
||||
|
||||
// Let the scrollview know about the AU view
|
||||
//
|
||||
// Should the AU view be released after this???
|
||||
[scrollView setDocumentView:auView];
|
||||
|
||||
// Carbonize it
|
||||
result = HICocoaViewCreate(scrollView, 0, &hiView);
|
||||
if (result == noErr)
|
||||
{
|
||||
// Resize the HIView to match the AU view
|
||||
SizeControl(hiView, viewFrame.size.width, viewFrame.size.height);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Release the bundle???
|
||||
// [bundle release];
|
||||
}
|
||||
|
||||
// Release the bundle path
|
||||
[bundleLoc release];
|
||||
|
||||
return hiView;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Create a Carbon based AU view
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
HIViewRef createCarbon(AudioUnit unit, WindowRef window, AudioUnitCarbonView *carbonView)
|
||||
{
|
||||
HIViewRef hiView = NULL;
|
||||
OSStatus result;
|
||||
|
||||
// Retrieve the view component description
|
||||
ComponentDescription compDesc;
|
||||
UInt32 dataSize = sizeof(compDesc);
|
||||
result = AudioUnitGetProperty(unit,
|
||||
kAudioUnitProperty_GetUIComponentList,
|
||||
kAudioUnitScope_Global,
|
||||
0,
|
||||
&compDesc,
|
||||
&dataSize);
|
||||
if (result != noErr)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Try to open it
|
||||
Component comp = FindNextComponent(NULL, &compDesc);
|
||||
result = OpenAComponent(comp, carbonView);
|
||||
if (result != noErr)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Get the root control
|
||||
ControlRef root = HIViewGetRoot(window);
|
||||
GetRootControl(window, &root);
|
||||
|
||||
// Find the content view within our window
|
||||
HIViewRef content;
|
||||
result = HIViewFindByID(root, kHIViewWindowContentID, &content);
|
||||
if (result != noErr)
|
||||
{
|
||||
CloseComponent(*carbonView);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Suggest a reasonable size
|
||||
Float32Point loc = {0.0, 0.0};
|
||||
Float32Point size = {800.0, 600.0};
|
||||
|
||||
// And create it
|
||||
result = AudioUnitCarbonViewCreate(*carbonView,
|
||||
unit,
|
||||
window,
|
||||
root,
|
||||
&loc,
|
||||
&size,
|
||||
&hiView);
|
||||
|
||||
return hiView;
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -8,22 +8,24 @@
|
||||
Leland Lucius
|
||||
|
||||
**********************************************************************/
|
||||
#ifndef AUDACITY_AUDIOUNIT_EFFECT_H
|
||||
|
||||
#include "../../Audacity.h"
|
||||
|
||||
#if USE_AUDIO_UNITS
|
||||
|
||||
#include <wx/dialog.h>
|
||||
|
||||
#include "../Effect.h"
|
||||
|
||||
#include <ApplicationServices/ApplicationServices.h>
|
||||
#include <CoreServices/CoreServices.h>
|
||||
#include <Carbon/Carbon.h>
|
||||
#include <AudioUnit/AudioUnitProperties.h>
|
||||
#include <AudioUnit/AudioUnitCarbonView.h>
|
||||
#include <AudioToolbox/AudioUnitUtilities.h>
|
||||
#include <AudioUnit/AudioUnit.h>
|
||||
#include <AudioUnit/AudioUnitProperties.h>
|
||||
|
||||
#include "audacity/EffectInterface.h"
|
||||
#include "audacity/ModuleInterface.h"
|
||||
#include "audacity/PluginInterface.h"
|
||||
|
||||
#include "AUControl.h"
|
||||
|
||||
#define AUDIOUNITEFFECTS_VERSION wxT("1.0.0.0")
|
||||
#define AUDIOUNITEFFECTS_FAMILY wxT("AudioUnit")
|
||||
|
||||
@@ -41,7 +43,7 @@ class AudioUnitEffect : public wxEvtHandler,
|
||||
public:
|
||||
AudioUnitEffect(const wxString & path,
|
||||
const wxString & name,
|
||||
Component component,
|
||||
AudioComponent component,
|
||||
AudioUnitEffect *master = NULL);
|
||||
virtual ~AudioUnitEffect();
|
||||
|
||||
@@ -156,53 +158,39 @@ private:
|
||||
void EventListener(const AudioUnitEvent *inEvent,
|
||||
AudioUnitParameterValue inParameterValue);
|
||||
|
||||
static pascal OSStatus WindowEventHandlerCallback(EventHandlerCallRef handler,
|
||||
EventRef event,
|
||||
void *data);
|
||||
OSStatus WindowEventHandler(EventRef event);
|
||||
|
||||
static pascal OSStatus ControlEventHandlerCallback(EventHandlerCallRef handler,
|
||||
EventRef event,
|
||||
void *data);
|
||||
OSStatus ControlEventHandler(EventRef event);
|
||||
|
||||
static pascal OSStatus TrackingEventHandler(EventHandlerCallRef handler,
|
||||
EventRef event,
|
||||
void *data);
|
||||
OSStatus OnTrackingEvent(EventRef event);
|
||||
|
||||
void RemoveHandler();
|
||||
|
||||
void GetChannelCounts();
|
||||
|
||||
bool LoadParameters(const wxString & group);
|
||||
bool SaveParameters(const wxString & group);
|
||||
|
||||
void OnSize(wxSizeEvent & evt);
|
||||
|
||||
bool CreatePlain(wxWindow *parent);
|
||||
|
||||
private:
|
||||
|
||||
wxString mPath;
|
||||
wxString mName;
|
||||
wxString mVendor;
|
||||
Component mComponent;
|
||||
AudioUnit mUnit;
|
||||
bool mSupportsMono;
|
||||
bool mSupportsStereo;
|
||||
wxString mPath;
|
||||
wxString mName;
|
||||
wxString mVendor;
|
||||
AudioComponent mComponent;
|
||||
AudioUnit mUnit;
|
||||
bool mUnitInitialized;
|
||||
|
||||
bool mSupportsMono;
|
||||
bool mSupportsStereo;
|
||||
|
||||
EffectHostInterface *mHost;
|
||||
int mAudioIns;
|
||||
int mAudioOuts;
|
||||
bool mInteractive;
|
||||
bool mLatencyDone;
|
||||
UInt32 mBlockSize;
|
||||
double mSampleRate;
|
||||
int mAudioIns;
|
||||
int mAudioOuts;
|
||||
bool mInteractive;
|
||||
bool mLatencyDone;
|
||||
UInt32 mBlockSize;
|
||||
double mSampleRate;
|
||||
|
||||
int mBufferSize;
|
||||
bool mUseLatency;
|
||||
int mBufferSize;
|
||||
bool mUseLatency;
|
||||
|
||||
AudioTimeStamp mTimeStamp;
|
||||
bool mReady;
|
||||
bool mReady;
|
||||
|
||||
AudioBufferList *mInputList;
|
||||
AudioBufferList *mOutputList;
|
||||
@@ -210,14 +198,9 @@ private:
|
||||
EffectUIHostInterface *mUIHost;
|
||||
wxWindow *mParent;
|
||||
wxDialog *mDialog;
|
||||
wxSizerItem *mContainer;
|
||||
AudioUnitCarbonView mCarbonView;
|
||||
bool mUseGUI;
|
||||
HIViewRef mAUView;
|
||||
EventTargetRef mEventRef;
|
||||
bool mIsCocoa;
|
||||
bool mIsCarbon;
|
||||
bool mIsGeneric;
|
||||
AUControl *mControl;
|
||||
wxString mUIType;
|
||||
bool mIsGraphical;
|
||||
|
||||
AudioUnitEffect *mMaster; // non-NULL if a slave
|
||||
AudioUnitEffectArray mSlaves;
|
||||
@@ -228,18 +211,6 @@ private:
|
||||
|
||||
AUEventListenerRef mEventListenerRef;
|
||||
|
||||
EventHandlerRef mHandlerRef;
|
||||
EventHandlerUPP mHandlerUPP;
|
||||
EventHandlerRef mControlHandlerRef;
|
||||
EventHandlerUPP mControlHandlerUPP;
|
||||
|
||||
EventHandlerUPP mTrackingHandlerUPP;
|
||||
EventHandlerRef mRootTrackingHandlerRef;
|
||||
EventHandlerRef mContentTrackingHandlerRef;
|
||||
EventHandlerRef mAUTrackingHandlerRef;
|
||||
|
||||
DECLARE_EVENT_TABLE();
|
||||
|
||||
friend class AudioUnitEffectExportDialog;
|
||||
friend class AudioUnitEffectImportDialog;
|
||||
};
|
||||
@@ -282,7 +253,7 @@ public:
|
||||
// AudioUnitEffectModule implementation
|
||||
|
||||
void LoadAudioUnitsOfType(OSType inAUType, wxArrayString & effects);
|
||||
Component FindAudioUnit(const wxString & path, wxString & name);
|
||||
AudioComponent FindAudioUnit(const wxString & path, wxString & name);
|
||||
|
||||
wxString FromOSType(OSType type);
|
||||
OSType ToOSType(const wxString & type);
|
||||
@@ -292,3 +263,6 @@ private:
|
||||
wxString mPath;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user