Commits

Peter Hosey  committed a86ca1b

Checking in version 0.2 as published.

  • Participants
  • Parent commits 40eb23e
  • Tags 0.2

Comments (0)

Files changed (86)

File AudioPlayer.h

-//
-//  AudioPlayer.h
-//  AudioPlayer
-//
-//  Created by Mac-arena the Bored Zo on 2005-11-15.
-//  Copyright 2005 Mac-arena the Bored Zo. All rights reserved.
-//
-
-@interface AudioPlayer : NSObject {
-	IBOutlet NSWindow *playerWindow;
-	IBOutlet NSMatrix *moviesMatrix;
-	IBOutlet NSPopUpButton *devicesPopUp;
-
-	int lastSelectedDeviceIndex; //in the pop-up menu (not adjusted for Default item, since it could be that item)
-}
-
-@end

File AudioPlayer.m

-//
-//  AudioPlayer.m
-//  AudioPlayer
-//
-//  Created by Mac-arena the Bored Zo on 2005-11-15.
-//  Copyright 2005 Mac-arena the Bored Zo. All rights reserved.
-//
-
-#import "AudioPlayer.h"
-
-#import "NSURLAdditions.h"
-#import "NSMutableArray+EasyMutation.h"
-
-#import "BZMovieButtonCell.h"
-#import "AudioDevice.h"
-
-#include <c.h>
-#include <errno.h>
-#include <string.h>
-#include <math.h>
-#include <float.h>
-#include <unistd.h> //TEMP
-#import <ExceptionHandling/NSExceptionHandler.h> //TEMP
-
-//#define STORED_PLAYLIST_KEY @"Saved playlist"
-#define LAST_DEVICE_KEY @"UID of last selected output device"
-#define CONTENTS_OF_SOUNDBOARD_KEY @"Rows in soundboard"
-
-//guaranteed invalid URL/path indicating an empty cell in the soundboard
-#define EMPTY_CELL @"//empty_cell"
-
-#import "CommonNotifications.h"
-
-@interface AudioPlayer (PRIVATE)
-
-- (void)fillOutDevicesPopUp;
-
-@end
-
-@interface AudioPlayer (PRIVATE_BindingsAccessors)
-
-//relative to (used by) the pop-up menu.
-- (int)currentDeviceSelectionIndex;
-- (void)setCurrentDeviceSelectionIndex:(int)newIndex;
-
-@end
-
-@implementation AudioPlayer
-
-- init {
-	if (self = [super init]) {
-	}
-	return self;
-}
-
-- (void)awakeFromNib {
-	//populate the devices pop-up with all the devices.
-	[self fillOutDevicesPopUp];
-
-	//if we had a device selected at last quit (which practically means, if there WAS a last quit), re-select it.
-	NSString *lastDeviceUID = [[NSUserDefaults standardUserDefaults] stringForKey:LAST_DEVICE_KEY];
-	if(lastDeviceUID) {
-		int lastSelectedIndex = [devicesPopUp indexOfItemWithRepresentedObject:lastDeviceUID];
-		//make sure the device still exists. if not, stay with the default device (already selected in the nib).
-		if(lastSelectedIndex < 0)
-			lastSelectedIndex = 0;
-
-		//store it in our ivar.
-		[self setCurrentDeviceSelectionIndex:lastSelectedIndex];
-	}
-
-	//IB has our top-left cell highlighted and on. this works around that.
-	BZMovieButtonCell *cell = [moviesMatrix cellAtRow:0 column:0];
-	[cell setHighlighted:NO];
-	[cell setState:NSOffState];
-	
-	//position the window appropriately.
-	if(![playerWindow setFrameUsingName:[playerWindow frameAutosaveName]])
-		[playerWindow center];
-	[playerWindow makeKeyAndOrderFront:nil];
-}
-
-- (void)dealloc {
-
-	[super dealloc];
-}
-
-#pragma mark -
-
-- (QTAudioContextRef)createAudioContextWithDeviceUID:(NSString *)deviceUID {
-	QTAudioContextRef audioContext;
-	OSStatus err = QTAudioContextCreateForAudioDevice(kCFAllocatorDefault, (CFStringRef)deviceUID, /*options*/ NULL, &audioContext);
-	if(err != noErr) {
-		NSPanel *alert = NSGetAlertPanel(@"Could not get default device", @"An error of type %li (%s) occurred: %s", @"OK", nil, nil, err, GetMacOSStatusErrorString(err), GetMacOSStatusCommentString(err));
-		[NSApp beginSheet:alert modalForWindow:playerWindow modalDelegate:self didEndSelector:@selector(panelDidEnd:returnCode:contextInfo:) contextInfo:NULL];
-	}
-
-	return audioContext;
-}
-
-//this must return a new context every time, because QT doesn't like it when we reuse audio contexts (even if the previous movie has been released).
-- (QTAudioContextRef)createAudioContextForSelectedDevice {
-	NSString *deviceUID = [[devicesPopUp selectedItem] representedObject];
-	//if it's the default device, there is no represented object, so the represented object is nil = NULL, so we will create the context with the default device.
-	//if it's a specific device, there is a represented object, so the represented object (UID) is not nil, so we will create the context with the UID for a device.
-
-	//make an audio context for the selected device.
-	return [self createAudioContextWithDeviceUID:deviceUID];
-}
-- (QTMovie *)movieWithFile:(NSString *)path {
-	QTMovie *movie = nil;
-	if(path) {
-		NSError *error = nil;
-		movie = [[[QTMovie alloc] initWithFile:path error:&error] autorelease];
-		if(error) {
-			NSPanel *alert = NSGetAlertPanel(@"Could not open file", @"The file %@ could not be opened because: %@", @"OK", nil, nil, path, [error localizedFailureReason]);
-			[NSApp beginSheet:alert modalForWindow:playerWindow modalDelegate:self didEndSelector:@selector(panelDidEnd:returnCode:contextInfo:) contextInfo:NULL];
-		}
-
-		//disable all video tracks.
-		NSArray *videoTracks = [movie tracksOfMediaType:QTMediaTypeVideo];
-		NSEnumerator *videoTracksEnum = [videoTracks objectEnumerator];
-		QTTrack *track;
-		while((track = [videoTracksEnum nextObject]))
-			[track setEnabled:NO];
-	
-		QTAudioContextRef audioContext = [self createAudioContextForSelectedDevice];
-		OSStatus err = SetMovieAudioContext([movie quickTimeMovie], audioContext);
-		if(err != noErr) {
-			NSPanel *alert = NSGetAlertPanel(@"Could not set audio device", @"When trying to set the audio output device for the movie, an error of type %i (%s) occurred: %s", @"OK", nil, nil, err, GetMacOSStatusErrorString(err), GetMacOSStatusCommentString(err));
-			[NSApp beginSheet:alert modalForWindow:playerWindow modalDelegate:self didEndSelector:@selector(panelDidEnd:returnCode:contextInfo:) contextInfo:NULL];
-
-			QTAudioContextRelease(audioContext);
-		}
-	}
-
-	return movie;
-}
-
-#pragma mark NSApplication delegate conformance
-
-- (BOOL)applicationShouldTerminateAfterLastWindowClosed:(NSApplication *)app {
-	return YES;
-}
-
-- (void)applicationWillFinishLaunching:(NSNotification *)notification {
-	[moviesMatrix registerForDraggedTypes:[NSArray arrayWithObject:NSFilenamesPboardType]];
-
-	NSRange range = { 0U, [moviesMatrix numberOfRows] };
-	NSArray *rows = [[NSUserDefaults standardUserDefaults] arrayForKey:CONTENTS_OF_SOUNDBOARD_KEY];
-	if([rows count] > range.length)
-		rows = [rows subarrayWithRange:range];
-
-	//in the loop, we use this range to crop the rows to the proper number of columns.
-	range.length = [moviesMatrix numberOfColumns];
-
-	NSEnumerator *rowsEnum = [rows objectEnumerator];
-	NSArray *row;
-	unsigned rowIndex = 0U;
-	while((row = [rowsEnum nextObject])) {
-		NSEnumerator *rowEnum = [row objectEnumerator];
-		NSObject *obj;
-		unsigned colIndex = 0U;
-		while((obj = [rowEnum nextObject])) {
-			if(![obj isEqual:EMPTY_CELL]) {
-				NSDictionary *desc = (NSDictionary *)obj;
-				NSString *path = [[NSURL fileURLWithDockDescription:desc] path];
-
-				NSError *error = nil;
-				QTMovie *movie = [[QTMovie alloc] initWithFile:path error:&error];
-				if(error) {
-					NSPanel *alert = NSGetAlertPanel(@"Could not open file", @"The file %@ could not be opened because: %@", @"OK", nil, nil, path, [error localizedFailureReason]);
-					[NSApp beginSheet:alert modalForWindow:playerWindow modalDelegate:self didEndSelector:@selector(panelDidEnd:returnCode:contextInfo:) contextInfo:NULL]; 
-				}
-
-				if(movie) {
-					BZMovieButtonCell *cell = [moviesMatrix cellAtRow:rowIndex column:colIndex];
-					[cell setMovie:movie];
-					[movie release];
-				}
-			}
-
-			if(++colIndex >= range.length)
-				break;
-		}
-
-		++rowIndex;
-	}
-}
-
-- (void)applicationWillTerminate:(NSNotification *)notification {
-	NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
-	NSArray *rowsFromPrefs = [defaults arrayForKey:CONTENTS_OF_SOUNDBOARD_KEY];
-	unsigned rowsFromPrefsCount = [rowsFromPrefs count];
-
-	NSMutableArray *rows = [NSMutableArray arrayWithCapacity:rowsFromPrefsCount];
-
-	unsigned numberOfColsInMatrix = [moviesMatrix numberOfColumns];
-	unsigned numberOfRowsInMatrix = [moviesMatrix numberOfRows];
-
-	NSRange rowsCrop = { 0U, 0U };
-
-	unsigned rowIndex = 0U;
-	NSMutableArray *row;
-	while(rowIndex < numberOfRowsInMatrix) {
-		if(rowIndex < rowsFromPrefsCount)
-			row = [[rowsFromPrefs objectAtIndex:rowIndex] mutableCopy];
-		else
-			row = [[NSMutableArray alloc] init];
-
-		//we want to crop any empty cells off of the end.
-		NSRange columnsCrop = { 0U, 0U };
-
-		unsigned colIndex = 0U;
-		while(colIndex < numberOfColsInMatrix) {
-			BZMovieButtonCell *cell = [moviesMatrix cellAtRow:rowIndex column:colIndex];
-
-			NSObject *value;
-			QTMovie *movie = [cell movie];
-			if(movie) {
-				//we know the movie has a filename because we create them with filenames, as does BZMovieButtonCell.
-				NSString *path = [movie attributeForKey:QTMovieFileNameAttribute];
-				value = [[NSURL fileURLWithPath:path] dockDescription];
-
-				//start columns crop here.
-				columnsCrop.location = colIndex + 1U;
-			} else {
-				value = EMPTY_CELL;
-			}
-
-			[row setObject:value atIndex:colIndex++];
-		}
-
-		//crop off any empty cells at the end.
-		//this may leave the row empty, which is fine.
-		columnsCrop.length = [row count] - columnsCrop.location;
-		if(columnsCrop.length)
-			[row removeObjectsInRange:columnsCrop];
-
-		++rowIndex;
-		
-		//start rows crop here.
-		if([row count])
-			rowsCrop.location = rowIndex;
-
-		[rows addObject:row];
-		[row release];
-	}
-
-	rowsCrop.length = [rows count] - rowsCrop.location;
-	if(rowsCrop.length)
-		[rows removeObjectsInRange:rowsCrop];
-
-	[defaults setObject:rows forKey:CONTENTS_OF_SOUNDBOARD_KEY];
-}
-
-#if 0
-#pragma mark NSExceptionHandler delegate conformance (TEMP)
-
-- (BOOL)exceptionHandler:(NSExceptionHandler *)sender shouldLogException:(NSException *)exception mask:(unsigned int)aMask {
-	NSLog(@"logging exception: %@", exception);
-	NSMutableArray *symbols = [[[[exception userInfo] objectForKey:NSStackTraceKey] componentsSeparatedByString:@"  "] mutableCopy];
-	
-	[symbols insertObject:@"-p" atIndex:0U];
-	[symbols insertObject:[[NSNumber numberWithInt:getpid()] stringValue] atIndex:1U];
-	
-	NSTask *task = [[NSTask alloc] init];
-	[task setLaunchPath:@"/usr/bin/atos"];
-	[task setArguments:symbols];
-	NSPipe *pipe = [NSPipe pipe];
-	[task setStandardOutput:pipe];
-	
-	[task launch];
-	[task waitUntilExit];
-	
-	NSFileHandle *fh = [pipe fileHandleForReading];
-	NSData *data = [fh readDataToEndOfFile];
-	NSString *stackTrace = [[[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding] autorelease];
-	
-	[task release];
-	
-	NSLog(@"got %@ with reason %@; stack trace follows\n%@", [exception name], [exception reason], stackTrace);
-	
-	return NO; //because we just did
-}
-#endif //0
-//END TEMP
-
-#pragma mark Generic panel end handler
-
-- (void)panelDidEnd:(NSPanel *)panel returnCode:(int)returnCode contextInfo:(void *)contextInfo {
-	[panel close];
-}
-
-#pragma mark Bindings accessors
-
-//relative to (used by) the pop-up menu.
-- (int)currentDeviceSelectionIndex {
-	return lastSelectedDeviceIndex;
-}
-- (void)setCurrentDeviceSelectionIndex:(int)newIndex {
-	[self willChangeValueForKey:@"currentDeviceSelectionIndex"];
-	lastSelectedDeviceIndex = newIndex;
-	[self  didChangeValueForKey:@"currentDeviceSelectionIndex"];
-
-	//store it in user defaults.
-	NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
-	NSString *deviceUID = [[devicesPopUp selectedItem] representedObject];
-	if(deviceUID)
-		[defaults setObject:deviceUID forKey:LAST_DEVICE_KEY];
-	else
-		[defaults removeObjectForKey:LAST_DEVICE_KEY];
-
-	NSDictionary *userInfo = [NSDictionary dictionaryWithObjectsAndKeys:
-		deviceUID, SELECTED_DEVICE_UID,
-		[AudioDevice deviceWithUID:deviceUID], SELECTED_DEVICE_AUDIODEVICE,
-		nil];
-	[[NSNotificationCenter defaultCenter] postNotificationName:SELECTED_DEVICE_CHANGED_NOTIFICATION
-														object:devicesPopUp
-													  userInfo:userInfo];
-}
-
-#pragma mark End of implementation
-@end
-
-@implementation AudioPlayer (PRIVATE)
-
-- (void)fillOutDevicesPopUp {
-	OSStatus err;
-	UInt32 size;
-
-	err = AudioHardwareGetPropertyInfo(kAudioHardwarePropertyDevices, &size, /*outWritable*/ NULL);
-
-	if(err != noErr) {
-		NSPanel *alert = NSGetAlertPanel(@"Could not get size of audio devices array", @"When trying to get the size of the array of audio output devices, an error of type %i (%s) occurred: %s", @"OK", nil, nil, err, GetMacOSStatusErrorString(err), GetMacOSStatusCommentString(err));
-		[NSApp beginSheet:alert modalForWindow:playerWindow modalDelegate:self didEndSelector:@selector(panelDidEnd:returnCode:contextInfo:) contextInfo:NULL];
-	} else {
-
-		AudioDeviceID *deviceIDs = malloc(size);
-
-		if(!deviceIDs) {
-			NSPanel *alert = NSGetAlertPanel(@"Could not allocate audio devices array", @"When trying to get memory for the array of audio output devices, an error of type %i occurred: %s", @"OK", nil, nil, errno, strerror(errno));
-			[NSApp beginSheet:alert modalForWindow:playerWindow modalDelegate:self didEndSelector:@selector(panelDidEnd:returnCode:contextInfo:) contextInfo:NULL];
-		} else {
-
-			err = AudioHardwareGetProperty(kAudioHardwarePropertyDevices, &size, deviceIDs);
-
-			if(err != noErr) {
-				NSPanel *alert = NSGetAlertPanel(@"Could not get audio devices array", @"When trying to get the the array of audio output devices, an error of type %i (%s) occurred: %s", @"OK", nil, nil, err, GetMacOSStatusErrorString(err), GetMacOSStatusCommentString(err));
-				[NSApp beginSheet:alert modalForWindow:playerWindow modalDelegate:self didEndSelector:@selector(panelDidEnd:returnCode:contextInfo:) contextInfo:NULL];
-			} else {
-				UInt32 numDevices = size / sizeof(AudioDeviceID);
-				for(UInt32 deviceIdx = 0U; deviceIdx < numDevices; ++deviceIdx) {
-					NSString *UID;
-					size = sizeof(UID);
-
-					err = AudioDeviceGetProperty(deviceIDs[deviceIdx], /*inChannel*/ 0U, /*isInput*/ false, kAudioDevicePropertyDeviceUID, &size, &UID);
-
-					if(err != noErr) {
-						NSPanel *alert = NSGetAlertPanel(@"Could not get audio device UID", @"When trying to get the UID (unique identifier) of an audio output device, an error of type %i (%s) occurred: %s", @"OK", nil, nil, err, GetMacOSStatusErrorString(err), GetMacOSStatusCommentString(err));
-						[NSApp beginSheet:alert modalForWindow:playerWindow modalDelegate:self didEndSelector:@selector(panelDidEnd:returnCode:contextInfo:) contextInfo:NULL];
-					} else {
-						NSString *name;
-						size = sizeof(name);
-
-						err = AudioDeviceGetProperty(deviceIDs[deviceIdx], /*inChannel*/ 0U, /*isInput*/ false, kAudioObjectPropertyName, &size, &name);
-
-						if(err != noErr) {
-							NSPanel *alert = NSGetAlertPanel(@"Could not get audio device name", @"When trying to get the name of an audio output device (with UID %@), an error of type %i (%s) occurred: %s", @"OK", nil, nil, UID, err, GetMacOSStatusErrorString(err), GetMacOSStatusCommentString(err));
-							[NSApp beginSheet:alert modalForWindow:playerWindow modalDelegate:self didEndSelector:@selector(panelDidEnd:returnCode:contextInfo:) contextInfo:NULL];
-						} else {
-							[devicesPopUp addItemWithTitle:name];
-							NSMenuItem *menuItem = [devicesPopUp lastItem];
-							[menuItem setRepresentedObject:UID];
-
-							//CoreAudio gives us an implicitly-retained CFString.
-							[name release];
-						} //if(err == noErr) (AudioDeviceGetProperty(...kAudioObjectPropertyObjectName...))
-
-						//CoreAudio gives us an implicitly-retained CFString.
-						[UID release];
-					} //if(err == noErr) (AudioDeviceGetProperty(...kAudioDevicePropertyDeviceUID...))
-				} //for(UInt32 deviceIdx = 0U; deviceIdx < numDevices; ++deviceIdx)
-			} //if(err == noErr) (AudioHardwareGetProperty(kAudioHardwarePropertyDevices...))
-		} //if(deviceIDs)
-	} //if(err == noErr) (AudioHardwareGetPropertyInfo(kAudioHardwarePropertyDevices...))
-}
-
-@end

File BZDragAndDropMatrix.m

 }
 
 - (void)draggingExited:(id <NSDraggingInfo>)sender {
-	NSPoint pt = [self convertPoint:[sender draggingLocation] fromView:[[sender draggingDestinationWindow] contentView]];
-	int row, col;
-	[self getRow:&row column:&col forPoint:pt];
-
-	id cell = [self cellAtRow:row column:col];
-	if(cell && [cell respondsToSelector:@selector(draggingEntered:)])
-		[cell draggingEntered:sender];
+	if(lastHoveredCell && [lastHoveredCell respondsToSelector:@selector(draggingExited:)])
+		[lastHoveredCell draggingExited:sender];
 
 	lastHoveredCell = currentHoveredCell = nil;
 }

