├── .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 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |
141 |
142 |
143 |
144 |
145 |
146 |
147 |
148 |
149 |
150 |
151 |
152 |
153 |
154 |
155 |
156 |
157 |
158 |
159 |
160 |
161 |
162 |
163 |
164 |
165 |
166 |
167 |
168 |
--------------------------------------------------------------------------------
/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 | 
7 |
8 | Requires OS X Lion 10.6 and up.
9 |
10 | Email ap@saudette.net if you'd like a pre-build binary.
--------------------------------------------------------------------------------