diff --git a/Plugins/MIDI/MIDI/AUPlayer.h b/Plugins/MIDI/MIDI/AUPlayer.h index 75e0ba97c..23f5c9f89 100644 --- a/Plugins/MIDI/MIDI/AUPlayer.h +++ b/Plugins/MIDI/MIDI/AUPlayer.h @@ -28,6 +28,7 @@ class AUPlayer : public MIDIPlayer { static void enumComponents(callback cbEnum); void setComponent(OSType uSubType, OSType uManufacturer); + void setPreset(NSDictionary *preset); protected: virtual unsigned int send_event_needs_time(); @@ -61,6 +62,8 @@ class AUPlayer : public MIDIPlayer { OSType componentSubType, componentManufacturer; BOOL needsInput; + + NSDictionary *preset; }; #endif diff --git a/Plugins/MIDI/MIDI/AUPlayer.mm b/Plugins/MIDI/MIDI/AUPlayer.mm index aaedd1f9a..6c20ee1c6 100644 --- a/Plugins/MIDI/MIDI/AUPlayer.mm +++ b/Plugins/MIDI/MIDI/AUPlayer.mm @@ -208,6 +208,10 @@ void AUPlayer::setSoundFont(const char *in) { } } +void AUPlayer::setPreset(NSDictionary *preset) { + this->preset = preset; +} + /*void AUPlayer::setFileSoundFont( const char * in ) { sFileSoundFontName = in; @@ -334,6 +338,11 @@ bool AUPlayer::startup() { value = 1; AudioUnitSetProperty(samplerUnit[i], kMusicDeviceProperty_StreamFromDisk, kAudioUnitScope_Global, 0, &value, size); + if(preset) { + CFDictionaryRef cdict = (__bridge CFDictionaryRef)preset; + AudioUnitSetProperty(samplerUnit[i], kAudioUnitProperty_ClassInfo, kAudioUnitScope_Global, 0, &cdict, sizeof(cdict)); + } + error = AudioUnitInitialize(samplerUnit[i]); if(error != noErr) diff --git a/Plugins/MIDI/MIDI/MIDIDecoder.mm b/Plugins/MIDI/MIDI/MIDIDecoder.mm index 1c553121b..02c8b594e 100644 --- a/Plugins/MIDI/MIDI/MIDIDecoder.mm +++ b/Plugins/MIDI/MIDI/MIDIDecoder.mm @@ -270,6 +270,14 @@ static OSType getOSType(const char *in_) { soundFontsAssigned = YES; } + NSDictionary *midiPluginSettings = [[[NSUserDefaultsController sharedUserDefaultsController] defaults] objectForKey:@"midiPluginSettings"]; + if(midiPluginSettings) { + NSDictionary *theSettings = [midiPluginSettings objectForKey:plugin]; + if(theSettings) { + auplayer->setPreset(theSettings); + } + } + player = auplayer; } } diff --git a/Preferences/Preferences/AUPlayerView.h b/Preferences/Preferences/AUPlayerView.h new file mode 100644 index 000000000..09270d1eb --- /dev/null +++ b/Preferences/Preferences/AUPlayerView.h @@ -0,0 +1,57 @@ +// +// AUPlayerView.h +// MIDI +// +// Created by Christopher Snowhill on 1/29/16. +// Copyright © 2016-2022 Christopher Snowhill. All rights reserved. +// + +#ifndef __AUPlayerView_h__ +#define __AUPlayerView_h__ + +#include +#include + +#include +#include +#include +#include + +@class NSWindowDeleter; + +class AUPluginUI { + public: + AUPluginUI(NSString *name, AudioUnit& sampler); + ~AUPluginUI(); + + bool window_opened() const; + + private: + AudioUnit& au; + NSString* name; + int prefheight; + int prefwidth; + + bool opened; + bool mapped; + bool resizable; + int min_width; + int min_height; + int req_width; + int req_height; + int alo_width; + int alo_height; + + /* Cocoa */ + + NSWindowDeleter* cocoa_window; + NSView* au_view; + NSRect last_au_frame; + + bool test_cocoa_view_support(); + int create_cocoa_view(); + + bool plugin_class_valid(Class pluginClass); +}; + +#endif diff --git a/Preferences/Preferences/AUPlayerView.mm b/Preferences/Preferences/AUPlayerView.mm new file mode 100644 index 000000000..03ed6c2a2 --- /dev/null +++ b/Preferences/Preferences/AUPlayerView.mm @@ -0,0 +1,222 @@ +// +// AUPlayerView.mm +// MIDI +// +// Created by Christopher Snowhill on 1/29/16. +// Copyright © 2016-2022 Christopher Snowhill. All rights reserved. +// + +#import +#import + +#import "AUPlayerView.h" + +@interface NSWindowDeleter : NSWindow { + AUPluginUI *parent; +} + +- (void)setParentObject:(AUPluginUI *)object; +- (void)dealloc; +@end + +@implementation NSWindowDeleter + +- (void)setParentObject:(AUPluginUI *)object { + parent = object; +} + +- (void)dealloc { + delete parent; +} +@end + +AUPluginUI::AUPluginUI(NSString *_name, AudioUnit &_au) +: name(_name), au(_au), mapped(false), resizable(false), min_width(0), min_height(0), req_width(0), req_height(0), alo_width(0), alo_height(0) { + opened = false; + cocoa_window = nil; + au_view = nil; + + if(test_cocoa_view_support()) { + create_cocoa_view(); + } + + if(au_view) { + cocoa_window = [[NSWindowDeleter alloc] initWithContentRect:NSMakeRect(0, 0, req_width, req_height) + styleMask:(NSWindowStyleMaskTitled | + NSWindowStyleMaskClosable) + backing:NSBackingStoreBuffered + defer:NO]; + + [cocoa_window setParentObject:this]; + + [cocoa_window setAutodisplay:YES]; + [cocoa_window setTitle:@"AU Plug-in"]; + [cocoa_window setOneShot:YES]; + + [cocoa_window setContentView:au_view]; + + NSDictionary *midiPluginSettings = [[[NSUserDefaultsController sharedUserDefaultsController] defaults] objectForKey:@"midiPluginSettings"]; + if(midiPluginSettings) { + NSDictionary *theSettings = [midiPluginSettings objectForKey:name]; + if(theSettings) { + CFDictionaryRef cdict = (__bridge CFDictionaryRef)theSettings; + AudioUnitSetProperty(au, + kAudioUnitProperty_ClassInfo, + kAudioUnitScope_Global, + 0, + &cdict, + sizeof(cdict)); + } + } + + [cocoa_window orderFront:cocoa_window]; + + opened = true; + } +} + +AUPluginUI::~AUPluginUI() { + if(opened) { + NSMutableDictionary *midiPluginSettings = [[[[NSUserDefaultsController sharedUserDefaultsController] defaults] objectForKey:@"midiPluginSettings"] mutableCopy]; + if(!midiPluginSettings) { + midiPluginSettings = [[NSMutableDictionary alloc] init]; + } + CFDictionaryRef outClassInfo = nil; + UInt32 objectSize = sizeof(outClassInfo); + OSErr err = AudioUnitGetProperty(au, + kAudioUnitProperty_ClassInfo, + kAudioUnitScope_Global, + 0, + &outClassInfo, + &objectSize); + if(err == noErr) { + NSDictionary *dict = (__bridge NSDictionary *)outClassInfo; + [midiPluginSettings setObject:dict forKey:name]; + [[[NSUserDefaultsController sharedUserDefaultsController] defaults] setObject:midiPluginSettings forKey:@"midiPluginSettings"]; + dict = nil; + CFRelease(outClassInfo); + } + } + + AudioUnitUninitialize(au); + AudioComponentInstanceDispose(au); + au = NULL; +} + +bool AUPluginUI::test_cocoa_view_support() { + UInt32 dataSize = 0; + Boolean isWritable = 0; + OSStatus err = AudioUnitGetPropertyInfo(au, + kAudioUnitProperty_CocoaUI, kAudioUnitScope_Global, + 0, &dataSize, &isWritable); + + return dataSize > 0 && err == noErr; +} + +bool AUPluginUI::plugin_class_valid(Class pluginClass) { + if([pluginClass conformsToProtocol:@protocol(AUCocoaUIBase)]) { + if([pluginClass instancesRespondToSelector:@selector(interfaceVersion)] && + [pluginClass instancesRespondToSelector:@selector(uiViewForAudioUnit:withSize:)]) { + return true; + } + } + return false; +} + +int AUPluginUI::create_cocoa_view() { + bool wasAbleToLoadCustomView = false; + AudioUnitCocoaViewInfo *cocoaViewInfo = NULL; + UInt32 numberOfClasses = 0; + UInt32 dataSize; + Boolean isWritable; + NSString *factoryClassName = 0; + NSURL *CocoaViewBundlePath = NULL; + + OSStatus result = AudioUnitGetPropertyInfo(au, + kAudioUnitProperty_CocoaUI, + kAudioUnitScope_Global, + 0, + &dataSize, + &isWritable); + + numberOfClasses = (dataSize - sizeof(CFURLRef)) / sizeof(CFStringRef); + + // Does view have custom Cocoa UI? + + if((result == noErr) && (numberOfClasses > 0)) { + cocoaViewInfo = (AudioUnitCocoaViewInfo *)malloc(dataSize); + + if(AudioUnitGetProperty(au, + kAudioUnitProperty_CocoaUI, + kAudioUnitScope_Global, + 0, + cocoaViewInfo, + &dataSize) == noErr) { + CocoaViewBundlePath = (__bridge NSURL *)cocoaViewInfo->mCocoaAUViewBundleLocation; + + // we only take the first view in this example. + factoryClassName = (__bridge NSString *)cocoaViewInfo->mCocoaAUViewClass[0]; + } else { + if(cocoaViewInfo != NULL) { + free(cocoaViewInfo); + cocoaViewInfo = NULL; + } + } + } + + // [A] Show custom UI if view has it + + if(CocoaViewBundlePath && factoryClassName) { + NSBundle *viewBundle = [NSBundle bundleWithPath:[CocoaViewBundlePath path]]; + + if(viewBundle == NULL) { + return -1; + } else { + Class factoryClass = [viewBundle classNamed:factoryClassName]; + if(!factoryClass) { + return -1; + } + + // make sure 'factoryClass' implements the AUCocoaUIBase protocol + if(!plugin_class_valid(factoryClass)) { + return -1; + } + // make a factory + id factory = [[factoryClass alloc] init]; + if(factory == NULL) { + return -1; + } + + // make a view + au_view = [factory uiViewForAudioUnit:au withSize:NSZeroSize]; + + // cleanup + if(cocoaViewInfo) { + UInt32 i; + for(i = 0; i < numberOfClasses; i++) + CFRelease(cocoaViewInfo->mCocoaAUViewClass[i]); + + free(cocoaViewInfo); + } + wasAbleToLoadCustomView = true; + } + } + + if(!wasAbleToLoadCustomView) { + // load generic Cocoa view + au_view = [[AUGenericView alloc] initWithAudioUnit:au]; + [(AUGenericView *)au_view setShowsExpertParameters:1]; + } + + // Get the initial size of the new AU View's frame + NSRect frame = [au_view frame]; + min_width = req_width = CGRectGetWidth(NSRectToCGRect(frame)); + min_height = req_height = CGRectGetHeight(NSRectToCGRect(frame)); + resizable = [au_view autoresizingMask]; + + return 0; +} + +bool AUPluginUI::window_opened() const { + return opened; +} diff --git a/Preferences/Preferences/Base.lproj/Preferences.xib b/Preferences/Preferences/Base.lproj/Preferences.xib index 2268d323c..c602a870b 100644 --- a/Preferences/Preferences/Base.lproj/Preferences.xib +++ b/Preferences/Preferences/Base.lproj/Preferences.xib @@ -449,6 +449,9 @@ + + + @@ -879,7 +882,7 @@ - + @@ -893,12 +896,24 @@ + + diff --git a/Preferences/Preferences/MIDIPane.h b/Preferences/Preferences/MIDIPane.h index 57e2b6341..936f44629 100644 --- a/Preferences/Preferences/MIDIPane.h +++ b/Preferences/Preferences/MIDIPane.h @@ -10,9 +10,14 @@ #import @interface MIDIPane : GeneralPreferencePane { + IBOutlet NSArrayController *midiPluginBehaviorArrayController; + IBOutlet NSButton *midiPluginSetupButton; + IBOutlet NSPopUpButton *midiPluginControl; IBOutlet NSPopUpButton *midiFlavorControl; } +- (IBAction)setupPlugin:(id)sender; + - (IBAction)setSoundFont:(id)sender; @end diff --git a/Preferences/Preferences/MIDIPane.mm b/Preferences/Preferences/MIDIPane.mm new file mode 100644 index 000000000..5c53fb376 --- /dev/null +++ b/Preferences/Preferences/MIDIPane.mm @@ -0,0 +1,128 @@ +// +// MIDIPane.m +// General +// +// Created by Christopher Snowhill on 10/15/13. +// +// + +#import "MIDIPane.h" + +#import "SandboxBroker.h" + +#import "AppController.h" + +#import "AUPlayerView.h" + +@implementation MIDIPane { + NSTimer *startupTimer; +} + +- (void)awakeFromNib { + __block MIDIPane *_self = self; + startupTimer = [NSTimer timerWithTimeInterval:0.2 repeats:YES block:^(NSTimer * _Nonnull timer) { + NSUInteger selectedItem = [_self->midiPluginControl indexOfSelectedItem]; + NSArray *arrangedObjects = [_self->midiPluginBehaviorArrayController arrangedObjects]; + if([arrangedObjects count] > selectedItem) { + NSDictionary *selectedInfo = arrangedObjects[selectedItem]; + [_self->midiPluginSetupButton setEnabled:[[selectedInfo objectForKey:@"configurable"] boolValue]]; + [timer invalidate]; + } + }]; + [[NSRunLoop mainRunLoop] addTimer:startupTimer forMode:NSRunLoopCommonModes]; +} + +- (void)dealloc { + [startupTimer invalidate]; + startupTimer = nil; +} + +- (NSString *)title { + return NSLocalizedPrefString(@"Synthesis"); +} + +- (NSImage *)icon { + if(@available(macOS 11.0, *)) + return [NSImage imageWithSystemSymbolName:@"pianokeys" accessibilityDescription:nil]; + return [[NSImage alloc] initWithContentsOfFile:[[NSBundle bundleForClass:[self class]] pathForImageResource:@"midi"]]; +} + +- (IBAction)setSoundFont:(id)sender { + NSArray *fileTypes = @[@"sf2", @"sf2pack", @"sflist", @"sf3"]; + NSOpenPanel *panel = [NSOpenPanel openPanel]; + [panel setAllowsMultipleSelection:NO]; + [panel setCanChooseDirectories:NO]; + [panel setCanChooseFiles:YES]; + [panel setFloatingPanel:YES]; + [panel setAllowedFileTypes:fileTypes]; + NSString *oldPath = [[NSUserDefaults standardUserDefaults] stringForKey:@"soundFontPath"]; + if(oldPath != nil) + [panel setDirectoryURL:[NSURL fileURLWithPath:oldPath]]; + NSInteger result = [panel runModal]; + if(result == NSModalResponseOK) { + [[NSUserDefaults standardUserDefaults] setValue:[[panel URL] path] forKey:@"soundFontPath"]; + + id sandboxBrokerClass = NSClassFromString(@"SandboxBroker"); + NSURL *pathUrl = [panel URL]; + if(![[sandboxBrokerClass sharedSandboxBroker] areAllPathsSafe:@[pathUrl]]) { + id appControllerClass = NSClassFromString(@"AppController"); + [appControllerClass globalShowPathSuggester]; + } + } +} + +- (IBAction)setMidiPlugin:(id)sender { + NSUInteger selectedItem = [midiPluginControl indexOfSelectedItem]; + NSDictionary *selectedInfo = [midiPluginBehaviorArrayController arrangedObjects][selectedItem]; + [midiPluginSetupButton setEnabled:[[selectedInfo objectForKey:@"configurable"] boolValue]]; +} + +static OSType getOSType(const char *in_) { + const unsigned char *in = (const unsigned char *)in_; + OSType v = (in[0] << 24) + (in[1] << 16) + (in[2] << 8) + in[3]; + return v; +} + +- (IBAction)setupPlugin:(id)sender { + NSUInteger selectedItem = [midiPluginControl indexOfSelectedItem]; + NSDictionary *selectedInfo = [midiPluginBehaviorArrayController arrangedObjects][selectedItem]; + if(![[selectedInfo objectForKey:@"configurable"] boolValue]) + return; + + NSString *plugin = [selectedInfo objectForKey:@"preference"]; + const char *cplugin = [plugin UTF8String]; + + AudioComponentDescription cd = { 0 }; + + cd.componentType = kAudioUnitType_MusicDevice; + cd.componentSubType = getOSType(cplugin); + cd.componentManufacturer = getOSType(cplugin + 4); + + AudioComponent comp = NULL; + + comp = AudioComponentFindNext(comp, &cd); + + if(!comp) + return; + + AudioUnit au = NULL; + + OSStatus error; + + error = AudioComponentInstanceNew(comp, &au); + + if(error != noErr) + return; + + /*error = AudioUnitInitialize(au); + if(error != noErr) + return;*/ + + AUPluginUI * pluginUI = new AUPluginUI(plugin, au); + + if(!pluginUI->window_opened()) { + delete pluginUI; + } +} + +@end diff --git a/Preferences/Preferences/MIDIPluginBehaviorArrayController.m b/Preferences/Preferences/MIDIPluginBehaviorArrayController.m index fdc7186eb..10c52ef59 100644 --- a/Preferences/Preferences/MIDIPluginBehaviorArrayController.m +++ b/Preferences/Preferences/MIDIPluginBehaviorArrayController.m @@ -60,25 +60,25 @@ static void enumCallback(void *context, OSType uSubType, OSType uManufacturer, c pref[8] = '\0'; [pself addObject: - [NSDictionary dictionaryWithObjectsAndKeys: - [NSString stringWithUTF8String:name], @"name", - [NSString stringWithUTF8String:pref], @"preference", nil]]; + @{@"name": [NSString stringWithUTF8String:name], + @"preference": [NSString stringWithUTF8String:pref], + @"configurable": @YES}]; } @implementation MIDIPluginBehaviorArrayController - (void)awakeFromNib { [self removeObjects:[self arrangedObjects]]; - [self addObject:@{@"name": @"BASSMIDI", @"preference": @"BASSMIDI"}]; + [self addObject:@{@"name": @"BASSMIDI", @"preference": @"BASSMIDI", @"configurable": @NO}]; - [self addObject:@{@"name": @"DMX Generic", @"preference": @"DOOM0000"}]; - [self addObject:@{@"name": @"DMX Doom 1", @"preference": @"DOOM0001"}]; - [self addObject:@{@"name": @"DMX Doom 2", @"preference": @"DOOM0002"}]; - [self addObject:@{@"name": @"DMX Raptor", @"preference": @"DOOM0003"}]; - [self addObject:@{@"name": @"DMX Strife", @"preference": @"DOOM0004"}]; - [self addObject:@{@"name": @"DMXOPL", @"preference": @"DOOM0005"}]; + [self addObject:@{@"name": @"DMX Generic", @"preference": @"DOOM0000", @"configurable": @NO}]; + [self addObject:@{@"name": @"DMX Doom 1", @"preference": @"DOOM0001", @"configurable": @NO}]; + [self addObject:@{@"name": @"DMX Doom 2", @"preference": @"DOOM0002", @"configurable": @NO}]; + [self addObject:@{@"name": @"DMX Raptor", @"preference": @"DOOM0003", @"configurable": @NO}]; + [self addObject:@{@"name": @"DMX Strife", @"preference": @"DOOM0004", @"configurable": @NO}]; + [self addObject:@{@"name": @"DMXOPL", @"preference": @"DOOM0005", @"configurable": @NO}]; - [self addObject:@{@"name": @"OPL3Windows", @"preference": @"OPL3W000"}]; + [self addObject:@{@"name": @"OPL3Windows", @"preference": @"OPL3W000", @"configurable": @NO}]; enumComponents(enumCallback, (__bridge void *)(self)); } diff --git a/Preferences/Preferences/Preferences.xcodeproj/project.pbxproj b/Preferences/Preferences/Preferences.xcodeproj/project.pbxproj index db97b9466..f7b1c1f71 100644 --- a/Preferences/Preferences/Preferences.xcodeproj/project.pbxproj +++ b/Preferences/Preferences/Preferences.xcodeproj/project.pbxproj @@ -32,10 +32,11 @@ 8391EA06286F9D3200A37593 /* PathSuggester.xib in Resources */ = {isa = PBXBuildFile; fileRef = 83DAD9F0286EDBCD000FAA9A /* PathSuggester.xib */; }; 83A3B72C283AE04800CC6593 /* ColorToValueTransformer.m in Sources */ = {isa = PBXBuildFile; fileRef = 83A3B72B283AE04800CC6593 /* ColorToValueTransformer.m */; }; 83AC573A2861A54D009D6F50 /* PathSuggester.m in Sources */ = {isa = PBXBuildFile; fileRef = 83AC57382861A54D009D6F50 /* PathSuggester.m */; }; - 83B06729180D85B8008E3612 /* MIDIPane.m in Sources */ = {isa = PBXBuildFile; fileRef = 83B06728180D85B8008E3612 /* MIDIPane.m */; }; + 83B06729180D85B8008E3612 /* MIDIPane.mm in Sources */ = {isa = PBXBuildFile; fileRef = 83B06728180D85B8008E3612 /* MIDIPane.mm */; }; 83B0672B180D8B39008E3612 /* midi.png in Resources */ = {isa = PBXBuildFile; fileRef = 83B0672A180D8B39008E3612 /* midi.png */; }; 83B8FE242D59CDA7005854C1 /* rubberband.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 83B8FE232D59CDA7005854C1 /* rubberband.pdf */; }; 83B8FE292D59D059005854C1 /* RubberbandPane.m in Sources */ = {isa = PBXBuildFile; fileRef = 83B8FE282D59D059005854C1 /* RubberbandPane.m */; }; + 83E83F7E2D96780E0054365C /* AUPlayerView.mm in Sources */ = {isa = PBXBuildFile; fileRef = 83E83F7D2D96780E0054365C /* AUPlayerView.mm */; }; 83EF495F17FBC96A00642E3C /* VolumeBehaviorArrayController.m in Sources */ = {isa = PBXBuildFile; fileRef = 83EF495E17FBC96A00642E3C /* VolumeBehaviorArrayController.m */; }; 83F27E6B1810DD3A00CEF538 /* appearance@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 83F27E651810DD3A00CEF538 /* appearance@2x.png */; }; 83F27E6E1810DD3A00CEF538 /* midi@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 83F27E681810DD3A00CEF538 /* midi@2x.png */; }; @@ -136,7 +137,7 @@ 83AC57382861A54D009D6F50 /* PathSuggester.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = PathSuggester.m; sourceTree = ""; }; 83AC573E2861B77E009D6F50 /* SandboxBroker.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SandboxBroker.h; path = ../../Utils/SandboxBroker.h; sourceTree = ""; }; 83B06727180D85B8008E3612 /* MIDIPane.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MIDIPane.h; sourceTree = ""; }; - 83B06728180D85B8008E3612 /* MIDIPane.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MIDIPane.m; sourceTree = ""; }; + 83B06728180D85B8008E3612 /* MIDIPane.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MIDIPane.mm; sourceTree = ""; }; 83B0672A180D8B39008E3612 /* midi.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = midi.png; path = Icons/midi.png; sourceTree = ""; }; 83B8FE232D59CDA7005854C1 /* rubberband.pdf */ = {isa = PBXFileReference; lastKnownFileType = image.pdf; name = rubberband.pdf; path = Icons/rubberband.pdf; sourceTree = ""; }; 83B8FE272D59D03F005854C1 /* RubberbandPane.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = RubberbandPane.h; sourceTree = ""; }; @@ -145,6 +146,8 @@ 83DAD9F1286EDBCD000FAA9A /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/PathSuggester.xib; sourceTree = ""; }; 83DAD9F3286EDBD2000FAA9A /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/PathSuggester.strings; sourceTree = ""; }; 83DAD9F5286EDBD6000FAA9A /* es */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = es; path = es.lproj/PathSuggester.strings; sourceTree = ""; }; + 83E83F7C2D96780E0054365C /* AUPlayerView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AUPlayerView.h; sourceTree = ""; }; + 83E83F7D2D96780E0054365C /* AUPlayerView.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = AUPlayerView.mm; sourceTree = ""; }; 83EF495D17FBC96A00642E3C /* VolumeBehaviorArrayController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = VolumeBehaviorArrayController.h; sourceTree = ""; }; 83EF495E17FBC96A00642E3C /* VolumeBehaviorArrayController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = VolumeBehaviorArrayController.m; sourceTree = ""; }; 83F0E6AF287CAB4100D84594 /* pl */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = pl; path = pl.lproj/PathSuggester.strings; sourceTree = ""; }; @@ -269,7 +272,7 @@ 17C6433D0B8A783F00C53518 /* OutputPane.h */, 17C6433E0B8A783F00C53518 /* OutputPane.m */, 83B06727180D85B8008E3612 /* MIDIPane.h */, - 83B06728180D85B8008E3612 /* MIDIPane.m */, + 83B06728180D85B8008E3612 /* MIDIPane.mm */, 8307D309286057B5000FF8EB /* GeneralPane.h */, 8307D30A286057B5000FF8EB /* GeneralPane.m */, 83B8FE272D59D03F005854C1 /* RubberbandPane.h */, @@ -281,6 +284,8 @@ 17D503410ABDB1660022D1E8 /* Custom */ = { isa = PBXGroup; children = ( + 83E83F7C2D96780E0054365C /* AUPlayerView.h */, + 83E83F7D2D96780E0054365C /* AUPlayerView.mm */, 83651DA427322C8700A2C097 /* MIDIFlavorBehaviorArrayController.h */, 83651DA327322C8700A2C097 /* MIDIFlavorBehaviorArrayController.m */, 837C0D3E1C50954000CAE18F /* MIDIPluginBehaviorArrayController.h */, @@ -502,8 +507,9 @@ 83AC573A2861A54D009D6F50 /* PathSuggester.m in Sources */, 83B8FE292D59D059005854C1 /* RubberbandPane.m in Sources */, 83726F022CF41B3200F15FBF /* AppearancePane.m in Sources */, + 83E83F7E2D96780E0054365C /* AUPlayerView.mm in Sources */, 83651DA527322C8700A2C097 /* MIDIFlavorBehaviorArrayController.m in Sources */, - 83B06729180D85B8008E3612 /* MIDIPane.m in Sources */, + 83B06729180D85B8008E3612 /* MIDIPane.mm in Sources */, 8E07AA880AAC8EA200A4B32F /* HotKeyPane.m in Sources */, 83F27E741810E45D00CEF538 /* PathToFileTransformer.m in Sources */, 8E07AA890AAC8EA200A4B32F /* GeneralPreferencePane.m in Sources */, diff --git a/Preferences/Preferences/en.lproj/Preferences.strings b/Preferences/Preferences/en.lproj/Preferences.strings index 7fe1785fe..d2053a484 100644 --- a/Preferences/Preferences/en.lproj/Preferences.strings +++ b/Preferences/Preferences/en.lproj/Preferences.strings @@ -292,3 +292,6 @@ /* Class = "NSTextFieldCell"; title = "Channels:"; ObjectID = "LpA-ak-Aj5"; */ "LpA-ak-Aj5.title" = "Channels:"; + +/* Class = "NSButtonCell"; title = "Setup"; ObjectID = "Tdt-2E-FVm"; */ +"Tdt-2E-FVm.title" = "Setup"; diff --git a/Preferences/Preferences/es.lproj/Preferences.strings b/Preferences/Preferences/es.lproj/Preferences.strings index f15f09430..6511c4539 100644 --- a/Preferences/Preferences/es.lproj/Preferences.strings +++ b/Preferences/Preferences/es.lproj/Preferences.strings @@ -291,3 +291,6 @@ /* Class = "NSTextFieldCell"; title = "Channels:"; ObjectID = "LpA-ak-Aj5"; */ "LpA-ak-Aj5.title" = "Canales:"; + +/* Class = "NSButtonCell"; title = "Setup"; ObjectID = "Tdt-2E-FVm"; */ +"Tdt-2E-FVm.title" = "Config.";