File BZEventForwardingMatrix.h

 //forwards mouse events to the cell under the mouse.
 //forwards key events to the key cell.
 
-@interface BZEventForwardingMatrix : NSMatrix {
+#import "BZNotifyingMatrix.h"
+
+@interface BZEventForwardingMatrix : BZNotifyingMatrix {
 
 }
 

File BZGeometry.h

+#include <Cocoa/Cocoa.h>
+
+//returns a + b.
+NSSize BZAddSizes(NSSize a, NSSize b);
+
+//returns from - delta.
+NSSize BZSubtractSizes(NSSize from, NSSize delta);
+
+//returns a * b.
+NSSize BZMultiplySizes(NSSize a, NSSize b);

File BZGeometry.m

+#import "BZGeometry.h"
+
+//returns a + b.
+NSSize BZAddSizes(NSSize a, NSSize b) {
+	return (NSSize){
+		a.width  + b.width,
+		a.height + b.height
+	};
+}
+
+//returns from - delta.
+NSSize BZSubtractSizes(NSSize from, NSSize delta) {
+	return (NSSize){
+		from.width  - delta.width,
+		from.height - delta.height
+	};
+}
+
+//returns a * b.
+NSSize BZMultiplySizes(NSSize a, NSSize b) {
+	return (NSSize){
+		a.width  * b.width,
+		a.height * b.height
+	};
+}

File BZMovieButtonCell.h

 @interface BZMovieButtonCell : NSButtonCell <BZClickableCell, BZKeyAcceptingCell> {
 	QTMovie *movie;
 	AudioDevice *device;
+	id <NSObject> notificationObject;
+
+	float volume;
+	NSToolTipTag tooltipTag;
+
+	unsigned reserved: 31;
+	unsigned drawDragHighlight: 1;
 }
 
 - (QTMovie *)movie;
 - (void)setMovie:(QTMovie *)newMovie;
 
+- (AudioDevice *)audioDevice;
+- (void)setAudioDevice:(AudioDevice *)newDevice;
+
+- (float)volume;
+- (void)setVolume:(float)newVol;
+
+//used when listening for notifications. not retained.
+- (id <NSObject>)notificationObject;
+- (void)setNotificationObject:(id <NSObject>)newObj;
+
 @end

File BZMovieButtonCell.m

 		[[NSNotificationCenter defaultCenter] addObserver:self
 												 selector:@selector(selectedDeviceChanged:)
 													 name:SELECTED_DEVICE_CHANGED_NOTIFICATION
-												   object:nil];
+												   object:notificationObject];
+		[[NSNotificationCenter defaultCenter] addObserver:self
+												 selector:@selector(selectedVolumeChanged:)
+													 name:VOLUME_CHANGED_NOTIFICATION
+												   object:notificationObject];
 	}
 	return self;
 }
 		[[NSNotificationCenter defaultCenter] addObserver:self
 												 selector:@selector(selectedDeviceChanged:)
 													 name:SELECTED_DEVICE_CHANGED_NOTIFICATION
-												   object:nil];
+												   object:notificationObject];
+		[[NSNotificationCenter defaultCenter] addObserver:self
+												 selector:@selector(selectedVolumeChanged:)
+													 name:VOLUME_CHANGED_NOTIFICATION
+												   object:notificationObject];
 	}
 	return self;
 }
 		[[NSNotificationCenter defaultCenter] addObserver:self
 												 selector:@selector(selectedDeviceChanged:)
 													 name:SELECTED_DEVICE_CHANGED_NOTIFICATION
-												   object:nil];
+												   object:notificationObject];
+		[[NSNotificationCenter defaultCenter] addObserver:self
+												 selector:@selector(selectedVolumeChanged:)
+													 name:VOLUME_CHANGED_NOTIFICATION
+												   object:notificationObject];
 	}
 	return self;
 }
