SoundNote 0.2 Start
This commit is contained in:
commit
2d15716b4a
9
.gitignore
vendored
Normal file
9
.gitignore
vendored
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
build
|
||||||
|
*.zip
|
||||||
|
*.xcodeproj/*.pbxuser
|
||||||
|
*.xcodeproj/*.mode*
|
||||||
|
*.xcodeproj/*.perspective*
|
||||||
|
*.xcodeproj/xcuserdata
|
||||||
|
*.xcodeproj/project.xcworkspace/xcuserdata
|
||||||
|
*.xcworkspace/xcuserdata
|
||||||
|
Screenshots/*
|
44
Classes/MGMController.h
Normal file
44
Classes/MGMController.h
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
//
|
||||||
|
// MGMController.h
|
||||||
|
// SoundNote
|
||||||
|
//
|
||||||
|
// Created by Mr. Gecko on 7/4/10.
|
||||||
|
// Copyright (c) 2011 Mr. Gecko's Media (James Coleman). All rights reserved. http://mrgeckosmedia.com/
|
||||||
|
//
|
||||||
|
|
||||||
|
#import <Cocoa/Cocoa.h>
|
||||||
|
|
||||||
|
extern NSString * const MGMApplicationSupportPath;
|
||||||
|
|
||||||
|
extern NSString * const MGMSoundEndedNotification;
|
||||||
|
|
||||||
|
extern NSString * const MGMNName;
|
||||||
|
extern NSString * const MGMNTitle;
|
||||||
|
extern NSString * const MGMNDescription;
|
||||||
|
extern NSString * const MGMNIcon;
|
||||||
|
extern NSString * const MGMNSound;
|
||||||
|
extern NSString * const MGMNTask;
|
||||||
|
|
||||||
|
@interface MGMController : NSObject <NSWindowDelegate> {
|
||||||
|
NSWindow *instructions;
|
||||||
|
|
||||||
|
NSMutableArray *watchers;
|
||||||
|
NSMutableArray *notifications;
|
||||||
|
|
||||||
|
NSTimer *wakeTimer;
|
||||||
|
BOOL ignoreNotifications;
|
||||||
|
NSDate *lastUpdated;
|
||||||
|
NSDictionary *growl;
|
||||||
|
}
|
||||||
|
+ (id)sharedController;
|
||||||
|
- (void)showInstructions;
|
||||||
|
|
||||||
|
- (void)registerDefaults;
|
||||||
|
- (IBAction)donate:(id)sender;
|
||||||
|
|
||||||
|
- (void)registerWatcher:(id)theWatcher;
|
||||||
|
- (NSMutableDictionary *)startNotificationWithInfo:(NSDictionary *)theInfo;
|
||||||
|
- (NSMutableDictionary *)notificationWithName:(NSString *)theName;
|
||||||
|
|
||||||
|
- (IBAction)Quit:(id)sender;
|
||||||
|
@end
|
356
Classes/MGMController.m
Normal file
356
Classes/MGMController.m
Normal file
@ -0,0 +1,356 @@
|
|||||||
|
//
|
||||||
|
// MGMController.m
|
||||||
|
// SoundNote
|
||||||
|
//
|
||||||
|
// Created by Mr. Gecko on 7/4/10.
|
||||||
|
// Copyright (c) 2011 Mr. Gecko's Media (James Coleman). All rights reserved. http://mrgeckosmedia.com/
|
||||||
|
//
|
||||||
|
|
||||||
|
#import "MGMController.h"
|
||||||
|
#import "MGMFileManager.h"
|
||||||
|
#import "MGMLoginItems.h"
|
||||||
|
#import "MGMSound.h"
|
||||||
|
#import <GeckoReporter/GeckoReporter.h>
|
||||||
|
#import <Growl/GrowlApplicationBridge.h>
|
||||||
|
|
||||||
|
#import "MGMDisplayWatcher.h"
|
||||||
|
#import "MGMApplicationWatcher.h"
|
||||||
|
#import "MGMVolumeWatcher.h"
|
||||||
|
#import "MGMITunesWatcher.h"
|
||||||
|
#import "MGMUSBWatcher.h"
|
||||||
|
#import "MGMBluetoothWatcher.h"
|
||||||
|
#import "MGMNetworkWatcher.h"
|
||||||
|
#import "MGMPowerWatcher.h"
|
||||||
|
#import "MGMKeyboardWatcher.h"
|
||||||
|
#import "MGMMouseWatcher.h"
|
||||||
|
#import "MGMAccessibleWatcher.h"
|
||||||
|
#import "MGMTrashWatcher.h"
|
||||||
|
|
||||||
|
static NSAutoreleasePool *pool = nil;
|
||||||
|
|
||||||
|
void runloop(CFRunLoopObserverRef observer, CFRunLoopActivity activity, void *info) {
|
||||||
|
if (activity & kCFRunLoopEntry) {
|
||||||
|
if (pool!=nil) [pool drain];
|
||||||
|
pool = [NSAutoreleasePool new];
|
||||||
|
} else if (activity & kCFRunLoopExit) {
|
||||||
|
[pool drain];
|
||||||
|
pool = nil;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
NSString * const MGMCopyright = @"Copyright (c) 2011 Mr. Gecko's Media (James Coleman). All rights reserved. http://mrgeckosmedia.com/";
|
||||||
|
NSString * const MGMVersion = @"MGMVersion";
|
||||||
|
NSString * const MGMLaunchCount = @"MGMLaunchCount";
|
||||||
|
|
||||||
|
NSString * const MGMApplicationSupportPath = @"~/Library/Application Support/MrGeckosMedia/SoundNote/";
|
||||||
|
NSString * const MGMNotesName = @"notes.txt";
|
||||||
|
NSString * const MGMGrowlName = @"growl.plist";
|
||||||
|
NSString * const MGMDisabledName = @"disabled.plist";
|
||||||
|
NSString * const MGMSoundEndedNotification = @"MGMSoundEndedNotification";
|
||||||
|
|
||||||
|
NSString * const MGMNName = @"MGMNName";
|
||||||
|
NSString * const MGMNTitle = @"MGMNTitle";
|
||||||
|
NSString * const MGMNDescription = @"MGMNDescription";
|
||||||
|
NSString * const MGMNIcon = @"MGMNIcon";
|
||||||
|
NSString * const MGMNSound = @"MGMNSound";
|
||||||
|
NSString * const MGMNTask = @"MGMNTask";
|
||||||
|
|
||||||
|
@protocol NSFileManagerProtocol <NSObject>
|
||||||
|
- (BOOL)createDirectoryAtPath:(NSString *)path withIntermediateDirectories:(BOOL)createIntermediates attributes:(NSDictionary *)attributes error:(NSError **)error;
|
||||||
|
- (BOOL)createDirectoryAtPath:(NSString *)path attributes:(NSDictionary *)attributes;
|
||||||
|
|
||||||
|
- (BOOL)removeItemAtPath:(NSString *)path error:(NSError **)error;
|
||||||
|
- (BOOL)removeFileAtPath:(NSString *)path handler:(id)handler;
|
||||||
|
|
||||||
|
- (BOOL)copyItemAtPath:(NSString *)srcPath toPath:(NSString *)dstPath error:(NSError **)error;
|
||||||
|
- (BOOL)copyPath:(NSString *)source toPath:(NSString *)destination handler:(id)handler;
|
||||||
|
|
||||||
|
- (BOOL)moveItemAtPath:(NSString *)srcPath toPath:(NSString *)dstPath error:(NSError **)error;
|
||||||
|
- (BOOL)movePath:(NSString *)source toPath:(NSString *)destination handler:(id)handler;
|
||||||
|
@end
|
||||||
|
|
||||||
|
static MGMController *MGMSharedController;
|
||||||
|
|
||||||
|
@implementation MGMController
|
||||||
|
+ (id)sharedController {
|
||||||
|
if (MGMSharedController==nil) {
|
||||||
|
MGMSharedController = [MGMController new];
|
||||||
|
}
|
||||||
|
return MGMSharedController;
|
||||||
|
}
|
||||||
|
- (id)init {
|
||||||
|
if (MGMSharedController!=nil) {
|
||||||
|
if ((self = [super init]))
|
||||||
|
[self release];
|
||||||
|
self = MGMSharedController;
|
||||||
|
} else if ((self = [super init])) {
|
||||||
|
MGMSharedController = self;
|
||||||
|
}
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
|
||||||
|
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(setup) name:MGMGRDoneNotification object:nil];
|
||||||
|
[MGMReporter sharedReporter];
|
||||||
|
}
|
||||||
|
- (void)setup {
|
||||||
|
CFRunLoopObserverContext context = {0, self, NULL, NULL, NULL};
|
||||||
|
CFRunLoopObserverRef observer = CFRunLoopObserverCreate(kCFAllocatorDefault, kCFRunLoopEntry | kCFRunLoopExit, YES, 0, runloop, &context);
|
||||||
|
CFRunLoopAddObserver(CFRunLoopGetCurrent(), observer, kCFRunLoopDefaultMode);
|
||||||
|
|
||||||
|
[GrowlApplicationBridge setGrowlDelegate:nil];
|
||||||
|
|
||||||
|
[[MGMLoginItems items] addSelf];
|
||||||
|
|
||||||
|
NSFileManager *manager = [NSFileManager defaultManager];
|
||||||
|
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
|
||||||
|
if ([defaults objectForKey:MGMVersion]==nil) {
|
||||||
|
if ([manager fileExistsAtPath:[MGMApplicationSupportPath stringByExpandingTildeInPath]]) {
|
||||||
|
[manager copyItemAtPath:[[NSBundle mainBundle] pathForResource:[MGMNotesName stringByDeletingPathExtension] ofType:[MGMNotesName pathExtension]] toPath:[[MGMApplicationSupportPath stringByExpandingTildeInPath] stringByAppendingPathComponent:MGMNotesName]];
|
||||||
|
[manager copyItemAtPath:[[NSBundle mainBundle] pathForResource:[MGMGrowlName stringByDeletingPathExtension] ofType:[MGMGrowlName pathExtension]] toPath:[[MGMApplicationSupportPath stringByExpandingTildeInPath] stringByAppendingPathComponent:MGMGrowlName]];
|
||||||
|
[manager copyItemAtPath:[[NSBundle mainBundle] pathForResource:[MGMDisabledName stringByDeletingPathExtension] ofType:[MGMDisabledName pathExtension]] toPath:[[MGMApplicationSupportPath stringByExpandingTildeInPath] stringByAppendingPathComponent:MGMDisabledName]];
|
||||||
|
[manager removeItemAtPath:[[MGMApplicationSupportPath stringByExpandingTildeInPath] stringByAppendingPathComponent:@"note.txt"]];
|
||||||
|
[self showInstructions];
|
||||||
|
[defaults setObject:[[MGMSystemInfo info] applicationVersion] forKey:MGMVersion];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
[self registerDefaults];
|
||||||
|
if (![manager fileExistsAtPath:[MGMApplicationSupportPath stringByExpandingTildeInPath]]) {
|
||||||
|
[manager createDirectoryAtPath:[MGMApplicationSupportPath stringByExpandingTildeInPath] withAttributes:nil];
|
||||||
|
[manager copyItemAtPath:[[NSBundle mainBundle] pathForResource:[MGMNotesName stringByDeletingPathExtension] ofType:[MGMNotesName pathExtension]] toPath:[[MGMApplicationSupportPath stringByExpandingTildeInPath] stringByAppendingPathComponent:MGMNotesName]];
|
||||||
|
[manager copyItemAtPath:[[NSBundle mainBundle] pathForResource:[MGMGrowlName stringByDeletingPathExtension] ofType:[MGMGrowlName pathExtension]] toPath:[[MGMApplicationSupportPath stringByExpandingTildeInPath] stringByAppendingPathComponent:MGMGrowlName]];
|
||||||
|
[manager copyItemAtPath:[[NSBundle mainBundle] pathForResource:[MGMDisabledName stringByDeletingPathExtension] ofType:[MGMDisabledName pathExtension]] toPath:[[MGMApplicationSupportPath stringByExpandingTildeInPath] stringByAppendingPathComponent:MGMDisabledName]];
|
||||||
|
[self showInstructions];
|
||||||
|
}
|
||||||
|
|
||||||
|
NSNotificationCenter *notificationCenter = [[NSWorkspace sharedWorkspace] notificationCenter];
|
||||||
|
[notificationCenter addObserver:self selector:@selector(willLogout:) name:NSWorkspaceWillPowerOffNotification object:nil];
|
||||||
|
[notificationCenter addObserver:self selector:@selector(willSleep:) name:NSWorkspaceWillSleepNotification object:nil];
|
||||||
|
[notificationCenter addObserver:self selector:@selector(didWake:) name:NSWorkspaceDidWakeNotification object:nil];
|
||||||
|
|
||||||
|
watchers = [NSMutableArray new];
|
||||||
|
notifications = [NSMutableArray new];
|
||||||
|
[self startNotificationWithInfo:[NSDictionary dictionaryWithObjectsAndKeys:@"login", MGMNName, @"Login", MGMNTitle, @"You have logged in.", MGMNDescription, nil]];
|
||||||
|
|
||||||
|
|
||||||
|
NSDictionary *disabledWatchers = [NSDictionary dictionaryWithContentsOfFile:[[MGMApplicationSupportPath stringByExpandingTildeInPath] stringByAppendingPathComponent:MGMDisabledName]];
|
||||||
|
if (![[disabledWatchers objectForKey:@"display"] boolValue])
|
||||||
|
[self registerWatcher:[[MGMDisplayWatcher new] autorelease]];
|
||||||
|
if (![[disabledWatchers objectForKey:@"application"] boolValue])
|
||||||
|
[self registerWatcher:[[MGMApplicationWatcher new] autorelease]];
|
||||||
|
if (![[disabledWatchers objectForKey:@"volume"] boolValue])
|
||||||
|
[self registerWatcher:[[MGMVolumeWatcher new] autorelease]];
|
||||||
|
if (![[disabledWatchers objectForKey:@"itunes"] boolValue])
|
||||||
|
[self registerWatcher:[[MGMITunesWatcher new] autorelease]];
|
||||||
|
if (![[disabledWatchers objectForKey:@"usb"] boolValue])
|
||||||
|
[self registerWatcher:[[MGMUSBWatcher new] autorelease]];
|
||||||
|
if (![[disabledWatchers objectForKey:@"bluetooth"] boolValue])
|
||||||
|
[self registerWatcher:[[MGMBluetoothWatcher new] autorelease]];
|
||||||
|
if (![[disabledWatchers objectForKey:@"network"] boolValue])
|
||||||
|
[self registerWatcher:[[MGMNetworkWatcher new] autorelease]];
|
||||||
|
if (![[disabledWatchers objectForKey:@"power"] boolValue])
|
||||||
|
[self registerWatcher:[[MGMPowerWatcher new] autorelease]];
|
||||||
|
if (![[disabledWatchers objectForKey:@"keyboard"] boolValue])
|
||||||
|
[self registerWatcher:[[MGMKeyboardWatcher new] autorelease]];
|
||||||
|
if (![[disabledWatchers objectForKey:@"mouse"] boolValue])
|
||||||
|
[self registerWatcher:[[MGMMouseWatcher new] autorelease]];
|
||||||
|
if (![[disabledWatchers objectForKey:@"accessible"] boolValue])
|
||||||
|
[self registerWatcher:[[MGMAccessibleWatcher new] autorelease]];
|
||||||
|
if (![[disabledWatchers objectForKey:@"trash"] boolValue])
|
||||||
|
[self registerWatcher:[[MGMTrashWatcher new] autorelease]];
|
||||||
|
|
||||||
|
if ([defaults integerForKey:MGMLaunchCount]!=5) {
|
||||||
|
[defaults setInteger:[defaults integerForKey:MGMLaunchCount]+1 forKey:MGMLaunchCount];
|
||||||
|
if ([defaults integerForKey:MGMLaunchCount]==5) {
|
||||||
|
NSAlert *alert = [[NSAlert new] autorelease];
|
||||||
|
[alert setMessageText:@"Donations"];
|
||||||
|
[alert setInformativeText:@"Thank you for using SoundNote. SoundNote is donation supported software. If you like using it, please consider giving a donation to help with development."];
|
||||||
|
[alert addButtonWithTitle:@"Yes"];
|
||||||
|
[alert addButtonWithTitle:@"No"];
|
||||||
|
int result = [alert runModal];
|
||||||
|
if (result==1000)
|
||||||
|
[self donate:self];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
- (void)dealloc {
|
||||||
|
[[[NSWorkspace sharedWorkspace] notificationCenter] removeObserver:self];
|
||||||
|
[watchers release];
|
||||||
|
[notifications release];
|
||||||
|
[wakeTimer invalidate];
|
||||||
|
[wakeTimer release];
|
||||||
|
[lastUpdated release];
|
||||||
|
[growl release];
|
||||||
|
[super dealloc];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)registerDefaults {
|
||||||
|
NSMutableDictionary *defaults = [NSMutableDictionary dictionary];
|
||||||
|
[defaults setObject:[NSNumber numberWithInt:1] forKey:MGMLaunchCount];
|
||||||
|
[[NSUserDefaults standardUserDefaults] registerDefaults:defaults];
|
||||||
|
}
|
||||||
|
- (BOOL)applicationShouldHandleReopen:(NSApplication *)theApplication hasVisibleWindows:(BOOL)flag {
|
||||||
|
[self showInstructions];
|
||||||
|
return YES;
|
||||||
|
}
|
||||||
|
- (IBAction)donate:(id)sender {
|
||||||
|
[[NSWorkspace sharedWorkspace] openURL:[NSURL URLWithString:@"https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=LMT7LSBTP4NDJ"]];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)showInstructions {
|
||||||
|
if (instructions==nil) {
|
||||||
|
NSRect size = NSMakeRect(0, 0, 450, 400);
|
||||||
|
instructions = [[NSWindow alloc] initWithContentRect:size styleMask:NSTitledWindowMask | NSClosableWindowMask backing:NSBackingStoreBuffered defer:NO];
|
||||||
|
[instructions setTitle:@"SoundNote"];
|
||||||
|
NSScrollView *scrollview = [[[NSScrollView alloc] initWithFrame:size] autorelease];
|
||||||
|
[scrollview setHasVerticalScroller:YES];
|
||||||
|
[scrollview setHasHorizontalScroller:NO];
|
||||||
|
NSSize contentSize = [scrollview contentSize];
|
||||||
|
NSTextView *textView = [[[NSTextView alloc] initWithFrame:NSMakeRect(0, 0, contentSize.width, contentSize.height)] autorelease];
|
||||||
|
[textView readRTFDFromFile:[[NSBundle mainBundle] pathForResource:@"Instructions" ofType:@"rtf"]];
|
||||||
|
[textView setEditable:NO];
|
||||||
|
[textView setVerticallyResizable:YES];
|
||||||
|
[textView setHorizontallyResizable:NO];
|
||||||
|
[textView setAutoresizingMask:NSViewHeightSizable];
|
||||||
|
[scrollview setDocumentView:textView];
|
||||||
|
[[textView textContainer] setHeightTracksTextView:YES];
|
||||||
|
[instructions setContentView:scrollview];
|
||||||
|
[instructions setDelegate:self];
|
||||||
|
[instructions setLevel:NSStatusWindowLevel];
|
||||||
|
[instructions setReleasedWhenClosed:YES];
|
||||||
|
[instructions center];
|
||||||
|
}
|
||||||
|
[instructions makeKeyAndOrderFront:self];
|
||||||
|
[[NSApplication sharedApplication] activateIgnoringOtherApps:YES];
|
||||||
|
}
|
||||||
|
- (void)windowWillClose:(NSNotification *)theNotification {
|
||||||
|
instructions = nil;
|
||||||
|
[[NSWorkspace sharedWorkspace] selectFile:[MGMApplicationSupportPath stringByExpandingTildeInPath] inFileViewerRootedAtPath:[MGMApplicationSupportPath stringByExpandingTildeInPath]];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)registerWatcher:(id)theWatcher {
|
||||||
|
[watchers addObject:theWatcher];
|
||||||
|
}
|
||||||
|
- (NSMutableDictionary *)startNotificationWithInfo:(NSDictionary *)theInfo {
|
||||||
|
NSArray *allowedNotifications = [NSArray arrayWithObjects:@"logout", @"willsleep", @"didwake", nil];
|
||||||
|
if (ignoreNotifications && ![allowedNotifications containsObject:[theInfo objectForKey:MGMNName]])
|
||||||
|
return nil;
|
||||||
|
//NSLog(@"%@", theInfo);
|
||||||
|
NSArray *allowedExtensions = [NSArray arrayWithObjects:@"aiff", @"aif", @"mp3", @"wav", @"au", @"m4a", nil];
|
||||||
|
NSMutableDictionary *info = [[theInfo mutableCopy] autorelease];
|
||||||
|
NSFileManager *manager = [NSFileManager defaultManager];
|
||||||
|
NSArray *files = [manager contentsOfDirectoryAtPath:[MGMApplicationSupportPath stringByExpandingTildeInPath]];
|
||||||
|
for (int i=0; i<[files count]; i++) {
|
||||||
|
if ([[[files objectAtIndex:i] stringByDeletingPathExtension] isEqual:[info objectForKey:MGMNName]]) {
|
||||||
|
NSString *path = [[MGMApplicationSupportPath stringByExpandingTildeInPath] stringByAppendingPathComponent:[files objectAtIndex:i]];
|
||||||
|
if ([allowedExtensions containsObject:[[path pathExtension] lowercaseString]]) {
|
||||||
|
MGMSound *sound = [[[MGMSound alloc] initWithContentsOfFile:path] autorelease];
|
||||||
|
[info setObject:sound forKey:MGMNSound];
|
||||||
|
[notifications addObject:info];
|
||||||
|
[sound setDelegate:self];
|
||||||
|
[sound play];
|
||||||
|
} else if ([[[path pathExtension] lowercaseString] isEqual:@"sh"]) {
|
||||||
|
NSTask *task = [[NSTask new] autorelease];
|
||||||
|
[task setLaunchPath:@"/bin/bash"];
|
||||||
|
NSMutableArray *arguments = [NSMutableArray arrayWithObject:path];
|
||||||
|
[arguments addObject:[info objectForKey:MGMNDescription]];
|
||||||
|
[task setArguments:arguments];
|
||||||
|
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(taskDidTerminate:) name:NSTaskDidTerminateNotification object:task];
|
||||||
|
[info setObject:task forKey:MGMNTask];
|
||||||
|
[notifications addObject:info];
|
||||||
|
[task launch];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
NSString *growlPath = [[MGMApplicationSupportPath stringByExpandingTildeInPath] stringByAppendingPathComponent:MGMGrowlName];
|
||||||
|
NSDictionary *attributes = [manager attributesOfItemAtPath:growlPath];
|
||||||
|
if (![[attributes objectForKey:NSFileModificationDate] isEqual:lastUpdated]) {
|
||||||
|
[growl release];
|
||||||
|
growl = [[NSDictionary dictionaryWithContentsOfFile:growlPath] retain];
|
||||||
|
[lastUpdated release];
|
||||||
|
lastUpdated = [[attributes objectForKey:NSFileModificationDate] retain];
|
||||||
|
}
|
||||||
|
if ([[growl objectForKey:[info objectForKey:MGMNName]] boolValue]) {
|
||||||
|
NSData *icon = nil;
|
||||||
|
if ([[info objectForKey:MGMNIcon] isKindOfClass:[NSData class]])
|
||||||
|
icon = [info objectForKey:MGMNIcon];
|
||||||
|
else if ([[info objectForKey:MGMNIcon] isKindOfClass:[NSImage class]])
|
||||||
|
icon = [[info objectForKey:MGMNIcon] TIFFRepresentation];
|
||||||
|
else
|
||||||
|
icon = [[[NSApplication sharedApplication] applicationIconImage] TIFFRepresentation];
|
||||||
|
[GrowlApplicationBridge notifyWithTitle:[info objectForKey:MGMNTitle] description:[info objectForKey:MGMNDescription] notificationName:[info objectForKey:MGMNName] iconData:icon priority:0 isSticky:NO clickContext:nil];
|
||||||
|
}
|
||||||
|
return info;
|
||||||
|
}
|
||||||
|
- (NSMutableDictionary *)notificationWithName:(NSString *)theName {
|
||||||
|
for (int i=0; i<[notifications count]; i++) {
|
||||||
|
if ([[[notifications objectAtIndex:i] objectForKey:MGMNName] isEqual:theName])
|
||||||
|
return [notifications objectAtIndex:i];
|
||||||
|
}
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
- (void)soundDidFinishPlaying:(MGMSound *)theSound {
|
||||||
|
for (int i=0; i<[notifications count]; i++) {
|
||||||
|
if ([[notifications objectAtIndex:i] objectForKey:MGMNSound]==theSound) {
|
||||||
|
NSMutableDictionary *notification = [notifications objectAtIndex:i];
|
||||||
|
[notification removeObjectForKey:MGMNSound];
|
||||||
|
[[NSNotificationCenter defaultCenter] postNotificationName:MGMSoundEndedNotification object:notification];
|
||||||
|
if ([notification objectForKey:MGMNTask]==nil)
|
||||||
|
[notifications removeObject:notification];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
- (void)taskDidTerminate:(NSNotification *)theNotification {
|
||||||
|
[[NSNotificationCenter defaultCenter] removeObserver:self name:[theNotification name] object:[theNotification object]];
|
||||||
|
for (int i=0; i<[notifications count]; i++) {
|
||||||
|
if ([[notifications objectAtIndex:i] objectForKey:MGMNTask]==[theNotification object]) {
|
||||||
|
NSMutableDictionary *notification = [notifications objectAtIndex:i];
|
||||||
|
[notification removeObjectForKey:MGMNTask];
|
||||||
|
if ([notification objectForKey:MGMNSound]==nil)
|
||||||
|
[notifications removeObject:notification];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)willLogout:(NSNotification *)theNotification {
|
||||||
|
ignoreNotifications = YES;
|
||||||
|
[self startNotificationWithInfo:[NSDictionary dictionaryWithObjectsAndKeys:@"logout", MGMNName, @"Logout", MGMNTitle, @"You are logging out.", MGMNDescription, nil]];
|
||||||
|
}
|
||||||
|
- (void)willSleep:(NSNotification *)theNotification {
|
||||||
|
if (wakeTimer!=nil) {
|
||||||
|
[wakeTimer invalidate];
|
||||||
|
[wakeTimer release];
|
||||||
|
wakeTimer = nil;
|
||||||
|
}
|
||||||
|
ignoreNotifications = YES;
|
||||||
|
NSMutableDictionary *info = [self startNotificationWithInfo:[NSDictionary dictionaryWithObjectsAndKeys:@"willsleep", MGMNName, @"Will Sleep", MGMNTitle, @"The computer will go to sleep.", MGMNDescription, nil]];
|
||||||
|
if ([info objectForKey:MGMNSound]!=nil) {
|
||||||
|
while ([[info objectForKey:MGMNSound] isPlaying]) {
|
||||||
|
[NSThread sleepUntilDate:[NSDate dateWithTimeIntervalSinceNow:0.5]];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
- (void)didWake:(NSNotification *)theNotification {
|
||||||
|
[self startNotificationWithInfo:[NSDictionary dictionaryWithObjectsAndKeys:@"didwake", MGMNName, @"Did Wake", MGMNTitle, @"The computer woke up from sleep.", MGMNDescription, nil]];
|
||||||
|
wakeTimer = [[NSTimer scheduledTimerWithTimeInterval:10.0 target:self selector:@selector(sendWakeNotification) userInfo:nil repeats:NO] retain];
|
||||||
|
}
|
||||||
|
- (void)sendWakeNotification {
|
||||||
|
[wakeTimer release];
|
||||||
|
wakeTimer = nil;
|
||||||
|
ignoreNotifications = NO;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (IBAction)Quit:(id)sender {
|
||||||
|
[[MGMLoginItems items] removeSelf];
|
||||||
|
[[NSApplication sharedApplication] terminate:self];
|
||||||
|
}
|
||||||
|
- (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication *)sender {
|
||||||
|
NSMutableDictionary *info = [self notificationWithName:@"logout"];
|
||||||
|
if ([info objectForKey:MGMNSound]!=nil) {
|
||||||
|
while ([[info objectForKey:MGMNSound] isPlaying]) {
|
||||||
|
[NSThread sleepUntilDate:[NSDate dateWithTimeIntervalSinceNow:0.5]];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return NSTerminateNow;
|
||||||
|
}
|
||||||
|
@end
|
23
Classes/MGMFileManager.h
Normal file
23
Classes/MGMFileManager.h
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
//
|
||||||
|
// MGMFileManager.h
|
||||||
|
// SoundNote
|
||||||
|
//
|
||||||
|
// Created by Mr. Gecko on 1/22/11.
|
||||||
|
// Copyright (c) 2011 Mr. Gecko's Media (James Coleman). All rights reserved. http://mrgeckosmedia.com/
|
||||||
|
//
|
||||||
|
|
||||||
|
#import <Cocoa/Cocoa.h>
|
||||||
|
|
||||||
|
@interface NSFileManager (MGMFileManager)
|
||||||
|
- (BOOL)moveItemAtPath:(NSString *)thePath toPath:(NSString *)theDestination;
|
||||||
|
- (BOOL)copyItemAtPath:(NSString *)thePath toPath:(NSString *)theDestination;
|
||||||
|
- (BOOL)removeItemAtPath:(NSString *)thePath;
|
||||||
|
- (BOOL)linkItemAtPath:(NSString *)thePath toPath:(NSString *)theDestination;
|
||||||
|
- (BOOL)createDirectoryAtPath:(NSString *)thePath withAttributes:(NSDictionary *)theAttributes;
|
||||||
|
- (BOOL)createSymbolicLinkAtPath:(NSString *)thePath withDestinationPath:(NSString *)theDestination;
|
||||||
|
- (NSString *)destinationOfSymbolicLinkAtPath:(NSString *)thePath;
|
||||||
|
- (NSArray *)contentsOfDirectoryAtPath:(NSString *)thePath;
|
||||||
|
- (NSDictionary *)attributesOfFileSystemForPath:(NSString *)thePath;
|
||||||
|
- (void)setAttributes:(NSDictionary *)theAttributes ofItemAtPath:(NSString *)thePath;
|
||||||
|
- (NSDictionary *)attributesOfItemAtPath:(NSString *)thePath;
|
||||||
|
@end
|
86
Classes/MGMFileManager.m
Normal file
86
Classes/MGMFileManager.m
Normal file
@ -0,0 +1,86 @@
|
|||||||
|
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
|
||||||
|
//
|
||||||
|
// MGMFileManager.m
|
||||||
|
// SoundNote
|
||||||
|
//
|
||||||
|
// Created by Mr. Gecko on 1/22/11.
|
||||||
|
// Copyright (c) 2011 Mr. Gecko's Media (James Coleman). All rights reserved. http://mrgeckosmedia.com/
|
||||||
|
//
|
||||||
|
|
||||||
|
#import "MGMFileManager.h"
|
||||||
|
|
||||||
|
@implementation NSFileManager (MGMFileManager)
|
||||||
|
- (BOOL)moveItemAtPath:(NSString *)thePath toPath:(NSString *)theDestination {
|
||||||
|
if ([self respondsToSelector:@selector(movePath:toPath:handler:)])
|
||||||
|
return [self movePath:thePath toPath:theDestination handler:nil];
|
||||||
|
else
|
||||||
|
return [self moveItemAtPath:thePath toPath:theDestination error:nil];
|
||||||
|
}
|
||||||
|
- (BOOL)copyItemAtPath:(NSString *)thePath toPath:(NSString *)theDestination {
|
||||||
|
if ([self respondsToSelector:@selector(copyPath:toPath:handler:)])
|
||||||
|
return [self copyPath:thePath toPath:theDestination handler:nil];
|
||||||
|
else
|
||||||
|
return [self copyItemAtPath:thePath toPath:theDestination error:nil];
|
||||||
|
}
|
||||||
|
- (BOOL)removeItemAtPath:(NSString *)thePath {
|
||||||
|
if ([self respondsToSelector:@selector(removeFileAtPath:handler:)])
|
||||||
|
return [self removeFileAtPath:thePath handler:nil];
|
||||||
|
else
|
||||||
|
return [self removeItemAtPath:thePath error:nil];
|
||||||
|
}
|
||||||
|
- (BOOL)linkItemAtPath:(NSString *)thePath toPath:(NSString *)theDestination {
|
||||||
|
if ([self respondsToSelector:@selector(linkPath:toPath:handler:)])
|
||||||
|
return [self linkPath:thePath toPath:theDestination handler:nil];
|
||||||
|
else
|
||||||
|
return [self linkItemAtPath:thePath toPath:theDestination error:nil];
|
||||||
|
}
|
||||||
|
- (BOOL)createDirectoryAtPath:(NSString *)thePath withAttributes:(NSDictionary *)theAttributes {
|
||||||
|
if ([self respondsToSelector:@selector(createDirectoryAtPath:attributes:)]) {
|
||||||
|
BOOL isDirectory;
|
||||||
|
if (![self fileExistsAtPath:thePath isDirectory:&isDirectory] && ![[thePath stringByDeletingLastPathComponent] isEqual:@""])
|
||||||
|
[self createDirectoryAtPath:[thePath stringByDeletingLastPathComponent] withAttributes:nil];
|
||||||
|
else if (!isDirectory || [[thePath stringByDeletingLastPathComponent] isEqual:@""])
|
||||||
|
return false;
|
||||||
|
return [self createDirectoryAtPath:thePath attributes:theAttributes];
|
||||||
|
} else {
|
||||||
|
return [self createDirectoryAtPath:thePath withIntermediateDirectories:YES attributes:theAttributes error:nil];
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
- (BOOL)createSymbolicLinkAtPath:(NSString *)thePath withDestinationPath:(NSString *)theDestination {
|
||||||
|
if ([self respondsToSelector:@selector(createSymbolicLinkAtPath:pathContent:)])
|
||||||
|
return [self createSymbolicLinkAtPath:thePath pathContent:theDestination];
|
||||||
|
else
|
||||||
|
return [self createSymbolicLinkAtPath:thePath withDestinationPath:theDestination error:nil];
|
||||||
|
}
|
||||||
|
- (NSString *)destinationOfSymbolicLinkAtPath:(NSString *)thePath {
|
||||||
|
if ([self respondsToSelector:@selector(pathContentOfSymbolicLinkAtPath:)])
|
||||||
|
return [self pathContentOfSymbolicLinkAtPath:thePath];
|
||||||
|
else
|
||||||
|
return [self destinationOfSymbolicLinkAtPath:thePath error:nil];
|
||||||
|
}
|
||||||
|
- (NSArray *)contentsOfDirectoryAtPath:(NSString *)thePath {
|
||||||
|
if ([self respondsToSelector:@selector(directoryContentsAtPath:)])
|
||||||
|
return [self directoryContentsAtPath:thePath];
|
||||||
|
else
|
||||||
|
return [self contentsOfDirectoryAtPath:thePath error:nil];
|
||||||
|
}
|
||||||
|
- (NSDictionary *)attributesOfFileSystemForPath:(NSString *)thePath {
|
||||||
|
if ([self respondsToSelector:@selector(fileSystemAttributesAtPath:)])
|
||||||
|
return [self fileSystemAttributesAtPath:thePath];
|
||||||
|
else
|
||||||
|
return [self attributesOfFileSystemForPath:thePath error:nil];
|
||||||
|
}
|
||||||
|
- (void)setAttributes:(NSDictionary *)theAttributes ofItemAtPath:(NSString *)thePath {
|
||||||
|
if ([self respondsToSelector:@selector(changeFileAttributes:atPath:)])
|
||||||
|
[self changeFileAttributes:theAttributes atPath:thePath];
|
||||||
|
else
|
||||||
|
[self setAttributes:theAttributes ofItemAtPath:thePath error:nil];
|
||||||
|
}
|
||||||
|
- (NSDictionary *)attributesOfItemAtPath:(NSString *)thePath {
|
||||||
|
if ([self respondsToSelector:@selector(fileAttributesAtPath:traverseLink:)])
|
||||||
|
return [self fileAttributesAtPath:thePath traverseLink:YES];
|
||||||
|
else
|
||||||
|
return [self attributesOfItemAtPath:thePath error:nil];
|
||||||
|
}
|
||||||
|
@end
|
26
Classes/MGMLoginItems.h
Normal file
26
Classes/MGMLoginItems.h
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
//
|
||||||
|
// MGMLoginItems.h
|
||||||
|
// SoundNote
|
||||||
|
//
|
||||||
|
// Created by Mr. Gecko on 8/7/10.
|
||||||
|
// Copyright (c) 2011 Mr. Gecko's Media (James Coleman). All rights reserved. http://mrgeckosmedia.com/
|
||||||
|
//
|
||||||
|
|
||||||
|
#import <Cocoa/Cocoa.h>
|
||||||
|
|
||||||
|
extern NSString * const MGMLoginItemsPath;
|
||||||
|
|
||||||
|
@interface MGMLoginItems : NSObject {
|
||||||
|
NSMutableDictionary *loginItems;
|
||||||
|
}
|
||||||
|
+ (id)items;
|
||||||
|
- (NSArray *)paths;
|
||||||
|
- (BOOL)selfExists;
|
||||||
|
- (BOOL)addSelf;
|
||||||
|
- (BOOL)removeSelf;
|
||||||
|
- (BOOL)exists:(NSString *)thePath;
|
||||||
|
- (BOOL)add:(NSString *)thePath;
|
||||||
|
- (BOOL)add:(NSString *)thePath hide:(BOOL)shouldHide;
|
||||||
|
- (BOOL)remove:(NSString *)thePath;
|
||||||
|
- (void)_save;
|
||||||
|
@end
|
89
Classes/MGMLoginItems.m
Normal file
89
Classes/MGMLoginItems.m
Normal file
@ -0,0 +1,89 @@
|
|||||||
|
//
|
||||||
|
// MGMLoginItems.m
|
||||||
|
// SoundNote
|
||||||
|
//
|
||||||
|
// Created by Mr. Gecko on 8/7/10.
|
||||||
|
// Copyright (c) 2011 Mr. Gecko's Media (James Coleman). All rights reserved. http://mrgeckosmedia.com/
|
||||||
|
//
|
||||||
|
|
||||||
|
#import "MGMLoginItems.h"
|
||||||
|
|
||||||
|
NSString * const MGMLoginItemsPath = @"~/Library/Preferences/loginwindow.plist";
|
||||||
|
NSString * const MGMItemsKey = @"AutoLaunchedApplicationDictionary";
|
||||||
|
NSString * const MGMPathKey = @"Path";
|
||||||
|
NSString * const MGMHideKey = @"Hide";
|
||||||
|
|
||||||
|
@implementation MGMLoginItems
|
||||||
|
+ (id)items {
|
||||||
|
return [[[self alloc] init] autorelease];
|
||||||
|
}
|
||||||
|
- (id)init {
|
||||||
|
if ((self = [super init])) {
|
||||||
|
loginItems = [[NSMutableDictionary dictionaryWithContentsOfFile:[MGMLoginItemsPath stringByExpandingTildeInPath]] retain];
|
||||||
|
}
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
- (void)dealloc {
|
||||||
|
[loginItems release];
|
||||||
|
[super dealloc];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (NSArray *)paths {
|
||||||
|
NSMutableArray *returnApps = [NSMutableArray array];
|
||||||
|
NSArray *applications = [loginItems objectForKey:MGMItemsKey];
|
||||||
|
for (int i=0; i<[applications count]; i++) {
|
||||||
|
[returnApps addObject:[[applications objectAtIndex:i] objectForKey:MGMPathKey]];
|
||||||
|
}
|
||||||
|
return returnApps;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (BOOL)selfExists {
|
||||||
|
return [self exists:[[NSBundle mainBundle] bundlePath]];
|
||||||
|
}
|
||||||
|
- (BOOL)addSelf {
|
||||||
|
return [self add:[[NSBundle mainBundle] bundlePath]];
|
||||||
|
}
|
||||||
|
- (BOOL)removeSelf {
|
||||||
|
return [self remove:[[NSBundle mainBundle] bundlePath]];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (BOOL)exists:(NSString *)thePath {
|
||||||
|
NSArray *applications = [loginItems objectForKey:MGMItemsKey];
|
||||||
|
for (int i=0; i<[applications count]; i++) {
|
||||||
|
if ([[[applications objectAtIndex:i] objectForKey:MGMPathKey] isEqual:thePath])
|
||||||
|
return YES;
|
||||||
|
}
|
||||||
|
return NO;
|
||||||
|
}
|
||||||
|
- (BOOL)add:(NSString *)thePath {
|
||||||
|
return [self add:thePath hide:NO];
|
||||||
|
}
|
||||||
|
- (BOOL)add:(NSString *)thePath hide:(BOOL)shouldHide {
|
||||||
|
if ([self exists:thePath])
|
||||||
|
return NO;
|
||||||
|
NSMutableArray *applications = [NSMutableArray arrayWithArray:[loginItems objectForKey:MGMItemsKey]];
|
||||||
|
NSMutableDictionary *info = [NSMutableDictionary dictionary];
|
||||||
|
[info setObject:thePath forKey:MGMPathKey];
|
||||||
|
[info setObject:[NSNumber numberWithBool:shouldHide] forKey:MGMHideKey];
|
||||||
|
[applications addObject:info];
|
||||||
|
[loginItems setObject:applications forKey:MGMItemsKey];
|
||||||
|
[self _save];
|
||||||
|
return YES;
|
||||||
|
}
|
||||||
|
- (BOOL)remove:(NSString *)thePath {
|
||||||
|
NSMutableArray *applications = [NSMutableArray arrayWithArray:[loginItems objectForKey:MGMItemsKey]];
|
||||||
|
for (int i=0; i<[applications count]; i++) {
|
||||||
|
if ([[[applications objectAtIndex:i] objectForKey:MGMPathKey] isEqual:thePath]) {
|
||||||
|
[applications removeObjectAtIndex:i];
|
||||||
|
[loginItems setObject:applications forKey:MGMItemsKey];
|
||||||
|
[self _save];
|
||||||
|
return YES;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return NO;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)_save {
|
||||||
|
[loginItems writeToFile:[MGMLoginItemsPath stringByExpandingTildeInPath] atomically:YES];
|
||||||
|
}
|
||||||
|
@end
|
48
Classes/MGMMD5.h
Normal file
48
Classes/MGMMD5.h
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
//
|
||||||
|
// MGMMD5.h
|
||||||
|
//
|
||||||
|
// Created by Mr. Gecko <GRMrGecko@gmail.com> on 1/6/10.
|
||||||
|
// No Copyright Claimed. Public Domain.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef _MD_MD5
|
||||||
|
#define _MD_MD5
|
||||||
|
|
||||||
|
#ifdef __NEXT_RUNTIME__
|
||||||
|
#import <Foundation/Foundation.h>
|
||||||
|
|
||||||
|
|
||||||
|
extern NSString * const MDNMD5;
|
||||||
|
|
||||||
|
@interface NSString (MGMMD5)
|
||||||
|
- (NSString *)MD5;
|
||||||
|
- (NSString *)pathMD5;
|
||||||
|
@end
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
char *MD5String(const char *string, int length);
|
||||||
|
char *MD5File(const char *path);
|
||||||
|
|
||||||
|
#define MD5Length 16
|
||||||
|
#define MD5BufferSize 4
|
||||||
|
|
||||||
|
struct MD5Context {
|
||||||
|
uint32_t buf[MD5BufferSize];
|
||||||
|
uint32_t bits[2];
|
||||||
|
unsigned char in[64];
|
||||||
|
};
|
||||||
|
|
||||||
|
void MD5Init(struct MD5Context *context);
|
||||||
|
void MD5Update(struct MD5Context *context, const unsigned char *buf, unsigned len);
|
||||||
|
void MD5Final(unsigned char digest[MD5Length], struct MD5Context *context);
|
||||||
|
void MD5Transform(uint32_t buf[MD5BufferSize], const unsigned char inraw[64]);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
297
Classes/MGMMD5.m
Normal file
297
Classes/MGMMD5.m
Normal file
@ -0,0 +1,297 @@
|
|||||||
|
//
|
||||||
|
// MGMMD5.m
|
||||||
|
//
|
||||||
|
// Created by Mr. Gecko <GRMrGecko@gmail.com> on 1/6/10.
|
||||||
|
// No Copyright Claimed. Public Domain.
|
||||||
|
// C Algorithm created by Colin Plumb
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifdef __NEXT_RUNTIME__
|
||||||
|
#import "MGMMD5.h"
|
||||||
|
#import "MGMTypes.h"
|
||||||
|
|
||||||
|
|
||||||
|
NSString * const MDNMD5 = @"md5";
|
||||||
|
|
||||||
|
@implementation NSString (MGMMD5)
|
||||||
|
- (NSString *)MD5 {
|
||||||
|
NSData *MDData = [self dataUsingEncoding:NSUTF8StringEncoding];
|
||||||
|
struct MD5Context MDContext;
|
||||||
|
unsigned char MDDigest[MD5Length];
|
||||||
|
|
||||||
|
MD5Init(&MDContext);
|
||||||
|
MD5Update(&MDContext, [MDData bytes], [MDData length]);
|
||||||
|
MD5Final(MDDigest, &MDContext);
|
||||||
|
|
||||||
|
char *stringBuffer = (char *)malloc(MD5Length * 2 + 1);
|
||||||
|
char *hexBuffer = stringBuffer;
|
||||||
|
|
||||||
|
for (int i=0; i<MD5Length; i++) {
|
||||||
|
*hexBuffer++ = hexdigits[(MDDigest[i] >> 4) & 0xF];
|
||||||
|
*hexBuffer++ = hexdigits[MDDigest[i] & 0xF];
|
||||||
|
}
|
||||||
|
*hexBuffer = '\0';
|
||||||
|
NSString *hash = [NSString stringWithUTF8String:stringBuffer];
|
||||||
|
free(stringBuffer);
|
||||||
|
return hash;
|
||||||
|
}
|
||||||
|
- (NSString *)pathMD5 {
|
||||||
|
NSFileHandle *file = [NSFileHandle fileHandleForReadingAtPath:self];
|
||||||
|
if (file==nil)
|
||||||
|
return nil;
|
||||||
|
struct MD5Context MDContext;
|
||||||
|
unsigned char MDDigest[MD5Length];
|
||||||
|
|
||||||
|
MD5Init(&MDContext);
|
||||||
|
int length;
|
||||||
|
do {
|
||||||
|
NSAutoreleasePool *pool = [NSAutoreleasePool new];
|
||||||
|
NSData *MDData = [file readDataOfLength:MDFileReadLength];
|
||||||
|
length = [MDData length];
|
||||||
|
MD5Update(&MDContext, [MDData bytes], length);
|
||||||
|
[pool release];
|
||||||
|
} while (length>0);
|
||||||
|
MD5Final(MDDigest, &MDContext);
|
||||||
|
|
||||||
|
char *stringBuffer = (char *)malloc(MD5Length * 2 + 1);
|
||||||
|
char *hexBuffer = stringBuffer;
|
||||||
|
|
||||||
|
for (int i=0; i<MD5Length; i++) {
|
||||||
|
*hexBuffer++ = hexdigits[(MDDigest[i] >> 4) & 0xF];
|
||||||
|
*hexBuffer++ = hexdigits[MDDigest[i] & 0xF];
|
||||||
|
}
|
||||||
|
*hexBuffer = '\0';
|
||||||
|
NSString *hash = [NSString stringWithUTF8String:stringBuffer];
|
||||||
|
free(stringBuffer);
|
||||||
|
return hash;
|
||||||
|
}
|
||||||
|
@end
|
||||||
|
#else
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include "MGMMD5.h"
|
||||||
|
#include "MGMTypes.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
char *MD5String(const char *string, int length) {
|
||||||
|
struct MD5Context MDContext;
|
||||||
|
unsigned char MDDigest[MD5Length];
|
||||||
|
|
||||||
|
MD5Init(&MDContext);
|
||||||
|
MD5Update(&MDContext, (const unsigned char *)string, length);
|
||||||
|
MD5Final(MDDigest, &MDContext);
|
||||||
|
|
||||||
|
char *stringBuffer = (char *)malloc(MD5Length * 2 + 1);
|
||||||
|
char *hexBuffer = stringBuffer;
|
||||||
|
|
||||||
|
for (int i=0; i<MD5Length; i++) {
|
||||||
|
*hexBuffer++ = hexdigits[(MDDigest[i] >> 4) & 0xF];
|
||||||
|
*hexBuffer++ = hexdigits[MDDigest[i] & 0xF];
|
||||||
|
}
|
||||||
|
*hexBuffer = '\0';
|
||||||
|
|
||||||
|
return stringBuffer;
|
||||||
|
}
|
||||||
|
char *MD5File(const char *path) {
|
||||||
|
FILE *file = fopen(path, "r");
|
||||||
|
if (file==NULL)
|
||||||
|
return NULL;
|
||||||
|
struct MD5Context MDContext;
|
||||||
|
unsigned char MDDigest[MD5Length];
|
||||||
|
|
||||||
|
MD5Init(&MDContext);
|
||||||
|
int length;
|
||||||
|
do {
|
||||||
|
unsigned char MDData[MDFileReadLength];
|
||||||
|
length = fread(&MDData, 1, MDFileReadLength, file);
|
||||||
|
MD5Update(&MDContext, MDData, length);
|
||||||
|
} while (length>0);
|
||||||
|
MD5Final(MDDigest, &MDContext);
|
||||||
|
|
||||||
|
fclose(file);
|
||||||
|
|
||||||
|
char *stringBuffer = (char *)malloc(MD5Length * 2 + 1);
|
||||||
|
char *hexBuffer = stringBuffer;
|
||||||
|
|
||||||
|
for (int i=0; i<MD5Length; i++) {
|
||||||
|
*hexBuffer++ = hexdigits[(MDDigest[i] >> 4) & 0xF];
|
||||||
|
*hexBuffer++ = hexdigits[MDDigest[i] & 0xF];
|
||||||
|
}
|
||||||
|
*hexBuffer = '\0';
|
||||||
|
|
||||||
|
return stringBuffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MD5Init(struct MD5Context *context) {
|
||||||
|
context->buf[0] = 0x67452301;
|
||||||
|
context->buf[1] = 0xefcdab89;
|
||||||
|
context->buf[2] = 0x98badcfe;
|
||||||
|
context->buf[3] = 0x10325476;
|
||||||
|
|
||||||
|
context->bits[0] = 0;
|
||||||
|
context->bits[1] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MD5Update(struct MD5Context *context, const unsigned char *buf, unsigned len) {
|
||||||
|
uint32_t t;
|
||||||
|
|
||||||
|
t = context->bits[0];
|
||||||
|
if ((context->bits[0] = (t + ((uint32_t)len << 3))) < t)
|
||||||
|
context->bits[1]++;
|
||||||
|
context->bits[1] += len >> 29;
|
||||||
|
|
||||||
|
t = (t >> 3) & 0x3f;
|
||||||
|
|
||||||
|
if (t!=0) {
|
||||||
|
unsigned char *p = context->in + t;
|
||||||
|
|
||||||
|
t = 64-t;
|
||||||
|
if (len < t) {
|
||||||
|
memcpy(p, buf, len);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
memcpy(p, buf, t);
|
||||||
|
MD5Transform(context->buf, context->in);
|
||||||
|
buf += t;
|
||||||
|
len -= t;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (len >= 64) {
|
||||||
|
memcpy(context->in, buf, 64);
|
||||||
|
MD5Transform(context->buf, context->in);
|
||||||
|
buf += 64;
|
||||||
|
len -= 64;
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(context->in, buf, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MD5Final(unsigned char digest[MD5Length], struct MD5Context *context) {
|
||||||
|
unsigned count;
|
||||||
|
unsigned char *p;
|
||||||
|
|
||||||
|
count = (context->bits[0] >> 3) & 0x3F;
|
||||||
|
|
||||||
|
p = context->in + count;
|
||||||
|
*p++ = MDPadding[0];
|
||||||
|
|
||||||
|
count = 64 - 1 - count;
|
||||||
|
|
||||||
|
if (count < 8) {
|
||||||
|
memset(p, MDPadding[1], count);
|
||||||
|
MD5Transform(context->buf, context->in);
|
||||||
|
|
||||||
|
memset(context->in, MDPadding[1], 56);
|
||||||
|
} else {
|
||||||
|
memset(p, MDPadding[1], count-8);
|
||||||
|
}
|
||||||
|
|
||||||
|
putu32l(context->bits[0], context->in + 56);
|
||||||
|
putu32l(context->bits[1], context->in + 60);
|
||||||
|
|
||||||
|
MD5Transform(context->buf, context->in);
|
||||||
|
for (int i=0; i<4; i++)
|
||||||
|
putu32l(context->buf[i], digest + (4 * i));
|
||||||
|
|
||||||
|
memset(context, 0, sizeof(context));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* #define MD5_F1(x, y, z) (x & y | ~x & z) */
|
||||||
|
#define MD5_F1(x, y, z) (z ^ (x & (y ^ z)))
|
||||||
|
#define MD5_F2(x, y, z) MD5_F1(z, x, y)
|
||||||
|
#define MD5_F3(x, y, z) (x ^ y ^ z)
|
||||||
|
#define MD5_F4(x, y, z) (y ^ (x | ~z))
|
||||||
|
|
||||||
|
#define MD5STEP(f, w, x, y, z, data, s) \
|
||||||
|
( w += f(x, y, z) + data, w &= 0xffffffff, w = w<<s | w>>(32-s), w += x )
|
||||||
|
|
||||||
|
void MD5Transform(uint32_t buf[MD5BufferSize], const unsigned char inraw[64]) {
|
||||||
|
uint32_t in[16];
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < 16; ++i) {
|
||||||
|
in[i] = getu32l(inraw+4*i);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t a = buf[0];
|
||||||
|
uint32_t b = buf[1];
|
||||||
|
uint32_t c = buf[2];
|
||||||
|
uint32_t d = buf[3];
|
||||||
|
|
||||||
|
// Round 1
|
||||||
|
MD5STEP(MD5_F1, a, b, c, d, in[ 0]+0xd76aa478, 7);
|
||||||
|
MD5STEP(MD5_F1, d, a, b, c, in[ 1]+0xe8c7b756, 12);
|
||||||
|
MD5STEP(MD5_F1, c, d, a, b, in[ 2]+0x242070db, 17);
|
||||||
|
MD5STEP(MD5_F1, b, c, d, a, in[ 3]+0xc1bdceee, 22);
|
||||||
|
MD5STEP(MD5_F1, a, b, c, d, in[ 4]+0xf57c0faf, 7);
|
||||||
|
MD5STEP(MD5_F1, d, a, b, c, in[ 5]+0x4787c62a, 12);
|
||||||
|
MD5STEP(MD5_F1, c, d, a, b, in[ 6]+0xa8304613, 17);
|
||||||
|
MD5STEP(MD5_F1, b, c, d, a, in[ 7]+0xfd469501, 22);
|
||||||
|
MD5STEP(MD5_F1, a, b, c, d, in[ 8]+0x698098d8, 7);
|
||||||
|
MD5STEP(MD5_F1, d, a, b, c, in[ 9]+0x8b44f7af, 12);
|
||||||
|
MD5STEP(MD5_F1, c, d, a, b, in[10]+0xffff5bb1, 17);
|
||||||
|
MD5STEP(MD5_F1, b, c, d, a, in[11]+0x895cd7be, 22);
|
||||||
|
MD5STEP(MD5_F1, a, b, c, d, in[12]+0x6b901122, 7);
|
||||||
|
MD5STEP(MD5_F1, d, a, b, c, in[13]+0xfd987193, 12);
|
||||||
|
MD5STEP(MD5_F1, c, d, a, b, in[14]+0xa679438e, 17);
|
||||||
|
MD5STEP(MD5_F1, b, c, d, a, in[15]+0x49b40821, 22);
|
||||||
|
|
||||||
|
// Round 2
|
||||||
|
MD5STEP(MD5_F2, a, b, c, d, in[ 1]+0xf61e2562, 5);
|
||||||
|
MD5STEP(MD5_F2, d, a, b, c, in[ 6]+0xc040b340, 9);
|
||||||
|
MD5STEP(MD5_F2, c, d, a, b, in[11]+0x265e5a51, 14);
|
||||||
|
MD5STEP(MD5_F2, b, c, d, a, in[ 0]+0xe9b6c7aa, 20);
|
||||||
|
MD5STEP(MD5_F2, a, b, c, d, in[ 5]+0xd62f105d, 5);
|
||||||
|
MD5STEP(MD5_F2, d, a, b, c, in[10]+0x02441453, 9);
|
||||||
|
MD5STEP(MD5_F2, c, d, a, b, in[15]+0xd8a1e681, 14);
|
||||||
|
MD5STEP(MD5_F2, b, c, d, a, in[ 4]+0xe7d3fbc8, 20);
|
||||||
|
MD5STEP(MD5_F2, a, b, c, d, in[ 9]+0x21e1cde6, 5);
|
||||||
|
MD5STEP(MD5_F2, d, a, b, c, in[14]+0xc33707d6, 9);
|
||||||
|
MD5STEP(MD5_F2, c, d, a, b, in[ 3]+0xf4d50d87, 14);
|
||||||
|
MD5STEP(MD5_F2, b, c, d, a, in[ 8]+0x455a14ed, 20);
|
||||||
|
MD5STEP(MD5_F2, a, b, c, d, in[13]+0xa9e3e905, 5);
|
||||||
|
MD5STEP(MD5_F2, d, a, b, c, in[ 2]+0xfcefa3f8, 9);
|
||||||
|
MD5STEP(MD5_F2, c, d, a, b, in[ 7]+0x676f02d9, 14);
|
||||||
|
MD5STEP(MD5_F2, b, c, d, a, in[12]+0x8d2a4c8a, 20);
|
||||||
|
|
||||||
|
// Round 3
|
||||||
|
MD5STEP(MD5_F3, a, b, c, d, in[ 5]+0xfffa3942, 4);
|
||||||
|
MD5STEP(MD5_F3, d, a, b, c, in[ 8]+0x8771f681, 11);
|
||||||
|
MD5STEP(MD5_F3, c, d, a, b, in[11]+0x6d9d6122, 16);
|
||||||
|
MD5STEP(MD5_F3, b, c, d, a, in[14]+0xfde5380c, 23);
|
||||||
|
MD5STEP(MD5_F3, a, b, c, d, in[ 1]+0xa4beea44, 4);
|
||||||
|
MD5STEP(MD5_F3, d, a, b, c, in[ 4]+0x4bdecfa9, 11);
|
||||||
|
MD5STEP(MD5_F3, c, d, a, b, in[ 7]+0xf6bb4b60, 16);
|
||||||
|
MD5STEP(MD5_F3, b, c, d, a, in[10]+0xbebfbc70, 23);
|
||||||
|
MD5STEP(MD5_F3, a, b, c, d, in[13]+0x289b7ec6, 4);
|
||||||
|
MD5STEP(MD5_F3, d, a, b, c, in[ 0]+0xeaa127fa, 11);
|
||||||
|
MD5STEP(MD5_F3, c, d, a, b, in[ 3]+0xd4ef3085, 16);
|
||||||
|
MD5STEP(MD5_F3, b, c, d, a, in[ 6]+0x04881d05, 23);
|
||||||
|
MD5STEP(MD5_F3, a, b, c, d, in[ 9]+0xd9d4d039, 4);
|
||||||
|
MD5STEP(MD5_F3, d, a, b, c, in[12]+0xe6db99e5, 11);
|
||||||
|
MD5STEP(MD5_F3, c, d, a, b, in[15]+0x1fa27cf8, 16);
|
||||||
|
MD5STEP(MD5_F3, b, c, d, a, in[ 2]+0xc4ac5665, 23);
|
||||||
|
|
||||||
|
// Round 4
|
||||||
|
MD5STEP(MD5_F4, a, b, c, d, in[ 0]+0xf4292244, 6);
|
||||||
|
MD5STEP(MD5_F4, d, a, b, c, in[ 7]+0x432aff97, 10);
|
||||||
|
MD5STEP(MD5_F4, c, d, a, b, in[14]+0xab9423a7, 15);
|
||||||
|
MD5STEP(MD5_F4, b, c, d, a, in[ 5]+0xfc93a039, 21);
|
||||||
|
MD5STEP(MD5_F4, a, b, c, d, in[12]+0x655b59c3, 6);
|
||||||
|
MD5STEP(MD5_F4, d, a, b, c, in[ 3]+0x8f0ccc92, 10);
|
||||||
|
MD5STEP(MD5_F4, c, d, a, b, in[10]+0xffeff47d, 15);
|
||||||
|
MD5STEP(MD5_F4, b, c, d, a, in[ 1]+0x85845dd1, 21);
|
||||||
|
MD5STEP(MD5_F4, a, b, c, d, in[ 8]+0x6fa87e4f, 6);
|
||||||
|
MD5STEP(MD5_F4, d, a, b, c, in[15]+0xfe2ce6e0, 10);
|
||||||
|
MD5STEP(MD5_F4, c, d, a, b, in[ 6]+0xa3014314, 15);
|
||||||
|
MD5STEP(MD5_F4, b, c, d, a, in[13]+0x4e0811a1, 21);
|
||||||
|
MD5STEP(MD5_F4, a, b, c, d, in[ 4]+0xf7537e82, 6);
|
||||||
|
MD5STEP(MD5_F4, d, a, b, c, in[11]+0xbd3af235, 10);
|
||||||
|
MD5STEP(MD5_F4, c, d, a, b, in[ 2]+0x2ad7d2bb, 15);
|
||||||
|
MD5STEP(MD5_F4, b, c, d, a, in[ 9]+0xeb86d391, 21);
|
||||||
|
|
||||||
|
buf[0] += a;
|
||||||
|
buf[1] += b;
|
||||||
|
buf[2] += c;
|
||||||
|
buf[3] += d;
|
||||||
|
}
|
33
Classes/MGMPathSubscriber.h
Normal file
33
Classes/MGMPathSubscriber.h
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
//
|
||||||
|
// MGMPathSubscriber.h
|
||||||
|
// SoundNote
|
||||||
|
//
|
||||||
|
// Created by Mr. Gecko on 1/15/11.
|
||||||
|
// Copyright (c) 2011 Mr. Gecko's Media (James Coleman). All rights reserved. http://mrgeckosmedia.com/
|
||||||
|
//
|
||||||
|
|
||||||
|
#import <Foundation/Foundation.h>
|
||||||
|
|
||||||
|
extern NSString * const MGMPathSubscriptionChangedNotification;
|
||||||
|
|
||||||
|
@protocol MGMPathSubscriberDelegate <NSObject>
|
||||||
|
- (void)subscribedPathChanged:(NSString *)thePath;
|
||||||
|
@end
|
||||||
|
|
||||||
|
@interface MGMPathSubscriber : NSObject {
|
||||||
|
id<MGMPathSubscriberDelegate> delegate;
|
||||||
|
NSMutableDictionary *subscriptions;
|
||||||
|
FNSubscriptionUPP subscriptionUPP;
|
||||||
|
NSMutableArray *notificationsSending;
|
||||||
|
}
|
||||||
|
+ (id)sharedPathSubscriber;
|
||||||
|
|
||||||
|
- (id<MGMPathSubscriberDelegate>)delegate;
|
||||||
|
- (void)setDelegate:(id)theDelegate;
|
||||||
|
|
||||||
|
- (void)addPath:(NSString *)thePath;
|
||||||
|
- (void)removePath:(NSString *)thePath;
|
||||||
|
- (void)removeAllPaths;
|
||||||
|
|
||||||
|
- (NSArray *)subscribedPaths;
|
||||||
|
@end
|
101
Classes/MGMPathSubscriber.m
Normal file
101
Classes/MGMPathSubscriber.m
Normal file
@ -0,0 +1,101 @@
|
|||||||
|
//
|
||||||
|
// MGMPathSubscriber.m
|
||||||
|
// SoundNote
|
||||||
|
//
|
||||||
|
// Created by Mr. Gecko on 1/15/11.
|
||||||
|
// Copyright (c) 2011 Mr. Gecko's Media (James Coleman). All rights reserved. http://mrgeckosmedia.com/
|
||||||
|
//
|
||||||
|
|
||||||
|
#import "MGMPathSubscriber.h"
|
||||||
|
|
||||||
|
@interface MGMPathSubscriber (MGMPrivate)
|
||||||
|
- (void)subscriptionChanged:(FNSubscriptionRef)theSubscription;
|
||||||
|
- (void)sendNotificationForPath:(NSString *)thePath;
|
||||||
|
@end
|
||||||
|
|
||||||
|
static MGMPathSubscriber *MGMSharedPathSubscriber;
|
||||||
|
NSString * const MGMSubscribedPathChangedNotification = @"MGMSubscribedPathChangedNotification";
|
||||||
|
|
||||||
|
void MGMPathSubscriptionChange(FNMessage theMessage, OptionBits theFlags, void *thePathSubscription, FNSubscriptionRef theSubscription) {
|
||||||
|
if (theMessage==kFNDirectoryModifiedMessage)
|
||||||
|
[(MGMPathSubscriber *)thePathSubscription subscriptionChanged:theSubscription];
|
||||||
|
else
|
||||||
|
NSLog(@"MGMPathSubscription: Received Unknown message: %d", (int)theMessage);
|
||||||
|
}
|
||||||
|
|
||||||
|
@implementation MGMPathSubscriber
|
||||||
|
+ (id)sharedPathSubscriber {
|
||||||
|
if (MGMSharedPathSubscriber==nil)
|
||||||
|
MGMSharedPathSubscriber = [MGMPathSubscriber new];
|
||||||
|
return MGMSharedPathSubscriber;
|
||||||
|
}
|
||||||
|
- (id)init {
|
||||||
|
if ((self = [super init])) {
|
||||||
|
subscriptions = [NSMutableDictionary new];
|
||||||
|
subscriptionUPP = NewFNSubscriptionUPP(MGMPathSubscriptionChange);
|
||||||
|
notificationsSending = [NSMutableArray new];
|
||||||
|
}
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
- (void)dealloc {
|
||||||
|
[self removeAllPaths];
|
||||||
|
DisposeFNSubscriptionUPP(subscriptionUPP);
|
||||||
|
[subscriptions release];
|
||||||
|
[notificationsSending release];
|
||||||
|
[super dealloc];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (id<MGMPathSubscriberDelegate>)delegate {
|
||||||
|
return delegate;
|
||||||
|
}
|
||||||
|
- (void)setDelegate:(id)theDelegate {
|
||||||
|
delegate = theDelegate;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)addPath:(NSString *)thePath {
|
||||||
|
NSValue *value = [subscriptions objectForKey:thePath];
|
||||||
|
if (value!=nil)
|
||||||
|
return;
|
||||||
|
FNSubscriptionRef subscription = NULL;
|
||||||
|
OSStatus error = FNSubscribeByPath((UInt8 *)[thePath fileSystemRepresentation], subscriptionUPP, self, kFNNotifyInBackground, &subscription);
|
||||||
|
if (error!=noErr) {
|
||||||
|
NSLog(@"MGMPathSubscription: Unable to subscribe to %@ due to the error %ld", thePath, (long)error);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
[subscriptions setObject:[NSValue valueWithPointer:subscription] forKey:thePath];
|
||||||
|
}
|
||||||
|
- (void)removePath:(NSString *)thePath {
|
||||||
|
NSValue *value = [subscriptions objectForKey:thePath];
|
||||||
|
if (value!=nil) {
|
||||||
|
FNUnsubscribe([value pointerValue]);
|
||||||
|
[subscriptions removeObjectForKey:thePath];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
- (void)removeAllPaths {
|
||||||
|
NSArray *keys = [subscriptions allKeys];
|
||||||
|
for (int i=0; i<[keys count]; i++) {
|
||||||
|
FNUnsubscribe([[subscriptions objectForKey:[keys objectAtIndex:i]] pointerValue]);
|
||||||
|
}
|
||||||
|
[subscriptions removeAllObjects];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (NSArray *)subscribedPaths {
|
||||||
|
return [subscriptions allKeys];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)subscriptionChanged:(FNSubscriptionRef)theSubscription {
|
||||||
|
NSArray *keys = [subscriptions allKeysForObject:[NSValue valueWithPointer:theSubscription]];
|
||||||
|
if ([keys count]>=1) {
|
||||||
|
NSString *path = [keys objectAtIndex:0];
|
||||||
|
if (![notificationsSending containsObject:path]) {
|
||||||
|
[notificationsSending addObject:path];
|
||||||
|
[self performSelector:@selector(sendNotificationForPath:) withObject:path afterDelay:0.5];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
- (void)sendNotificationForPath:(NSString *)thePath {
|
||||||
|
[[NSNotificationCenter defaultCenter] postNotificationName:MGMSubscribedPathChangedNotification object:thePath];
|
||||||
|
if ([delegate respondsToSelector:@selector(subscribedPathChanged:)]) [delegate subscribedPathChanged:thePath];
|
||||||
|
[notificationsSending removeObject:thePath];
|
||||||
|
}
|
||||||
|
@end
|
52
Classes/MGMSound.h
Normal file
52
Classes/MGMSound.h
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
//
|
||||||
|
// MGMSound.h
|
||||||
|
// SoundNote
|
||||||
|
//
|
||||||
|
// Created by Mr. Gecko on 9/23/10.
|
||||||
|
// Copyright (c) 2011 Mr. Gecko's Media (James Coleman). All rights reserved. http://mrgeckosmedia.com/
|
||||||
|
//
|
||||||
|
|
||||||
|
#if TARGET_OS_IPHONE
|
||||||
|
#import <UIKit/UIKit.h>
|
||||||
|
#import <AVFoundation/AVFoundation.h>
|
||||||
|
#else
|
||||||
|
#import <Cocoa/Cocoa.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
@class MGMSound;
|
||||||
|
|
||||||
|
@protocol MGMSoundDelegate <NSObject>
|
||||||
|
- (void)soundDidFinishPlaying:(MGMSound *)theSound;
|
||||||
|
@end
|
||||||
|
|
||||||
|
@interface MGMSound : NSObject
|
||||||
|
#if TARGET_OS_IPHONE
|
||||||
|
<AVAudioPlayerDelegate>
|
||||||
|
#else
|
||||||
|
<NSSoundDelegate>
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
#if TARGET_OS_IPHONE
|
||||||
|
AVAudioPlayer *sound;
|
||||||
|
#else
|
||||||
|
NSSound *sound;
|
||||||
|
#endif
|
||||||
|
id<MGMSoundDelegate> delegate;
|
||||||
|
|
||||||
|
BOOL loops;
|
||||||
|
}
|
||||||
|
- (id)initWithContentsOfFile:(NSString *)theFile;
|
||||||
|
- (id)initWithContentsOfURL:(NSURL *)theURL;
|
||||||
|
- (id)initWithData:(NSData *)theData;
|
||||||
|
|
||||||
|
- (void)setDelegate:(id)theDelegate;
|
||||||
|
- (id<MGMSoundDelegate>)delegate;
|
||||||
|
|
||||||
|
- (void)setLoops:(BOOL)shouldLoop;
|
||||||
|
- (BOOL)loops;
|
||||||
|
|
||||||
|
- (void)play;
|
||||||
|
- (void)pause;
|
||||||
|
- (void)stop;
|
||||||
|
- (BOOL)isPlaying;
|
||||||
|
@end
|
98
Classes/MGMSound.m
Normal file
98
Classes/MGMSound.m
Normal file
@ -0,0 +1,98 @@
|
|||||||
|
//
|
||||||
|
// MGMSound.m
|
||||||
|
// SoundNote
|
||||||
|
//
|
||||||
|
// Created by Mr. Gecko on 9/23/10.
|
||||||
|
// Copyright (c) 2011 Mr. Gecko's Media (James Coleman). All rights reserved. http://mrgeckosmedia.com/
|
||||||
|
//
|
||||||
|
|
||||||
|
#import "MGMSound.h"
|
||||||
|
|
||||||
|
@implementation MGMSound
|
||||||
|
- (id)init {
|
||||||
|
if ((self = [super init])) {
|
||||||
|
loops = NO;
|
||||||
|
}
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
- (id)initWithContentsOfFile:(NSString *)theFile {
|
||||||
|
return [self initWithContentsOfURL:[NSURL fileURLWithPath:theFile]];
|
||||||
|
}
|
||||||
|
- (id)initWithContentsOfURL:(NSURL *)theURL {
|
||||||
|
if ((self = [self init])) {
|
||||||
|
#if TARGET_OS_IPHONE
|
||||||
|
sound = [[AVAudioPlayer alloc] initWithContentsOfURL:theURL error:nil];
|
||||||
|
#else
|
||||||
|
sound = [[NSSound alloc] initWithContentsOfURL:theURL byReference:YES];
|
||||||
|
#endif
|
||||||
|
[sound setDelegate:self];
|
||||||
|
}
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
- (id)initWithData:(NSData *)theData {
|
||||||
|
if ((self = [self init])) {
|
||||||
|
#if TARGET_OS_IPHONE
|
||||||
|
sound = [[AVAudioPlayer alloc] initWithData:theData error:nil];
|
||||||
|
#else
|
||||||
|
sound = [[NSSound alloc] initWithData:theData];
|
||||||
|
#endif
|
||||||
|
[sound setDelegate:self];
|
||||||
|
}
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
- (void)dealloc {
|
||||||
|
[sound setDelegate:nil];
|
||||||
|
[sound stop];
|
||||||
|
[sound release];
|
||||||
|
[super dealloc];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)setDelegate:(id)theDelegate {
|
||||||
|
delegate = theDelegate;
|
||||||
|
}
|
||||||
|
- (id<MGMSoundDelegate>)delegate {
|
||||||
|
return delegate;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if TARGET_OS_IPHONE
|
||||||
|
- (void)audioPlayerDidFinishPlaying:(AVAudioPlayer *)player successfully:(BOOL)flag {
|
||||||
|
if (loops) {
|
||||||
|
[sound stop];
|
||||||
|
[sound play];
|
||||||
|
} else {
|
||||||
|
if (delegate!=nil && [delegate respondsToSelector:@selector(soundDidFinishPlaying:)]) [delegate soundDidFinishPlaying:self];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
- (void)sound:(NSSound *)theSound didFinishPlaying:(BOOL)finishedPlaying {
|
||||||
|
if (finishedPlaying) {
|
||||||
|
if (loops) {
|
||||||
|
[sound stop];
|
||||||
|
[sound play];
|
||||||
|
} else {
|
||||||
|
if (delegate!=nil && [delegate respondsToSelector:@selector(soundDidFinishPlaying:)]) [delegate soundDidFinishPlaying:self];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
- (void)setLoops:(BOOL)shouldLoop {
|
||||||
|
loops = shouldLoop;
|
||||||
|
}
|
||||||
|
- (BOOL)loops {
|
||||||
|
return loops;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)play {
|
||||||
|
[sound performSelectorOnMainThread:@selector(play) withObject:nil waitUntilDone:YES];
|
||||||
|
}
|
||||||
|
- (void)pause {
|
||||||
|
[sound pause];
|
||||||
|
}
|
||||||
|
- (void)stop {
|
||||||
|
[sound stop];
|
||||||
|
}
|
||||||
|
- (BOOL)isPlaying {
|
||||||
|
return [sound isPlaying];
|
||||||
|
}
|
||||||
|
@end
|
100
Classes/MGMTypes.h
Normal file
100
Classes/MGMTypes.h
Normal file
@ -0,0 +1,100 @@
|
|||||||
|
//
|
||||||
|
// MGMTypes.h
|
||||||
|
//
|
||||||
|
// Created by Mr. Gecko on 2/24/10.
|
||||||
|
// No Copyright Claimed. Public Domain.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifdef __NEXT_RUNTIME__
|
||||||
|
#import <Foundation/Foundation.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define INT64(n) n ## ULL
|
||||||
|
|
||||||
|
#define ROR32(x, b) ((x >> b) | (x << (32 - b)))
|
||||||
|
#define ROR64(x, b) ((x >> b) | (x << (64 - b)))
|
||||||
|
#define SHR(x, b) (x >> b)
|
||||||
|
|
||||||
|
#define MDFileReadLength 1048576
|
||||||
|
|
||||||
|
static const char hexdigits[] = "0123456789abcdef";
|
||||||
|
|
||||||
|
static const unsigned char MDPadding[128] =
|
||||||
|
{
|
||||||
|
0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
|
||||||
|
};
|
||||||
|
|
||||||
|
static uint32_t getu32(const uint8_t *addr) {
|
||||||
|
return ((uint32_t)addr[0] << 24)
|
||||||
|
| ((uint32_t)addr[1] << 16)
|
||||||
|
| ((uint32_t)addr[2] << 8)
|
||||||
|
| ((uint32_t)addr[3]);
|
||||||
|
}
|
||||||
|
static void putu32(uint32_t data, uint8_t *addr) {
|
||||||
|
addr[0] = (uint8_t)(data >> 24);
|
||||||
|
addr[1] = (uint8_t)(data >> 16);
|
||||||
|
addr[2] = (uint8_t)(data >> 8);
|
||||||
|
addr[3] = (uint8_t)data;
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint64_t getu64(const uint8_t *addr) {
|
||||||
|
return ((uint64_t)addr[0] << 56)
|
||||||
|
| ((uint64_t)addr[1] << 48)
|
||||||
|
| ((uint64_t)addr[2] << 40)
|
||||||
|
| ((uint64_t)addr[3] << 32)
|
||||||
|
| ((uint64_t)addr[4] << 24)
|
||||||
|
| ((uint64_t)addr[5] << 16)
|
||||||
|
| ((uint64_t)addr[6] << 8)
|
||||||
|
| ((uint64_t)addr[7]);
|
||||||
|
}
|
||||||
|
static void putu64(uint64_t data, uint8_t *addr) {
|
||||||
|
addr[0] = (uint8_t)(data >> 56);
|
||||||
|
addr[1] = (uint8_t)(data >> 48);
|
||||||
|
addr[2] = (uint8_t)(data >> 40);
|
||||||
|
addr[3] = (uint8_t)(data >> 32);
|
||||||
|
addr[4] = (uint8_t)(data >> 24);
|
||||||
|
addr[5] = (uint8_t)(data >> 16);
|
||||||
|
addr[6] = (uint8_t)(data >> 8);
|
||||||
|
addr[7] = (uint8_t)data;
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint32_t getu32l(const uint8_t *addr) {
|
||||||
|
return ((uint32_t)addr[0])
|
||||||
|
| ((uint32_t)addr[1] << 8)
|
||||||
|
| ((uint32_t)addr[2] << 16)
|
||||||
|
| ((uint32_t)addr[3] << 24);
|
||||||
|
}
|
||||||
|
static void putu32l(uint32_t data, uint8_t *addr) {
|
||||||
|
addr[0] = (uint8_t)data;
|
||||||
|
addr[1] = (uint8_t)(data >> 8);
|
||||||
|
addr[2] = (uint8_t)(data >> 16);
|
||||||
|
addr[3] = (uint8_t)(data >> 24);
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint64_t getu64l(const uint8_t *addr) {
|
||||||
|
return ((uint64_t)addr[0])
|
||||||
|
| ((uint64_t)addr[1] << 8)
|
||||||
|
| ((uint64_t)addr[2] << 16)
|
||||||
|
| ((uint64_t)addr[3] << 24)
|
||||||
|
| ((uint64_t)addr[4] << 32)
|
||||||
|
| ((uint64_t)addr[5] << 40)
|
||||||
|
| ((uint64_t)addr[6] << 48)
|
||||||
|
| ((uint64_t)addr[7] << 56);
|
||||||
|
}
|
||||||
|
static void putu64l(uint64_t data, uint8_t *addr) {
|
||||||
|
addr[0] = (uint8_t)data;
|
||||||
|
addr[1] = (uint8_t)(data >> 8);
|
||||||
|
addr[2] = (uint8_t)(data >> 16);
|
||||||
|
addr[3] = (uint8_t)(data >> 24);
|
||||||
|
addr[4] = (uint8_t)(data >> 32);
|
||||||
|
addr[5] = (uint8_t)(data >> 40);
|
||||||
|
addr[6] = (uint8_t)(data >> 48);
|
||||||
|
addr[7] = (uint8_t)(data >> 56);
|
||||||
|
}
|
17
Classes/Watchers/MGMAccessibleWatcher.h
Normal file
17
Classes/Watchers/MGMAccessibleWatcher.h
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
//
|
||||||
|
// MGMAccessibleWatcher.h
|
||||||
|
// SoundNote
|
||||||
|
//
|
||||||
|
// Created by Mr. Gecko on 2/17/11.
|
||||||
|
// Copyright (c) 2011 Mr. Gecko's Media (James Coleman). All rights reserved. http://mrgeckosmedia.com/
|
||||||
|
//
|
||||||
|
|
||||||
|
#import <Foundation/Foundation.h>
|
||||||
|
|
||||||
|
@interface MGMAccessibleWatcher : NSObject {
|
||||||
|
NSMutableDictionary *observers;
|
||||||
|
}
|
||||||
|
- (void)registerObserversFor:(NSDictionary *)application;
|
||||||
|
|
||||||
|
- (void)receivedNotification:(NSString *)theName process:(ProcessSerialNumber *)theProcess element:(AXUIElementRef)theElement;
|
||||||
|
@end
|
161
Classes/Watchers/MGMAccessibleWatcher.m
Normal file
161
Classes/Watchers/MGMAccessibleWatcher.m
Normal file
@ -0,0 +1,161 @@
|
|||||||
|
//
|
||||||
|
// MGMAccessibleWatcher.m
|
||||||
|
// SoundNote
|
||||||
|
//
|
||||||
|
// Created by Mr. Gecko on 2/17/11.
|
||||||
|
// Copyright (c) 2011 Mr. Gecko's Media (James Coleman). All rights reserved. http://mrgeckosmedia.com/
|
||||||
|
//
|
||||||
|
|
||||||
|
#import "MGMAccessibleWatcher.h"
|
||||||
|
#import "MGMController.h"
|
||||||
|
#import <GeckoReporter/GeckoReporter.h>
|
||||||
|
|
||||||
|
NSString *MGMANSApplicationProcessIdentifier = @"NSApplicationProcessIdentifier";
|
||||||
|
NSString *MGMANSApplicationName = @"NSApplicationName";
|
||||||
|
NSString *MGMBundlePath = @"BundlePath";
|
||||||
|
|
||||||
|
static void receivedNotification(AXObserverRef observer, AXUIElementRef element, CFStringRef notification, void *refcon) {
|
||||||
|
pid_t pid = 0;
|
||||||
|
AXUIElementGetPid(element, &pid);
|
||||||
|
ProcessSerialNumber process;
|
||||||
|
GetProcessForPID(pid, &process);
|
||||||
|
[(MGMAccessibleWatcher *)refcon receivedNotification:(NSString *)notification process:&process element:element];
|
||||||
|
}
|
||||||
|
|
||||||
|
@implementation MGMAccessibleWatcher
|
||||||
|
- (id)init {
|
||||||
|
if ((self = [super init])) {
|
||||||
|
if (!AXAPIEnabled()) {
|
||||||
|
NSAlert *alert = [[NSAlert new] autorelease];
|
||||||
|
[alert setMessageText:@"'Enable access for assistive devices' is not enabled."];
|
||||||
|
[alert setInformativeText:@"For Accessible Notifications to work, you must have 'Enable access for assistive devices' in the 'Universal Access' preferences panel enabled. Once you have enabled this, you can quit SoundNote by opening it in the finder and pressing command (apple) and the q key and relaunch it to gain these features."];
|
||||||
|
[alert runModal];
|
||||||
|
} else {
|
||||||
|
observers = [NSMutableDictionary new];
|
||||||
|
NSNotificationCenter *notificationCenter = [[NSWorkspace sharedWorkspace] notificationCenter];
|
||||||
|
[notificationCenter addObserver:self selector:@selector(applicationDidLaunch:) name:NSWorkspaceDidLaunchApplicationNotification object:nil];
|
||||||
|
[notificationCenter addObserver:self selector:@selector(applicationDidTerminate:) name:NSWorkspaceDidTerminateApplicationNotification object:nil];
|
||||||
|
|
||||||
|
NSArray *applications = [[NSWorkspace sharedWorkspace] launchedApplications];
|
||||||
|
for (int i=0; i<[applications count]; i++) {
|
||||||
|
[self registerObserversFor:[applications objectAtIndex:i]];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
- (void)dealloc {
|
||||||
|
[[[NSWorkspace sharedWorkspace] notificationCenter] removeObserver:self];
|
||||||
|
NSArray *keys = [observers allKeys];
|
||||||
|
for (int i=0; i<[keys count]; i++) {
|
||||||
|
CFRunLoopRemoveSource(CFRunLoopGetCurrent(), AXObserverGetRunLoopSource((AXObserverRef)[observers objectForKey:[keys objectAtIndex:i]]), kCFRunLoopDefaultMode);
|
||||||
|
}
|
||||||
|
[observers release];
|
||||||
|
[super dealloc];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)applicationDidLaunch:(NSNotification *)theNotification {
|
||||||
|
[self registerObserversFor:[theNotification userInfo]];
|
||||||
|
}
|
||||||
|
- (void)applicationDidTerminate:(NSNotification *)theNotification {
|
||||||
|
NSNumber *pidNumber = [[theNotification userInfo] objectForKey:MGMANSApplicationProcessIdentifier];
|
||||||
|
AXObserverRef observer = (AXObserverRef)[observers objectForKey:pidNumber];
|
||||||
|
if (observer!=NULL) {
|
||||||
|
CFRunLoopRemoveSource(CFRunLoopGetCurrent(), AXObserverGetRunLoopSource(observer), kCFRunLoopDefaultMode);
|
||||||
|
[observers removeObjectForKey:pidNumber];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)observe:(CFStringRef)theNotification element:(AXUIElementRef)theElement observer:(AXObserverRef)theObserver application:(NSDictionary *)theApplication {
|
||||||
|
if (AXObserverAddNotification(theObserver, theElement, theNotification, self)!=kAXErrorSuccess)
|
||||||
|
NSLog(@"Unable to observe %@ for %@.", (NSString *)theNotification, [theApplication valueForKey:MGMANSApplicationName]);
|
||||||
|
}
|
||||||
|
- (void)registerObserversFor:(NSDictionary *)theApplication {
|
||||||
|
NSNumber *pidNumber = [theApplication objectForKey:MGMANSApplicationProcessIdentifier];
|
||||||
|
if ([pidNumber intValue]!=getpid()) {
|
||||||
|
if (![observers objectForKey:pidNumber]) {
|
||||||
|
pid_t pid = (pid_t)[pidNumber intValue];
|
||||||
|
AXObserverRef observer;
|
||||||
|
if (AXObserverCreate(pid, receivedNotification, &observer)==kAXErrorSuccess) {
|
||||||
|
CFRunLoopAddSource(CFRunLoopGetCurrent(), AXObserverGetRunLoopSource(observer), kCFRunLoopDefaultMode);
|
||||||
|
AXUIElementRef element = AXUIElementCreateApplication(pid);
|
||||||
|
[self observe:kAXFocusedWindowChangedNotification element:element observer:observer application:theApplication];
|
||||||
|
[self observe:kAXWindowCreatedNotification element:element observer:observer application:theApplication];
|
||||||
|
[self observe:kAXWindowMiniaturizedNotification element:element observer:observer application:theApplication];
|
||||||
|
[self observe:kAXWindowDeminiaturizedNotification element:element observer:observer application:theApplication];
|
||||||
|
[self observe:kAXDrawerCreatedNotification element:element observer:observer application:theApplication];
|
||||||
|
[self observe:kAXSheetCreatedNotification element:element observer:observer application:theApplication];
|
||||||
|
[self observe:kAXMenuOpenedNotification element:element observer:observer application:theApplication];
|
||||||
|
[self observe:kAXMenuClosedNotification element:element observer:observer application:theApplication];
|
||||||
|
[self observe:kAXMenuItemSelectedNotification element:element observer:observer application:theApplication];
|
||||||
|
[self observe:kAXRowExpandedNotification element:element observer:observer application:theApplication];
|
||||||
|
[self observe:kAXRowCollapsedNotification element:element observer:observer application:theApplication];
|
||||||
|
[self observe:kAXSelectedRowsChangedNotification element:element observer:observer application:theApplication];
|
||||||
|
if (![[MGMSystemInfo info] isAfterSnowLeopard]) {
|
||||||
|
[self observe:kAXApplicationHiddenNotification element:element observer:observer application:theApplication];
|
||||||
|
[self observe:kAXApplicationShownNotification element:element observer:observer application:theApplication];
|
||||||
|
}
|
||||||
|
[observers setObject:(id)observer forKey:pidNumber];
|
||||||
|
CFRelease(observer);
|
||||||
|
CFRelease(element);
|
||||||
|
} else {
|
||||||
|
NSLog(@"Unable to create observer for %@.", [theApplication valueForKey:MGMANSApplicationName]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)receivedNotification:(NSString *)theName process:(ProcessSerialNumber *)theProcess element:(AXUIElementRef)theElement {
|
||||||
|
NSDictionary *information = (NSDictionary *)ProcessInformationCopyDictionary(theProcess, kProcessDictionaryIncludeAllInformationMask);
|
||||||
|
if ([theName isEqual:(NSString *)kAXFocusedWindowChangedNotification]) {
|
||||||
|
CFTypeRef title;
|
||||||
|
AXUIElementCopyAttributeValue(theElement, CFSTR("AXTitle"), &title);
|
||||||
|
[[MGMController sharedController] startNotificationWithInfo:[NSDictionary dictionaryWithObjectsAndKeys:@"focusedwindowchanged", MGMNName, @"Focused Window Changed", MGMNTitle, [NSString stringWithFormat:@"%@ in %@", (NSString *)title, [information objectForKey:(NSString *)kCFBundleNameKey]], MGMNDescription, [[NSWorkspace sharedWorkspace] iconForFile:[information objectForKey:MGMBundlePath]], MGMNIcon, nil]];
|
||||||
|
if (title!=NULL)
|
||||||
|
CFRelease(title);
|
||||||
|
} else if ([theName isEqual:(NSString *)kAXWindowCreatedNotification]) {
|
||||||
|
CFTypeRef title;
|
||||||
|
AXUIElementCopyAttributeValue(theElement, CFSTR("AXTitle"), &title);
|
||||||
|
[[MGMController sharedController] startNotificationWithInfo:[NSDictionary dictionaryWithObjectsAndKeys:@"windowcreated", MGMNName, @"Window Created", MGMNTitle, [NSString stringWithFormat:@"%@ in %@", (NSString *)title, [information objectForKey:(NSString *)kCFBundleNameKey]], MGMNDescription, [[NSWorkspace sharedWorkspace] iconForFile:[information objectForKey:MGMBundlePath]], MGMNIcon, nil]];
|
||||||
|
if (title!=NULL)
|
||||||
|
CFRelease(title);
|
||||||
|
} else if ([theName isEqual:(NSString *)kAXWindowMiniaturizedNotification]) {
|
||||||
|
CFTypeRef title;
|
||||||
|
AXUIElementCopyAttributeValue(theElement, CFSTR("AXTitle"), &title);
|
||||||
|
[[MGMController sharedController] startNotificationWithInfo:[NSDictionary dictionaryWithObjectsAndKeys:@"windowminiaturized", MGMNName, @"Window Miniaturized", MGMNTitle, [NSString stringWithFormat:@"%@ in %@", (NSString *)title, [information objectForKey:(NSString *)kCFBundleNameKey]], MGMNDescription, [[NSWorkspace sharedWorkspace] iconForFile:[information objectForKey:MGMBundlePath]], MGMNIcon, nil]];
|
||||||
|
if (title!=NULL)
|
||||||
|
CFRelease(title);
|
||||||
|
} else if ([theName isEqual:(NSString *)kAXWindowDeminiaturizedNotification]) {
|
||||||
|
CFTypeRef title;
|
||||||
|
AXUIElementCopyAttributeValue(theElement, CFSTR("AXTitle"), &title);
|
||||||
|
[[MGMController sharedController] startNotificationWithInfo:[NSDictionary dictionaryWithObjectsAndKeys:@"windowdeminiaturized", MGMNName, @"Window Deminiaturized", MGMNTitle, [NSString stringWithFormat:@"%@ in %@", (NSString *)title, [information objectForKey:(NSString *)kCFBundleNameKey]], MGMNDescription, [[NSWorkspace sharedWorkspace] iconForFile:[information objectForKey:MGMBundlePath]], MGMNIcon, nil]];
|
||||||
|
if (title!=NULL)
|
||||||
|
CFRelease(title);
|
||||||
|
} else if ([theName isEqual:(NSString *)kAXDrawerCreatedNotification]) {
|
||||||
|
[[MGMController sharedController] startNotificationWithInfo:[NSDictionary dictionaryWithObjectsAndKeys:@"drawercreated", MGMNName, @"Drawer Created", MGMNTitle, [information objectForKey:(NSString *)kCFBundleNameKey], MGMNDescription, [[NSWorkspace sharedWorkspace] iconForFile:[information objectForKey:MGMBundlePath]], MGMNIcon, nil]];
|
||||||
|
} else if ([theName isEqual:(NSString *)kAXSheetCreatedNotification]) {
|
||||||
|
[[MGMController sharedController] startNotificationWithInfo:[NSDictionary dictionaryWithObjectsAndKeys:@"sheetcreated", MGMNName, @"Sheet Created", MGMNTitle, [information objectForKey:(NSString *)kCFBundleNameKey], MGMNDescription, [[NSWorkspace sharedWorkspace] iconForFile:[information objectForKey:MGMBundlePath]], MGMNIcon, nil]];
|
||||||
|
} else if ([theName isEqual:(NSString *)kAXMenuOpenedNotification]) {
|
||||||
|
[[MGMController sharedController] startNotificationWithInfo:[NSDictionary dictionaryWithObjectsAndKeys:@"menuopened", MGMNName, @"Menu Opened", MGMNTitle, [information objectForKey:(NSString *)kCFBundleNameKey], MGMNDescription, [[NSWorkspace sharedWorkspace] iconForFile:[information objectForKey:MGMBundlePath]], MGMNIcon, nil]];
|
||||||
|
} else if ([theName isEqual:(NSString *)kAXMenuClosedNotification]) {
|
||||||
|
[[MGMController sharedController] startNotificationWithInfo:[NSDictionary dictionaryWithObjectsAndKeys:@"menuclosed", MGMNName, @"Menu Closed", MGMNTitle, [information objectForKey:(NSString *)kCFBundleNameKey], MGMNDescription, [[NSWorkspace sharedWorkspace] iconForFile:[information objectForKey:MGMBundlePath]], MGMNIcon, nil]];
|
||||||
|
} else if ([theName isEqual:(NSString *)kAXMenuItemSelectedNotification]) {
|
||||||
|
CFTypeRef title;
|
||||||
|
AXUIElementCopyAttributeValue(theElement, CFSTR("AXTitle"), &title);
|
||||||
|
[[MGMController sharedController] startNotificationWithInfo:[NSDictionary dictionaryWithObjectsAndKeys:@"menuitemselected", MGMNName, @"Menu Item Selected", MGMNTitle, [NSString stringWithFormat:@"%@ in %@", (NSString *)title, [information objectForKey:(NSString *)kCFBundleNameKey]], MGMNDescription, [[NSWorkspace sharedWorkspace] iconForFile:[information objectForKey:MGMBundlePath]], MGMNIcon, nil]];
|
||||||
|
if (title!=NULL)
|
||||||
|
CFRelease(title);
|
||||||
|
} else if ([theName isEqual:(NSString *)kAXRowExpandedNotification]) {
|
||||||
|
[[MGMController sharedController] startNotificationWithInfo:[NSDictionary dictionaryWithObjectsAndKeys:@"rowexpanded", MGMNName, @"Row Expanded", MGMNTitle, [information objectForKey:(NSString *)kCFBundleNameKey], MGMNDescription, [[NSWorkspace sharedWorkspace] iconForFile:[information objectForKey:MGMBundlePath]], MGMNIcon, nil]];
|
||||||
|
} else if ([theName isEqual:(NSString *)kAXRowCollapsedNotification]) {
|
||||||
|
[[MGMController sharedController] startNotificationWithInfo:[NSDictionary dictionaryWithObjectsAndKeys:@"rowcollapsed", MGMNName, @"Row Collapsed", MGMNTitle, [information objectForKey:(NSString *)kCFBundleNameKey], MGMNDescription, [[NSWorkspace sharedWorkspace] iconForFile:[information objectForKey:MGMBundlePath]], MGMNIcon, nil]];
|
||||||
|
} else if ([theName isEqual:(NSString *)kAXSelectedRowsChangedNotification]) {
|
||||||
|
[[MGMController sharedController] startNotificationWithInfo:[NSDictionary dictionaryWithObjectsAndKeys:@"selectedrowschanged", MGMNName, @"Selected Rows Changed", MGMNTitle, [information objectForKey:(NSString *)kCFBundleNameKey], MGMNDescription, [[NSWorkspace sharedWorkspace] iconForFile:[information objectForKey:MGMBundlePath]], MGMNIcon, nil]];
|
||||||
|
} else if ([theName isEqual:(NSString *)kAXApplicationHiddenNotification]) {
|
||||||
|
[[MGMController sharedController] startNotificationWithInfo:[NSDictionary dictionaryWithObjectsAndKeys:@"applicationdidhide", MGMNName, @"Application Did Hide", MGMNTitle, [information objectForKey:(NSString *)kCFBundleNameKey], MGMNDescription, [[NSWorkspace sharedWorkspace] iconForFile:[information objectForKey:MGMBundlePath]], MGMNIcon, nil]];
|
||||||
|
} else if ([theName isEqual:(NSString *)kAXApplicationShownNotification]) {
|
||||||
|
[[MGMController sharedController] startNotificationWithInfo:[NSDictionary dictionaryWithObjectsAndKeys:@"applicationdidunhide", MGMNName, @"Application Did Unhide", MGMNTitle, [information objectForKey:(NSString *)kCFBundleNameKey], MGMNDescription, [[NSWorkspace sharedWorkspace] iconForFile:[information objectForKey:MGMBundlePath]], MGMNIcon, nil]];
|
||||||
|
}
|
||||||
|
[information release];
|
||||||
|
}
|
||||||
|
@end
|
15
Classes/Watchers/MGMApplicationWatcher.h
Normal file
15
Classes/Watchers/MGMApplicationWatcher.h
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
//
|
||||||
|
// MGMApplicationWatcher.h
|
||||||
|
// SoundNote
|
||||||
|
//
|
||||||
|
// Created by Mr. Gecko on 2/15/11.
|
||||||
|
// Copyright (c) 2011 Mr. Gecko's Media (James Coleman). All rights reserved. http://mrgeckosmedia.com/
|
||||||
|
//
|
||||||
|
|
||||||
|
#import <Foundation/Foundation.h>
|
||||||
|
|
||||||
|
@interface MGMApplicationWatcher : NSObject {
|
||||||
|
|
||||||
|
}
|
||||||
|
- (void)frontApplicationChangedTo:(ProcessSerialNumber *)theProcess;
|
||||||
|
@end
|
79
Classes/Watchers/MGMApplicationWatcher.m
Normal file
79
Classes/Watchers/MGMApplicationWatcher.m
Normal file
@ -0,0 +1,79 @@
|
|||||||
|
//
|
||||||
|
// MGMApplicationWatcher.m
|
||||||
|
// SoundNote
|
||||||
|
//
|
||||||
|
// Created by Mr. Gecko on 2/15/11.
|
||||||
|
// Copyright (c) 2011 Mr. Gecko's Media (James Coleman). All rights reserved. http://mrgeckosmedia.com/
|
||||||
|
//
|
||||||
|
|
||||||
|
#import "MGMApplicationWatcher.h"
|
||||||
|
#import "MGMController.h"
|
||||||
|
#import <GeckoReporter/GeckoReporter.h>
|
||||||
|
#import <Carbon/Carbon.h>
|
||||||
|
|
||||||
|
NSString * const MGMNSApplicationName = @"NSApplicationName";
|
||||||
|
NSString * const MGMNSApplicationPath = @"NSApplicationPath";
|
||||||
|
NSString * const MGMNSWorkspaceApplicationKey = @"NSWorkspaceApplicationKey";
|
||||||
|
|
||||||
|
OSStatus frontAppChanged(EventHandlerCallRef nextHandler, EventRef theEvent, void *userData) {
|
||||||
|
ProcessSerialNumber thisProcess;
|
||||||
|
GetCurrentProcess(&thisProcess);
|
||||||
|
ProcessSerialNumber newProcess;
|
||||||
|
GetFrontProcess(&newProcess);
|
||||||
|
Boolean same;
|
||||||
|
SameProcess(&newProcess, &thisProcess, &same);
|
||||||
|
if (!same)
|
||||||
|
[(MGMApplicationWatcher *)userData frontApplicationChangedTo:&newProcess];
|
||||||
|
return (CallNextEventHandler(nextHandler, theEvent));
|
||||||
|
}
|
||||||
|
|
||||||
|
@implementation MGMApplicationWatcher
|
||||||
|
- (id)init {
|
||||||
|
if ((self = [super init])) {
|
||||||
|
EventTypeSpec eventType;
|
||||||
|
eventType.eventClass = kEventClassApplication;
|
||||||
|
eventType.eventKind = kEventAppFrontSwitched;
|
||||||
|
InstallApplicationEventHandler(NewEventHandlerUPP(frontAppChanged), 1, &eventType, self, NULL);
|
||||||
|
|
||||||
|
NSNotificationCenter *notificationCenter = [[NSWorkspace sharedWorkspace] notificationCenter];
|
||||||
|
[notificationCenter addObserver:self selector:@selector(applicationWillLaunch:) name:NSWorkspaceWillLaunchApplicationNotification object:nil];
|
||||||
|
[notificationCenter addObserver:self selector:@selector(applicationDidLaunch:) name:NSWorkspaceDidLaunchApplicationNotification object:nil];
|
||||||
|
[notificationCenter addObserver:self selector:@selector(applicationDidTerminate:) name:NSWorkspaceDidTerminateApplicationNotification object:nil];
|
||||||
|
if ([[MGMSystemInfo info] isAfterSnowLeopard]) {
|
||||||
|
[notificationCenter addObserver:self selector:@selector(applicationDidHide:) name:@"NSWorkspaceDidHideApplicationNotification" object:nil];
|
||||||
|
[notificationCenter addObserver:self selector:@selector(applicationDidUnhide:) name:@"NSWorkspaceDidUnhideApplicationNotification" object:nil];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
- (void)dealloc {
|
||||||
|
DisposeEventHandlerUPP(frontAppChanged);
|
||||||
|
[[[NSWorkspace sharedWorkspace] notificationCenter] removeObserver:self];
|
||||||
|
[super dealloc];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)frontApplicationChangedTo:(ProcessSerialNumber *)theProcess {
|
||||||
|
NSDictionary *information = (NSDictionary *)ProcessInformationCopyDictionary(theProcess, kProcessDictionaryIncludeAllInformationMask);
|
||||||
|
if ([[information objectForKey:(NSString *)kCFBundleNameKey] isEqual:@"SecurityAgent"])
|
||||||
|
[[MGMController sharedController] startNotificationWithInfo:[NSDictionary dictionaryWithObjectsAndKeys:@"passworddialogopened", MGMNName, @"Password Dialog Opened", MGMNTitle, @"The system is requesting you enter your password.", MGMNDescription, nil]];
|
||||||
|
[[MGMController sharedController] startNotificationWithInfo:[NSDictionary dictionaryWithObjectsAndKeys:@"applicationbecamefront", MGMNName, @"Application Became Front", MGMNTitle, [information objectForKey:(NSString *)kCFBundleNameKey], MGMNDescription, [[NSWorkspace sharedWorkspace] iconForFile:[information objectForKey:@"BundlePath"]], MGMNIcon, nil]];
|
||||||
|
[information release];
|
||||||
|
}
|
||||||
|
- (void)applicationWillLaunch:(NSNotification *)theNotification {
|
||||||
|
[[MGMController sharedController] startNotificationWithInfo:[NSDictionary dictionaryWithObjectsAndKeys:@"applicationwilllaunch", MGMNName, @"Application Will Launch", MGMNTitle, [[theNotification userInfo] objectForKey:MGMNSApplicationName], MGMNDescription, [[NSWorkspace sharedWorkspace] iconForFile:[[theNotification userInfo] objectForKey:MGMNSApplicationPath]], MGMNIcon, nil]];
|
||||||
|
}
|
||||||
|
- (void)applicationDidLaunch:(NSNotification *)theNotification {
|
||||||
|
[[MGMController sharedController] startNotificationWithInfo:[NSDictionary dictionaryWithObjectsAndKeys:@"applicationdidlaunch", MGMNName, @"Application Did Launch", MGMNTitle, [[theNotification userInfo] objectForKey:MGMNSApplicationName], MGMNDescription, [[NSWorkspace sharedWorkspace] iconForFile:[[theNotification userInfo] objectForKey:MGMNSApplicationPath]], MGMNIcon, nil]];
|
||||||
|
}
|
||||||
|
- (void)applicationDidTerminate:(NSNotification *)theNotification {
|
||||||
|
[[MGMController sharedController] startNotificationWithInfo:[NSDictionary dictionaryWithObjectsAndKeys:@"applicationdidterminate", MGMNName, @"Application Did Terminate", MGMNTitle, [[theNotification userInfo] objectForKey:MGMNSApplicationName], MGMNDescription, [[NSWorkspace sharedWorkspace] iconForFile:[[theNotification userInfo] objectForKey:MGMNSApplicationPath]], MGMNIcon, nil]];
|
||||||
|
}
|
||||||
|
- (void)applicationDidHide:(NSNotification *)theNotification {
|
||||||
|
NSRunningApplication *application = [[theNotification userInfo] objectForKey:MGMNSWorkspaceApplicationKey];
|
||||||
|
[[MGMController sharedController] startNotificationWithInfo:[NSDictionary dictionaryWithObjectsAndKeys:@"applicationdidhide", MGMNName, @"Application Did Hide", MGMNTitle, [application localizedName], MGMNDescription, [application icon], MGMNIcon, nil]];
|
||||||
|
}
|
||||||
|
- (void)applicationDidUnhide:(NSNotification *)theNotification {
|
||||||
|
NSRunningApplication *application = [[theNotification userInfo] objectForKey:MGMNSWorkspaceApplicationKey];
|
||||||
|
[[MGMController sharedController] startNotificationWithInfo:[NSDictionary dictionaryWithObjectsAndKeys:@"applicationdidunhide", MGMNName, @"Application Did Unhide", MGMNTitle, [application localizedName], MGMNDescription, [application icon], MGMNIcon, nil]];
|
||||||
|
}
|
||||||
|
@end
|
21
Classes/Watchers/MGMBluetoothWatcher.h
Normal file
21
Classes/Watchers/MGMBluetoothWatcher.h
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
//
|
||||||
|
// MGMBluetoothWatcher.h
|
||||||
|
// SoundNote
|
||||||
|
//
|
||||||
|
// Created by Mr. Gecko on 2/16/11.
|
||||||
|
// Copyright (c) 2011 Mr. Gecko's Media (James Coleman). All rights reserved. http://mrgeckosmedia.com/
|
||||||
|
//
|
||||||
|
|
||||||
|
#import <Foundation/Foundation.h>
|
||||||
|
#import <IOBluetooth/IOBluetooth.h>
|
||||||
|
|
||||||
|
@interface MGMBluetoothWatcher : NSObject {
|
||||||
|
IOBluetoothUserNotificationRef bluetoothNotification;
|
||||||
|
NSMutableArray *notifications;
|
||||||
|
}
|
||||||
|
- (void)addNotification:(IOBluetoothUserNotificationRef)theNotification;
|
||||||
|
- (void)removeNotification:(IOBluetoothUserNotificationRef)theNotification;
|
||||||
|
|
||||||
|
- (void)bluetoohDeviceConnected:(IOBluetoothObjectRef)theDevice;
|
||||||
|
- (void)bluetoohDeviceDisconnected:(IOBluetoothObjectRef)theDevice;
|
||||||
|
@end
|
68
Classes/Watchers/MGMBluetoothWatcher.m
Normal file
68
Classes/Watchers/MGMBluetoothWatcher.m
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
//
|
||||||
|
// MGMBluetoothWatcher.m
|
||||||
|
// SoundNote
|
||||||
|
//
|
||||||
|
// Created by Mr. Gecko on 2/16/11.
|
||||||
|
// Copyright (c) 2011 Mr. Gecko's Media (James Coleman). All rights reserved. http://mrgeckosmedia.com/
|
||||||
|
//
|
||||||
|
|
||||||
|
#import "MGMBluetoothWatcher.h"
|
||||||
|
#import "MGMController.h"
|
||||||
|
|
||||||
|
static BOOL loadingBlueTooth;
|
||||||
|
|
||||||
|
static void bluetoothDisconnected(void *userRefCon, IOBluetoothUserNotificationRef inRef, IOBluetoothDeviceRef objectRef) {
|
||||||
|
[(MGMBluetoothWatcher *)userRefCon bluetoohDeviceDisconnected:objectRef];
|
||||||
|
[(MGMBluetoothWatcher *)userRefCon removeNotification:inRef];
|
||||||
|
IOBluetoothUserNotificationUnregister(inRef);
|
||||||
|
}
|
||||||
|
static void bluetoothConnected(void *userRefCon, IOBluetoothUserNotificationRef inRef, IOBluetoothDeviceRef objectRef) {
|
||||||
|
if (!loadingBlueTooth)
|
||||||
|
[(MGMBluetoothWatcher *)userRefCon bluetoohDeviceConnected:objectRef];
|
||||||
|
[(MGMBluetoothWatcher *)userRefCon addNotification:IOBluetoothDeviceRegisterForDisconnectNotification(objectRef, bluetoothDisconnected, userRefCon)];
|
||||||
|
}
|
||||||
|
|
||||||
|
@implementation MGMBluetoothWatcher
|
||||||
|
- (id)init {
|
||||||
|
if ((self = [super init])) {
|
||||||
|
loadingBlueTooth = YES;
|
||||||
|
bluetoothNotification = IOBluetoothRegisterForDeviceConnectNotifications(bluetoothConnected, self);
|
||||||
|
loadingBlueTooth = NO;
|
||||||
|
}
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
- (void)dealloc {
|
||||||
|
IOBluetoothUserNotificationUnregister(bluetoothNotification);
|
||||||
|
for (int i=0; i<[notifications count]; i++) {
|
||||||
|
IOBluetoothUserNotificationUnregister([[notifications objectAtIndex:i] pointerValue]);
|
||||||
|
}
|
||||||
|
[notifications release];
|
||||||
|
[super dealloc];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)addNotification:(IOBluetoothUserNotificationRef)theNotification {
|
||||||
|
[notifications addObject:(id)theNotification];
|
||||||
|
}
|
||||||
|
- (void)removeNotification:(IOBluetoothUserNotificationRef)theNotification {
|
||||||
|
[notifications removeObject:(id)theNotification];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)bluetoohDeviceConnected:(IOBluetoothDeviceRef)theDevice {
|
||||||
|
IOBluetoothDevice *device = [IOBluetoothDevice withDeviceRef:theDevice];
|
||||||
|
NSString *name = @"";
|
||||||
|
if ([device respondsToSelector:@selector(getNameOrAddress)])
|
||||||
|
name = [device getNameOrAddress];
|
||||||
|
else
|
||||||
|
name = [device nameOrAddress];
|
||||||
|
[[MGMController sharedController] startNotificationWithInfo:[NSDictionary dictionaryWithObjectsAndKeys:@"bluetoothconnected", MGMNName, @"Bluetooth Connected", MGMNTitle, name, MGMNDescription, [NSImage imageNamed:@"Bluetooth"], MGMNIcon, nil]];
|
||||||
|
}
|
||||||
|
- (void)bluetoohDeviceDisconnected:(IOBluetoothDeviceRef)theDevice {
|
||||||
|
IOBluetoothDevice *device = [IOBluetoothDevice withDeviceRef:theDevice];
|
||||||
|
NSString *name = @"";
|
||||||
|
if ([device respondsToSelector:@selector(getNameOrAddress)])
|
||||||
|
name = [device getNameOrAddress];
|
||||||
|
else
|
||||||
|
name = [device nameOrAddress];
|
||||||
|
[[MGMController sharedController] startNotificationWithInfo:[NSDictionary dictionaryWithObjectsAndKeys:@"bluetoothdisconnected", MGMNName, @"Bluetooth Disconnected", MGMNTitle, name, MGMNDescription, [NSImage imageNamed:@"Bluetooth"], MGMNIcon, nil]];
|
||||||
|
}
|
||||||
|
@end
|
15
Classes/Watchers/MGMDisplayWatcher.h
Normal file
15
Classes/Watchers/MGMDisplayWatcher.h
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
//
|
||||||
|
// MGMDisplayWatcher.h
|
||||||
|
// SoundNote
|
||||||
|
//
|
||||||
|
// Created by Mr. Gecko on 2/15/11.
|
||||||
|
// Copyright (c) 2011 Mr. Gecko's Media (James Coleman). All rights reserved. http://mrgeckosmedia.com/
|
||||||
|
//
|
||||||
|
|
||||||
|
#import <Foundation/Foundation.h>
|
||||||
|
|
||||||
|
@interface MGMDisplayWatcher : NSObject {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
41
Classes/Watchers/MGMDisplayWatcher.m
Normal file
41
Classes/Watchers/MGMDisplayWatcher.m
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
//
|
||||||
|
// MGMDisplayWatcher.m
|
||||||
|
// SoundNote
|
||||||
|
//
|
||||||
|
// Created by Mr. Gecko on 2/15/11.
|
||||||
|
// Copyright (c) 2011 Mr. Gecko's Media (James Coleman). All rights reserved. http://mrgeckosmedia.com/
|
||||||
|
//
|
||||||
|
|
||||||
|
#import "MGMDisplayWatcher.h"
|
||||||
|
#import "MGMController.h"
|
||||||
|
|
||||||
|
@implementation MGMDisplayWatcher
|
||||||
|
- (id)init {
|
||||||
|
if ((self = [super init])) {
|
||||||
|
NSNotificationCenter *notificationCenter = [[NSWorkspace sharedWorkspace] notificationCenter];
|
||||||
|
[notificationCenter addObserver:self selector:@selector(screensDidSleep:) name:@"NSWorkspaceScreensDidSleepNotification" object:nil];
|
||||||
|
[notificationCenter addObserver:self selector:@selector(screensDidWake:) name:@"NSWorkspaceScreensDidWakeNotification" object:nil];
|
||||||
|
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(didChangeScreenParameters:) name:NSApplicationDidChangeScreenParametersNotification object:nil];
|
||||||
|
[notificationCenter addObserver:self selector:@selector(spaceChanged:) name:@"NSWorkspaceActiveSpaceDidChangeNotification" object:nil];
|
||||||
|
}
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
- (void)dealloc {
|
||||||
|
[[[NSWorkspace sharedWorkspace] notificationCenter] removeObserver:self];
|
||||||
|
[[NSNotificationCenter defaultCenter] removeObserver:self];
|
||||||
|
[super dealloc];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)screensDidSleep:(NSNotification *)theNotification {
|
||||||
|
[[MGMController sharedController] startNotificationWithInfo:[NSDictionary dictionaryWithObjectsAndKeys:@"screensdidsleep", MGMNName, @"Screens Did Sleep", MGMNTitle, @"Your screens went to sleep.", MGMNDescription, nil]];
|
||||||
|
}
|
||||||
|
- (void)screensDidWake:(NSNotification *)theNotification {
|
||||||
|
[[MGMController sharedController] startNotificationWithInfo:[NSDictionary dictionaryWithObjectsAndKeys:@"screenswakesleep", MGMNName, @"Screens Did Wake", MGMNTitle, @"Your screens woke up from sleep.", MGMNDescription, nil]];
|
||||||
|
}
|
||||||
|
- (void)didChangeScreenParameters:(NSNotification *)theNotification {
|
||||||
|
[[MGMController sharedController] startNotificationWithInfo:[NSDictionary dictionaryWithObjectsAndKeys:@"screenchange", MGMNName, @"Screen Changed", MGMNTitle, @"The screen parameters has been changed.", MGMNDescription, nil]];
|
||||||
|
}
|
||||||
|
- (void)spaceChanged:(NSNotification *)theNotification {
|
||||||
|
[[MGMController sharedController] startNotificationWithInfo:[NSDictionary dictionaryWithObjectsAndKeys:@"spacechanged", MGMNName, @"Space Changed", MGMNTitle, @"You changed spaces.", MGMNDescription, nil]];
|
||||||
|
}
|
||||||
|
@end
|
19
Classes/Watchers/MGMFireWireWatcher.h
Normal file
19
Classes/Watchers/MGMFireWireWatcher.h
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
//
|
||||||
|
// MGMFireWireWatcher.h
|
||||||
|
// SoundNote
|
||||||
|
//
|
||||||
|
// Created by Mr. Gecko on 2/15/11.
|
||||||
|
// Copyright (c) 2011 Mr. Gecko's Media (James Coleman). All rights reserved. http://mrgeckosmedia.com/
|
||||||
|
//
|
||||||
|
|
||||||
|
#import <Foundation/Foundation.h>
|
||||||
|
|
||||||
|
@interface MGMFireWireWatcher : NSObject {
|
||||||
|
IONotificationPortRef notificationPort;
|
||||||
|
CFRunLoopSourceRef runLoop;
|
||||||
|
|
||||||
|
NSMutableArray *firewireDevices;
|
||||||
|
}
|
||||||
|
- (void)firewireDeviceConnected:(io_object_t)theDevice;
|
||||||
|
- (void)firewireDeviceDisconnected:(io_object_t)theDevice;
|
||||||
|
@end
|
124
Classes/Watchers/MGMFireWireWatcher.m
Normal file
124
Classes/Watchers/MGMFireWireWatcher.m
Normal file
@ -0,0 +1,124 @@
|
|||||||
|
//
|
||||||
|
// MGMFireWireWatcher.m
|
||||||
|
// SoundNote
|
||||||
|
//
|
||||||
|
// Created by Mr. Gecko on 2/15/11.
|
||||||
|
// Copyright (c) 2011 Mr. Gecko's Media (James Coleman). All rights reserved. http://mrgeckosmedia.com/
|
||||||
|
//
|
||||||
|
|
||||||
|
#import "MGMFireWireWatcher.h"
|
||||||
|
#import "MGMController.h"
|
||||||
|
#import <IOKit/IOKitLib.h>
|
||||||
|
|
||||||
|
char * const IOFireWireDevice = "IOFireWireDevice";
|
||||||
|
|
||||||
|
static void firewireConnected(void *refCon, io_iterator_t iterator) {
|
||||||
|
io_object_t object;
|
||||||
|
while ((object = IOIteratorNext(iterator))) {
|
||||||
|
[(MGMFireWireWatcher *)refCon firewireDeviceConnected:object];
|
||||||
|
IOObjectRelease(object);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
static void firewireDisconnected(void *refCon, io_iterator_t iterator) {
|
||||||
|
io_object_t object;
|
||||||
|
while ((object = IOIteratorNext(iterator))) {
|
||||||
|
[(MGMFireWireWatcher *)refCon firewireDeviceDisconnected:object];
|
||||||
|
IOObjectRelease(object);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static NSString *nameForIOFW(io_object_t object) {
|
||||||
|
io_name_t ioDeviceName;
|
||||||
|
NSString *deviceName = nil;
|
||||||
|
kern_return_t result = IORegistryEntryGetName(object, ioDeviceName);
|
||||||
|
if (result==noErr)
|
||||||
|
deviceName = [(NSString *)CFStringCreateWithCString(kCFAllocatorDefault, ioDeviceName, kCFStringEncodingUTF8) autorelease];
|
||||||
|
if (deviceName!=nil)
|
||||||
|
return deviceName;
|
||||||
|
|
||||||
|
if (deviceName!=nil && ![deviceName isEqual:@"IOFireWireDevice"])
|
||||||
|
return deviceName;
|
||||||
|
|
||||||
|
deviceName = [(NSString *)IORegistryEntrySearchCFProperty(object, kIOFireWirePlane, (CFStringRef)@"FireWire Product Name", nil, kIORegistryIterateRecursively) autorelease];
|
||||||
|
if (deviceName!=nil)
|
||||||
|
return deviceName;
|
||||||
|
|
||||||
|
deviceName = [(NSString *)IORegistryEntrySearchCFProperty(object, kIOFireWirePlane, (CFStringRef)@"FireWire Vendor Name", nil, kIORegistryIterateRecursively) autorelease];
|
||||||
|
if (deviceName!=nil)
|
||||||
|
return deviceName;
|
||||||
|
|
||||||
|
return @"Unnamed Device";
|
||||||
|
}
|
||||||
|
static NSString *idForIOFW(io_object_t object) {
|
||||||
|
uint64_t ioDeviceID;
|
||||||
|
NSString *deviceID = nil;
|
||||||
|
kern_return_t result = IORegistryEntryGetRegistryEntryID(object, &ioDeviceID);
|
||||||
|
if (result==noErr)
|
||||||
|
deviceID = [NSString stringWithFormat:@"%11x", ioDeviceID];
|
||||||
|
if (deviceID!=nil)
|
||||||
|
return deviceID;
|
||||||
|
|
||||||
|
return @"Unknown ID";
|
||||||
|
}
|
||||||
|
|
||||||
|
@implementation MGMFireWireWatcher
|
||||||
|
- (id)init {
|
||||||
|
if ((self = [super init])) {
|
||||||
|
notificationPort = IONotificationPortCreate(kIOMasterPortDefault);
|
||||||
|
runLoop = IONotificationPortGetRunLoopSource(notificationPort);
|
||||||
|
CFRunLoopAddSource(CFRunLoopGetCurrent(), runLoop, kCFRunLoopDefaultMode);
|
||||||
|
|
||||||
|
firewireDevices = [NSMutableArray new];
|
||||||
|
|
||||||
|
CFDictionaryRef servicesMatch = IOServiceMatching(IOFireWireDevice);
|
||||||
|
io_iterator_t found;
|
||||||
|
kern_return_t result = IOServiceAddMatchingNotification(notificationPort, kIOPublishNotification, servicesMatch, firewireConnected, NULL, &found);
|
||||||
|
if (result!=kIOReturnSuccess)
|
||||||
|
NSLog(@"Unable to register for firewire add %d", result);
|
||||||
|
io_object_t object;
|
||||||
|
while ((object = IOIteratorNext(found))) {
|
||||||
|
NSString *deviceID = idForIOFW(object);
|
||||||
|
if (![firewireDevices containsObject:deviceID])
|
||||||
|
[firewireDevices addObject:deviceID];
|
||||||
|
IOObjectRelease(object);
|
||||||
|
}
|
||||||
|
|
||||||
|
servicesMatch = IOServiceMatching(IOFireWireDevice);
|
||||||
|
result = IOServiceAddMatchingNotification(notificationPort, kIOTerminatedNotification, servicesMatch, firewireDisconnected, NULL, &found);
|
||||||
|
if (result!=kIOReturnSuccess)
|
||||||
|
NSLog(@"Unable to register for firewire remove %d", result);
|
||||||
|
else {
|
||||||
|
while ((object = IOIteratorNext(found))) {
|
||||||
|
NSString *deviceID = idForIOFW(object);
|
||||||
|
if ([firewireDevices containsObject:deviceID])
|
||||||
|
[firewireDevices removeObject:deviceID];
|
||||||
|
IOObjectRelease(object);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
- (void)dealloc {
|
||||||
|
if (notificationPort) {
|
||||||
|
CFRunLoopRemoveSource(CFRunLoopGetCurrent(), runLoop, kCFRunLoopDefaultMode);
|
||||||
|
IONotificationPortDestroy(notificationPort);
|
||||||
|
}
|
||||||
|
[firewireDevices release];
|
||||||
|
[super dealloc];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)firewireDeviceConnected:(io_object_t)theDevice {
|
||||||
|
NSString *deviceID = idForIOFW(theDevice);
|
||||||
|
if (![firewireDevices containsObject:deviceID]) {
|
||||||
|
[firewireDevices addObject:deviceID];
|
||||||
|
[[MGMController sharedController] startNotificationWithInfo:[NSDictionary dictionaryWithObjectsAndKeys:@"firewireconnected", MGMNName, @"FireWire Connected", MGMNTitle, nameForIOFW(theDevice), MGMNDescription, [NSImage imageNamed:@"FireWire"], MGMNIcon, nil]];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
- (void)firewireDeviceDisconnected:(io_object_t)theDevice {
|
||||||
|
NSString *deviceID = idForIOFW(theDevice);
|
||||||
|
if ([firewireDevices containsObject:deviceID]) {
|
||||||
|
[firewireDevices removeObject:deviceID];
|
||||||
|
[[MGMController sharedController] startNotificationWithInfo:[NSDictionary dictionaryWithObjectsAndKeys:@"firewiredisconnected", MGMNName, @"FireWire Disconnected", MGMNTitle, nameForIOFW(theDevice), MGMNDescription, [NSImage imageNamed:@"FireWire"], MGMNIcon, nil]];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@end
|
15
Classes/Watchers/MGMITunesWatcher.h
Normal file
15
Classes/Watchers/MGMITunesWatcher.h
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
//
|
||||||
|
// MGMITunesWatcher.h
|
||||||
|
// SoundNote
|
||||||
|
//
|
||||||
|
// Created by Mr. Gecko on 2/15/11.
|
||||||
|
// Copyright (c) 2011 Mr. Gecko's Media (James Coleman). All rights reserved. http://mrgeckosmedia.com/
|
||||||
|
//
|
||||||
|
|
||||||
|
#import <Foundation/Foundation.h>
|
||||||
|
|
||||||
|
@interface MGMITunesWatcher : NSObject {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
59
Classes/Watchers/MGMITunesWatcher.m
Normal file
59
Classes/Watchers/MGMITunesWatcher.m
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
//
|
||||||
|
// MGMITunesWatcher.m
|
||||||
|
// SoundNote
|
||||||
|
//
|
||||||
|
// Created by Mr. Gecko on 2/15/11.
|
||||||
|
// Copyright (c) 2011 Mr. Gecko's Media (James Coleman). All rights reserved. http://mrgeckosmedia.com/
|
||||||
|
//
|
||||||
|
|
||||||
|
#import "MGMITunesWatcher.h"
|
||||||
|
#import "MGMController.h"
|
||||||
|
#import <EyeTunes/EyeTunes.h>
|
||||||
|
|
||||||
|
NSString * const MGMTName = @"Name";
|
||||||
|
NSString * const MGMTArtist = @"Artist";
|
||||||
|
|
||||||
|
@implementation MGMITunesWatcher
|
||||||
|
- (id)init {
|
||||||
|
if ((self = [super init])) {
|
||||||
|
NSDistributedNotificationCenter *notificationCenter = [NSDistributedNotificationCenter defaultCenter];
|
||||||
|
[notificationCenter addObserver:self selector:@selector(itunesActivity:) name:@"com.apple.iTunes.playerInfo" object:nil];
|
||||||
|
[notificationCenter addObserver:self selector:@selector(itunesSaved:) name:@"com.apple.iTunes.sourceSaved" object:nil];
|
||||||
|
}
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
- (void)dealloc {
|
||||||
|
[[NSDistributedNotificationCenter defaultCenter] removeObserver:self];
|
||||||
|
[super dealloc];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)itunesActivity:(NSNotification *)theNotification {
|
||||||
|
NSString *playerState = [[theNotification userInfo] objectForKey:@"Player State"];
|
||||||
|
ETTrack *currentTrack = [[EyeTunes sharedInstance] currentTrack];
|
||||||
|
NSImage *image = nil;
|
||||||
|
NSArray *artwork = [currentTrack artwork];
|
||||||
|
if ([artwork count]>0)
|
||||||
|
image = [artwork objectAtIndex:0];
|
||||||
|
else
|
||||||
|
image = [[NSWorkspace sharedWorkspace] iconForFile:[[NSWorkspace sharedWorkspace] fullPathForApplication:@"iTunes"]];
|
||||||
|
|
||||||
|
NSString *trackName = @"";
|
||||||
|
if ([[theNotification userInfo] objectForKey:MGMTName]!=nil && ![[[theNotification userInfo] objectForKey:MGMTName] isEqual:@""])
|
||||||
|
trackName = [[theNotification userInfo] objectForKey:MGMTName];
|
||||||
|
if ([[theNotification userInfo] objectForKey:MGMTArtist]!=nil && ![[[theNotification userInfo] objectForKey:MGMTArtist] isEqual:@""]) {
|
||||||
|
trackName = [trackName stringByAppendingFormat:@" by %@", [[theNotification userInfo] objectForKey:MGMTArtist]];
|
||||||
|
}
|
||||||
|
if ([playerState isEqualToString:@"Playing"]) {
|
||||||
|
[[MGMController sharedController] startNotificationWithInfo:[NSDictionary dictionaryWithObjectsAndKeys:@"itunesplaying", MGMNName, @"Now Playing", MGMNTitle, trackName, MGMNDescription, image, MGMNIcon, nil]];
|
||||||
|
} else if ([playerState isEqualToString:@"Paused"]) {
|
||||||
|
[[MGMController sharedController] startNotificationWithInfo:[NSDictionary dictionaryWithObjectsAndKeys:@"itunespaused", MGMNName, @"Paused", MGMNTitle, trackName, MGMNDescription, image, MGMNIcon, nil]];
|
||||||
|
} else {
|
||||||
|
[[MGMController sharedController] startNotificationWithInfo:[NSDictionary dictionaryWithObjectsAndKeys:@"itunesstopped", MGMNName, @"Stopped", MGMNTitle, @"iTunes is no longer playing.", MGMNDescription, image, MGMNIcon, nil]];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
- (void)itunesSaved:(NSNotification *)theNotification {
|
||||||
|
NSAutoreleasePool *pool = [NSAutoreleasePool new];
|
||||||
|
[[MGMController sharedController] startNotificationWithInfo:[NSDictionary dictionaryWithObjectsAndKeys:@"itunessaved", MGMNName, @"iTunes Saved", MGMNTitle, [NSString stringWithFormat:@"iTunes saved %@.", [[theNotification userInfo] objectForKey:MGMTName]], MGMNDescription, [[NSWorkspace sharedWorkspace] iconForFile:[[NSWorkspace sharedWorkspace] fullPathForApplication:@"iTunes"]], MGMNIcon, nil]];
|
||||||
|
[pool drain];
|
||||||
|
}
|
||||||
|
@end
|
15
Classes/Watchers/MGMKeyboardWatcher.h
Normal file
15
Classes/Watchers/MGMKeyboardWatcher.h
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
//
|
||||||
|
// MGMKeyboardWatcher.h
|
||||||
|
// SoundNote
|
||||||
|
//
|
||||||
|
// Created by Mr. Gecko on 2/16/11.
|
||||||
|
// Copyright (c) 2011 Mr. Gecko's Media (James Coleman). All rights reserved. http://mrgeckosmedia.com/
|
||||||
|
//
|
||||||
|
|
||||||
|
#import <Foundation/Foundation.h>
|
||||||
|
|
||||||
|
@interface MGMKeyboardWatcher : NSObject {
|
||||||
|
|
||||||
|
}
|
||||||
|
- (void)keyPushed;
|
||||||
|
@end
|
36
Classes/Watchers/MGMKeyboardWatcher.m
Normal file
36
Classes/Watchers/MGMKeyboardWatcher.m
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
//
|
||||||
|
// MGMKeyboardWatcher.m
|
||||||
|
// SoundNote
|
||||||
|
//
|
||||||
|
// Created by Mr. Gecko on 2/16/11.
|
||||||
|
// Copyright (c) 2011 Mr. Gecko's Media (James Coleman). All rights reserved. http://mrgeckosmedia.com/
|
||||||
|
//
|
||||||
|
|
||||||
|
#import "MGMKeyboardWatcher.h"
|
||||||
|
#import "MGMController.h"
|
||||||
|
#import <Carbon/Carbon.h>
|
||||||
|
|
||||||
|
OSStatus keyPushed(EventHandlerCallRef nextHandler, EventRef theEvent, void *userData) {
|
||||||
|
[(MGMKeyboardWatcher *)userData keyPushed];
|
||||||
|
return (CallNextEventHandler(nextHandler, theEvent));
|
||||||
|
}
|
||||||
|
|
||||||
|
@implementation MGMKeyboardWatcher
|
||||||
|
- (id)init {
|
||||||
|
if ((self = [super init])) {
|
||||||
|
EventTypeSpec eventType;
|
||||||
|
eventType.eventClass = kEventClassKeyboard;
|
||||||
|
eventType.eventKind = kEventRawKeyDown;
|
||||||
|
InstallEventHandler(GetEventMonitorTarget(), NewEventHandlerUPP(keyPushed), 1, &eventType, self, NULL);
|
||||||
|
}
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
- (void)dealloc {
|
||||||
|
DisposeEventHandlerUPP(keyPushed);
|
||||||
|
[super dealloc];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)keyPushed {
|
||||||
|
[[MGMController sharedController] startNotificationWithInfo:[NSDictionary dictionaryWithObjectsAndKeys:@"keypushed", MGMNName, @"Key Pushed", MGMNTitle, @"", MGMNDescription, nil]];
|
||||||
|
}
|
||||||
|
@end
|
15
Classes/Watchers/MGMMouseWatcher.h
Normal file
15
Classes/Watchers/MGMMouseWatcher.h
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
//
|
||||||
|
// MGMMouseWatcher.h
|
||||||
|
// SoundNote
|
||||||
|
//
|
||||||
|
// Created by Mr. Gecko on 2/16/11.
|
||||||
|
// Copyright (c) 2011 Mr. Gecko's Media (James Coleman). All rights reserved. http://mrgeckosmedia.com/
|
||||||
|
//
|
||||||
|
|
||||||
|
#import <Foundation/Foundation.h>
|
||||||
|
|
||||||
|
@interface MGMMouseWatcher : NSObject {
|
||||||
|
|
||||||
|
}
|
||||||
|
- (void)mouseClicked;
|
||||||
|
@end
|
36
Classes/Watchers/MGMMouseWatcher.m
Normal file
36
Classes/Watchers/MGMMouseWatcher.m
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
//
|
||||||
|
// MGMMouseWatcher.m
|
||||||
|
// SoundNote
|
||||||
|
//
|
||||||
|
// Created by Mr. Gecko on 2/16/11.
|
||||||
|
// Copyright (c) 2011 Mr. Gecko's Media (James Coleman). All rights reserved. http://mrgeckosmedia.com/
|
||||||
|
//
|
||||||
|
|
||||||
|
#import "MGMMouseWatcher.h"
|
||||||
|
#import "MGMController.h"
|
||||||
|
#import <Carbon/Carbon.h>
|
||||||
|
|
||||||
|
OSStatus mouseClicked(EventHandlerCallRef nextHandler, EventRef theEvent, void *userData) {
|
||||||
|
[(MGMMouseWatcher *)userData mouseClicked];
|
||||||
|
return (CallNextEventHandler(nextHandler, theEvent));
|
||||||
|
}
|
||||||
|
|
||||||
|
@implementation MGMMouseWatcher
|
||||||
|
- (id)init {
|
||||||
|
if ((self = [super init])) {
|
||||||
|
EventTypeSpec eventType;
|
||||||
|
eventType.eventClass = kEventClassMouse;
|
||||||
|
eventType.eventKind = kEventMouseDown;
|
||||||
|
InstallEventHandler(GetEventMonitorTarget(), NewEventHandlerUPP(mouseClicked), 1, &eventType, self, NULL);
|
||||||
|
}
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
- (void)dealloc {
|
||||||
|
DisposeEventHandlerUPP(mouseClicked);
|
||||||
|
[super dealloc];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)mouseClicked {
|
||||||
|
[[MGMController sharedController] startNotificationWithInfo:[NSDictionary dictionaryWithObjectsAndKeys:@"mouseclicked", MGMNName, @"Mouse Clicked", MGMNTitle, @"", MGMNDescription, nil]];
|
||||||
|
}
|
||||||
|
@end
|
35
Classes/Watchers/MGMNetworkWatcher.h
Normal file
35
Classes/Watchers/MGMNetworkWatcher.h
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
//
|
||||||
|
// MGMNetworkWatcher.h
|
||||||
|
// SoundNote
|
||||||
|
//
|
||||||
|
// Created by Mr. Gecko on 2/16/11.
|
||||||
|
// Copyright (c) 2011 Mr. Gecko's Media (James Coleman). All rights reserved. http://mrgeckosmedia.com/
|
||||||
|
//
|
||||||
|
|
||||||
|
#import <Foundation/Foundation.h>
|
||||||
|
#import <SystemConfiguration/SystemConfiguration.h>
|
||||||
|
|
||||||
|
@interface MGMNetworkWatcher : NSObject {
|
||||||
|
CFRunLoopSourceRef runLoop;
|
||||||
|
SCDynamicStoreRef store;
|
||||||
|
NSDictionary *lastAirPortState;
|
||||||
|
|
||||||
|
NSString *lastMediaInfo;
|
||||||
|
NSString *IPv4Addresses;
|
||||||
|
NSString *IPv6Addresses;
|
||||||
|
|
||||||
|
NSDate *lastCheck;
|
||||||
|
|
||||||
|
NSURLConnection *connection;
|
||||||
|
NSMutableData *data;
|
||||||
|
NSURLConnection *connection2;
|
||||||
|
NSMutableData *data2;
|
||||||
|
}
|
||||||
|
- (NSString *)getEthernetMedia;
|
||||||
|
- (void)ethernetLinkChanged:(NSDictionary *)theState;
|
||||||
|
|
||||||
|
- (void)ipv4Changed:(NSDictionary *)theInfo;
|
||||||
|
- (void)ipv6Changed:(NSDictionary *)theInfo;
|
||||||
|
|
||||||
|
- (void)airportChanged:(NSDictionary *)theInfo;
|
||||||
|
@end
|
315
Classes/Watchers/MGMNetworkWatcher.m
Normal file
315
Classes/Watchers/MGMNetworkWatcher.m
Normal file
@ -0,0 +1,315 @@
|
|||||||
|
//
|
||||||
|
// MGMNetworkWatcher.m
|
||||||
|
// SoundNote
|
||||||
|
//
|
||||||
|
// Created by Mr. Gecko on 2/16/11.
|
||||||
|
// Copyright (c) 2011 Mr. Gecko's Media (James Coleman). All rights reserved. http://mrgeckosmedia.com/
|
||||||
|
//
|
||||||
|
|
||||||
|
#import "MGMNetworkWatcher.h"
|
||||||
|
#import "MGMController.h"
|
||||||
|
#import <sys/socket.h>
|
||||||
|
#import <sys/sockio.h>
|
||||||
|
#import <sys/ioctl.h>
|
||||||
|
#import <net/if.h>
|
||||||
|
#import <net/if_media.h>
|
||||||
|
#import <netinet/in.h>
|
||||||
|
#import <arpa/inet.h>
|
||||||
|
#import <unistd.h>
|
||||||
|
|
||||||
|
NSString * const MGMPrimaryInterface = @"PrimaryInterface";
|
||||||
|
NSString * const MGMAddresses = @"Addresses";
|
||||||
|
NSString * const MGMBSSID = @"BSSID";
|
||||||
|
NSString * const MGMSSID = @"SSID_STR";
|
||||||
|
NSString * const MGMCHANNEL = @"CHANNEL";
|
||||||
|
|
||||||
|
NSString * const MGMIPv4Info = @"State:/Network/Interface/%@/IPv4";
|
||||||
|
NSString * const MGMIPv6Info = @"State:/Network/Interface/%@/IPv6";
|
||||||
|
NSString * const MGMEthernetLink = @"State:/Network/Interface/en0/Link";
|
||||||
|
NSString * const MGMIPv4State = @"State:/Network/Global/IPv4";
|
||||||
|
NSString * const MGMIPv6State = @"State:/Network/Global/IPv6";
|
||||||
|
NSString * const MGMAirPortInfo = @"State:/Network/Interface/en1/AirPort";
|
||||||
|
|
||||||
|
static struct ifmedia_description ifm_subtype_ethernet_descriptions[] = IFM_SUBTYPE_ETHERNET_DESCRIPTIONS;
|
||||||
|
static struct ifmedia_description ifm_shared_option_descriptions[] = IFM_SHARED_OPTION_DESCRIPTIONS;
|
||||||
|
|
||||||
|
static void systemNotification(SCDynamicStoreRef store, NSArray *changedKeys, void *info) {
|
||||||
|
for (int i=0; i<[changedKeys count]; ++i) {
|
||||||
|
NSString *key = [changedKeys objectAtIndex:i];
|
||||||
|
if ([key isEqual:MGMEthernetLink]) {
|
||||||
|
NSDictionary *value = (NSDictionary *)SCDynamicStoreCopyValue(store, (CFStringRef)key);
|
||||||
|
[(MGMNetworkWatcher *)info ethernetLinkChanged:value];
|
||||||
|
[value release];
|
||||||
|
} else if ([key isEqual:MGMIPv4State]) {
|
||||||
|
NSDictionary *value = (NSDictionary *)SCDynamicStoreCopyValue(store, (CFStringRef)key);
|
||||||
|
[(MGMNetworkWatcher *)info ipv4Changed:value];
|
||||||
|
[value release];
|
||||||
|
} else if ([key isEqual:MGMIPv6State]) {
|
||||||
|
NSDictionary *value = (NSDictionary *)SCDynamicStoreCopyValue(store, (CFStringRef)key);
|
||||||
|
[(MGMNetworkWatcher *)info ipv6Changed:value];
|
||||||
|
[value release];
|
||||||
|
} else if ([key isEqual:MGMAirPortInfo]) {
|
||||||
|
NSDictionary *value = (NSDictionary *)SCDynamicStoreCopyValue(store, (CFStringRef)key);
|
||||||
|
[(MGMNetworkWatcher *)info airportChanged:value];
|
||||||
|
[value release];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@implementation MGMNetworkWatcher
|
||||||
|
- (id)init {
|
||||||
|
if ((self = [super init])) {
|
||||||
|
SCDynamicStoreContext context = {0, self, NULL, NULL, NULL};
|
||||||
|
store = SCDynamicStoreCreate(kCFAllocatorDefault, CFBundleGetIdentifier(CFBundleGetMainBundle()), (SCDynamicStoreCallBack)systemNotification, &context);
|
||||||
|
if (!store) {
|
||||||
|
NSLog(@"Unable to create store for system configuration %s", SCErrorString(SCError()));
|
||||||
|
} else {
|
||||||
|
NSArray *keys = [NSArray arrayWithObjects:MGMEthernetLink, MGMIPv4State, MGMIPv6State, MGMAirPortInfo, nil];
|
||||||
|
if (!SCDynamicStoreSetNotificationKeys(store, (CFArrayRef)keys, NULL)) {
|
||||||
|
NSLog(@"faild to set the store for notifications %s", SCErrorString(SCError()));
|
||||||
|
CFRelease(store);
|
||||||
|
store = NULL;
|
||||||
|
} else {
|
||||||
|
runLoop = SCDynamicStoreCreateRunLoopSource(kCFAllocatorDefault, store, 0);
|
||||||
|
CFRunLoopAddSource(CFRunLoopGetCurrent(), runLoop, kCFRunLoopDefaultMode);
|
||||||
|
|
||||||
|
[lastMediaInfo release];
|
||||||
|
lastMediaInfo = [[self getEthernetMedia] retain];
|
||||||
|
|
||||||
|
NSDictionary *IPv4State = (NSDictionary *)SCDynamicStoreCopyValue(store, (CFStringRef)MGMIPv4State);
|
||||||
|
NSDictionary *IPv4Info = (NSDictionary *)SCDynamicStoreCopyValue(store, (CFStringRef)[NSString stringWithFormat:MGMIPv4Info, [IPv4State objectForKey:MGMPrimaryInterface]]);
|
||||||
|
NSArray *addressesArray = [IPv4Info objectForKey:MGMAddresses];
|
||||||
|
if ([addressesArray count]>0) {
|
||||||
|
NSMutableString *addresses = [NSMutableString string];
|
||||||
|
for (int i=0; i<[addressesArray count]; i++) {
|
||||||
|
if (![addresses isEqual:@""])
|
||||||
|
[addresses appendString:@"\n"];
|
||||||
|
[addresses appendString:[addressesArray objectAtIndex:i]];
|
||||||
|
}
|
||||||
|
IPv4Addresses = [addresses retain];
|
||||||
|
}
|
||||||
|
[IPv4Info release];
|
||||||
|
[IPv4State release];
|
||||||
|
|
||||||
|
NSDictionary *IPv6State = (NSDictionary *)SCDynamicStoreCopyValue(store, (CFStringRef)MGMIPv6State);
|
||||||
|
NSDictionary *IPv6Info = (NSDictionary *)SCDynamicStoreCopyValue(store, (CFStringRef)[NSString stringWithFormat:MGMIPv6Info, [IPv6State objectForKey:MGMPrimaryInterface]]);
|
||||||
|
addressesArray = [IPv6Info objectForKey:MGMAddresses];
|
||||||
|
if ([addressesArray count]>0) {
|
||||||
|
NSMutableString *addresses = [NSMutableString string];
|
||||||
|
for (int i=0; i<[addressesArray count]; i++) {
|
||||||
|
if (![addresses isEqual:@""])
|
||||||
|
[addresses appendString:@"\n"];
|
||||||
|
[addresses appendString:[addressesArray objectAtIndex:i]];
|
||||||
|
}
|
||||||
|
IPv6Addresses = [addresses retain];
|
||||||
|
}
|
||||||
|
[IPv6Info release];
|
||||||
|
[IPv6State release];
|
||||||
|
|
||||||
|
lastAirPortState = (NSDictionary *)SCDynamicStoreCopyValue(store, (CFStringRef)MGMAirPortInfo);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
- (void)dealloc {
|
||||||
|
if (store!=NULL) {
|
||||||
|
CFRunLoopRemoveSource(CFRunLoopGetCurrent(), runLoop, kCFRunLoopDefaultMode);
|
||||||
|
CFRelease(store);
|
||||||
|
}
|
||||||
|
[lastAirPortState release];
|
||||||
|
[super dealloc];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (NSString *)getEthernetMedia {
|
||||||
|
int testSocket = socket(AF_INET, SOCK_DGRAM, 0);
|
||||||
|
if (testSocket<0) {
|
||||||
|
NSLog(@"Can't open datagram socket");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
struct ifmediareq mediaRequest;
|
||||||
|
memset(&mediaRequest, 0, sizeof(mediaRequest));
|
||||||
|
strncpy(mediaRequest.ifm_name, "en0", sizeof(mediaRequest.ifm_name));
|
||||||
|
|
||||||
|
if (ioctl(testSocket, SIOCGIFMEDIA, (caddr_t)&mediaRequest) < 0) {
|
||||||
|
close(testSocket);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
close(testSocket);
|
||||||
|
|
||||||
|
const char *type = "Unknown";
|
||||||
|
struct ifmedia_description *description;
|
||||||
|
for (description = ifm_subtype_ethernet_descriptions; description->ifmt_string; description++) {
|
||||||
|
if (IFM_SUBTYPE(mediaRequest.ifm_active) == description->ifmt_word) {
|
||||||
|
type = description->ifmt_string;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
NSMutableString *options = [NSMutableString string];
|
||||||
|
for (description = ifm_shared_option_descriptions; description->ifmt_string; description++) {
|
||||||
|
if (mediaRequest.ifm_active & description->ifmt_word) {
|
||||||
|
if (![options isEqual:@""])
|
||||||
|
[options appendString:@","];
|
||||||
|
[options appendString:[NSString stringWithUTF8String:description->ifmt_string]];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ([options isEqual:@""])
|
||||||
|
return [NSString stringWithUTF8String:type];
|
||||||
|
return [NSString stringWithFormat:@"%s <%@>", type, options];
|
||||||
|
}
|
||||||
|
- (void)ethernetLinkChanged:(NSDictionary *)theState {
|
||||||
|
if ([[theState objectForKey:@"Active"] boolValue]) {
|
||||||
|
[lastMediaInfo release];
|
||||||
|
lastMediaInfo = [[self getEthernetMedia] retain];
|
||||||
|
[[MGMController sharedController] startNotificationWithInfo:[NSDictionary dictionaryWithObjectsAndKeys:@"ethernetconnected", MGMNName, @"Ethernet Connected", MGMNTitle, lastMediaInfo, MGMNDescription, [NSImage imageNamed:@"Ethernet"], MGMNIcon, nil]];
|
||||||
|
} else{
|
||||||
|
[[MGMController sharedController] startNotificationWithInfo:[NSDictionary dictionaryWithObjectsAndKeys:@"ethernetdisconnected", MGMNName, @"Ethernet Disconnected", MGMNTitle, lastMediaInfo, MGMNDescription, [NSImage imageNamed:@"Ethernet"], MGMNIcon, nil]];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)checkIPAddresses {
|
||||||
|
if (lastCheck!=nil && [lastCheck earlierDate:[NSDate dateWithTimeIntervalSinceNow:-2]]==lastCheck)
|
||||||
|
return;
|
||||||
|
[lastCheck release];
|
||||||
|
lastCheck = [NSDate new];
|
||||||
|
|
||||||
|
[connection cancel];
|
||||||
|
[connection release];
|
||||||
|
[data release];
|
||||||
|
data = [NSMutableData new];
|
||||||
|
connection = [[NSURLConnection connectionWithRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:@"http://ipv4.mrgeckosmedia.net/ip.php"] cachePolicy:NSURLRequestReloadIgnoringCacheData timeoutInterval:5] delegate:self] retain];
|
||||||
|
[connection2 cancel];
|
||||||
|
[connection2 release];
|
||||||
|
[data2 release];
|
||||||
|
data2 = [NSMutableData new];
|
||||||
|
connection2 = [[NSURLConnection connectionWithRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:@"http://ipv6.mrgeckosmedia.net/ip.php"] cachePolicy:NSURLRequestReloadIgnoringCacheData timeoutInterval:5] delegate:self] retain];
|
||||||
|
}
|
||||||
|
- (void)connection:(NSURLConnection *)theConnection didFailWithError:(NSError *)theError {
|
||||||
|
NSLog(@"%@", theError);
|
||||||
|
}
|
||||||
|
- (void)connection:(NSURLConnection *)theConnection didReceiveResponse:(NSHTTPURLResponse *)theResponse {
|
||||||
|
if (![[[theResponse MIMEType] lowercaseString] isEqual:@"text/plain"]) {
|
||||||
|
if (theConnection==connection) {
|
||||||
|
[connection cancel];
|
||||||
|
[connection release];
|
||||||
|
connection = nil;
|
||||||
|
[data release];
|
||||||
|
data = nil;
|
||||||
|
} else if (theConnection==connection2) {
|
||||||
|
[connection2 cancel];
|
||||||
|
[connection2 release];
|
||||||
|
connection2 = nil;
|
||||||
|
[data2 release];
|
||||||
|
data2 = nil;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
- (void)connection:(NSURLConnection *)theConnection didReceiveData:(NSData *)theData {
|
||||||
|
if (theConnection==connection)
|
||||||
|
[data appendData:theData];
|
||||||
|
else if (theConnection==connection2)
|
||||||
|
[data2 appendData:theData];
|
||||||
|
}
|
||||||
|
- (void)connectionDidFinishLoading:(NSURLConnection *)theConnection {
|
||||||
|
if (theConnection==connection) {
|
||||||
|
NSString *ip = [[[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding] autorelease];
|
||||||
|
[[MGMController sharedController] startNotificationWithInfo:[NSDictionary dictionaryWithObjectsAndKeys:@"ipv4address", MGMNName, @"External IPv4 Address", MGMNTitle, ip, MGMNDescription, [NSImage imageNamed:@"Ethernet"], MGMNIcon, nil]];
|
||||||
|
[data release];
|
||||||
|
data = nil;
|
||||||
|
[connection release];
|
||||||
|
connection = nil;
|
||||||
|
} else if (theConnection==connection2) {
|
||||||
|
NSString *ip = [[[NSString alloc] initWithData:data2 encoding:NSUTF8StringEncoding] autorelease];
|
||||||
|
[[MGMController sharedController] startNotificationWithInfo:[NSDictionary dictionaryWithObjectsAndKeys:@"ipv6address", MGMNName, @"External IPv6 Address", MGMNTitle, ip, MGMNDescription, [NSImage imageNamed:@"Ethernet"], MGMNIcon, nil]];
|
||||||
|
[data2 release];
|
||||||
|
data2 = nil;
|
||||||
|
[connection2 release];
|
||||||
|
connection2 = nil;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)ipv4Changed:(NSDictionary *)theInfo {
|
||||||
|
NSDictionary *info = (NSDictionary *)SCDynamicStoreCopyValue(store, (CFStringRef)[NSString stringWithFormat:MGMIPv4Info, [theInfo objectForKey:MGMPrimaryInterface]]);
|
||||||
|
NSArray *addressesArray = [info objectForKey:MGMAddresses];
|
||||||
|
if ([addressesArray count]>0) {
|
||||||
|
NSMutableString *addresses = [NSMutableString string];
|
||||||
|
for (int i=0; i<[addressesArray count]; i++) {
|
||||||
|
if (![addresses isEqual:@""])
|
||||||
|
[addresses appendString:@"\n"];
|
||||||
|
[addresses appendString:[addressesArray objectAtIndex:i]];
|
||||||
|
}
|
||||||
|
[IPv4Addresses release];
|
||||||
|
IPv4Addresses = [addresses retain];
|
||||||
|
[[MGMController sharedController] startNotificationWithInfo:[NSDictionary dictionaryWithObjectsAndKeys:@"ipv4acquired", MGMNName, @"IPv4 Acquired", MGMNTitle, addresses, MGMNDescription, [NSImage imageNamed:@"Ethernet"], MGMNIcon, nil]];
|
||||||
|
[self checkIPAddresses];
|
||||||
|
} else {
|
||||||
|
[[MGMController sharedController] startNotificationWithInfo:[NSDictionary dictionaryWithObjectsAndKeys:@"ipv4released", MGMNName, @"IPv4 Released", MGMNTitle, IPv4Addresses, MGMNDescription, [NSImage imageNamed:@"Ethernet"], MGMNIcon, nil]];
|
||||||
|
}
|
||||||
|
[info release];
|
||||||
|
}
|
||||||
|
- (void)ipv6Changed:(NSDictionary *)theInfo {
|
||||||
|
NSDictionary *info = (NSDictionary *)SCDynamicStoreCopyValue(store, (CFStringRef)[NSString stringWithFormat:MGMIPv6Info, [theInfo objectForKey:MGMPrimaryInterface]]);
|
||||||
|
NSArray *addressesArray = [info objectForKey:MGMAddresses];
|
||||||
|
if ([addressesArray count]>0) {
|
||||||
|
NSMutableString *addresses = [NSMutableString string];
|
||||||
|
for (int i=0; i<[addressesArray count]; i++) {
|
||||||
|
if (![addresses isEqual:@""])
|
||||||
|
[addresses appendString:@"\n"];
|
||||||
|
[addresses appendString:[addressesArray objectAtIndex:i]];
|
||||||
|
}
|
||||||
|
[IPv6Addresses release];
|
||||||
|
IPv6Addresses = [addresses retain];
|
||||||
|
[[MGMController sharedController] startNotificationWithInfo:[NSDictionary dictionaryWithObjectsAndKeys:@"ipv6acquired", MGMNName, @"IPv6 Acquired", MGMNTitle, addresses, MGMNDescription, [NSImage imageNamed:@"Ethernet"], MGMNIcon, nil]];
|
||||||
|
[self checkIPAddresses];
|
||||||
|
} else {
|
||||||
|
[[MGMController sharedController] startNotificationWithInfo:[NSDictionary dictionaryWithObjectsAndKeys:@"ipv6released", MGMNName, @"IPv6 Released", MGMNTitle, IPv6Addresses, MGMNDescription, [NSImage imageNamed:@"Ethernet"], MGMNIcon, nil]];
|
||||||
|
}
|
||||||
|
[info release];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)airportChanged:(NSDictionary *)theInfo {
|
||||||
|
if (theInfo!=nil && ![theInfo isEqual:lastAirPortState]) {
|
||||||
|
NSData *BSSID = [theInfo objectForKey:MGMBSSID];
|
||||||
|
if (![BSSID isEqual:[NSData dataWithBytes:"\x00" length:1]]) {
|
||||||
|
NSNumber *linkStatus = [theInfo objectForKey:@"Link Status"];
|
||||||
|
NSNumber *powerStatus = [theInfo objectForKey:@"Power Status"];
|
||||||
|
if (linkStatus || powerStatus) {
|
||||||
|
int status = 0;
|
||||||
|
if (linkStatus) {
|
||||||
|
status = [linkStatus intValue];
|
||||||
|
} else if (powerStatus) {
|
||||||
|
status = [powerStatus intValue];
|
||||||
|
status = !status;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ([BSSID isEqual:[lastAirPortState objectForKey:MGMBSSID]] && status!=1 && [[theInfo objectForKey:@"Busy"] boolValue])
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (status==1) {
|
||||||
|
NSString *SSID = [lastAirPortState objectForKey:MGMSSID];
|
||||||
|
const unsigned char *BSSIDBytes = [[lastAirPortState objectForKey:MGMBSSID] bytes];
|
||||||
|
NSString *BSSIDString = nil;
|
||||||
|
if (BSSIDBytes!=NULL)
|
||||||
|
BSSIDString = [NSString stringWithFormat:@"%02X:%02X:%02X:%02X:%02X:%02X", BSSIDBytes[0], BSSIDBytes[1], BSSIDBytes[2], BSSIDBytes[3], BSSIDBytes[4], BSSIDBytes[5]];
|
||||||
|
int channel = [[[lastAirPortState objectForKey:MGMCHANNEL] objectForKey:MGMCHANNEL] intValue];
|
||||||
|
NSString *name = [NSString stringWithFormat:@"SSID: %@\nBSSID: %@\nChannel: %d", SSID, BSSIDString, channel];
|
||||||
|
[[MGMController sharedController] startNotificationWithInfo:[NSDictionary dictionaryWithObjectsAndKeys:@"airportdisconnected", MGMNName, @"AirPort Disconnected", MGMNTitle, name, MGMNDescription, [NSImage imageNamed:@"AirPort"], MGMNIcon, nil]];
|
||||||
|
} else {
|
||||||
|
NSString *SSID = [theInfo objectForKey:MGMSSID];
|
||||||
|
const unsigned char *BSSIDBytes = [BSSID bytes];
|
||||||
|
NSString *BSSIDString = nil;
|
||||||
|
if (BSSIDBytes!=NULL)
|
||||||
|
BSSIDString = [NSString stringWithFormat:@"%02X:%02X:%02X:%02X:%02X:%02X", BSSIDBytes[0], BSSIDBytes[1], BSSIDBytes[2], BSSIDBytes[3], BSSIDBytes[4], BSSIDBytes[5]];
|
||||||
|
int channel = [[[theInfo objectForKey:MGMCHANNEL] objectForKey:MGMCHANNEL] intValue];
|
||||||
|
NSString *name = [NSString stringWithFormat:@"SSID: %@\nBSSID: %@\nChannel: %d", SSID, BSSIDString, channel];
|
||||||
|
[[MGMController sharedController] startNotificationWithInfo:[NSDictionary dictionaryWithObjectsAndKeys:@"airportconnected", MGMNName, @"AirPort Connected", MGMNTitle, name, MGMNDescription, [NSImage imageNamed:@"AirPort"], MGMNIcon, nil]];
|
||||||
|
}
|
||||||
|
[lastAirPortState release];
|
||||||
|
lastAirPortState = [theInfo retain];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@end
|
20
Classes/Watchers/MGMPowerWatcher.h
Normal file
20
Classes/Watchers/MGMPowerWatcher.h
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
//
|
||||||
|
// MGMPowerWatcher.h
|
||||||
|
// SoundNote
|
||||||
|
//
|
||||||
|
// Created by Mr. Gecko on 2/16/11.
|
||||||
|
// Copyright (c) 2011 Mr. Gecko's Media (James Coleman). All rights reserved. http://mrgeckosmedia.com/
|
||||||
|
//
|
||||||
|
|
||||||
|
#import <Foundation/Foundation.h>
|
||||||
|
|
||||||
|
@interface MGMPowerWatcher : NSObject {
|
||||||
|
CFRunLoopSourceRef runLoop;
|
||||||
|
BOOL batterWarned20;
|
||||||
|
BOOL batterWarned10;
|
||||||
|
BOOL batterWarned5;
|
||||||
|
}
|
||||||
|
- (void)powerSourceChanged:(int)theType;
|
||||||
|
- (void)powerChargingStateChanged:(BOOL)isCharging percentage:(int)thePercent;
|
||||||
|
- (void)powerTimeChanged:(int)theTime;
|
||||||
|
@end
|
135
Classes/Watchers/MGMPowerWatcher.m
Normal file
135
Classes/Watchers/MGMPowerWatcher.m
Normal file
@ -0,0 +1,135 @@
|
|||||||
|
//
|
||||||
|
// MGMPowerWatcher.m
|
||||||
|
// SoundNote
|
||||||
|
//
|
||||||
|
// Created by Mr. Gecko on 2/16/11.
|
||||||
|
// Copyright (c) 2011 Mr. Gecko's Media (James Coleman). All rights reserved. http://mrgeckosmedia.com/
|
||||||
|
//
|
||||||
|
|
||||||
|
#import "MGMPowerWatcher.h"
|
||||||
|
#import "MGMController.h"
|
||||||
|
#import <IOKit/IOKitLib.h>
|
||||||
|
#import <IOKit/ps/IOPSKeys.h>
|
||||||
|
#import <IOKit/ps/IOPowerSources.h>
|
||||||
|
|
||||||
|
static int lastPowerSource;
|
||||||
|
static BOOL lastChargingState;
|
||||||
|
static int lastBatteryTime;
|
||||||
|
|
||||||
|
static void powerNotification(void *context) {
|
||||||
|
CFTypeRef powerInfo = IOPSCopyPowerSourcesInfo();
|
||||||
|
NSArray *powerSources = (NSArray *)IOPSCopyPowerSourcesList(powerInfo);
|
||||||
|
|
||||||
|
for (int i=0; i<[powerSources count]; ++i) {
|
||||||
|
NSString *powerSource;
|
||||||
|
NSDictionary *powerSourceInfo;
|
||||||
|
int powerSourceType = -1;
|
||||||
|
BOOL charging = NO;
|
||||||
|
int batteryTime = -1;
|
||||||
|
int percentage = 0;
|
||||||
|
|
||||||
|
powerSource = [powerSources objectAtIndex:i];
|
||||||
|
powerSourceInfo = (NSDictionary *)IOPSGetPowerSourceDescription(powerInfo, powerSource);
|
||||||
|
|
||||||
|
if (![[powerSourceInfo objectForKey:[NSString stringWithUTF8String:kIOPSIsPresentKey]] boolValue])
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if ([[powerSourceInfo objectForKey:[NSString stringWithUTF8String:kIOPSTransportTypeKey]] isEqual:[NSString stringWithUTF8String:kIOPSInternalType]]) {
|
||||||
|
NSString *currentState = [powerSourceInfo objectForKey:[NSString stringWithUTF8String:kIOPSPowerSourceStateKey]];
|
||||||
|
|
||||||
|
if ([currentState isEqual:[NSString stringWithUTF8String:kIOPSACPowerValue]])
|
||||||
|
powerSourceType = 0;
|
||||||
|
else if ([currentState isEqual:[NSString stringWithUTF8String:kIOPSBatteryPowerValue]])
|
||||||
|
powerSourceType = 1;
|
||||||
|
else
|
||||||
|
powerSourceType = -1;
|
||||||
|
|
||||||
|
charging = [[powerSourceInfo objectForKey:[NSString stringWithUTF8String:kIOPSIsChargingKey]] boolValue];
|
||||||
|
if (charging) {
|
||||||
|
batteryTime = [[powerSourceInfo objectForKey:[NSString stringWithUTF8String:kIOPSTimeToFullChargeKey]] intValue];
|
||||||
|
} else {
|
||||||
|
batteryTime = [[powerSourceInfo objectForKey:[NSString stringWithUTF8String:kIOPSTimeToEmptyKey]] intValue];
|
||||||
|
}
|
||||||
|
|
||||||
|
float currentCapacity = [[powerSourceInfo objectForKey:[NSString stringWithUTF8String:kIOPSCurrentCapacityKey]] floatValue];;
|
||||||
|
float maxCapacity = [[powerSourceInfo objectForKey:[NSString stringWithUTF8String:kIOPSMaxCapacityKey]] floatValue];;
|
||||||
|
percentage = roundf((currentCapacity/maxCapacity)*100.0);
|
||||||
|
} else {
|
||||||
|
powerSourceType = 2;
|
||||||
|
}
|
||||||
|
if (lastPowerSource!=powerSourceType) {
|
||||||
|
[(MGMPowerWatcher *)context powerSourceChanged:powerSourceType];
|
||||||
|
lastPowerSource = powerSourceType;
|
||||||
|
}
|
||||||
|
if (powerSourceType==0 && lastChargingState!=charging) {
|
||||||
|
[(MGMPowerWatcher *)context powerChargingStateChanged:charging percentage:percentage];
|
||||||
|
lastChargingState = charging;
|
||||||
|
}
|
||||||
|
if (batteryTime!=-1 && lastBatteryTime!=batteryTime) {
|
||||||
|
[(MGMPowerWatcher *)context powerTimeChanged:batteryTime];
|
||||||
|
lastBatteryTime = batteryTime;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[powerSources release];
|
||||||
|
CFRelease(powerInfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
@implementation MGMPowerWatcher
|
||||||
|
- (id)init {
|
||||||
|
if ((self = [super init])) {
|
||||||
|
runLoop = IOPSNotificationCreateRunLoopSource(powerNotification, self);
|
||||||
|
if (runLoop!=NULL)
|
||||||
|
CFRunLoopAddSource(CFRunLoopGetCurrent(), runLoop, kCFRunLoopDefaultMode);
|
||||||
|
lastPowerSource = -1;
|
||||||
|
lastBatteryTime = -1;
|
||||||
|
batterWarned20 = NO;
|
||||||
|
batterWarned10 = NO;
|
||||||
|
batterWarned5 = NO;
|
||||||
|
}
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
- (void)dealloc {
|
||||||
|
[super dealloc];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)powerSourceChanged:(int)theType {
|
||||||
|
NSString *name = (theType==0 ? @"Power Adapter" : (theType==1 ? @"Battery" : @"UPS"));
|
||||||
|
[[MGMController sharedController] startNotificationWithInfo:[NSDictionary dictionaryWithObjectsAndKeys:@"powersourcechanged", MGMNName, @"New Power Source", MGMNTitle, name, MGMNDescription, [NSImage imageNamed:(theType==0 ? @"BatteryCharging" : @"Battery")], MGMNIcon, nil]];
|
||||||
|
if (theType==0) {
|
||||||
|
batterWarned20 = NO;
|
||||||
|
batterWarned10 = NO;
|
||||||
|
batterWarned5 = NO;
|
||||||
|
lastBatteryTime = -1;
|
||||||
|
[[MGMController sharedController] startNotificationWithInfo:[NSDictionary dictionaryWithObjectsAndKeys:@"poweronac", MGMNName, @"Power Source", MGMNTitle, name, MGMNDescription, [NSImage imageNamed:@"BatteryCharging"], MGMNIcon, nil]];
|
||||||
|
} else if (theType==1) {
|
||||||
|
[[MGMController sharedController] startNotificationWithInfo:[NSDictionary dictionaryWithObjectsAndKeys:@"poweronbattery", MGMNName, @"Power Source", MGMNTitle, name, MGMNDescription, [NSImage imageNamed:@"Battery"], MGMNIcon, nil]];
|
||||||
|
} else if (theType==2) {
|
||||||
|
[[MGMController sharedController] startNotificationWithInfo:[NSDictionary dictionaryWithObjectsAndKeys:@"poweronups", MGMNName, @"Power Source", MGMNTitle, name, MGMNDescription, [NSImage imageNamed:@"Battery"], MGMNIcon, nil]];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
- (void)powerChargingStateChanged:(BOOL)isCharging percentage:(int)thePercent {
|
||||||
|
if (isCharging) {
|
||||||
|
[[MGMController sharedController] startNotificationWithInfo:[NSDictionary dictionaryWithObjectsAndKeys:@"charging", MGMNName, @"Charging", MGMNTitle, [NSString stringWithFormat:@"%d%%", thePercent], MGMNDescription, [NSImage imageNamed:(isCharging ? @"BatteryCharging" : @"Battery")], MGMNIcon, nil]];
|
||||||
|
} else {
|
||||||
|
[[MGMController sharedController] startNotificationWithInfo:[NSDictionary dictionaryWithObjectsAndKeys:@"charged", MGMNName, @"Charged", MGMNTitle, [NSString stringWithFormat:@"%d%%", thePercent], MGMNDescription, [NSImage imageNamed:(isCharging ? @"BatteryCharging" : @"Battery")], MGMNIcon, nil]];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
- (void)powerTimeChanged:(int)theTime {
|
||||||
|
if (lastBatteryTime==-1) {
|
||||||
|
[[MGMController sharedController] startNotificationWithInfo:[NSDictionary dictionaryWithObjectsAndKeys:@"batterytime", MGMNName, @"Battery Charging", MGMNTitle, [NSString stringWithFormat:@"There is %d minutes remaining.", theTime], MGMNDescription, [NSImage imageNamed:(lastChargingState ? @"BatteryCharging" : @"Battery")], MGMNIcon, nil]];
|
||||||
|
}
|
||||||
|
if (lastPowerSource!=0) {
|
||||||
|
if (theTime<=20 && theTime>10 && !batterWarned20) {
|
||||||
|
batterWarned20 = YES;
|
||||||
|
[[MGMController sharedController] startNotificationWithInfo:[NSDictionary dictionaryWithObjectsAndKeys:@"battery20minutes", MGMNName, @"Battery Warning", MGMNTitle, @"There is 20 minutes remaining.", MGMNDescription, [NSImage imageNamed:(lastChargingState ? @"BatteryCharging" : @"Battery")], MGMNIcon, nil]];
|
||||||
|
} else if (theTime<=10 && theTime>5 && !batterWarned10) {
|
||||||
|
batterWarned10 = YES;
|
||||||
|
[[MGMController sharedController] startNotificationWithInfo:[NSDictionary dictionaryWithObjectsAndKeys:@"battery10minutes", MGMNName, @"Battery Warning", MGMNTitle, @"There is 10 minutes remaining.", MGMNDescription, [NSImage imageNamed:(lastChargingState ? @"BatteryCharging" : @"Battery")], MGMNIcon, nil]];
|
||||||
|
} else if (theTime<=5 && !batterWarned5) {
|
||||||
|
batterWarned5 = YES;
|
||||||
|
[[MGMController sharedController] startNotificationWithInfo:[NSDictionary dictionaryWithObjectsAndKeys:@"battery5minutes", MGMNName, @"Battery Warning", MGMNTitle, @"There is 5 minutes remaining.", MGMNDescription, [NSImage imageNamed:(lastChargingState ? @"BatteryCharging" : @"Battery")], MGMNIcon, nil]];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@end
|
18
Classes/Watchers/MGMTrashWatcher.h
Normal file
18
Classes/Watchers/MGMTrashWatcher.h
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
//
|
||||||
|
// MGMTrashWatcher.h
|
||||||
|
// SoundNote
|
||||||
|
//
|
||||||
|
// Created by Mr. Gecko on 2/17/11.
|
||||||
|
// Copyright (c) 2011 Mr. Gecko's Media (James Coleman). All rights reserved. http://mrgeckosmedia.com/
|
||||||
|
//
|
||||||
|
|
||||||
|
#import <Foundation/Foundation.h>
|
||||||
|
|
||||||
|
@class MGMPathSubscriber;
|
||||||
|
|
||||||
|
@interface MGMTrashWatcher : NSObject {
|
||||||
|
MGMPathSubscriber *trashWatcher;
|
||||||
|
int lastCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
42
Classes/Watchers/MGMTrashWatcher.m
Normal file
42
Classes/Watchers/MGMTrashWatcher.m
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
//
|
||||||
|
// MGMTrashWatcher.m
|
||||||
|
// SoundNote
|
||||||
|
//
|
||||||
|
// Created by Mr. Gecko on 2/17/11.
|
||||||
|
// Copyright (c) 2011 Mr. Gecko's Media (James Coleman). All rights reserved. http://mrgeckosmedia.com/
|
||||||
|
//
|
||||||
|
|
||||||
|
#import "MGMTrashWatcher.h"
|
||||||
|
#import "MGMController.h"
|
||||||
|
#import "MGMPathSubscriber.h"
|
||||||
|
#import "MGMFileManager.h"
|
||||||
|
|
||||||
|
NSString * const MGMTrashFolder = @"~/.Trash";
|
||||||
|
|
||||||
|
@implementation MGMTrashWatcher
|
||||||
|
- (id)init {
|
||||||
|
if ((self = [super init])) {
|
||||||
|
NSFileManager *manager = [NSFileManager defaultManager];
|
||||||
|
lastCount = [[manager contentsOfDirectoryAtPath:[MGMTrashFolder stringByExpandingTildeInPath]] count];
|
||||||
|
trashWatcher = [MGMPathSubscriber new];
|
||||||
|
[trashWatcher setDelegate:self];
|
||||||
|
[trashWatcher addPath:[MGMTrashFolder stringByExpandingTildeInPath]];
|
||||||
|
}
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
- (void)dealloc {
|
||||||
|
[trashWatcher release];
|
||||||
|
[super dealloc];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)subscribedPathChanged:(NSString *)thePath {
|
||||||
|
NSFileManager *manager = [NSFileManager defaultManager];
|
||||||
|
int count = [[manager contentsOfDirectoryAtPath:[MGMTrashFolder stringByExpandingTildeInPath]] count];
|
||||||
|
if (count>lastCount) {
|
||||||
|
[[MGMController sharedController] startNotificationWithInfo:[NSDictionary dictionaryWithObjectsAndKeys:@"movedtotrash", MGMNName, @"Moved to Trash", MGMNTitle, @"An item was moved to the trash.", MGMNDescription, nil]];
|
||||||
|
} else if (lastCount!=count && count==0) {
|
||||||
|
[[MGMController sharedController] startNotificationWithInfo:[NSDictionary dictionaryWithObjectsAndKeys:@"trashemptied", MGMNName, @"Trash Emptied", MGMNTitle, @"The trash was emptied.", MGMNDescription, nil]];
|
||||||
|
}
|
||||||
|
lastCount = count;
|
||||||
|
}
|
||||||
|
@end
|
19
Classes/Watchers/MGMUSBWatcher.h
Normal file
19
Classes/Watchers/MGMUSBWatcher.h
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
//
|
||||||
|
// MGMUSBWatcher.h
|
||||||
|
// SoundNote
|
||||||
|
//
|
||||||
|
// Created by Mr. Gecko on 2/15/11.
|
||||||
|
// Copyright (c) 2011 Mr. Gecko's Media (James Coleman). All rights reserved. http://mrgeckosmedia.com/
|
||||||
|
//
|
||||||
|
|
||||||
|
#import <Foundation/Foundation.h>
|
||||||
|
|
||||||
|
@interface MGMUSBWatcher : NSObject {
|
||||||
|
IONotificationPortRef notificationPort;
|
||||||
|
CFRunLoopSourceRef runLoop;
|
||||||
|
|
||||||
|
NSMutableArray *USBDevices;
|
||||||
|
}
|
||||||
|
- (void)usbDeviceConnected:(io_object_t)theDevice;
|
||||||
|
- (void)usbDeviceDisconnected:(io_object_t)theDevice;
|
||||||
|
@end
|
113
Classes/Watchers/MGMUSBWatcher.m
Normal file
113
Classes/Watchers/MGMUSBWatcher.m
Normal file
@ -0,0 +1,113 @@
|
|||||||
|
//
|
||||||
|
// MGMUSBWatcher.m
|
||||||
|
// SoundNote
|
||||||
|
//
|
||||||
|
// Created by Mr. Gecko on 2/15/11.
|
||||||
|
// Copyright (c) 2011 Mr. Gecko's Media (James Coleman). All rights reserved. http://mrgeckosmedia.com/
|
||||||
|
//
|
||||||
|
|
||||||
|
#import "MGMUSBWatcher.h"
|
||||||
|
#import "MGMController.h"
|
||||||
|
#import <IOKit/IOKitLib.h>
|
||||||
|
|
||||||
|
char * const IOUSBDevice = "IOUSBDevice";
|
||||||
|
|
||||||
|
static void usbConnected(void *refCon, io_iterator_t iterator) {
|
||||||
|
io_object_t object;
|
||||||
|
while ((object = IOIteratorNext(iterator))) {
|
||||||
|
[(MGMUSBWatcher *)refCon usbDeviceConnected:object];
|
||||||
|
IOObjectRelease(object);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
static void usbDisconnected(void *refCon, io_iterator_t iterator) {
|
||||||
|
io_object_t object;
|
||||||
|
while ((object = IOIteratorNext(iterator))) {
|
||||||
|
[(MGMUSBWatcher *)refCon usbDeviceDisconnected:object];
|
||||||
|
IOObjectRelease(object);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static NSString *nameForIOUSB(io_object_t object) {
|
||||||
|
io_name_t ioDeviceName;
|
||||||
|
NSString *deviceName = nil;
|
||||||
|
kern_return_t result = IORegistryEntryGetName(object, ioDeviceName);
|
||||||
|
if (result==noErr)
|
||||||
|
deviceName = [(NSString *)CFStringCreateWithCString(kCFAllocatorDefault, ioDeviceName, kCFStringEncodingUTF8) autorelease];
|
||||||
|
if (deviceName!=nil)
|
||||||
|
return deviceName;
|
||||||
|
|
||||||
|
return @"Unnamed Device";
|
||||||
|
}
|
||||||
|
static NSString *idForIOUSB(io_object_t object) {
|
||||||
|
uint64_t ioDeviceID;
|
||||||
|
NSString *deviceID = nil;
|
||||||
|
kern_return_t result = IORegistryEntryGetRegistryEntryID(object, &ioDeviceID);
|
||||||
|
if (result==noErr)
|
||||||
|
deviceID = [NSString stringWithFormat:@"%11x", ioDeviceID];
|
||||||
|
if (deviceID!=nil)
|
||||||
|
return deviceID;
|
||||||
|
|
||||||
|
return @"Unknown ID";
|
||||||
|
}
|
||||||
|
|
||||||
|
@implementation MGMUSBWatcher
|
||||||
|
- (id)init {
|
||||||
|
if ((self = [super init])) {
|
||||||
|
notificationPort = IONotificationPortCreate(kIOMasterPortDefault);
|
||||||
|
runLoop = IONotificationPortGetRunLoopSource(notificationPort);
|
||||||
|
CFRunLoopAddSource(CFRunLoopGetCurrent(), runLoop, kCFRunLoopDefaultMode);
|
||||||
|
|
||||||
|
USBDevices = [NSMutableArray new];
|
||||||
|
|
||||||
|
CFDictionaryRef servicesMatch = IOServiceMatching(IOUSBDevice);
|
||||||
|
io_iterator_t found;
|
||||||
|
kern_return_t result = IOServiceAddMatchingNotification(notificationPort, kIOPublishNotification, servicesMatch, usbConnected, self, &found);
|
||||||
|
if (result!=kIOReturnSuccess)
|
||||||
|
NSLog(@"Unable to register for usb add %d", result);
|
||||||
|
io_object_t object;
|
||||||
|
while ((object = IOIteratorNext(found))) {
|
||||||
|
NSString *deviceID = idForIOUSB(object);
|
||||||
|
if (![USBDevices containsObject:deviceID])
|
||||||
|
[USBDevices addObject:deviceID];
|
||||||
|
IOObjectRelease(object);
|
||||||
|
}
|
||||||
|
|
||||||
|
servicesMatch = IOServiceMatching(IOUSBDevice);
|
||||||
|
result = IOServiceAddMatchingNotification(notificationPort, kIOTerminatedNotification, servicesMatch, usbDisconnected, self, &found);
|
||||||
|
if (result!=kIOReturnSuccess)
|
||||||
|
NSLog(@"Unable to register for usb remove %d", result);
|
||||||
|
else {
|
||||||
|
while ((object = IOIteratorNext(found))) {
|
||||||
|
NSString *deviceID = idForIOUSB(object);
|
||||||
|
if ([USBDevices containsObject:deviceID])
|
||||||
|
[USBDevices removeObject:deviceID];
|
||||||
|
IOObjectRelease(object);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
- (void)dealloc {
|
||||||
|
if (notificationPort) {
|
||||||
|
CFRunLoopRemoveSource(CFRunLoopGetCurrent(), runLoop, kCFRunLoopDefaultMode);
|
||||||
|
IONotificationPortDestroy(notificationPort);
|
||||||
|
}
|
||||||
|
[USBDevices release];
|
||||||
|
[super dealloc];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)usbDeviceConnected:(io_object_t)theDevice {
|
||||||
|
NSString *deviceID = idForIOUSB(theDevice);
|
||||||
|
if (![USBDevices containsObject:deviceID]) {
|
||||||
|
[USBDevices addObject:deviceID];
|
||||||
|
[[MGMController sharedController] startNotificationWithInfo:[NSDictionary dictionaryWithObjectsAndKeys:@"usbconnected", MGMNName, @"USB Connected", MGMNTitle, nameForIOUSB(theDevice), MGMNDescription, [NSImage imageNamed:@"USB"], MGMNIcon, nil]];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
- (void)usbDeviceDisconnected:(io_object_t)theDevice {
|
||||||
|
NSString *deviceID = idForIOUSB(theDevice);
|
||||||
|
if ([USBDevices containsObject:deviceID]) {
|
||||||
|
[USBDevices removeObject:deviceID];
|
||||||
|
[[MGMController sharedController] startNotificationWithInfo:[NSDictionary dictionaryWithObjectsAndKeys:@"usbdisconnected", MGMNName, @"USB Disconnected", MGMNTitle, nameForIOUSB(theDevice), MGMNDescription, [NSImage imageNamed:@"USB"], MGMNIcon, nil]];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@end
|
15
Classes/Watchers/MGMVolumeWatcher.h
Normal file
15
Classes/Watchers/MGMVolumeWatcher.h
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
//
|
||||||
|
// MGMVolumeWatcher.h
|
||||||
|
// SoundNote
|
||||||
|
//
|
||||||
|
// Created by Mr. Gecko on 2/15/11.
|
||||||
|
// Copyright (c) 2011 Mr. Gecko's Media (James Coleman). All rights reserved. http://mrgeckosmedia.com/
|
||||||
|
//
|
||||||
|
|
||||||
|
#import <Foundation/Foundation.h>
|
||||||
|
|
||||||
|
@interface MGMVolumeWatcher : NSObject {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
81
Classes/Watchers/MGMVolumeWatcher.m
Normal file
81
Classes/Watchers/MGMVolumeWatcher.m
Normal file
@ -0,0 +1,81 @@
|
|||||||
|
//
|
||||||
|
// MGMVolumeWatcher.m
|
||||||
|
// SoundNote
|
||||||
|
//
|
||||||
|
// Created by Mr. Gecko on 2/15/11.
|
||||||
|
// Copyright (c) 2011 Mr. Gecko's Media (James Coleman). All rights reserved. http://mrgeckosmedia.com/
|
||||||
|
//
|
||||||
|
|
||||||
|
#import "MGMVolumeWatcher.h"
|
||||||
|
#import "MGMController.h"
|
||||||
|
#import "MGMMD5.h"
|
||||||
|
#import "MGMFileManager.h"
|
||||||
|
|
||||||
|
NSString * const MGMCachePath = @"~/Library/Caches/com.MrGeckosMedia.SoundNote/";
|
||||||
|
NSString * const MGMNSWorkspaceVolumeLocalizedNameKey = @"NSWorkspaceVolumeLocalizedNameKey";
|
||||||
|
NSString * const MGMNSDevicePath = @"NSDevicePath";
|
||||||
|
|
||||||
|
@implementation MGMVolumeWatcher
|
||||||
|
- (id)init {
|
||||||
|
if ((self = [super init])) {
|
||||||
|
NSFileManager *manager = [NSFileManager defaultManager];
|
||||||
|
if ([manager fileExistsAtPath:[MGMCachePath stringByExpandingTildeInPath]]) {
|
||||||
|
[manager removeItemAtPath:[MGMCachePath stringByExpandingTildeInPath]];
|
||||||
|
[manager createDirectoryAtPath:[MGMCachePath stringByExpandingTildeInPath] withAttributes:nil];
|
||||||
|
} else {
|
||||||
|
[manager createDirectoryAtPath:[MGMCachePath stringByExpandingTildeInPath] withAttributes:nil];
|
||||||
|
}
|
||||||
|
NSNotificationCenter *notificationCenter = [[NSWorkspace sharedWorkspace] notificationCenter];
|
||||||
|
[notificationCenter addObserver:self selector:@selector(volumeRenamed:) name:@"NSWorkspaceDidRenameVolumeNotification" object:nil];
|
||||||
|
[notificationCenter addObserver:self selector:@selector(didMountDrive:) name:NSWorkspaceDidMountNotification object:nil];
|
||||||
|
[notificationCenter addObserver:self selector:@selector(willUnmountDrive:) name:NSWorkspaceWillUnmountNotification object:nil];
|
||||||
|
[notificationCenter addObserver:self selector:@selector(didUnmountDrive:) name:NSWorkspaceDidUnmountNotification object:nil];
|
||||||
|
}
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
- (void)dealloc {
|
||||||
|
[[[NSWorkspace sharedWorkspace] notificationCenter] removeObserver:self];
|
||||||
|
[super dealloc];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)volumeRenamed:(NSNotification *)theNotification {
|
||||||
|
NSString *oldPath = [[[theNotification userInfo] objectForKey:@"NSWorkspaceVolumeOldURLKey"] path];
|
||||||
|
NSString *newPath = [[[theNotification userInfo] objectForKey:@"NSWorkspaceVolumeURLKey"] path];
|
||||||
|
NSFileManager *manager = [NSFileManager defaultManager];
|
||||||
|
NSImage *icon = [[NSWorkspace sharedWorkspace] iconForFile:newPath];
|
||||||
|
if ([manager fileExistsAtPath:[[MGMCachePath stringByExpandingTildeInPath] stringByAppendingPathComponent:[oldPath MD5]]]) {
|
||||||
|
[manager moveItemAtPath:[[MGMCachePath stringByExpandingTildeInPath] stringByAppendingPathComponent:[oldPath MD5]] toPath:[[MGMCachePath stringByExpandingTildeInPath] stringByAppendingPathComponent:[newPath MD5]]];
|
||||||
|
} else {
|
||||||
|
[[icon TIFFRepresentation] writeToFile:[[MGMCachePath stringByExpandingTildeInPath] stringByAppendingPathComponent:[newPath MD5]] atomically:NO];
|
||||||
|
}
|
||||||
|
[[MGMController sharedController] startNotificationWithInfo:[NSDictionary dictionaryWithObjectsAndKeys:@"volumerenamed", MGMNName, @"Volume Renamed", MGMNTitle, [NSString stringWithFormat:@"%@ is now %@.", [[theNotification userInfo] objectForKey:@"NSWorkspaceVolumeOldLocalizedNameKey"], [[theNotification userInfo] objectForKey:@"NSWorkspaceVolumeLocalizedNameKey"]], MGMNDescription, icon, MGMNIcon, nil]];
|
||||||
|
}
|
||||||
|
- (void)didMountDrive:(NSNotification *)theNotification {
|
||||||
|
NSImage *icon = [[NSWorkspace sharedWorkspace] iconForFile:[[theNotification userInfo] objectForKey:MGMNSDevicePath]];
|
||||||
|
[[icon TIFFRepresentation] writeToFile:[[MGMCachePath stringByExpandingTildeInPath] stringByAppendingPathComponent:[[[theNotification userInfo] objectForKey:MGMNSDevicePath] MD5]] atomically:NO];
|
||||||
|
[[MGMController sharedController] startNotificationWithInfo:[NSDictionary dictionaryWithObjectsAndKeys:@"didmountvolume", MGMNName, @"Volume Mounted", MGMNTitle, [[theNotification userInfo] objectForKey:MGMNSWorkspaceVolumeLocalizedNameKey], MGMNDescription, icon, MGMNIcon, nil]];
|
||||||
|
}
|
||||||
|
- (void)willUnmountDrive:(NSNotification *)theNotification {
|
||||||
|
NSFileManager *manager = [NSFileManager defaultManager];
|
||||||
|
NSImage *icon = nil;
|
||||||
|
if ([manager fileExistsAtPath:[[MGMCachePath stringByExpandingTildeInPath] stringByAppendingPathComponent:[[[theNotification userInfo] objectForKey:MGMNSDevicePath] MD5]]]) {
|
||||||
|
icon = [[[NSImage alloc] initWithContentsOfFile:[[MGMCachePath stringByExpandingTildeInPath] stringByAppendingPathComponent:[[[theNotification userInfo] objectForKey:MGMNSDevicePath] MD5]]] autorelease];
|
||||||
|
} else {
|
||||||
|
icon = [[NSWorkspace sharedWorkspace] iconForFile:[[theNotification userInfo] objectForKey:MGMNSDevicePath]];
|
||||||
|
[[icon TIFFRepresentation] writeToFile:[[MGMCachePath stringByExpandingTildeInPath] stringByAppendingPathComponent:[[[theNotification userInfo] objectForKey:MGMNSDevicePath] MD5]] atomically:NO];
|
||||||
|
}
|
||||||
|
[[MGMController sharedController] startNotificationWithInfo:[NSDictionary dictionaryWithObjectsAndKeys:@"willunmountvolume", MGMNName, @"Volume Will Umount", MGMNTitle, [[theNotification userInfo] objectForKey:MGMNSWorkspaceVolumeLocalizedNameKey], MGMNDescription, icon, MGMNIcon, nil]];
|
||||||
|
}
|
||||||
|
- (void)didUnmountDrive:(NSNotification *)theNotification {
|
||||||
|
NSFileManager *manager = [NSFileManager defaultManager];
|
||||||
|
NSImage *icon = nil;
|
||||||
|
if ([manager fileExistsAtPath:[[MGMCachePath stringByExpandingTildeInPath] stringByAppendingPathComponent:[[[theNotification userInfo] objectForKey:MGMNSDevicePath] MD5]]]) {
|
||||||
|
icon = [[[NSImage alloc] initWithContentsOfFile:[[MGMCachePath stringByExpandingTildeInPath] stringByAppendingPathComponent:[[[theNotification userInfo] objectForKey:MGMNSDevicePath] MD5]]] autorelease];
|
||||||
|
[manager removeItemAtPath:[[MGMCachePath stringByExpandingTildeInPath] stringByAppendingPathComponent:[[[theNotification userInfo] objectForKey:MGMNSDevicePath] MD5]]];
|
||||||
|
} else {
|
||||||
|
icon = [[NSWorkspace sharedWorkspace] iconForFile:[[theNotification userInfo] objectForKey:MGMNSDevicePath]];
|
||||||
|
[[icon TIFFRepresentation] writeToFile:[[MGMCachePath stringByExpandingTildeInPath] stringByAppendingPathComponent:[[[theNotification userInfo] objectForKey:MGMNSDevicePath] MD5]] atomically:NO];
|
||||||
|
}
|
||||||
|
[[MGMController sharedController] startNotificationWithInfo:[NSDictionary dictionaryWithObjectsAndKeys:@"didunmountvolume", MGMNName, @"Volume Unmounted", MGMNTitle, [[theNotification userInfo] objectForKey:MGMNSWorkspaceVolumeLocalizedNameKey], MGMNDescription, icon, MGMNIcon, nil]];
|
||||||
|
}
|
||||||
|
@end
|
14
Classes/main.m
Normal file
14
Classes/main.m
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
//
|
||||||
|
// main.m
|
||||||
|
// SoundNote
|
||||||
|
//
|
||||||
|
// Created by Mr. Gecko on 7/4/10.
|
||||||
|
// Copyright (c) 2011 Mr. Gecko's Media (James Coleman). All rights reserved. http://mrgeckosmedia.com/
|
||||||
|
//
|
||||||
|
|
||||||
|
#import <Cocoa/Cocoa.h>
|
||||||
|
|
||||||
|
int main(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
return NSApplicationMain(argc, (const char **) argv);
|
||||||
|
}
|
7
Classes/prefix.pch
Normal file
7
Classes/prefix.pch
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
//
|
||||||
|
// Prefix header for all source files of the 'SoundNote' target in the 'SoundNote' project
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifdef __OBJC__
|
||||||
|
#import <Cocoa/Cocoa.h>
|
||||||
|
#endif
|
1
Frameworks/EyeTunes.framework/EyeTunes
Symbolic link
1
Frameworks/EyeTunes.framework/EyeTunes
Symbolic link
@ -0,0 +1 @@
|
|||||||
|
Versions/Current/EyeTunes
|
1
Frameworks/EyeTunes.framework/Headers
Symbolic link
1
Frameworks/EyeTunes.framework/Headers
Symbolic link
@ -0,0 +1 @@
|
|||||||
|
Versions/Current/Headers
|
1
Frameworks/EyeTunes.framework/Resources
Symbolic link
1
Frameworks/EyeTunes.framework/Resources
Symbolic link
@ -0,0 +1 @@
|
|||||||
|
Versions/Current/Resources
|
BIN
Frameworks/EyeTunes.framework/Versions/A/EyeTunes
Executable file
BIN
Frameworks/EyeTunes.framework/Versions/A/EyeTunes
Executable file
Binary file not shown.
@ -0,0 +1,127 @@
|
|||||||
|
/* ETAppleEventObject.h -- Proxy Object For AppleEvent iTunes Objects
|
||||||
|
forwards parameter/element requests through
|
||||||
|
AppleEvent transparently */
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
EyeTunes.framework - Cocoa iTunes Interface
|
||||||
|
http://www.liquidx.net/eyetunes/
|
||||||
|
|
||||||
|
Copyright (c) 2005-2007, Alastair Tse <alastair@liquidx.net>
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
|
Redistributions of source code must retain the above copyright notice, this
|
||||||
|
list of conditions and the following disclaimer.
|
||||||
|
|
||||||
|
Redistributions in binary form must reproduce the above copyright notice, this
|
||||||
|
list of conditions and the following disclaimer in the documentation and/or
|
||||||
|
other materials provided with the distribution.
|
||||||
|
|
||||||
|
Neither the Alastair Tse nor the names of its contributors may
|
||||||
|
be used to endorse or promote products derived from this software without
|
||||||
|
specific prior written permission.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
|
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||||
|
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
|
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||||
|
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
|
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||||
|
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||||
|
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Important URLs:
|
||||||
|
// http://developer.apple.com/documentation/mac/IAC/IAC-230.html
|
||||||
|
|
||||||
|
#import "EyeTunesEventCodes.h"
|
||||||
|
|
||||||
|
#define ET_APPLE_EVENT_OBJECT_DEFAULT_APPL 'hook'
|
||||||
|
|
||||||
|
@interface ETAppleEventObject : NSObject {
|
||||||
|
AEDesc *refDescriptor;
|
||||||
|
OSType targetApplCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (id) initWithDescriptor:(AEDesc *)aDesc applCode:(OSType)applCode;
|
||||||
|
- (AEDesc *)descriptor;
|
||||||
|
|
||||||
|
|
||||||
|
+ (AliasHandle)newAliasHandleWithPath:(NSString *)path;
|
||||||
|
|
||||||
|
// AEGizmo String Generation
|
||||||
|
- (NSString *) stringForOSType: (DescType) descType;
|
||||||
|
- (NSString *) eventParameterStringForCountElementsOfClass:(DescType)classType;
|
||||||
|
- (NSString *) eventParameterStringForElementOfClass:(DescType)classType atIndex:(int)index;
|
||||||
|
- (NSString *) eventParameterStringForProperty:(DescType)descType;
|
||||||
|
- (NSString *) eventParameterStringForSettingProperty:(DescType)descType;
|
||||||
|
- (NSString *) eventParameterStringForSettingProperty:(DescType)propertyType OfElementOfClass:(DescType)classType atIndex:(int)index;
|
||||||
|
- (NSString *) eventParameterStringForTestObject:(DescType)objectType
|
||||||
|
forProperty:(DescType)propertyType
|
||||||
|
forIntValue:(int)value;
|
||||||
|
- (NSString *) eventParameterStringForTestObject:(DescType)objectType
|
||||||
|
forProperty:(DescType)propertyType
|
||||||
|
forStringValue:(NSString *)value;
|
||||||
|
- (NSString *) eventParameterStringForTestObject:(DescType)objectType
|
||||||
|
forProperty:(DescType)propertyType;
|
||||||
|
|
||||||
|
- (NSString *) eventParameterStringForSearchingType:(DescType)objectType withTest:(NSString *)testString;
|
||||||
|
|
||||||
|
// Get/Set Object "Properties"
|
||||||
|
- (AppleEvent *) getPropertyOfType:(DescType)descType forObject:(AEDesc *)targetObject;
|
||||||
|
- (AppleEvent *) getPropertyOfType:(DescType)descType;
|
||||||
|
- (BOOL) setPropertyWithValue:(AEDesc *)valueDesc ofType:(DescType)descType forObject:(AEDesc *)targetObject;
|
||||||
|
- (BOOL) setPropertyWithValue:(AEDesc *)valueDesc ofType:(DescType)descType;
|
||||||
|
|
||||||
|
// Count/Get/Set Object "Elements"
|
||||||
|
- (int) getCountOfElementsOfClass:(DescType)descType;
|
||||||
|
- (AppleEvent *) getElementOfClass:(DescType)classType atIndex:(int)index;
|
||||||
|
- (AppleEvent *) deleteAllElementsOfClass:(DescType)descType;
|
||||||
|
- (AppleEvent *) getElementOfClass:(DescType)classType
|
||||||
|
byKey:(DescType)key
|
||||||
|
withIntValue:(int)value;
|
||||||
|
- (AppleEvent *) getElementOfClass:(DescType)classType
|
||||||
|
byKey:(DescType)key
|
||||||
|
withLongIntValue:(long long int)value;
|
||||||
|
- (AppleEvent *) getElementOfClass:(DescType)classType
|
||||||
|
byKey:(DescType)key
|
||||||
|
withStringValue:(NSString *)value;
|
||||||
|
|
||||||
|
// not working yet
|
||||||
|
- (AppleEvent *) deleteElement:(int)index OfClass:(DescType)descType;
|
||||||
|
- (BOOL) setElementOfClass:(DescType)classType atIndex:(int)index withValue:(AEDesc *)value;
|
||||||
|
- (BOOL) setProperty:(DescType)propertyType OfElementOfClass:(DescType)classType atIndex:(int)index withValue:(AEDesc *)value;
|
||||||
|
|
||||||
|
// Get/Set Properties directly
|
||||||
|
- (DescType) getPropertyAsEnumForDesc:(DescType)descType;
|
||||||
|
- (int) getPropertyAsIntegerForDesc:(DescType)descType;
|
||||||
|
- (long long int) getPropertyAsLongIntegerForDesc:(DescType)descType;
|
||||||
|
- (NSString *) getPropertyAsStringForDesc:(DescType)descType;
|
||||||
|
- (NSDate *) getPropertyAsDateForDesc:(DescType)descType;
|
||||||
|
- (NSString *) getPropertyAsPathForDesc:(DescType)descType;
|
||||||
|
- (NSString *) getPropertyAsPathURLForDesc:(DescType)descType;
|
||||||
|
- (NSString *) getPropertyAsVersionForDesc:(DescType)descType;
|
||||||
|
|
||||||
|
- (BOOL) setPropertyWithInteger:(int)value forDesc:(DescType)descType;
|
||||||
|
- (BOOL) setPropertyWithLongInteger:(long long int)value forDesc:(DescType)descType;
|
||||||
|
- (BOOL) setPropertyWithString:(NSString *)value forDesc:(DescType)descType;
|
||||||
|
- (BOOL) setPropertyWithDate:(NSDate *)value forDesc:(DescType)descType;
|
||||||
|
// Debug functions
|
||||||
|
#ifdef ET_DEBUG
|
||||||
|
+ (void) printDescriptor:(AEDesc *)desc;
|
||||||
|
+ (NSString *) debugHexDump:(void *)ptr ofLength:(int)len;
|
||||||
|
- (NSArray *) getPropertyAsIntegerWithDumpForDesc:(DescType)descType;
|
||||||
|
- (NSArray *) getPropertyAsStringWithDumpForDesc:(DescType)descType;
|
||||||
|
- (NSArray *) getPropertyAsDateWithDumpForDesc:(DescType)descType;
|
||||||
|
- (NSArray *) getPropertyAsPathURLWithDumpForDesc:(DescType)descType;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
@end
|
@ -0,0 +1,9 @@
|
|||||||
|
#import <Foundation/Foundation.h>
|
||||||
|
|
||||||
|
#ifdef ET_DEBUG
|
||||||
|
#define ETLog NSLog
|
||||||
|
#else
|
||||||
|
#define ETLog NullLog
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void NullLog(NSString *format, ...);
|
107
Frameworks/EyeTunes.framework/Versions/A/Headers/ETEyeTunes.h
Normal file
107
Frameworks/EyeTunes.framework/Versions/A/Headers/ETEyeTunes.h
Normal file
@ -0,0 +1,107 @@
|
|||||||
|
/* EyeTunes.h - Interface to iTunes Application */
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
EyeTunes.framework - Cocoa iTunes Interface
|
||||||
|
http://www.liquidx.net/eyetunes/
|
||||||
|
|
||||||
|
Copyright (c) 2005-2007, Alastair Tse <alastair@liquidx.net>
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
|
Redistributions of source code must retain the above copyright notice, this
|
||||||
|
list of conditions and the following disclaimer.
|
||||||
|
|
||||||
|
Redistributions in binary form must reproduce the above copyright notice, this
|
||||||
|
list of conditions and the following disclaimer in the documentation and/or
|
||||||
|
other materials provided with the distribution.
|
||||||
|
|
||||||
|
Neither the Alastair Tse nor the names of its contributors may
|
||||||
|
be used to endorse or promote products derived from this software without
|
||||||
|
specific prior written permission.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
|
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||||
|
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
|
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||||
|
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
|
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||||
|
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||||
|
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#import <Foundation/Foundation.h>
|
||||||
|
|
||||||
|
#import "ETAppleEventObject.h"
|
||||||
|
|
||||||
|
@class ETTrack, ETPlaylist;
|
||||||
|
|
||||||
|
@interface EyeTunes : ETAppleEventObject {
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (EyeTunes *) sharedInstance;
|
||||||
|
|
||||||
|
// things that return a Track object
|
||||||
|
- (NSArray *)search:(ETPlaylist *)playlist forString:(NSString *)searchString inField:(DescType)typeCode;
|
||||||
|
|
||||||
|
// get all playlists
|
||||||
|
- (int)playlistCount;
|
||||||
|
- (NSArray *)playlists;
|
||||||
|
- (NSEnumerator *)playlistEnumerator;
|
||||||
|
|
||||||
|
// search for playlist by reference
|
||||||
|
- (ETPlaylist *)playlistWithPersistentId:(long long int)persistentId;
|
||||||
|
- (ETTrack *)trackWithPersistentId:(long long int)persistentId;
|
||||||
|
- (ETTrack *)trackWithPersistentIdString:(NSString *)persistentId;
|
||||||
|
|
||||||
|
// parameters
|
||||||
|
- (ETTrack *)currentTrack;
|
||||||
|
- (ETPlaylist *)currentPlaylist;
|
||||||
|
- (ETPlaylist *)libraryPlaylist;
|
||||||
|
- (BOOL) fixedIndexing;
|
||||||
|
- (void) setFixedIndexing:(BOOL)useFixedIndexing;
|
||||||
|
- (NSArray *)selectedTracks;
|
||||||
|
|
||||||
|
// version
|
||||||
|
- (NSString *)versionString;
|
||||||
|
- (unsigned int)versionNumber;
|
||||||
|
- (BOOL) versionGreaterThan:(unsigned int)version;
|
||||||
|
- (BOOL) versionLessThan:(unsigned int)version;
|
||||||
|
|
||||||
|
// state info. playerState returns kETPlayerState* in EyeTunesEventCode.h
|
||||||
|
- (int)playerPosition;
|
||||||
|
- (int)volume;
|
||||||
|
- (void)setVolume:(int)volume;
|
||||||
|
- (DescType)playerState;
|
||||||
|
|
||||||
|
// no return value
|
||||||
|
- (void)backTrack;
|
||||||
|
- (void)fastForward;
|
||||||
|
- (void)nextTrack;
|
||||||
|
- (void)pause;
|
||||||
|
- (void)play;
|
||||||
|
- (void)playTrack:(ETTrack *)track;
|
||||||
|
- (void)playTrackWithPath:(NSString *)path;
|
||||||
|
- (void)playPause;
|
||||||
|
- (void)revealPlaylist:(NSString *)playlist;
|
||||||
|
- (void)playPlaylist:(NSString *)playlist;
|
||||||
|
- (void)playTrack:(long)track ofPlaylist:(NSString *)playlist;
|
||||||
|
- (void)previousTrack;
|
||||||
|
- (void)resume;
|
||||||
|
- (void)rewind;
|
||||||
|
- (void)stop;
|
||||||
|
|
||||||
|
// TODO: - (id)addTrack:(NSURL *)fromlocation toLocation:(NSURL *)toLocation;
|
||||||
|
// TODO: - (id)convertTrack:(id)trackReference;
|
||||||
|
// TODO: - (void)refresh:(id)fileTrack;
|
||||||
|
// TODO: - (void)update:(id)iPod;
|
||||||
|
// TODO: - (void)eject:(id)iPod;
|
||||||
|
// TODO: - (void)subscribe:(NSString *)streamURL;
|
||||||
|
|
||||||
|
@end
|
@ -0,0 +1,60 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
EyeTunes.framework - Cocoa iTunes Interface
|
||||||
|
http://www.liquidx.net/eyetunes/
|
||||||
|
|
||||||
|
Copyright (c) 2005-2007, Alastair Tse <alastair@liquidx.net>
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
|
Redistributions of source code must retain the above copyright notice, this
|
||||||
|
list of conditions and the following disclaimer.
|
||||||
|
|
||||||
|
Redistributions in binary form must reproduce the above copyright notice, this
|
||||||
|
list of conditions and the following disclaimer in the documentation and/or
|
||||||
|
other materials provided with the distribution.
|
||||||
|
|
||||||
|
Neither the Alastair Tse nor the names of its contributors may
|
||||||
|
be used to endorse or promote products derived from this software without
|
||||||
|
specific prior written permission.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
|
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||||
|
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
|
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||||
|
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
|
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||||
|
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||||
|
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#import "EyeTunesEventCodes.h"
|
||||||
|
#import "ETAppleEventObject.h"
|
||||||
|
|
||||||
|
@class ETTrackEnumerator;
|
||||||
|
@class ETTrack;
|
||||||
|
|
||||||
|
@interface ETPlaylist : ETAppleEventObject {
|
||||||
|
}
|
||||||
|
|
||||||
|
- (id) initWithDescriptor:(AEDesc *)desc;
|
||||||
|
|
||||||
|
- (NSString *)name;
|
||||||
|
|
||||||
|
- (NSArray *)tracks;
|
||||||
|
- (int) trackCount;
|
||||||
|
- (NSEnumerator *)trackEnumerator;
|
||||||
|
- (ETTrack *)trackWithDatabaseId:(int)databaseId;
|
||||||
|
|
||||||
|
- (long long int)persistentId;
|
||||||
|
- (NSString *) persistentIdAsString;
|
||||||
|
|
||||||
|
- (ETTrack *)trackWithPersistentId:(long long int)persistentId;
|
||||||
|
- (ETTrack *)trackWithPersistentIdString:(NSString *)persistentId;
|
||||||
|
@end
|
@ -0,0 +1,43 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
EyeTunes.framework - Cocoa iTunes Interface
|
||||||
|
http://www.liquidx.net/eyetunes/
|
||||||
|
|
||||||
|
Copyright (c) 2005-2007 Alastair Tse <alastair@liquidx.net>
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
|
Redistributions of source code must retain the above copyright notice, this
|
||||||
|
list of conditions and the following disclaimer.
|
||||||
|
|
||||||
|
Redistributions in binary form must reproduce the above copyright notice, this
|
||||||
|
list of conditions and the following disclaimer in the documentation and/or
|
||||||
|
other materials provided with the distribution.
|
||||||
|
|
||||||
|
Neither the Alastair Tse nor the names of its contributors may
|
||||||
|
be used to endorse or promote products derived from this software without
|
||||||
|
specific prior written permission.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
|
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||||
|
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
|
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||||
|
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
|
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||||
|
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||||
|
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
@interface ETPlaylistEnumerator : NSEnumerator {
|
||||||
|
int count;
|
||||||
|
int seq;
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
143
Frameworks/EyeTunes.framework/Versions/A/Headers/ETTrack.h
Normal file
143
Frameworks/EyeTunes.framework/Versions/A/Headers/ETTrack.h
Normal file
@ -0,0 +1,143 @@
|
|||||||
|
/* ETTrack.h -- iTunes Track Object */
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
EyeTunes.framework - Cocoa iTunes Interface
|
||||||
|
http://www.liquidx.net/eyetunes/
|
||||||
|
|
||||||
|
Copyright (c) 2005-2007, Alastair Tse <alastair@liquidx.net>
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
|
Redistributions of source code must retain the above copyright notice, this
|
||||||
|
list of conditions and the following disclaimer.
|
||||||
|
|
||||||
|
Redistributions in binary form must reproduce the above copyright notice, this
|
||||||
|
list of conditions and the following disclaimer in the documentation and/or
|
||||||
|
other materials provided with the distribution.
|
||||||
|
|
||||||
|
Neither the Alastair Tse nor the names of its contributors may
|
||||||
|
be used to endorse or promote products derived from this software without
|
||||||
|
specific prior written permission.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
|
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||||
|
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
|
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||||
|
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
|
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||||
|
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||||
|
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#import <Foundation/Foundation.h>
|
||||||
|
#import "ETAppleEventObject.h"
|
||||||
|
|
||||||
|
@interface ETTrack : ETAppleEventObject {
|
||||||
|
}
|
||||||
|
|
||||||
|
- (id) initWithDescriptor:(AEDesc *)desc;
|
||||||
|
|
||||||
|
- (NSString *)name;
|
||||||
|
- (NSString *)album;
|
||||||
|
- (NSString *)albumArtist; // >=7.0
|
||||||
|
- (NSString *)artist;
|
||||||
|
- (int)bitrate;
|
||||||
|
- (int)bpm;
|
||||||
|
- (int)bookmark; // >=6.0.2
|
||||||
|
- (BOOL)bookmarkable; // >=6.0.2
|
||||||
|
- (NSString *)category; // >=6.0.2
|
||||||
|
- (NSString *)comment;
|
||||||
|
- (BOOL)compilation;
|
||||||
|
- (NSString *)composer;
|
||||||
|
- (NSString *)description; // >=6.0.2
|
||||||
|
- (int)databaseId;
|
||||||
|
- (NSDate *)dateAdded;
|
||||||
|
- (int)discCount;
|
||||||
|
- (int)discNumber;
|
||||||
|
- (int)duration;
|
||||||
|
- (BOOL)enabled;
|
||||||
|
- (NSString *)episodeId; // >=7.0
|
||||||
|
- (int)episodeNumber; // >=7.0
|
||||||
|
- (NSString *)eq;
|
||||||
|
- (int)finish;
|
||||||
|
- (BOOL)gapless; // >=7.0
|
||||||
|
- (NSString *)genre;
|
||||||
|
- (NSString *)grouping;
|
||||||
|
- (NSString *)kind;
|
||||||
|
- (NSString *)location;
|
||||||
|
- (NSString *)longDescription; // >=6.0.2
|
||||||
|
- (NSString *)lyrics; // >=6.0.2
|
||||||
|
- (NSDate *)modificationDate;
|
||||||
|
- (long long int)persistentId; // >=6.0
|
||||||
|
- (NSString *) persistentIdAsString; // >=6.0
|
||||||
|
- (int)playedCount;
|
||||||
|
- (NSDate *)playedDate;
|
||||||
|
- (BOOL)podcast;
|
||||||
|
- (int)rating;
|
||||||
|
- (int)sampleRate;
|
||||||
|
- (int)seasonNumber; // >=7.0
|
||||||
|
- (int)size;
|
||||||
|
- (NSString *)show; // >=7.0
|
||||||
|
- (int)skippedCount; // >=7.0
|
||||||
|
- (NSDate *)skippedDate; // >=7.0
|
||||||
|
- (int)start;
|
||||||
|
- (NSString *)time;
|
||||||
|
- (int)trackCount;
|
||||||
|
- (int)trackNumber;
|
||||||
|
- (BOOL)unplayed; // >=7.1
|
||||||
|
- (DescType)videoKind; // >=7.0
|
||||||
|
- (int)volumeAdjustment;
|
||||||
|
- (int)year;
|
||||||
|
|
||||||
|
- (void)setName:(NSString *)newValue;
|
||||||
|
- (void)setAlbum:(NSString *)newValue;
|
||||||
|
- (void)setArtist:(NSString *)newValue;
|
||||||
|
- (void)setAlbumArtist:(NSString *)newValue; // >=7.0
|
||||||
|
- (void)setBookmark:(int)newValueSeconds; // >=6.0.2
|
||||||
|
- (void)setBookmarkable:(BOOL)newValue; // >=6.0.2
|
||||||
|
- (void)setBpm:(int)newValue;
|
||||||
|
- (void)setCategory:(NSString *)newValue; // >=6.0.2
|
||||||
|
- (void)setComment:(NSString *)newValue;
|
||||||
|
- (void)setCompilation:(BOOL)newValue;
|
||||||
|
- (void)setComposer:(NSString *)newValue;
|
||||||
|
- (void)setDescription:(NSString *)newValue; // >=6.0.2
|
||||||
|
- (void)setDiscCount:(int)newValue;
|
||||||
|
- (void)setDiscNumber:(int)newValue;
|
||||||
|
- (void)setEnabled:(BOOL)newValue;
|
||||||
|
- (void)setEpisodeId:(NSString *)newValue; // >=7.0
|
||||||
|
- (void)setEpisodeNumber:(int)newValue; // >=7.0
|
||||||
|
- (void)setEq:(NSString *)newValue;
|
||||||
|
- (void)setFinish:(int)newValueSeconds;
|
||||||
|
- (void)setGapless:(BOOL)newValue; // >=7.0
|
||||||
|
- (void)setGenre:(NSString *)newValue;
|
||||||
|
- (void)setGrouping:(NSString *)newValue;
|
||||||
|
- (void)setLongDescription:(NSString *)newValue;// >=6.0.1
|
||||||
|
- (void)setLyrics:(NSString *)newValue; // >=6.0.1
|
||||||
|
- (void)setPlayedCount:(int)newValue;
|
||||||
|
- (void)setPlayedDate:(NSDate *)newValue;
|
||||||
|
- (void)setRating:(int)newValue;
|
||||||
|
- (void)setSeasonNumber:(int)newValue; // >=7.0
|
||||||
|
- (void)setSkippedCount:(int)newValue; // >=7.0
|
||||||
|
- (void)setSkippedDate:(NSDate *)newValue; // >=7.0
|
||||||
|
- (void)setStart:(int)newValue;
|
||||||
|
- (void)setTrackCount:(int)newValue;
|
||||||
|
- (void)setTrackNumber:(int)newValue;
|
||||||
|
- (void)setUnplayed:(BOOL)newValue; // >=7.1
|
||||||
|
- (void)setVideoKind:(DescType)newValue; // >=7.0
|
||||||
|
- (void)setVolumeAdjustment:(int)newValue;
|
||||||
|
|
||||||
|
- (void)setYear:(int)newValue;
|
||||||
|
|
||||||
|
- (NSArray *)artwork;
|
||||||
|
- (void)setArtwork:(NSArray *)newArtworks;
|
||||||
|
- (BOOL)setArtwork:(NSImage *)artwork atIndex:(int)index;
|
||||||
|
|
||||||
|
|
||||||
|
@end
|
@ -0,0 +1,51 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
EyeTunes.framework - Cocoa iTunes Interface
|
||||||
|
http://www.liquidx.net/eyetunes/
|
||||||
|
|
||||||
|
Copyright (c) 2005-2007 Alastair Tse <alastair@liquidx.net>
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
|
Redistributions of source code must retain the above copyright notice, this
|
||||||
|
list of conditions and the following disclaimer.
|
||||||
|
|
||||||
|
Redistributions in binary form must reproduce the above copyright notice, this
|
||||||
|
list of conditions and the following disclaimer in the documentation and/or
|
||||||
|
other materials provided with the distribution.
|
||||||
|
|
||||||
|
Neither the Alastair Tse nor the names of its contributors may
|
||||||
|
be used to endorse or promote products derived from this software without
|
||||||
|
specific prior written permission.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
|
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||||
|
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
|
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||||
|
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
|
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||||
|
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||||
|
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#import <Foundation/Foundation.h>
|
||||||
|
#import "ETDebug.h"
|
||||||
|
#import "EyeTunesEventCodes.h"
|
||||||
|
#import "ETPlaylist.h"
|
||||||
|
#import "ETTrack.h"
|
||||||
|
|
||||||
|
@interface ETTrackEnumerator : NSEnumerator {
|
||||||
|
ETPlaylist *playlist;
|
||||||
|
int count;
|
||||||
|
int seq;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (id) initWithPlaylist:(ETPlaylist *)newPlaylist;
|
||||||
|
|
||||||
|
@end
|
60
Frameworks/EyeTunes.framework/Versions/A/Headers/EyeTunes.h
Normal file
60
Frameworks/EyeTunes.framework/Versions/A/Headers/EyeTunes.h
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
/* EyeTunes.h - Interface to iTunes Application */
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
EyeTunes.framework - Cocoa iTunes Interface
|
||||||
|
http://www.liquidx.net/eyetunes/
|
||||||
|
|
||||||
|
Copyright (c) 2005-2007, Alastair Tse <alastair@liquidx.net>
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
|
Redistributions of source code must retain the above copyright notice, this
|
||||||
|
list of conditions and the following disclaimer.
|
||||||
|
|
||||||
|
Redistributions in binary form must reproduce the above copyright notice, this
|
||||||
|
list of conditions and the following disclaimer in the documentation and/or
|
||||||
|
other materials provided with the distribution.
|
||||||
|
|
||||||
|
Neither the Alastair Tse nor the names of its contributors may
|
||||||
|
be used to endorse or promote products derived from this software without
|
||||||
|
specific prior written permission.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
|
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||||
|
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
|
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||||
|
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
|
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||||
|
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||||
|
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
1.3 : Moved the actual concrete EyeTunes object implementation to ETEyeTunes.h/m
|
||||||
|
to avoid circular dependencies.
|
||||||
|
|
||||||
|
0.2 : backwards incompatible changes
|
||||||
|
* ETAppleEventObject : getCountofElementClass.. returns int rather than AppleEvent*
|
||||||
|
* ETTrack : databaseID renamed to databaseId
|
||||||
|
group renamed to grouping, type changed from int to NSString*
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#import <Foundation/Foundation.h>
|
||||||
|
#import <ApplicationServices/ApplicationServices.h>
|
||||||
|
|
||||||
|
#import "EyeTunesVersions.h"
|
||||||
|
#import "EyeTunesEventCodes.h"
|
||||||
|
|
||||||
|
#import "ETAppleEventObject.h"
|
||||||
|
#import "ETEyeTunes.h"
|
||||||
|
#import "ETTrack.h"
|
||||||
|
#import "ETPlaylist.h"
|
@ -0,0 +1,271 @@
|
|||||||
|
/* EyeTunesEventCodes.h - Extracted AppleEvent Constants that iTunes Uses */
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
EyeTunes.framework - Cocoa iTunes Interface
|
||||||
|
http://www.liquidx.net/eyetunes/
|
||||||
|
|
||||||
|
Copyright (c) 2005-2007, Alastair Tse <alastair@liquidx.net>
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
|
Redistributions of source code must retain the above copyright notice, this
|
||||||
|
list of conditions and the following disclaimer.
|
||||||
|
|
||||||
|
Redistributions in binary form must reproduce the above copyright notice, this
|
||||||
|
list of conditions and the following disclaimer in the documentation and/or
|
||||||
|
other materials provided with the distribution.
|
||||||
|
|
||||||
|
Neither the Alastair Tse nor the names of its contributors may
|
||||||
|
be used to endorse or promote products derived from this software without
|
||||||
|
specific prior written permission.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
|
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||||
|
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
|
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||||
|
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
|
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||||
|
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||||
|
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
enum {
|
||||||
|
kETPlayerStateStopped = 'kPSS',
|
||||||
|
kETPlayerStatePlaying = 'kPSP',
|
||||||
|
kETPlayerStatePaused = 'kPSp',
|
||||||
|
kETPlayerStateFastForwarding = 'kPSF',
|
||||||
|
kETPlayerStateRewinding = 'kPSR'
|
||||||
|
};
|
||||||
|
|
||||||
|
enum {
|
||||||
|
kETRepeatModeOff = 'kRp0',
|
||||||
|
kETRepeatModeOne = 'kRp1',
|
||||||
|
kETRepeatModeAll = 'kRpA'
|
||||||
|
};
|
||||||
|
|
||||||
|
enum {
|
||||||
|
kETVideoSizeSmall = 'kVSS',
|
||||||
|
kETVideoSizeMedium = 'kVSM',
|
||||||
|
kETVideoSizeLarge = 'kVSL'
|
||||||
|
};
|
||||||
|
|
||||||
|
enum {
|
||||||
|
kETSourceLibrary = 'kLib',
|
||||||
|
kETSourceiPod = 'kPod',
|
||||||
|
kETSourceAudioCD = 'kACD',
|
||||||
|
kETSourceMP3CD = 'kMCD',
|
||||||
|
kETSourceDevice = 'kDev',
|
||||||
|
kETSourceRadioTuner = 'kTun',
|
||||||
|
kETSourceSharedLibrary = 'kShd',
|
||||||
|
kETSourceUnknown = 'kUnk'
|
||||||
|
};
|
||||||
|
|
||||||
|
enum {
|
||||||
|
kETSearchAttributeAlbums = 'kSrL',
|
||||||
|
kETSearchAttributeAll = 'kSrA',
|
||||||
|
kETSearchAttributeArtist = 'kSrR',
|
||||||
|
kETSearchAttributeComposers = 'kSrC',
|
||||||
|
kETSearchAttributeDisplayed = 'kSrV',
|
||||||
|
kETSearchAttributeSongs = 'kSrs'
|
||||||
|
};
|
||||||
|
|
||||||
|
#if ITUNES_VERSION < ITUNES_6_0
|
||||||
|
enum {
|
||||||
|
kETSpecialPlaylistNone = 'kSpN',
|
||||||
|
kETSpecialPlaylistPartyShuffle = 'kSpS',
|
||||||
|
kETSpecialPlaylistPodcasts = 'kSpP',
|
||||||
|
kETSpecialPlaylistPurchasedMusic = 'kSpM',
|
||||||
|
};
|
||||||
|
#else
|
||||||
|
enum {
|
||||||
|
kETSpecialPlaylistNone = 'kSpN',
|
||||||
|
kETSpecialPlaylistFolder = 'kSpF',
|
||||||
|
kETSpecialPlaylistPartyShuffle = 'kSpS',
|
||||||
|
kETSpecialPlaylistPodcasts = 'kSpP',
|
||||||
|
kETSpecialPlaylistPurchasedMusic = 'kSpM',
|
||||||
|
kETSpecialPlaylistVideo = 'kSpV',
|
||||||
|
#if ITUNES_VERSION >= ITUNES_7_0
|
||||||
|
kETSpecialPlaylistAudiobooks = 'kSpA',
|
||||||
|
kETSpecialPlaylistMovies = 'kSpI',
|
||||||
|
kETSpecialPlaylistMusic = 'kSpZ',
|
||||||
|
kETSpecialPlaylistTVShows = 'kSpT',
|
||||||
|
#endif
|
||||||
|
}; // ET_PLAYLIST_SPECIAL_KIND (eSpK)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if ITUNES_VERSION >= ITUNES_7_0
|
||||||
|
enum {
|
||||||
|
kETVideoKindUnknown = 'kVdN',
|
||||||
|
kETVideoKindMovie = 'kVdM',
|
||||||
|
kETVideoKindMusicVideo = 'kVdV',
|
||||||
|
kETVideoKindTVShow = 'kVdT',
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
enum {
|
||||||
|
pETTrackLocation = 'pLoc'
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// --- itunes commmands start ---
|
||||||
|
#define ET_ADD_FILE 'Add '
|
||||||
|
#define ET_BACK_TRACK 'Back'
|
||||||
|
#define ET_CONVERT 'Conv'
|
||||||
|
#define ET_FAST_FORWARD 'Fast'
|
||||||
|
#define ET_NEXT_TRACK 'Next'
|
||||||
|
#define ET_PAUSE 'Paus'
|
||||||
|
#define ET_PLAY 'Play'
|
||||||
|
#define ET_PLAYPAUSE 'PlPs'
|
||||||
|
#define ET_PREVIOUS_TRACK 'Prev'
|
||||||
|
#define ET_REFRESH 'Rfrs'
|
||||||
|
#define ET_RESUME 'Resu'
|
||||||
|
#define ET_REWIND 'Rwnd'
|
||||||
|
#define ET_SEARCH 'Srch'
|
||||||
|
#define ET_STOP 'Stop'
|
||||||
|
#define ET_UPDATE 'Updt'
|
||||||
|
#define ET_EJECT 'Ejct'
|
||||||
|
#define ET_SUBSCRIBE 'pSub'
|
||||||
|
#if ITUNES_VERSION >= ITUNES_7_2
|
||||||
|
#define ET_REVEAL_SELECT 'Revl'
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if ITUNES_VERSION >= ITUNES_6_0
|
||||||
|
#define ET_UPDATE_ALL_PODCASTS 'Updp'
|
||||||
|
#define ET_UPDATE_ONE_PODCAST 'Upd1'
|
||||||
|
#define ET_DOWNLOAD_PODCAST 'Dwnl'
|
||||||
|
#endif
|
||||||
|
// --- itunes commmands end ---
|
||||||
|
|
||||||
|
|
||||||
|
// --- itunes application parameters start ---
|
||||||
|
#define ET_CLASS_LIBRARY_PLAYLIST 'cLiP'
|
||||||
|
#define ET_APP_ENCODER 'pEnc'
|
||||||
|
#define ET_APP_EQ_PRESET 'pEQP'
|
||||||
|
#define ET_APP_CURRENT_PLAYLIST 'pPla'
|
||||||
|
#define ET_APP_CURRENT_STREAM_TITLE 'pStT'
|
||||||
|
#define ET_APP_CURRENT_STREAM_URL 'pStU'
|
||||||
|
#define ET_APP_CURRENT_TRACK 'pTrk'
|
||||||
|
#define ET_APP_CURRENT_VISUAL 'pVis'
|
||||||
|
#define ET_APP_FIXED_INDEXING 'pFix'
|
||||||
|
#define ET_APP_PLAYER_POSITION 'pPos'
|
||||||
|
#define ET_APP_PLAYER_VOLUME 'pVol'
|
||||||
|
#define ET_APP_PLAYER_STATE 'pPlS'
|
||||||
|
#define ET_APP_SELECTION 'sele'
|
||||||
|
#define ET_APP_VERSION 'vers'
|
||||||
|
// --- itunes application parameters end ---
|
||||||
|
|
||||||
|
// --- track artwork start ---
|
||||||
|
#define ET_CLASS_ARTWORK 'cArt'
|
||||||
|
#define ET_ARTWORK_PROP_FORMAT 'pFmt' // type (r)
|
||||||
|
#define ET_ARTWORK_PROP_DATA 'pPCT' // PICT (rw)
|
||||||
|
#define ET_ARTWORK_PROP_KIND 'pKnd' // integer (rw)
|
||||||
|
#if ITUNES_VERSION >= ITUNES_7_0
|
||||||
|
#define ET_ARTWORK_PROP_DOWNLOAD_FROM_ITMS 'pDlA' // bool
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// --- track artwork end ---
|
||||||
|
|
||||||
|
// --- generic applescript item codes start ---
|
||||||
|
#define ET_CLASS_ITEM 'cobj'
|
||||||
|
#define ET_ITEM_PROP_CONTAINER 'cntr' // object (r)
|
||||||
|
#define ET_ITEM_PROP_NAME 'pnam' // utxt (rw)
|
||||||
|
#if ITUNES_VERSION >= ITUNES_6_0_1
|
||||||
|
#define ET_ITEM_PROP_PERSISTENT_ID 'pPID' // double int (r)
|
||||||
|
#endif
|
||||||
|
// --- generic applescript item codes end ---
|
||||||
|
|
||||||
|
// --- itunes track parameters start ---
|
||||||
|
#define ET_CLASS_TRACK 'cTrk'
|
||||||
|
#define ET_TRACK_PROP_ALBUM 'pAlb' // utxt
|
||||||
|
#define ET_TRACK_PROP_ARTIST 'pArt' // utxt
|
||||||
|
#define ET_TRACK_PROP_BITRATE 'pBRt' // integer
|
||||||
|
#define ET_TRACK_PROP_BPM 'pBPM' // integer
|
||||||
|
#define ET_TRACK_PROP_COMMENT 'pCmt' // utxt
|
||||||
|
#define ET_TRACK_PROP_COMPILATION 'pAnt' // bool
|
||||||
|
#define ET_TRACK_PROP_COMPOSER 'pCmp' // utxt
|
||||||
|
#define ET_TRACK_PROP_DATABASE_ID 'pDID' // integer
|
||||||
|
#define ET_TRACK_PROP_DATE_ADDED 'pAdd' // ldt
|
||||||
|
#define ET_TRACK_PROP_DISC_COUNT 'pDsC' // integer
|
||||||
|
#define ET_TRACK_PROP_DISC_NUMBER 'pDsN' // integer
|
||||||
|
#define ET_TRACK_PROP_DURATION 'pDur' // integer
|
||||||
|
#define ET_TRACK_PROP_ENABLED 'enbl' // bool
|
||||||
|
#define ET_TRACK_PROP_EQ 'pEQp' // utxt
|
||||||
|
#define ET_TRACK_PROP_FINISH 'pStp' // integer
|
||||||
|
#define ET_TRACK_PROP_GENRE 'pGen' // utxt
|
||||||
|
#define ET_TRACK_PROP_GROUPING 'pGrp' // utxt
|
||||||
|
#define ET_TRACK_PROP_KIND 'pKnd' // utxt
|
||||||
|
#define ET_TRACK_PROP_MOD_DATE 'asmo' // ldt
|
||||||
|
#define ET_TRACK_PROP_PLAYED_COUNT 'pPlC' // integer
|
||||||
|
#define ET_TRACK_PROP_PLAYED_DATE 'pPlD' // ldt
|
||||||
|
#define ET_TRACK_PROP_PODCAST 'pTPc' // bool
|
||||||
|
#define ET_TRACK_PROP_RATING 'pRte' // integer
|
||||||
|
#define ET_TRACK_PROP_SAMPLE_RATE 'pSRt' // integer
|
||||||
|
#define ET_TRACK_PROP_SIZE 'pSiz' // integer
|
||||||
|
#define ET_TRACK_PROP_START 'pStr' // integer
|
||||||
|
#define ET_TRACK_PROP_TIME 'pTim' // utxt
|
||||||
|
#define ET_TRACK_PROP_TRACK_COUNT 'pTrC' // integer
|
||||||
|
#define ET_TRACK_PROP_TRACK_NUMBER 'pTrN' // integer
|
||||||
|
#define ET_TRACK_PROP_VOLUME_ADJ 'pAdj' // integer
|
||||||
|
#define ET_TRACK_PROP_YEAR 'pYr ' // integer
|
||||||
|
|
||||||
|
#if ITUNES_VERSION >= ITUNES_6_0_2
|
||||||
|
#define ET_TRACK_PROP_BOOKMARK 'pBkt' // integer
|
||||||
|
#define ET_TRACK_PROP_BOOKMARKABLE 'pBkm' // boolean
|
||||||
|
#define ET_TRACK_PROP_CATEGORY 'pCat' // utxt
|
||||||
|
#define ET_TRACK_PROP_DESCRIPTION 'pDes' // utxt
|
||||||
|
#define ET_TRACK_PROP_LONG_DESCRIPTION 'pLds' // utxt
|
||||||
|
#define ET_TRACK_PROP_LYRICS 'pLyr' // utxt
|
||||||
|
#define ET_TRACK_PROP_SHUFFABLE 'pSfa' // bool
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if ITUNES_VERSION >= ITUNES_7_0
|
||||||
|
#define ET_TRACK_PROP_ALBUM_ARTIST 'pAlA' // utxt
|
||||||
|
#define ET_TRACK_PROP_EPISODE_ID 'pEpD' // utxt
|
||||||
|
#define ET_TRACK_PROP_EPISODE_NUMBER 'pEpN' // integer
|
||||||
|
#define ET_TRACK_PROP_GAPLESS 'pGpl' // bool
|
||||||
|
#define ET_TRACK_PROP_SEASON_NUMBER 'pSeN' // integer
|
||||||
|
#define ET_TRACK_PROP_SKIPPED_COUNT 'pSkC' // integer
|
||||||
|
#define ET_TRACK_PROP_SKIPPED_DATE 'pSkD' // ldt
|
||||||
|
#define ET_TRACK_PROP_SHOW 'pShw' // utxt
|
||||||
|
#define ET_TRACK_PROP_VIDEO_KIND 'pVdk' // enum (see: video kind)
|
||||||
|
#endif
|
||||||
|
#if ITUNES_VERSION >= ITUNES_7_1
|
||||||
|
#define ET_TRACK_PROP_SORT_ALBUM 'pSAl' // utxt
|
||||||
|
#define ET_TRACK_PROP_SORT_ARTIST 'pSAr' // utxt
|
||||||
|
#define ET_TRACK_PROP_SORT_NAME 'pSNm' // utxt
|
||||||
|
#define ET_TRACK_PROP_SORT_COMPOSER 'pSNm' // utxt
|
||||||
|
#define ET_TRACK_PROP_SORT_SHOW 'pSSN' // utxt
|
||||||
|
#define ET_TRACK_PROP_UNPLAYED 'pUnp' // bool
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// --- itunes track parameters end ---
|
||||||
|
|
||||||
|
// --- other track classes start ---
|
||||||
|
#define ET_CLASS_FILE_TRACK 'cFlT'
|
||||||
|
#define ET_CLASS_URL_TRACK 'cURT'
|
||||||
|
#define ET_CLASS_CD_TRACK 'cCDT'
|
||||||
|
#define ET_FILE_TRACK_PROP_LOCATION 'pLoc' // alis
|
||||||
|
#define ET_URL_TRACK_PROP_ADDRESS 'pURL' // utxt
|
||||||
|
#define ET_CD_TRACK_PROP_LOCATION 'pLoc' // alis
|
||||||
|
// --- other track classes end ---
|
||||||
|
|
||||||
|
// generic playlist properies ---
|
||||||
|
#define ET_CLASS_PLAYLIST 'cPly'
|
||||||
|
#define ET_PLAYLIST_PROP_DURATION 'pDur' // integer (r)
|
||||||
|
#define ET_PLAYLIST_PROP_INTERNAL_INDEX 'pidx' // integer (r)
|
||||||
|
#define ET_PLAYLIST_PROP_SHUFFLE 'pShf' // bool (rw)
|
||||||
|
#define ET_PLAYLIST_PROP_SIZE 'pSiz' // longlong (double int) (r)
|
||||||
|
#define ET_PLAYLIST_PROP_REPEAT 'pRpt' // eRpt? (rw)
|
||||||
|
#define ET_PLAYLIST_PROP_SPECIAL_KIND 'pSpK' // eSpk? (r)
|
||||||
|
#define ET_PLAYLIST_PROP_TIME 'pTim' // utxt (r)
|
||||||
|
#define ET_PLAYLIST_PROP_VISIBLE 'pvis' // bool (r)
|
||||||
|
// generic playlist properies ---
|
||||||
|
|
||||||
|
|
@ -0,0 +1,15 @@
|
|||||||
|
/* Useful version constants for iTunes version checking. */
|
||||||
|
|
||||||
|
// guard against exporting features that are not in earlier versions
|
||||||
|
#define ITUNES_7_3 0x0730
|
||||||
|
#define ITUNES_7_2 0x0720
|
||||||
|
#define ITUNES_7_1 0x0710
|
||||||
|
#define ITUNES_7_0_1 0x0701
|
||||||
|
#define ITUNES_6_0_2 0x0602
|
||||||
|
#define ITUNES_6_0_1 0x0601
|
||||||
|
#define ITUNES_6_0 0x0600
|
||||||
|
#define ITUNES_4_0 0x0400
|
||||||
|
|
||||||
|
// Enable all features by default.
|
||||||
|
#define ITUNES_VERSION 0xffff
|
||||||
|
|
@ -0,0 +1,44 @@
|
|||||||
|
/* EyeTunesEventCodes.h - Extracted AppleEvent Constants that iTunes Uses */
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
EyeTunes.framework - Cocoa iTunes Interface
|
||||||
|
http://www.liquidx.net/eyetunes/
|
||||||
|
|
||||||
|
Copyright (c) 2007, Alastair Tse <alastair@liquidx.net>
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
|
Redistributions of source code must retain the above copyright notice, this
|
||||||
|
list of conditions and the following disclaimer.
|
||||||
|
|
||||||
|
Redistributions in binary form must reproduce the above copyright notice, this
|
||||||
|
list of conditions and the following disclaimer in the documentation and/or
|
||||||
|
other materials provided with the distribution.
|
||||||
|
|
||||||
|
Neither the Alastair Tse nor the names of its contributors may
|
||||||
|
be used to endorse or promote products derived from this software without
|
||||||
|
specific prior written permission.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
|
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||||
|
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
|
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||||
|
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
|
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||||
|
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||||
|
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#import <Cocoa/Cocoa.h>
|
||||||
|
|
||||||
|
|
||||||
|
@interface NSString (LongLongValue)
|
||||||
|
- (long long int)longlongValue;
|
||||||
|
@end
|
Binary file not shown.
@ -0,0 +1,24 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
|
<plist version="1.0">
|
||||||
|
<dict>
|
||||||
|
<key>CFBundleDevelopmentRegion</key>
|
||||||
|
<string>English</string>
|
||||||
|
<key>CFBundleExecutable</key>
|
||||||
|
<string>EyeTunesDebug</string>
|
||||||
|
<key>CFBundleIdentifier</key>
|
||||||
|
<string>net.liquidx.EyeTunesDebug</string>
|
||||||
|
<key>CFBundleInfoDictionaryVersion</key>
|
||||||
|
<string>6.0</string>
|
||||||
|
<key>CFBundlePackageType</key>
|
||||||
|
<string>APPL</string>
|
||||||
|
<key>CFBundleSignature</key>
|
||||||
|
<string>????</string>
|
||||||
|
<key>CFBundleVersion</key>
|
||||||
|
<string>1.0</string>
|
||||||
|
<key>NSMainNibFile</key>
|
||||||
|
<string>MainMenu</string>
|
||||||
|
<key>NSPrincipalClass</key>
|
||||||
|
<string>NSApplication</string>
|
||||||
|
</dict>
|
||||||
|
</plist>
|
@ -0,0 +1,36 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
|
<plist version="1.0">
|
||||||
|
<dict>
|
||||||
|
<key>BuildMachineOSBuild</key>
|
||||||
|
<string>10J567</string>
|
||||||
|
<key>CFBundleDevelopmentRegion</key>
|
||||||
|
<string>English</string>
|
||||||
|
<key>CFBundleExecutable</key>
|
||||||
|
<string>EyeTunes</string>
|
||||||
|
<key>CFBundleIdentifier</key>
|
||||||
|
<string>net.liquidx.EyeTunes</string>
|
||||||
|
<key>CFBundleInfoDictionaryVersion</key>
|
||||||
|
<string>6.0</string>
|
||||||
|
<key>CFBundlePackageType</key>
|
||||||
|
<string>FMWK</string>
|
||||||
|
<key>CFBundleSignature</key>
|
||||||
|
<string>????</string>
|
||||||
|
<key>CFBundleVersion</key>
|
||||||
|
<string>1.2</string>
|
||||||
|
<key>DTCompiler</key>
|
||||||
|
<string>4.2</string>
|
||||||
|
<key>DTPlatformBuild</key>
|
||||||
|
<string>4A278b</string>
|
||||||
|
<key>DTPlatformVersion</key>
|
||||||
|
<string>GM</string>
|
||||||
|
<key>DTSDKBuild</key>
|
||||||
|
<string>4A278b</string>
|
||||||
|
<key>DTSDKName</key>
|
||||||
|
<string>macosx10.6</string>
|
||||||
|
<key>DTXcode</key>
|
||||||
|
<string>0400</string>
|
||||||
|
<key>DTXcodeBuild</key>
|
||||||
|
<string>4A278b</string>
|
||||||
|
</dict>
|
||||||
|
</plist>
|
1
Frameworks/EyeTunes.framework/Versions/Current
Symbolic link
1
Frameworks/EyeTunes.framework/Versions/Current
Symbolic link
@ -0,0 +1 @@
|
|||||||
|
A
|
1
Frameworks/GeckoReporter.framework/GeckoReporter
Symbolic link
1
Frameworks/GeckoReporter.framework/GeckoReporter
Symbolic link
@ -0,0 +1 @@
|
|||||||
|
Versions/Current/GeckoReporter
|
1
Frameworks/GeckoReporter.framework/Headers
Symbolic link
1
Frameworks/GeckoReporter.framework/Headers
Symbolic link
@ -0,0 +1 @@
|
|||||||
|
Versions/Current/Headers
|
1
Frameworks/GeckoReporter.framework/Resources
Symbolic link
1
Frameworks/GeckoReporter.framework/Resources
Symbolic link
@ -0,0 +1 @@
|
|||||||
|
Versions/Current/Resources
|
BIN
Frameworks/GeckoReporter.framework/Versions/A/GeckoReporter
Executable file
BIN
Frameworks/GeckoReporter.framework/Versions/A/GeckoReporter
Executable file
Binary file not shown.
@ -0,0 +1,12 @@
|
|||||||
|
//
|
||||||
|
// GeckoReporter.h
|
||||||
|
// GeckoReporter
|
||||||
|
//
|
||||||
|
// Created by Mr. Gecko on 12/27/09.
|
||||||
|
// Copyright (c) 2011 Mr. Gecko's Media (James Coleman). All rights reserved. http://mrgeckosmedia.com/
|
||||||
|
//
|
||||||
|
|
||||||
|
#import "MGMReporter.h"
|
||||||
|
#import "MGMSender.h"
|
||||||
|
#import "MGMSystemInfo.h"
|
||||||
|
#import "MGMLog.h"
|
@ -0,0 +1,16 @@
|
|||||||
|
//
|
||||||
|
// MGMFeedback.h
|
||||||
|
// GeckoReporter
|
||||||
|
//
|
||||||
|
// Created by Mr. Gecko on 1/2/10.
|
||||||
|
// Copyright (c) 2011 Mr. Gecko's Media (James Coleman). All rights reserved. http://mrgeckosmedia.com/
|
||||||
|
//
|
||||||
|
|
||||||
|
#import <Cocoa/Cocoa.h>
|
||||||
|
|
||||||
|
@interface MGMFeedback : NSObject {
|
||||||
|
|
||||||
|
}
|
||||||
|
- (IBAction)openBugReport:(id)sender;
|
||||||
|
- (IBAction)openContact:(id)sender;
|
||||||
|
@end
|
@ -0,0 +1,12 @@
|
|||||||
|
//
|
||||||
|
// MGMLog.h
|
||||||
|
// GeckoReporter
|
||||||
|
//
|
||||||
|
// Created by Mr. Gecko on 1/1/10.
|
||||||
|
// Copyright (c) 2011 Mr. Gecko's Media (James Coleman). All rights reserved. http://mrgeckosmedia.com/
|
||||||
|
//
|
||||||
|
|
||||||
|
#import <Cocoa/Cocoa.h>
|
||||||
|
|
||||||
|
void MGMLog(NSString *format, ...);
|
||||||
|
void MGMLogv(NSString *format, va_list args);
|
@ -0,0 +1,28 @@
|
|||||||
|
//
|
||||||
|
// MGMReporter.h
|
||||||
|
// GeckoReporter
|
||||||
|
//
|
||||||
|
// Created by Mr. Gecko on 12/27/09.
|
||||||
|
// Copyright (c) 2011 Mr. Gecko's Media (James Coleman). All rights reserved. http://mrgeckosmedia.com/
|
||||||
|
//
|
||||||
|
|
||||||
|
#import <Cocoa/Cocoa.h>
|
||||||
|
|
||||||
|
extern NSString * const MGMGRDoneNotification;
|
||||||
|
extern NSString * const MGMGRUserEmail;
|
||||||
|
extern NSString * const MGMGRUserName;
|
||||||
|
extern NSString * const MGMGRLastCrashDate;
|
||||||
|
extern NSString * const MGMGRSendAll;
|
||||||
|
extern NSString * const MGMGRIgnoreAll;
|
||||||
|
|
||||||
|
#define MGMGRReleaseDebug 0
|
||||||
|
|
||||||
|
@class MGMSender;
|
||||||
|
|
||||||
|
@interface MGMReporter : NSObject {
|
||||||
|
BOOL foundReport;
|
||||||
|
NSDate *lastDate;
|
||||||
|
MGMSender *mailSender;
|
||||||
|
}
|
||||||
|
+ (id)sharedReporter;
|
||||||
|
@end
|
@ -0,0 +1,20 @@
|
|||||||
|
//
|
||||||
|
// MGMSender.h
|
||||||
|
// GeckoReporter
|
||||||
|
//
|
||||||
|
// Created by Mr. Gecko on 12/28/09.
|
||||||
|
// Copyright (c) 2011 Mr. Gecko's Media (James Coleman). All rights reserved. http://mrgeckosmedia.com/
|
||||||
|
//
|
||||||
|
|
||||||
|
#import <Cocoa/Cocoa.h>
|
||||||
|
#import "MGMSenderDelegate.h"
|
||||||
|
|
||||||
|
@interface MGMSender : NSObject {
|
||||||
|
id<MGMSenderDelegate> delegate;
|
||||||
|
NSMutableData *receivedData;
|
||||||
|
NSURLConnection *theConnection;
|
||||||
|
}
|
||||||
|
- (void)sendReport:(NSString *)theReportPath reportDate:(NSDate *)theReportDate userReport:(NSString *)theUserReport delegate:(id)theDelegate;
|
||||||
|
- (void)sendBug:(NSString *)theBug reproduce:(NSString *)theReproduce delegate:(id)theDelegate;
|
||||||
|
- (void)sendMessage:(NSString *)theMessage subject:(NSString *)theSubject delegate:(id)theDelegate;
|
||||||
|
@end
|
@ -0,0 +1,15 @@
|
|||||||
|
//
|
||||||
|
// MGMSenderDelegate.h
|
||||||
|
// GeckoReporter
|
||||||
|
//
|
||||||
|
// Created by Mr. Gecko on 1/2/10.
|
||||||
|
// Copyright (c) 2011 Mr. Gecko's Media (James Coleman). All rights reserved. http://mrgeckosmedia.com/
|
||||||
|
//
|
||||||
|
|
||||||
|
#import <Cocoa/Cocoa.h>
|
||||||
|
|
||||||
|
|
||||||
|
@protocol MGMSenderDelegate <NSObject>
|
||||||
|
- (void)sendError:(NSError *)error;
|
||||||
|
- (void)sendFinished:(NSString *)received;
|
||||||
|
@end
|
@ -0,0 +1,46 @@
|
|||||||
|
//
|
||||||
|
// MGMSystemInfo.h
|
||||||
|
// GeckoReporter
|
||||||
|
//
|
||||||
|
// Created by Mr. Gecko on 12/31/09.
|
||||||
|
// Copyright (c) 2011 Mr. Gecko's Media (James Coleman). All rights reserved. http://mrgeckosmedia.com/
|
||||||
|
//
|
||||||
|
|
||||||
|
#import <Cocoa/Cocoa.h>
|
||||||
|
|
||||||
|
|
||||||
|
@interface MGMSystemInfo : NSObject {
|
||||||
|
|
||||||
|
}
|
||||||
|
+ (MGMSystemInfo *)info;
|
||||||
|
- (NSString *)architecture;
|
||||||
|
- (BOOL)is64Bit;
|
||||||
|
- (NSString *)CPUFamily;
|
||||||
|
- (int)CPUCount;
|
||||||
|
- (NSString *)model;
|
||||||
|
- (NSString *)modelName;
|
||||||
|
- (int)CPUMHz;
|
||||||
|
- (int)RAMSize;
|
||||||
|
- (int)OSMajorVersion;
|
||||||
|
- (int)OSMinorVersion;
|
||||||
|
- (int)OSBugFixVersion;
|
||||||
|
- (NSString *)OSVersion;
|
||||||
|
- (NSString *)OSVersionName;
|
||||||
|
- (BOOL)isAfterCheetah;
|
||||||
|
- (BOOL)isAfterPuma;
|
||||||
|
- (BOOL)isAfterJaguar;
|
||||||
|
- (BOOL)isAfterPanther;
|
||||||
|
- (BOOL)isAfterTiger;
|
||||||
|
- (BOOL)isAfterLeopard;
|
||||||
|
- (BOOL)isAfterSnowLeopard;
|
||||||
|
- (NSString *)language;
|
||||||
|
- (NSString *)applicationIdentifier;
|
||||||
|
- (NSString *)applicationName;
|
||||||
|
- (NSString *)applicationEXECName;
|
||||||
|
- (NSString *)applicationVersion;
|
||||||
|
- (BOOL)isUIElement;
|
||||||
|
- (NSBundle *)frameworkBundle;
|
||||||
|
- (NSString *)frameworkVersion;
|
||||||
|
- (NSString *)useragentWithApplicationNameAndVersion:(NSString *)nameAndVersion;
|
||||||
|
- (NSString *)useragent;
|
||||||
|
@end
|
Binary file not shown.
BIN
Frameworks/GeckoReporter.framework/Versions/A/Resources/English.lproj/MGMBugWindow.nib
generated
Normal file
BIN
Frameworks/GeckoReporter.framework/Versions/A/Resources/English.lproj/MGMBugWindow.nib
generated
Normal file
Binary file not shown.
BIN
Frameworks/GeckoReporter.framework/Versions/A/Resources/English.lproj/MGMContactWindow.nib
generated
Normal file
BIN
Frameworks/GeckoReporter.framework/Versions/A/Resources/English.lproj/MGMContactWindow.nib
generated
Normal file
Binary file not shown.
BIN
Frameworks/GeckoReporter.framework/Versions/A/Resources/English.lproj/MGMReportWindow.nib
generated
Normal file
BIN
Frameworks/GeckoReporter.framework/Versions/A/Resources/English.lproj/MGMReportWindow.nib
generated
Normal file
Binary file not shown.
Binary file not shown.
BIN
Frameworks/GeckoReporter.framework/Versions/A/Resources/French.lproj/MGMBugWindow.nib
generated
Normal file
BIN
Frameworks/GeckoReporter.framework/Versions/A/Resources/French.lproj/MGMBugWindow.nib
generated
Normal file
Binary file not shown.
BIN
Frameworks/GeckoReporter.framework/Versions/A/Resources/French.lproj/MGMContactWindow.nib
generated
Normal file
BIN
Frameworks/GeckoReporter.framework/Versions/A/Resources/French.lproj/MGMContactWindow.nib
generated
Normal file
Binary file not shown.
BIN
Frameworks/GeckoReporter.framework/Versions/A/Resources/French.lproj/MGMReportWindow.nib
generated
Normal file
BIN
Frameworks/GeckoReporter.framework/Versions/A/Resources/French.lproj/MGMReportWindow.nib
generated
Normal file
Binary file not shown.
@ -0,0 +1,42 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
|
<plist version="1.0">
|
||||||
|
<dict>
|
||||||
|
<key>BuildMachineOSBuild</key>
|
||||||
|
<string>10J567</string>
|
||||||
|
<key>CFBundleDevelopmentRegion</key>
|
||||||
|
<string>English</string>
|
||||||
|
<key>CFBundleExecutable</key>
|
||||||
|
<string>GeckoReporter</string>
|
||||||
|
<key>CFBundleIdentifier</key>
|
||||||
|
<string>com.MrGeckosMedia.GeckoReporter</string>
|
||||||
|
<key>CFBundleInfoDictionaryVersion</key>
|
||||||
|
<string>6.0</string>
|
||||||
|
<key>CFBundleName</key>
|
||||||
|
<string>GeckoReporter</string>
|
||||||
|
<key>CFBundlePackageType</key>
|
||||||
|
<string>FMWK</string>
|
||||||
|
<key>CFBundleShortVersionString</key>
|
||||||
|
<string>0.2</string>
|
||||||
|
<key>CFBundleSignature</key>
|
||||||
|
<string>????</string>
|
||||||
|
<key>CFBundleVersion</key>
|
||||||
|
<string>0.2</string>
|
||||||
|
<key>DTCompiler</key>
|
||||||
|
<string>4.2</string>
|
||||||
|
<key>DTPlatformBuild</key>
|
||||||
|
<string>4A278b</string>
|
||||||
|
<key>DTPlatformVersion</key>
|
||||||
|
<string>GM</string>
|
||||||
|
<key>DTSDKBuild</key>
|
||||||
|
<string>4A278b</string>
|
||||||
|
<key>DTSDKName</key>
|
||||||
|
<string>macosx10.6</string>
|
||||||
|
<key>DTXcode</key>
|
||||||
|
<string>0400</string>
|
||||||
|
<key>DTXcodeBuild</key>
|
||||||
|
<string>4A278b</string>
|
||||||
|
<key>NSHumanReadableCopyright</key>
|
||||||
|
<string>Copyright (c) 2011 Mr. Gecko's Media (James Coleman). All rights reserved. http://mrgeckosmedia.com/</string>
|
||||||
|
</dict>
|
||||||
|
</plist>
|
@ -0,0 +1,27 @@
|
|||||||
|
Copyright (c) 2010 Mr. Gecko's Media (James Coleman). All rights reserved. http://mrgeckosmedia.com/
|
||||||
|
|
||||||
|
Permission is granted, to any person obtaining a copy of this framework, to
|
||||||
|
use, copy, modify, merge, or redistribute this framework under the following terms:
|
||||||
|
|
||||||
|
1. This file must be included in all copies of this framework unmodified in
|
||||||
|
GeckoReporter.framework/Resource/License.txt and/or GeckoReporter.framework/Versions/A/Resources/License.txt.
|
||||||
|
|
||||||
|
2. THIS FRAMEWORK IS PROVIDED "AS IS" BY JAMES COLEMAN, WITHOUT WARRANTY OF
|
||||||
|
ANY KIND. IF YOUR SOFTWARE/FRAMEWORK/COMPUTER CRASH OR FAILS TO WORK IN ANY
|
||||||
|
WAY SHAPE OR FORM BECAUSE OF THIS FRAMEWORK, I (JAMES COLEMAN) AM NOT IN ANYWAY
|
||||||
|
RESPONSIBLE FOR YOUR PROBLEM. BUT, I MAY BE WILLING TO HELP YOU, NO PROMISES.
|
||||||
|
|
||||||
|
3. Redistributions of source code included in this framework must retain the
|
||||||
|
copyright notice above this license file without modifications.
|
||||||
|
|
||||||
|
4. Redistributions of binary must contain the copyright above this license file
|
||||||
|
without modifications.
|
||||||
|
|
||||||
|
5. If you use the crash reporter in this framework, you are allowed to remove the
|
||||||
|
NSTextField that says, "GeckoReporter by Mr. Gecko's Media".
|
||||||
|
|
||||||
|
6. For the users convenience, you must retain the notice about anonymous system
|
||||||
|
information being sent.
|
||||||
|
|
||||||
|
7. Mr. Gecko's Media (James Coleman) is allowed to modify these terms without notice to you
|
||||||
|
or your customers.
|
@ -0,0 +1,206 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
|
<plist version="1.0">
|
||||||
|
<dict>
|
||||||
|
<key>ADP2,1</key>
|
||||||
|
<string>Developer Transition Kit</string>
|
||||||
|
<key>iMac1,1</key>
|
||||||
|
<string>iMac G3 (Rev A-D)</string>
|
||||||
|
<key>PowerMac2,1</key>
|
||||||
|
<string>iMac G3 (Slot-loading CD-ROM)</string>
|
||||||
|
<key>PowerMac2,2</key>
|
||||||
|
<string>iMac G3 (Summer 2000)</string>
|
||||||
|
<key>PowerMac4,1</key>
|
||||||
|
<string>iMac G3 (2001)</string>
|
||||||
|
<key>PowerMac4,2</key>
|
||||||
|
<string>iMac G4 (Flat Panel)</string>
|
||||||
|
<key>PowerMac4,5</key>
|
||||||
|
<string>iMac G4 (17" Flat Panel)</string>
|
||||||
|
<key>PowerMac6,1</key>
|
||||||
|
<string>iMac G4 (USB 2.0)</string>
|
||||||
|
<key>PowerMac6,3</key>
|
||||||
|
<string>iMac G4 (20" Flat Panel)</string>
|
||||||
|
<key>PowerMac8,1</key>
|
||||||
|
<string>iMac G5</string>
|
||||||
|
<key>PowerMac8,2</key>
|
||||||
|
<string>iMac G5 (Ambient Light Sensor)</string>
|
||||||
|
<key>PowerMac12,1</key>
|
||||||
|
<string>iMac G5 (iSight)</string>
|
||||||
|
<key>iMac4,1</key>
|
||||||
|
<string>iMac (Core Duo)</string>
|
||||||
|
<key>iMac4,2</key>
|
||||||
|
<string>iMac for Education (17" Core Duo)</string>
|
||||||
|
<key>iMac5,1</key>
|
||||||
|
<string>iMac (Core 2 Duo 17"/20" SuperDrive)</string>
|
||||||
|
<key>iMac5,2</key>
|
||||||
|
<string>iMac (Core 2 Duo 17" Combo Drive)</string>
|
||||||
|
<key>iMac6,1</key>
|
||||||
|
<string>iMac (Core 2 Duo 24" SuperDrive)</string>
|
||||||
|
<key>iMac7,1</key>
|
||||||
|
<string>iMac (AI)</string>
|
||||||
|
<key>iMac8,1</key>
|
||||||
|
<string>iMac (2008)</string>
|
||||||
|
<key>iMac9,1</key>
|
||||||
|
<string>iMac (2009)</string>
|
||||||
|
<key>iMac10,1</key>
|
||||||
|
<string>iMac (2009 Magic)</string>
|
||||||
|
<key>iMac11,1</key>
|
||||||
|
<string>iMac (2009 Core I5)</string>
|
||||||
|
<key>PowerMac4,4</key>
|
||||||
|
<string>eMac</string>
|
||||||
|
<key>PowerMac6,4</key>
|
||||||
|
<string>eMac (USB 2.0 2005)</string>
|
||||||
|
<key>PowerMac10,1</key>
|
||||||
|
<string>Mac Mini G4</string>
|
||||||
|
<key>PowerMac10,2</key>
|
||||||
|
<string>Mac Mini (2005)</string>
|
||||||
|
<key>Macmini1,1</key>
|
||||||
|
<string>Mac Mini (Core Solo/Duo)</string>
|
||||||
|
<key>Macmini2,1</key>
|
||||||
|
<string>Mac Mini (Core 2 Duo)</string>
|
||||||
|
<key>Macmini3,1</key>
|
||||||
|
<string>Mac Mini (2009)</string>
|
||||||
|
<key>PowerBook2,1</key>
|
||||||
|
<string>iBook G3</string>
|
||||||
|
<key>PowerBook2,2</key>
|
||||||
|
<string>iBook G3 (FireWire)</string>
|
||||||
|
<key>PowerBook2,3</key>
|
||||||
|
<string>iBook G3</string>
|
||||||
|
<key>PowerBook2,4</key>
|
||||||
|
<string>iBook G3</string>
|
||||||
|
<key>PowerBook4,1</key>
|
||||||
|
<string>iBook G3 (Dual USB 2001)</string>
|
||||||
|
<key>PowerBook4,2</key>
|
||||||
|
<string>iBook G3 (16MB VRAM)</string>
|
||||||
|
<key>PowerBook4,3</key>
|
||||||
|
<string>iBook G3 Opaque 16MB VRAM/32MB VRAM 2003)</string>
|
||||||
|
<key>PowerBook6,3</key>
|
||||||
|
<string>iBook G4</string>
|
||||||
|
<key>PowerBook6,5</key>
|
||||||
|
<string>iBook G4 (2004)</string>
|
||||||
|
<key>PowerBook6,7</key>
|
||||||
|
<string>iBook G4 (Mid 2005)</string>
|
||||||
|
<key>PowerBook1,1</key>
|
||||||
|
<string>PowerBook G3</string>
|
||||||
|
<key>PowerBook3,1</key>
|
||||||
|
<string>PowerBook G3 (FireWire)</string>
|
||||||
|
<key>PowerBook3,2</key>
|
||||||
|
<string>PowerBook G4</string>
|
||||||
|
<key>PowerBook3,3</key>
|
||||||
|
<string>PowerBook G4 (Gigabit Ethernet)</string>
|
||||||
|
<key>PowerBook3,4</key>
|
||||||
|
<string>PowerBook G4 (DVI)</string>
|
||||||
|
<key>PowerBook3,5</key>
|
||||||
|
<string>PowerBook G4 (1GHz/867MHz)</string>
|
||||||
|
<key>PowerBook5,1</key>
|
||||||
|
<string>PowerBook G4 (17")</string>
|
||||||
|
<key>PowerBook5,2</key>
|
||||||
|
<string>PowerBook G4 (15" FW 800)</string>
|
||||||
|
<key>PowerBook5,3</key>
|
||||||
|
<string>PowerBook G4 (17" 1.33GHz)</string>
|
||||||
|
<key>PowerBook5,4</key>
|
||||||
|
<string>PowerBook G4 (15" 1.5/1.33GHz)</string>
|
||||||
|
<key>PowerBook5,5</key>
|
||||||
|
<string>PowerBook G4 (17" 1.5GHz)</string>
|
||||||
|
<key>PowerBook5,6</key>
|
||||||
|
<string>PowerBook G4 (15" 1.67GHz/1.5GHz)</string>
|
||||||
|
<key>PowerBook5,7</key>
|
||||||
|
<string>PowerBook G4 (17" 1.67GHz)</string>
|
||||||
|
<key>PowerBook5,8</key>
|
||||||
|
<string>PowerBook G4 (Double layer SD 15")</string>
|
||||||
|
<key>PowerBook5,9</key>
|
||||||
|
<string>PowerBook G4 (Double layer SD 17")</string>
|
||||||
|
<key>PowerBook6,1</key>
|
||||||
|
<string>PowerBook G4 (12")</string>
|
||||||
|
<key>PowerBook6,2</key>
|
||||||
|
<string>PowerBook G4 (12" DVI)</string>
|
||||||
|
<key>PowerBook6,4</key>
|
||||||
|
<string>PowerBook G4 (12" 1.33GHz)</string>
|
||||||
|
<key>PowerBook6,8</key>
|
||||||
|
<string>PowerBook G4 (12" 1.5GHz)</string>
|
||||||
|
<key>MacBook1,1</key>
|
||||||
|
<string>MacBook (Core Duo)</string>
|
||||||
|
<key>MacBook2,1</key>
|
||||||
|
<string>MacBook (Core 2 Duo)</string>
|
||||||
|
<key>MacBook4,1</key>
|
||||||
|
<string>MacBook (2008)</string>
|
||||||
|
<key>MacBook5,1</key>
|
||||||
|
<string>MacBook (Unibody)</string>
|
||||||
|
<key>MacBook5,2</key>
|
||||||
|
<string>MacBook (White 2009)</string>
|
||||||
|
<key>MacBook6,1</key>
|
||||||
|
<string>MacBook (White Unibody)</string>
|
||||||
|
<key>MacBookAir1,1</key>
|
||||||
|
<string>MacBook Air (2008)</string>
|
||||||
|
<key>MacBookPro1,1</key>
|
||||||
|
<string>MacBook Pro Core Duo (15")</string>
|
||||||
|
<key>MacBookPro1,2</key>
|
||||||
|
<string>MacBook Pro Core Duo (17")</string>
|
||||||
|
<key>MacBookPro2,1</key>
|
||||||
|
<string>MacBook Pro Core 2 Duo (17")</string>
|
||||||
|
<key>MacBookPro2,2</key>
|
||||||
|
<string>MacBook Pro Core 2 Duo (15")</string>
|
||||||
|
<key>MacBookPro3,1</key>
|
||||||
|
<string>MacBook Pro Core 2 Duo (15" LED Core 2 Duo)</string>
|
||||||
|
<key>MacBookPro3,2</key>
|
||||||
|
<string>MacBook Pro Core 2 Duo (17" HD Core 2 Duo)</string>
|
||||||
|
<key>MacBookPro4,1</key>
|
||||||
|
<string>MacBook Pro (Core 2 Duo 2008)</string>
|
||||||
|
<key>MacBookPro5,1</key>
|
||||||
|
<string>MacBook Pro (Unibody)</string>
|
||||||
|
<key>MacBookPro5,2</key>
|
||||||
|
<string>MacBook Pro (Unibody 17" 2009)</string>
|
||||||
|
<key>MacBookPro5,3</key>
|
||||||
|
<string>MacBook Pro (Unibody 15" 2009)</string>
|
||||||
|
<key>MacBookPro5,4</key>
|
||||||
|
<string>MacBook Pro (Unibody 15" 2009)</string>
|
||||||
|
<key>MacBookPro5,5</key>
|
||||||
|
<string>MacBook Pro (Unibody 13" 2009)</string>
|
||||||
|
<key>PowerMac1,1</key>
|
||||||
|
<string>Power Macintosh G3 (Blue & White)</string>
|
||||||
|
<key>PowerMac1,2</key>
|
||||||
|
<string>Power Macintosh G4 (PCI Graphics)</string>
|
||||||
|
<key>PowerMac11,2</key>
|
||||||
|
<string>Power Macintosh G5 (2005)</string>
|
||||||
|
<key>PowerMac3,1</key>
|
||||||
|
<string>Power Macintosh G4 (AGP Graphics)</string>
|
||||||
|
<key>PowerMac3,2</key>
|
||||||
|
<string>Power Macintosh G4 (AGP Graphics)</string>
|
||||||
|
<key>PowerMac3,3</key>
|
||||||
|
<string>Power Macintosh G4 (Gigabit Ethernet)</string>
|
||||||
|
<key>PowerMac3,4</key>
|
||||||
|
<string>Power Macintosh G4 (Digital Audio)</string>
|
||||||
|
<key>PowerMac3,5</key>
|
||||||
|
<string>Power Macintosh G4 (Quick Silver)</string>
|
||||||
|
<key>PowerMac3,6</key>
|
||||||
|
<string>Power Macintosh G4 (Mirrored Drive Door)</string>
|
||||||
|
<key>PowerMac5,1</key>
|
||||||
|
<string>Power Macintosh G4 Cube</string>
|
||||||
|
<key>PowerMac7,2</key>
|
||||||
|
<string>Power Macintosh G5</string>
|
||||||
|
<key>PowerMac7,3</key>
|
||||||
|
<string>Power Macintosh G5</string>
|
||||||
|
<key>PowerMac9,1</key>
|
||||||
|
<string>Power Macintosh G5 (2005)</string>
|
||||||
|
<key>MacPro1,1</key>
|
||||||
|
<string>Mac Pro (Four-Core)</string>
|
||||||
|
<key>MacPro2,1</key>
|
||||||
|
<string>Mac Pro (Eight-Core)</string>
|
||||||
|
<key>MacPro3,1</key>
|
||||||
|
<string>Mac Pro (2008 4/8 core "Harpertown")</string>
|
||||||
|
<key>MacPro4,1</key>
|
||||||
|
<string>Mac Pro (2009 "Nehalem")</string>
|
||||||
|
<key>RackMac1,1</key>
|
||||||
|
<string>Xserve G4</string>
|
||||||
|
<key>RackMac1,2</key>
|
||||||
|
<string>Xserve G4 (Slot-loading cluster node)</string>
|
||||||
|
<key>RackMac3,1</key>
|
||||||
|
<string>Xserve G5</string>
|
||||||
|
<key>Xserve1,1</key>
|
||||||
|
<string>Xserve (Intel Xeon)</string>
|
||||||
|
<key>Xserve2,1</key>
|
||||||
|
<string>Xserve (2008 Quad-Core)</string>
|
||||||
|
<key>Xserve3,1</key>
|
||||||
|
<string>Xserve (2009 Quad-Core)</string>
|
||||||
|
</dict>
|
||||||
|
</plist>
|
Binary file not shown.
BIN
Frameworks/GeckoReporter.framework/Versions/A/Resources/es.lproj/MGMBugWindow.nib
generated
Normal file
BIN
Frameworks/GeckoReporter.framework/Versions/A/Resources/es.lproj/MGMBugWindow.nib
generated
Normal file
Binary file not shown.
BIN
Frameworks/GeckoReporter.framework/Versions/A/Resources/es.lproj/MGMContactWindow.nib
generated
Normal file
BIN
Frameworks/GeckoReporter.framework/Versions/A/Resources/es.lproj/MGMContactWindow.nib
generated
Normal file
Binary file not shown.
BIN
Frameworks/GeckoReporter.framework/Versions/A/Resources/es.lproj/MGMReportWindow.nib
generated
Normal file
BIN
Frameworks/GeckoReporter.framework/Versions/A/Resources/es.lproj/MGMReportWindow.nib
generated
Normal file
Binary file not shown.
Binary file not shown.
BIN
Frameworks/GeckoReporter.framework/Versions/A/Resources/pt-PT.lproj/MGMBugWindow.nib
generated
Normal file
BIN
Frameworks/GeckoReporter.framework/Versions/A/Resources/pt-PT.lproj/MGMBugWindow.nib
generated
Normal file
Binary file not shown.
BIN
Frameworks/GeckoReporter.framework/Versions/A/Resources/pt-PT.lproj/MGMContactWindow.nib
generated
Normal file
BIN
Frameworks/GeckoReporter.framework/Versions/A/Resources/pt-PT.lproj/MGMContactWindow.nib
generated
Normal file
Binary file not shown.
BIN
Frameworks/GeckoReporter.framework/Versions/A/Resources/pt-PT.lproj/MGMReportWindow.nib
generated
Normal file
BIN
Frameworks/GeckoReporter.framework/Versions/A/Resources/pt-PT.lproj/MGMReportWindow.nib
generated
Normal file
Binary file not shown.
Binary file not shown.
BIN
Frameworks/GeckoReporter.framework/Versions/A/Resources/sv.lproj/MGMBugWindow.nib
generated
Normal file
BIN
Frameworks/GeckoReporter.framework/Versions/A/Resources/sv.lproj/MGMBugWindow.nib
generated
Normal file
Binary file not shown.
BIN
Frameworks/GeckoReporter.framework/Versions/A/Resources/sv.lproj/MGMContactWindow.nib
generated
Normal file
BIN
Frameworks/GeckoReporter.framework/Versions/A/Resources/sv.lproj/MGMContactWindow.nib
generated
Normal file
Binary file not shown.
BIN
Frameworks/GeckoReporter.framework/Versions/A/Resources/sv.lproj/MGMReportWindow.nib
generated
Normal file
BIN
Frameworks/GeckoReporter.framework/Versions/A/Resources/sv.lproj/MGMReportWindow.nib
generated
Normal file
Binary file not shown.
1
Frameworks/GeckoReporter.framework/Versions/Current
Symbolic link
1
Frameworks/GeckoReporter.framework/Versions/Current
Symbolic link
@ -0,0 +1 @@
|
|||||||
|
A
|
1
Frameworks/Growl.framework/Growl
Symbolic link
1
Frameworks/Growl.framework/Growl
Symbolic link
@ -0,0 +1 @@
|
|||||||
|
Versions/Current/Growl
|
1
Frameworks/Growl.framework/Headers
Symbolic link
1
Frameworks/Growl.framework/Headers
Symbolic link
@ -0,0 +1 @@
|
|||||||
|
Versions/Current/Headers
|
1
Frameworks/Growl.framework/Resources
Symbolic link
1
Frameworks/Growl.framework/Resources
Symbolic link
@ -0,0 +1 @@
|
|||||||
|
Versions/Current/Resources
|
BIN
Frameworks/Growl.framework/Versions/A/Growl
Executable file
BIN
Frameworks/Growl.framework/Versions/A/Growl
Executable file
Binary file not shown.
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user