├── .gitignore ├── AppPolice Tests ├── AppPolice Tests-Info.plist ├── AppPolice Tests-Prefix.pch ├── AppPolice_Tests.m └── en.lproj │ └── InfoPlist.strings ├── AppPolice.xcodeproj ├── project.pbxproj ├── project.xcworkspace │ ├── contents.xcworkspacedata │ ├── xcshareddata │ │ ├── AppPolice.xccheckout │ │ └── AppPolice.xcscmblueprint │ └── xcuserdata │ │ └── objective.xcuserdatad │ │ ├── UserInterfaceState.xcuserstate │ │ └── WorkspaceSettings.xcsettings └── xcuserdata │ └── objective.xcuserdatad │ ├── xcdebugger │ ├── Breakpoints.xcbkptlist │ └── Breakpoints_v2.xcbkptlist │ └── xcschemes │ ├── AppPolice Tests.xcscheme │ ├── AppPolice.xcscheme │ └── xcschememanagement.plist ├── AppPolice ├── AppDelegate.h ├── AppDelegate.m ├── AppInspector │ ├── AppInspector.h │ ├── AppInspector.m │ ├── AppLimitHintView.h │ ├── AppLimitHintView.m │ ├── AppLimitSliderCell.h │ ├── AppLimitSliderCell.m │ ├── AppLoadLevelIndicator.h │ └── AppLoadLevelIndicator.m ├── AppPolice-Info.plist ├── AppPolice-Prefix.pch ├── AppPolice.entitlements ├── C │ ├── app_inspector_c.c │ ├── app_inspector_c.h │ ├── proc_cpulim.c │ ├── proc_cpulim.h │ ├── selfprofile.c │ ├── selfprofile.h │ ├── subroutines.c │ └── subroutines.h ├── Media.xcassets │ └── AppPolice.appiconset │ │ ├── Contents.json │ │ ├── icon_128x128.png │ │ ├── icon_128x128@2x.png │ │ ├── icon_16x16.png │ │ ├── icon_16x16@2x.png │ │ ├── icon_256x256.png │ │ ├── icon_256x256@2x.png │ │ ├── icon_32x32.png │ │ ├── icon_32x32@2x.png │ │ ├── icon_512x512.png │ │ └── icon_512x512@2x.png ├── Other │ ├── APPreferencesController.h │ ├── APPreferencesController.m │ ├── NSMenu+APAdditions.h │ ├── NSMenu+APAdditions.m │ ├── NSMenuItem+APAdditions.h │ └── NSMenuItem+APAdditions.m ├── Statusbar │ ├── StatusbarMenuController.h │ └── StatusbarMenuController.m ├── UserDefaults.plist ├── en.lproj │ ├── APPreferencesWindow.xib │ ├── AppInspectorView.xib │ ├── Credits.rtf │ ├── InfoPlist.strings │ ├── Localizable.strings │ ├── MainMenu.xib │ └── PopoverContentView.strings ├── main.m └── status_icon.pdf ├── LICENSE └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | # OS generated files # 2 | ###################### 3 | .DS_Store 4 | .DS_Store? 5 | ._* 6 | .Spotlight-V100 7 | .Trashes 8 | ehthumbs.db 9 | Thumbs.db 10 | Resources/ 11 | 12 | *.swp 13 | -------------------------------------------------------------------------------- /AppPolice Tests/AppPolice Tests-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | ${EXECUTABLE_NAME} 9 | CFBundleIdentifier 10 | FloyLabs.${PRODUCT_NAME:rfc1034identifier} 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundlePackageType 14 | BNDL 15 | CFBundleShortVersionString 16 | 1.0 17 | CFBundleSignature 18 | ???? 19 | CFBundleVersion 20 | 1 21 | 22 | 23 | -------------------------------------------------------------------------------- /AppPolice Tests/AppPolice Tests-Prefix.pch: -------------------------------------------------------------------------------- 1 | // 2 | // Prefix header 3 | // 4 | // The contents of this file are implicitly included at the beginning of every source file. 5 | // 6 | 7 | #ifdef __OBJC__ 8 | #import 9 | #endif 10 | -------------------------------------------------------------------------------- /AppPolice Tests/AppPolice_Tests.m: -------------------------------------------------------------------------------- 1 | // 2 | // AppPolice_Tests.m 3 | // AppPolice Tests 4 | // 5 | // Created by Maksym on 9/5/13. 6 | // Copyright (c) 2013 Maksym Stefanchuk. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface AppPolice_Tests : XCTestCase 12 | 13 | @end 14 | 15 | @implementation AppPolice_Tests 16 | 17 | - (void)setUp { 18 | [super setUp]; 19 | 20 | // Set-up code here. 21 | } 22 | 23 | - (void)tearDown { 24 | // Tear-down code here. 25 | 26 | [super tearDown]; 27 | } 28 | 29 | - (void)testMenuIsCreating { 30 | NSMenu *menu = [[NSMenu alloc] init]; 31 | XCTAssertNotNil(menu, @"Menu could not be created."); 32 | } 33 | 34 | @end 35 | -------------------------------------------------------------------------------- /AppPolice Tests/en.lproj/InfoPlist.strings: -------------------------------------------------------------------------------- 1 | /* Localized versions of Info.plist keys */ 2 | 3 | -------------------------------------------------------------------------------- /AppPolice.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 34A22D421D1F6BFD0084E3F2 /* NSMenuItem+APAdditions.m in Sources */ = {isa = PBXBuildFile; fileRef = 34A22D411D1F6BFD0084E3F2 /* NSMenuItem+APAdditions.m */; }; 11 | 34A22D481D1F6DE30084E3F2 /* NSMenu+APAdditions.m in Sources */ = {isa = PBXBuildFile; fileRef = 34A22D471D1F6DE30084E3F2 /* NSMenu+APAdditions.m */; }; 12 | 34A22D4D1D20DDB60084E3F2 /* AppLoadLevelIndicator.m in Sources */ = {isa = PBXBuildFile; fileRef = 34A22D4C1D20DDB60084E3F2 /* AppLoadLevelIndicator.m */; }; 13 | 34A22D4F1D20EA0B0084E3F2 /* status_icon.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 34A22D4E1D20EA0B0084E3F2 /* status_icon.pdf */; }; 14 | A00C3B2E183F8937005E596C /* UserDefaults.plist in Resources */ = {isa = PBXBuildFile; fileRef = A00C3B2D183F8937005E596C /* UserDefaults.plist */; }; 15 | A00D28551803E85F00D71F71 /* AppLimitSliderCell.m in Sources */ = {isa = PBXBuildFile; fileRef = A00D28541803E85F00D71F71 /* AppLimitSliderCell.m */; }; 16 | A00FBF4D17DF54BF0083B482 /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A00FBF4C17DF54BF0083B482 /* QuartzCore.framework */; }; 17 | A0100693182106A10017296D /* app_inspector_c.c in Sources */ = {isa = PBXBuildFile; fileRef = A0100692182106A10017296D /* app_inspector_c.c */; }; 18 | A011916A1807E2EF004777D9 /* StatusbarMenuController.m in Sources */ = {isa = PBXBuildFile; fileRef = A01191691807E2EF004777D9 /* StatusbarMenuController.m */; }; 19 | A01453BE17833F5700FFFB39 /* AppInspectorView.xib in Resources */ = {isa = PBXBuildFile; fileRef = A0154E7F1782E05B008CF159 /* AppInspectorView.xib */; }; 20 | A0154E851782EC6F008CF159 /* AppInspector.m in Sources */ = {isa = PBXBuildFile; fileRef = A0154E841782E972008CF159 /* AppInspector.m */; }; 21 | A04FA3D3174D4BD9002E688C /* selfprofile.c in Sources */ = {isa = PBXBuildFile; fileRef = A04FA3D2174D4BD9002E688C /* selfprofile.c */; }; 22 | A063796817492AEF006F2347 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A063796717492AEF006F2347 /* Cocoa.framework */; }; 23 | A063797217492AEF006F2347 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = A063797017492AEF006F2347 /* InfoPlist.strings */; }; 24 | A063797417492AEF006F2347 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = A063797317492AEF006F2347 /* main.m */; }; 25 | A063797817492AEF006F2347 /* Credits.rtf in Resources */ = {isa = PBXBuildFile; fileRef = A063797617492AEF006F2347 /* Credits.rtf */; }; 26 | A063797B17492AEF006F2347 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = A063797A17492AEF006F2347 /* AppDelegate.m */; }; 27 | A063797E17492AF0006F2347 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = A063797C17492AF0006F2347 /* MainMenu.xib */; }; 28 | A063798717492D42006F2347 /* proc_cpulim.c in Sources */ = {isa = PBXBuildFile; fileRef = A063798617492D42006F2347 /* proc_cpulim.c */; }; 29 | A067A0B718369681003B677E /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = A067A0B918369681003B677E /* Localizable.strings */; }; 30 | A067A0C618369782003B677E /* Media.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = A067A0C518369782003B677E /* Media.xcassets */; }; 31 | A071B69517D8812500D3866E /* XCTest.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A071B69417D8812500D3866E /* XCTest.framework */; }; 32 | A071B69B17D8812500D3866E /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = A071B69917D8812500D3866E /* InfoPlist.strings */; }; 33 | A071B69D17D8812500D3866E /* AppPolice_Tests.m in Sources */ = {isa = PBXBuildFile; fileRef = A071B69C17D8812500D3866E /* AppPolice_Tests.m */; }; 34 | A07E4B90183CBD1900D773E5 /* APPreferencesController.m in Sources */ = {isa = PBXBuildFile; fileRef = A07E4B8E183CBD1900D773E5 /* APPreferencesController.m */; }; 35 | A0ADD314174A1438002BAADE /* subroutines.c in Sources */ = {isa = PBXBuildFile; fileRef = A0ADD313174A1438002BAADE /* subroutines.c */; }; 36 | A0BD1BEA183E10680054FC06 /* APPreferencesWindow.xib in Resources */ = {isa = PBXBuildFile; fileRef = A0BD1BEC183E10680054FC06 /* APPreferencesWindow.xib */; }; 37 | A0FFE0A91805D673007F510E /* AppLimitHintView.m in Sources */ = {isa = PBXBuildFile; fileRef = A0FFE0A81805D673007F510E /* AppLimitHintView.m */; }; 38 | /* End PBXBuildFile section */ 39 | 40 | /* Begin PBXContainerItemProxy section */ 41 | A071B69F17D8812500D3866E /* PBXContainerItemProxy */ = { 42 | isa = PBXContainerItemProxy; 43 | containerPortal = A063795C17492AEF006F2347 /* Project object */; 44 | proxyType = 1; 45 | remoteGlobalIDString = A063796317492AEF006F2347; 46 | remoteInfo = Ishimura; 47 | }; 48 | /* End PBXContainerItemProxy section */ 49 | 50 | /* Begin PBXCopyFilesBuildPhase section */ 51 | A0448B60183BEB670056818A /* Copy Files */ = { 52 | isa = PBXCopyFilesBuildPhase; 53 | buildActionMask = 12; 54 | dstPath = ""; 55 | dstSubfolderSpec = 10; 56 | files = ( 57 | ); 58 | name = "Copy Files"; 59 | runOnlyForDeploymentPostprocessing = 0; 60 | }; 61 | /* End PBXCopyFilesBuildPhase section */ 62 | 63 | /* Begin PBXFileReference section */ 64 | 34A22D401D1F6BFD0084E3F2 /* NSMenuItem+APAdditions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "NSMenuItem+APAdditions.h"; path = "Other/NSMenuItem+APAdditions.h"; sourceTree = ""; }; 65 | 34A22D411D1F6BFD0084E3F2 /* NSMenuItem+APAdditions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "NSMenuItem+APAdditions.m"; path = "Other/NSMenuItem+APAdditions.m"; sourceTree = ""; }; 66 | 34A22D461D1F6DE30084E3F2 /* NSMenu+APAdditions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "NSMenu+APAdditions.h"; path = "Other/NSMenu+APAdditions.h"; sourceTree = ""; }; 67 | 34A22D471D1F6DE30084E3F2 /* NSMenu+APAdditions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "NSMenu+APAdditions.m"; path = "Other/NSMenu+APAdditions.m"; sourceTree = ""; }; 68 | 34A22D4B1D20DDB60084E3F2 /* AppLoadLevelIndicator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AppLoadLevelIndicator.h; path = AppInspector/AppLoadLevelIndicator.h; sourceTree = ""; }; 69 | 34A22D4C1D20DDB60084E3F2 /* AppLoadLevelIndicator.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = AppLoadLevelIndicator.m; path = AppInspector/AppLoadLevelIndicator.m; sourceTree = ""; }; 70 | 34A22D4E1D20EA0B0084E3F2 /* status_icon.pdf */ = {isa = PBXFileReference; lastKnownFileType = image.pdf; path = status_icon.pdf; sourceTree = ""; }; 71 | A00C3B2D183F8937005E596C /* UserDefaults.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = UserDefaults.plist; sourceTree = ""; }; 72 | A00D28531803E85F00D71F71 /* AppLimitSliderCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AppLimitSliderCell.h; path = AppInspector/AppLimitSliderCell.h; sourceTree = ""; }; 73 | A00D28541803E85F00D71F71 /* AppLimitSliderCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = AppLimitSliderCell.m; path = AppInspector/AppLimitSliderCell.m; sourceTree = ""; }; 74 | A00FBF4C17DF54BF0083B482 /* QuartzCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QuartzCore.framework; path = System/Library/Frameworks/QuartzCore.framework; sourceTree = SDKROOT; }; 75 | A0100691182106900017296D /* app_inspector_c.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = app_inspector_c.h; path = C/app_inspector_c.h; sourceTree = ""; }; 76 | A0100692182106A10017296D /* app_inspector_c.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = app_inspector_c.c; path = C/app_inspector_c.c; sourceTree = ""; }; 77 | A01191681807E2EF004777D9 /* StatusbarMenuController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = StatusbarMenuController.h; path = Statusbar/StatusbarMenuController.h; sourceTree = ""; }; 78 | A01191691807E2EF004777D9 /* StatusbarMenuController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = StatusbarMenuController.m; path = Statusbar/StatusbarMenuController.m; sourceTree = ""; }; 79 | A0154E801782E05B008CF159 /* en */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = en; path = en.lproj/AppInspectorView.xib; sourceTree = ""; }; 80 | A0154E831782E972008CF159 /* AppInspector.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = AppInspector.h; path = AppInspector/AppInspector.h; sourceTree = ""; }; 81 | A0154E841782E972008CF159 /* AppInspector.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = AppInspector.m; path = AppInspector/AppInspector.m; sourceTree = ""; }; 82 | A0448A5D183B7BD60056818A /* AppPolice.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.xml; path = AppPolice.entitlements; sourceTree = ""; }; 83 | A04FA3D2174D4BD9002E688C /* selfprofile.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = selfprofile.c; path = C/selfprofile.c; sourceTree = ""; }; 84 | A04FA3D4174D4BF5002E688C /* selfprofile.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = selfprofile.h; path = C/selfprofile.h; sourceTree = ""; }; 85 | A063796417492AEF006F2347 /* AppPolice.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = AppPolice.app; sourceTree = BUILT_PRODUCTS_DIR; }; 86 | A063796717492AEF006F2347 /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = System/Library/Frameworks/Cocoa.framework; sourceTree = SDKROOT; }; 87 | A063796A17492AEF006F2347 /* AppKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppKit.framework; path = System/Library/Frameworks/AppKit.framework; sourceTree = SDKROOT; }; 88 | A063796B17492AEF006F2347 /* CoreData.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreData.framework; path = System/Library/Frameworks/CoreData.framework; sourceTree = SDKROOT; }; 89 | A063796C17492AEF006F2347 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; 90 | A063796F17492AEF006F2347 /* AppPolice-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "AppPolice-Info.plist"; sourceTree = ""; }; 91 | A063797117492AEF006F2347 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; }; 92 | A063797317492AEF006F2347 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 93 | A063797517492AEF006F2347 /* AppPolice-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "AppPolice-Prefix.pch"; sourceTree = ""; }; 94 | A063797717492AEF006F2347 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.rtf; name = en; path = en.lproj/Credits.rtf; sourceTree = ""; }; 95 | A063797917492AEF006F2347 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; 96 | A063797A17492AEF006F2347 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; 97 | A063797D17492AF0006F2347 /* en */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = en; path = en.lproj/MainMenu.xib; sourceTree = ""; }; 98 | A063798517492D19006F2347 /* proc_cpulim.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = proc_cpulim.h; path = C/proc_cpulim.h; sourceTree = ""; }; 99 | A063798617492D42006F2347 /* proc_cpulim.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = proc_cpulim.c; path = C/proc_cpulim.c; sourceTree = ""; }; 100 | A067A0B818369681003B677E /* en */ = {isa = PBXFileReference; fileEncoding = 10; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/Localizable.strings; sourceTree = ""; }; 101 | A067A0C518369782003B677E /* Media.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Media.xcassets; sourceTree = ""; }; 102 | A071B69317D8812500D3866E /* AppPolice Tests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "AppPolice Tests.xctest"; sourceTree = BUILT_PRODUCTS_DIR; }; 103 | A071B69417D8812500D3866E /* XCTest.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = XCTest.framework; path = Library/Frameworks/XCTest.framework; sourceTree = DEVELOPER_DIR; }; 104 | A071B69817D8812500D3866E /* AppPolice Tests-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "AppPolice Tests-Info.plist"; sourceTree = ""; }; 105 | A071B69A17D8812500D3866E /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; }; 106 | A071B69C17D8812500D3866E /* AppPolice_Tests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppPolice_Tests.m; sourceTree = ""; }; 107 | A071B69E17D8812500D3866E /* AppPolice Tests-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "AppPolice Tests-Prefix.pch"; sourceTree = ""; }; 108 | A07E4B8D183CBD1900D773E5 /* APPreferencesController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = APPreferencesController.h; path = Other/APPreferencesController.h; sourceTree = ""; }; 109 | A07E4B8E183CBD1900D773E5 /* APPreferencesController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = APPreferencesController.m; path = Other/APPreferencesController.m; sourceTree = ""; }; 110 | A0ADD312174A142A002BAADE /* subroutines.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = subroutines.h; path = C/subroutines.h; sourceTree = ""; }; 111 | A0ADD313174A1438002BAADE /* subroutines.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = subroutines.c; path = C/subroutines.c; sourceTree = ""; }; 112 | A0BD1BEB183E10680054FC06 /* en */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = en; path = en.lproj/APPreferencesWindow.xib; sourceTree = ""; }; 113 | A0FFE0A71805D673007F510E /* AppLimitHintView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AppLimitHintView.h; path = AppInspector/AppLimitHintView.h; sourceTree = ""; }; 114 | A0FFE0A81805D673007F510E /* AppLimitHintView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = AppLimitHintView.m; path = AppInspector/AppLimitHintView.m; sourceTree = ""; }; 115 | /* End PBXFileReference section */ 116 | 117 | /* Begin PBXFrameworksBuildPhase section */ 118 | A063796117492AEF006F2347 /* Frameworks */ = { 119 | isa = PBXFrameworksBuildPhase; 120 | buildActionMask = 2147483647; 121 | files = ( 122 | A00FBF4D17DF54BF0083B482 /* QuartzCore.framework in Frameworks */, 123 | A063796817492AEF006F2347 /* Cocoa.framework in Frameworks */, 124 | ); 125 | runOnlyForDeploymentPostprocessing = 0; 126 | }; 127 | A071B69017D8812500D3866E /* Frameworks */ = { 128 | isa = PBXFrameworksBuildPhase; 129 | buildActionMask = 2147483647; 130 | files = ( 131 | A071B69517D8812500D3866E /* XCTest.framework in Frameworks */, 132 | ); 133 | runOnlyForDeploymentPostprocessing = 0; 134 | }; 135 | /* End PBXFrameworksBuildPhase section */ 136 | 137 | /* Begin PBXGroup section */ 138 | A01191611807DE2C004777D9 /* Statusbar */ = { 139 | isa = PBXGroup; 140 | children = ( 141 | A01191681807E2EF004777D9 /* StatusbarMenuController.h */, 142 | A01191691807E2EF004777D9 /* StatusbarMenuController.m */, 143 | ); 144 | name = Statusbar; 145 | sourceTree = ""; 146 | }; 147 | A0154E7C1782DEDA008CF159 /* AppInspector */ = { 148 | isa = PBXGroup; 149 | children = ( 150 | A0154E831782E972008CF159 /* AppInspector.h */, 151 | A0154E841782E972008CF159 /* AppInspector.m */, 152 | A00D28531803E85F00D71F71 /* AppLimitSliderCell.h */, 153 | A00D28541803E85F00D71F71 /* AppLimitSliderCell.m */, 154 | A0FFE0A71805D673007F510E /* AppLimitHintView.h */, 155 | A0FFE0A81805D673007F510E /* AppLimitHintView.m */, 156 | 34A22D4B1D20DDB60084E3F2 /* AppLoadLevelIndicator.h */, 157 | 34A22D4C1D20DDB60084E3F2 /* AppLoadLevelIndicator.m */, 158 | A0154E7D1782DF16008CF159 /* Resources */, 159 | ); 160 | name = AppInspector; 161 | sourceTree = ""; 162 | }; 163 | A0154E7D1782DF16008CF159 /* Resources */ = { 164 | isa = PBXGroup; 165 | children = ( 166 | A0154E7F1782E05B008CF159 /* AppInspectorView.xib */, 167 | ); 168 | name = Resources; 169 | sourceTree = ""; 170 | }; 171 | A063795B17492AEF006F2347 = { 172 | isa = PBXGroup; 173 | children = ( 174 | A063796D17492AEF006F2347 /* AppPolice */, 175 | A071B69617D8812500D3866E /* AppPolice Tests */, 176 | A063796617492AEF006F2347 /* Frameworks */, 177 | A063796517492AEF006F2347 /* Products */, 178 | ); 179 | sourceTree = ""; 180 | }; 181 | A063796517492AEF006F2347 /* Products */ = { 182 | isa = PBXGroup; 183 | children = ( 184 | A063796417492AEF006F2347 /* AppPolice.app */, 185 | A071B69317D8812500D3866E /* AppPolice Tests.xctest */, 186 | ); 187 | name = Products; 188 | sourceTree = ""; 189 | }; 190 | A063796617492AEF006F2347 /* Frameworks */ = { 191 | isa = PBXGroup; 192 | children = ( 193 | A00FBF4C17DF54BF0083B482 /* QuartzCore.framework */, 194 | A063796717492AEF006F2347 /* Cocoa.framework */, 195 | A071B69417D8812500D3866E /* XCTest.framework */, 196 | A063796917492AEF006F2347 /* Other Frameworks */, 197 | ); 198 | name = Frameworks; 199 | sourceTree = ""; 200 | }; 201 | A063796917492AEF006F2347 /* Other Frameworks */ = { 202 | isa = PBXGroup; 203 | children = ( 204 | A063796A17492AEF006F2347 /* AppKit.framework */, 205 | A063796B17492AEF006F2347 /* CoreData.framework */, 206 | A063796C17492AEF006F2347 /* Foundation.framework */, 207 | ); 208 | name = "Other Frameworks"; 209 | sourceTree = ""; 210 | }; 211 | A063796D17492AEF006F2347 /* AppPolice */ = { 212 | isa = PBXGroup; 213 | children = ( 214 | A063797917492AEF006F2347 /* AppDelegate.h */, 215 | A063797A17492AEF006F2347 /* AppDelegate.m */, 216 | A063797317492AEF006F2347 /* main.m */, 217 | A01191611807DE2C004777D9 /* Statusbar */, 218 | A0154E7C1782DEDA008CF159 /* AppInspector */, 219 | A07E4B6F183CB3F600D773E5 /* Other */, 220 | A063798417492CCB006F2347 /* C */, 221 | A063796E17492AEF006F2347 /* Supporting Files */, 222 | ); 223 | path = AppPolice; 224 | sourceTree = ""; 225 | }; 226 | A063796E17492AEF006F2347 /* Supporting Files */ = { 227 | isa = PBXGroup; 228 | children = ( 229 | 34A22D4E1D20EA0B0084E3F2 /* status_icon.pdf */, 230 | A0448A5D183B7BD60056818A /* AppPolice.entitlements */, 231 | A063797C17492AF0006F2347 /* MainMenu.xib */, 232 | A0BD1BEC183E10680054FC06 /* APPreferencesWindow.xib */, 233 | A063796F17492AEF006F2347 /* AppPolice-Info.plist */, 234 | A063797017492AEF006F2347 /* InfoPlist.strings */, 235 | A067A0B918369681003B677E /* Localizable.strings */, 236 | A00C3B2D183F8937005E596C /* UserDefaults.plist */, 237 | A063797517492AEF006F2347 /* AppPolice-Prefix.pch */, 238 | A063797617492AEF006F2347 /* Credits.rtf */, 239 | A067A0C518369782003B677E /* Media.xcassets */, 240 | ); 241 | name = "Supporting Files"; 242 | sourceTree = ""; 243 | }; 244 | A063798417492CCB006F2347 /* C */ = { 245 | isa = PBXGroup; 246 | children = ( 247 | A063798517492D19006F2347 /* proc_cpulim.h */, 248 | A063798617492D42006F2347 /* proc_cpulim.c */, 249 | A0ADD312174A142A002BAADE /* subroutines.h */, 250 | A0ADD313174A1438002BAADE /* subroutines.c */, 251 | A04FA3D4174D4BF5002E688C /* selfprofile.h */, 252 | A04FA3D2174D4BD9002E688C /* selfprofile.c */, 253 | A0100691182106900017296D /* app_inspector_c.h */, 254 | A0100692182106A10017296D /* app_inspector_c.c */, 255 | ); 256 | name = C; 257 | sourceTree = ""; 258 | }; 259 | A071B69617D8812500D3866E /* AppPolice Tests */ = { 260 | isa = PBXGroup; 261 | children = ( 262 | A071B69C17D8812500D3866E /* AppPolice_Tests.m */, 263 | A071B69717D8812500D3866E /* Supporting Files */, 264 | ); 265 | path = "AppPolice Tests"; 266 | sourceTree = ""; 267 | }; 268 | A071B69717D8812500D3866E /* Supporting Files */ = { 269 | isa = PBXGroup; 270 | children = ( 271 | A071B69817D8812500D3866E /* AppPolice Tests-Info.plist */, 272 | A071B69917D8812500D3866E /* InfoPlist.strings */, 273 | A071B69E17D8812500D3866E /* AppPolice Tests-Prefix.pch */, 274 | ); 275 | name = "Supporting Files"; 276 | sourceTree = ""; 277 | }; 278 | A07E4B6F183CB3F600D773E5 /* Other */ = { 279 | isa = PBXGroup; 280 | children = ( 281 | A07E4B8D183CBD1900D773E5 /* APPreferencesController.h */, 282 | A07E4B8E183CBD1900D773E5 /* APPreferencesController.m */, 283 | 34A22D461D1F6DE30084E3F2 /* NSMenu+APAdditions.h */, 284 | 34A22D471D1F6DE30084E3F2 /* NSMenu+APAdditions.m */, 285 | 34A22D401D1F6BFD0084E3F2 /* NSMenuItem+APAdditions.h */, 286 | 34A22D411D1F6BFD0084E3F2 /* NSMenuItem+APAdditions.m */, 287 | ); 288 | name = Other; 289 | sourceTree = ""; 290 | }; 291 | /* End PBXGroup section */ 292 | 293 | /* Begin PBXNativeTarget section */ 294 | A063796317492AEF006F2347 /* AppPolice */ = { 295 | isa = PBXNativeTarget; 296 | buildConfigurationList = A063798117492AF0006F2347 /* Build configuration list for PBXNativeTarget "AppPolice" */; 297 | buildPhases = ( 298 | A063796017492AEF006F2347 /* Sources */, 299 | A063796117492AEF006F2347 /* Frameworks */, 300 | A063796217492AEF006F2347 /* Resources */, 301 | A0448B60183BEB670056818A /* Copy Files */, 302 | ); 303 | buildRules = ( 304 | ); 305 | dependencies = ( 306 | ); 307 | name = AppPolice; 308 | productName = cpulim; 309 | productReference = A063796417492AEF006F2347 /* AppPolice.app */; 310 | productType = "com.apple.product-type.application"; 311 | }; 312 | A071B69217D8812500D3866E /* AppPolice Tests */ = { 313 | isa = PBXNativeTarget; 314 | buildConfigurationList = A071B6A117D8812500D3866E /* Build configuration list for PBXNativeTarget "AppPolice Tests" */; 315 | buildPhases = ( 316 | A071B68F17D8812500D3866E /* Sources */, 317 | A071B69017D8812500D3866E /* Frameworks */, 318 | A071B69117D8812500D3866E /* Resources */, 319 | ); 320 | buildRules = ( 321 | ); 322 | dependencies = ( 323 | A071B6A017D8812500D3866E /* PBXTargetDependency */, 324 | ); 325 | name = "AppPolice Tests"; 326 | productName = "Ishimura Tests"; 327 | productReference = A071B69317D8812500D3866E /* AppPolice Tests.xctest */; 328 | productType = "com.apple.product-type.bundle.unit-test"; 329 | }; 330 | /* End PBXNativeTarget section */ 331 | 332 | /* Begin PBXProject section */ 333 | A063795C17492AEF006F2347 /* Project object */ = { 334 | isa = PBXProject; 335 | attributes = { 336 | LastUpgradeCheck = 0500; 337 | ORGANIZATIONNAME = "Maksym Stefanchuk"; 338 | TargetAttributes = { 339 | A063796317492AEF006F2347 = { 340 | SystemCapabilities = { 341 | com.apple.Sandbox = { 342 | enabled = 0; 343 | }; 344 | }; 345 | }; 346 | A071B69217D8812500D3866E = { 347 | TestTargetID = A063796317492AEF006F2347; 348 | }; 349 | }; 350 | }; 351 | buildConfigurationList = A063795F17492AEF006F2347 /* Build configuration list for PBXProject "AppPolice" */; 352 | compatibilityVersion = "Xcode 3.2"; 353 | developmentRegion = English; 354 | hasScannedForEncodings = 0; 355 | knownRegions = ( 356 | en, 357 | ); 358 | mainGroup = A063795B17492AEF006F2347; 359 | productRefGroup = A063796517492AEF006F2347 /* Products */; 360 | projectDirPath = ""; 361 | projectRoot = ""; 362 | targets = ( 363 | A063796317492AEF006F2347 /* AppPolice */, 364 | A071B69217D8812500D3866E /* AppPolice Tests */, 365 | ); 366 | }; 367 | /* End PBXProject section */ 368 | 369 | /* Begin PBXResourcesBuildPhase section */ 370 | A063796217492AEF006F2347 /* Resources */ = { 371 | isa = PBXResourcesBuildPhase; 372 | buildActionMask = 2147483647; 373 | files = ( 374 | A01453BE17833F5700FFFB39 /* AppInspectorView.xib in Resources */, 375 | A00C3B2E183F8937005E596C /* UserDefaults.plist in Resources */, 376 | A063797217492AEF006F2347 /* InfoPlist.strings in Resources */, 377 | A063797817492AEF006F2347 /* Credits.rtf in Resources */, 378 | A0BD1BEA183E10680054FC06 /* APPreferencesWindow.xib in Resources */, 379 | 34A22D4F1D20EA0B0084E3F2 /* status_icon.pdf in Resources */, 380 | A063797E17492AF0006F2347 /* MainMenu.xib in Resources */, 381 | A067A0C618369782003B677E /* Media.xcassets in Resources */, 382 | A067A0B718369681003B677E /* Localizable.strings in Resources */, 383 | ); 384 | runOnlyForDeploymentPostprocessing = 0; 385 | }; 386 | A071B69117D8812500D3866E /* Resources */ = { 387 | isa = PBXResourcesBuildPhase; 388 | buildActionMask = 2147483647; 389 | files = ( 390 | A071B69B17D8812500D3866E /* InfoPlist.strings in Resources */, 391 | ); 392 | runOnlyForDeploymentPostprocessing = 0; 393 | }; 394 | /* End PBXResourcesBuildPhase section */ 395 | 396 | /* Begin PBXSourcesBuildPhase section */ 397 | A063796017492AEF006F2347 /* Sources */ = { 398 | isa = PBXSourcesBuildPhase; 399 | buildActionMask = 2147483647; 400 | files = ( 401 | A00D28551803E85F00D71F71 /* AppLimitSliderCell.m in Sources */, 402 | A0FFE0A91805D673007F510E /* AppLimitHintView.m in Sources */, 403 | 34A22D421D1F6BFD0084E3F2 /* NSMenuItem+APAdditions.m in Sources */, 404 | A0100693182106A10017296D /* app_inspector_c.c in Sources */, 405 | A011916A1807E2EF004777D9 /* StatusbarMenuController.m in Sources */, 406 | A063797417492AEF006F2347 /* main.m in Sources */, 407 | 34A22D481D1F6DE30084E3F2 /* NSMenu+APAdditions.m in Sources */, 408 | 34A22D4D1D20DDB60084E3F2 /* AppLoadLevelIndicator.m in Sources */, 409 | A063797B17492AEF006F2347 /* AppDelegate.m in Sources */, 410 | A063798717492D42006F2347 /* proc_cpulim.c in Sources */, 411 | A0ADD314174A1438002BAADE /* subroutines.c in Sources */, 412 | A04FA3D3174D4BD9002E688C /* selfprofile.c in Sources */, 413 | A0154E851782EC6F008CF159 /* AppInspector.m in Sources */, 414 | A07E4B90183CBD1900D773E5 /* APPreferencesController.m in Sources */, 415 | ); 416 | runOnlyForDeploymentPostprocessing = 0; 417 | }; 418 | A071B68F17D8812500D3866E /* Sources */ = { 419 | isa = PBXSourcesBuildPhase; 420 | buildActionMask = 2147483647; 421 | files = ( 422 | A071B69D17D8812500D3866E /* AppPolice_Tests.m in Sources */, 423 | ); 424 | runOnlyForDeploymentPostprocessing = 0; 425 | }; 426 | /* End PBXSourcesBuildPhase section */ 427 | 428 | /* Begin PBXTargetDependency section */ 429 | A071B6A017D8812500D3866E /* PBXTargetDependency */ = { 430 | isa = PBXTargetDependency; 431 | target = A063796317492AEF006F2347 /* AppPolice */; 432 | targetProxy = A071B69F17D8812500D3866E /* PBXContainerItemProxy */; 433 | }; 434 | /* End PBXTargetDependency section */ 435 | 436 | /* Begin PBXVariantGroup section */ 437 | A0154E7F1782E05B008CF159 /* AppInspectorView.xib */ = { 438 | isa = PBXVariantGroup; 439 | children = ( 440 | A0154E801782E05B008CF159 /* en */, 441 | ); 442 | name = AppInspectorView.xib; 443 | sourceTree = ""; 444 | }; 445 | A063797017492AEF006F2347 /* InfoPlist.strings */ = { 446 | isa = PBXVariantGroup; 447 | children = ( 448 | A063797117492AEF006F2347 /* en */, 449 | ); 450 | name = InfoPlist.strings; 451 | sourceTree = ""; 452 | }; 453 | A063797617492AEF006F2347 /* Credits.rtf */ = { 454 | isa = PBXVariantGroup; 455 | children = ( 456 | A063797717492AEF006F2347 /* en */, 457 | ); 458 | name = Credits.rtf; 459 | sourceTree = ""; 460 | }; 461 | A063797C17492AF0006F2347 /* MainMenu.xib */ = { 462 | isa = PBXVariantGroup; 463 | children = ( 464 | A063797D17492AF0006F2347 /* en */, 465 | ); 466 | name = MainMenu.xib; 467 | sourceTree = ""; 468 | }; 469 | A067A0B918369681003B677E /* Localizable.strings */ = { 470 | isa = PBXVariantGroup; 471 | children = ( 472 | A067A0B818369681003B677E /* en */, 473 | ); 474 | name = Localizable.strings; 475 | sourceTree = ""; 476 | }; 477 | A071B69917D8812500D3866E /* InfoPlist.strings */ = { 478 | isa = PBXVariantGroup; 479 | children = ( 480 | A071B69A17D8812500D3866E /* en */, 481 | ); 482 | name = InfoPlist.strings; 483 | sourceTree = ""; 484 | }; 485 | A0BD1BEC183E10680054FC06 /* APPreferencesWindow.xib */ = { 486 | isa = PBXVariantGroup; 487 | children = ( 488 | A0BD1BEB183E10680054FC06 /* en */, 489 | ); 490 | name = APPreferencesWindow.xib; 491 | sourceTree = ""; 492 | }; 493 | /* End PBXVariantGroup section */ 494 | 495 | /* Begin XCBuildConfiguration section */ 496 | A063797F17492AF0006F2347 /* Debug */ = { 497 | isa = XCBuildConfiguration; 498 | buildSettings = { 499 | ALWAYS_SEARCH_USER_PATHS = NO; 500 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 501 | CLANG_CXX_LIBRARY = "libc++"; 502 | CLANG_WARN_CONSTANT_CONVERSION = YES; 503 | CLANG_WARN_EMPTY_BODY = YES; 504 | CLANG_WARN_ENUM_CONVERSION = YES; 505 | CLANG_WARN_INT_CONVERSION = YES; 506 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 507 | COPY_PHASE_STRIP = NO; 508 | GCC_C_LANGUAGE_STANDARD = gnu99; 509 | GCC_DYNAMIC_NO_PIC = NO; 510 | GCC_ENABLE_OBJC_EXCEPTIONS = YES; 511 | GCC_OPTIMIZATION_LEVEL = 0; 512 | GCC_PREPROCESSOR_DEFINITIONS = ( 513 | "DEBUG=1", 514 | "$(inherited)", 515 | ); 516 | GCC_SYMBOLS_PRIVATE_EXTERN = NO; 517 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 518 | GCC_WARN_ABOUT_RETURN_TYPE = YES; 519 | GCC_WARN_SIGN_COMPARE = YES; 520 | GCC_WARN_UNINITIALIZED_AUTOS = YES; 521 | GCC_WARN_UNUSED_VARIABLE = YES; 522 | MACOSX_DEPLOYMENT_TARGET = 10.7; 523 | ONLY_ACTIVE_ARCH = YES; 524 | SDKROOT = macosx; 525 | }; 526 | name = Debug; 527 | }; 528 | A063798017492AF0006F2347 /* Release */ = { 529 | isa = XCBuildConfiguration; 530 | buildSettings = { 531 | ALWAYS_SEARCH_USER_PATHS = NO; 532 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 533 | CLANG_CXX_LIBRARY = "libc++"; 534 | CLANG_WARN_CONSTANT_CONVERSION = YES; 535 | CLANG_WARN_EMPTY_BODY = YES; 536 | CLANG_WARN_ENUM_CONVERSION = YES; 537 | CLANG_WARN_INT_CONVERSION = YES; 538 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 539 | COPY_PHASE_STRIP = YES; 540 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 541 | GCC_C_LANGUAGE_STANDARD = gnu99; 542 | GCC_ENABLE_OBJC_EXCEPTIONS = YES; 543 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 544 | GCC_WARN_ABOUT_RETURN_TYPE = YES; 545 | GCC_WARN_SIGN_COMPARE = YES; 546 | GCC_WARN_UNINITIALIZED_AUTOS = YES; 547 | GCC_WARN_UNUSED_VARIABLE = YES; 548 | MACOSX_DEPLOYMENT_TARGET = 10.7; 549 | SDKROOT = macosx; 550 | }; 551 | name = Release; 552 | }; 553 | A063798217492AF0006F2347 /* Debug */ = { 554 | isa = XCBuildConfiguration; 555 | buildSettings = { 556 | ASSETCATALOG_COMPILER_APPICON_NAME = AppPolice; 557 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 558 | CLANG_WARN_IMPLICIT_SIGN_CONVERSION = YES; 559 | CLANG_WARN_SUSPICIOUS_IMPLICIT_CONVERSION = YES; 560 | COMBINE_HIDPI_IMAGES = YES; 561 | FRAMEWORK_SEARCH_PATHS = "$(BUILT_PRODUCTS_DIR)"; 562 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 563 | GCC_PREFIX_HEADER = "AppPolice/AppPolice-Prefix.pch"; 564 | GCC_WARN_ABOUT_MISSING_NEWLINE = YES; 565 | GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES; 566 | GCC_WARN_MULTIPLE_DEFINITION_TYPES_FOR_SELECTOR = NO; 567 | GCC_WARN_SIGN_COMPARE = YES; 568 | GCC_WARN_STRICT_SELECTOR_MATCH = YES; 569 | GCC_WARN_UNDECLARED_SELECTOR = YES; 570 | GCC_WARN_UNUSED_FUNCTION = YES; 571 | GCC_WARN_UNUSED_LABEL = YES; 572 | HEADER_SEARCH_PATHS = ( 573 | "$(inherited)", 574 | /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include, 575 | ); 576 | INFOPLIST_FILE = "AppPolice/AppPolice-Info.plist"; 577 | MACOSX_DEPLOYMENT_TARGET = 10.6; 578 | PRODUCT_NAME = AppPolice; 579 | SDKROOT = macosx; 580 | WRAPPER_EXTENSION = app; 581 | }; 582 | name = Debug; 583 | }; 584 | A063798317492AF0006F2347 /* Release */ = { 585 | isa = XCBuildConfiguration; 586 | buildSettings = { 587 | ASSETCATALOG_COMPILER_APPICON_NAME = AppPolice; 588 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 589 | CLANG_WARN_IMPLICIT_SIGN_CONVERSION = YES; 590 | CLANG_WARN_SUSPICIOUS_IMPLICIT_CONVERSION = YES; 591 | COMBINE_HIDPI_IMAGES = YES; 592 | COPY_PHASE_STRIP = NO; 593 | FRAMEWORK_SEARCH_PATHS = "$(BUILT_PRODUCTS_DIR)"; 594 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 595 | GCC_PREFIX_HEADER = "AppPolice/AppPolice-Prefix.pch"; 596 | GCC_WARN_ABOUT_MISSING_NEWLINE = YES; 597 | GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES; 598 | GCC_WARN_MULTIPLE_DEFINITION_TYPES_FOR_SELECTOR = NO; 599 | GCC_WARN_SIGN_COMPARE = YES; 600 | GCC_WARN_STRICT_SELECTOR_MATCH = YES; 601 | GCC_WARN_UNDECLARED_SELECTOR = YES; 602 | GCC_WARN_UNUSED_FUNCTION = YES; 603 | GCC_WARN_UNUSED_LABEL = YES; 604 | HEADER_SEARCH_PATHS = ( 605 | "$(inherited)", 606 | /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include, 607 | ); 608 | INFOPLIST_FILE = "AppPolice/AppPolice-Info.plist"; 609 | MACOSX_DEPLOYMENT_TARGET = 10.6; 610 | PRODUCT_NAME = AppPolice; 611 | SDKROOT = macosx; 612 | WRAPPER_EXTENSION = app; 613 | }; 614 | name = Release; 615 | }; 616 | A071B6A217D8812500D3866E /* Debug */ = { 617 | isa = XCBuildConfiguration; 618 | buildSettings = { 619 | BUNDLE_LOADER = "$(BUILT_PRODUCTS_DIR)/AppPolice.app/Contents/MacOS/AppPolice"; 620 | CLANG_ENABLE_MODULES = YES; 621 | CLANG_ENABLE_OBJC_ARC = YES; 622 | CLANG_WARN_BOOL_CONVERSION = YES; 623 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 624 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 625 | COMBINE_HIDPI_IMAGES = YES; 626 | FRAMEWORK_SEARCH_PATHS = ( 627 | "$(DEVELOPER_FRAMEWORKS_DIR)", 628 | "$(inherited)", 629 | ); 630 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 631 | GCC_PREFIX_HEADER = "AppPolice Tests/AppPolice Tests-Prefix.pch"; 632 | GCC_PREPROCESSOR_DEFINITIONS = ( 633 | "DEBUG=1", 634 | "$(inherited)", 635 | ); 636 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 637 | GCC_WARN_UNDECLARED_SELECTOR = YES; 638 | GCC_WARN_UNUSED_FUNCTION = YES; 639 | INFOPLIST_FILE = "AppPolice Tests/AppPolice Tests-Info.plist"; 640 | MACOSX_DEPLOYMENT_TARGET = 10.7; 641 | PRODUCT_NAME = "AppPolice Tests"; 642 | TEST_HOST = "$(BUNDLE_LOADER)"; 643 | WRAPPER_EXTENSION = xctest; 644 | }; 645 | name = Debug; 646 | }; 647 | A071B6A317D8812500D3866E /* Release */ = { 648 | isa = XCBuildConfiguration; 649 | buildSettings = { 650 | BUNDLE_LOADER = "$(BUILT_PRODUCTS_DIR)/AppPolice.app/Contents/MacOS/AppPolice"; 651 | CLANG_ENABLE_MODULES = YES; 652 | CLANG_ENABLE_OBJC_ARC = YES; 653 | CLANG_WARN_BOOL_CONVERSION = YES; 654 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 655 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 656 | COMBINE_HIDPI_IMAGES = YES; 657 | ENABLE_NS_ASSERTIONS = NO; 658 | FRAMEWORK_SEARCH_PATHS = ( 659 | "$(DEVELOPER_FRAMEWORKS_DIR)", 660 | "$(inherited)", 661 | ); 662 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 663 | GCC_PREFIX_HEADER = "AppPolice Tests/AppPolice Tests-Prefix.pch"; 664 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 665 | GCC_WARN_UNDECLARED_SELECTOR = YES; 666 | GCC_WARN_UNUSED_FUNCTION = YES; 667 | INFOPLIST_FILE = "AppPolice Tests/AppPolice Tests-Info.plist"; 668 | MACOSX_DEPLOYMENT_TARGET = 10.7; 669 | PRODUCT_NAME = "AppPolice Tests"; 670 | TEST_HOST = "$(BUNDLE_LOADER)"; 671 | WRAPPER_EXTENSION = xctest; 672 | }; 673 | name = Release; 674 | }; 675 | /* End XCBuildConfiguration section */ 676 | 677 | /* Begin XCConfigurationList section */ 678 | A063795F17492AEF006F2347 /* Build configuration list for PBXProject "AppPolice" */ = { 679 | isa = XCConfigurationList; 680 | buildConfigurations = ( 681 | A063797F17492AF0006F2347 /* Debug */, 682 | A063798017492AF0006F2347 /* Release */, 683 | ); 684 | defaultConfigurationIsVisible = 0; 685 | defaultConfigurationName = Release; 686 | }; 687 | A063798117492AF0006F2347 /* Build configuration list for PBXNativeTarget "AppPolice" */ = { 688 | isa = XCConfigurationList; 689 | buildConfigurations = ( 690 | A063798217492AF0006F2347 /* Debug */, 691 | A063798317492AF0006F2347 /* Release */, 692 | ); 693 | defaultConfigurationIsVisible = 0; 694 | defaultConfigurationName = Release; 695 | }; 696 | A071B6A117D8812500D3866E /* Build configuration list for PBXNativeTarget "AppPolice Tests" */ = { 697 | isa = XCConfigurationList; 698 | buildConfigurations = ( 699 | A071B6A217D8812500D3866E /* Debug */, 700 | A071B6A317D8812500D3866E /* Release */, 701 | ); 702 | defaultConfigurationIsVisible = 0; 703 | defaultConfigurationName = Release; 704 | }; 705 | /* End XCConfigurationList section */ 706 | }; 707 | rootObject = A063795C17492AEF006F2347 /* Project object */; 708 | } 709 | -------------------------------------------------------------------------------- /AppPolice.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /AppPolice.xcodeproj/project.xcworkspace/xcshareddata/AppPolice.xccheckout: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDESourceControlProjectFavoriteDictionaryKey 6 | 7 | IDESourceControlProjectIdentifier 8 | 4B9E28C5-30A0-4A35-80DD-8B58980CF6D4 9 | IDESourceControlProjectName 10 | project 11 | IDESourceControlProjectOriginsDictionary 12 | 13 | 0ED10799ADEDBDBDFC451785415C2F5F26ACCAB6 14 | github.com:fuyu/AppPolice.git 15 | 78DF898BEC1190EEB5909754834CBE0BE39026BC 16 | github.com:fuyu/ChromeMenu.git 17 | 18 | IDESourceControlProjectPath 19 | AppPolice.xcodeproj/project.xcworkspace 20 | IDESourceControlProjectRelativeInstallPathDictionary 21 | 22 | 0ED10799ADEDBDBDFC451785415C2F5F26ACCAB6 23 | ../.. 24 | 78DF898BEC1190EEB5909754834CBE0BE39026BC 25 | ../../../ChromeMenu 26 | 27 | IDESourceControlProjectURL 28 | github.com:fuyu/AppPolice.git 29 | IDESourceControlProjectVersion 30 | 111 31 | IDESourceControlProjectWCCIdentifier 32 | 0ED10799ADEDBDBDFC451785415C2F5F26ACCAB6 33 | IDESourceControlProjectWCConfigurations 34 | 35 | 36 | IDESourceControlRepositoryExtensionIdentifierKey 37 | public.vcs.git 38 | IDESourceControlWCCIdentifierKey 39 | 0ED10799ADEDBDBDFC451785415C2F5F26ACCAB6 40 | IDESourceControlWCCName 41 | AppPolice 42 | 43 | 44 | IDESourceControlRepositoryExtensionIdentifierKey 45 | public.vcs.git 46 | IDESourceControlWCCIdentifierKey 47 | 78DF898BEC1190EEB5909754834CBE0BE39026BC 48 | IDESourceControlWCCName 49 | ChromeMenu 50 | 51 | 52 | 53 | 54 | -------------------------------------------------------------------------------- /AppPolice.xcodeproj/project.xcworkspace/xcshareddata/AppPolice.xcscmblueprint: -------------------------------------------------------------------------------- 1 | { 2 | "DVTSourceControlWorkspaceBlueprintPrimaryRemoteRepositoryKey" : "0ED10799ADEDBDBDFC451785415C2F5F26ACCAB6", 3 | "DVTSourceControlWorkspaceBlueprintWorkingCopyRepositoryLocationsKey" : { 4 | 5 | }, 6 | "DVTSourceControlWorkspaceBlueprintWorkingCopyStatesKey" : { 7 | "78DF898BEC1190EEB5909754834CBE0BE39026BC" : 0, 8 | "0ED10799ADEDBDBDFC451785415C2F5F26ACCAB6" : 0 9 | }, 10 | "DVTSourceControlWorkspaceBlueprintIdentifierKey" : "4B9E28C5-30A0-4A35-80DD-8B58980CF6D4", 11 | "DVTSourceControlWorkspaceBlueprintWorkingCopyPathsKey" : { 12 | "78DF898BEC1190EEB5909754834CBE0BE39026BC" : "ChromeMenu\/", 13 | "0ED10799ADEDBDBDFC451785415C2F5F26ACCAB6" : "AppPolice\/" 14 | }, 15 | "DVTSourceControlWorkspaceBlueprintNameKey" : "AppPolice", 16 | "DVTSourceControlWorkspaceBlueprintVersion" : 204, 17 | "DVTSourceControlWorkspaceBlueprintRelativePathToProjectKey" : "AppPolice.xcodeproj", 18 | "DVTSourceControlWorkspaceBlueprintRemoteRepositoriesKey" : [ 19 | { 20 | "DVTSourceControlWorkspaceBlueprintRemoteRepositoryURLKey" : "github.com:fuyu\/AppPolice.git", 21 | "DVTSourceControlWorkspaceBlueprintRemoteRepositorySystemKey" : "com.apple.dt.Xcode.sourcecontrol.Git", 22 | "DVTSourceControlWorkspaceBlueprintRemoteRepositoryIdentifierKey" : "0ED10799ADEDBDBDFC451785415C2F5F26ACCAB6" 23 | }, 24 | { 25 | "DVTSourceControlWorkspaceBlueprintRemoteRepositoryURLKey" : "github.com:fuyu\/ChromeMenu.git", 26 | "DVTSourceControlWorkspaceBlueprintRemoteRepositorySystemKey" : "com.apple.dt.Xcode.sourcecontrol.Git", 27 | "DVTSourceControlWorkspaceBlueprintRemoteRepositoryIdentifierKey" : "78DF898BEC1190EEB5909754834CBE0BE39026BC" 28 | } 29 | ] 30 | } -------------------------------------------------------------------------------- /AppPolice.xcodeproj/project.xcworkspace/xcuserdata/objective.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bumper314/AppPolice/62595bb21417d9e06e78edc37c51b998d83fa1d5/AppPolice.xcodeproj/project.xcworkspace/xcuserdata/objective.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /AppPolice.xcodeproj/project.xcworkspace/xcuserdata/objective.xcuserdatad/WorkspaceSettings.xcsettings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | BuildLocationStyle 6 | UseAppPreferences 7 | CustomBuildLocationType 8 | RelativeToDerivedData 9 | DerivedDataLocationStyle 10 | Default 11 | HasAskedToTakeAutomaticSnapshotBeforeSignificantChanges 12 | 13 | IssueFilterStyle 14 | ShowActiveSchemeOnly 15 | LiveSourceIssuesEnabled 16 | 17 | SnapshotAutomaticallyBeforeSignificantChanges 18 | 19 | SnapshotLocationStyle 20 | Default 21 | 22 | 23 | -------------------------------------------------------------------------------- /AppPolice.xcodeproj/xcuserdata/objective.xcuserdatad/xcdebugger/Breakpoints.xcbkptlist: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 18 | 19 | 31 | 32 | 44 | 45 | 55 | 56 | 68 | 69 | 81 | 82 | 94 | 95 | 107 | 108 | 120 | 121 | 122 | 123 | -------------------------------------------------------------------------------- /AppPolice.xcodeproj/xcuserdata/objective.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 8 | 20 | 21 | 22 | 24 | 36 | 37 | 38 | 40 | 52 | 53 | 54 | 56 | 68 | 69 | 70 | 72 | 78 | 79 | 81 | 84 | 85 | 86 | 87 | 88 | 89 | 91 | 103 | 104 | 105 | 107 | 113 | 114 | 115 | 117 | 123 | 124 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | -------------------------------------------------------------------------------- /AppPolice.xcodeproj/xcuserdata/objective.xcuserdatad/xcschemes/AppPolice Tests.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 14 | 15 | 17 | 23 | 24 | 25 | 26 | 27 | 36 | 37 | 38 | 39 | 45 | 46 | 48 | 49 | 52 | 53 | 54 | -------------------------------------------------------------------------------- /AppPolice.xcodeproj/xcuserdata/objective.xcuserdatad/xcschemes/AppPolice.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 33 | 39 | 40 | 41 | 42 | 43 | 49 | 50 | 51 | 52 | 61 | 62 | 68 | 69 | 70 | 71 | 74 | 75 | 78 | 79 | 82 | 83 | 84 | 85 | 86 | 87 | 93 | 94 | 100 | 101 | 102 | 103 | 105 | 106 | 109 | 110 | 111 | -------------------------------------------------------------------------------- /AppPolice.xcodeproj/xcuserdata/objective.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | AppPolice Tests.xcscheme 8 | 9 | orderHint 10 | 1 11 | 12 | AppPolice.xcscheme 13 | 14 | orderHint 15 | 0 16 | 17 | 18 | SuppressBuildableAutocreation 19 | 20 | A063796317492AEF006F2347 21 | 22 | primary 23 | 24 | 25 | A071B69217D8812500D3866E 26 | 27 | primary 28 | 29 | 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /AppPolice/AppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.h 3 | // AppPolice 4 | // 5 | // Created by Maksym on 5/19/13. 6 | // Copyright (c) 2013 Maksym Stefanchuk. All rights reserved. 7 | // 8 | 9 | @class StatusbarItemController, StatusbarMenuController; 10 | 11 | @interface AppDelegate : NSObject 12 | { 13 | @private 14 | NSStatusItem *_statusbarItem; 15 | StatusbarMenuController *_statusbarMenuController; 16 | } 17 | 18 | 19 | @end 20 | -------------------------------------------------------------------------------- /AppPolice/AppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.m 3 | // AppPolice 4 | // 5 | // Created by Maksym on 5/19/13. 6 | // Copyright (c) 2013 Maksym Stefanchuk. All rights reserved. 7 | // 8 | 9 | #import "AppDelegate.h" 10 | #import "StatusbarMenuController.h" 11 | 12 | #include "C/proc_cpulim.h" 13 | #include "C/selfprofile.h" 14 | 15 | 16 | @implementation AppDelegate 17 | 18 | 19 | - (void)dealloc { 20 | [_statusbarMenuController release]; 21 | [super dealloc]; 22 | } 23 | 24 | 25 | - (void)applicationWillFinishLaunching:(NSNotification *)notification { 26 | NSImage *ico = [NSImage imageNamed:@"status_icon"]; 27 | [ico setTemplate:YES]; 28 | _statusbarItem = [[NSStatusBar systemStatusBar] statusItemWithLength:NSVariableStatusItemLength]; 29 | [_statusbarItem retain]; 30 | [_statusbarItem setImage:ico]; 31 | [_statusbarItem setHighlightMode:YES]; 32 | } 33 | 34 | 35 | - (void)applicationDidFinishLaunching:(NSNotification *)aNotification { 36 | #ifdef PROFILE_APPLICATION 37 | /* print stats right after App launch: resources used by OS X to launch the App */ 38 | profiling_print_stats(); 39 | #endif 40 | 41 | // Add status item with menu 42 | _statusbarMenuController = [[StatusbarMenuController alloc] init]; 43 | NSMenu *mainMenu = [_statusbarMenuController mainMenu]; 44 | [_statusbarItem setMenu:mainMenu]; 45 | 46 | // Register default preferences 47 | NSString *defaultsPath = [[NSBundle mainBundle] pathForResource:@"UserDefaults" ofType:@"plist"]; 48 | NSDictionary *defaults = [NSDictionary dictionaryWithContentsOfFile:defaultsPath]; 49 | NSUserDefaults *preferences = [NSUserDefaults standardUserDefaults]; 50 | [preferences registerDefaults:defaults]; 51 | 52 | // Set default task schedule interval 53 | unsigned int task_schedule_interval = (unsigned int)[preferences integerForKey:@"APProcCpulimTaskScheduleInterval"]; 54 | (void) proc_cpulim_schedule_interval(task_schedule_interval, NULL); 55 | } 56 | 57 | 58 | - (void)applicationWillTerminate:(NSNotification *)notification { 59 | // We really want to stop limiter before application terminates, 60 | // or otherwise any limited processes will remain sleeping. 61 | proc_cpulim_suspend_wait(); 62 | } 63 | 64 | 65 | 66 | @end 67 | -------------------------------------------------------------------------------- /AppPolice/AppInspector/AppInspector.h: -------------------------------------------------------------------------------- 1 | // 2 | // AppInspector.h 3 | // AppPolice 4 | // 5 | // Created by Maksym on 7/2/13. 6 | // Copyright (c) 2013 Maksym Stefanchuk. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | #define APApplicationInfoNameKey @"appInfoNameKey" 12 | #define APApplicationInfoIconKey @"appInfoIconKey" 13 | #define APApplicationInfoPidKey @"appInfoPidKey" 14 | #define APApplicationInfoLimitKey @"appInfoLimitKey" 15 | #define APApplicationInfoUserKey @"appInfoUserKey" 16 | 17 | #define APAppInspectorProcessDidChangeLimit @"appInspectorProcDidChangeLim" 18 | 19 | 20 | @interface AppInspector : NSObject 21 | { 22 | @private 23 | NSMenuItem *_attachedToItem; 24 | IBOutlet NSViewController *_appViewController; 25 | IBOutlet NSView *_appView; 26 | NSTimer *_cpuTimer; 27 | struct { 28 | uint64_t cputime; 29 | uint64_t timestamp; 30 | } _cpuTime; 31 | 32 | IBOutlet NSImageView *_applicationIcon; 33 | IBOutlet NSTextField *_applicationNameTextfield; 34 | IBOutlet NSTextField *_applicationUserTextfield; 35 | IBOutlet NSTextField *_applicationCPUTextfield; 36 | IBOutlet NSTextField *_sliderLimit1Textfield; 37 | IBOutlet NSTextField *_sliderLimit2Textfield; 38 | IBOutlet NSTextField *_sliderLeftTextfield; 39 | IBOutlet NSTextField *_sliderMiddleTextfield; 40 | IBOutlet NSTextField *_sliderRightTextfield; 41 | IBOutlet NSSlider *_slider; 42 | IBOutlet NSLevelIndicator *_levelIndicator; 43 | } 44 | 45 | @property (assign) NSMutableDictionary *applicationInfo; 46 | @property (assign, nonatomic) NSMenuItem *attachedToItem; 47 | @property (readonly) NSView *appView; 48 | 49 | @end 50 | -------------------------------------------------------------------------------- /AppPolice/AppInspector/AppInspector.m: -------------------------------------------------------------------------------- 1 | // 2 | // AppInspector.m 3 | // AppPolice 4 | // 5 | // Created by Maksym on 7/2/13. 6 | // Copyright (c) 2013 Maksym Stefanchuk. All rights reserved. 7 | // 8 | 9 | #import "AppInspector.h" 10 | #import "APPreferencesController.h" 11 | #import "AppLimitSliderCell.h" 12 | #import "AppLimitHintView.h" 13 | #include "app_inspector_c.h" 14 | #include "proc_cpulim.h" 15 | #include 16 | 17 | #define SLIDER_NOT_LIMITED_VALUE [_slider maxValue] 18 | #define NO_LIMIT 0.0 19 | 20 | 21 | @interface AppInspector () 22 | { 23 | BOOL _processIsRunning; 24 | } 25 | 26 | - (void)cpuTimerFire:(NSTimer *)timer; 27 | - (void)updateTextfieldsWithLimitValue:(float)limit; 28 | - (void)setProcessLimit:(float)limit; 29 | - (float)limitFromSliderValue:(double)value; // |limit| is a fraction of 1 for 100% 30 | - (double)sliderValueFromLimit:(float)limit; 31 | - (double)levelIndicatorValueFromCPU:(double)cpu; 32 | 33 | @end 34 | 35 | 36 | 37 | @implementation AppInspector 38 | 39 | @synthesize appView = _appView; 40 | 41 | - (id)init { 42 | self = [super init]; 43 | if (self) { 44 | [NSBundle loadNibNamed:@"AppInspectorView" owner:self]; 45 | } 46 | return self; 47 | } 48 | 49 | 50 | - (void)dealloc { 51 | [super dealloc]; 52 | } 53 | 54 | 55 | - (void)awakeFromNib { 56 | // Set popover content view 57 | [_appViewController setView:_appView]; 58 | int ncpu = system_ncpu(); 59 | 60 | [_slider setContinuous:YES]; 61 | [_slider setTarget:self]; 62 | [_slider setAction:@selector(sliderAction:)]; 63 | [_levelIndicator setWarningValue:5]; 64 | [_levelIndicator setCriticalValue:7.5]; 65 | [_sliderMiddleTextfield setStringValue:[NSString stringWithFormat:@"%d%%", (ncpu > 2) ? 100 : ncpu / 2 * 100]]; 66 | [_sliderRightTextfield setStringValue:[NSString stringWithFormat:@"%d%%", ncpu * 100]]; 67 | 68 | [_applicationNameTextfield setFont:[NSFont systemFontOfSize:14]]; 69 | 70 | /* 71 | [_applicationNameTextfield setDrawsBackground:YES]; 72 | [_applicationNameTextfield setBackgroundColor:[NSColor clearColor]]; 73 | [_applicationUserTextfield setDrawsBackground:YES]; 74 | [_applicationUserTextfield setBackgroundColor:[NSColor clearColor]]; 75 | [_applicationCPUTextfield setDrawsBackground:YES]; 76 | [_applicationCPUTextfield setBackgroundColor:[NSColor clearColor]]; 77 | */ 78 | } 79 | 80 | 81 | - (NSMenuItem *)attachedToItem { 82 | return _attachedToItem; 83 | } 84 | 85 | 86 | /* 87 | * 88 | */ 89 | - (void)setAttachedToItem:(NSMenuItem *)attachedToItem { 90 | if (attachedToItem == _attachedToItem) 91 | return; 92 | 93 | _attachedToItem = attachedToItem; 94 | if (! attachedToItem) 95 | return; 96 | 97 | NSMutableDictionary *applicationInfo = [attachedToItem representedObject]; 98 | if (! applicationInfo) { 99 | NSLog(@"No application info provided with menu item (represented object)."); 100 | return; 101 | } 102 | 103 | NSImage *icon = [applicationInfo objectForKey:APApplicationInfoIconKey]; 104 | NSString *name = [applicationInfo objectForKey:APApplicationInfoNameKey]; 105 | pid_t pid = [(NSNumber *)[applicationInfo objectForKey:APApplicationInfoPidKey] intValue]; 106 | float limit = [(NSNumber *)[applicationInfo objectForKey:APApplicationInfoLimitKey] floatValue]; 107 | 108 | // Technics used to load default images (kept for reference) 109 | // NSImage *genericIcon = [[NSWorkspace sharedWorkspace] iconForFileType:NSFileTypeForHFSTypeCode(kGenericExtensionIcon)]; 110 | // NSImage *genericIcon = [[NSWorkspace sharedWorkspace] iconForFile:@"/bin/ls"]; 111 | 112 | [_applicationIcon setImage:icon]; 113 | [_applicationNameTextfield setStringValue:[NSString stringWithFormat:@"%@ (%d)", name, pid]]; 114 | 115 | 116 | if (_cpuTimer) { 117 | [_cpuTimer invalidate]; 118 | _cpuTimer = nil; 119 | } 120 | 121 | 122 | errno = 0; 123 | // Current cpu time for a process 124 | _cpuTime.cputime = get_proc_cputime(pid); 125 | if (_cpuTime.cputime == 0 && errno != 0) { 126 | _processIsRunning = NO; 127 | if (errno == ESRCH) { 128 | [_applicationUserTextfield setStringValue:NSLocalizedString(@"No such process", @"AppInspector")]; 129 | } else if (errno == EPERM) { 130 | [[_applicationUserTextfield cell] setWraps:YES]; 131 | //[_applicationUserTextfield setPreferredMaxLayoutWidth:150.0]; 132 | [_applicationUserTextfield setStringValue:NSLocalizedString(@"No permission to access process information", @"AppInspector")]; 133 | } else { 134 | [[_applicationUserTextfield cell] setWraps:YES]; 135 | //[_applicationUserTextfield setPreferredMaxLayoutWidth:150.0]; 136 | [_applicationUserTextfield setStringValue:NSLocalizedString(@"Error accessing process information", @"AppInspector")]; 137 | } 138 | [_applicationCPUTextfield setStringValue:@""]; 139 | [_slider setDoubleValue:SLIDER_NOT_LIMITED_VALUE]; 140 | [self updateTextfieldsWithLimitValue:NO_LIMIT]; 141 | [_levelIndicator setDoubleValue:0.0]; 142 | [self setProcessLimit:NO_LIMIT]; 143 | } else { 144 | _processIsRunning = YES; 145 | _cpuTime.timestamp = get_timestamp(); 146 | 147 | // Reset params 148 | if ([[_applicationUserTextfield cell] wraps]) { 149 | [[_applicationUserTextfield cell] setWraps:NO]; 150 | //[_applicationUserTextfield setPreferredMaxLayoutWidth:0.0]; 151 | } 152 | // Basically, we handled to possible process access permission problem above 153 | // so this should always evaluate to true. 154 | char *proc_username = get_proc_username(pid); 155 | if (proc_username) 156 | [_applicationUserTextfield setStringValue:[NSString stringWithFormat:NSLocalizedString(@"User: %@", @"AppInspector process User name"), [NSString stringWithCString:proc_username encoding:NSUTF8StringEncoding]]]; 157 | else 158 | [_applicationUserTextfield setStringValue:[NSString stringWithFormat:NSLocalizedString(@"User: %@", @"AppInspector process User name"), @"-"]]; 159 | [_applicationCPUTextfield setStringValue:@"\% CPU: 0.00"]; 160 | // Update level indicator 161 | [_levelIndicator setFloatValue:0.0]; 162 | // Update slider 163 | if (limit == 0) { 164 | [_slider setDoubleValue:[_slider maxValue]]; 165 | } else { 166 | double sliderValue = [self sliderValueFromLimit:limit]; 167 | [_slider setDoubleValue:sliderValue]; 168 | } 169 | [self updateTextfieldsWithLimitValue:limit]; 170 | 171 | 172 | NSDictionary *timerUserInfo = [NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithInt:pid], @"pid", nil]; 173 | _cpuTimer = [NSTimer timerWithTimeInterval:2.0 target:self selector:@selector(cpuTimerFire:) userInfo:timerUserInfo repeats:YES]; 174 | [[NSRunLoop currentRunLoop] addTimer:_cpuTimer forMode:NSRunLoopCommonModes]; 175 | } 176 | } 177 | 178 | 179 | /* 180 | * 181 | */ 182 | - (void)cpuTimerFire:(NSTimer *)timer { 183 | uint64_t cputime; 184 | uint64_t timestamp; 185 | double cpuload; 186 | pid_t pid; 187 | NSDictionary *userInfo; 188 | 189 | userInfo = [timer userInfo]; 190 | pid = [(NSNumber *)[userInfo objectForKey:@"pid"] intValue]; 191 | errno = 0; 192 | cputime = get_proc_cputime(pid); 193 | 194 | 195 | // Info about the process is not available. Stop polling 196 | if (cputime == 0 && errno != 0) { 197 | _processIsRunning = NO; 198 | if (errno == ESRCH) { 199 | [_applicationUserTextfield setStringValue:NSLocalizedString(@"No such process", @"AppInspector")]; 200 | } else if (errno == EPERM) { 201 | [[_applicationUserTextfield cell] setWraps:YES]; 202 | //[_applicationUserTextfield setPreferredMaxLayoutWidth:150.0]; 203 | [_applicationUserTextfield setStringValue:NSLocalizedString(@"No permission to access process information", @"AppInspector")]; 204 | } else { 205 | [[_applicationUserTextfield cell] setWraps:YES]; 206 | //[_applicationUserTextfield setPreferredMaxLayoutWidth:150.0]; 207 | [_applicationUserTextfield setStringValue:NSLocalizedString(@"Error accessing process information", @"AppInspector")]; 208 | } 209 | [_applicationCPUTextfield setStringValue:@""]; 210 | [_slider setDoubleValue:SLIDER_NOT_LIMITED_VALUE]; 211 | [self updateTextfieldsWithLimitValue:NO_LIMIT]; 212 | [_levelIndicator setDoubleValue:0.0]; 213 | [self setProcessLimit:NO_LIMIT]; 214 | 215 | [_cpuTimer invalidate]; 216 | _cpuTimer = nil; 217 | return; 218 | } 219 | 220 | timestamp = get_timestamp(); 221 | 222 | // First run: write values and continue 223 | if (_cpuTime.cputime == 0) { 224 | _cpuTime.cputime = cputime; 225 | _cpuTime.timestamp = timestamp; 226 | return; 227 | } 228 | 229 | 230 | cpuload = (double)(cputime - _cpuTime.cputime) / (timestamp - _cpuTime.timestamp) * 100; 231 | _cpuTime.cputime = cputime; 232 | _cpuTime.timestamp = timestamp; 233 | 234 | [_applicationCPUTextfield setStringValue:[NSString stringWithFormat:@"%% CPU: %.2f", cpuload]]; 235 | [_levelIndicator setDoubleValue:[self levelIndicatorValueFromCPU:cpuload]]; 236 | } 237 | 238 | 239 | /* 240 | * 241 | */ 242 | - (void)sliderAction:(id)sender { 243 | double value = [_slider doubleValue]; 244 | float limit; 245 | if (value == [_slider maxValue]) 246 | limit = NO_LIMIT; 247 | else 248 | limit = [self limitFromSliderValue:value]; 249 | 250 | [self updateTextfieldsWithLimitValue:limit]; 251 | 252 | NSEvent *theEvent = [NSApp currentEvent]; 253 | NSEventType eventType = [theEvent type]; 254 | 255 | if (eventType == NSLeftMouseUp) { // update applicatoinInfo when slider is released 256 | [self setProcessLimit:limit]; 257 | } 258 | } 259 | 260 | 261 | /* 262 | * 263 | */ 264 | - (void)updateTextfieldsWithLimitValue:(float)limit { 265 | if (limit == NO_LIMIT) { 266 | [_sliderLimit2Textfield setStringValue:NSLocalizedString(@"Not limited", @"AppInspector slider Not limiter")]; 267 | } else { 268 | int percents; 269 | percents = (int)floor(limit * 100 + 0.5); 270 | if (percents < 1) 271 | percents = 1; 272 | [_sliderLimit2Textfield setStringValue:[NSString stringWithFormat:@"%d%%", percents]]; 273 | } 274 | } 275 | 276 | 277 | /* 278 | * 279 | */ 280 | - (void)setProcessLimit:(float)limit { 281 | // Update the attached-to menu item state 282 | if (! _attachedToItem) 283 | return; 284 | 285 | if (! _processIsRunning) 286 | limit = NO_LIMIT; 287 | 288 | NSMutableDictionary *applicationInfo = [_attachedToItem representedObject]; 289 | [applicationInfo setObject:[NSNumber numberWithFloat:limit] forKey:APApplicationInfoLimitKey]; 290 | 291 | NSString *applicationName = [applicationInfo valueForKey:APApplicationInfoNameKey]; 292 | if (applicationName != nil && [applicationName length] > 0) { 293 | NSUserDefaults *preferences = [NSUserDefaults standardUserDefaults]; 294 | NSMutableDictionary *storedApplicationLimits = [[preferences valueForKey:kPrefApplicationLimits] mutableCopy]; 295 | if (storedApplicationLimits == nil) { 296 | storedApplicationLimits = [NSMutableDictionary new]; 297 | } 298 | if (limit == NO_LIMIT) { 299 | if ([storedApplicationLimits objectForKey:applicationName] != nil) { 300 | [storedApplicationLimits removeObjectForKey:applicationName]; 301 | } 302 | } else { 303 | [storedApplicationLimits setValue:[NSNumber numberWithFloat:limit] forKey:applicationName]; 304 | } 305 | [preferences setObject:storedApplicationLimits forKey:kPrefApplicationLimits]; 306 | } 307 | 308 | NSNumber *pid_n = [applicationInfo objectForKey:APApplicationInfoPidKey]; 309 | pid_t pid = [pid_n intValue]; 310 | // Set limit for process and start limiter in case it's not already running 311 | proc_cpulim_set(pid, limit); 312 | // proc_cpulim_resume(); 313 | 314 | // Post notification about process changed limit 315 | NSDictionary *userInfo = @{ 316 | @"menuItem" : _attachedToItem 317 | }; 318 | NSNotification *postNotification = [NSNotification notificationWithName:APAppInspectorProcessDidChangeLimit object:self userInfo:userInfo]; 319 | [[NSNotificationQueue defaultQueue] enqueueNotification:postNotification 320 | postingStyle:NSPostNow 321 | coalesceMask:NSNotificationCoalescingOnName 322 | forModes:[NSArray arrayWithObject:NSRunLoopCommonModes]]; 323 | 324 | } 325 | 326 | 327 | /* 328 | * 329 | */ 330 | - (float)limitFromSliderValue:(double)value { 331 | double maxValue = [_slider maxValue]; 332 | double minValue = [_slider minValue]; 333 | double rangeOfValues; 334 | double middleRange; 335 | float limit; 336 | int ncpu; 337 | 338 | if (value == maxValue) 339 | return 0; 340 | 341 | value -= minValue; 342 | rangeOfValues = maxValue - minValue; 343 | rangeOfValues -= maxValue / ([_slider numberOfTickMarks] - 1); // last mark is deducted from the range 344 | middleRange = rangeOfValues / 2; 345 | ncpu = system_ncpu(); 346 | 347 | if (ncpu > 2) { 348 | if (value <= middleRange) 349 | limit = (float)(value / middleRange); 350 | else 351 | limit = (float)((value - middleRange) / middleRange * (ncpu - 1) + 1); 352 | } else { 353 | if (value > rangeOfValues) 354 | value = rangeOfValues; 355 | 356 | limit = (float)(value / rangeOfValues * ncpu); 357 | } 358 | 359 | if (limit < 0.01f) 360 | limit = 0.01f; 361 | 362 | return limit; 363 | } 364 | 365 | 366 | - (double)sliderValueFromLimit:(float)limit { 367 | double maxValue = [_slider maxValue]; 368 | double minValue = [_slider minValue]; 369 | double rangeOfValues; 370 | double value; 371 | int ncpu; 372 | 373 | if (limit == 0) 374 | return maxValue; 375 | 376 | ncpu = system_ncpu(); 377 | rangeOfValues = maxValue - minValue; 378 | rangeOfValues -= maxValue / ([_slider numberOfTickMarks] - 1); // deduct one tick mark 379 | 380 | // If there are more that 2 CPUs we take half of the slider width 381 | // to show 100%. Other half will show (ncpu - 1) * 100% 382 | if (ncpu > 2) { 383 | double middleRange = rangeOfValues / 2; 384 | if (limit <= 1) 385 | value = limit * middleRange; 386 | else 387 | value = (limit - 1) / (ncpu - 1) * middleRange + middleRange; 388 | } else { 389 | value = limit / ncpu * rangeOfValues; 390 | } 391 | 392 | // offset |value| back by minValue 393 | if (minValue) 394 | value += minValue; 395 | 396 | return value; 397 | } 398 | 399 | 400 | - (double)levelIndicatorValueFromCPU:(double)cpu { 401 | double minValue = [_levelIndicator minValue]; 402 | double maxValue = [_levelIndicator maxValue]; 403 | double rangeOfValues; 404 | double value; 405 | int ncpu; 406 | 407 | if (cpu == 0) 408 | return minValue; 409 | 410 | ncpu = system_ncpu(); 411 | rangeOfValues = maxValue - minValue; 412 | 413 | 414 | if (ncpu > 2) { 415 | double middleRange = rangeOfValues / 2; 416 | if (cpu <= 100.0) { 417 | value = cpu / 100 * middleRange; 418 | } else { 419 | value = (cpu / 100.0 - 1) / (ncpu - 1) * middleRange + middleRange; 420 | } 421 | } else { 422 | value = cpu / 100 / ncpu * rangeOfValues; 423 | } 424 | 425 | if (minValue) 426 | value += minValue; 427 | 428 | return value; 429 | } 430 | 431 | @end 432 | -------------------------------------------------------------------------------- /AppPolice/AppInspector/AppLimitHintView.h: -------------------------------------------------------------------------------- 1 | // 2 | // AppLimitHintView.h 3 | // AppPolice 4 | // 5 | // Created by Maksym on 10/9/13. 6 | // Copyright (c) 2013 Maksym Stefanchuk. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @protocol AppLimitHintViewDelegate; 12 | 13 | #define APAppLimitHintMouseDownNotification @"appLimitHintMouseDownNotification" 14 | 15 | 16 | @interface AppLimitHintView : NSView 17 | { 18 | @private 19 | IBOutlet NSImageView *_hintImage; 20 | NSTrackingArea *_trackingArea; 21 | BOOL _observingAppInspectorNotifications; 22 | } 23 | @end 24 | -------------------------------------------------------------------------------- /AppPolice/AppInspector/AppLimitHintView.m: -------------------------------------------------------------------------------- 1 | // 2 | // AppLimitHintView.m 3 | // AppPolice 4 | // 5 | // Created by Maksym on 10/9/13. 6 | // Copyright (c) 2013 Maksym Stefanchuk. All rights reserved. 7 | // 8 | 9 | #import "AppInspector.h" 10 | #import "AppLimitHintView.h" 11 | 12 | @implementation AppLimitHintView 13 | 14 | 15 | - (void)dealloc { 16 | [_trackingArea release]; 17 | [[NSNotificationCenter defaultCenter] removeObserver:self]; 18 | [super dealloc]; 19 | } 20 | 21 | 22 | - (void)viewDidMoveToSuperview { 23 | [self updateTrackingAreas]; 24 | } 25 | 26 | 27 | - (void)updateTrackingAreas { 28 | if (_trackingArea) { 29 | [self removeTrackingArea:_trackingArea]; 30 | [_trackingArea release]; 31 | _trackingArea = nil; 32 | } 33 | 34 | NSTrackingAreaOptions options = NSTrackingActiveAlways | NSTrackingMouseEnteredAndExited; 35 | _trackingArea = [[NSTrackingArea alloc] initWithRect:[self bounds] options:options owner:self userInfo:nil]; 36 | [self addTrackingArea:_trackingArea]; 37 | 38 | // Run RunLoop in default mode for AppKit to update tracking areas 39 | CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0, YES); 40 | } 41 | 42 | 43 | - (void)mouseEntered:(NSEvent *)theEvent { 44 | [_hintImage setAlphaValue:0]; 45 | [_hintImage setHidden:NO]; 46 | [[NSAnimationContext currentContext] setDuration:0.08]; 47 | [[_hintImage animator] setAlphaValue:1.0]; 48 | } 49 | 50 | 51 | - (void)mouseExited:(NSEvent *)theEvent { 52 | [_hintImage setHidden:YES]; 53 | // [NSAnimationContext beginGrouping]; 54 | // [[NSAnimationContext currentContext] setDuration:0.1]; 55 | // [[NSAnimationContext currentContext] setCompletionHandler:^(void) { 56 | // [_hintImage setHidden:YES]; 57 | // }]; 58 | // [[_hintImage animator] setAlphaValue:0]; 59 | // [NSAnimationContext endGrouping]; 60 | } 61 | 62 | 63 | - (void)mouseDown:(NSEvent *)theEvent { 64 | NSNotification *notification = [NSNotification notificationWithName:APAppLimitHintMouseDownNotification object:self userInfo:nil]; 65 | [[NSNotificationQueue defaultQueue] enqueueNotification:notification 66 | postingStyle:NSPostASAP 67 | coalesceMask:NSNotificationCoalescingOnName 68 | forModes:[NSArray arrayWithObject:NSRunLoopCommonModes]]; 69 | 70 | // [super mouseUp:theEvent]; 71 | } 72 | 73 | @end 74 | -------------------------------------------------------------------------------- /AppPolice/AppInspector/AppLimitSliderCell.h: -------------------------------------------------------------------------------- 1 | // 2 | // AppLimitSliderCell.h 3 | // AppPolice 4 | // 5 | // Created by Maksym on 10/8/13. 6 | // Copyright (c) 2013 Maksym Stefanchuk. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface AppLimitSliderCell : NSSliderCell 12 | { 13 | @private 14 | NSInteger _penultimateTickMark; // the next to last tick mark 15 | NSRect _penultimateTickMarkRect; 16 | CGFloat _offsetFromKnobCenter; 17 | } 18 | 19 | @end 20 | -------------------------------------------------------------------------------- /AppPolice/AppInspector/AppLimitSliderCell.m: -------------------------------------------------------------------------------- 1 | // 2 | // AppLimitSliderCell.m 3 | // AppPolice 4 | // 5 | // Created by Maksym on 10/8/13. 6 | // Copyright (c) 2013 Maksym Stefanchuk. All rights reserved. 7 | // 8 | 9 | #import "AppLimitSliderCell.h" 10 | 11 | @implementation AppLimitSliderCell 12 | 13 | 14 | - (BOOL)startTrackingAt:(NSPoint)startPoint inView:(NSView *)controlView { 15 | _penultimateTickMark = [self numberOfTickMarks] - 2; 16 | _penultimateTickMarkRect = [self rectOfTickMarkAtIndex:_penultimateTickMark]; 17 | 18 | NSRect knobRect = [self knobRectFlipped:[controlView isFlipped]]; 19 | CGFloat knobThickness = [self knobThickness]; 20 | _offsetFromKnobCenter = startPoint.x - knobRect.origin.x - knobThickness / 2; 21 | if (ABS(_offsetFromKnobCenter) > knobThickness / 2) 22 | _offsetFromKnobCenter = 0; 23 | 24 | // NSLog(@"Start tracking, value: %f", [self floatValue]); 25 | // NSLog(@"Start tracking, offset from knob: %f\tstart point: %@", _offsetFromKnobCenter, NSStringFromPoint(startPoint)); 26 | 27 | // When the mouse is down between penultimate and final tick marks 28 | // the slider is not yet sticky and the value is wrong. Run the method 29 | // manually once to validate mouse starting point. 30 | (void) [self continueTracking:NSMakePoint(0, 0) at:startPoint inView:controlView]; 31 | 32 | return [super startTrackingAt:startPoint inView:controlView]; 33 | } 34 | 35 | 36 | - (BOOL)continueTracking:(NSPoint)lastPoint at:(NSPoint)currentPoint inView:(NSView *)controlView { 37 | CGFloat value = [self floatValue]; 38 | // NSLog(@"value: %f\t last: %f\t current: %f \t delta: %f", value, lastPoint.x, currentPoint.x, _offsetFromKnobCenter); 39 | 40 | if (currentPoint.x > _penultimateTickMarkRect.origin.x + _offsetFromKnobCenter) { 41 | [self setAllowsTickMarkValuesOnly:YES]; 42 | 43 | // NSSlider value is not being updated once NSSliderCell sets allowsTickMarkValuesOnly. 44 | // Send the finalizing action manually. 45 | NSSlider *slider = (NSSlider *)controlView; 46 | if (value != [slider floatValue]) { 47 | [NSApp sendAction:[self action] to:[self target] from:self]; 48 | } 49 | } else if ([self allowsTickMarkValuesOnly]) { 50 | [self setAllowsTickMarkValuesOnly:NO]; 51 | } 52 | 53 | return [super continueTracking:lastPoint at:currentPoint inView:controlView]; 54 | } 55 | 56 | 57 | @end 58 | -------------------------------------------------------------------------------- /AppPolice/AppInspector/AppLoadLevelIndicator.h: -------------------------------------------------------------------------------- 1 | // 2 | // AppLoadLevelIndicator.h 3 | // AppPolice 4 | // 5 | // Created by Maksym on 10/7/13. 6 | // Copyright (c) 2013 Maksym Stefanchuk. All rights reserved. 7 | // 8 | 9 | 10 | @class NSLevelIndicator; 11 | 12 | @interface AppLoadLevelIndicator : NSLevelIndicator 13 | 14 | @end 15 | -------------------------------------------------------------------------------- /AppPolice/AppInspector/AppLoadLevelIndicator.m: -------------------------------------------------------------------------------- 1 | // 2 | // AppLoadLevelIndicator.m 3 | // AppPolice 4 | // 5 | // Created by Maksym on 10/7/13. 6 | // Copyright (c) 2013 Maksym Stefanchuk. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "AppLoadLevelIndicator.h" 11 | 12 | @implementation AppLoadLevelIndicator 13 | 14 | 15 | // Draw custom Level Indicator 16 | - (void)drawRect:(NSRect)dirtyRect { 17 | // [super drawRect:dirtyRect]; 18 | 19 | NSRect rect = [self bounds]; 20 | float value = [self floatValue]; 21 | double minValue = [self minValue]; 22 | double maxValue = [self maxValue]; 23 | double percents = (value - minValue) / (maxValue - minValue); 24 | CGFloat x = rect.size.width * percents; 25 | double warningValue = [self warningValue]; 26 | double criticalValue = [self criticalValue]; 27 | 28 | [[NSColor colorWithCalibratedRed:0.7 green:0.7 blue:0.7 alpha:0.95] setFill]; 29 | NSRectFill(rect); 30 | 31 | if (value < warningValue) { 32 | // [[NSColor colorWithCalibratedRed:0.031 green:0.7 blue:0.33 alpha:1.0] setFill]; 33 | [[NSColor colorWithCalibratedRed:0.0 green:0.82 blue:0.36 alpha:1.0] setFill]; 34 | } else if (value < criticalValue) { 35 | // [[NSColor colorWithCalibratedRed:0.87 green:0.74 blue:0.0 alpha:1.0] setFill]; 36 | // [[NSColor colorWithCalibratedRed:0.72 green:0.82 blue:0.0 alpha:1.0] setFill]; 37 | [[NSColor colorWithCalibratedRed:0.8 green:0.7 blue:0.1 alpha:1.0] setFill]; 38 | } else { 39 | [[NSColor colorWithCalibratedRed:1.0 green:0.38 blue:0.38 alpha:1.0] setFill]; 40 | } 41 | NSRectFill(NSMakeRect(rect.origin.x, rect.origin.y, x, rect.size.height)); 42 | } 43 | 44 | @end 45 | -------------------------------------------------------------------------------- /AppPolice/AppPolice-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | ${EXECUTABLE_NAME} 9 | CFBundleIdentifier 10 | com.definemac.${PRODUCT_NAME:rfc1034identifier} 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | ${PRODUCT_NAME} 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | 1.2 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 3 23 | LSApplicationCategoryType 24 | public.app-category.utilities 25 | LSMinimumSystemVersion 26 | ${MACOSX_DEPLOYMENT_TARGET} 27 | LSUIElement 28 | 29 | NSHumanReadableCopyright 30 | Copyright © 2015 Maksym Stefanchuk 31 | NSMainNibFile 32 | MainMenu 33 | NSPrincipalClass 34 | NSApplication 35 | 36 | 37 | -------------------------------------------------------------------------------- /AppPolice/AppPolice-Prefix.pch: -------------------------------------------------------------------------------- 1 | // 2 | // Prefix header for all source files of the 'AppPolice' target in the 'AppPolice' project 3 | // 4 | 5 | #ifdef __OBJC__ 6 | #import 7 | #import "NSMenu+APAdditions.h" 8 | #import "NSMenuItem+APAdditions.h" 9 | #endif 10 | -------------------------------------------------------------------------------- /AppPolice/AppPolice.entitlements: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /AppPolice/C/app_inspector_c.c: -------------------------------------------------------------------------------- 1 | // 2 | // app_inspector_c.c 3 | // AppPolice 4 | // 5 | // Created by Maksym on 30/10/13. 6 | // Copyright (c) 2013 Maksym Stefanchuk. All rights reserved. 7 | // 8 | 9 | #include 10 | #include /* sysctl() */ 11 | #include /* sysconf(_SC_NPROCESSORS_ONLN) */ 12 | #include /* proc_pidinfo() */ 13 | #include /* getpwuid() */ 14 | #include /* mach_absolute_time() */ 15 | #include 16 | #include /* errno */ 17 | //#include /* strerror() */ 18 | 19 | #include "app_inspector_c.h" 20 | 21 | 22 | 23 | /* 24 | * Return number of CPUs in computer 25 | */ 26 | int system_ncpu(void) { 27 | static int ncpu = 0; 28 | if (ncpu) 29 | return ncpu; 30 | 31 | #ifdef _SC_NPROCESSORS_ONLN 32 | ncpu = (int)sysconf(_SC_NPROCESSORS_ONLN); 33 | #else 34 | int mib[2]; 35 | mib[0] = CTL_HW; 36 | mig[1] = HW_NCPU; 37 | size_t len = sizeof(ncpu); 38 | sysctl(mib, 2, &ncpu, &len, NULL, 0); 39 | #endif 40 | return ncpu; 41 | } 42 | 43 | 44 | /* 45 | * 46 | */ 47 | char *get_proc_username(pid_t pid) { 48 | int numbytes; 49 | struct passwd *pwdinfo; 50 | struct proc_bsdshortinfo bsdinfo; 51 | 52 | errno = 0; 53 | numbytes = proc_pidinfo(pid, PROC_PIDT_SHORTBSDINFO, (uint64_t)0, &bsdinfo, PROC_PIDT_SHORTBSDINFO_SIZE); 54 | if (numbytes <= 0) { 55 | if (errno == EPERM) 56 | (void) fprintf(stderr, "\nUser is not permitted to get info about process: %d", pid); 57 | return NULL; 58 | } 59 | pwdinfo = getpwuid(bsdinfo.pbsi_uid); 60 | 61 | return pwdinfo->pw_name; 62 | } 63 | 64 | 65 | /* 66 | * 67 | */ 68 | uid_t get_proc_uid(pid_t pid) { 69 | int numbytes; 70 | struct proc_bsdshortinfo bsdinfo; 71 | 72 | errno = 0; 73 | numbytes = proc_pidinfo(pid, PROC_PIDT_SHORTBSDINFO, (uint64_t)0, &bsdinfo, PROC_PIDT_SHORTBSDINFO_SIZE); 74 | if (numbytes <= 0) { 75 | if (errno == EPERM) 76 | (void) fprintf(stderr, "\nUser is not permitted to get info about process: %d", pid); 77 | return UINT32_MAX; 78 | } 79 | 80 | return bsdinfo.pbsi_uid; 81 | } 82 | 83 | 84 | /* 85 | * 86 | */ 87 | uint64_t get_proc_cputime(pid_t pid) { 88 | int numbytes; 89 | struct proc_taskinfo ptinfo; 90 | 91 | errno = 0; 92 | numbytes = proc_pidinfo(pid, PROC_PIDTASKINFO, (uint64_t)0, &ptinfo, PROC_PIDTASKINFO_SIZE); 93 | if (numbytes <= 0) { 94 | if (errno == EPERM) 95 | (void) fprintf(stderr, "User is not permitted to get info about process: %d\n", pid); 96 | // else 97 | // (void) fprintf(stderr, "\nGet process %d info error: %s", pid, strerror(errno)); 98 | return 0; 99 | } 100 | 101 | return (ptinfo.pti_total_user + ptinfo.pti_total_system); 102 | } 103 | 104 | 105 | /* 106 | * 107 | */ 108 | uint64_t get_timestamp(void) { 109 | uint64_t timestamp; 110 | uint64_t mach_time; 111 | static mach_timebase_info_data_t sTimebaseInfo; 112 | 113 | // See "Mach Absolute Time Units" for instructions: 114 | // https://developer.apple.com/library/mac/qa/qa1398/ 115 | mach_time = mach_absolute_time(); 116 | if (sTimebaseInfo.denom == 0) { 117 | (void) mach_timebase_info(&sTimebaseInfo); 118 | } 119 | timestamp = mach_time * sTimebaseInfo.numer / sTimebaseInfo.denom; 120 | return timestamp; 121 | } 122 | 123 | 124 | /* 125 | * 126 | */ 127 | int proc_name_from_path(char name[], const char path[], int maxlen) { 128 | int pos = -1; 129 | int i = 0; 130 | for (i = 0; path[i] != '\0'; ++i) { 131 | if (path[i] == '/') 132 | pos = i; 133 | } 134 | if (pos == -1) 135 | return 0; 136 | 137 | i = 0; 138 | ++pos; 139 | // Copy substring 140 | while ((name[i++] = path[pos++]) && i < maxlen) 141 | ; 142 | // Make sure the string is always properly terminated 143 | name[maxlen - 1] = '\0'; 144 | return (i - 1); 145 | } 146 | -------------------------------------------------------------------------------- /AppPolice/C/app_inspector_c.h: -------------------------------------------------------------------------------- 1 | // 2 | // app_inspector_c.h 3 | // AppPolice 4 | // 5 | // Created by Maksym on 30/10/13. 6 | // Copyright (c) 2013 Maksym Stefanchuk. All rights reserved. 7 | // 8 | 9 | #ifndef AppPolice_app_inspector_c_h 10 | #define AppPolice_app_inspector_c_h 11 | 12 | #include 13 | #include 14 | 15 | // Return number of CPUs in computer 16 | int system_ncpu(void); 17 | 18 | // Return pointer to a string containing username of a provided process id 19 | char *get_proc_username(pid_t pid); 20 | 21 | // Return process uid if successful or, UINT32_MAX otherwise. 22 | uid_t get_proc_uid(pid_t pid); 23 | 24 | // Return current CPU time for a process id 25 | uint64_t get_proc_cputime(pid_t pid); 26 | 27 | // Return timestemp in nanoseconds 28 | uint64_t get_timestamp(void); 29 | 30 | // Sets "logind" into provided |name| buffer for the path 31 | // like "/System/Library/CoreServices/logind" 32 | // Returns the number of chars written 33 | int proc_name_from_path(char name[], const char path[], int maxlen); 34 | 35 | 36 | 37 | #endif 38 | -------------------------------------------------------------------------------- /AppPolice/C/proc_cpulim.c: -------------------------------------------------------------------------------- 1 | // 2 | // proc_cpulim.c 3 | // proc_cpulim 4 | // 5 | // Created by Maksym on 5/19/13. 6 | // Copyright (c) 2013 Maksym Stefanchuk. All rights reserved. 7 | // 8 | 9 | 10 | #include 11 | #include /* malloc */ 12 | #include /* memset */ 13 | #include /* nanosleep */ 14 | #include 15 | #include 16 | #include /* proc_pidinfo */ 17 | #include /* dispatch_queue */ 18 | #include 19 | #include /* errno */ 20 | 21 | #include "proc_cpulim.h" 22 | 23 | 24 | #define TASK_SCHEDULE_INTERVAL_MIN 1000000 // 1ms 25 | #define DISPATCH_QUEUE_LIMITER 0 26 | #define DISPATCH_QUEUE_UPDTASKSTATS 1 27 | 28 | 29 | /**************** Private Declarations ****************/ 30 | 31 | /* options */ 32 | static short opt_verbose_level = 0; 33 | 34 | struct proc_taskstats_s { 35 | pid_t pid; 36 | float lim; /* fraction, 1 is 100% for 1 core */ 37 | uint64_t time; /* process system_time + user_time */ 38 | uint64_t sleep_time; 39 | int is_sleeping; 40 | struct proc_taskstats_s *next; 41 | }; 42 | typedef struct proc_taskstats_s *proc_taskstats_t; 43 | 44 | static proc_taskstats_t _proc_taskstats_list; /* pointer to the first task in list */ 45 | 46 | /* This option corresponds for how often proc_cpulim will wake up to monitor processes. 47 | Value is in nanoseconds, for example 200000000 means proc_cpulim will be awake 48 | every 0.2s to reschedule processes for sleep time. This value should never be zero. */ 49 | static uint64_t _task_schedule_interval = 30000000; // default is 30ms 50 | static int _keep_limiter_running; 51 | // Global variable _keep_limiter_running specifies whether limiter should run 52 | // or not. When _keep_limiter_running is set to 0 limiter could still be running 53 | // until all tasks in queue are processed. _limit_is_running on other other hand 54 | // tells whether limiter is running at this moment or not. 55 | static int _limiter_is_running; 56 | static volatile int32_t _managing_dispatch_queue_locked; // safely create, return or release queue 57 | 58 | static void do_proc_cpulim_set(int pid, float newlim); 59 | static void proc_limiter_resume(void); 60 | static uint64_t do_sleep_loop(void); 61 | static uint proc_tasks_calcsleeptime(void); 62 | static uint64_t proc_tasks_execsleeptime(void); 63 | static void proc_task_delete(pid_t pid); 64 | static void do_proc_task_delete(pid_t pid); 65 | static void reset_all_taskstats(void); 66 | 67 | // Internally count the number of queue operators. 68 | // When the number reaches zero call libdispatch's release. 69 | typedef struct { 70 | dispatch_queue_t queue; 71 | int refcnt; 72 | } _proc_cpulim_dispatch_queue_t; 73 | // These variables should never be used directly! Instead 74 | // use get_dispatch_queue() with proper type specified: 75 | // DISPATCH_QUEUE_LIMITER or 76 | // DISPATCH_QUEUE_UPDTASKSTATS 77 | // The call needs to be paired with according release_dispatch_queue(). 78 | static _proc_cpulim_dispatch_queue_t _limiter_queue; 79 | static _proc_cpulim_dispatch_queue_t _updtaskstats_queue; 80 | 81 | static dispatch_queue_t get_dispatch_queue(int type); 82 | static void release_dispatch_queue(int type); 83 | 84 | static struct timespec timespec_from_ns(int64_t nanoseconds); 85 | 86 | 87 | 88 | 89 | 90 | int proc_cpulim_set(int pid, float newlim) { 91 | short einval = 1; 92 | pid_t shared_pid = getpid(); 93 | 94 | if (pid < 1 || pid == shared_pid || newlim < 0) 95 | return einval; 96 | 97 | dispatch_queue_t updtaskstats_queue = get_dispatch_queue(DISPATCH_QUEUE_UPDTASKSTATS); 98 | 99 | // fputs("\nSetting new lim on queue", stdout); 100 | // fflush(stdout); 101 | // dispatch_debug(updtaskstats_queue, "setting queue"); 102 | 103 | dispatch_async(updtaskstats_queue, ^{ 104 | do_proc_cpulim_set(pid, newlim); 105 | release_dispatch_queue(DISPATCH_QUEUE_UPDTASKSTATS); 106 | }); 107 | 108 | return 0; 109 | } 110 | 111 | 112 | /* 113 | * 114 | */ 115 | static void do_proc_cpulim_set(int pid, float newlim) { 116 | /* if there are no tasks yet */ 117 | if (_proc_taskstats_list == NULL) { 118 | if (newlim == 0) 119 | return; 120 | 121 | proc_taskstats_t task; 122 | task = (proc_taskstats_t)xmalloc(sizeof(struct proc_taskstats_s)); 123 | task->pid = pid; 124 | task->lim = newlim; 125 | task->time = 0; 126 | task->sleep_time = 0; 127 | task->is_sleeping = 0; 128 | task->next = NULL; 129 | _proc_taskstats_list = task; // make list point to the first task 130 | 131 | return; 132 | } 133 | 134 | 135 | proc_taskstats_t task; 136 | 137 | 138 | /* if found task with pid -- update it */ 139 | for (task = _proc_taskstats_list; task != NULL; task = task->next) { 140 | if (task->pid == pid) { 141 | if (newlim == 0) 142 | proc_task_delete(pid); 143 | else 144 | task->lim = newlim; 145 | return; 146 | } 147 | } 148 | 149 | 150 | /* if no task with such pid */ 151 | if (newlim == 0) 152 | return; 153 | 154 | proc_taskstats_t head = _proc_taskstats_list; 155 | proc_taskstats_t newtask = (proc_taskstats_t)xmalloc(sizeof(struct proc_taskstats_s)); 156 | newtask->pid = pid; 157 | newtask->lim = newlim; 158 | newtask->time = 0; 159 | newtask->sleep_time = 0; 160 | newtask->is_sleeping = 0; 161 | newtask->next = head; 162 | _proc_taskstats_list = newtask; 163 | } 164 | 165 | 166 | /* 167 | * 168 | */ 169 | void proc_cpulim_resume(void) { 170 | if (_keep_limiter_running) 171 | return; 172 | 173 | if (_limiter_is_running) { 174 | if (opt_verbose_level) { 175 | fputs("[proc_cpulim] Info: Limiter is still running. Try when it's fully stopped.\n", stdout); 176 | fflush(stdout); 177 | } 178 | return; 179 | } 180 | 181 | 182 | _limiter_is_running = 1; 183 | _keep_limiter_running = 1; 184 | dispatch_queue_t limiter_queue = get_dispatch_queue(DISPATCH_QUEUE_LIMITER); 185 | 186 | dispatch_async(limiter_queue, ^{ 187 | proc_limiter_resume(); 188 | 189 | // The code below is going to be executed only after proc_limiter_resume() has returned. 190 | // It will return only if proc_cpulim_suspend() or proc_cpulim_suspend_wait() has been called 191 | // and the value of '_keep_limiter_running' has been set to 0. 192 | // Either of the 'suspend' functions could be called either: 193 | // - by the user directly; or 194 | // - internally, when there are no tasks left with non-zero limit level. 195 | 196 | release_dispatch_queue(DISPATCH_QUEUE_LIMITER); 197 | _limiter_is_running = 0; 198 | }); 199 | } 200 | 201 | 202 | /* 203 | * 204 | */ 205 | static void proc_limiter_resume(void) { 206 | struct timespec sleepspec; 207 | int64_t sleepns; 208 | __block uint64_t loop_slept; 209 | dispatch_queue_t updtaskstats_queue; 210 | 211 | /* before resuming, make sure some values are valid */ 212 | if (_task_schedule_interval < 1) 213 | return; 214 | 215 | updtaskstats_queue = get_dispatch_queue(DISPATCH_QUEUE_UPDTASKSTATS); 216 | 217 | // fputs("\nResuming on queue:\n", stdout); 218 | // fflush(stdout); 219 | // dispatch_debug(updtaskstats_queue, "resuming queue"); 220 | 221 | dispatch_async(updtaskstats_queue, ^{ 222 | reset_all_taskstats(); 223 | }); 224 | 225 | while (_keep_limiter_running) { 226 | // While the processes, that need to, are sleeping tasks info data is being read. 227 | // We protect it by making all read/write changes to this info only happend 228 | // in serial dispatch queue "updtaskstats_queue". 229 | dispatch_sync(updtaskstats_queue, ^{ 230 | loop_slept = do_sleep_loop(); 231 | }); 232 | 233 | sleepns = (int64_t)(_task_schedule_interval - loop_slept); 234 | if (sleepns > 0) { 235 | sleepspec = timespec_from_ns(sleepns); 236 | nanosleep(&sleepspec, NULL); 237 | } 238 | } 239 | 240 | release_dispatch_queue(DISPATCH_QUEUE_UPDTASKSTATS); 241 | } 242 | 243 | 244 | /* 245 | * Return total number of nanoseconds slept 246 | */ 247 | static uint64_t do_sleep_loop(void) { 248 | uint ntasks_with_lim; 249 | uint64_t sleptns; 250 | 251 | ntasks_with_lim = proc_tasks_calcsleeptime(); 252 | if (ntasks_with_lim == 0) { 253 | if (opt_verbose_level) 254 | fputs("[proc_cpulim] Info: There are no process tasks with limits.\n", stdout); 255 | proc_cpulim_suspend(); 256 | return 0; 257 | } 258 | sleptns = proc_tasks_execsleeptime(); 259 | 260 | return sleptns; 261 | } 262 | 263 | 264 | /* 265 | * Calculate how much time each task should sleep. 266 | * Return number of tasks that have sleep_time set. 267 | */ 268 | static uint proc_tasks_calcsleeptime(void) { 269 | struct proc_taskinfo ptinfo; 270 | int numbytes; // number of bytes returned by proc_pidinfo() 271 | uint64_t time_prev; 272 | uint64_t time_diff; 273 | int64_t sleep_time; 274 | int64_t work_time; 275 | float cpuload; 276 | proc_taskstats_t task; 277 | uint ntasks_with_lim; 278 | 279 | ntasks_with_lim = 0; 280 | for (task = _proc_taskstats_list; task != NULL; task = task->next) { 281 | if (task->lim == 0) 282 | continue; 283 | 284 | ++ntasks_with_lim; 285 | errno = 0; 286 | numbytes = proc_pidinfo(task->pid, PROC_PIDTASKINFO, (uint64_t)0, &ptinfo, PROC_PIDTASKINFO_SIZE); 287 | if (numbytes <= 0) { 288 | if (errno == ESRCH && opt_verbose_level) 289 | (void) fprintf(stdout, "[proc_cpulim] Info: process %d not found. Removing from the list\n", task->pid); 290 | proc_task_delete(task->pid); 291 | continue; 292 | } 293 | 294 | time_prev = task->time; 295 | task->time = ptinfo.pti_total_system + ptinfo.pti_total_user; 296 | 297 | 298 | if (time_prev == 0) { 299 | continue; /* first run for a task */ 300 | } 301 | 302 | 303 | time_diff = task->time - time_prev; 304 | cpuload = (float)time_diff / _task_schedule_interval; 305 | 306 | work_time = (int64_t)(_task_schedule_interval - task->sleep_time); 307 | if (work_time == 0) { 308 | // If work_time of a process is nearly zero (highloaded and throttled extensively) flipping it to an opposite value 309 | // of sleep_time won't be a big deal because of the expression (cpuload - task->lim) ---> to zero, so the sleep_time 310 | // will balance in the same ranges. 311 | // But in this case, if the limit is raised the sleep_time will be able to correlate with the new limit. In other words 312 | // sleep_time will be dropping from nearly '_task_schedule_interval' values down letting process run freely. 313 | // Otherwise, zero value of work_time will hang the process sleeping '_task_schedule_interval' nanoseconds always 314 | // despite raising the limit. E.g: 315 | // sleep_time = sleep_time + 0 * (0.01 - 0.5) / 0.5; will yield constant sleep_time 316 | work_time = (int64_t)_task_schedule_interval; 317 | } 318 | sleep_time = (int64_t)floor(task->sleep_time + work_time * (cpuload - task->lim) / MAX(cpuload, task->lim)); 319 | 320 | if (sleep_time < 0) { 321 | sleep_time = 0; 322 | } else if (sleep_time > (int64_t)_task_schedule_interval) { 323 | sleep_time = (int64_t)_task_schedule_interval; 324 | } 325 | 326 | task->sleep_time = (uint64_t)sleep_time; 327 | 328 | if (opt_verbose_level) 329 | printf("pid # %d, time_prev: %llu, current_time: %llu, time_diff: %llu sleep_time: %llu or %0.3f(s) Worktime(ns): %lld\n", 330 | task->pid, 331 | time_prev, 332 | task->time, 333 | time_diff, 334 | task->sleep_time, 335 | (double)task->sleep_time / NANOSEC_PER_SEC, 336 | work_time 337 | ); 338 | } 339 | 340 | if (opt_verbose_level) 341 | fputs("\n", stdout); 342 | 343 | return ntasks_with_lim; 344 | } 345 | 346 | 347 | /* 348 | * Put process tasks to sleep. 349 | * Return total number of nanoseconds slept. 350 | */ 351 | static uint64_t proc_tasks_execsleeptime(void) { 352 | uint64_t sleptns = 0; 353 | short there_are_proc_sleeping = 0; 354 | short all_awake = 0; 355 | uint64_t pt_sleep_min; 356 | struct timespec sleepspec; 357 | proc_taskstats_t task; 358 | 359 | pt_sleep_min = ULONG_LONG_MAX; 360 | for (task = _proc_taskstats_list; task != NULL; task = task->next) { 361 | if (task->sleep_time != 0) { 362 | if (kill(task->pid, SIGSTOP) == -1) { 363 | if (opt_verbose_level) 364 | fputs("[proc_cpulim] Error: could not send a signal to a process.\n", stderr); 365 | continue; 366 | } 367 | 368 | task->is_sleeping = 1; 369 | there_are_proc_sleeping = 1; 370 | if (task->sleep_time < pt_sleep_min) 371 | pt_sleep_min = task->sleep_time; 372 | } 373 | } 374 | 375 | if (! there_are_proc_sleeping) 376 | return sleptns; 377 | 378 | sleepspec = timespec_from_ns((int64_t)pt_sleep_min); 379 | nanosleep(&sleepspec, NULL); 380 | sleptns = pt_sleep_min; 381 | 382 | while (! all_awake) { 383 | all_awake = 1; 384 | pt_sleep_min = ULONG_LONG_MAX; 385 | 386 | for (task = _proc_taskstats_list; task != NULL; task = task->next) { 387 | if (task->sleep_time == 0 || task->is_sleeping == 0) 388 | continue; 389 | else if (task->sleep_time == sleptns) { 390 | kill(task->pid, SIGCONT); 391 | task->is_sleeping = 0; 392 | } else if (task->sleep_time < pt_sleep_min) { 393 | pt_sleep_min = task->sleep_time; 394 | all_awake = 0; 395 | } 396 | } 397 | 398 | if (! all_awake) { 399 | sleepspec = timespec_from_ns((int64_t)(pt_sleep_min - sleptns)); 400 | nanosleep(&sleepspec, NULL); 401 | sleptns = pt_sleep_min; 402 | } 403 | 404 | } 405 | 406 | 407 | return sleptns; 408 | } 409 | 410 | 411 | /* 412 | * 413 | */ 414 | static dispatch_queue_t get_dispatch_queue(int type) { 415 | // Non-blocking spinner until the queue management is finished 416 | while (! OSAtomicCompareAndSwap32Barrier(0, 1, &_managing_dispatch_queue_locked)) 417 | ; 418 | 419 | dispatch_queue_t retval = NULL; 420 | 421 | if (type == DISPATCH_QUEUE_LIMITER) { 422 | if (_limiter_queue.queue) { 423 | _limiter_queue.refcnt += 1; 424 | retval = _limiter_queue.queue; 425 | } else { 426 | _limiter_queue.queue = dispatch_queue_create("com.proc_cpulim.LimiterQueue", DISPATCH_QUEUE_SERIAL); 427 | _limiter_queue.refcnt = 1; 428 | retval = _limiter_queue.queue; 429 | } 430 | } else if (type == DISPATCH_QUEUE_UPDTASKSTATS) { 431 | if (_updtaskstats_queue.queue) { 432 | _updtaskstats_queue.refcnt += 1; 433 | retval = _updtaskstats_queue.queue; 434 | } else { 435 | _updtaskstats_queue.queue = dispatch_queue_create("com.proc_cpulim.UpdTaskStatsQueue", DISPATCH_QUEUE_SERIAL); 436 | _updtaskstats_queue.refcnt = 1; 437 | retval = _updtaskstats_queue.queue; 438 | } 439 | 440 | } 441 | 442 | _managing_dispatch_queue_locked = 0; 443 | return retval; 444 | } 445 | 446 | 447 | /* 448 | * 449 | */ 450 | static void release_dispatch_queue(int type) { 451 | while (! OSAtomicCompareAndSwap32Barrier(0, 1, &_managing_dispatch_queue_locked)) 452 | ; 453 | 454 | if (type == DISPATCH_QUEUE_LIMITER) { 455 | _limiter_queue.refcnt -= 1; 456 | if (_limiter_queue.refcnt < 1) { 457 | // dispatch_debug(_limiter_queue.queue, " <--- RELEASING limiter queue"); 458 | dispatch_release(_limiter_queue.queue); 459 | _limiter_queue.queue = NULL; 460 | } 461 | } else if (type == DISPATCH_QUEUE_UPDTASKSTATS) { 462 | _updtaskstats_queue.refcnt -= 1; 463 | if (_updtaskstats_queue.refcnt < 1) { 464 | // dispatch_debug(_updtaskstats_queue.queue, " <--- RELEASING updtaskstats queue"); 465 | dispatch_release(_updtaskstats_queue.queue); 466 | _updtaskstats_queue.queue = NULL; 467 | } 468 | } 469 | 470 | _managing_dispatch_queue_locked = 0; 471 | } 472 | 473 | 474 | /* 475 | * 476 | */ 477 | void proc_cpulim_suspend(void) { 478 | _keep_limiter_running = 0; 479 | if (opt_verbose_level) 480 | fputs("[proc_cpulim] Info: Limiter going to hibernate.\n", stdout); 481 | } 482 | 483 | 484 | /* 485 | * Function returns only after limiter stops 486 | */ 487 | void proc_cpulim_suspend_wait(void) { 488 | if (! _keep_limiter_running) 489 | return; 490 | 491 | dispatch_queue_t limiter_queue = get_dispatch_queue(DISPATCH_QUEUE_LIMITER); 492 | _keep_limiter_running = 0; 493 | // dispatch_SYNC is used here: 494 | // Submits a block object for execution on a dispatch queue and waits until that block completes 495 | dispatch_sync(limiter_queue, ^{ 496 | if (opt_verbose_level) 497 | fputs("[proc_cpulim] Info: Limiter going to hibernate.\n", stdout); 498 | }); 499 | 500 | release_dispatch_queue(DISPATCH_QUEUE_LIMITER); 501 | } 502 | 503 | 504 | /* 505 | * 506 | */ 507 | static void proc_task_delete(pid_t pid) { 508 | dispatch_queue_t updtaskstats_queue = get_dispatch_queue(DISPATCH_QUEUE_UPDTASKSTATS); 509 | dispatch_async(updtaskstats_queue, ^{ 510 | do_proc_task_delete(pid); 511 | release_dispatch_queue(DISPATCH_QUEUE_UPDTASKSTATS); 512 | }); 513 | } 514 | 515 | 516 | static void do_proc_task_delete(pid_t pid) { 517 | proc_taskstats_t head = _proc_taskstats_list; 518 | proc_taskstats_t task; 519 | proc_taskstats_t prev_task = NULL; 520 | for (task = head; task != NULL; prev_task = task, task = task->next) { 521 | if (task->pid == pid) { 522 | // if it's the first task in the list simply make the head point to the next task 523 | if (task == head) { 524 | _proc_taskstats_list = task->next; 525 | } else if (prev_task) { // if it's not the only task in the list 526 | prev_task->next = task->next; 527 | } 528 | 529 | free(task); 530 | 531 | break; 532 | } 533 | 534 | } 535 | 536 | if (opt_verbose_level) 537 | fprintf(stdout, "[proc_cpulim] Info: Process '%d' deleted from the task list.\n", pid); 538 | } 539 | 540 | 541 | /* 542 | * 543 | */ 544 | static void reset_all_taskstats(void) { 545 | proc_taskstats_t task; 546 | for (task = _proc_taskstats_list; task != NULL; task = task->next) { 547 | task->time = 0; 548 | task->sleep_time = 0; 549 | task->is_sleeping = 0; 550 | } 551 | } 552 | 553 | 554 | /* 555 | * 556 | */ 557 | static struct timespec timespec_from_ns(int64_t nanoseconds) { 558 | struct timespec timef; 559 | if (nanoseconds >= NANOSEC_PER_SEC) { 560 | timef.tv_sec = (int)floor(nanoseconds / NANOSEC_PER_SEC); 561 | timef.tv_nsec = nanoseconds % NANOSEC_PER_SEC; 562 | } else { 563 | timef.tv_sec = 0; 564 | timef.tv_nsec = nanoseconds; 565 | } 566 | 567 | return timef; 568 | } 569 | 570 | 571 | /* 572 | * 573 | */ 574 | int proc_cpulim_schedule_interval(unsigned int new_interval, unsigned int *old_interval) { 575 | if (old_interval) { 576 | *old_interval = (unsigned int)_task_schedule_interval; 577 | } 578 | 579 | if (new_interval) { 580 | if (new_interval < TASK_SCHEDULE_INTERVAL_MIN) 581 | return(1); 582 | 583 | if (_limiter_is_running) { 584 | dispatch_queue_t updtaskstats_queue = get_dispatch_queue(DISPATCH_QUEUE_UPDTASKSTATS); 585 | dispatch_async(updtaskstats_queue, ^{ 586 | _task_schedule_interval = new_interval; 587 | release_dispatch_queue(DISPATCH_QUEUE_UPDTASKSTATS); 588 | }); 589 | } else { 590 | _task_schedule_interval = new_interval; 591 | } 592 | } 593 | 594 | return(0); 595 | } 596 | 597 | 598 | /* 599 | * 600 | */ 601 | void proc_taskstats_print(void) { 602 | fputs("\n\n---------------- STATS BEGIN --------------", stdout); 603 | 604 | if (_proc_taskstats_list) { 605 | int task_num = 0; 606 | proc_taskstats_t task; 607 | 608 | fputs("\nTask # PID Limit Time ptr nextptr\n", stdout); 609 | for (task = _proc_taskstats_list; task != NULL; task = task->next) { 610 | printf("%-10d %-7d %-10.3f %-14llu %-16p %p\n", 611 | task_num, 612 | task->pid, 613 | task->lim, 614 | task->time, 615 | task, 616 | task->next); 617 | 618 | ++task_num; 619 | } 620 | fprintf(stdout, "\nTasks count: %d", task_num); 621 | } else { 622 | printf("\nThere are no tasks"); 623 | } 624 | 625 | if (_limiter_queue.queue) { 626 | fprintf(stdout, "\n\nLimiter queue:\n"); 627 | dispatch_debug(_limiter_queue.queue, ""); 628 | } else { 629 | fprintf(stdout, "\n\nLimiter queue: NULL"); 630 | } 631 | 632 | if (_updtaskstats_queue.queue) { 633 | fprintf(stdout, "\nUpdtaskstats queue:\n"); 634 | dispatch_debug(_updtaskstats_queue.queue, ""); 635 | } else { 636 | fprintf(stdout, "\nUpdtaskstats queue: NULL"); 637 | } 638 | 639 | 640 | fputs("\n---------------- STATS END --------------\n", stdout); 641 | } 642 | -------------------------------------------------------------------------------- /AppPolice/C/proc_cpulim.h: -------------------------------------------------------------------------------- 1 | // 2 | // proc_cpulim.h 3 | // as part of AppPolice 4 | // 5 | // Created by Maksym on 5/19/13. 6 | // Copyright (c) 2013 Maksym Stefanchuk. All rights reserved. 7 | // 8 | 9 | #ifndef _PROC_CPULIM_H 10 | #define _PROC_CPULIM_H 11 | 12 | #include "subroutines.h" 13 | 14 | // Clocks per second OSX uses for processes. 15 | // It could be a better option to use "sysctl hw.tbfrequency" (time base frequency) 16 | // to find out the value for different computers. 17 | #define NANOSEC_PER_SEC 1000000000 18 | 19 | /* 20 | Note, to use dispatch_debug() an appropriate env. variable must be set: 21 | setenv("LIBDISPATCH_LOG", "stderr", 1); 22 | A proper place for this call could be in the application main file. 23 | */ 24 | 25 | 26 | /* 27 | newlim is the fraction of percents. For example 1 corresponds to 100% 28 | of permitted cpu load, 0.5 to 50% and 2.5 to 250% (in multicore environment). 29 | Return 0 if limit set successful, and 1 if provided parameters are invalid. */ 30 | int proc_cpulim_set(int pid, float newlim); 31 | void proc_cpulim_resume(void); 32 | void proc_cpulim_suspend(void); 33 | /* function returns only after limiter stoped */ 34 | void proc_cpulim_suspend_wait(void); 35 | 36 | /* 37 | 38 | Set the task schedule interval--how often processes should be 39 | inquired about their work times. 40 | 41 | new_interval If provided new interval is set. Value is in 42 | nanoseconds and should not be smaller then 1ms. 43 | old_interval If pointer is given old value is written into it. 44 | 45 | Return (0) if interval was changed and (1) otherwise. 46 | 47 | */ 48 | int proc_cpulim_schedule_interval(unsigned int new_interval, unsigned int *old_interval); 49 | 50 | /* should be private */ 51 | void proc_taskstats_print(void); 52 | 53 | #endif 54 | -------------------------------------------------------------------------------- /AppPolice/C/selfprofile.c: -------------------------------------------------------------------------------- 1 | // 2 | // selfprofile.c 3 | // proc_cpulim 4 | // 5 | // Created by Maksym on 5/22/13. 6 | // Copyright (c) 2013 Maksym Stefanchuk. All rights reserved. 7 | // 8 | 9 | #include "selfprofile.h" 10 | 11 | #ifdef PROFILE_APPLICATION 12 | 13 | #include 14 | #include 15 | 16 | static clock_t clocks_start, clocks_end; 17 | static time_t time_start, time_end; 18 | 19 | 20 | void profiling_start(void) { 21 | clocks_start = clock(); 22 | time(&time_start); 23 | } 24 | 25 | 26 | void profiling_print_stats(void) { 27 | double cpu_time_used; 28 | clocks_end = clock(); 29 | cpu_time_used = ((double)(clocks_end - clocks_start)) / CLOCKS_PER_SEC; 30 | 31 | time(&time_end); 32 | 33 | fputs("\n\n------- STATS --------\n", stdout); 34 | fprintf(stdout, "CPU time: %f\nTotal clocks: %lu\n", cpu_time_used, (clocks_end - clocks_start)); 35 | fprintf(stdout, "Elapsed time from launch: %lu second(s)", (time_end - time_start)); 36 | fputs("\n-----------------------\n", stdout); 37 | } 38 | 39 | #endif 40 | -------------------------------------------------------------------------------- /AppPolice/C/selfprofile.h: -------------------------------------------------------------------------------- 1 | // 2 | // selfprofile.h 3 | // proc_cpulim 4 | // 5 | // Created by Maksym on 5/22/13. 6 | // Copyright (c) 2013 Maksym Stefanchuk. All rights reserved. 7 | // 8 | 9 | /* 10 | * Methods for profiling our own App 11 | */ 12 | 13 | // It is for profiling currently running application in general 14 | #if defined(DEBUG) && !defined(PROFILE_APPLICATION) 15 | #define PROFILE_APPLICATION 16 | 17 | 18 | // Call this method to mark the beginning of profiling. 19 | void profiling_start(void); 20 | 21 | // Print profiling stats as of the current moment. 22 | void profiling_print_stats(void); 23 | 24 | #endif 25 | -------------------------------------------------------------------------------- /AppPolice/C/subroutines.c: -------------------------------------------------------------------------------- 1 | // 2 | // subroutines.c 3 | // proc_cpulim 4 | // 5 | // Created by Maksym on 5/20/13. 6 | // Copyright (c) 2013 Maksym Stefanchuk. All rights reserved. 7 | // 8 | 9 | #include 10 | #include 11 | #include "subroutines.h" 12 | 13 | 14 | void *xmalloc(size_t size) { 15 | register void *value = malloc(size); 16 | if (value == 0) { 17 | fputs("Virtual memory exhausted", stderr); 18 | exit(EXIT_FAILURE); 19 | } 20 | return value; 21 | } 22 | -------------------------------------------------------------------------------- /AppPolice/C/subroutines.h: -------------------------------------------------------------------------------- 1 | // 2 | // subroutines.h 3 | // proc_cpulim 4 | // 5 | // Created by Maksym on 5/20/13. 6 | // Copyright (c) 2013 Maksym Stefanchuk. All rights reserved. 7 | // 8 | 9 | #ifndef _SUBROUTINES_H 10 | #define _SUBROUTINES_H 11 | 12 | /* secure malloc */ 13 | void *xmalloc(size_t size); 14 | 15 | #endif 16 | -------------------------------------------------------------------------------- /AppPolice/Media.xcassets/AppPolice.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "size" : "16x16", 5 | "idiom" : "mac", 6 | "filename" : "icon_16x16.png", 7 | "scale" : "1x" 8 | }, 9 | { 10 | "size" : "16x16", 11 | "idiom" : "mac", 12 | "filename" : "icon_16x16@2x.png", 13 | "scale" : "2x" 14 | }, 15 | { 16 | "size" : "32x32", 17 | "idiom" : "mac", 18 | "filename" : "icon_32x32.png", 19 | "scale" : "1x" 20 | }, 21 | { 22 | "size" : "32x32", 23 | "idiom" : "mac", 24 | "filename" : "icon_32x32@2x.png", 25 | "scale" : "2x" 26 | }, 27 | { 28 | "size" : "128x128", 29 | "idiom" : "mac", 30 | "filename" : "icon_128x128.png", 31 | "scale" : "1x" 32 | }, 33 | { 34 | "size" : "128x128", 35 | "idiom" : "mac", 36 | "filename" : "icon_128x128@2x.png", 37 | "scale" : "2x" 38 | }, 39 | { 40 | "size" : "256x256", 41 | "idiom" : "mac", 42 | "filename" : "icon_256x256.png", 43 | "scale" : "1x" 44 | }, 45 | { 46 | "size" : "256x256", 47 | "idiom" : "mac", 48 | "filename" : "icon_256x256@2x.png", 49 | "scale" : "2x" 50 | }, 51 | { 52 | "size" : "512x512", 53 | "idiom" : "mac", 54 | "filename" : "icon_512x512.png", 55 | "scale" : "1x" 56 | }, 57 | { 58 | "size" : "512x512", 59 | "idiom" : "mac", 60 | "filename" : "icon_512x512@2x.png", 61 | "scale" : "2x" 62 | } 63 | ], 64 | "info" : { 65 | "version" : 1, 66 | "author" : "xcode" 67 | } 68 | } -------------------------------------------------------------------------------- /AppPolice/Media.xcassets/AppPolice.appiconset/icon_128x128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bumper314/AppPolice/62595bb21417d9e06e78edc37c51b998d83fa1d5/AppPolice/Media.xcassets/AppPolice.appiconset/icon_128x128.png -------------------------------------------------------------------------------- /AppPolice/Media.xcassets/AppPolice.appiconset/icon_128x128@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bumper314/AppPolice/62595bb21417d9e06e78edc37c51b998d83fa1d5/AppPolice/Media.xcassets/AppPolice.appiconset/icon_128x128@2x.png -------------------------------------------------------------------------------- /AppPolice/Media.xcassets/AppPolice.appiconset/icon_16x16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bumper314/AppPolice/62595bb21417d9e06e78edc37c51b998d83fa1d5/AppPolice/Media.xcassets/AppPolice.appiconset/icon_16x16.png -------------------------------------------------------------------------------- /AppPolice/Media.xcassets/AppPolice.appiconset/icon_16x16@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bumper314/AppPolice/62595bb21417d9e06e78edc37c51b998d83fa1d5/AppPolice/Media.xcassets/AppPolice.appiconset/icon_16x16@2x.png -------------------------------------------------------------------------------- /AppPolice/Media.xcassets/AppPolice.appiconset/icon_256x256.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bumper314/AppPolice/62595bb21417d9e06e78edc37c51b998d83fa1d5/AppPolice/Media.xcassets/AppPolice.appiconset/icon_256x256.png -------------------------------------------------------------------------------- /AppPolice/Media.xcassets/AppPolice.appiconset/icon_256x256@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bumper314/AppPolice/62595bb21417d9e06e78edc37c51b998d83fa1d5/AppPolice/Media.xcassets/AppPolice.appiconset/icon_256x256@2x.png -------------------------------------------------------------------------------- /AppPolice/Media.xcassets/AppPolice.appiconset/icon_32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bumper314/AppPolice/62595bb21417d9e06e78edc37c51b998d83fa1d5/AppPolice/Media.xcassets/AppPolice.appiconset/icon_32x32.png -------------------------------------------------------------------------------- /AppPolice/Media.xcassets/AppPolice.appiconset/icon_32x32@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bumper314/AppPolice/62595bb21417d9e06e78edc37c51b998d83fa1d5/AppPolice/Media.xcassets/AppPolice.appiconset/icon_32x32@2x.png -------------------------------------------------------------------------------- /AppPolice/Media.xcassets/AppPolice.appiconset/icon_512x512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bumper314/AppPolice/62595bb21417d9e06e78edc37c51b998d83fa1d5/AppPolice/Media.xcassets/AppPolice.appiconset/icon_512x512.png -------------------------------------------------------------------------------- /AppPolice/Media.xcassets/AppPolice.appiconset/icon_512x512@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bumper314/AppPolice/62595bb21417d9e06e78edc37c51b998d83fa1d5/AppPolice/Media.xcassets/AppPolice.appiconset/icon_512x512@2x.png -------------------------------------------------------------------------------- /AppPolice/Other/APPreferencesController.h: -------------------------------------------------------------------------------- 1 | // 2 | // APPreferencesController.h 3 | // AppPolice 4 | // 5 | // Created by Maksym on 20/11/13. 6 | // Copyright (c) 2013 Maksym Stefanchuk. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | #define kPrefRestoreApplicationLimits @"APRestoreApplicationLimits" 12 | #define kPrefApplicationLimits @"APApplicationLimits" 13 | 14 | @interface APPreferencesController : NSWindowController 15 | 16 | @property (assign) IBOutlet NSMatrix *sortByMatrix; 17 | @property (assign) IBOutlet NSMatrix *orderMatrix; 18 | @property (assign) IBOutlet NSButton *restoreApplicationLimitsButton; 19 | @property (assign) IBOutlet NSButton *showSystemProcessesButton; 20 | @property (assign) IBOutlet NSButton *launchAtLoginButton; 21 | 22 | - (IBAction)changeSortByPreferences:(id)sender; 23 | - (IBAction)changeOrderPreferences:(id)sender; 24 | - (IBAction)changeShowSystemProcessesPreferences:(id)sender; 25 | - (IBAction)changeLaunchAtLoginPreferences:(id)sender; 26 | 27 | @end 28 | -------------------------------------------------------------------------------- /AppPolice/Other/APPreferencesController.m: -------------------------------------------------------------------------------- 1 | // 2 | // APPreferencesController.m 3 | // AppPolice 4 | // 5 | // Created by Maksym on 20/11/13. 6 | // Copyright (c) 2013 Maksym Stefanchuk. All rights reserved. 7 | // 8 | 9 | #import "APPreferencesController.h" 10 | #include "proc_cpulim.h" 11 | 12 | @implementation APPreferencesController 13 | 14 | - (id)init { 15 | return [super initWithWindowNibName:@"APPreferencesWindow"]; 16 | } 17 | 18 | 19 | - (void)windowDidLoad { 20 | [super windowDidLoad]; 21 | 22 | NSUserDefaults *preferences = [NSUserDefaults standardUserDefaults]; 23 | NSInteger sortByValue = [preferences integerForKey:@"APSortBy"]; 24 | BOOL orderAsc = [preferences boolForKey:@"APOrderAsc"]; 25 | BOOL restoreApplicationLimits = [preferences boolForKey:kPrefRestoreApplicationLimits]; 26 | BOOL showSystemProcesses = [preferences boolForKey:@"APShowSystemProcesses"]; 27 | BOOL launchAtLogin = [preferences boolForKey:@"APLaunchAtLogin"]; 28 | LSSharedFileListItemRef item = [self copyLoginItem]; 29 | 30 | [[self sortByMatrix] selectCellAtRow:sortByValue column:0]; 31 | [[self orderMatrix] selectCellAtRow:(orderAsc ? 0 : 1) column:0]; 32 | [[self restoreApplicationLimitsButton] setIntegerValue:(restoreApplicationLimits) ? 1 : 0]; 33 | [[self showSystemProcessesButton] setIntegerValue:(showSystemProcesses) ? 1 : 0]; 34 | // Synchronize "Lauch at login" with real presence of login item in Mac OS X prefs 35 | if (item) { 36 | [[self launchAtLoginButton] setIntegerValue:1]; 37 | if (! launchAtLogin) { 38 | [preferences setBool:YES forKey:@"APLaunchAtLogin"]; 39 | } 40 | CFRelease(item); 41 | } else { 42 | [[self launchAtLoginButton] setIntegerValue:0]; 43 | if (launchAtLogin) 44 | [preferences setBool:NO forKey:@"APLaunchAtLogin"]; 45 | } 46 | 47 | // NSLog(@"showsys: %d", showSystemProcesses); 48 | // NSLog(@"launch: %d", launchAtLogin); 49 | // NSLog(@"prefs: %@", [preferences dictionaryRepresentation]); 50 | } 51 | 52 | 53 | - (IBAction)changeSortByPreferences:(id)sender { 54 | NSMatrix *matrix = (NSMatrix *)sender; 55 | NSNumber *value = [NSNumber numberWithInteger:[matrix selectedRow]]; 56 | NSUserDefaults *preferences = [NSUserDefaults standardUserDefaults]; 57 | [preferences setValue:value forKey:@"APSortBy"]; 58 | } 59 | 60 | 61 | - (IBAction)changeOrderPreferences:(id)sender { 62 | NSMatrix *matrix = (NSMatrix *)sender; 63 | NSInteger value = [matrix selectedRow]; 64 | NSUserDefaults *preferences = [NSUserDefaults standardUserDefaults]; 65 | [preferences setBool:(value == 0) forKey:@"APOrderAsc"]; 66 | } 67 | 68 | 69 | - (IBAction)changeRestoreApplicationLimitsPreferences:(id)sender { 70 | NSButton *button = (NSButton *)sender; 71 | NSUserDefaults *preferences = [NSUserDefaults standardUserDefaults]; 72 | [preferences setBool:([button intValue] == 1) forKey:kPrefRestoreApplicationLimits]; 73 | } 74 | 75 | 76 | - (IBAction)changeShowSystemProcessesPreferences:(id)sender { 77 | NSButton *button = (NSButton *)sender; 78 | NSUserDefaults *preferences = [NSUserDefaults standardUserDefaults]; 79 | [preferences setBool:([button intValue] == 1) forKey:@"APShowSystemProcesses"]; 80 | } 81 | 82 | 83 | - (IBAction)changeLaunchAtLoginPreferences:(id)sender { 84 | NSButton *button = (NSButton *)sender; 85 | BOOL stateOn = ([button intValue] == 1); 86 | NSUserDefaults *preferences = [NSUserDefaults standardUserDefaults]; 87 | [preferences setBool:stateOn forKey:@"APLaunchAtLogin"]; 88 | 89 | if (stateOn) { 90 | (void) [self addLoginItem]; 91 | } else { 92 | [self removeLoginItem]; 93 | } 94 | } 95 | 96 | 97 | - (BOOL)addLoginItem { 98 | LSSharedFileListRef fileList = LSSharedFileListCreate(NULL, kLSSharedFileListSessionLoginItems, NULL); 99 | if (fileList) { 100 | NSURL *bundleURL = [[NSBundle mainBundle] bundleURL]; 101 | LSSharedFileListItemRef listItem = LSSharedFileListInsertItemURL(fileList, kLSSharedFileListItemLast, NULL, NULL, (CFURLRef)bundleURL, NULL, NULL); 102 | CFRelease(fileList); 103 | if (listItem) { 104 | CFRelease(listItem); 105 | return YES; 106 | } 107 | } 108 | 109 | return NO; 110 | } 111 | 112 | - (void)removeLoginItem { 113 | LSSharedFileListRef fileList; 114 | LSSharedFileListItemRef item; 115 | 116 | item = [self copyLoginItem]; 117 | if (item) { 118 | fileList = LSSharedFileListCreate(NULL, kLSSharedFileListSessionLoginItems, NULL); 119 | (void) LSSharedFileListItemRemove(fileList, item); 120 | CFRelease(fileList); 121 | CFRelease(item); 122 | } 123 | } 124 | 125 | 126 | - (LSSharedFileListItemRef)copyLoginItem { 127 | LSSharedFileListItemRef retRef = NULL; 128 | LSSharedFileListRef fileList; 129 | CFURLRef itemURLRef; 130 | NSURL *bundleURL; 131 | CFArrayRef arrayOfItems; 132 | CFIndex count; 133 | CFIndex i; 134 | 135 | fileList = LSSharedFileListCreate(NULL, kLSSharedFileListSessionLoginItems, NULL); 136 | if (fileList) { 137 | arrayOfItems = LSSharedFileListCopySnapshot(fileList, NULL); 138 | count = CFArrayGetCount(arrayOfItems); 139 | if (count) { 140 | bundleURL = [[NSBundle mainBundle] bundleURL]; 141 | for (i = 0; i < count; ++i) { 142 | LSSharedFileListItemRef item = (LSSharedFileListItemRef)CFArrayGetValueAtIndex(arrayOfItems, i); 143 | if ((LSSharedFileListItemResolve(item, 0, &itemURLRef, NULL) == noErr)) { 144 | if ([bundleURL isEqual:(NSURL *)itemURLRef]) { 145 | CFRetain(item); 146 | retRef = item; 147 | CFRelease(itemURLRef); 148 | break; 149 | } 150 | CFRelease(itemURLRef); 151 | } 152 | } 153 | } 154 | 155 | // CFStringRef description = CFCopyDescription(arrayOfItems); 156 | // NSLog(@"list: %@", (NSString *)description); 157 | 158 | CFRelease(arrayOfItems); 159 | CFRelease(fileList); 160 | } 161 | 162 | return retRef; 163 | } 164 | 165 | @end 166 | -------------------------------------------------------------------------------- /AppPolice/Other/NSMenu+APAdditions.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSMenu+APAdditions.h 3 | // AppPolice 4 | // 5 | // Created by Steve Audette on 06/25/16. 6 | // Copyright (c) 2016 Maksym Stefanchuk. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface NSMenu (APAdditions) 12 | 13 | - (void)insertItem:(NSMenuItem *)newItem atIndex:(NSInteger)index animate:(BOOL)animate; 14 | - (void)removeItemAtIndex:(NSInteger)index animate:(BOOL)animate; 15 | - (void)removeItemsAtIndexes:(NSIndexSet *)indexes; 16 | 17 | @end 18 | -------------------------------------------------------------------------------- /AppPolice/Other/NSMenu+APAdditions.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSMenu+APAdditions.m 3 | // AppPolice 4 | // 5 | // Created by Steve Audette on 06/25/16. 6 | // Copyright (c) 2016 Maksym Stefanchuk. All rights reserved. 7 | // 8 | 9 | #import "NSMenu+APAdditions.h" 10 | 11 | @implementation NSMenu (APAdditions) 12 | 13 | - (void)insertItem:(NSMenuItem *)newItem atIndex:(NSInteger)index animate:(BOOL)animate 14 | { 15 | [self insertItem:newItem atIndex:index]; 16 | } 17 | 18 | - (void)removeItemAtIndex:(NSInteger)index animate:(BOOL)animate 19 | { 20 | [self removeItemAtIndex:index]; 21 | } 22 | 23 | - (void)removeItemsAtIndexes:(NSIndexSet *)indexes { 24 | NSMutableArray *items = [[self itemArray] mutableCopy]; 25 | __block NSUInteger itemsCount = [items count]; 26 | if (! itemsCount) { 27 | [NSException raise:NSInvalidArgumentException format:@"Removing items from empty Menu at -removeItemsAtIndexes:"]; 28 | return; 29 | } 30 | if ([indexes indexGreaterThanOrEqualToIndex:itemsCount] != NSNotFound) { 31 | [NSException raise:NSRangeException format:@"Indexes out of bounds at NSMenu -removeItemsAtIndexes:"]; 32 | return; 33 | } 34 | 35 | [indexes enumerateIndexesUsingBlock:^(NSUInteger idx, BOOL *stop) { 36 | // See if any of the removing items has submenus 37 | NSMenuItem *item = [[self itemArray] objectAtIndex:idx]; 38 | if ([item hasSubmenu]) { 39 | [item setSubmenu:nil]; 40 | } 41 | }]; 42 | 43 | [indexes enumerateIndexesUsingBlock:^(NSUInteger idx, BOOL *stop) { 44 | [self removeItemAtIndex:idx]; 45 | }]; 46 | } 47 | 48 | @end 49 | -------------------------------------------------------------------------------- /AppPolice/Other/NSMenuItem+APAdditions.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSMenuItem+APAdditions.h 3 | // AppPolice 4 | // 5 | // Created by Steve Audette on 06/25/16. 6 | // Copyright (c) 2016 Maksym Stefanchuk. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface NSMenuItem (APAdditions) 12 | 13 | - (id)initWithTitle:(NSString *)title action:(SEL)action; 14 | - (id)initWithTitle:(NSString *)title icon:(NSImage *)icon action:(SEL)action; 15 | 16 | @end 17 | -------------------------------------------------------------------------------- /AppPolice/Other/NSMenuItem+APAdditions.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSMenuItem+APAdditions.m 3 | // AppPolice 4 | // 5 | // Created by Steve Audette on 06/25/16. 6 | // Copyright (c) 2016 Maksym Stefanchuk. All rights reserved. 7 | // 8 | 9 | #import "NSMenuItem+APAdditions.h" 10 | 11 | @implementation NSMenuItem (APAdditions) 12 | 13 | - (id)initWithTitle:(NSString *)title action:(SEL)action 14 | { 15 | return [[NSMenuItem alloc] initWithTitle:title action:action keyEquivalent:@""]; 16 | } 17 | 18 | - (id)initWithTitle:(NSString *)title icon:(NSImage *)icon action:(SEL)action 19 | { 20 | NSMenuItem *temp = [[NSMenuItem alloc] initWithTitle:title action:action keyEquivalent:@""]; 21 | [temp setImage:icon]; 22 | return temp; 23 | } 24 | 25 | @end 26 | -------------------------------------------------------------------------------- /AppPolice/Statusbar/StatusbarMenuController.h: -------------------------------------------------------------------------------- 1 | // 2 | // StatusbarMenuController.h 3 | // AppPolice 4 | // 5 | // Created by Maksym on 10/11/13. 6 | // Copyright (c) 2013 Maksym Stefanchuk. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | #define APApplicationsSortedByName 0 12 | #define APApplicationsSortedByPid 1 13 | 14 | @class AppInspector; 15 | 16 | @interface StatusbarMenuController : NSObject 17 | { 18 | @private; 19 | NSMenu *_mainMenu; 20 | NSMutableArray *_runningApplications; 21 | NSMutableArray *_runningSystemProcesses; 22 | NSMenuItem *_appInspectorItem; 23 | int _sortKey; 24 | BOOL _orderAsc; 25 | AppInspector *_appInspector; 26 | } 27 | 28 | - (NSMenu *)mainMenu; 29 | 30 | // Default is |APApplicationsSortedByName| 31 | - (int)sortKey; 32 | - (void)setSortKey:(int)sortKey; 33 | 34 | @end 35 | -------------------------------------------------------------------------------- /AppPolice/UserDefaults.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | APSortBy 6 | 0 7 | APOrderAsc 8 | 9 | APShowSystemProcesses 10 | 11 | APLaunchAtLogin 12 | 13 | APRestoreApplicationLimits 14 | 15 | APProcCpulimTaskScheduleInterval 16 | 30000000 17 | 18 | 19 | -------------------------------------------------------------------------------- /AppPolice/en.lproj/APPreferencesWindow.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 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 121 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | -------------------------------------------------------------------------------- /AppPolice/en.lproj/AppInspectorView.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 | 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 | -------------------------------------------------------------------------------- /AppPolice/en.lproj/Credits.rtf: -------------------------------------------------------------------------------- 1 | {\rtf0\ansi{\fonttbl\f0\fswiss Helvetica;} 2 | {\colortbl;\red255\green255\blue255;} 3 | \paperw9840\paperh8400 4 | \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural 5 | 6 | \f0\b\fs24 \cf0 Engineering: 7 | \b0 \ 8 | Some people\ 9 | \ 10 | 11 | \b Human Interface Design: 12 | \b0 \ 13 | Some other people\ 14 | \ 15 | 16 | \b Testing: 17 | \b0 \ 18 | Hopefully not nobody\ 19 | \ 20 | 21 | \b Documentation: 22 | \b0 \ 23 | Whoever\ 24 | \ 25 | 26 | \b With special thanks to: 27 | \b0 \ 28 | Mom\ 29 | } 30 | -------------------------------------------------------------------------------- /AppPolice/en.lproj/InfoPlist.strings: -------------------------------------------------------------------------------- 1 | /* Localized versions of Info.plist keys */ 2 | 3 | -------------------------------------------------------------------------------- /AppPolice/en.lproj/Localizable.strings: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bumper314/AppPolice/62595bb21417d9e06e78edc37c51b998d83fa1d5/AppPolice/en.lproj/Localizable.strings -------------------------------------------------------------------------------- /AppPolice/en.lproj/MainMenu.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /AppPolice/en.lproj/PopoverContentView.strings: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bumper314/AppPolice/62595bb21417d9e06e78edc37c51b998d83fa1d5/AppPolice/en.lproj/PopoverContentView.strings -------------------------------------------------------------------------------- /AppPolice/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // AppPolice 4 | // 5 | // Created by Maksym on 5/19/13. 6 | // Copyright (c) 2013 Maksym Stefanchuk. All rights reserved. 7 | // 8 | 9 | #import 10 | #include 11 | #include "C/proc_cpulim.h" 12 | #include "C/selfprofile.h" 13 | 14 | int gAPAllLimitsPaused; 15 | 16 | void install_signal_handlers(void); 17 | void termination_handler(int signum); 18 | void tstp_handler(int signum); 19 | void cont_handler(int signum); 20 | 21 | 22 | int main(int argc, char *argv[]) { 23 | #ifdef PROFILE_APPLICATION 24 | profiling_start(); 25 | if (atexit(profiling_print_stats) != 0) 26 | fputs("[AppPolice] Error: Could not establish atexit() method", stderr); 27 | #endif 28 | 29 | 30 | // print dispatch_debug() logs to stderr 31 | // setenv("LIBDISPATCH_LOG", "stderr", 1); 32 | 33 | 34 | install_signal_handlers(); 35 | 36 | return NSApplicationMain(argc, (const char **)argv); 37 | } 38 | 39 | 40 | 41 | void install_signal_handlers(void) { 42 | struct sigaction term_action, tstp_action, cont_action; 43 | 44 | term_action.sa_handler = termination_handler; 45 | sigfillset(&term_action.sa_mask); 46 | term_action.sa_flags = 0; 47 | 48 | tstp_action.sa_handler = tstp_handler; 49 | sigfillset(&tstp_action.sa_mask); 50 | tstp_action.sa_flags = 0; 51 | 52 | cont_action.sa_handler = cont_handler; 53 | sigfillset(&cont_action.sa_mask); 54 | cont_action.sa_flags = 0; 55 | 56 | sigaction(SIGINT, &term_action, NULL); 57 | sigaction(SIGTERM, &term_action, NULL); 58 | sigaction(SIGHUP, &term_action, NULL); 59 | sigaction(SIGCONT, &cont_action, NULL); 60 | sigaction(SIGTSTP, &tstp_action, NULL); 61 | } 62 | 63 | 64 | 65 | void termination_handler(int signum) { 66 | struct sigaction new_action; 67 | 68 | fputs("[AppPolice] Info: Termination signal received. Let processes run freely.\n", stdout); 69 | fflush(stdout); 70 | proc_cpulim_suspend_wait(); 71 | 72 | // set default action and re-raise signal 73 | new_action.sa_handler = SIG_DFL; 74 | sigfillset(&new_action.sa_mask); 75 | new_action.sa_flags = 0; 76 | sigaction(signum, &new_action, NULL); 77 | raise(signum); 78 | } 79 | 80 | 81 | void tstp_handler(int signum) { 82 | struct sigaction new_action; 83 | 84 | fputs("[AppPolice] Info: SIGTSTP signal received. Let processes run freely.\n", stdout); 85 | fflush(stdout); 86 | proc_cpulim_suspend_wait(); 87 | 88 | // set default action and re-raise signal 89 | new_action.sa_handler = SIG_DFL; 90 | sigemptyset(&new_action.sa_mask); 91 | new_action.sa_flags = 0; 92 | sigaction(signum, &new_action, NULL); 93 | raise(signum); 94 | } 95 | 96 | 97 | void cont_handler(int signum) { 98 | struct sigaction tstp_action; 99 | 100 | // Restore the SIGTSTP handler back 101 | tstp_action.sa_handler = tstp_handler; 102 | sigfillset(&tstp_action.sa_mask); 103 | tstp_action.sa_flags = 0; 104 | sigaction(SIGTSTP, &tstp_action, NULL); 105 | 106 | fputs("[AppPolice] Info: SIGCONT signal received. Resume all limits.\n", stdout); 107 | fflush(stdout); 108 | if (! gAPAllLimitsPaused) 109 | proc_cpulim_resume(); 110 | } 111 | 112 | -------------------------------------------------------------------------------- /AppPolice/status_icon.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bumper314/AppPolice/62595bb21417d9e06e78edc37c51b998d83fa1d5/AppPolice/status_icon.pdf -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | GNU GENERAL PUBLIC LICENSE 2 | Version 2, June 1991 3 | 4 | Copyright (C) 1989, 1991 Free Software Foundation, Inc., 5 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 6 | Everyone is permitted to copy and distribute verbatim copies 7 | of this license document, but changing it is not allowed. 8 | 9 | Preamble 10 | 11 | The licenses for most software are designed to take away your 12 | freedom to share and change it. By contrast, the GNU General Public 13 | License is intended to guarantee your freedom to share and change free 14 | software--to make sure the software is free for all its users. This 15 | General Public License applies to most of the Free Software 16 | Foundation's software and to any other program whose authors commit to 17 | using it. (Some other Free Software Foundation software is covered by 18 | the GNU Lesser General Public License instead.) You can apply it to 19 | your programs, too. 20 | 21 | When we speak of free software, we are referring to freedom, not 22 | price. Our General Public Licenses are designed to make sure that you 23 | have the freedom to distribute copies of free software (and charge for 24 | this service if you wish), that you receive source code or can get it 25 | if you want it, that you can change the software or use pieces of it 26 | in new free programs; and that you know you can do these things. 27 | 28 | To protect your rights, we need to make restrictions that forbid 29 | anyone to deny you these rights or to ask you to surrender the rights. 30 | These restrictions translate to certain responsibilities for you if you 31 | distribute copies of the software, or if you modify it. 32 | 33 | For example, if you distribute copies of such a program, whether 34 | gratis or for a fee, you must give the recipients all the rights that 35 | you have. You must make sure that they, too, receive or can get the 36 | source code. And you must show them these terms so they know their 37 | rights. 38 | 39 | We protect your rights with two steps: (1) copyright the software, and 40 | (2) offer you this license which gives you legal permission to copy, 41 | distribute and/or modify the software. 42 | 43 | Also, for each author's protection and ours, we want to make certain 44 | that everyone understands that there is no warranty for this free 45 | software. If the software is modified by someone else and passed on, we 46 | want its recipients to know that what they have is not the original, so 47 | that any problems introduced by others will not reflect on the original 48 | authors' reputations. 49 | 50 | Finally, any free program is threatened constantly by software 51 | patents. We wish to avoid the danger that redistributors of a free 52 | program will individually obtain patent licenses, in effect making the 53 | program proprietary. To prevent this, we have made it clear that any 54 | patent must be licensed for everyone's free use or not licensed at all. 55 | 56 | The precise terms and conditions for copying, distribution and 57 | modification follow. 58 | 59 | GNU GENERAL PUBLIC LICENSE 60 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 61 | 62 | 0. This License applies to any program or other work which contains 63 | a notice placed by the copyright holder saying it may be distributed 64 | under the terms of this General Public License. The "Program", below, 65 | refers to any such program or work, and a "work based on the Program" 66 | means either the Program or any derivative work under copyright law: 67 | that is to say, a work containing the Program or a portion of it, 68 | either verbatim or with modifications and/or translated into another 69 | language. (Hereinafter, translation is included without limitation in 70 | the term "modification".) Each licensee is addressed as "you". 71 | 72 | Activities other than copying, distribution and modification are not 73 | covered by this License; they are outside its scope. The act of 74 | running the Program is not restricted, and the output from the Program 75 | is covered only if its contents constitute a work based on the 76 | Program (independent of having been made by running the Program). 77 | Whether that is true depends on what the Program does. 78 | 79 | 1. You may copy and distribute verbatim copies of the Program's 80 | source code as you receive it, in any medium, provided that you 81 | conspicuously and appropriately publish on each copy an appropriate 82 | copyright notice and disclaimer of warranty; keep intact all the 83 | notices that refer to this License and to the absence of any warranty; 84 | and give any other recipients of the Program a copy of this License 85 | along with the Program. 86 | 87 | You may charge a fee for the physical act of transferring a copy, and 88 | you may at your option offer warranty protection in exchange for a fee. 89 | 90 | 2. You may modify your copy or copies of the Program or any portion 91 | of it, thus forming a work based on the Program, and copy and 92 | distribute such modifications or work under the terms of Section 1 93 | above, provided that you also meet all of these conditions: 94 | 95 | a) You must cause the modified files to carry prominent notices 96 | stating that you changed the files and the date of any change. 97 | 98 | b) You must cause any work that you distribute or publish, that in 99 | whole or in part contains or is derived from the Program or any 100 | part thereof, to be licensed as a whole at no charge to all third 101 | parties under the terms of this License. 102 | 103 | c) If the modified program normally reads commands interactively 104 | when run, you must cause it, when started running for such 105 | interactive use in the most ordinary way, to print or display an 106 | announcement including an appropriate copyright notice and a 107 | notice that there is no warranty (or else, saying that you provide 108 | a warranty) and that users may redistribute the program under 109 | these conditions, and telling the user how to view a copy of this 110 | License. (Exception: if the Program itself is interactive but 111 | does not normally print such an announcement, your work based on 112 | the Program is not required to print an announcement.) 113 | 114 | These requirements apply to the modified work as a whole. If 115 | identifiable sections of that work are not derived from the Program, 116 | and can be reasonably considered independent and separate works in 117 | themselves, then this License, and its terms, do not apply to those 118 | sections when you distribute them as separate works. But when you 119 | distribute the same sections as part of a whole which is a work based 120 | on the Program, the distribution of the whole must be on the terms of 121 | this License, whose permissions for other licensees extend to the 122 | entire whole, and thus to each and every part regardless of who wrote it. 123 | 124 | Thus, it is not the intent of this section to claim rights or contest 125 | your rights to work written entirely by you; rather, the intent is to 126 | exercise the right to control the distribution of derivative or 127 | collective works based on the Program. 128 | 129 | In addition, mere aggregation of another work not based on the Program 130 | with the Program (or with a work based on the Program) on a volume of 131 | a storage or distribution medium does not bring the other work under 132 | the scope of this License. 133 | 134 | 3. You may copy and distribute the Program (or a work based on it, 135 | under Section 2) in object code or executable form under the terms of 136 | Sections 1 and 2 above provided that you also do one of the following: 137 | 138 | a) Accompany it with the complete corresponding machine-readable 139 | source code, which must be distributed under the terms of Sections 140 | 1 and 2 above on a medium customarily used for software interchange; or, 141 | 142 | b) Accompany it with a written offer, valid for at least three 143 | years, to give any third party, for a charge no more than your 144 | cost of physically performing source distribution, a complete 145 | machine-readable copy of the corresponding source code, to be 146 | distributed under the terms of Sections 1 and 2 above on a medium 147 | customarily used for software interchange; or, 148 | 149 | c) Accompany it with the information you received as to the offer 150 | to distribute corresponding source code. (This alternative is 151 | allowed only for noncommercial distribution and only if you 152 | received the program in object code or executable form with such 153 | an offer, in accord with Subsection b above.) 154 | 155 | The source code for a work means the preferred form of the work for 156 | making modifications to it. For an executable work, complete source 157 | code means all the source code for all modules it contains, plus any 158 | associated interface definition files, plus the scripts used to 159 | control compilation and installation of the executable. However, as a 160 | special exception, the source code distributed need not include 161 | anything that is normally distributed (in either source or binary 162 | form) with the major components (compiler, kernel, and so on) of the 163 | operating system on which the executable runs, unless that component 164 | itself accompanies the executable. 165 | 166 | If distribution of executable or object code is made by offering 167 | access to copy from a designated place, then offering equivalent 168 | access to copy the source code from the same place counts as 169 | distribution of the source code, even though third parties are not 170 | compelled to copy the source along with the object code. 171 | 172 | 4. You may not copy, modify, sublicense, or distribute the Program 173 | except as expressly provided under this License. Any attempt 174 | otherwise to copy, modify, sublicense or distribute the Program is 175 | void, and will automatically terminate your rights under this License. 176 | However, parties who have received copies, or rights, from you under 177 | this License will not have their licenses terminated so long as such 178 | parties remain in full compliance. 179 | 180 | 5. You are not required to accept this License, since you have not 181 | signed it. However, nothing else grants you permission to modify or 182 | distribute the Program or its derivative works. These actions are 183 | prohibited by law if you do not accept this License. Therefore, by 184 | modifying or distributing the Program (or any work based on the 185 | Program), you indicate your acceptance of this License to do so, and 186 | all its terms and conditions for copying, distributing or modifying 187 | the Program or works based on it. 188 | 189 | 6. Each time you redistribute the Program (or any work based on the 190 | Program), the recipient automatically receives a license from the 191 | original licensor to copy, distribute or modify the Program subject to 192 | these terms and conditions. You may not impose any further 193 | restrictions on the recipients' exercise of the rights granted herein. 194 | You are not responsible for enforcing compliance by third parties to 195 | this License. 196 | 197 | 7. If, as a consequence of a court judgment or allegation of patent 198 | infringement or for any other reason (not limited to patent issues), 199 | conditions are imposed on you (whether by court order, agreement or 200 | otherwise) that contradict the conditions of this License, they do not 201 | excuse you from the conditions of this License. If you cannot 202 | distribute so as to satisfy simultaneously your obligations under this 203 | License and any other pertinent obligations, then as a consequence you 204 | may not distribute the Program at all. For example, if a patent 205 | license would not permit royalty-free redistribution of the Program by 206 | all those who receive copies directly or indirectly through you, then 207 | the only way you could satisfy both it and this License would be to 208 | refrain entirely from distribution of the Program. 209 | 210 | If any portion of this section is held invalid or unenforceable under 211 | any particular circumstance, the balance of the section is intended to 212 | apply and the section as a whole is intended to apply in other 213 | circumstances. 214 | 215 | It is not the purpose of this section to induce you to infringe any 216 | patents or other property right claims or to contest validity of any 217 | such claims; this section has the sole purpose of protecting the 218 | integrity of the free software distribution system, which is 219 | implemented by public license practices. Many people have made 220 | generous contributions to the wide range of software distributed 221 | through that system in reliance on consistent application of that 222 | system; it is up to the author/donor to decide if he or she is willing 223 | to distribute software through any other system and a licensee cannot 224 | impose that choice. 225 | 226 | This section is intended to make thoroughly clear what is believed to 227 | be a consequence of the rest of this License. 228 | 229 | 8. If the distribution and/or use of the Program is restricted in 230 | certain countries either by patents or by copyrighted interfaces, the 231 | original copyright holder who places the Program under this License 232 | may add an explicit geographical distribution limitation excluding 233 | those countries, so that distribution is permitted only in or among 234 | countries not thus excluded. In such case, this License incorporates 235 | the limitation as if written in the body of this License. 236 | 237 | 9. The Free Software Foundation may publish revised and/or new versions 238 | of the General Public License from time to time. Such new versions will 239 | be similar in spirit to the present version, but may differ in detail to 240 | address new problems or concerns. 241 | 242 | Each version is given a distinguishing version number. If the Program 243 | specifies a version number of this License which applies to it and "any 244 | later version", you have the option of following the terms and conditions 245 | either of that version or of any later version published by the Free 246 | Software Foundation. If the Program does not specify a version number of 247 | this License, you may choose any version ever published by the Free Software 248 | Foundation. 249 | 250 | 10. If you wish to incorporate parts of the Program into other free 251 | programs whose distribution conditions are different, write to the author 252 | to ask for permission. For software which is copyrighted by the Free 253 | Software Foundation, write to the Free Software Foundation; we sometimes 254 | make exceptions for this. Our decision will be guided by the two goals 255 | of preserving the free status of all derivatives of our free software and 256 | of promoting the sharing and reuse of software generally. 257 | 258 | NO WARRANTY 259 | 260 | 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY 261 | FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN 262 | OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES 263 | PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED 264 | OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 265 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS 266 | TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE 267 | PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, 268 | REPAIR OR CORRECTION. 269 | 270 | 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 271 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR 272 | REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, 273 | INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING 274 | OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED 275 | TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY 276 | YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER 277 | PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE 278 | POSSIBILITY OF SUCH DAMAGES. 279 | 280 | END OF TERMS AND CONDITIONS 281 | 282 | How to Apply These Terms to Your New Programs 283 | 284 | If you develop a new program, and you want it to be of the greatest 285 | possible use to the public, the best way to achieve this is to make it 286 | free software which everyone can redistribute and change under these terms. 287 | 288 | To do so, attach the following notices to the program. It is safest 289 | to attach them to the start of each source file to most effectively 290 | convey the exclusion of warranty; and each file should have at least 291 | the "copyright" line and a pointer to where the full notice is found. 292 | 293 | Minimalistic Firefox add-on for Google and Alexa site statistics 294 | Copyright (C) 2013 fuyu 295 | 296 | This program is free software; you can redistribute it and/or modify 297 | it under the terms of the GNU General Public License as published by 298 | the Free Software Foundation; either version 2 of the License, or 299 | (at your option) any later version. 300 | 301 | This program is distributed in the hope that it will be useful, 302 | but WITHOUT ANY WARRANTY; without even the implied warranty of 303 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 304 | GNU General Public License for more details. 305 | 306 | You should have received a copy of the GNU General Public License along 307 | with this program; if not, write to the Free Software Foundation, Inc., 308 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 309 | 310 | Also add information on how to contact you by electronic and paper mail. 311 | 312 | If the program is interactive, make it output a short notice like this 313 | when it starts in an interactive mode: 314 | 315 | Gnomovision version 69, Copyright (C) year name of author 316 | Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. 317 | This is free software, and you are welcome to redistribute it 318 | under certain conditions; type `show c' for details. 319 | 320 | The hypothetical commands `show w' and `show c' should show the appropriate 321 | parts of the General Public License. Of course, the commands you use may 322 | be called something other than `show w' and `show c'; they could even be 323 | mouse-clicks or menu items--whatever suits your program. 324 | 325 | You should also get your employer (if you work as a programmer) or your 326 | school, if any, to sign a "copyright disclaimer" for the program, if 327 | necessary. Here is a sample; alter the names: 328 | 329 | Yoyodyne, Inc., hereby disclaims all copyright interest in the program 330 | `Gnomovision' (which makes passes at compilers) written by James Hacker. 331 | 332 | {signature of Ty Coon}, 1 April 1989 333 | Ty Coon, President of Vice 334 | 335 | This General Public License does not permit incorporating your program into 336 | proprietary programs. If your program is a subroutine library, you may 337 | consider it more useful to permit linking proprietary applications with the 338 | library. If this is what you want to do, use the GNU Lesser General 339 | Public License instead of this License. 340 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | AppPolice 2 | ========= 3 | 4 | An app for Mac OS X with a minimalistic UI which lets you quickly throttle down the CPU usage of any running process. 5 | 6 | ![](http://d.pr/i/1gn2p+) 7 | 8 | Requires OS X Lion 10.6 and up. 9 | 10 | Email ap@saudette.net if you'd like a pre-build binary. --------------------------------------------------------------------------------