+//DON'T FORGET to add new notifications in -setNotificationObject: as well!
 
 - (void)dealloc {
-	[[NSNotificationCenter defaultCenter] removeObserver:self
-													name:SELECTED_DEVICE_CHANGED_NOTIFICATION
-												  object:nil];
+	[[NSNotificationCenter defaultCenter] removeObserver:self];
 
 	[super dealloc];
 }
 
-#pragma mark -
+#pragma mark Generating useful info
+
+- (NSString *)tooltip {
+	if(movie) {
+		return [NSString stringWithFormat:@"%@\n%@",
+			[movie attributeForKey:QTMovieDisplayNameAttribute],
+			[movie attributeForKey:QTMovieFileNameAttribute]];
+	} else
+		return nil;
+}
+
+- (NSRect)frame {
+	NSView *view = [self controlView];
+	if([view isKindOfClass:[NSMatrix class]]) {
+		NSMatrix *matrix = (NSMatrix *)view;
+		int row, col;
+		[matrix getRow:&row column:&col ofCell:self];
+		return [matrix cellFrameAtRow:row column:col];
+	} else {
+		return [view frame];
+	}
+}
+
+#pragma mark Accessors
 
 - (QTMovie *)movie {
 	return movie;
 		[movie release];
 		movie = [newMovie retain];
 
+		NSView *view = [self controlView];
+		NSMatrix *matrix = (NSMatrix *)view;
 		if(movie) {
 			[movie setAudioDevice:device];
+			[movie setVolume:volume];
 
-			[self setImage:[[NSWorkspace sharedWorkspace] iconForFile:[movie attributeForKey:QTMovieFileNameAttribute]]];
+			NSString *path = [movie attributeForKey:QTMovieFileNameAttribute];
+			[self setImage:[[NSWorkspace sharedWorkspace] iconForFile:path]];
 			[self setTitle:[movie attributeForKey:QTMovieDisplayNameAttribute]];
+
+			if([view isKindOfClass:[NSMatrix class]]) {
+				int row, col;
+				[matrix getRow:&row column:&col ofCell:self];
+				tooltipTag = [matrix addToolTipRect:[matrix cellFrameAtRow:row column:col]
+											  owner:self
+										   userData:NULL];
+			} else {
+				[view setToolTip:[self tooltip]];
+			}
 		} else {
 			[self setImage:nil];
 			[self setTitle:NSLocalizedString(@"Drop file here", /*comment*/ nil)];
+			if([view isKindOfClass:[NSMatrix class]]) {
+				[matrix removeToolTip:tooltipTag];
+			} else {
+				[view setToolTip:nil];
+			}
+			[self setState:NSOffState];
 		}
 
 		[[self controlView] setNeedsDisplay:YES];
 	}
 }
 
