├── IMLight.xcodeproj ├── xcuserdata │ └── BlahGeek.xcuserdatad │ │ ├── xcdebugger │ │ └── Breakpoints_v2.xcbkptlist │ │ └── xcschemes │ │ ├── xcschememanagement.plist │ │ └── IMLight.xcscheme ├── project.xcworkspace │ ├── contents.xcworkspacedata │ └── xcuserdata │ │ └── BlahGeek.xcuserdatad │ │ ├── UserInterfaceState.xcuserstate │ │ └── WorkspaceSettings.xcsettings └── project.pbxproj ├── IMLight ├── Images.xcassets │ └── AppIcon.appiconset │ │ ├── Editing-Generic-Text-icon.png │ │ ├── Editing-Generic-Text-icon-1.png │ │ ├── Editing-Generic-Text-icon-2.png │ │ └── Contents.json ├── IMLight.entitlements ├── main.m ├── Credits.rtf ├── AppDelegate.h ├── LED.h ├── Info.plist ├── LaunchAtLoginController.h ├── AppDelegate.m ├── README.md ├── LaunchAtLoginController.m ├── LED.m └── Base.lproj │ └── MainMenu.xib └── IMLightTests ├── Info.plist └── IMLightTests.m /IMLight.xcodeproj/xcuserdata/BlahGeek.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | -------------------------------------------------------------------------------- /IMLight/Images.xcassets/AppIcon.appiconset/Editing-Generic-Text-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/blahgeek/IMLight/HEAD/IMLight/Images.xcassets/AppIcon.appiconset/Editing-Generic-Text-icon.png -------------------------------------------------------------------------------- /IMLight/Images.xcassets/AppIcon.appiconset/Editing-Generic-Text-icon-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/blahgeek/IMLight/HEAD/IMLight/Images.xcassets/AppIcon.appiconset/Editing-Generic-Text-icon-1.png -------------------------------------------------------------------------------- /IMLight/Images.xcassets/AppIcon.appiconset/Editing-Generic-Text-icon-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/blahgeek/IMLight/HEAD/IMLight/Images.xcassets/AppIcon.appiconset/Editing-Generic-Text-icon-2.png -------------------------------------------------------------------------------- /IMLight/IMLight.entitlements: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /IMLight.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /IMLight.xcodeproj/project.xcworkspace/xcuserdata/BlahGeek.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/blahgeek/IMLight/HEAD/IMLight.xcodeproj/project.xcworkspace/xcuserdata/BlahGeek.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /IMLight/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // IMLight 4 | // 5 | // Created by BlahGeek on 14/11/6. 6 | // Copyright (c) 2014年 BlahGeek. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | int main(int argc, const char * argv[]) { 12 | return NSApplicationMain(argc, argv); 13 | } 14 | -------------------------------------------------------------------------------- /IMLight/Credits.rtf: -------------------------------------------------------------------------------- 1 | {\rtf1\ansi\ansicpg936\cocoartf1343\cocoasubrtf140 2 | {\fonttbl\f0\fswiss\fcharset0 Helvetica;} 3 | {\colortbl;\red255\green255\blue255;} 4 | \paperw12240\paperh15840\margl1440\margr1440\vieww11040\viewh8400\viewkind0 5 | \pard\tx566\tx1133\tx1700\tx2267\tx2834\tx3401\tx3968\tx4535\tx5102\tx5669\tx6236\tx6803\pardirnatural\qc 6 | 7 | \f0\fs28 \cf0 This is a simple application to turn on Caps Lock light when an input method is selected, which is useful if you use \'93Caps Lock\'94 to switch IM. \ 8 | \ 9 | See {\field{\*\fldinst{HYPERLINK "http://blog.blahgeek.com/IMLight"}}{\fldrslt this post}} to see HOWTO.} -------------------------------------------------------------------------------- /IMLight/AppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.h 3 | // IMLight 4 | // 5 | // Created by BlahGeek on 14/11/6. 6 | // Copyright (c) 2014年 BlahGeek. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "LED.h" 11 | #import "LaunchAtLoginController.h" 12 | 13 | @interface AppDelegate : NSObject 14 | 15 | @property (weak) IBOutlet NSMenu *statusMenu; 16 | @property (weak) IBOutlet NSMenuItem *startAtLoginItem; 17 | @property (strong, nonatomic) NSStatusItem *statusBar; 18 | 19 | @property (strong) LED * caps_led; 20 | @property (strong) LaunchAtLoginController * launchController; 21 | 22 | - (void)initLED; 23 | - (IBAction)setStartAtLogin:(id)sender; 24 | 25 | @end 26 | 27 | -------------------------------------------------------------------------------- /IMLight/LED.h: -------------------------------------------------------------------------------- 1 | // 2 | // LED.h 3 | // IMMonitor 4 | // 5 | // Created by BlahGeek on 14/11/6. 6 | // Copyright (c) 2014年 BlahGeek. All rights reserved. 7 | // 8 | 9 | #ifndef IMMonitor_LED_h 10 | #define IMMonitor_LED_h 11 | 12 | #import 13 | #include 14 | #include 15 | 16 | #define MAX_DEVICE_COUNT 16 17 | 18 | @interface LED : NSObject 19 | { 20 | IOHIDDeviceRef ledDevices[MAX_DEVICE_COUNT]; 21 | IOHIDElementRef ledElements[MAX_DEVICE_COUNT]; 22 | int device_count; 23 | } 24 | // Pass either kHIDUsage_LED_NumLock or kHIDUsage_LED_CapsLock 25 | -(id)initWithUsage:(uint32_t)usage; 26 | -(void)setValue:(SInt32)value; 27 | @end 28 | 29 | #endif 30 | -------------------------------------------------------------------------------- /IMLight.xcodeproj/xcuserdata/BlahGeek.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | IMLight.xcscheme 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | SuppressBuildableAutocreation 14 | 15 | DAA79EA11A0B65810094CD1A 16 | 17 | primary 18 | 19 | 20 | DAA79EB41A0B65810094CD1A 21 | 22 | primary 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /IMLight.xcodeproj/project.xcworkspace/xcuserdata/BlahGeek.xcuserdatad/WorkspaceSettings.xcsettings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | BuildLocationStyle 6 | UseAppPreferences 7 | CustomBuildLocationType 8 | RelativeToDerivedData 9 | DerivedDataLocationStyle 10 | Default 11 | IssueFilterStyle 12 | ShowActiveSchemeOnly 13 | LiveSourceIssuesEnabled 14 | 15 | SnapshotAutomaticallyBeforeSignificantChanges 16 | 17 | SnapshotLocationStyle 18 | Default 19 | 20 | 21 | -------------------------------------------------------------------------------- /IMLightTests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | blahgeek.$(PRODUCT_NAME:rfc1034identifier) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | 24 | 25 | -------------------------------------------------------------------------------- /IMLightTests/IMLightTests.m: -------------------------------------------------------------------------------- 1 | // 2 | // IMLightTests.m 3 | // IMLightTests 4 | // 5 | // Created by BlahGeek on 14/11/6. 6 | // Copyright (c) 2014年 BlahGeek. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | 12 | @interface IMLightTests : XCTestCase 13 | 14 | @end 15 | 16 | @implementation IMLightTests 17 | 18 | - (void)setUp { 19 | [super setUp]; 20 | // Put setup code here. This method is called before the invocation of each test method in the class. 21 | } 22 | 23 | - (void)tearDown { 24 | // Put teardown code here. This method is called after the invocation of each test method in the class. 25 | [super tearDown]; 26 | } 27 | 28 | - (void)testExample { 29 | // This is an example of a functional test case. 30 | XCTAssert(YES, @"Pass"); 31 | } 32 | 33 | - (void)testPerformanceExample { 34 | // This is an example of a performance test case. 35 | [self measureBlock:^{ 36 | // Put the code you want to measure the time of here. 37 | }]; 38 | } 39 | 40 | @end 41 | -------------------------------------------------------------------------------- /IMLight/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | blahgeek.$(PRODUCT_NAME:rfc1034identifier) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | LSMinimumSystemVersion 24 | $(MACOSX_DEPLOYMENT_TARGET) 25 | LSUIElement 26 | 27 | NSHumanReadableCopyright 28 | Copyright © 2014年 BlahGeek. All rights reserved. 29 | NSMainNibFile 30 | MainMenu 31 | NSPrincipalClass 32 | NSApplication 33 | 34 | 35 | -------------------------------------------------------------------------------- /IMLight/Images.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "mac", 5 | "size" : "16x16", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "mac", 10 | "size" : "16x16", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "size" : "32x32", 15 | "idiom" : "mac", 16 | "filename" : "Editing-Generic-Text-icon-2.png", 17 | "scale" : "1x" 18 | }, 19 | { 20 | "idiom" : "mac", 21 | "size" : "32x32", 22 | "scale" : "2x" 23 | }, 24 | { 25 | "size" : "128x128", 26 | "idiom" : "mac", 27 | "filename" : "Editing-Generic-Text-icon-1.png", 28 | "scale" : "1x" 29 | }, 30 | { 31 | "idiom" : "mac", 32 | "size" : "128x128", 33 | "scale" : "2x" 34 | }, 35 | { 36 | "size" : "256x256", 37 | "idiom" : "mac", 38 | "filename" : "Editing-Generic-Text-icon.png", 39 | "scale" : "1x" 40 | }, 41 | { 42 | "idiom" : "mac", 43 | "size" : "256x256", 44 | "scale" : "2x" 45 | }, 46 | { 47 | "idiom" : "mac", 48 | "size" : "512x512", 49 | "scale" : "1x" 50 | }, 51 | { 52 | "idiom" : "mac", 53 | "size" : "512x512", 54 | "scale" : "2x" 55 | } 56 | ], 57 | "info" : { 58 | "version" : 1, 59 | "author" : "xcode" 60 | } 61 | } -------------------------------------------------------------------------------- /IMLight/LaunchAtLoginController.h: -------------------------------------------------------------------------------- 1 | // 2 | // LaunchAtLoginController.h 3 | // 4 | // Copyright 2011 Tomáš Znamenáček 5 | // Copyright 2010 Ben Clark-Robinson 6 | // 7 | // Permission is hereby granted, free of charge, to any person obtaining 8 | // a copy of this software and associated documentation files (the ‘Software’), 9 | // to deal in the Software without restriction, including without limitation 10 | // the rights to use, copy, modify, merge, publish, distribute, sublicense, 11 | // and/or sell copies of the Software, and to permit persons to whom the 12 | // Software is furnished to do so, subject to the following conditions: 13 | // 14 | // The above copyright notice and this permission notice shall be 15 | // included in all copies or substantial portions of the Software. 16 | // 17 | // THE SOFTWARE IS PROVIDED ‘AS IS’, WITHOUT WARRANTY OF ANY KIND, 18 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 20 | // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 21 | // CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 22 | // TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 23 | // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 | 25 | #import 26 | 27 | @interface LaunchAtLoginController : NSObject {} 28 | 29 | @property(assign) BOOL launchAtLogin; 30 | 31 | - (BOOL) willLaunchAtLogin: (NSURL*) itemURL; 32 | - (void) setLaunchAtLogin: (BOOL) enabled forURL: (NSURL*) itemURL; 33 | 34 | @end 35 | -------------------------------------------------------------------------------- /IMLight/AppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.m 3 | // IMLight 4 | // 5 | // Created by BlahGeek on 14/11/6. 6 | // Copyright (c) 2014年 BlahGeek. All rights reserved. 7 | // 8 | 9 | #import "AppDelegate.h" 10 | #import 11 | 12 | @interface AppDelegate () 13 | 14 | @property (weak) IBOutlet NSWindow *window; 15 | @end 16 | 17 | @implementation AppDelegate 18 | 19 | - (void)initLED { 20 | self.caps_led = [[LED alloc] initWithUsage:kHIDUsage_LED_CapsLock]; 21 | NSLog(@"LED inited!"); 22 | } 23 | 24 | - (void)applicationDidFinishLaunching:(NSNotification *)aNotification { 25 | self.launchController = [[LaunchAtLoginController alloc] init]; 26 | [self.startAtLoginItem setState:([self.launchController launchAtLogin] ? NSOnState : NSOffState)]; 27 | 28 | [[[NSWorkspace sharedWorkspace] notificationCenter] addObserver:self 29 | selector:@selector(initLED) 30 | name:NSWorkspaceDidWakeNotification 31 | object:NULL]; 32 | [self initLED]; 33 | 34 | [[NSDistributedNotificationCenter defaultCenter] 35 | addObserverForName:(__bridge NSString *)kTISNotifySelectedKeyboardInputSourceChanged 36 | object:nil 37 | queue:nil 38 | usingBlock:^(NSNotification * noti) { 39 | 40 | NSLog(@"In callback block of notification."); 41 | 42 | CFArrayRef all_im = TISCreateInputSourceList(NULL, false); 43 | for(int i = 0 ; i < CFArrayGetCount(all_im) ; i += 1) { 44 | TISInputSourceRef im = (TISInputSourceRef)CFArrayGetValueAtIndex(all_im, i); 45 | 46 | CFStringRef im_type = TISGetInputSourceProperty(im, kTISPropertyInputSourceType); 47 | CFBooleanRef im_selected = TISGetInputSourceProperty(im, kTISPropertyInputSourceIsSelected); 48 | if (CFBooleanGetValue(im_selected) == YES) { 49 | [self.caps_led setValue:(im_type != kTISTypeKeyboardLayout)]; 50 | break; 51 | } 52 | } 53 | CFRelease(all_im); 54 | } 55 | ]; 56 | // Insert code here to initialize your application 57 | } 58 | 59 | - (void)applicationWillTerminate:(NSNotification *)aNotification { 60 | // Insert code here to tear down your application 61 | } 62 | 63 | - (void)awakeFromNib { 64 | self.statusBar = [[NSStatusBar systemStatusBar] statusItemWithLength:NSVariableStatusItemLength]; 65 | [self.statusBar setTitle:@"A"]; 66 | self.statusBar.menu = self.statusMenu; 67 | self.statusBar.highlightMode = YES; 68 | } 69 | 70 | - (IBAction)setStartAtLogin:(id)sender { 71 | NSUInteger state = NSOffState; 72 | if(self.startAtLoginItem.state == NSOffState) 73 | state = NSOnState; 74 | [self.startAtLoginItem setState:state]; 75 | [self.launchController setLaunchAtLogin: (state == NSOnState)]; 76 | } 77 | @end 78 | -------------------------------------------------------------------------------- /IMLight/README.md: -------------------------------------------------------------------------------- 1 | # LaunchAtLoginController 2 | 3 | A very simple to implement Controller for use in Cocoa Mac Apps to register/deregister itself for Launch at Login using LSSharedFileList. 4 | 5 | It uses LSSharedFileList which means your Users will be able to check System Preferences > Accounts > Login Items. 6 | 7 | I'm currently using it on 10.6 (32/64) successfully. I've not investigated being able to flag the "Hide" flag which is possible from System Preferences. 8 | 9 | ## IMPLEMENTATION (Code): 10 | 11 | ### Will app launch at login? 12 | 13 | LaunchAtLoginController *launchController = [[LaunchAtLoginController alloc] init]; 14 | BOOL launch = [launchController launchAtLogin]; 15 | [launchController release]; 16 | 17 | ### Set launch at login state. 18 | 19 | LaunchAtLoginController *launchController = [[LaunchAtLoginController alloc] init]; 20 | [launchController setLaunchAtLogin:YES]; 21 | [launchController release]; 22 | 23 | ## IMPLEMENTATION (Interface builder): 24 | 25 | * Open Interface Builder 26 | * Place a NSObject (the blue box) into the nib window 27 | * From the Inspector - Identity Tab (Cmd+6) set the Class to LaunchAtLoginController 28 | * Place a Checkbox on your Window/View 29 | * From the Inspector - Bindings Tab (Cmd+4) unroll the > Value item 30 | * Bind to Launch at Login Controller 31 | * Model Key Path: launchAtLogin 32 | 33 | ## IS IT WORKING: 34 | 35 | After implementing either through code or through IB, setLaunchAtLogin:YES and then check System Preferences > Accounts > Login Items. You should see your app in the list of apps that will start when the user logs in. 36 | 37 | ## CAVEATS (HelperApp Bundles): 38 | 39 | If you're trying to set a different bundle (perhaps a HelperApp as a resource to your main bundle) you will simply want to change 40 | - (NSURL *)appURL 41 | to return the path to this other bundle. 42 | 43 | ## REQUIREMENTS: 44 | 45 | Works on 10.6/10.5 46 | 47 | ## ORIGINAL CODE IDEAS: 48 | 49 | * Growl. 50 | * User: invariant Link: (http://stackoverflow.com/questions/815063/how-do-you-make-your-app-open-at-login/2318004#2318004) 51 | 52 | 53 | ## LICENSE: 54 | 55 | (The MIT License) 56 | 57 | Copyright (c) 2010 Ben Clark-Robinson, ben.clarkrobinson@gmail.com 58 | 59 | Permission is hereby granted, free of charge, to any person obtaining 60 | a copy of this software and associated documentation files (the 61 | 'Software'), to deal in the Software without restriction, including 62 | without limitation the rights to use, copy, modify, merge, publish, 63 | distribute, sublicense, and/or sell copies of the Software, and to 64 | permit persons to whom the Software is furnished to do so, subject to 65 | the following conditions: 66 | 67 | The above copyright notice and this permission notice shall be 68 | included in all copies or substantial portions of the Software. 69 | 70 | THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, 71 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 72 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 73 | IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 74 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 75 | TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 76 | SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 77 | -------------------------------------------------------------------------------- /IMLight/LaunchAtLoginController.m: -------------------------------------------------------------------------------- 1 | // 2 | // LaunchAtLoginController.m 3 | // 4 | // Copyright 2011 Tomáš Znamenáček 5 | // Copyright 2010 Ben Clark-Robinson 6 | // 7 | // Permission is hereby granted, free of charge, to any person obtaining 8 | // a copy of this software and associated documentation files (the ‘Software’), 9 | // to deal in the Software without restriction, including without limitation 10 | // the rights to use, copy, modify, merge, publish, distribute, sublicense, 11 | // and/or sell copies of the Software, and to permit persons to whom the 12 | // Software is furnished to do so, subject to the following conditions: 13 | // 14 | // The above copyright notice and this permission notice shall be 15 | // included in all copies or substantial portions of the Software. 16 | // 17 | // THE SOFTWARE IS PROVIDED ‘AS IS’, WITHOUT WARRANTY OF ANY KIND, 18 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 20 | // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 21 | // CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 22 | // TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 23 | // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 | 25 | #import "LaunchAtLoginController.h" 26 | 27 | static NSString *const StartAtLoginKey = @"launchAtLogin"; 28 | 29 | @interface LaunchAtLoginController () 30 | @property(assign) LSSharedFileListRef loginItems; 31 | @end 32 | 33 | @implementation LaunchAtLoginController 34 | @synthesize loginItems; 35 | 36 | #pragma mark Change Observing 37 | 38 | void sharedFileListDidChange(LSSharedFileListRef inList, void *context) 39 | { 40 | LaunchAtLoginController *self = (id) context; 41 | [self willChangeValueForKey:StartAtLoginKey]; 42 | [self didChangeValueForKey:StartAtLoginKey]; 43 | } 44 | 45 | #pragma mark Initialization 46 | 47 | - (id) init 48 | { 49 | [super init]; 50 | loginItems = LSSharedFileListCreate(NULL, kLSSharedFileListSessionLoginItems, NULL); 51 | LSSharedFileListAddObserver(loginItems, CFRunLoopGetMain(), 52 | (CFStringRef)NSDefaultRunLoopMode, sharedFileListDidChange, self); 53 | return self; 54 | } 55 | 56 | - (void) dealloc 57 | { 58 | LSSharedFileListRemoveObserver(loginItems, CFRunLoopGetMain(), 59 | (CFStringRef)NSDefaultRunLoopMode, sharedFileListDidChange, self); 60 | CFRelease(loginItems); 61 | [super dealloc]; 62 | } 63 | 64 | #pragma mark Launch List Control 65 | 66 | - (LSSharedFileListItemRef) findItemWithURL: (NSURL*) wantedURL inFileList: (LSSharedFileListRef) fileList 67 | { 68 | if (wantedURL == NULL || fileList == NULL) 69 | return NULL; 70 | 71 | NSArray *listSnapshot = [NSMakeCollectable(LSSharedFileListCopySnapshot(fileList, NULL)) autorelease]; 72 | for (id itemObject in listSnapshot) { 73 | LSSharedFileListItemRef item = (LSSharedFileListItemRef) itemObject; 74 | UInt32 resolutionFlags = kLSSharedFileListNoUserInteraction | kLSSharedFileListDoNotMountVolumes; 75 | CFURLRef currentItemURL = NULL; 76 | LSSharedFileListItemResolve(item, resolutionFlags, ¤tItemURL, NULL); 77 | if (currentItemURL && CFEqual(currentItemURL, wantedURL)) { 78 | CFRelease(currentItemURL); 79 | return item; 80 | } 81 | if (currentItemURL) 82 | CFRelease(currentItemURL); 83 | } 84 | 85 | return NULL; 86 | } 87 | 88 | - (BOOL) willLaunchAtLogin: (NSURL*) itemURL 89 | { 90 | return !![self findItemWithURL:itemURL inFileList:loginItems]; 91 | } 92 | 93 | - (void) setLaunchAtLogin: (BOOL) enabled forURL: (NSURL*) itemURL 94 | { 95 | LSSharedFileListItemRef appItem = [self findItemWithURL:itemURL inFileList:loginItems]; 96 | if (enabled && !appItem) { 97 | LSSharedFileListInsertItemURL(loginItems, kLSSharedFileListItemBeforeFirst, 98 | NULL, NULL, (CFURLRef)itemURL, NULL, NULL); 99 | } else if (!enabled && appItem) 100 | LSSharedFileListItemRemove(loginItems, appItem); 101 | } 102 | 103 | #pragma mark Basic Interface 104 | 105 | - (NSURL*) appURL 106 | { 107 | return [NSURL fileURLWithPath:[[NSBundle mainBundle] bundlePath]]; 108 | } 109 | 110 | - (void) setLaunchAtLogin: (BOOL) enabled 111 | { 112 | [self willChangeValueForKey:StartAtLoginKey]; 113 | [self setLaunchAtLogin:enabled forURL:[self appURL]]; 114 | [self didChangeValueForKey:StartAtLoginKey]; 115 | } 116 | 117 | - (BOOL) launchAtLogin 118 | { 119 | return [self willLaunchAtLogin:[self appURL]]; 120 | } 121 | 122 | @end 123 | -------------------------------------------------------------------------------- /IMLight.xcodeproj/xcuserdata/BlahGeek.xcuserdatad/xcschemes/IMLight.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 29 | 35 | 36 | 37 | 38 | 39 | 44 | 45 | 47 | 53 | 54 | 55 | 56 | 57 | 63 | 64 | 65 | 66 | 75 | 76 | 82 | 83 | 84 | 85 | 86 | 87 | 93 | 94 | 100 | 101 | 102 | 103 | 105 | 106 | 109 | 110 | 111 | -------------------------------------------------------------------------------- /IMLight/LED.m: -------------------------------------------------------------------------------- 1 | // 2 | // LED.m 3 | // IMMonitor 4 | // 5 | // Created by BlahGeek on 14/11/6. 6 | // Copyright (c) 2014年 BlahGeek. All rights reserved. 7 | // 8 | 9 | #import 10 | #include 11 | #include 12 | #include "LED.h" 13 | 14 | static NSMutableDictionary* _CreateMatchingDict(Boolean isDeviceNotElement, 15 | uint32_t inUsagePage, 16 | uint32_t inUsage); 17 | 18 | static NSMutableDictionary* _CreateMatchingDict(Boolean isDeviceNotElement, 19 | uint32_t inUsagePage, 20 | uint32_t inUsage) 21 | { 22 | NSMutableDictionary* dic = [[NSMutableDictionary alloc] initWithObjectsAndKeys: 23 | [NSNumber numberWithUnsignedInt:inUsagePage], 24 | (isDeviceNotElement)? 25 | CFSTR(kIOHIDDeviceUsagePageKey): 26 | CFSTR(kIOHIDElementUsagePageKey), 27 | NULL]; 28 | if (inUsage) [dic setObject:[NSNumber numberWithUnsignedInt:inUsage] 29 | forKey:(isDeviceNotElement)? 30 | (NSString*)CFSTR(kIOHIDDeviceUsageKey): 31 | (NSString*)CFSTR(kIOHIDElementUsageKey)]; 32 | return dic; 33 | } 34 | 35 | @implementation LED 36 | -(id)init 37 | { 38 | return [self initWithUsage:kHIDUsage_LED_CapsLock]; 39 | } 40 | 41 | -(id)initWithUsage:(uint32_t)usage 42 | { 43 | self = [super init]; 44 | device_count = 0; 45 | 46 | CFSetRef deviceCFSetRef = NULL; 47 | IOHIDDeviceRef* refs = NULL; 48 | // create a IO HID Manager reference 49 | IOHIDManagerRef mgr = IOHIDManagerCreate(kCFAllocatorDefault, kIOHIDOptionsTypeNone); 50 | if(!mgr) 51 | return self; 52 | // Create a device matching dictionary 53 | NSDictionary* dic = _CreateMatchingDict(true, kHIDPage_GenericDesktop, 54 | kHIDUsage_GD_Keyboard); 55 | require(dic, Oops); 56 | // set the HID device matching dictionary 57 | IOHIDManagerSetDeviceMatching(mgr, (__bridge CFDictionaryRef)dic); 58 | // [dic release]; 59 | // Now open the IO HID Manager reference 60 | IOReturn err = IOHIDManagerOpen(mgr, kIOHIDOptionsTypeNone); 61 | require_noerr(err, Oops); 62 | // and copy out its devices 63 | deviceCFSetRef = IOHIDManagerCopyDevices(mgr); 64 | require(deviceCFSetRef, Oops); 65 | // how many devices in the set? 66 | CFIndex deviceIndex, deviceCount = CFSetGetCount(deviceCFSetRef); 67 | // allocate a block of memory to extact the device refs from the set into 68 | refs = malloc(sizeof(IOHIDDeviceRef) * deviceCount); 69 | require(refs, Oops); 70 | // now extract the device refs from the set 71 | CFSetGetValues(deviceCFSetRef, (const void**)refs); 72 | // before we get into the device loop set up element matching dictionary 73 | dic = _CreateMatchingDict(false, kHIDPage_LEDs, 0); 74 | require(dic, Oops); 75 | for (deviceIndex = 0; deviceIndex < deviceCount; deviceIndex++) 76 | { 77 | // if this isn't a keyboard device... 78 | if (!IOHIDDeviceConformsTo(refs[deviceIndex], kHIDPage_GenericDesktop, 79 | kHIDUsage_GD_Keyboard)) 80 | { 81 | //printf("skipping nonconforming device at %d\n", deviceIndex); 82 | continue; // ...skip it 83 | } 84 | // copy all the elements 85 | CFArrayRef elements = IOHIDDeviceCopyMatchingElements(refs[deviceIndex], 86 | (__bridge CFDictionaryRef)dic, 87 | kIOHIDOptionsTypeNone); 88 | if(!elements) 89 | continue; 90 | // iterate over all the elements 91 | CFIndex i, n = CFArrayGetCount(elements); 92 | for (i = 0; i < n; i++) 93 | { 94 | IOHIDElementRef element = (IOHIDElementRef)CFArrayGetValueAtIndex(elements, i); 95 | if(!element) 96 | continue; 97 | uint32_t usagePage = IOHIDElementGetUsagePage(element); 98 | // if this isn't an LED element, skip it 99 | if (kHIDPage_LEDs != usagePage) continue; 100 | uint32_t elusage = IOHIDElementGetUsage(element); 101 | if (elusage == usage) 102 | { 103 | ledDevices[device_count] = (IOHIDDeviceRef)CFRetain(refs[deviceIndex]); 104 | ledElements[device_count++] = (IOHIDElementRef)CFRetain(element); 105 | break; 106 | } 107 | next_element: ; 108 | continue; 109 | } 110 | next_device: ; 111 | if (elements) CFRelease(elements); 112 | continue; 113 | } 114 | if (mgr) CFRelease(mgr); 115 | // [dic release]; 116 | Oops: ; 117 | if (deviceCFSetRef) CFRelease(deviceCFSetRef); 118 | if (refs) free(refs); 119 | 120 | NSLog(@"LED Inited, %d devices found", device_count); 121 | return self; 122 | } 123 | 124 | -(void)dealloc 125 | { 126 | for(int i = 0 ; i < device_count ; i += 1) { 127 | 128 | if (ledDevices[i]) CFRelease(ledDevices[i]); 129 | if (ledElements[i]) CFRelease(ledElements[i]); 130 | } 131 | // [super dealloc]; 132 | } 133 | 134 | -(void)setValue:(SInt32)value 135 | { 136 | for(int i = 0 ; i < device_count ; i += 1) { 137 | if (ledDevices[i] && ledElements[i]) 138 | { 139 | IOReturn err = IOHIDDeviceOpen(ledDevices[i], 0); 140 | if (!err) 141 | { 142 | // create the IO HID Value to be sent to this LED element 143 | uint64_t timestamp = 0; 144 | IOHIDValueRef val = IOHIDValueCreateWithIntegerValue(kCFAllocatorDefault, 145 | ledElements[i], timestamp, 146 | value); 147 | if (val) 148 | { 149 | // now set it on the device 150 | err = IOHIDDeviceSetValue(ledDevices[i], ledElements[i], val); 151 | CFRelease(val); 152 | } 153 | IOHIDDeviceClose(ledDevices[i], 0); 154 | } 155 | if (err) printf("error 0x%X\n", err); 156 | } 157 | } 158 | 159 | } 160 | @end -------------------------------------------------------------------------------- /IMLight.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | DA6182EB1A0B88D600735728 /* Credits.rtf in Resources */ = {isa = PBXBuildFile; fileRef = DA6182EA1A0B88D600735728 /* Credits.rtf */; }; 11 | DAA79EA91A0B65810094CD1A /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = DAA79EA81A0B65810094CD1A /* AppDelegate.m */; }; 12 | DAA79EAB1A0B65810094CD1A /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = DAA79EAA1A0B65810094CD1A /* main.m */; }; 13 | DAA79EAD1A0B65810094CD1A /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = DAA79EAC1A0B65810094CD1A /* Images.xcassets */; }; 14 | DAA79EB01A0B65810094CD1A /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = DAA79EAE1A0B65810094CD1A /* MainMenu.xib */; }; 15 | DAA79EBC1A0B65810094CD1A /* IMLightTests.m in Sources */ = {isa = PBXBuildFile; fileRef = DAA79EBB1A0B65810094CD1A /* IMLightTests.m */; }; 16 | DAA79EC61A0B68850094CD1A /* LED.m in Sources */ = {isa = PBXBuildFile; fileRef = DAA79EC51A0B68850094CD1A /* LED.m */; }; 17 | DAA79ECE1A0B7F6A0094CD1A /* LaunchAtLoginController.m in Sources */ = {isa = PBXBuildFile; fileRef = DAA79ECC1A0B7F6A0094CD1A /* LaunchAtLoginController.m */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; 18 | DAA79ECF1A0B7F6A0094CD1A /* README.md in Sources */ = {isa = PBXBuildFile; fileRef = DAA79ECD1A0B7F6A0094CD1A /* README.md */; }; 19 | /* End PBXBuildFile section */ 20 | 21 | /* Begin PBXContainerItemProxy section */ 22 | DAA79EB61A0B65810094CD1A /* PBXContainerItemProxy */ = { 23 | isa = PBXContainerItemProxy; 24 | containerPortal = DAA79E9A1A0B65810094CD1A /* Project object */; 25 | proxyType = 1; 26 | remoteGlobalIDString = DAA79EA11A0B65810094CD1A; 27 | remoteInfo = IMLight; 28 | }; 29 | /* End PBXContainerItemProxy section */ 30 | 31 | /* Begin PBXFileReference section */ 32 | DA6182E91A0B851F00735728 /* IMLight.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.xml; path = IMLight.entitlements; sourceTree = ""; }; 33 | DA6182EA1A0B88D600735728 /* Credits.rtf */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.rtf; path = Credits.rtf; sourceTree = ""; }; 34 | DAA79EA21A0B65810094CD1A /* IMLight.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = IMLight.app; sourceTree = BUILT_PRODUCTS_DIR; }; 35 | DAA79EA61A0B65810094CD1A /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 36 | DAA79EA71A0B65810094CD1A /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; 37 | DAA79EA81A0B65810094CD1A /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; 38 | DAA79EAA1A0B65810094CD1A /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 39 | DAA79EAC1A0B65810094CD1A /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; }; 40 | DAA79EAF1A0B65810094CD1A /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/MainMenu.xib; sourceTree = ""; }; 41 | DAA79EB51A0B65810094CD1A /* IMLightTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = IMLightTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 42 | DAA79EBA1A0B65810094CD1A /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 43 | DAA79EBB1A0B65810094CD1A /* IMLightTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = IMLightTests.m; sourceTree = ""; }; 44 | DAA79EC51A0B68850094CD1A /* LED.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = LED.m; sourceTree = ""; }; 45 | DAA79EC71A0B688B0094CD1A /* LED.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = LED.h; sourceTree = ""; }; 46 | DAA79ECB1A0B7F6A0094CD1A /* LaunchAtLoginController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LaunchAtLoginController.h; sourceTree = ""; }; 47 | DAA79ECC1A0B7F6A0094CD1A /* LaunchAtLoginController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = LaunchAtLoginController.m; sourceTree = ""; }; 48 | DAA79ECD1A0B7F6A0094CD1A /* README.md */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = net.daringfireball.markdown; path = README.md; sourceTree = ""; }; 49 | /* End PBXFileReference section */ 50 | 51 | /* Begin PBXFrameworksBuildPhase section */ 52 | DAA79E9F1A0B65810094CD1A /* Frameworks */ = { 53 | isa = PBXFrameworksBuildPhase; 54 | buildActionMask = 2147483647; 55 | files = ( 56 | ); 57 | runOnlyForDeploymentPostprocessing = 0; 58 | }; 59 | DAA79EB21A0B65810094CD1A /* Frameworks */ = { 60 | isa = PBXFrameworksBuildPhase; 61 | buildActionMask = 2147483647; 62 | files = ( 63 | ); 64 | runOnlyForDeploymentPostprocessing = 0; 65 | }; 66 | /* End PBXFrameworksBuildPhase section */ 67 | 68 | /* Begin PBXGroup section */ 69 | DAA79E991A0B65810094CD1A = { 70 | isa = PBXGroup; 71 | children = ( 72 | DAA79EA41A0B65810094CD1A /* IMLight */, 73 | DAA79EB81A0B65810094CD1A /* IMLightTests */, 74 | DAA79EA31A0B65810094CD1A /* Products */, 75 | ); 76 | sourceTree = ""; 77 | }; 78 | DAA79EA31A0B65810094CD1A /* Products */ = { 79 | isa = PBXGroup; 80 | children = ( 81 | DAA79EA21A0B65810094CD1A /* IMLight.app */, 82 | DAA79EB51A0B65810094CD1A /* IMLightTests.xctest */, 83 | ); 84 | name = Products; 85 | sourceTree = ""; 86 | }; 87 | DAA79EA41A0B65810094CD1A /* IMLight */ = { 88 | isa = PBXGroup; 89 | children = ( 90 | DA6182E91A0B851F00735728 /* IMLight.entitlements */, 91 | DAA79ED01A0B7F740094CD1A /* LaunchAtLoginController */, 92 | DAA79EC71A0B688B0094CD1A /* LED.h */, 93 | DAA79EC51A0B68850094CD1A /* LED.m */, 94 | DAA79EA71A0B65810094CD1A /* AppDelegate.h */, 95 | DAA79EA81A0B65810094CD1A /* AppDelegate.m */, 96 | DAA79EAC1A0B65810094CD1A /* Images.xcassets */, 97 | DAA79EAE1A0B65810094CD1A /* MainMenu.xib */, 98 | DAA79EA51A0B65810094CD1A /* Supporting Files */, 99 | ); 100 | path = IMLight; 101 | sourceTree = ""; 102 | }; 103 | DAA79EA51A0B65810094CD1A /* Supporting Files */ = { 104 | isa = PBXGroup; 105 | children = ( 106 | DAA79EA61A0B65810094CD1A /* Info.plist */, 107 | DAA79EAA1A0B65810094CD1A /* main.m */, 108 | DA6182EA1A0B88D600735728 /* Credits.rtf */, 109 | ); 110 | name = "Supporting Files"; 111 | sourceTree = ""; 112 | }; 113 | DAA79EB81A0B65810094CD1A /* IMLightTests */ = { 114 | isa = PBXGroup; 115 | children = ( 116 | DAA79EBB1A0B65810094CD1A /* IMLightTests.m */, 117 | DAA79EB91A0B65810094CD1A /* Supporting Files */, 118 | ); 119 | path = IMLightTests; 120 | sourceTree = ""; 121 | }; 122 | DAA79EB91A0B65810094CD1A /* Supporting Files */ = { 123 | isa = PBXGroup; 124 | children = ( 125 | DAA79EBA1A0B65810094CD1A /* Info.plist */, 126 | ); 127 | name = "Supporting Files"; 128 | sourceTree = ""; 129 | }; 130 | DAA79ED01A0B7F740094CD1A /* LaunchAtLoginController */ = { 131 | isa = PBXGroup; 132 | children = ( 133 | DAA79ECB1A0B7F6A0094CD1A /* LaunchAtLoginController.h */, 134 | DAA79ECC1A0B7F6A0094CD1A /* LaunchAtLoginController.m */, 135 | DAA79ECD1A0B7F6A0094CD1A /* README.md */, 136 | ); 137 | name = LaunchAtLoginController; 138 | sourceTree = ""; 139 | }; 140 | /* End PBXGroup section */ 141 | 142 | /* Begin PBXNativeTarget section */ 143 | DAA79EA11A0B65810094CD1A /* IMLight */ = { 144 | isa = PBXNativeTarget; 145 | buildConfigurationList = DAA79EBF1A0B65810094CD1A /* Build configuration list for PBXNativeTarget "IMLight" */; 146 | buildPhases = ( 147 | DAA79E9E1A0B65810094CD1A /* Sources */, 148 | DAA79E9F1A0B65810094CD1A /* Frameworks */, 149 | DAA79EA01A0B65810094CD1A /* Resources */, 150 | ); 151 | buildRules = ( 152 | ); 153 | dependencies = ( 154 | ); 155 | name = IMLight; 156 | productName = IMLight; 157 | productReference = DAA79EA21A0B65810094CD1A /* IMLight.app */; 158 | productType = "com.apple.product-type.application"; 159 | }; 160 | DAA79EB41A0B65810094CD1A /* IMLightTests */ = { 161 | isa = PBXNativeTarget; 162 | buildConfigurationList = DAA79EC21A0B65810094CD1A /* Build configuration list for PBXNativeTarget "IMLightTests" */; 163 | buildPhases = ( 164 | DAA79EB11A0B65810094CD1A /* Sources */, 165 | DAA79EB21A0B65810094CD1A /* Frameworks */, 166 | DAA79EB31A0B65810094CD1A /* Resources */, 167 | ); 168 | buildRules = ( 169 | ); 170 | dependencies = ( 171 | DAA79EB71A0B65810094CD1A /* PBXTargetDependency */, 172 | ); 173 | name = IMLightTests; 174 | productName = IMLightTests; 175 | productReference = DAA79EB51A0B65810094CD1A /* IMLightTests.xctest */; 176 | productType = "com.apple.product-type.bundle.unit-test"; 177 | }; 178 | /* End PBXNativeTarget section */ 179 | 180 | /* Begin PBXProject section */ 181 | DAA79E9A1A0B65810094CD1A /* Project object */ = { 182 | isa = PBXProject; 183 | attributes = { 184 | LastUpgradeCheck = 0610; 185 | ORGANIZATIONNAME = BlahGeek; 186 | TargetAttributes = { 187 | DAA79EA11A0B65810094CD1A = { 188 | CreatedOnToolsVersion = 6.1; 189 | SystemCapabilities = { 190 | com.apple.Sandbox = { 191 | enabled = 0; 192 | }; 193 | }; 194 | }; 195 | DAA79EB41A0B65810094CD1A = { 196 | CreatedOnToolsVersion = 6.1; 197 | TestTargetID = DAA79EA11A0B65810094CD1A; 198 | }; 199 | }; 200 | }; 201 | buildConfigurationList = DAA79E9D1A0B65810094CD1A /* Build configuration list for PBXProject "IMLight" */; 202 | compatibilityVersion = "Xcode 3.2"; 203 | developmentRegion = English; 204 | hasScannedForEncodings = 0; 205 | knownRegions = ( 206 | en, 207 | Base, 208 | ); 209 | mainGroup = DAA79E991A0B65810094CD1A; 210 | productRefGroup = DAA79EA31A0B65810094CD1A /* Products */; 211 | projectDirPath = ""; 212 | projectRoot = ""; 213 | targets = ( 214 | DAA79EA11A0B65810094CD1A /* IMLight */, 215 | DAA79EB41A0B65810094CD1A /* IMLightTests */, 216 | ); 217 | }; 218 | /* End PBXProject section */ 219 | 220 | /* Begin PBXResourcesBuildPhase section */ 221 | DAA79EA01A0B65810094CD1A /* Resources */ = { 222 | isa = PBXResourcesBuildPhase; 223 | buildActionMask = 2147483647; 224 | files = ( 225 | DAA79EAD1A0B65810094CD1A /* Images.xcassets in Resources */, 226 | DA6182EB1A0B88D600735728 /* Credits.rtf in Resources */, 227 | DAA79EB01A0B65810094CD1A /* MainMenu.xib in Resources */, 228 | ); 229 | runOnlyForDeploymentPostprocessing = 0; 230 | }; 231 | DAA79EB31A0B65810094CD1A /* Resources */ = { 232 | isa = PBXResourcesBuildPhase; 233 | buildActionMask = 2147483647; 234 | files = ( 235 | ); 236 | runOnlyForDeploymentPostprocessing = 0; 237 | }; 238 | /* End PBXResourcesBuildPhase section */ 239 | 240 | /* Begin PBXSourcesBuildPhase section */ 241 | DAA79E9E1A0B65810094CD1A /* Sources */ = { 242 | isa = PBXSourcesBuildPhase; 243 | buildActionMask = 2147483647; 244 | files = ( 245 | DAA79EC61A0B68850094CD1A /* LED.m in Sources */, 246 | DAA79ECE1A0B7F6A0094CD1A /* LaunchAtLoginController.m in Sources */, 247 | DAA79ECF1A0B7F6A0094CD1A /* README.md in Sources */, 248 | DAA79EAB1A0B65810094CD1A /* main.m in Sources */, 249 | DAA79EA91A0B65810094CD1A /* AppDelegate.m in Sources */, 250 | ); 251 | runOnlyForDeploymentPostprocessing = 0; 252 | }; 253 | DAA79EB11A0B65810094CD1A /* Sources */ = { 254 | isa = PBXSourcesBuildPhase; 255 | buildActionMask = 2147483647; 256 | files = ( 257 | DAA79EBC1A0B65810094CD1A /* IMLightTests.m in Sources */, 258 | ); 259 | runOnlyForDeploymentPostprocessing = 0; 260 | }; 261 | /* End PBXSourcesBuildPhase section */ 262 | 263 | /* Begin PBXTargetDependency section */ 264 | DAA79EB71A0B65810094CD1A /* PBXTargetDependency */ = { 265 | isa = PBXTargetDependency; 266 | target = DAA79EA11A0B65810094CD1A /* IMLight */; 267 | targetProxy = DAA79EB61A0B65810094CD1A /* PBXContainerItemProxy */; 268 | }; 269 | /* End PBXTargetDependency section */ 270 | 271 | /* Begin PBXVariantGroup section */ 272 | DAA79EAE1A0B65810094CD1A /* MainMenu.xib */ = { 273 | isa = PBXVariantGroup; 274 | children = ( 275 | DAA79EAF1A0B65810094CD1A /* Base */, 276 | ); 277 | name = MainMenu.xib; 278 | sourceTree = ""; 279 | }; 280 | /* End PBXVariantGroup section */ 281 | 282 | /* Begin XCBuildConfiguration section */ 283 | DAA79EBD1A0B65810094CD1A /* Debug */ = { 284 | isa = XCBuildConfiguration; 285 | buildSettings = { 286 | ALWAYS_SEARCH_USER_PATHS = NO; 287 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 288 | CLANG_CXX_LIBRARY = "libc++"; 289 | CLANG_ENABLE_MODULES = YES; 290 | CLANG_ENABLE_OBJC_ARC = YES; 291 | CLANG_WARN_BOOL_CONVERSION = YES; 292 | CLANG_WARN_CONSTANT_CONVERSION = YES; 293 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 294 | CLANG_WARN_EMPTY_BODY = YES; 295 | CLANG_WARN_ENUM_CONVERSION = YES; 296 | CLANG_WARN_INT_CONVERSION = YES; 297 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 298 | CLANG_WARN_UNREACHABLE_CODE = YES; 299 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 300 | CODE_SIGN_IDENTITY = "-"; 301 | COPY_PHASE_STRIP = NO; 302 | ENABLE_STRICT_OBJC_MSGSEND = YES; 303 | GCC_C_LANGUAGE_STANDARD = gnu99; 304 | GCC_DYNAMIC_NO_PIC = NO; 305 | GCC_OPTIMIZATION_LEVEL = 0; 306 | GCC_PREPROCESSOR_DEFINITIONS = ( 307 | "DEBUG=1", 308 | "$(inherited)", 309 | ); 310 | GCC_SYMBOLS_PRIVATE_EXTERN = NO; 311 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 312 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 313 | GCC_WARN_UNDECLARED_SELECTOR = YES; 314 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 315 | GCC_WARN_UNUSED_FUNCTION = YES; 316 | GCC_WARN_UNUSED_VARIABLE = YES; 317 | MACOSX_DEPLOYMENT_TARGET = 10.10; 318 | MTL_ENABLE_DEBUG_INFO = YES; 319 | ONLY_ACTIVE_ARCH = YES; 320 | SDKROOT = macosx; 321 | }; 322 | name = Debug; 323 | }; 324 | DAA79EBE1A0B65810094CD1A /* Release */ = { 325 | isa = XCBuildConfiguration; 326 | buildSettings = { 327 | ALWAYS_SEARCH_USER_PATHS = NO; 328 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 329 | CLANG_CXX_LIBRARY = "libc++"; 330 | CLANG_ENABLE_MODULES = YES; 331 | CLANG_ENABLE_OBJC_ARC = YES; 332 | CLANG_WARN_BOOL_CONVERSION = YES; 333 | CLANG_WARN_CONSTANT_CONVERSION = YES; 334 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 335 | CLANG_WARN_EMPTY_BODY = YES; 336 | CLANG_WARN_ENUM_CONVERSION = YES; 337 | CLANG_WARN_INT_CONVERSION = YES; 338 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 339 | CLANG_WARN_UNREACHABLE_CODE = YES; 340 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 341 | CODE_SIGN_IDENTITY = "-"; 342 | COPY_PHASE_STRIP = YES; 343 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 344 | ENABLE_NS_ASSERTIONS = NO; 345 | ENABLE_STRICT_OBJC_MSGSEND = YES; 346 | GCC_C_LANGUAGE_STANDARD = gnu99; 347 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 348 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 349 | GCC_WARN_UNDECLARED_SELECTOR = YES; 350 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 351 | GCC_WARN_UNUSED_FUNCTION = YES; 352 | GCC_WARN_UNUSED_VARIABLE = YES; 353 | MACOSX_DEPLOYMENT_TARGET = 10.10; 354 | MTL_ENABLE_DEBUG_INFO = NO; 355 | SDKROOT = macosx; 356 | }; 357 | name = Release; 358 | }; 359 | DAA79EC01A0B65810094CD1A /* Debug */ = { 360 | isa = XCBuildConfiguration; 361 | buildSettings = { 362 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 363 | COMBINE_HIDPI_IMAGES = YES; 364 | INFOPLIST_FILE = IMLight/Info.plist; 365 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; 366 | PRODUCT_NAME = "$(TARGET_NAME)"; 367 | }; 368 | name = Debug; 369 | }; 370 | DAA79EC11A0B65810094CD1A /* Release */ = { 371 | isa = XCBuildConfiguration; 372 | buildSettings = { 373 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 374 | COMBINE_HIDPI_IMAGES = YES; 375 | INFOPLIST_FILE = IMLight/Info.plist; 376 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; 377 | PRODUCT_NAME = "$(TARGET_NAME)"; 378 | }; 379 | name = Release; 380 | }; 381 | DAA79EC31A0B65810094CD1A /* Debug */ = { 382 | isa = XCBuildConfiguration; 383 | buildSettings = { 384 | BUNDLE_LOADER = "$(TEST_HOST)"; 385 | COMBINE_HIDPI_IMAGES = YES; 386 | FRAMEWORK_SEARCH_PATHS = ( 387 | "$(DEVELOPER_FRAMEWORKS_DIR)", 388 | "$(inherited)", 389 | ); 390 | GCC_PREPROCESSOR_DEFINITIONS = ( 391 | "DEBUG=1", 392 | "$(inherited)", 393 | ); 394 | INFOPLIST_FILE = IMLightTests/Info.plist; 395 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; 396 | PRODUCT_NAME = "$(TARGET_NAME)"; 397 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/IMLight.app/Contents/MacOS/IMLight"; 398 | }; 399 | name = Debug; 400 | }; 401 | DAA79EC41A0B65810094CD1A /* Release */ = { 402 | isa = XCBuildConfiguration; 403 | buildSettings = { 404 | BUNDLE_LOADER = "$(TEST_HOST)"; 405 | COMBINE_HIDPI_IMAGES = YES; 406 | FRAMEWORK_SEARCH_PATHS = ( 407 | "$(DEVELOPER_FRAMEWORKS_DIR)", 408 | "$(inherited)", 409 | ); 410 | INFOPLIST_FILE = IMLightTests/Info.plist; 411 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; 412 | PRODUCT_NAME = "$(TARGET_NAME)"; 413 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/IMLight.app/Contents/MacOS/IMLight"; 414 | }; 415 | name = Release; 416 | }; 417 | /* End XCBuildConfiguration section */ 418 | 419 | /* Begin XCConfigurationList section */ 420 | DAA79E9D1A0B65810094CD1A /* Build configuration list for PBXProject "IMLight" */ = { 421 | isa = XCConfigurationList; 422 | buildConfigurations = ( 423 | DAA79EBD1A0B65810094CD1A /* Debug */, 424 | DAA79EBE1A0B65810094CD1A /* Release */, 425 | ); 426 | defaultConfigurationIsVisible = 0; 427 | defaultConfigurationName = Release; 428 | }; 429 | DAA79EBF1A0B65810094CD1A /* Build configuration list for PBXNativeTarget "IMLight" */ = { 430 | isa = XCConfigurationList; 431 | buildConfigurations = ( 432 | DAA79EC01A0B65810094CD1A /* Debug */, 433 | DAA79EC11A0B65810094CD1A /* Release */, 434 | ); 435 | defaultConfigurationIsVisible = 0; 436 | defaultConfigurationName = Release; 437 | }; 438 | DAA79EC21A0B65810094CD1A /* Build configuration list for PBXNativeTarget "IMLightTests" */ = { 439 | isa = XCConfigurationList; 440 | buildConfigurations = ( 441 | DAA79EC31A0B65810094CD1A /* Debug */, 442 | DAA79EC41A0B65810094CD1A /* Release */, 443 | ); 444 | defaultConfigurationIsVisible = 0; 445 | defaultConfigurationName = Release; 446 | }; 447 | /* End XCConfigurationList section */ 448 | }; 449 | rootObject = DAA79E9A1A0B65810094CD1A /* Project object */; 450 | } 451 | -------------------------------------------------------------------------------- /IMLight/Base.lproj/MainMenu.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | 209 | 210 | 211 | 212 | 213 | 214 | 215 | 216 | 217 | 218 | 219 | 220 | 221 | 222 | 223 | 224 | 225 | 226 | 227 | 228 | 229 | 230 | 231 | 232 | 233 | 234 | 235 | 236 | 237 | 238 | 239 | 240 | 241 | 242 | 243 | 244 | 245 | 246 | 247 | 248 | 249 | 250 | 251 | 252 | 253 | 254 | 255 | 256 | 257 | 258 | 259 | 260 | 261 | 262 | 263 | 264 | 265 | 266 | 267 | 268 | 269 | 270 | 271 | 272 | 273 | 274 | 275 | 276 | 277 | 278 | 279 | 280 | 281 | 282 | 283 | 284 | 285 | 286 | 287 | 288 | 289 | 290 | 291 | 292 | 293 | 294 | 295 | 296 | 297 | 298 | 299 | 300 | 301 | 302 | 303 | 304 | 305 | 306 | 307 | 308 | 309 | 310 | 311 | 312 | 313 | 314 | 315 | 316 | 317 | 318 | 319 | 320 | 321 | 322 | 323 | 324 | 325 | 326 | 327 | 328 | 329 | 330 | 331 | 332 | 333 | 334 | 335 | 336 | 337 | 338 | 339 | 340 | 341 | 342 | 343 | 344 | 345 | 346 | 347 | 348 | 349 | 350 | 351 | 352 | 353 | 354 | 355 | 356 | 357 | 358 | 359 | 360 | 361 | 362 | 363 | 364 | 365 | 366 | 367 | 368 | 369 | 370 | 371 | 372 | 373 | 374 | 375 | 376 | 377 | 378 | 379 | 380 | 381 | 382 | 383 | 384 | 385 | 386 | 387 | 388 | 389 | 390 | 391 | 392 | 393 | 394 | 395 | 396 | 397 | 398 | 399 | 400 | 401 | 402 | 403 | 404 | 405 | 406 | 407 | 408 | 409 | 410 | 411 | 412 | 413 | 414 | 415 | 416 | 417 | 418 | 419 | 420 | 421 | 422 | 423 | 424 | 425 | 426 | 427 | 428 | 429 | 430 | 431 | 432 | 433 | 434 | 435 | 436 | 437 | 438 | 439 | 440 | 441 | 442 | 443 | 444 | 445 | 446 | 447 | 448 | 449 | 450 | 451 | 452 | 453 | 454 | 455 | 456 | 457 | 458 | 459 | 460 | 461 | 462 | 463 | 464 | 465 | 466 | 467 | 468 | 469 | 470 | 471 | 472 | 473 | 474 | 475 | 476 | 477 | 478 | 479 | 480 | 481 | 482 | 483 | 484 | 485 | 486 | 487 | 488 | 489 | 490 | 491 | 492 | 493 | 494 | 495 | 496 | 497 | 498 | 499 | 500 | 501 | 502 | 503 | 504 | 505 | 506 | 507 | 508 | 509 | 510 | 511 | 512 | 513 | 514 | 515 | 516 | 517 | 518 | 519 | 520 | 521 | 522 | 523 | 524 | 525 | 526 | 527 | 528 | 529 | 530 | 531 | 532 | 533 | 534 | 535 | 536 | 537 | 538 | 539 | Default 540 | 541 | 542 | 543 | 544 | 545 | 546 | Left to Right 547 | 548 | 549 | 550 | 551 | 552 | 553 | Right to Left 554 | 555 | 556 | 557 | 558 | 559 | 560 | 561 | 562 | 563 | 564 | Default 565 | 566 | 567 | 568 | 569 | 570 | 571 | Left to Right 572 | 573 | 574 | 575 | 576 | 577 | 578 | Right to Left 579 | 580 | 581 | 582 | 583 | 584 | 585 | 586 | 587 | 588 | 589 | 590 | 591 | 592 | 593 | 594 | 595 | 596 | 597 | 598 | 599 | 600 | 601 | 602 | 603 | 604 | 605 | 606 | 607 | 608 | 609 | 610 | 611 | 612 | 613 | 614 | 615 | 616 | 617 | 618 | 619 | 620 | 621 | 622 | 623 | 624 | 625 | 626 | 627 | 628 | 629 | 630 | 631 | 632 | 633 | 634 | 635 | 636 | 637 | 638 | 639 | 640 | 641 | 642 | 643 | 644 | 645 | 646 | 647 | 648 | 649 | 650 | 651 | 652 | 653 | 654 | 655 | 656 | 657 | 658 | 659 | 660 | 661 | 662 | 663 | 664 | 665 | 666 | 667 | 668 | 669 | 670 | 671 | 672 | 673 | 674 | 675 | 676 | 677 | 678 | 679 | 680 | 681 | 682 | 683 | 684 | 685 | 686 | 687 | 688 | 689 | 690 | 691 | 692 | 693 | 694 | 695 | 696 | --------------------------------------------------------------------------------