+- (float)volume {
+	return volume;
+}
+- (void)setVolume:(float)newVol {
+	volume = newVol;
+	[movie setVolume:newVol];
+}
+
+- (id <NSObject>)notificationObject {
+	return notificationObject;
+}
+- (void)setNotificationObject:(id <NSObject>)newObj {
+	NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];
+
+	[nc removeObserver:self
+				  name:SELECTED_DEVICE_CHANGED_NOTIFICATION
+				object:notificationObject];
+	[nc removeObserver:self
+				  name:VOLUME_CHANGED_NOTIFICATION
+				object:notificationObject];
+	
+	notificationObject = newObj;
+
+	[nc addObserver:self
+		   selector:@selector(selectedDeviceChanged:)
+			   name:SELECTED_DEVICE_CHANGED_NOTIFICATION
+			 object:notificationObject];
+	[nc addObserver:self
+		   selector:@selector(selectedVolumeChanged:)
+			   name:VOLUME_CHANGED_NOTIFICATION
+			 object:notificationObject];
+}
+
+#pragma mark Drawing
+
+- (void)drawWithFrame:(NSRect)cellFrame inView:(NSView *)controlView {
+	[super drawWithFrame:cellFrame inView:controlView];
+
+	if(drawDragHighlight) {
+		NSColor *color = [[NSColor alternateSelectedControlColor] colorWithAlphaComponent:0.5f];
+		NSRect   frame = [self frame];
+
+		[color set];
+		NSFrameRectWithWidth(frame, 2.0f);
+
+		drawDragHighlight = NO;
+	}
+}
+
 #pragma mark Drag-and-drop
 
 - (NSDragOperation)draggingEntered:(id <NSDraggingInfo>)sender {
 	NSArray *array = [[sender draggingPasteboard] propertyListForType:NSFilenamesPboardType];
+	if(array && ([array count] == 1U)) {
+		drawDragHighlight = YES;
+		[[self controlView] setNeedsDisplayInRect:[self frame]];
+
+		return NSDragOperationLink;
+	} else
+		return NSDragOperationNone;
+}
+- (void)draggingExited:(id <NSDraggingInfo>)sender {
+	NSArray *array = [[sender draggingPasteboard] propertyListForType:NSFilenamesPboardType];
 	if(array && ([array count] == 1U))
-		return NSDragOperationLink;
-	else
-		return NSDragOperationNone;
+		[[self controlView] setNeedsDisplayInRect:[self frame]];
+}
+- (void)concludeDragOperation:(id <NSDraggingInfo>)sender {
+	[[self controlView] setNeedsDisplayInRect:[self frame]];
 }
 
 - (BOOL)performDragOperation:(id <NSDraggingInfo>)sender {
 #pragma mark BZClickableCell conformance
 
 - (void)mouseDown:(NSEvent *)event {
-	[movie setAttribute:[NSNumber numberWithBool:YES] forKey:QTMovieLoopsAttribute];
-
-	[movie setCurrentTime:QTZeroTime];
-
-	if([movie rate] > FLT_EPSILON) {
-		//if the movie is already playing, stop it.
-		[movie stop];
-		[[NSNotificationCenter defaultCenter] removeObserver:self
-														name:QTMovieDidEndNotification
-													  object:movie];
-		[self setState:NSOffState];
-	} else {
-		//if the movie is not playing, start it.
-		[movie play];
-		[[NSNotificationCenter defaultCenter] addObserver:self
-												 selector:@selector(movieDidEnd:)
-													 name:QTMovieDidEndNotification
-												   object:movie];
-		[self setState:NSOnState];
+	NSView *controlView = [self controlView];
+	if([controlView isKindOfClass:[NSMatrix class]]) {
+		NSMatrix *matrix = (NSMatrix *)controlView;
+		[matrix setKeyCell:self];
 	}
 
-	[[self controlView] setNeedsDisplay:YES];
+	if((!event) || !([event modifierFlags] & NSCommandKeyMask)) {
+		[movie setAttribute:[NSNumber numberWithBool:YES] forKey:QTMovieLoopsAttribute];
+
+		[movie setCurrentTime:QTZeroTime];
+
+		if([movie rate] > FLT_EPSILON) {
+			//if the movie is already playing, stop it.
+			[movie stop];
+			[[NSNotificationCenter defaultCenter] removeObserver:self
+															name:QTMovieDidEndNotification
+														  object:movie];
+			[self setState:NSOffState];
+		} else {
+			//if the movie is not playing, start it.
+			[movie play];
+			[[NSNotificationCenter defaultCenter] addObserver:self
+													 selector:@selector(movieDidEnd:)
+														 name:QTMovieDidEndNotification
+													   object:movie];
+			[self setState:NSOnState];
+		}
+
+		[controlView setNeedsDisplay:YES];
+	}
 }
 - (void)mouseUp:(NSEvent *)event {
-	[movie setAttribute:[NSNumber numberWithBool:NO] forKey:QTMovieLoopsAttribute];
+	if(event && ([event modifierFlags] & NSCommandKeyMask)) {
+		//cmd-click reveals the file.
+		NSString *filename = [movie attributeForKey:QTMovieFileNameAttribute];
+		if(filename) {
+			[[NSWorkspace sharedWorkspace] selectFile:filename
+							 inFileViewerRootedAtPath:[filename stringByDeletingLastPathComponent]];
+		}
+	} else 
+		[movie setAttribute:[NSNumber numberWithBool:NO] forKey:QTMovieLoopsAttribute];
 }
 
 - (void)performClick:sender {
 				[self setMovie:nil];
 
 				//show a poof.
-				NSRect frame;
+				NSRect frame = [self frame];
 				NSView *view = [self controlView];
-				if([view isKindOfClass:[NSMatrix class]]) {
-					NSMatrix *matrix = (NSMatrix *)view;
-					int row, col;
-					[matrix getRow:&row column:&col ofCell:self];
-					frame = [matrix cellFrameAtRow:row column:col];
-				} else {
-					frame = [view frame];
-				}
 
 				NSPoint centerPoint = {
 					frame.origin.x + frame.size.width  * 0.5f,
 	return NO;
 }
 
+#pragma mark NSToolTipOwner
+
+//the tooltip for a cell is its path.
+- (NSString *)view:(NSView *)view stringForToolTip:(NSToolTipTag)tag point:(NSPoint)point userData:(void *)userData {
+	return [self tooltip];
+}
+
 #pragma mark Notifications
 
 - (void)movieDidEnd:(NSNotification *)notification {
 - (void)selectedDeviceChanged:(NSNotification *)notification {
 	[self setAudioDevice:[[notification userInfo] objectForKey:SELECTED_DEVICE_AUDIODEVICE]];
 }
+- (void)selectedVolumeChanged:(NSNotification *)notification {
+	[self setVolume:[[[notification userInfo] objectForKey:NEW_VOLUME] floatValue]];
+}
 
 @end
 

File BZNotifyingMatrix.h

+//
+//  BZNotifyingMatrix.h
+//  BZSoundboard
+//
+//  Created by Mac-arena the Bored Zo on 2006-01-26.
+//  Copyright 2006 Mac-arena the Bored Zo. All rights reserved.
+//
+
+#import <Cocoa/Cocoa.h>
+
+extern NSString *BZNotifyingMatrixWillAddCellNotification;
+extern NSString *BZNotifyingMatrixDidAddCellNotification;
+
+//userInfo keys:
+extern NSString *BZNotifyingMatrix_ColumnIndex; //NSNumber
+extern NSString *BZNotifyingMatrix_RowIndex; //NSNumber
+extern NSString *BZNotifyingMatrix_NewCell; //NSCell (only exists in DidAddCell)
+
+@interface BZNotifyingMatrix : NSMatrix {
+
+}
+
+@end

File BZNotifyingMatrix.m

+//
+//  BZNotifyingMatrix.m
+//  BZSoundboard
+//
+//  Created by Mac-arena the Bored Zo on 2006-01-26.
+//  Copyright 2006 Mac-arena the Bored Zo. All rights reserved.
+//
+
+#import "BZNotifyingMatrix.h"
+
+NSString *BZNotifyingMatrixWillAddCellNotification = @"BZNotifyingMatrixWillAddCellNotification";
+NSString *BZNotifyingMatrixDidAddCellNotification  = @"BZNotifyingMatrixDidAddCellNotification";
+
+//userInfo keys:
+NSString *BZNotifyingMatrix_ColumnIndex = @"BZNotifyingMatrix_ColumnIndex"; //NSNumber
+NSString *BZNotifyingMatrix_RowIndex = @"BZNotifyingMatrix_RowIndex"; //NSNumber
+NSString *BZNotifyingMatrix_NewCell = @"BZNotifyingMatrix_NewCell"; //NSCell (only exists in DidAddCell)
+
+@implementation BZNotifyingMatrix
+
+- (NSCell *)makeCellAtRow:(int)row column:(int)col {
+	NSMutableDictionary *willAddCellUserInfo = [[NSMutableDictionary alloc] initWithCapacity:3U];
+	NSNumber *num = [[NSNumber alloc] initWithInt:row];
+	[willAddCellUserInfo setObject:num forKey:BZNotifyingMatrix_RowIndex];
+	[num release];
+	num = [[NSNumber alloc] initWithInt:col];
+	[willAddCellUserInfo setObject:num forKey:BZNotifyingMatrix_ColumnIndex];
+	[num release];
+
+	NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];
+	[nc postNotificationName:BZNotifyingMatrixWillAddCellNotification
+					  object:self
+					userInfo:willAddCellUserInfo];
+
+	NSCell *cell = [super makeCellAtRow:row column:col];
+
+	NSMutableDictionary *didAddCellUserInfo = [willAddCellUserInfo mutableCopy];
+	[willAddCellUserInfo release];
+	[didAddCellUserInfo setObject:cell forKey:BZNotifyingMatrix_NewCell];
+
+	[nc postNotificationName:BZNotifyingMatrixDidAddCellNotification
+					  object:self
+					userInfo:didAddCellUserInfo];
+	[didAddCellUserInfo release];
+
+	return cell;
+}
+
+@end

File BZResizeNotifyingWindow.h

+//
+//  BZResizeNotifyingWindow.h
+//  BZSoundboard
+//
+//  Created by Mac-arena the Bored Zo on 2006-01-25.
+//  Copyright 2006 Mac-arena the Bored Zo. All rights reserved.
+//
+
+#import <Cocoa/Cocoa.h>
+
+extern NSString *BZWindowLiveResizeWillBegin;
+extern NSString *BZWindowLiveResizeDidBegin;
+extern NSString *BZWindowLiveResizeWillEnd;
+extern NSString *BZWindowLiveResizeDidEnd;
+
+@interface BZResizeNotifyingWindow : NSWindow {
+
+}
+
+@end

File BZResizeNotifyingWindow.m

+//
+//  BZResizeNotifyingWindow.m
+//  BZSoundboard
+//
+//  Created by Mac-arena the Bored Zo on 2006-01-25.
+//  Copyright 2006 Mac-arena the Bored Zo. All rights reserved.
+//
+
+#import "BZResizeNotifyingWindow.h"
+
+NSString *BZWindowLiveResizeWillBegin = @"BZWindowLiveResizeWillBegin";
+NSString *BZWindowLiveResizeDidBegin  = @"BZWindowLiveResizeDidBegin";
+NSString *BZWindowLiveResizeWillEnd   = @"BZWindowLiveResizeWillEnd";
+NSString *BZWindowLiveResizeDidEnd    = @"BZWindowLiveResizeDidEnd";
+
+@interface NSWindow (BZResizeNotifyingWindow_UndocumentedGoodness)
+- (void)_startLiveResize;
+- (void)_endLiveResize;
+@end
+
+@implementation BZResizeNotifyingWindow
+
+- (void)_startLiveResize {
+	NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];
+	[nc postNotificationName:BZWindowLiveResizeWillBegin
+					  object:self];
+
+	[super _startLiveResize];
+
+	[nc postNotificationName:BZWindowLiveResizeDidBegin
+					  object:self];
+}
+- (void)_endLiveResize {
+	NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];
+	[nc postNotificationName:BZWindowLiveResizeWillEnd
+					  object:self];
+
+	[super _endLiveResize];
+
+	[nc postNotificationName:BZWindowLiveResizeDidEnd
+					  object:self];
+}
+
+@end

File BZSoundboard.xcodeproj/boredzo.mode2

 			<key>Content</key>
 			<dict>
 				<key>PBXProjectModuleGUID</key>
-				<string>072B2EFC0984CCDF00C0DDD1</string>
+				<string>0795B84209822895002412FE</string>
 				<key>PBXProjectModuleLabel</key>
-				<string>CFURLAdditions.c</string>
+				<string>SBDocument.m</string>
 				<key>PBXSplitModuleInNavigatorKey</key>
 				<dict>
 					<key>Split0</key>
 					<dict>
 						<key>PBXProjectModuleGUID</key>
-						<string>072B2EFD0984CCDF00C0DDD1</string>
+						<string>0795B84309822895002412FE</string>
 						<key>PBXProjectModuleLabel</key>
-						<string>CFURLAdditions.c</string>
+						<string>SBDocument.m</string>
 						<key>_historyCapacity</key>
 						<integer>0</integer>
 						<key>bookmark</key>
-						<string>072B2F010984CCDF00C0DDD1</string>
+						<string>0775F93D098E38F800812F08</string>
 						<key>history</key>
 						<array>
-							<string>072B2EFE0984CCDF00C0DDD1</string>
-							<string>072B2EFF0984CCDF00C0DDD1</string>
+							<string>07EC03AA098D12510037BF4C</string>
+							<string>0775F92B098E1A3D00812F08</string>
 						</array>
 						<key>prevStack</key>
 						<array>
-							<string>072B2F000984CCDF00C0DDD1</string>
+							<string>07EC03AC098D12510037BF4C</string>
 						</array>
 					</dict>
 					<key>SplitCount</key>
 			<key>Geometry</key>
 			<dict>
 				<key>Frame</key>
-				<string>{{0, 20}, {731, 460}}</string>
+				<string>{{0, 20}, {722, 866}}</string>
 				<key>PBXModuleWindowStatusBarHidden2</key>
 				<false/>
 				<key>RubberWindowFrame</key>
-				<string>38 475 731 501 0 0 1280 1002 </string>
-			</dict>
-		</dict>
-		<dict>
-			<key>Content</key>
-			<dict>
-				<key>PBXProjectModuleGUID</key>
-				<string>072B2F020984CCDF00C0DDD1</string>
-				<key>PBXProjectModuleLabel</key>
-				<string>CFNumber.h</string>
-				<key>PBXSplitModuleInNavigatorKey</key>
-				<dict>
-					<key>Split0</key>
-					<dict>
-						<key>PBXProjectModuleGUID</key>
-						<string>072B2F030984CCDF00C0DDD1</string>
-						<key>PBXProjectModuleLabel</key>
-						<string>CFNumber.h</string>
-						<key>_historyCapacity</key>
-						<integer>0</integer>
-						<key>bookmark</key>
-						<string>072B2F060984CCDF00C0DDD1</string>
-						<key>history</key>
-						<array>
-							<string>072B2F040984CCDF00C0DDD1</string>
-						</array>
-					</dict>
-					<key>SplitCount</key>
-					<string>1</string>
-				</dict>
-				<key>StatusBarVisibility</key>
-				<true/>
-			</dict>
-			<key>Geometry</key>
-			<dict>
-				<key>Frame</key>
-				<string>{{0, 20}, {737, 517}}</string>
-				<key>PBXModuleWindowStatusBarHidden2</key>
-				<false/>
-				<key>RubberWindowFrame</key>
-				<string>222 250 737 558 0 0 1280 1002 </string>
+				<string>178 95 722 907 0 0 1280 1002 </string>
 			</dict>
 		</dict>
 		<dict>
 						<key>_historyCapacity</key>
 						<integer>0</integer>
 						<key>bookmark</key>
-						<string>072B2F080984CCDF00C0DDD1</string>
+						<string>0775F93E098E38F800812F08</string>
 						<key>history</key>
 						<array>
-							<string>072B2E740984B89700C0DDD1</string>
-							<string>072B2E750984B89700C0DDD1</string>
+							<string>07A79A1C098A036F000CEE96</string>
+							<string>0775F92C098E1A3D00812F08</string>
+						</array>
+						<key>nextStack</key>
+						<array>
+							<string>072BE7A50989720900E0AE13</string>
 						</array>
 						<key>prevStack</key>
 						<array>
-							<string>072B2E760984B89700C0DDD1</string>
+							<string>07A79A1E098A036F000CEE96</string>
 						</array>
 					</dict>
 					<key>SplitCount</key>
 				<string>205 444 737 558 0 0 1280 1002 </string>
 			</dict>
 		</dict>
-		<dict>
-			<key>Content</key>
-			<dict>
-				<key>PBXProjectModuleGUID</key>
-				<string>0795B84209822895002412FE</string>
-				<key>PBXProjectModuleLabel</key>
-				<string>AudioPlayer.m</string>
-				<key>PBXSplitModuleInNavigatorKey</key>
-				<dict>
-					<key>Split0</key>
-					<dict>
-						<key>PBXProjectModuleGUID</key>
-						<string>0795B84309822895002412FE</string>
-						<key>PBXProjectModuleLabel</key>
-						<string>AudioPlayer.m</string>
-						<key>_historyCapacity</key>
-						<integer>0</integer>
-						<key>bookmark</key>
-						<string>072B2F090984CCDF00C0DDD1</string>
-						<key>history</key>
-						<array>
-							<string>0795B91B0982416E002412FE</string>
-							<string>072B2E0B0984B1EF00C0DDD1</string>
-						</array>
-						<key>prevStack</key>
-						<array>
-							<string>0795B91C0982416E002412FE</string>
-						</array>
-					</dict>
-					<key>SplitCount</key>
-					<string>1</string>
-				</dict>
-				<key>StatusBarVisibility</key>
-				<true/>
-			</dict>
-			<key>Geometry</key>
-			<dict>
-				<key>Frame</key>
-				<string>{{0, 20}, {731, 460}}</string>
-				<key>PBXModuleWindowStatusBarHidden2</key>
-				<false/>
-				<key>RubberWindowFrame</key>
-				<string>15 496 731 501 0 0 1280 1002 </string>
-			</dict>
-		</dict>
-		<dict>
-			<key>Content</key>
-			<dict>
-				<key>PBXProjectModuleGUID</key>
-				<string>072B2EAF0984BB1C00C0DDD1</string>
-				<key>PBXProjectModuleLabel</key>
-				<string>NSCell.h</string>
-				<key>PBXSplitModuleInNavigatorKey</key>
-				<dict>
-					<key>Split0</key>
-					<dict>
-						<key>PBXProjectModuleGUID</key>
-						<string>072B2EB00984BB1C00C0DDD1</string>
-						<key>PBXProjectModuleLabel</key>
-						<string>NSCell.h</string>
-						<key>_historyCapacity</key>
-						<integer>0</integer>
-						<key>bookmark</key>
-						<string>072B2F0A0984CCDF00C0DDD1</string>
-						<key>history</key>
-						<array>
-							<string>072B2EB10984BB1C00C0DDD1</string>
-						</array>
-					</dict>
-					<key>SplitCount</key>
-					<string>1</string>
-				</dict>
-				<key>StatusBarVisibility</key>
-				<true/>
-			</dict>
-			<key>Geometry</key>
-			<dict>
-				<key>Frame</key>
-				<string>{{0, 20}, {737, 517}}</string>
-				<key>PBXModuleWindowStatusBarHidden2</key>
-				<false/>
-				<key>RubberWindowFrame</key>
-				<string>199 271 737 558 0 0 1280 1002 </string>
-			</dict>
-		</dict>
-		<dict>
-			<key>Content</key>
-			<dict>
-				<key>PBXProjectModuleGUID</key>
-				<string>072B2E200984B2B200C0DDD1</string>
-				<key>PBXProjectModuleLabel</key>
-				<string>QTMovie+AudioDevice.m</string>
-				<key>PBXSplitModuleInNavigatorKey</key>
-				<dict>
-					<key>Split0</key>
-					<dict>
-						<key>PBXProjectModuleGUID</key>
-						<string>072B2E210984B2B200C0DDD1</string>
-						<key>PBXProjectModuleLabel</key>
-						<string>QTMovie+AudioDevice.m</string>
-						<key>_historyCapacity</key>
-						<integer>0</integer>
-						<key>bookmark</key>
-						<string>072B2F0B0984CCDF00C0DDD1</string>
-						<key>history</key>
-						<array>
-							<string>072B2E220984B2B200C0DDD1</string>
-							<string>072B2E230984B2B200C0DDD1</string>
-						</array>
-						<key>prevStack</key>
-						<array>
-							<string>072B2E240984B2B200C0DDD1</string>
-						</array>
-					</dict>
-					<key>SplitCount</key>
-					<string>1</string>
-				</dict>
-				<key>StatusBarVisibility</key>
-				<true/>
-			</dict>
-			<key>Geometry</key>
-			<dict>
-				<key>Frame</key>
-				<string>{{0, 20}, {737, 517}}</string>
-				<key>PBXModuleWindowStatusBarHidden2</key>
-				<false/>
-				<key>RubberWindowFrame</key>
-				<string>153 313 737 558 0 0 1280 1002 </string>
-			</dict>
-		</dict>
-		<dict>
-			<key>Content</key>
-			<dict>
-				<key>PBXProjectModuleGUID</key>
-				<string>072B2E270984B2B200C0DDD1</string>
-				<key>PBXProjectModuleLabel</key>
-				<string>AudioDevice.m</string>
-				<key>PBXSplitModuleInNavigatorKey</key>
-				<dict>
-					<key>Split0</key>
-					<dict>
-						<key>PBXProjectModuleGUID</key>
-						<string>072B2E280984B2B200C0DDD1</string>
-						<key>PBXProjectModuleLabel</key>
-						<string>AudioDevice.m</string>
-						<key>_historyCapacity</key>
-						<integer>0</integer>
-						<key>bookmark</key>
-						<string>072B2F0C0984CCDF00C0DDD1</string>
-						<key>history</key>
-						<array>
-							<string>072B2E290984B2B200C0DDD1</string>
-							<string>072B2E460984B3C000C0DDD1</string>
-						</array>
-						<key>prevStack</key>
-						<array>
-							<string>072B2E2B0984B2B200C0DDD1</string>
-						</array>
-					</dict>
-					<key>SplitCount</key>
-					<string>1</string>
-				</dict>
-				<key>StatusBarVisibility</key>
-				<true/>
-			</dict>
-			<key>Geometry</key>
-			<dict>
-				<key>Frame</key>
-				<string>{{0, 20}, {737, 517}}</string>
-				<key>PBXModuleWindowStatusBarHidden2</key>
-				<false/>
-				<key>RubberWindowFrame</key>
-				<string>226 126 737 558 0 0 1280 1002 </string>
-			</dict>
-		</dict>
-		<dict>
-			<key>Content</key>
-			<dict>
-				<key>PBXProjectModuleGUID</key>
-				<string>0795B84709822895002412FE</string>
-				<key>PBXProjectModuleLabel</key>
-				<string>BZEventForwardingMatrix.m</string>
-				<key>PBXSplitModuleInNavigatorKey</key>
-				<dict>
-					<key>Split0</key>
-					<dict>
-						<key>PBXProjectModuleGUID</key>
-						<string>0795B84809822895002412FE</string>
-						<key>PBXProjectModuleLabel</key>
-						<string>BZEventForwardingMatrix.m</string>
-						<key>_historyCapacity</key>
-						<integer>0</integer>
-						<key>bookmark</key>
-						<string>072B2F0D0984CCDF00C0DDD1</string>
-						<key>history</key>
-						<array>
-							<string>072866A30983740F00C9C0E4</string>
-							<string>072868370983AA3B00C9C0E4</string>
-						</array>
-						<key>prevStack</key>
-						<array>
-							<string>072866A50983740F00C9C0E4</string>
-						</array>
-					</dict>
-					<key>SplitCount</key>
-					<string>1</string>
-				</dict>
-				<key>StatusBarVisibility</key>
-				<true/>
-			</dict>
-			<key>Geometry</key>
-			<dict>
-				<key>Frame</key>
-				<string>{{0, 20}, {737, 517}}</string>
-				<key>PBXModuleWindowStatusBarHidden2</key>
-				<false/>
-				<key>RubberWindowFrame</key>
-				<string>38 418 737 558 0 0 1280 1002 </string>
-			</dict>
-		</dict>
-		<dict>
-			<key>Content</key>
-			<dict>
-				<key>PBXProjectModuleGUID</key>
-				<string>0795B93E09824A0D002412FE</string>
-				<key>PBXProjectModuleLabel</key>
-				<string>BZDragAndDropMatrix.m</string>
-				<key>PBXSplitModuleInNavigatorKey</key>
-				<dict>
-					<key>Split0</key>
-					<dict>
-						<key>PBXProjectModuleGUID</key>
-						<string>0795B93F09824A0D002412FE</string>
-						<key>PBXProjectModuleLabel</key>
-						<string>BZDragAndDropMatrix.m</string>
-						<key>_historyCapacity</key>
-						<integer>0</integer>
-						<key>bookmark</key>
-						<string>072B2F0E0984CCDF00C0DDD1</string>
-						<key>history</key>
-						<array>
-							<string>0795B9EB09825660002412FE</string>
-							<string>0728683A0983AA3B00C9C0E4</string>
-						</array>
-						<key>prevStack</key>
-						<array>
-							<string>0795B9ED09825660002412FE</string>
-						</array>
-					</dict>
-					<key>SplitCount</key>
-					<string>1</string>
-				</dict>
-				<key>StatusBarVisibility</key>
-				<true/>
-			</dict>
-			<key>Geometry</key>
-			<dict>
-				<key>Frame</key>
-				<string>{{0, 20}, {737, 517}}</string>
-				<key>PBXModuleWindowStatusBarHidden2</key>
-				<false/>
-				<key>RubberWindowFrame</key>
-				<string>199 271 737 558 0 0 1280 1002 </string>
-			</dict>
-		</dict>
 	</array>
 	<key>PerspectiveWidths</key>
 	<array>
 					<key>Tabs</key>
 					<array>
 						<dict>
+							<key>BecomeActive</key>
+							<true/>
 							<key>ContentConfiguration</key>
 							<dict>
 								<key>PBXBottomSmartGroupGIDs</key>
 									<array>
 										<string>29B97314FDCFA39411CA2CEA</string>
 										<string>080E96DDFE201D6D7F000001</string>
-										<string>0747C034092B4FE9002A2C63</string>
-										<string>29B97315FDCFA39411CA2CEA</string>
+										<string>072B2E0E0984B22300C0DDD1</string>
+										<string>0795B92C09824217002412FE</string>
+										<string>29B97317FDCFA39411CA2CEA</string>
 										<string>29B97323FDCFA39411CA2CEA</string>
+										<string>1058C7A0FEA54F0111CA2CBB</string>
 										<string>19C28FACFE9D520D11CA2CBB</string>
 									</array>
 									<key>PBXSmartGroupTreeModuleOutlineStateSelectionKey</key>
 									<array>
 										<array>
-											<integer>12</integer>
-											<integer>9</integer>
+											<integer>49</integer>
+											<integer>48</integer>
 											<integer>0</integer>
 										</array>
 									</array>
 									<key>PBXSmartGroupTreeModuleOutlineStateVisibleRectKey</key>
-									<string>{{0, 0}, {350, 334}}</string>
+									<string>{{0, 516}, {349, 334}}</string>
 								</dict>
 								<key>PBXTopSmartGroupGIDs</key>
 								<array/>
 									<string>WarningsColumn</string>
 									<real>43</real>
 								</array>
+								<key>RubberWindowFrame</key>
+								<string>858 508 350 420 0 0 1280 1002 </string>
 							</dict>
 							<key>Module</key>
 							<string>PBXSmartGroupTreeModule</string>
 						</dict>
 						<dict>
-							<key>BecomeActive</key>
-							<true/>
 							<key>ContentConfiguration</key>
 							<dict>
 								<key>PBXBottomSmartGroupGIDs</key>
 									<key>PBXSmartGroupTreeModuleOutlineStateSelectionKey</key>
 									<array>
 										<array>
+											<integer>1</integer>
 											<integer>0</integer>
 										</array>
 									</array>
 									<key>PBXSmartGroupTreeModuleOutlineStateVisibleRectKey</key>
-									<string>{{0, 0}, {349, 334}}</string>
+									<string>{{0, 0}, {350, 334}}</string>
 								</dict>
 								<key>PBXTopSmartGroupGIDs</key>
 								<array/>
 									<string>MainColumn</string>
 									<real>350</real>
 								</array>
-								<key>RubberWindowFrame</key>
-								<string>928 577 350 420 0 0 1280 1002 </string>
 							</dict>
 							<key>Module</key>
 							<string>PBXSmartGroupTreeModule</string>
 								<dict>
 									<key>PBXSmartGroupTreeModuleColumnWidthsKey</key>
 									<array>
-										<real>555</real>
+										<real>350</real>
 									</array>
 									<key>PBXSmartGroupTreeModuleColumnsKey_v4</key>
 									<array>
 										</array>
 									</array>
 									<key>PBXSmartGroupTreeModuleOutlineStateVisibleRectKey</key>
-									<string>{{0, 0}, {555, 301}}</string>
+									<string>{{0, 0}, {350, 334}}</string>
 								</dict>
 								<key>PBXTopSmartGroupGIDs</key>
 								<array/>
 							<key>GeometryConfiguration</key>
 							<dict>
 								<key>Frame</key>
-								<string>{{0, 0}, {572, 319}}</string>
+								<string>{{10, 27}, {367, 352}}</string>
 								<key>GroupTreeTableConfiguration</key>
 								<array>
 									<string>MainColumn</string>
-									<real>555</real>
+									<real>350</real>
 								</array>
 							</dict>
 							<key>Module</key>
 			</array>
 			<key>TableOfContents</key>
 			<array>
-				<string>072B2DCE0984AA3100C0DDD1</string>
-				<string>072B2DCF0984AA3100C0DDD1</string>
+				<string>0775F931098E353B00812F08</string>
+				<string>0775F932098E353B00812F08</string>
 				<string>1C9437FD063B20B00039CFAC</string>
 				<string>1C9437FE063B20B00039CFAC</string>
 				<string>1C9437FF063B20B00039CFAC</string>
 	<key>StatusbarIsVisible</key>
 	<true/>
 	<key>TimeStamp</key>
-	<real>159698143.77197999</real>
+	<real>160315640.85655501</real>
 	<key>ToolbarDisplayMode</key>
 	<integer>3</integer>
 	<key>ToolbarIsVisible</key>
 	<integer>0</integer>
 	<key>WindowOrderList</key>
 	<array>
-		<string>072B2E5E0984B40000C0DDD1</string>
-		<string>072B2E5F0984B40000C0DDD1</string>
-		<string>1C530D5B069F1CE1000CFCEE</string>
-		<string>1C530D54069F1CE1000CFCEE</string>
-		<string>072B2DBF0984A76600C0DDD1</string>
-		<string>0795B93E09824A0D002412FE</string>
-		<string>0795B84709822895002412FE</string>
-		<string>072B2E270984B2B200C0DDD1</string>
-		<string>072B2E200984B2B200C0DDD1</string>
-		<string>072B2EAF0984BB1C00C0DDD1</string>
+		<string>1C0AD2B3069F1EA900FABCE6</string>
+		<string>0795B83C09822895002412FE</string>
 		<string>0795B84209822895002412FE</string>
-		<string>0795B83C09822895002412FE</string>
-		<string>072B2F020984CCDF00C0DDD1</string>
-		<string>072B2EFC0984CCDF00C0DDD1</string>
-		<string>1C0AD2B3069F1EA900FABCE6</string>
 		<string>/Users/boredzo/Projects/BZSoundboard/BZSoundboard.xcodeproj</string>
 		<string>072CCCDF092F2680001B6CAD</string>
 	</array>
 	<key>WindowString</key>
-	<string>928 577 350 420 0 0 1280 1002 </string>
+	<string>858 508 350 420 0 0 1280 1002 </string>
 	<key>WindowTools</key>
 	<array>
 		<dict>
 							<key>ContentConfiguration</key>
 							<dict>
 								<key>PBXBuildLogShowsTranscriptDefaultKey</key>
-								<string>{{0, 271}, {727, 126}}</string>
+								<string>{{0, 240}, {727, 157}}</string>
 								<key>PBXProjectModuleGUID</key>
 								<string>XCMainBuildResultsModuleGUID</string>
 								<key>PBXProjectModuleLabel</key>
 			<key>TableOfContents</key>
 			<array>
 				<string>072CCCDF092F2680001B6CAD</string>
-				<string>072B2E2F0984B2B200C0DDD1</string>
+				<string>0775F93C098E357400812F08</string>
 				<string>1CD0528F0623707200166675</string>
 				<string>XCMainBuildResultsModuleGUID</string>
 			</array>
 										<string>yes</string>
 										<key>sizes</key>
 										<array>
-											<string>{{0, 0}, {315, 163}}</string>
-											<string>{{315, 0}, {402, 163}}</string>
+											<string>{{0, 0}, {379, 707}}</string>
+											<string>{{379, 0}, {351, 707}}</string>
 										</array>
 									</dict>
 									<key>VerticalSplitView</key>
 										<string>yes</string>
 										<key>sizes</key>
 										<array>
-											<string>{{0, 0}, {717, 163}}</string>
-											<string>{{0, 163}, {717, 233}}</string>
+											<string>{{0, 0}, {730, 707}}</string>
+											<string>{{0, 707}, {730, 0}}</string>
 										</array>
 									</dict>
 								</dict>
 								<key>DebugSTDIOWindowFrame</key>
 								<string>{{200, 200}, {500, 300}}</string>
 								<key>Frame</key>
-								<string>{{0, 0}, {717, 396}}</string>
+								<string>{{0, 0}, {730, 707}}</string>
 								<key>RubberWindowFrame</key>
-								<string>180 531 717 437 0 0 1280 1002 </string>
+								<string>505 147 730 748 0 0 1280 1002 </string>
 							</dict>
 							<key>Module</key>
 							<string>PBXDebugSessionModule</string>
 							<key>Proportion</key>
-							<string>396pt</string>
+							<string>707pt</string>
 						</dict>
 					</array>
 					<key>Proportion</key>
-					<string>396pt</string>
+					<string>707pt</string>
 				</dict>
 			</array>
 			<key>Name</key>
 			<key>TableOfContents</key>
 			<array>
 				<string>1C530D54069F1CE1000CFCEE</string>
-				<string>072B2DB90984A76600C0DDD1</string>
+				<string>0775F8EF098DFCF600812F08</string>
 				<string>1C162984064C10D400B95A72</string>
-				<string>072B2DBA0984A76600C0DDD1</string>
-				<string>072B2DBB0984A76600C0DDD1</string>
-				<string>072B2DBC0984A76600C0DDD1</string>
-				<string>072B2DBD0984A76600C0DDD1</string>
-				<string>072B2DBE0984A76600C0DDD1</string>
-				<string>072B2DBF0984A76600C0DDD1</string>
+				<string>0775F8F0098DFCF600812F08</string>
+				<string>0775F8F1098DFCF600812F08</string>
+				<string>0775F8F2098DFCF600812F08</string>
+				<string>0775F8F3098DFCF600812F08</string>
+				<string>0775F8F4098DFCF600812F08</string>
+				<string>0775F8F5098DFCF600812F08</string>
 			</array>
 			<key>ToolbarConfiguration</key>
 			<string>xcode.toolbar.config.debug</string>
 			<key>WindowString</key>
-			<string>180 531 717 437 0 0 1280 1002 </string>
+			<string>505 147 730 748 0 0 1280 1002 </string>
 			<key>WindowToolGUID</key>
 			<string>1C530D54069F1CE1000CFCEE</string>
 			<key>WindowToolIsVisible</key>
 					<key>Dock</key>
 					<array>
 						<dict>
+							<key>BecomeActive</key>
+							<true/>
 							<key>ContentConfiguration</key>
 							<dict>
 								<key>PBXProjectModuleGUID</key>
 			<key>TableOfContents</key>
 			<array>
 				<string>1C530D5B069F1CE1000CFCEE</string>
-				<string>072B2E5D0984B40000C0DDD1</string>
+				<string>0775F901098DFD2600812F08</string>
 				<string>1C78EAAC065D492600B07095</string>
 			</array>
 			<key>WindowString</key>
 			<key>WindowToolGUID</key>
 			<string>1C530D5B069F1CE1000CFCEE</string>
 			<key>WindowToolIsVisible</key>
-			<false/>
+			<true/>
 		</dict>
 		<dict>
 			<key>FirstTimeWindowDisplayed</key>
 										<string>yes</string>
 										<key>sizes</key>
 										<array>
-											<string>{{0, 0}, {366, 168}}</string>
-											<string>{{0, 173}, {366, 270}}</string>
+											<string>{{0, 0}, {491, 168}}</string>
+											<string>{{0, 173}, {491, 270}}</string>
 										</array>
 									</dict>
 									<key>VerticalSplitView</key>
 								<key>Frame</key>
 								<string>{{0, 0}, {459, 159}}</string>
 								<key>RubberWindowFrame</key>
-								<string>166 98 459 200 0 0 1280 1002 </string>
+								<string>795 101 459 200 0 0 1280 1002 </string>
 							</dict>
 							<key>Module</key>
 							<string>PBXRunSessionModule</string>
 			<key>TableOfContents</key>
 			<array>
 				<string>1C0AD2B3069F1EA900FABCE6</string>
-				<string>072B2DC00984A76600C0DDD1</string>
+				<string>0775F935098E353B00812F08</string>
 				<string>1CD0528B0623707200166675</string>
-				<string>072B2DC10984A76600C0DDD1</string>
+				<string>0775F936098E353B00812F08</string>
 			</array>
 			<key>ToolbarConfiguration</key>
 			<string>xcode.toolbar.config.run</string>
 			<key>WindowString</key>
-			<string>166 98 459 200 0 0 1280 1002 </string>
+			<string>795 101 459 200 0 0 1280 1002 </string>
 			<key>WindowToolGUID</key>
 			<string>1C0AD2B3069F1EA900FABCE6</string>
 			<key>WindowToolIsVisible</key>
 			<string>743 379 452 308 0 0 1280 1002 </string>
 		</dict>
 		<dict>
+			<key>FirstTimeWindowDisplayed</key>
+			<false/>
 			<key>Identifier</key>
 			<string>windowTool.breakpoints</string>
 			<key>IsVertical</key>
-			<integer>0</integer>
+			<false/>
 			<key>Layout</key>
 			<array>
 				<dict>
 					<key>Dock</key>
 					<array>
 						<dict>
-							<key>BecomeActive</key>
-							<integer>1</integer>
 							<key>ContentConfiguration</key>
 							<dict>
 								<key>PBXBottomSmartGroupGIDs</key>
 								<key>PBXTopSmartGroupGIDs</key>
 								<array/>
 								<key>XCIncludePerspectivesSwitch</key>
-								<integer>0</integer>
+								<false/>
 							</dict>
 							<key>GeometryConfiguration</key>
 							<dict>
 									<real>168</real>
 								</array>
 								<key>RubberWindowFrame</key>
-								<string>315 424 744 409 0 0 1440 878 </string>
+								<string>201 536 744 409 0 0 1280 1002 </string>
 							</dict>
 							<key>Module</key>
 							<string>PBXSmartGroupTreeModule</string>
 								<key>Frame</key>
 								<string>{{190, 0}, {554, 368}}</string>
 								<key>RubberWindowFrame</key>
-								<string>315 424 744 409 0 0 1440 878 </string>
+								<string>201 536 744 409 0 0 1280 1002 </string>
 							</dict>
 							<key>Module</key>
 							<string>XCDetailModule</string>
 				<string>XCDetailModule</string>
 			</array>
 			<key>StatusbarIsVisible</key>
-			<integer>1</integer>
+			<true/>
 			<key>TableOfContents</key>
 			<array>
-				<string>1CDDB66807F98D9800BB5817</string>
-				<string>1CDDB66907F98D9800BB5817</string>
+				<string>07A9FFFF098A6C72009C114D</string>
+				<string>07A90000098A6C72009C114D</string>
 				<string>1CE0B1FE06471DED0097A5F4</string>
 				<string>1CA1AED706398EBD00589147</string>
 			</array>
 			<key>ToolbarConfiguration</key>
 			<string>xcode.toolbar.config.breakpoints</string>
 			<key>WindowString</key>
-			<string>315 424 744 409 0 0 1440 878 </string>
+			<string>201 536 744 409 0 0 1280 1002 </string>
 			<key>WindowToolGUID</key>
-			<string>1CDDB66807F98D9800BB5817</string>
+			<string>07A9FFFF098A6C72009C114D</string>
 			<key>WindowToolIsVisible</key>
-			<integer>1</integer>
+			<true/>
 		</dict>
 		<dict>
 			<key>Identifier</key>
 			<key>TableOfContents</key>
 			<array>
 				<string>073BC5F2092DB55F0016AF6D</string>
-				<string>073BC5F3092DB55F0016AF6D</string>
+				<string>07EF03940987CED6002DC899</string>
 				<string>073BC5F1092DB55F0016AF6D</string>
 			</array>
 			<key>WindowString</key>

File BZSoundboard.xcodeproj/boredzo.pbxuser

 // !$*UTF8*$!
 {
-	07021AB00982662B0074A648 /* PBXTextBookmark */ = {
-		isa = PBXTextBookmark;
-		fRef = 0795B92E09824249002412FE /* BZDragAndDropMatrix.m */;
-		name = "BZDragAndDropMatrix.m: 47";
-		rLen = 0;
-		rLoc = 1678;
-		rType = 0;
-		vrLen = 1789;
-		vrLoc = 263;
+	070DDD01098B7EF700B72372 /* BZGeometry.h */ = {
+		uiCtxt = {
+			sepNavIntBoundsRect = "{{0, 0}, {677, 849}}";
+			sepNavSelRange = "{158, 60}";
+			sepNavVisRect = "{{0, 0}, {677, 849}}";
+			sepNavWindowFrame = "{{15, 70}, {722, 927}}";
+		};
 	};
-	07021AB30982662B0074A648 /* PBXTextBookmark */ = {
-		isa = PBXTextBookmark;
-		fRef = 0747BE78092B1D53002A2C63 /* AudioPlayer.m */;
-		name = "AudioPlayer.m: 161";
-		rLen = 0;
-		rLoc = 6109;
-		rType = 0;
-		vrLen = 1503;
-		vrLoc = 5062;
-	};
-	07021AB40982662B0074A648 /* PBXTextBookmark */ = {
-		isa = PBXTextBookmark;
-		fRef = 07021AB50982662B0074A648 /* NSDragging.h */;
-		name = "NSDragOperationNone\t\t= 0,";
-		rLen = 30;
-		rLoc = 296;
-		rType = 0;
-		vrLen = 1438;
-		vrLoc = 0;
-	};
-	07021AB50982662B0074A648 /* NSDragging.h */ = {
-		isa = PBXFileReference;
-		lastKnownFileType = sourcecode.c.h;
-		name = NSDragging.h;
-		path = /System/Library/Frameworks/AppKit.framework/Versions/C/Headers/NSDragging.h;
-		sourceTree = "<absolute>";
+	070DDD08098B7F0E00B72372 /* BZGeometry.m */ = {
 		uiCtxt = {
-			sepNavIntBoundsRect = "{{0, 0}, {692, 1012}}";
-			sepNavSelRange = "{296, 30}";
-			sepNavVisRect = "{{0, 504}, {692, 500}}";
-			sepNavWindowFrame = "{{245, 209}, {737, 578}}";
+			sepNavIntBoundsRect = "{{0, 0}, {677, 849}}";
+			sepNavSelRange = "{333, 15}";
+			sepNavVisRect = "{{0, 0}, {677, 849}}";
+			sepNavWindowFrame = "{{15, 70}, {722, 927}}";
 		};
 	};
 	0728666E0983724200C9C0E4 /* BZKeyAcceptingCell.h */ = {
 			sepNavWindowFrame = "{{15, 419}, {737, 578}}";
 		};
 	};
-	072866A30983740F00C9C0E4 /* PBXTextBookmark */ = {
-		isa = PBXTextBookmark;
-		fRef = 0795B81D09821B8C002412FE /* BZEventForwardingMatrix.h */;
-		name = "BZEventForwardingMatrix.h: 10";
-		rLen = 0;
-		rLoc = 266;
-		rType = 0;
-		vrLen = 325;
-		vrLoc = 0;
-	};
-	072866A40983740F00C9C0E4 /* PBXTextBookmark */ = {
-		isa = PBXTextBookmark;
-		fRef = 0795B81E09821B8C002412FE /* BZEventForwardingMatrix.m */;
-		name = "BZEventForwardingMatrix.m: 45";
-		rLen = 0;
-		rLoc = 1520;
-		rType = 0;
-		vrLen = 1294;
-		vrLoc = 54;
-	};
-	072866A50983740F00C9C0E4 /* PBXTextBookmark */ = {
-		isa = PBXTextBookmark;
-		fRef = 0795B81D09821B8C002412FE /* BZEventForwardingMatrix.h */;
-		name = "BZEventForwardingMatrix.h: 10";
-		rLen = 0;
-		rLoc = 266;
-		rType = 0;
-		vrLen = 325;
-		vrLoc = 0;
-	};
-	072866B7098374DD00C9C0E4 /* PBXTextBookmark */ = {
-		isa = PBXTextBookmark;
-		fRef = 0795B81009821731002412FE /* BZMovieButtonCell.h */;
-		name = "BZMovieButtonCell.h: 12";
-		rLen = 0;
-		rLoc = 330;
-		rType = 0;
-		vrLen = 397;
-		vrLoc = 0;
-	};
-	072866B9098374DD00C9C0E4 /* PBXTextBookmark */ = {
-		isa = PBXTextBookmark;
-		fRef = 0795B81009821731002412FE /* BZMovieButtonCell.h */;
-		name = "BZMovieButtonCell.h: 12";
-		rLen = 0;
-		rLoc = 330;
-		rType = 0;
-		vrLen = 397;
-		vrLoc = 0;
-	};
 	072866F10983863700C9C0E4 /* NSMutableArray+EasyMutation.h */ = {
 		uiCtxt = {
 			sepNavIntBoundsRect = "{{0, 0}, {692, 500}}";
 			sepNavWindowFrame = "{{153, 293}, {737, 578}}";
 		};
 	};
-	072866FF0983872200C9C0E4 /* PBXTextBookmark */ = {
-		isa = PBXTextBookmark;
-		fRef = 072866F10983863700C9C0E4 /* NSMutableArray+EasyMutation.h */;
-		name = "- (void)setObject:(id)obj atIndex:(unsigned)idx";
-		rLen = 47;
-		rLoc = 256;
-		rType = 0;
-		vrLen = 311;
-		vrLoc = 0;
-	};
-	072867000983872200C9C0E4 /* PBXTextBookmark */ = {
-		isa = PBXTextBookmark;
-		fRef = 072866F20983863700C9C0E4 /* NSMutableArray+EasyMutation.m */;
-		name = "NSMutableArray+EasyMutation.m: 6";
-		rLen = 0;
-		rLoc = 151;
-		rType = 0;
-		vrLen = 320;
-		vrLoc = 0;
-	};
-	072867010983872200C9C0E4 /* PBXTextBookmark */ = {
-		isa = PBXTextBookmark;
-		fRef = 072866F10983863700C9C0E4 /* NSMutableArray+EasyMutation.h */;
-		name = "- (void)setObject:(id)obj atIndex:(unsigned)idx";
-		rLen = 47;
-		rLoc = 256;
-		rType = 0;
-		vrLen = 311;
-		vrLoc = 0;
-	};
-	072867280983888A00C9C0E4 /* PBXTextBookmark */ = {
-		isa = PBXTextBookmark;
-		comments = "warning: method definition for '-keyUp:' not found";
-		fRef = 0795B81109821731002412FE /* BZMovieButtonCell.m */;
-		rLen = 1;
-		rLoc = 219;
-		rType = 1;
-	};
-	0728673D098389E000C9C0E4 /* AudioPlayer.m:203 */ = {
-		isa = PBXFileBreakpoint;
-		actions = (
-		);
-		continueAfterActions = 0;
-		delayBeforeContinue = 0;
-		fileReference = 0747BE78092B1D53002A2C63 /* AudioPlayer.m */;
-		functionName = "-applicationWillTerminate:";
-		hitCount = 1;
-		lineNumber = 203;
-		modificationTime = 159691772.820417;
-		state = 1;
-	};
-	072868320983AA3B00C9C0E4 /* PBXTextBookmark */ = {
-		isa = PBXTextBookmark;
-		fRef = 072868330983AA3B00C9C0E4 /* NSGraphics.h */;
-		rLen = 1;
-		rLoc = 175;
-		rType = 1;
-	};
-	072868330983AA3B00C9C0E4 /* NSGraphics.h */ = {
-		isa = PBXFileReference;
-		lastKnownFileType = sourcecode.c.h;
-		name = NSGraphics.h;
-		path = /System/Library/Frameworks/AppKit.framework/Versions/C/Headers/NSGraphics.h;
-		sourceTree = "<absolute>";
-		uiCtxt = {
-			sepNavIntBoundsRect = "{{0, 0}, {692, 2200}}";
-			sepNavSelRange = "{8960, 47}";
-			sepNavVisRect = "{{0, 1692}, {692, 500}}";
-			sepNavWindowFrame = "{{314, 146}, {737, 578}}";
-		};
-	};
-	072868340983AA3B00C9C0E4 /* PBXTextBookmark */ = {
-		isa = PBXTextBookmark;
-		fRef = 072868350983AA3B00C9C0E4 /* NSGraphics.h */;
-		name = "NSAnimationEffectDisappearingItemDefault = 0,";
-		rLen = 47;
-		rLoc = 8960;
-		rType = 0;
-		vrLen = 2350;
-		vrLoc = 6972;
-	};
-	072868350983AA3B00C9C0E4 /* NSGraphics.h */ = {
-		isa = PBXFileReference;
-		lastKnownFileType = sourcecode.c.h;
-		name = NSGraphics.h;
-		path = /System/Library/Frameworks/AppKit.framework/Versions/C/Headers/NSGraphics.h;
-		sourceTree = "<absolute>";
-	};
-	072868360983AA3B00C9C0E4 /* PBXTextBookmark */ = {
-		isa = PBXTextBookmark;